From da26eb3382de885a01933f55dec9b19505cb763f Mon Sep 17 00:00:00 2001 From: Fyodor Kupolov Date: Fri, 30 Mar 2018 16:01:26 -0700 Subject: [PATCH] Added dontSendToRestrictedApps broadcast option Sets whether pending intent can be sent for an application with background restrictions Test: manual Bug: 77237719 Change-Id: I9acc2471f1dbd657ed9a6dd93888e04a6ae48d61 --- api/system-current.txt | 1 + core/java/android/app/BroadcastOptions.java | 28 +++++++++++++++++++ .../server/am/ActivityManagerService.java | 16 +++++++++-- 3 files changed, 42 insertions(+), 3 deletions(-) diff --git a/api/system-current.txt b/api/system-current.txt index 1322a39495a32..97a78502ad596 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -316,6 +316,7 @@ package android.app { public class BroadcastOptions { method public static android.app.BroadcastOptions makeBasic(); + method public void setDontSendToRestrictedApps(boolean); method public void setTemporaryAppWhitelistDuration(long); method public android.os.Bundle toBundle(); } diff --git a/core/java/android/app/BroadcastOptions.java b/core/java/android/app/BroadcastOptions.java index b6cff385d7523..69c3632b7ab24 100644 --- a/core/java/android/app/BroadcastOptions.java +++ b/core/java/android/app/BroadcastOptions.java @@ -32,6 +32,7 @@ public class BroadcastOptions { private long mTemporaryAppWhitelistDuration; private int mMinManifestReceiverApiLevel = 0; private int mMaxManifestReceiverApiLevel = Build.VERSION_CODES.CUR_DEVELOPMENT; + private boolean mDontSendToRestrictedApps = false; /** * How long to temporarily put an app on the power whitelist when executing this broadcast @@ -52,6 +53,12 @@ public class BroadcastOptions { static final String KEY_MAX_MANIFEST_RECEIVER_API_LEVEL = "android:broadcast.maxManifestReceiverApiLevel"; + /** + * Corresponds to {@link #setMaxManifestReceiverApiLevel}. + */ + static final String KEY_DONT_SEND_TO_RESTRICTED_APPS = + "android:broadcast.dontSendToRestrictedApps"; + public static BroadcastOptions makeBasic() { BroadcastOptions opts = new BroadcastOptions(); return opts; @@ -66,6 +73,7 @@ public class BroadcastOptions { mMinManifestReceiverApiLevel = opts.getInt(KEY_MIN_MANIFEST_RECEIVER_API_LEVEL, 0); mMaxManifestReceiverApiLevel = opts.getInt(KEY_MAX_MANIFEST_RECEIVER_API_LEVEL, Build.VERSION_CODES.CUR_DEVELOPMENT); + mDontSendToRestrictedApps = opts.getBoolean(KEY_DONT_SEND_TO_RESTRICTED_APPS, false); } /** @@ -122,6 +130,23 @@ public class BroadcastOptions { return mMaxManifestReceiverApiLevel; } + /** + * Sets whether pending intent can be sent for an application with background restrictions + * @param dontSendToRestrictedApps if true, pending intent will not be sent for an application + * with background restrictions. Default value is {@code false} + */ + public void setDontSendToRestrictedApps(boolean dontSendToRestrictedApps) { + mDontSendToRestrictedApps = dontSendToRestrictedApps; + } + + /** + * @hide + * @return #setDontSendToRestrictedApps + */ + public boolean isDontSendToRestrictedApps() { + return mDontSendToRestrictedApps; + } + /** * Returns the created options as a Bundle, which can be passed to * {@link android.content.Context#sendBroadcast(android.content.Intent) @@ -141,6 +166,9 @@ public class BroadcastOptions { if (mMaxManifestReceiverApiLevel != Build.VERSION_CODES.CUR_DEVELOPMENT) { b.putInt(KEY_MAX_MANIFEST_RECEIVER_API_LEVEL, mMaxManifestReceiverApiLevel); } + if (mDontSendToRestrictedApps) { + b.putBoolean(KEY_DONT_SEND_TO_RESTRICTED_APPS, true); + } return b.isEmpty() ? null : b; } } diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index db52b9700e4ef..44db803f27411 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -12954,9 +12954,13 @@ public class ActivityManagerService extends IActivityManager.Stub } catch (RemoteException exc) { // Ignore. } + return isBackgroundRestrictedNoCheck(callingUid, packageName); + } + + boolean isBackgroundRestrictedNoCheck(final int uid, final String packageName) { final int mode = mAppOpsService.checkOperation(AppOpsManager.OP_RUN_ANY_IN_BACKGROUND, - callingUid, packageName); - return (mode != AppOpsManager.MODE_ALLOWED); + uid, packageName); + return mode != AppOpsManager.MODE_ALLOWED; } @Override @@ -21061,6 +21065,7 @@ public class ActivityManagerService extends IActivityManager.Stub } } + final String action = intent.getAction(); BroadcastOptions brOptions = null; if (bOptions != null) { brOptions = new BroadcastOptions(bOptions); @@ -21081,11 +21086,16 @@ public class ActivityManagerService extends IActivityManager.Stub throw new SecurityException(msg); } } + if (brOptions.isDontSendToRestrictedApps() + && isBackgroundRestrictedNoCheck(callingUid, callerPackage)) { + Slog.i(TAG, "Not sending broadcast " + action + " - app " + callerPackage + + " has background restrictions"); + return ActivityManager.START_CANCELED; + } } // Verify that protected broadcasts are only being sent by system code, // and that system code is only sending protected broadcasts. - final String action = intent.getAction(); final boolean isProtectedBroadcast; try { isProtectedBroadcast = AppGlobals.getPackageManager().isProtectedBroadcast(action);