android 10 后台启动activity
摘要:Android 10(API 级别 29)及更高版本会限制应用何时可以启动 activity 背景。这些限制有助于最大限度地减少对用户的干扰, 让用户能够更好地控制其屏幕上显示的内容。本文以此为出发点,基于展锐平台对系统代码进行改造,通过白名单的方式允许部分应用可以从后台启动activity。
Google官方:
针对从后台启动 activity 的限制
1.添加白名单
Index: build/make/target/product/base_system.mk
===================================================================
--- build/make/target/product/base_system.mk (版本 1957)
+++ build/make/target/product/base_system.mk (版本 1959)
@@ -269,6 +269,9 @@
wifi-service \
wm \
+PRODUCT_PACKAGES += background-startactivity-package-whitelist.txt
+
# VINTF data for system image
PRODUCT_PACKAGES += \
system_manifest.xml \
Index: frameworks/base/data/etc/background-startactivity-package-whitelist.txt
===================================================================
--- frameworks/base/data/etc/background-startactivity-package-whitelist.txt (不存在的)
+++ frameworks/base/data/etc/background-startactivity-package-whitelist.txt (版本 1959)
@@ -0,0 +1 @@
+com.android.permissioncontroller
Index: frameworks/base/data/etc/Android.bp
===================================================================
--- frameworks/base/data/etc/Android.bp (版本 1957)
+++ frameworks/base/data/etc/Android.bp (版本 1959)
@@ -133,3 +133,9 @@
sub_dir: "permissions",
src: "com.android.timezone.updater.xml",
}
+
+prebuilt_etc {
+ name: "background-startactivity-package-whitelist.txt",
+ sub_dir: "permissions",
+ src: "background-startactivity-package-whitelist.txt",
+}
2. 实现方案
Index: frameworks/base/services/core/java/com/android/server/wm/ActivityStarter.java
===================================================================
--- frameworks/base/services/core/java/com/android/server/wm/ActivityStarter.java (版本 1957)
+++ frameworks/base/services/core/java/com/android/server/wm/ActivityStarter.java (版本 1959)
@@ -1064,6 +1064,14 @@
+ " allowed because SYSTEM_ALERT_WINDOW permission is granted.");
return false;
}
+
+ // don't abort if the callingPackage on the whitelist
+ if (ActivityBackgroundStartCheckUtil.isWhitelistApp(callingPackage, intent)) {
+ Slog.w(TAG, "Background activity start for " + callingPackage
+ + " allowed because it is on the whitelist.");
+ return false;
+ }
+
// anything that has fallen through would currently be aborted
Slog.w(TAG, "Background activity start [callingPackage: " + callingPackage
+ "; callingUid: " + callingUid
Index: frameworks/base/services/core/java/com/android/server/wm/ActivityBackgroundStartCheckUtil.java
===================================================================
--- frameworks/base/services/core/java/com/android/server/wm/ActivityBackgroundStartCheckUtil.java (不存在的)
+++ frameworks/base/services/core/java/com/android/server/wm/ActivityBackgroundStartCheckUtil.java (版本 1959)
@@ -0,0 +1,100 @@
+package com.android.server.wm;
+
+
+import android.content.Context;
+import android.content.Intent;
+import android.os.Environment;
+import android.os.Process;
+import android.text.TextUtils;
+import android.util.Log;
+
+import com.android.internal.util.ArrayUtils;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileReader;
+import java.io.IOException;
+import java.util.HashSet;
+
+public class ActivityBackgroundStartCheckUtil{
+
+ private static String TAG = "ActivityBackgroundStartCheckUtil";
+
+ private static final File GRANT_SYS_APP_LIST_SYSTEM = Environment
+ .buildPath(Environment.getRootDirectory(), "etc", "permissions",
+ "background-startactivity-package-whitelist.txt");
+
+ private static HashSet<String> mWhitelistAppSet = new HashSet<String>();
+
+ private static String Key[] = {"android", "call"};
+
+ public static boolean isWhitelistApp(String callingPackage, Intent intent){
+ sGetGrantSystemAppFromFile(mWhitelistAppSet, GRANT_SYS_APP_LIST_SYSTEM);
+ Log.d(TAG, "isWhitelistApp callingPackage="+callingPackage);
+ try {
+ String packageName = intent.getComponent().getPackageName();
+ String className = intent.getComponent().getClassName();
+ if (mWhitelistAppSet.contains(callingPackage) ||
+ mWhitelistAppSet.contains(packageName)) {
+ return true;
+ }
+ for (String key : Key) {
+ if (className.contains(key)) {
+ return true;
+ }
+ }
+ } catch (Exception e) {
+ //e.printStackTrace();
+ Log.d(TAG, e.getMessage());
+ }
+ return false;
+ }
+
+
+ /**
+ * Get removable system app list from config file
+ *
+ * @param resultSet
+ * Returned result list
+ * @param file
+ * The config file
+ */
+ private static void sGetGrantSystemAppFromFile(
+ HashSet<String> resultSet, File file) {
+ resultSet.clear();
+ FileReader fr = null;
+ BufferedReader br = null;
+ try {
+ if (file.exists()) {
+ fr = new FileReader(file);
+ } else {
+ Log.d(TAG, "file in " + file + " does not exist!");
+ return;
+ }
+ br = new BufferedReader(fr);
+ String line;
+ while ((line = br.readLine()) != null) {
+ line = line.trim();
+ if (!TextUtils.isEmpty(line)) {
+ Log.d(TAG, "read line " + line);
+ resultSet.add(line);
+ }
+ }
+ Log.e(TAG,"GRANT_SYS_APP_LIST_SYSTEM size="+resultSet.size());
+ } catch (Exception io) {
+ Log.d(TAG, io.getMessage());
+ } finally {
+ try {
+ if (br != null) {
+ br.close();
+ }
+ if (fr != null) {
+ fr.close();
+ }
+ } catch (IOException io) {
+ Log.d(TAG, io.getMessage());
+ }
+ }
+ }
+}
+