summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/android/app/ActivityManager.java8
-rw-r--r--core/java/android/app/ContextImpl.java4
-rw-r--r--core/java/android/app/IActivityManager.aidl2
-rw-r--r--packages/SystemUI/AndroidManifest.xml3
-rw-r--r--services/core/java/com/android/server/AlarmManagerService.java7
-rw-r--r--services/core/java/com/android/server/am/ActiveServices.java9
-rw-r--r--services/core/java/com/android/server/am/ActivityManagerService.java143
-rw-r--r--services/core/java/com/android/server/am/BroadcastQueue.java23
-rw-r--r--services/core/java/com/android/server/content/SyncManager.java3
-rw-r--r--services/core/java/com/android/server/job/JobSchedulerService.java9
10 files changed, 95 insertions, 116 deletions
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index 1d4b038f2d82..c1a888d28428 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -520,17 +520,17 @@ public class ActivityManager {
/** @hide Flag for registerUidObserver: report uid has become active. */
public static final int UID_OBSERVER_ACTIVE = 1<<3;
- /** @hide Mode for {@link IActivityManager#getAppStartMode}: normal free-to-run operation. */
+ /** @hide Mode for {@link IActivityManager#isAppStartModeDisabled}: normal free-to-run operation. */
public static final int APP_START_MODE_NORMAL = 0;
- /** @hide Mode for {@link IActivityManager#getAppStartMode}: delay running until later. */
+ /** @hide Mode for {@link IActivityManager#isAppStartModeDisabled}: delay running until later. */
public static final int APP_START_MODE_DELAYED = 1;
- /** @hide Mode for {@link IActivityManager#getAppStartMode}: delay running until later, with
+ /** @hide Mode for {@link IActivityManager#isAppStartModeDisabled}: delay running until later, with
* rigid errors (throwing exception). */
public static final int APP_START_MODE_DELAYED_RIGID = 2;
- /** @hide Mode for {@link IActivityManager#getAppStartMode}: disable/cancel pending
+ /** @hide Mode for {@link IActivityManager#isAppStartModeDisabled}: disable/cancel pending
* launches; this is the mode for ephemeral apps. */
public static final int APP_START_MODE_DISABLED = 3;
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index 5e7d46fe05aa..1b31cc5ea41f 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -1342,8 +1342,8 @@ class ContextImpl extends Context {
}
try {
final Intent intent = ActivityManager.getService().registerReceiver(
- mMainThread.getApplicationThread(), mBasePackageName,
- rd, filter, broadcastPermission, userId);
+ mMainThread.getApplicationThread(), mBasePackageName, rd, filter,
+ broadcastPermission, userId);
if (intent != null) {
intent.setExtrasClassLoader(getClassLoader());
intent.prepareToEnterProcess();
diff --git a/core/java/android/app/IActivityManager.aidl b/core/java/android/app/IActivityManager.aidl
index 135c2a4eef91..ec7c1709b3c5 100644
--- a/core/java/android/app/IActivityManager.aidl
+++ b/core/java/android/app/IActivityManager.aidl
@@ -475,7 +475,7 @@ interface IActivityManager {
void suppressResizeConfigChanges(boolean suppress);
void moveTasksToFullscreenStack(int fromStackId, boolean onTop);
boolean moveTopActivityToPinnedStack(int stackId, in Rect bounds);
- int getAppStartMode(int uid, in String packageName);
+ boolean isAppStartModeDisabled(int uid, in String packageName);
boolean unlockUser(int userid, in byte[] token, in byte[] secret,
in IProgressListener listener);
boolean isInMultiWindowMode(in IBinder token);
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index fede34d2ced3..f72d091607ac 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -131,6 +131,9 @@
<!-- Assist -->
<uses-permission android:name="android.permission.ACCESS_VOICE_INTERACTION_SERVICE" />
+ <!-- Doze mode temp whitelisting for notification dispatching. -->
+ <uses-permission android:name="android.permission.CHANGE_DEVICE_IDLE_TEMP_WHITELIST" />
+
<!-- Listen for keyboard attachment / detachment -->
<uses-permission android:name="android.permission.TABLET_MODE" />
diff --git a/services/core/java/com/android/server/AlarmManagerService.java b/services/core/java/com/android/server/AlarmManagerService.java
index 581aa05d7d32..0e07ec0e27f4 100644
--- a/services/core/java/com/android/server/AlarmManagerService.java
+++ b/services/core/java/com/android/server/AlarmManagerService.java
@@ -504,8 +504,8 @@ class AlarmManagerService extends SystemService {
for (int i = alarms.size()-1; i >= 0; i--) {
Alarm alarm = alarms.get(i);
try {
- if (alarm.uid == uid && ActivityManager.getService().getAppStartMode(
- uid, alarm.packageName) == ActivityManager.APP_START_MODE_DISABLED) {
+ if (alarm.uid == uid && ActivityManager.getService().isAppStartModeDisabled(
+ uid, alarm.packageName)) {
alarms.remove(i);
didRemove = true;
if (alarm.alarmClock != null) {
@@ -1089,8 +1089,7 @@ class AlarmManagerService extends SystemService {
operation, directReceiver, listenerTag, workSource, flags, alarmClock,
callingUid, callingPackage);
try {
- if (ActivityManager.getService().getAppStartMode(callingUid, callingPackage)
- == ActivityManager.APP_START_MODE_DISABLED) {
+ if (ActivityManager.getService().isAppStartModeDisabled(callingUid, callingPackage)) {
Slog.w(TAG, "Not setting alarm from " + callingUid + ":" + a
+ " -- package not allowed to start");
return;
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index 4b89b404f9b6..4ab09c4d8ae3 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -349,8 +349,8 @@ public final class ActiveServices {
try {
// Before going further -- if this app is not allowed to start services in the
// background, then at this point we aren't going to let it period.
- final int allowed = mAm.checkAllowBackgroundLocked(
- r.appInfo.uid, r.packageName, callingPid, false);
+ final int allowed = mAm.getAppStartModeLocked(r.appInfo.uid, r.packageName,
+ r.appInfo.targetSdkVersion, callingPid, false, false);
if (allowed != ActivityManager.APP_START_MODE_NORMAL) {
Slog.w(TAG, "Background start not allowed: service "
+ service + " to " + r.name.flattenToShortString()
@@ -607,8 +607,9 @@ public final class ActiveServices {
for (int i=services.mServicesByName.size()-1; i>=0; i--) {
ServiceRecord service = services.mServicesByName.valueAt(i);
if (service.appInfo.uid == uid && service.startRequested) {
- if (mAm.checkAllowBackgroundLocked(service.appInfo.uid, service.packageName,
- -1, false) != ActivityManager.APP_START_MODE_NORMAL) {
+ if (mAm.getAppStartModeLocked(service.appInfo.uid, service.packageName,
+ service.appInfo.targetSdkVersion, -1, false, false)
+ != ActivityManager.APP_START_MODE_NORMAL) {
if (stopping == null) {
stopping = new ArrayList<>();
stopping.add(service);
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 75ae43b02329..2bec90d7313b 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -22,6 +22,7 @@ import static android.Manifest.permission.INTERACT_ACROSS_USERS_FULL;
import static android.Manifest.permission.MANAGE_ACTIVITY_STACKS;
import static android.Manifest.permission.READ_FRAME_BUFFER;
import static android.Manifest.permission.START_TASKS_FROM_RECENTS;
+import static android.Manifest.permission.CHANGE_DEVICE_IDLE_TEMP_WHITELIST;
import static android.app.ActivityManager.DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT;
import static android.app.ActivityManager.RESIZE_MODE_PRESERVE_WINDOW;
import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
@@ -7283,18 +7284,23 @@ public class ActivityManagerService extends IActivityManager.Stub
Slog.d(TAG, "tempWhitelistAppForPowerSave(" + callerPid + ", " + callerUid + ", "
+ targetUid + ", " + duration + ")");
}
- synchronized (mPidsSelfLocked) {
- final ProcessRecord pr = mPidsSelfLocked.get(callerPid);
- if (pr == null) {
- Slog.w(TAG, "tempWhitelistAppForPowerSave() no ProcessRecord for pid " + callerPid);
- return;
- }
- if (!pr.whitelistManager) {
- if (DEBUG_WHITELISTS) {
- Slog.d(TAG, "tempWhitelistAppForPowerSave() for target " + targetUid + ": pid "
- + callerPid + " is not allowed");
+
+ if (checkPermission(CHANGE_DEVICE_IDLE_TEMP_WHITELIST, callerPid, callerUid)
+ != PackageManager.PERMISSION_GRANTED) {
+ synchronized (mPidsSelfLocked) {
+ final ProcessRecord pr = mPidsSelfLocked.get(callerPid);
+ if (pr == null) {
+ Slog.w(TAG, "tempWhitelistAppForPowerSave() no ProcessRecord for pid "
+ + callerPid);
+ return;
+ }
+ if (!pr.whitelistManager) {
+ if (DEBUG_WHITELISTS) {
+ Slog.d(TAG, "tempWhitelistAppForPowerSave() for target " + targetUid
+ + ": pid " + callerPid + " is not allowed");
+ }
+ return;
}
- return;
}
}
@@ -8019,65 +8025,42 @@ public class ActivityManagerService extends IActivityManager.Stub
return readMet && writeMet;
}
- public int getAppStartMode(int uid, String packageName) {
+ public boolean isAppStartModeDisabled(int uid, String packageName) {
synchronized (this) {
- return checkAllowBackgroundLocked(uid, packageName, -1, false);
+ return getAppStartModeLocked(uid, packageName, 0, -1, false, true)
+ == ActivityManager.APP_START_MODE_DISABLED;
}
}
// Unified app-op and target sdk check
- int appRestrictedInBackgroundLocked(int uid, String packageName) {
- if (packageName == null) {
- packageName = mPackageManagerInt.getNameForUid(uid);
- if (packageName == null) {
- Slog.w(TAG, "No package known for uid " + uid);
- return ActivityManager.APP_START_MODE_NORMAL;
+ int appRestrictedInBackgroundLocked(int uid, String packageName, int packageTargetSdk) {
+ // Apps that target O+ are always subject to background check
+ if (mEnforceBackgroundCheck && packageTargetSdk >= Build.VERSION_CODES.O) {
+ if (DEBUG_BACKGROUND_CHECK) {
+ Slog.i(TAG, "App " + uid + "/" + packageName + " targets O+, restricted");
}
+ return ActivityManager.APP_START_MODE_DELAYED_RIGID;
}
-
- // !!! TODO: cache the package/versionCode lookups to fast path this
- ApplicationInfo app = getPackageManagerInternalLocked().getApplicationInfo(packageName,
- UserHandle.getUserId(uid));
- if (app != null) {
- // Apps that target O+ are always subject to background check
- if (mEnforceBackgroundCheck && app.targetSdkVersion >= Build.VERSION_CODES.O) {
- if (DEBUG_BACKGROUND_CHECK) {
- Slog.i(TAG, "App " + uid + "/" + packageName + " targets O+, restricted");
- }
+ // ...and legacy apps get an AppOp check
+ int appop = mAppOpsService.noteOperation(AppOpsManager.OP_RUN_IN_BACKGROUND,
+ uid, packageName);
+ if (DEBUG_BACKGROUND_CHECK) {
+ Slog.i(TAG, "Legacy app " + uid + "/" + packageName + " bg appop " + appop);
+ }
+ switch (appop) {
+ case AppOpsManager.MODE_ALLOWED:
+ return ActivityManager.APP_START_MODE_NORMAL;
+ case AppOpsManager.MODE_IGNORED:
+ return ActivityManager.APP_START_MODE_DELAYED;
+ default:
return ActivityManager.APP_START_MODE_DELAYED_RIGID;
- }
- // ...and legacy apps get an AppOp check
- int appop = mAppOpsService.noteOperation(AppOpsManager.OP_RUN_IN_BACKGROUND,
- uid, packageName);
- if (DEBUG_BACKGROUND_CHECK) {
- Slog.i(TAG, "Legacy app " + uid + "/" + packageName + " bg appop " + appop);
- }
- switch (appop) {
- case AppOpsManager.MODE_ALLOWED:
- return ActivityManager.APP_START_MODE_NORMAL;
- case AppOpsManager.MODE_IGNORED:
- return ActivityManager.APP_START_MODE_DELAYED;
- default:
- return ActivityManager.APP_START_MODE_DELAYED_RIGID;
- }
- } else {
- Slog.w(TAG, "Unknown app " + packageName + " / " + uid);
}
- return ActivityManager.APP_START_MODE_NORMAL;
}
// Service launch is available to apps with run-in-background exemptions but
// some other background operations are not. If we're doing a check
// of service-launch policy, allow those callers to proceed unrestricted.
- int appServicesRestrictedInBackgroundLocked(int uid, String packageName) {
- if (packageName == null) {
- packageName = mPackageManagerInt.getNameForUid(uid);
- if (packageName == null) {
- Slog.w(TAG, "No package known for uid " + uid);
- return ActivityManager.APP_START_MODE_NORMAL;
- }
- }
-
+ int appServicesRestrictedInBackgroundLocked(int uid, String packageName, int packageTargetSdk) {
// Persistent app? NB: expects that persistent uids are always active.
final UidRecord uidRec = mActiveUids.get(uid);
if (uidRec != null && uidRec.persistent) {
@@ -8107,11 +8090,11 @@ public class ActivityManagerService extends IActivityManager.Stub
}
// None of the service-policy criteria apply, so we apply the common criteria
- return appRestrictedInBackgroundLocked(uid, packageName);
+ return appRestrictedInBackgroundLocked(uid, packageName, packageTargetSdk);
}
- int checkAllowBackgroundLocked(int uid, String packageName, int callingPid,
- boolean alwaysRestrict) {
+ int getAppStartModeLocked(int uid, String packageName, int packageTargetSdk,
+ int callingPid, boolean alwaysRestrict, boolean disabledOnly) {
UidRecord uidRec = mActiveUids.get(uid);
if (DEBUG_BACKGROUND_CHECK) Slog.d(TAG, "checkAllowBackground: uid=" + uid + " pkg="
+ packageName + " rec=" + uidRec + " always=" + alwaysRestrict + " idle="
@@ -8129,27 +8112,37 @@ public class ActivityManagerService extends IActivityManager.Stub
// We are hard-core about ephemeral apps not running in the background.
return ActivityManager.APP_START_MODE_DISABLED;
} else {
- /** Don't want to allow this exception in the final background check impl?
- if (callingPid >= 0) {
- ProcessRecord proc;
- synchronized (mPidsSelfLocked) {
- proc = mPidsSelfLocked.get(callingPid);
- }
- if (proc != null && proc.curProcState
- < ActivityManager.PROCESS_STATE_RECEIVER) {
- // Whoever is instigating this is in the foreground, so we will allow it
- // to go through.
- return ActivityManager.APP_START_MODE_NORMAL;
- }
+ if (disabledOnly) {
+ // The caller is only interested in whether app starts are completely
+ // disabled for the given package (that is, it is an instant app). So
+ // we don't need to go further, which is all just seeing if we should
+ // apply a "delayed" mode for a regular app.
+ return ActivityManager.APP_START_MODE_NORMAL;
}
- */
-
final int startMode = (alwaysRestrict)
- ? appRestrictedInBackgroundLocked(uid, packageName)
- : appServicesRestrictedInBackgroundLocked(uid, packageName);
+ ? appRestrictedInBackgroundLocked(uid, packageName, packageTargetSdk)
+ : appServicesRestrictedInBackgroundLocked(uid, packageName,
+ packageTargetSdk);
if (DEBUG_BACKGROUND_CHECK) Slog.d(TAG, "checkAllowBackground: uid=" + uid
+ " pkg=" + packageName + " startMode=" + startMode
+ " onwhitelist=" + isOnDeviceIdleWhitelistLocked(uid));
+ if (startMode == ActivityManager.APP_START_MODE_DELAYED) {
+ // This is an old app that has been forced into a "compatible as possible"
+ // mode of background check. To increase compatibility, we will allow other
+ // foreground apps to cause its services to start.
+ if (callingPid >= 0) {
+ ProcessRecord proc;
+ synchronized (mPidsSelfLocked) {
+ proc = mPidsSelfLocked.get(callingPid);
+ }
+ if (proc != null && proc.curProcState
+ < ActivityManager.PROCESS_STATE_RECEIVER) {
+ // Whoever is instigating this is in the foreground, so we will allow it
+ // to go through.
+ return ActivityManager.APP_START_MODE_NORMAL;
+ }
+ }
+ }
return startMode;
}
}
diff --git a/services/core/java/com/android/server/am/BroadcastQueue.java b/services/core/java/com/android/server/am/BroadcastQueue.java
index 61e555bd8b21..ee2467a925c1 100644
--- a/services/core/java/com/android/server/am/BroadcastQueue.java
+++ b/services/core/java/com/android/server/am/BroadcastQueue.java
@@ -592,22 +592,6 @@ public final class BroadcastQueue {
+ " (uid " + r.callingUid + ")");
skip = true;
}
- if (!skip) {
- final int allowed = mService.checkAllowBackgroundLocked(filter.receiverList.uid,
- filter.packageName, -1, false);
- if (false && allowed == ActivityManager.APP_START_MODE_DISABLED) {
- // XXX should we really not allow this? It means that while we are
- // keeping an ephemeral app cached, its registered receivers will stop
- // receiving broadcasts after it goes idle... so if it comes back to
- // the foreground, it won't know what the current state of those broadcasts is.
- Slog.w(TAG, "Background execution not allowed: receiving "
- + r.intent
- + " to " + filter.receiverList.app
- + " (pid=" + filter.receiverList.pid
- + ", uid=" + filter.receiverList.uid + ")");
- skip = true;
- }
- }
if (!mService.mIntentFirewall.checkBroadcast(r.intent, r.callingUid,
r.callingPid, r.resolvedType, filter.receiverList.uid)) {
@@ -1156,13 +1140,14 @@ public final class BroadcastQueue {
info.activityInfo.applicationInfo.uid, false);
if (!skip) {
- final int allowed = mService.checkAllowBackgroundLocked(
- info.activityInfo.applicationInfo.uid, info.activityInfo.packageName, -1, true);
+ final int allowed = mService.getAppStartModeLocked(
+ info.activityInfo.applicationInfo.uid, info.activityInfo.packageName,
+ info.activityInfo.applicationInfo.targetSdkVersion, -1, true, false);
if (allowed != ActivityManager.APP_START_MODE_NORMAL) {
// We won't allow this receiver to be launched if the app has been
// completely disabled from launches, or it was not explicitly sent
// to it and the app is in a state that should not receive it
- // (depending on how checkAllowBackgroundLocked has determined that).
+ // (depending on how getAppStartModeLocked has determined that).
if (allowed == ActivityManager.APP_START_MODE_DISABLED) {
Slog.w(TAG, "Background execution disabled: receiving "
+ r.intent + " to "
diff --git a/services/core/java/com/android/server/content/SyncManager.java b/services/core/java/com/android/server/content/SyncManager.java
index 11a3f1189129..5b539ff1976d 100644
--- a/services/core/java/com/android/server/content/SyncManager.java
+++ b/services/core/java/com/android/server/content/SyncManager.java
@@ -1019,8 +1019,7 @@ public class SyncManager {
final int owningUid = syncAdapterInfo.uid;
final String owningPackage = syncAdapterInfo.componentName.getPackageName();
try {
- if (ActivityManager.getService().getAppStartMode(owningUid,
- owningPackage) == ActivityManager.APP_START_MODE_DISABLED) {
+ if (ActivityManager.getService().isAppStartModeDisabled(owningUid, owningPackage)) {
Slog.w(TAG, "Not scheduling job " + syncAdapterInfo.uid + ":"
+ syncAdapterInfo.componentName
+ " -- package not allowed to start");
diff --git a/services/core/java/com/android/server/job/JobSchedulerService.java b/services/core/java/com/android/server/job/JobSchedulerService.java
index f42c5be0ebf9..a7480133972a 100644
--- a/services/core/java/com/android/server/job/JobSchedulerService.java
+++ b/services/core/java/com/android/server/job/JobSchedulerService.java
@@ -566,8 +566,8 @@ public final class JobSchedulerService extends com.android.server.SystemService
String tag) {
JobStatus jobStatus = JobStatus.createFromJobInfo(job, uId, packageName, userId, tag);
try {
- if (ActivityManager.getService().getAppStartMode(uId,
- job.getService().getPackageName()) == ActivityManager.APP_START_MODE_DISABLED) {
+ if (ActivityManager.getService().isAppStartModeDisabled(uId,
+ job.getService().getPackageName())) {
Slog.w(TAG, "Not scheduling job " + uId + ":" + job.toString()
+ " -- package not allowed to start");
return JobScheduler.RESULT_FAILURE;
@@ -1201,9 +1201,8 @@ public final class JobSchedulerService extends com.android.server.SystemService
public void process(JobStatus job) {
if (isReadyToBeExecutedLocked(job)) {
try {
- if (ActivityManager.getService().getAppStartMode(job.getUid(),
- job.getJob().getService().getPackageName())
- == ActivityManager.APP_START_MODE_DISABLED) {
+ if (ActivityManager.getService().isAppStartModeDisabled(job.getUid(),
+ job.getJob().getService().getPackageName())) {
Slog.w(TAG, "Aborting job " + job.getUid() + ":"
+ job.getJob().toString() + " -- package not allowed to start");
mHandler.obtainMessage(MSG_STOP_JOB, job).sendToTarget();