OSDN Git Service

ShortcutManager: Update foreground check.
authorMakoto Onuki <omakoto@google.com>
Wed, 3 Aug 2016 22:45:24 +0000 (15:45 -0700)
committerMakoto Onuki <omakoto@google.com>
Wed, 3 Aug 2016 23:36:38 +0000 (16:36 -0700)
- When the cached UID state says a UID is in the background,
check with AM and get the latest state, since the state
might just have been changed.

Bug 30640208

Change-Id: If448f6f21f290fa0fc13550d9c740f56aa8bfce0

core/java/android/app/ActivityManagerInternal.java
services/core/java/com/android/server/am/ActivityManagerService.java
services/core/java/com/android/server/pm/ShortcutService.java
services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java

index 83e2678..0ba937a 100644 (file)
@@ -171,4 +171,12 @@ public abstract class ActivityManagerInternal {
      */
     public abstract int startActivitiesAsPackage(String packageName,
             int userId, Intent[] intents, Bundle bOptions);
+
+    /**
+     * Get the procstate for the UID.  The return value will be between
+     * {@link ActivityManager#MIN_PROCESS_STATE} and {@link ActivityManager#MAX_PROCESS_STATE}.
+     * Note if the UID doesn't exist, it'll return {@link ActivityManager#PROCESS_STATE_NONEXISTENT}
+     * (-1).
+     */
+    public abstract int getUidProcessState(int uid);
 }
index 87036cf..5cd0255 100644 (file)
@@ -21942,6 +21942,11 @@ public final class ActivityManagerService extends ActivityManagerNative
                         /*resultTo*/ null, bOptions, userId);
             }
         }
+
+        @Override
+        public int getUidProcessState(int uid) {
+            return getUidState(uid);
+        }
     }
 
     private final class SleepTokenImpl extends SleepToken {
index 8d400b5..558467b 100644 (file)
@@ -20,6 +20,7 @@ import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.UserIdInt;
 import android.app.ActivityManager;
+import android.app.ActivityManagerInternal;
 import android.app.ActivityManagerNative;
 import android.app.AppGlobals;
 import android.app.IUidObserver;
@@ -284,6 +285,7 @@ public class ShortcutService extends IShortcutService.Stub {
     private final PackageManagerInternal mPackageManagerInternal;
     private final UserManager mUserManager;
     private final UsageStatsManagerInternal mUsageStatsManagerInternal;
+    private final ActivityManagerInternal mActivityManagerInternal;
 
     @GuardedBy("mLock")
     final SparseIntArray mUidState = new SparseIntArray();
@@ -372,6 +374,8 @@ public class ShortcutService extends IShortcutService.Stub {
         mUserManager = Preconditions.checkNotNull(context.getSystemService(UserManager.class));
         mUsageStatsManagerInternal = Preconditions.checkNotNull(
                 LocalServices.getService(UsageStatsManagerInternal.class));
+        mActivityManagerInternal = Preconditions.checkNotNull(
+                LocalServices.getService(ActivityManagerInternal.class));
 
         if (onlyForPackageManagerApis) {
             return; // Don't do anything further.  For unit tests only.
@@ -456,7 +460,8 @@ public class ShortcutService extends IShortcutService.Stub {
     }
 
     private boolean isProcessStateForeground(int processState) {
-        return processState <= PROCESS_STATE_FOREGROUND_THRESHOLD;
+        return (processState != ActivityManager.PROCESS_STATE_NONEXISTENT)
+                && (processState <= PROCESS_STATE_FOREGROUND_THRESHOLD);
     }
 
     boolean isUidForegroundLocked(int uid) {
@@ -465,7 +470,13 @@ public class ShortcutService extends IShortcutService.Stub {
             // so it's foreground anyway.
             return true;
         }
-        return isProcessStateForeground(mUidState.get(uid, ActivityManager.MAX_PROCESS_STATE));
+        // First, check with the local cache.
+        if (isProcessStateForeground(mUidState.get(uid, ActivityManager.MAX_PROCESS_STATE))) {
+            return true;
+        }
+        // If the cache says background, reach out to AM.  Since it'll internally need to hold
+        // the AM lock, we use it as a last resort.
+        return isProcessStateForeground(mActivityManagerInternal.getUidProcessState(uid));
     }
 
     long getUidLastForegroundElapsedTimeLocked(int uid) {
index d003e56..e7f3345 100644 (file)
@@ -36,6 +36,7 @@ import static org.mockito.Mockito.when;
 import android.annotation.NonNull;
 import android.annotation.UserIdInt;
 import android.app.Activity;
+import android.app.ActivityManager;
 import android.app.ActivityManagerInternal;
 import android.app.IUidObserver;
 import android.app.usage.UsageStatsManagerInternal;
@@ -715,6 +716,9 @@ public abstract class BaseShortcutManagerTest extends InstrumentationTestCase {
                     return b(mRunningUsers.get(userId)) && b(mUnlockedUsers.get(userId));
                 }));
 
+        when(mMockActivityManagerInternal.getUidProcessState(anyInt())).thenReturn(
+                ActivityManager.PROCESS_STATE_CACHED_EMPTY);
+
         // User 0 and P0 are always running
         mRunningUsers.put(USER_0, true);
         mRunningUsers.put(USER_10, false);