am 1a7cb969: Merge "Fix issue #16662560: SingleTop activity is getting instantiated multiple time" into lmp-dev

* commit '1a7cb969b833be16632cbcadc498a1fb978ca659':
  Fix issue #16662560: SingleTop activity is getting instantiated multiple time
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index e224ac0..a3f48f8 100755
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -550,10 +550,10 @@
 
             if (DEBUG_TASKS) Slog.d(TAG, "Comparing existing cls="
                     + taskIntent.getComponent().flattenToShortString()
-                    + "/aff=" + r.task.affinity + " to new cls="
+                    + "/aff=" + r.task.rootAffinity + " to new cls="
                     + intent.getComponent().flattenToShortString() + "/aff=" + info.taskAffinity);
-            if (!isDocument && !taskIsDocument && task.affinity != null) {
-                if (task.affinity.equals(target.taskAffinity)) {
+            if (!isDocument && !taskIsDocument && task.rootAffinity != null) {
+                if (task.rootAffinity.equals(target.taskAffinity)) {
                     if (DEBUG_TASKS) Slog.d(TAG, "Found matching affinity!");
                     return r;
                 }
diff --git a/services/core/java/com/android/server/am/TaskRecord.java b/services/core/java/com/android/server/am/TaskRecord.java
index 071db97..4de7367 100644
--- a/services/core/java/com/android/server/am/TaskRecord.java
+++ b/services/core/java/com/android/server/am/TaskRecord.java
@@ -58,6 +58,7 @@
     private static final String ATTR_ORIGACTIVITY = "orig_activity";
     private static final String TAG_ACTIVITY = "activity";
     private static final String ATTR_AFFINITY = "affinity";
+    private static final String ATTR_ROOT_AFFINITY = "root_affinity";
     private static final String ATTR_ROOTHASRESET = "root_has_reset";
     private static final String ATTR_AUTOREMOVERECENTS = "auto_remove_recents";
     private static final String ATTR_ASKEDCOMPATMODE = "asked_compat_mode";
@@ -84,7 +85,8 @@
     static final boolean IGNORE_RETURN_TO_RECENTS = true;
 
     final int taskId;       // Unique identifier for this task.
-    String affinity;        // The affinity name for this task, or null.
+    String affinity;        // The affinity name for this task, or null; may change identity.
+    String rootAffinity;    // Initial base affinity, or null; does not change from initial root.
     final IVoiceInteractionSession voiceSession;    // Voice interaction session driving task
     final IVoiceInteractor voiceInteractor;         // Associated interactor to provide to app
     Intent intent;          // The original intent that started the task.
@@ -208,9 +210,9 @@
     }
 
     TaskRecord(ActivityManagerService service, int _taskId, Intent _intent, Intent _affinityIntent,
-            String _affinity, ComponentName _realActivity, ComponentName _origActivity,
-            boolean _rootWasReset, boolean _autoRemoveRecents, boolean _askedCompatMode,
-            int _taskType, int _userId, int _effectiveUid,
+            String _affinity, String _rootAffinity, ComponentName _realActivity,
+            ComponentName _origActivity, boolean _rootWasReset, boolean _autoRemoveRecents,
+            boolean _askedCompatMode, int _taskType, int _userId, int _effectiveUid,
             String _lastDescription, ArrayList<ActivityRecord> activities, long _firstActiveTime,
             long _lastActiveTime, long lastTimeMoved, boolean neverRelinquishIdentity,
             ActivityManager.TaskDescription _lastTaskDescription, int taskAffiliation,
@@ -224,6 +226,7 @@
         intent = _intent;
         affinityIntent = _affinityIntent;
         affinity = _affinity;
+        rootAffinity = _affinity;
         voiceSession = null;
         voiceInteractor = null;
         realActivity = _realActivity;
@@ -279,6 +282,12 @@
         }
 
         affinity = info.taskAffinity;
+        if (intent == null) {
+            // If this task already has an intent associated with it, don't set the root
+            // affinity -- we don't want it changing after initially set, but the initially
+            // set value may be null.
+            rootAffinity = affinity;
+        }
         effectiveUid = info.applicationInfo.uid;
         stringName = null;
 
@@ -840,8 +849,17 @@
         if (origActivity != null) {
             out.attribute(null, ATTR_ORIGACTIVITY, origActivity.flattenToShortString());
         }
+        // Write affinity, and root affinity if it is different from affinity.
+        // We use the special string "@" for a null root affinity, so we can identify
+        // later whether we were given a root affinity or should just make it the
+        // same as the affinity.
         if (affinity != null) {
             out.attribute(null, ATTR_AFFINITY, affinity);
+            if (!affinity.equals(rootAffinity)) {
+                out.attribute(null, ATTR_ROOT_AFFINITY, rootAffinity != null ? rootAffinity : "@");
+            }
+        } else if (rootAffinity != null) {
+            out.attribute(null, ATTR_ROOT_AFFINITY, rootAffinity != null ? rootAffinity : "@");
         }
         out.attribute(null, ATTR_ROOTHASRESET, String.valueOf(rootWasReset));
         out.attribute(null, ATTR_AUTOREMOVERECENTS, String.valueOf(autoRemoveRecents));
@@ -901,6 +919,8 @@
         ComponentName realActivity = null;
         ComponentName origActivity = null;
         String affinity = null;
+        String rootAffinity = null;
+        boolean hasRootAffinity = false;
         boolean rootHasReset = false;
         boolean autoRemoveRecents = false;
         boolean askedCompatMode = false;
@@ -935,6 +955,9 @@
                 origActivity = ComponentName.unflattenFromString(attrValue);
             } else if (ATTR_AFFINITY.equals(attrName)) {
                 affinity = attrValue;
+            } else if (ATTR_ROOT_AFFINITY.equals(attrName)) {
+                rootAffinity = attrValue;
+                hasRootAffinity = true;
             } else if (ATTR_ROOTHASRESET.equals(attrName)) {
                 rootHasReset = Boolean.valueOf(attrValue);
             } else if (ATTR_AUTOREMOVERECENTS.equals(attrName)) {
@@ -1007,6 +1030,12 @@
                     createLastTaskDescriptionIconFilename(taskId, lastActiveTime)));
         }
 
+        if (!hasRootAffinity) {
+            rootAffinity = affinity;
+        } else if ("@".equals(rootAffinity)) {
+            rootAffinity = null;
+        }
+
         if (effectiveUid <= 0) {
             Intent checkIntent = intent != null ? intent : affinityIntent;
             effectiveUid = 0;
@@ -1028,7 +1057,7 @@
         }
 
         final TaskRecord task = new TaskRecord(stackSupervisor.mService, taskId, intent,
-                affinityIntent, affinity, realActivity, origActivity, rootHasReset,
+                affinityIntent, affinity, rootAffinity, realActivity, origActivity, rootHasReset,
                 autoRemoveRecents, askedCompatMode, taskType, userId, effectiveUid, lastDescription,
                 activities, firstActiveTime, lastActiveTime, lastTimeOnTop, neverRelinquishIdentity,
                 taskDescription, taskAffiliation, prevTaskId, nextTaskId, taskAffiliationColor,
@@ -1047,8 +1076,13 @@
                 pw.print(" effectiveUid="); UserHandle.formatUid(pw, effectiveUid);
                 pw.print(" mCallingUid="); UserHandle.formatUid(pw, mCallingUid);
                 pw.print(" mCallingPackage="); pw.println(mCallingPackage);
-        if (affinity != null) {
-            pw.print(prefix); pw.print("affinity="); pw.println(affinity);
+        if (affinity != null || rootAffinity != null) {
+            pw.print(prefix); pw.print("affinity="); pw.print(affinity);
+            if (affinity == null || !affinity.equals(rootAffinity)) {
+                pw.print(" root="); pw.println(rootAffinity);
+            } else {
+                pw.println();
+            }
         }
         if (voiceSession != null || voiceInteractor != null) {
             pw.print(prefix); pw.print("VOICE: session=0x");
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index d87fc2e..79c9955 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -4311,7 +4311,7 @@
                  * grantPermissions will assume the package update is trying to
                  * expand its permissions.
                  */
-                grantPermissionsLPw(pkg, true);
+                grantPermissionsLPw(pkg, true, pkg.packageName);
                 mSettings.disableSystemPackageLPw(pkg.packageName);
             }
         }
@@ -6696,17 +6696,19 @@
         if ((flags&UPDATE_PERMISSIONS_ALL) != 0) {
             for (PackageParser.Package pkg : mPackages.values()) {
                 if (pkg != pkgInfo) {
-                    grantPermissionsLPw(pkg, (flags&UPDATE_PERMISSIONS_REPLACE_ALL) != 0);
+                    grantPermissionsLPw(pkg, (flags&UPDATE_PERMISSIONS_REPLACE_ALL) != 0,
+                            changingPkg);
                 }
             }
         }
         
         if (pkgInfo != null) {
-            grantPermissionsLPw(pkgInfo, (flags&UPDATE_PERMISSIONS_REPLACE_PKG) != 0);
+            grantPermissionsLPw(pkgInfo, (flags&UPDATE_PERMISSIONS_REPLACE_PKG) != 0, changingPkg);
         }
     }
 
-    private void grantPermissionsLPw(PackageParser.Package pkg, boolean replace) {
+    private void grantPermissionsLPw(PackageParser.Package pkg, boolean replace,
+            String packageOfInterest) {
         final PackageSetting ps = (PackageSetting) pkg.mExtras;
         if (ps == null) {
             return;
@@ -6740,8 +6742,10 @@
             }
 
             if (bp == null || bp.packageSetting == null) {
-                Slog.w(TAG, "Unknown permission " + name
-                        + " in package " + pkg.packageName);
+                if (packageOfInterest == null || packageOfInterest.equals(pkg.packageName)) {
+                    Slog.w(TAG, "Unknown permission " + name
+                            + " in package " + pkg.packageName);
+                }
                 continue;
             }
 
@@ -6806,9 +6810,11 @@
                         gp.gids = appendInts(gp.gids, bp.gids);
                     }
                 } else {
-                    Slog.w(TAG, "Not granting permission " + perm
-                            + " to package " + pkg.packageName
-                            + " because it was previously installed without");
+                    if (packageOfInterest == null || packageOfInterest.equals(pkg.packageName)) {
+                        Slog.w(TAG, "Not granting permission " + perm
+                                + " to package " + pkg.packageName
+                                + " because it was previously installed without");
+                    }
                 }
             } else {
                 if (gp.grantedPermissions.remove(perm)) {
@@ -6822,11 +6828,13 @@
                 } else if ((bp.protectionLevel&PermissionInfo.PROTECTION_FLAG_APPOP) == 0) {
                     // Don't print warning for app op permissions, since it is fine for them
                     // not to be granted, there is a UI for the user to decide.
-                    Slog.w(TAG, "Not granting permission " + perm
-                            + " to package " + pkg.packageName
-                            + " (protectionLevel=" + bp.protectionLevel
-                            + " flags=0x" + Integer.toHexString(pkg.applicationInfo.flags)
-                            + ")");
+                    if (packageOfInterest == null || packageOfInterest.equals(pkg.packageName)) {
+                        Slog.w(TAG, "Not granting permission " + perm
+                                + " to package " + pkg.packageName
+                                + " (protectionLevel=" + bp.protectionLevel
+                                + " flags=0x" + Integer.toHexString(pkg.applicationInfo.flags)
+                                + ")");
+                    }
                 }
             }
         }