在AndroidQ(12)中,如果应用尝试获取SYSTEM_ALERT_WINDOW权限,且设备被视为低内存设备时,系统会阻止该功能。可以通过修改ro.config.low_ram属性为false来避免这一限制,从而在设备上启用权限。
一问题描述:
预装应用到系统,应用有申请悬浮窗功能,点击去设置界面该应用下开启该开关,但是系统提示禁用该功能,截图如下:
二分析:
这是系统功能限制控制了该功能:
定位源码:android/packages/apps/Settings/src/com/android/settings/applications/manageapplications/ManageApplications.java
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
if (mListType == LIST_TYPE_OVERLAY && !Utils.isSystemAlertWindowEnabled(getContext())) {//Utils.isSystemAlertWindowEnabled(getContext())表示弹窗是否可用
mRootView = inflater.inflate(R.layout.manage_applications_apps_unsupported, null);
setHasOptionsMenu(false);
return mRootView;
}
mRootView = inflater.inflate(R.layout.manage_applications_apps, null);
mLoadingContainer = mRootView.findViewById(R.id.loading_container);
mEmptyView = mRootView.findViewById(android.R.id.empty);
mRecyclerView = mRootView.findViewById(R.id.apps_list);
mApplications = new ApplicationsAdapter(mApplicationsState, this, mFilter,
savedInstanceState);
if (savedInstanceState != null) {
mApplications.mHasReceivedLoadEntries =
savedInstanceState.getBoolean(EXTRA_HAS_ENTRIES, false);
mApplications.mHasReceivedBridgeCallback =
savedInstanceState.getBoolean(EXTRA_HAS_BRIDGE, false);
}
我们看下面的工具类
android/packages/apps/Settings/src/com/android/settings/Utils.java
/** Get {@link Resources} by subscription id if subscription id is valid. */
public static Resources getResourcesForSubId(Context context, int subId) {
if (subId != SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
return SubscriptionManager.getResourcesForSubId(context, subId);
} else {
return context.getResources();
}
}
//********************start***********************
/**
* Returns true if SYSTEM_ALERT_WINDOW permission is available.
* Starting from Q, SYSTEM_ALERT_WINDOW is disabled on low ram phones.
*/
public static boolean isSystemAlertWindowEnabled(Context context) {
// SYSTEM_ALERT_WINDOW is disabled on on low ram devices starting from Q
ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
return !(am.isLowRamDevice() && (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q));
}
//*********************end************************
/**
* Adds a shadow appear/disappear animation to action bar scroll.
*
* <p/>
* This method must be called after {@link Fragment#onCreate(Bundle)}.
*/
public static void setActionBarShadowAnimation(Activity activity, Lifecycle lifecycle,
View scrollView) {
if (activity == null) {
Log.w(TAG, "No activity, cannot style actionbar.");
return;
}
final ActionBar actionBar = activity.getActionBar();
if (actionBar == null) {
看上面的代码,该版本是否大于Q,且am.isLowRamDevice() 设备是否是低内存
我们接下来看android/frameworks/base/core/java/android/app/ActivityManager.java
/**
* Returns true if this is a low-RAM device. Exactly whether a device is low-RAM
* is ultimately up to the device configuration, but currently it generally means
* something with 1GB or less of RAM. This is mostly intended to be used by apps
* to determine whether they should turn off certain features that require more RAM.
*/
public boolean isLowRamDevice() {
return isLowRamDeviceStatic();
}
/** @hide */
@UnsupportedAppUsage
public static boolean isLowRamDeviceStatic() {
return RoSystemProperties.CONFIG_LOW_RAM ||
(Build.IS_DEBUGGABLE && DEVELOPMENT_FORCE_LOW_RAM);
}
我们看下面的/frameworks/base/core/java/com/android/internal/os/RoSystemProperties.java
// ------ ro.config.* -------- //
public static final boolean CONFIG_AVOID_GFX_ACCEL =
SystemProperties.getBoolean("ro.config.avoid_gfx_accel", false);
public static final boolean CONFIG_LOW_RAM =
SystemProperties.getBoolean("ro.config.low_ram", false);
public static final boolean CONFIG_SMALL_BATTERY =
SystemProperties.getBoolean("ro.config.small_battery", false);
// ------ ro.fw.* ------------ //
public static final boolean FW_SYSTEM_USER_SPLIT =
SystemProperties.getBoolean("ro.fw.system_user_split", false);
public static final boolean MULTIUSER_HEADLESS_SYSTEM_USER =
SystemProperties.getBoolean("ro.fw.mu.headless_system_user", false);
public static final boolean CONFIG_LOW_RAM =
SystemProperties.getBoolean("ro.config.low_ram", false);
我们看到以上是从变量o.config.low_ram读取的,这样我们需要从属性文件中修改改默认值就可以了。
在build、device下检索,该属性,最后在build目录下找到。
三修改
修改点:
//build目录下
Date: Fri Aug 15 11:40:32 2025 +0800
关闭低内存系统禁用悬浮窗
Change-Id: I784af2652c3a9426ec7eb9be023ffebb60318681
diff --git a/target/product/go_defaults_common.mk b/target/product/go_defaults_common.mk
index 7f19615ed..5d384eff5 100644
--- a/target/product/go_defaults_common.mk
+++ b/target/product/go_defaults_common.mk
@@ -19,7 +19,7 @@
# Set lowram options and enable traced by default
PRODUCT_VENDOR_PROPERTIES += \
- ro.config.low_ram=true \
+ ro.config.low_ram=false \
# Speed profile services and wifi-service to reduce RAM and storage.
PRODUCT_SYSTEM_SERVER_COMPILER_FILTER := speed-profile
四重新编译刷机,效果如下:
问题解决~
参考文章: