diff options
| author | 2021-05-13 09:30:42 -0700 | |
|---|---|---|
| committer | 2021-05-13 12:21:39 -0700 | |
| commit | dc4aa4b86e87f4eabecd236a9d75dff8b89fd623 (patch) | |
| tree | d07cbeeb15628146fe642782ea891977a390cfa4 | |
| parent | b04efdff7045dfe585b7dbc9571dd95b0e35f204 (diff) | |
Add a permission for CDM apps to start FGS from the background
Previously, any apps with a CDM association was allowed to start
foreground services from the background.
Now, only apps with
REQUEST_COMPANION_START_FOREGROUND_SERVICES_FROM_BACKGROUND
(or REQUEST_COMPANION_RUN_IN_BACKGROUND) are allowed to do so.
Bug: 186536261
Test: Manual test with a test app using CDM. With and without these
permissions.
Change-Id: Ic00aa1c7cfefc37bf89ea3079ef0977aee12499b
| -rw-r--r-- | core/api/current.txt | 1 | ||||
| -rw-r--r-- | core/res/AndroidManifest.xml | 6 | ||||
| -rw-r--r-- | services/core/java/com/android/server/am/ActiveServices.java | 36 | ||||
| -rw-r--r-- | services/core/java/com/android/server/am/ProcessStateRecord.java | 12 |
4 files changed, 35 insertions, 20 deletions
diff --git a/core/api/current.txt b/core/api/current.txt index 324ad33166a1..4a053073997c 100644 --- a/core/api/current.txt +++ b/core/api/current.txt @@ -141,6 +141,7 @@ package android { field public static final String REORDER_TASKS = "android.permission.REORDER_TASKS"; field public static final String REQUEST_COMPANION_PROFILE_WATCH = "android.permission.REQUEST_COMPANION_PROFILE_WATCH"; field public static final String REQUEST_COMPANION_RUN_IN_BACKGROUND = "android.permission.REQUEST_COMPANION_RUN_IN_BACKGROUND"; + field public static final String REQUEST_COMPANION_START_FOREGROUND_SERVICES_FROM_BACKGROUND = "android.permission.REQUEST_COMPANION_START_FOREGROUND_SERVICES_FROM_BACKGROUND"; field public static final String REQUEST_COMPANION_USE_DATA_IN_BACKGROUND = "android.permission.REQUEST_COMPANION_USE_DATA_IN_BACKGROUND"; field public static final String REQUEST_DELETE_PACKAGES = "android.permission.REQUEST_DELETE_PACKAGES"; field public static final String REQUEST_IGNORE_BATTERY_OPTIMIZATIONS = "android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS"; diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index ffb8d1daac90..bcecd7442e9c 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -2900,6 +2900,12 @@ android:description="@string/permdesc_runInBackground" android:protectionLevel="normal" /> + <!-- Allows a companion app to start a foreground service from the background. + {@see android.Manifest.permission#REQUEST_COMPANION_RUN_IN_BACKGROUND} + --> + <permission android:name="android.permission.REQUEST_COMPANION_START_FOREGROUND_SERVICES_FROM_BACKGROUND" + android:protectionLevel="normal"/> + <!-- Allows a companion app to use data in the background. <p>Protection level: normal --> diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java index aadb25c7ef7f..f480cbc26ff4 100644 --- a/services/core/java/com/android/server/am/ActiveServices.java +++ b/services/core/java/com/android/server/am/ActiveServices.java @@ -16,6 +16,8 @@ package com.android.server.am; +import static android.Manifest.permission.REQUEST_COMPANION_RUN_IN_BACKGROUND; +import static android.Manifest.permission.REQUEST_COMPANION_START_FOREGROUND_SERVICES_FROM_BACKGROUND; import static android.Manifest.permission.START_ACTIVITIES_FROM_BACKGROUND; import static android.Manifest.permission.START_FOREGROUND_SERVICES_FROM_BACKGROUND; import static android.app.ActivityManager.PROCESS_STATE_HEAVY_WEIGHT; @@ -5831,6 +5833,26 @@ public final class ActiveServices { } } + // Check for CDM apps with either REQUEST_COMPANION_RUN_IN_BACKGROUND or + // REQUEST_COMPANION_START_FOREGROUND_SERVICES_FROM_BACKGROUND. + // Note: When a CDM app has REQUEST_COMPANION_RUN_IN_BACKGROUND, the app is also put + // in the user-allowlist. However, in this case, we want to use the reason code + // REASON_COMPANION_DEVICE_MANAGER, so this check needs to be before the + // isAllowlistedForFgsStartLOSP check. + if (ret == REASON_DENIED) { + final boolean isCompanionApp = mAm.mInternal.isAssociatedCompanionApp( + UserHandle.getUserId(callingUid), callingUid); + if (isCompanionApp) { + if (isPermissionGranted( + REQUEST_COMPANION_START_FOREGROUND_SERVICES_FROM_BACKGROUND, + callingPid, callingUid) + || isPermissionGranted(REQUEST_COMPANION_RUN_IN_BACKGROUND, + callingPid, callingUid)) { + ret = REASON_COMPANION_DEVICE_MANAGER; + } + } + } + if (ret == REASON_DENIED) { ActivityManagerService.FgsTempAllowListItem item = mAm.isAllowlistedForFgsStartLOSP(callingUid); @@ -5858,14 +5880,6 @@ public final class ActiveServices { } if (ret == REASON_DENIED) { - final boolean isCompanionApp = mAm.mInternal.isAssociatedCompanionApp( - UserHandle.getUserId(callingUid), callingUid); - if (isCompanionApp) { - ret = REASON_COMPANION_DEVICE_MANAGER; - } - } - - if (ret == REASON_DENIED) { final AppOpsManager appOpsManager = mAm.getAppOpsManager(); if (appOpsManager.checkOpNoThrow(AppOpsManager.OP_ACTIVATE_VPN, callingUid, callingPackage) == AppOpsManager.MODE_ALLOWED) { @@ -5884,6 +5898,10 @@ public final class ActiveServices { return ret; } + private boolean isPermissionGranted(String permission, int callingPid, int callingUid) { + return mAm.checkPermission(permission, callingPid, callingUid) == PERMISSION_GRANTED; + } + private static boolean isFgsBgStart(@ReasonCode int code) { return code != REASON_PROC_STATE_PERSISTENT && code != REASON_PROC_STATE_PERSISTENT_UI @@ -5957,7 +5975,7 @@ public final class ActiveServices { } FrameworkStatsLog.write(FrameworkStatsLog.FOREGROUND_SERVICE_STATE_CHANGED, r.appInfo.uid, - r.shortInstanceName, + null, state, r.mAllowWhileInUsePermissionInFgs, r.mAllowStartForeground, diff --git a/services/core/java/com/android/server/am/ProcessStateRecord.java b/services/core/java/com/android/server/am/ProcessStateRecord.java index 6429b79f6111..801e3824d7b0 100644 --- a/services/core/java/com/android/server/am/ProcessStateRecord.java +++ b/services/core/java/com/android/server/am/ProcessStateRecord.java @@ -25,7 +25,6 @@ import static android.app.ActivityManager.PROCESS_STATE_NONEXISTENT; import static android.content.pm.PackageManager.PERMISSION_GRANTED; import static android.os.PowerWhitelistManager.REASON_BACKGROUND_ACTIVITY_PERMISSION; import static android.os.PowerWhitelistManager.REASON_BACKGROUND_FGS_PERMISSION; -import static android.os.PowerWhitelistManager.REASON_COMPANION_DEVICE_MANAGER; import static android.os.PowerWhitelistManager.REASON_DENIED; import static android.os.PowerWhitelistManager.REASON_DEVICE_OWNER; import static android.os.PowerWhitelistManager.REASON_PROFILE_OWNER; @@ -1217,6 +1216,7 @@ final class ProcessStateRecord { mAllowStartFgs = mAllowStartFgsByPermission = ret; } + // TODO(b/188063200) Clean up this method. Why do we need to duplicate only some of the checks? @GuardedBy("mService") void setAllowStartFgs() { if (mAllowStartFgs != REASON_DENIED) { @@ -1238,16 +1238,6 @@ final class ProcessStateRecord { } if (mAllowStartFgs == REASON_DENIED) { - if (mService.mInternal != null) { - final boolean isCompanionApp = mService.mInternal.isAssociatedCompanionApp( - UserHandle.getUserId(mApp.info.uid), mApp.info.uid); - if (isCompanionApp) { - mAllowStartFgs = REASON_COMPANION_DEVICE_MANAGER; - } - } - } - - if (mAllowStartFgs == REASON_DENIED) { // Is the calling UID a profile owner app? if (mService.mInternal != null) { if (mService.mInternal.isProfileOwner(mApp.info.uid)) { |