diff options
| author | 2021-05-11 15:55:14 +0000 | |
|---|---|---|
| committer | 2021-05-11 15:55:14 +0000 | |
| commit | 987f9040723f4c433c7084cb2d003c00774467c8 (patch) | |
| tree | 4337ebd7d89eef1f30c530fe51cdc4f879baa42a | |
| parent | 3ee3029e96912b267fb11e357fd9551631ceda2c (diff) | |
| parent | 619c5a46d8e20e29c320c35a2b4dea45bca0bc5d (diff) | |
Merge "Implement requestForegroundServiceExemption, without enabling it" into sc-dev
12 files changed, 96 insertions, 3 deletions
diff --git a/apex/jobscheduler/framework/java/android/os/PowerExemptionManager.java b/apex/jobscheduler/framework/java/android/os/PowerExemptionManager.java index 9dd1296d681c..42e953b72a69 100644 --- a/apex/jobscheduler/framework/java/android/os/PowerExemptionManager.java +++ b/apex/jobscheduler/framework/java/android/os/PowerExemptionManager.java @@ -344,6 +344,9 @@ public class PowerExemptionManager { */ public static final int REASON_MEDIA_SESSION_CALLBACK = 317; + /** @hide The app requests out-out. */ + public static final int REASON_OPT_OUT_REQUESTED = 1000; + /** * The list of BG-FGS-Launch and temp-allow-list reason code. * @hide @@ -411,6 +414,7 @@ public class PowerExemptionManager { REASON_EVENT_MMS, REASON_SHELL, REASON_MEDIA_SESSION_CALLBACK, + REASON_OPT_OUT_REQUESTED, }) @Retention(RetentionPolicy.SOURCE) public @interface ReasonCode {} @@ -709,6 +713,8 @@ public class PowerExemptionManager { return "SHELL"; case REASON_MEDIA_SESSION_CALLBACK: return "MEDIA_SESSION_CALLBACK"; + case REASON_OPT_OUT_REQUESTED: + return "REASON_OPT_OUT_REQUESTED"; default: return "(unknown:" + reasonCode + ")"; } diff --git a/core/api/test-current.txt b/core/api/test-current.txt index edceac3fed74..f4581079e7e8 100644 --- a/core/api/test-current.txt +++ b/core/api/test-current.txt @@ -50,6 +50,10 @@ package android { field public static final String UNDEFINED = "android.permission-group.UNDEFINED"; } + public static final class R.attr { + field public static final int requestForegroundServiceExemption; + } + public static final class R.bool { field public static final int config_assistantOnTopOfDream = 17891333; // 0x1110005 field public static final int config_perDisplayFocusEnabled = 17891332; // 0x1110004 @@ -806,6 +810,7 @@ package android.content.pm { } public class ApplicationInfo extends android.content.pm.PackageItemInfo implements android.os.Parcelable { + method public boolean hasRequestForegroundServiceExemption(); method public boolean isPrivilegedApp(); method public boolean isSystemApp(); field public static final int PRIVATE_FLAG_PRIVILEGED = 8; // 0x8 diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java index a3e0473e39cc..8b0e99236806 100644 --- a/core/java/android/content/pm/ApplicationInfo.java +++ b/core/java/android/content/pm/ApplicationInfo.java @@ -778,9 +778,18 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { */ public static final int PRIVATE_FLAG_EXT_PROFILEABLE = 1 << 0; + /** + * Value for {@link #privateFlagsExt}: whether this application has requested + * exemption from the foreground service restriction introduced in S + * (https://developer.android.com/about/versions/12/foreground-services). + * @hide + */ + public static final int PRIVATE_FLAG_EXT_REQUEST_FOREGROUND_SERVICE_EXEMPTION = 1 << 1; + /** @hide */ @IntDef(flag = true, prefix = { "PRIVATE_FLAG_EXT_" }, value = { PRIVATE_FLAG_EXT_PROFILEABLE, + PRIVATE_FLAG_EXT_REQUEST_FOREGROUND_SERVICE_EXEMPTION, }) @Retention(RetentionPolicy.SOURCE) public @interface ApplicationInfoPrivateFlagsExt {} @@ -2445,6 +2454,17 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { } /** + * @return whether the app has requested exemption from the foreground service restrictions. + * This does not take any affect for now. + * @hide + */ + @TestApi + public boolean hasRequestForegroundServiceExemption() { + return (privateFlagsExt + & ApplicationInfo.PRIVATE_FLAG_EXT_REQUEST_FOREGROUND_SERVICE_EXEMPTION) != 0; + } + + /** * @hide */ @Override protected ApplicationInfo getApplicationInfo() { diff --git a/core/java/android/content/pm/parsing/PackageInfoWithoutStateUtils.java b/core/java/android/content/pm/parsing/PackageInfoWithoutStateUtils.java index 980f10d5e688..75fa1c1b45d7 100644 --- a/core/java/android/content/pm/parsing/PackageInfoWithoutStateUtils.java +++ b/core/java/android/content/pm/parsing/PackageInfoWithoutStateUtils.java @@ -806,7 +806,9 @@ public class PackageInfoWithoutStateUtils { public static int appInfoPrivateFlagsExt(ParsingPackageRead pkg) { // @formatter:off int privateFlagsExt = - flag(pkg.isProfileable(), ApplicationInfo.PRIVATE_FLAG_EXT_PROFILEABLE); + flag(pkg.isProfileable(), ApplicationInfo.PRIVATE_FLAG_EXT_PROFILEABLE) + | flag(pkg.hasRequestForegroundServiceExemption(), + ApplicationInfo.PRIVATE_FLAG_EXT_REQUEST_FOREGROUND_SERVICE_EXEMPTION); // @formatter:on return privateFlagsExt; } diff --git a/core/java/android/content/pm/parsing/ParsingPackage.java b/core/java/android/content/pm/parsing/ParsingPackage.java index cea50cbaf234..2413e6d99f5f 100644 --- a/core/java/android/content/pm/parsing/ParsingPackage.java +++ b/core/java/android/content/pm/parsing/ParsingPackage.java @@ -338,6 +338,8 @@ public interface ParsingPackage extends ParsingPackageRead { ParsingPackage setTheme(int theme); + ParsingPackage setRequestForegroundServiceExemption(boolean requestForegroundServiceExemption); + ParsingPackage setUpgradeKeySets(@NonNull Set<String> upgradeKeySets); ParsingPackage setUse32BitAbi(boolean use32BitAbi); diff --git a/core/java/android/content/pm/parsing/ParsingPackageImpl.java b/core/java/android/content/pm/parsing/ParsingPackageImpl.java index 711488670f56..b0342aa95fc9 100644 --- a/core/java/android/content/pm/parsing/ParsingPackageImpl.java +++ b/core/java/android/content/pm/parsing/ParsingPackageImpl.java @@ -464,6 +464,7 @@ public class ParsingPackageImpl implements ParsingPackage, Parcelable { CROSS_PROFILE, ENABLED, DISALLOW_PROFILING, + REQUEST_FOREGROUND_SERVICE_EXEMPTION, }) public @interface Values {} private static final long EXTERNAL_STORAGE = 1L; @@ -512,6 +513,7 @@ public class ParsingPackageImpl implements ParsingPackage, Parcelable { private static final long CROSS_PROFILE = 1L << 43; private static final long ENABLED = 1L << 44; private static final long DISALLOW_PROFILING = 1L << 45; + private static final long REQUEST_FOREGROUND_SERVICE_EXEMPTION = 1L << 46; } private ParsingPackageImpl setBoolean(@Booleans.Values long flag, boolean value) { @@ -2199,6 +2201,11 @@ public class ParsingPackageImpl implements ParsingPackage, Parcelable { } @Override + public boolean hasRequestForegroundServiceExemption() { + return getBoolean(Booleans.REQUEST_FOREGROUND_SERVICE_EXEMPTION); + } + + @Override public ParsingPackageImpl setBaseRevisionCode(int value) { baseRevisionCode = value; return this; @@ -2420,6 +2427,11 @@ public class ParsingPackageImpl implements ParsingPackage, Parcelable { } @Override + public ParsingPackageImpl setRequestForegroundServiceExemption(boolean value) { + return setBoolean(Booleans.REQUEST_FOREGROUND_SERVICE_EXEMPTION, value); + } + + @Override public ParsingPackageImpl setUiOptions(int value) { uiOptions = value; return this; diff --git a/core/java/android/content/pm/parsing/ParsingPackageRead.java b/core/java/android/content/pm/parsing/ParsingPackageRead.java index 1c2c59f7504c..35a2b9aeb338 100644 --- a/core/java/android/content/pm/parsing/ParsingPackageRead.java +++ b/core/java/android/content/pm/parsing/ParsingPackageRead.java @@ -906,10 +906,15 @@ public interface ParsingPackageRead extends Parcelable { */ @ApplicationInfo.NativeHeapZeroInitialized int getNativeHeapZeroInitialized(); - @Nullable Boolean hasRequestRawExternalStorageAccess(); + /** + * @see ApplicationInfo#hasRequestForegroundServiceExemption() + * @see R.styleable#AndroidManifest_requestForegroundServiceExemption + */ + boolean hasRequestForegroundServiceExemption(); + // TODO(b/135203078): Hide and enforce going through PackageInfoUtils ApplicationInfo toAppInfoWithoutState(); diff --git a/core/java/android/content/pm/parsing/ParsingPackageUtils.java b/core/java/android/content/pm/parsing/ParsingPackageUtils.java index 22d75ef93137..5d74e7452a0b 100644 --- a/core/java/android/content/pm/parsing/ParsingPackageUtils.java +++ b/core/java/android/content/pm/parsing/ParsingPackageUtils.java @@ -2033,6 +2033,12 @@ public class ParsingPackageUtils { .AndroidManifestApplication_requestRawExternalStorageAccess, false)); } + if (sa.hasValue( + R.styleable.AndroidManifestApplication_requestForegroundServiceExemption)) { + pkg.setRequestForegroundServiceExemption(sa.getBoolean(R.styleable + .AndroidManifestApplication_requestForegroundServiceExemption, + false)); + } } finally { sa.recycle(); } diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml index c5f4fd1a898a..638627422eff 100644 --- a/core/res/res/values/attrs_manifest.xml +++ b/core/res/res/values/attrs_manifest.xml @@ -1954,6 +1954,13 @@ See the <a href="{@docRoot}about/versions/12/backup-restore">Changes in backup and restore</a> document for the format of the XML file.--> <attr name="dataExtractionRules" format="reference"/> + + <!-- @hide Request exemption from the foreground service restrictions introduced in S + (https://developer.android.com/about/versions/12/foreground-services) + Note the framework <b>ignores</b> this attribute at this time. Once apps target S or above, + there's no way to be exempted (without using a privileged permission). + --> + <attr name="requestForegroundServiceExemption" format="boolean" /> </declare-styleable> <!-- An attribution is a logical part of an app and is identified by a tag. diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml index 500a9dae6554..f7a99309ec5a 100644 --- a/core/res/res/values/public.xml +++ b/core/res/res/values/public.xml @@ -3099,6 +3099,8 @@ <public name="durationBetweenRequestsMillis" /> <public name="showInInputMethodPicker" /> <public name="effectColor" /> + <!-- @hide @TestApi --> + <public name="requestForegroundServiceExemption" /> </staging-public-group> <staging-public-group type="drawable" first-id="0x010800b5"> diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java index 1bd53ae24730..aadb25c7ef7f 100644 --- a/services/core/java/com/android/server/am/ActiveServices.java +++ b/services/core/java/com/android/server/am/ActiveServices.java @@ -24,6 +24,7 @@ import static android.app.ActivityManager.PROCESS_STATE_TOP; import static android.content.pm.PackageManager.PERMISSION_GRANTED; import static android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_MANIFEST; import static android.os.PowerExemptionManager.REASON_ACTIVITY_VISIBILITY_GRACE_PERIOD; +import static android.os.PowerExemptionManager.REASON_OPT_OUT_REQUESTED; import static android.os.PowerExemptionManager.REASON_OP_ACTIVATE_PLATFORM_VPN; import static android.os.PowerExemptionManager.REASON_OP_ACTIVATE_VPN; import static android.os.PowerExemptionManager.REASON_TEMP_ALLOWED_WHILE_IN_USE; @@ -5874,7 +5875,12 @@ public final class ActiveServices { ret = REASON_OP_ACTIVATE_PLATFORM_VPN; } } - + if (ret == REASON_DENIED) { + if (mAm.mConstants.mFgsAllowOptOut + && targetService.appInfo.hasRequestForegroundServiceExemption()) { + ret = REASON_OPT_OUT_REQUESTED; + } + } return ret; } diff --git a/services/core/java/com/android/server/am/ActivityManagerConstants.java b/services/core/java/com/android/server/am/ActivityManagerConstants.java index 09795855ac27..0fff8be70574 100644 --- a/services/core/java/com/android/server/am/ActivityManagerConstants.java +++ b/services/core/java/com/android/server/am/ActivityManagerConstants.java @@ -110,6 +110,7 @@ final class ActivityManagerConstants extends ContentObserver { static final String KEY_FGS_START_FOREGROUND_TIMEOUT = "fgs_start_foreground_timeout"; static final String KEY_FGS_ATOM_SAMPLE_RATE = "fgs_atom_sample_rate"; static final String KEY_KILL_FAS_CACHED_IDLE = "kill_fas_cached_idle"; + static final String KEY_FGS_ALLOW_OPT_OUT = "fgs_allow_opt_out"; private static final int DEFAULT_MAX_CACHED_PROCESSES = 32; private static final long DEFAULT_FGSERVICE_MIN_SHOWN_TIME = 2*1000; @@ -161,6 +162,7 @@ final class ActivityManagerConstants extends ContentObserver { */ private static final int DEFAULT_PUSH_MESSAGING_OVER_QUOTA_BEHAVIOR = 1; + private static final boolean DEFAULT_FGS_ALLOW_OPT_OUT = false; // Flag stored in the DeviceConfig API. /** @@ -493,6 +495,12 @@ final class ActivityManagerConstants extends ContentObserver { */ volatile boolean mKillForceAppStandByAndCachedIdle = DEFAULT_KILL_FAS_CACHED_IDLE; + /** + * Whether to allow "opt-out" from the foreground service restrictions. + * (https://developer.android.com/about/versions/12/foreground-services) + */ + volatile boolean mFgsAllowOptOut = DEFAULT_FGS_ALLOW_OPT_OUT; + private final ActivityManagerService mService; private ContentResolver mResolver; private final KeyValueListParser mParser = new KeyValueListParser(','); @@ -701,6 +709,9 @@ final class ActivityManagerConstants extends ContentObserver { case KEY_KILL_FAS_CACHED_IDLE: updateKillFasCachedIdle(); break; + case KEY_FGS_ALLOW_OPT_OUT: + updateFgsAllowOptOut(); + break; default: break; } @@ -1040,6 +1051,13 @@ final class ActivityManagerConstants extends ContentObserver { DEFAULT_KILL_FAS_CACHED_IDLE); } + private void updateFgsAllowOptOut() { + mFgsAllowOptOut = DeviceConfig.getBoolean( + DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, + KEY_FGS_ALLOW_OPT_OUT, + DEFAULT_FGS_ALLOW_OPT_OUT); + } + private void updateImperceptibleKillExemptions() { IMPERCEPTIBLE_KILL_EXEMPT_PACKAGES.clear(); IMPERCEPTIBLE_KILL_EXEMPT_PACKAGES.addAll(mDefaultImperceptibleKillExemptPackages); @@ -1260,6 +1278,8 @@ final class ActivityManagerConstants extends ContentObserver { pw.print("="); pw.println(mFgsAtomSampleRate); pw.print(" "); pw.print(KEY_PUSH_MESSAGING_OVER_QUOTA_BEHAVIOR); pw.print("="); pw.println(mPushMessagingOverQuotaBehavior); + pw.print(" "); pw.print(KEY_FGS_ALLOW_OPT_OUT); + pw.print("="); pw.println(mFgsAllowOptOut); pw.println(); if (mOverrideMaxCachedProcesses >= 0) { |