Merge "QS: Hacks to fix bigger problems in TileService binding" into nyc-dev
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index 3c7eef5..cf5240b 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -1813,12 +1813,13 @@
             return true;
         }
 
-        case KILL_APPLICATION_WITH_APPID_TRANSACTION: {
+        case KILL_APPLICATION_TRANSACTION: {
             data.enforceInterface(IActivityManager.descriptor);
             String pkg = data.readString();
-            int appid = data.readInt();
+            int appId = data.readInt();
+            int userId = data.readInt();
             String reason = data.readString();
-            killApplicationWithAppId(pkg, appid, reason);
+            killApplication(pkg, appId, userId, reason);
             reply.writeNoException();
             return true;
         }
@@ -5291,15 +5292,16 @@
         reply.recycle();
     }
 
-    public void killApplicationWithAppId(String pkg, int appid, String reason)
+    public void killApplication(String pkg, int appId, int userId, String reason)
             throws RemoteException {
         Parcel data = Parcel.obtain();
         Parcel reply = Parcel.obtain();
         data.writeInterfaceToken(IActivityManager.descriptor);
         data.writeString(pkg);
-        data.writeInt(appid);
+        data.writeInt(appId);
+        data.writeInt(userId);
         data.writeString(reason);
-        mRemote.transact(KILL_APPLICATION_WITH_APPID_TRANSACTION, data, reply, 0);
+        mRemote.transact(KILL_APPLICATION_TRANSACTION, data, reply, 0);
         reply.readException();
         data.recycle();
         reply.recycle();
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
index ac21346..5037e3e 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -398,7 +398,7 @@
 
     public void addPackageDependency(String packageName) throws RemoteException;
 
-    public void killApplicationWithAppId(String pkg, int appid, String reason)
+    public void killApplication(String pkg, int appId, int userId, String reason)
             throws RemoteException;
 
     public void closeSystemDialogs(String reason) throws RemoteException;
@@ -852,7 +852,7 @@
     int GET_UID_FOR_INTENT_SENDER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+92;
     int HANDLE_INCOMING_USER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+93;
     int ADD_PACKAGE_DEPENDENCY_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+94;
-    int KILL_APPLICATION_WITH_APPID_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+95;
+    int KILL_APPLICATION_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+95;
     int CLOSE_SYSTEM_DIALOGS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+96;
     int GET_PROCESS_MEMORY_INFO_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+97;
     int KILL_APPLICATION_PROCESS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+98;
diff --git a/core/java/android/view/Choreographer.java b/core/java/android/view/Choreographer.java
index a865307..d3db74d 100644
--- a/core/java/android/view/Choreographer.java
+++ b/core/java/android/view/Choreographer.java
@@ -232,6 +232,19 @@
         return sThreadInstance.get();
     }
 
+    /** Destroys the calling thread's choreographer
+     * @hide
+     */
+    public static void releaseInstance() {
+        Choreographer old = sThreadInstance.get();
+        sThreadInstance.remove();
+        old.dispose();
+    }
+
+    private void dispose() {
+        mDisplayEventReceiver.dispose();
+    }
+
     /**
      * The amount of time, in milliseconds, between each frame of the animation.
      * <p>
diff --git a/core/java/com/android/internal/policy/BackdropFrameRenderer.java b/core/java/com/android/internal/policy/BackdropFrameRenderer.java
index 28281b3c..488f769 100644
--- a/core/java/com/android/internal/policy/BackdropFrameRenderer.java
+++ b/core/java/com/android/internal/policy/BackdropFrameRenderer.java
@@ -217,6 +217,7 @@
         synchronized (this) {
             // Make sure no more messages are being sent.
             mChoreographer = null;
+            Choreographer.releaseInstance();
         }
     }
 
diff --git a/core/jni/android_view_DisplayEventReceiver.cpp b/core/jni/android_view_DisplayEventReceiver.cpp
index f9936ae..a0d5904 100644
--- a/core/jni/android_view_DisplayEventReceiver.cpp
+++ b/core/jni/android_view_DisplayEventReceiver.cpp
@@ -81,14 +81,12 @@
 NativeDisplayEventReceiver::~NativeDisplayEventReceiver() {
     JNIEnv* env = AndroidRuntime::getJNIEnv();
     env->DeleteGlobalRef(mReceiverWeakGlobal);
+    ALOGV("receiver %p ~ dtor display event receiver.", this);
 }
 
 void NativeDisplayEventReceiver::dispose() {
     ALOGV("receiver %p ~ Disposing display event receiver.", this);
-
-    if (!mReceiver.initCheck()) {
-        mMessageQueue->getLooper()->removeFd(mReceiver.getFd());
-    }
+    DisplayEventDispatcher::dispose();
 }
 
 void NativeDisplayEventReceiver::dispatchVsync(nsecs_t timestamp, int32_t id, uint32_t count) {
@@ -143,7 +141,7 @@
 }
 
 static void nativeDispose(JNIEnv* env, jclass clazz, jlong receiverPtr) {
-    sp<NativeDisplayEventReceiver> receiver =
+    NativeDisplayEventReceiver* receiver =
             reinterpret_cast<NativeDisplayEventReceiver*>(receiverPtr);
     receiver->dispose();
     receiver->decStrong(gDisplayEventReceiverClassInfo.clazz); // drop reference held by the object
diff --git a/docs/html/wear/preview/api-overview.jd b/docs/html/wear/preview/api-overview.jd
index 543313a..11331a7 100644
--- a/docs/html/wear/preview/api-overview.jd
+++ b/docs/html/wear/preview/api-overview.jd
@@ -4,9 +4,6 @@
 page.image=images/cards/card-n-apis_2x.png
 @jd:body
 
-
-
-
 <div id="qv-wrapper">
 <div id="qv">
   <h2>Key developer features</h2>
@@ -298,36 +295,35 @@
  authentication capabilities will be more powerful; apps will have new ways to
  authenticate.</p>
 
- <h4> Authentication tokens can be passed over the Wearable Data Layer </h4>
-
-<p>For Android-paired watches (only), the phone will securely transfer authentication
- data to a watch app via the
- <a href="{@docRoot}training/wearables/data-layer/index.html">
- Wearable Data Layer API</a>. The data can be transferred as
- Messages or Data Items. </p>
-
-<p>If your watch app needs to determine if your phone app is installed, you can
-advertise a capability on the phone app and retrieve the capability on the watch.
- For more information, see following sections of
- <a href="{@docRoot}training/wearables/data-layer/messages.html">
- Sending and Receiving Messages</a>:
- <ul>
- <li>Advertise Capabilities</li>
- <li>Retrieve the Nodes with the Required Capabilities</li>
- </ul>
 <h4>Users can enter a username and password on a watch</h4>
 
-<p>Google Keyboard will be standard on Android Wear, allowing for direct text entry.
- This feature will work as expected with standard
- <a href="{@docRoot}reference/android/widget/EditText.html">
-  EditText widgets</a>. For passwords, the {@code textPassword} attribute will be
-   used.
+<p>Google Keyboard will be standard on Android Wear, allowing for direct text
+entry. This feature will work as expected with standard
+<a href="{@docRoot}reference/android/widget/EditText.html">EditText widgets</a>.
+For passwords, the {@code textPassword} attribute will be used.</p>
 
 <h4>Utilizing Account Manager</h4>
-Android Wear will include the <a href="{@docRoot}reference/android/accounts/AccountManager.html">
+
+<p>Android Wear will include the
+<a href="{@docRoot}reference/android/accounts/AccountManager.html">
 AccountManager</a>, which will be accessible for syncing and storing account
- data, as it is on an Android phone.
-</p>
+data, as it is on an Android phone.</p>
 
+<h4>Authentication tokens can be passed over the Wearable Data Layer</h4>
 
+<p>For Android-paired watches (only), a phone securely
+transfers authentication credentials to a watch app via the
+<a href="{@docRoot}training/wearables/data-layer/index.html">
+Wearable Data Layer API</a>. The credentials can be transferred as
+messages or data items.</p>
 
+<p>If your watch app needs to determine if your phone app is installed, you can
+advertise a capability on the phone app and retrieve the capability on the
+watch. For more information, see the following sections of
+<a href="{@docRoot}training/wearables/data-layer/messages.html">
+Sending and Receiving Messages</a>:</p>
+
+<ul>
+  <li>Advertise Capabilities</li>
+  <li>Retrieve the Nodes with the Required Capabilities</li>
+</ul>
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java
index d3434e5..016c4b7 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java
@@ -85,6 +85,7 @@
             mController.addCallback(mCallback);
             final IntentFilter filter = new IntentFilter();
             filter.addAction(Intent.ACTION_AIRPLANE_MODE_CHANGED);
+            refreshState();
         } else {
             mController.removeCallback(mCallback);
         }
diff --git a/services/core/java/com/android/server/MountService.java b/services/core/java/com/android/server/MountService.java
index 55464e4..cdd977b 100644
--- a/services/core/java/com/android/server/MountService.java
+++ b/services/core/java/com/android/server/MountService.java
@@ -827,8 +827,9 @@
                 if (provider != null) {
                     final IActivityManager am = ActivityManagerNative.getDefault();
                     try {
-                        am.killApplicationWithAppId(provider.applicationInfo.packageName,
-                                UserHandle.getAppId(provider.applicationInfo.uid), "vold reset");
+                        am.killApplication(provider.applicationInfo.packageName,
+                                UserHandle.getAppId(provider.applicationInfo.uid),
+                                UserHandle.USER_ALL, "vold reset");
                         // We only need to run this once. It will kill all users' media processes.
                         break;
                     } catch (RemoteException e) {
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index d1ee634..8f63dc3 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -1849,13 +1849,13 @@
             } break;
             case KILL_APPLICATION_MSG: {
                 synchronized (ActivityManagerService.this) {
-                    int appid = msg.arg1;
-                    boolean restart = (msg.arg2 == 1);
+                    final int appId = msg.arg1;
+                    final int userId = msg.arg2;
                     Bundle bundle = (Bundle)msg.obj;
                     String pkg = bundle.getString("pkg");
                     String reason = bundle.getString("reason");
-                    forceStopPackageLocked(pkg, appid, restart, false, true, false,
-                            false, UserHandle.USER_ALL, reason);
+                    forceStopPackageLocked(pkg, appId, false, false, true, false,
+                            false, userId, reason);
                 }
             } break;
             case FINALIZE_PENDING_INTENT_MSG: {
@@ -5717,12 +5717,12 @@
      * The pkg name and app id have to be specified.
      */
     @Override
-    public void killApplicationWithAppId(String pkg, int appid, String reason) {
+    public void killApplication(String pkg, int appId, int userId, String reason) {
         if (pkg == null) {
             return;
         }
         // Make sure the uid is valid.
-        if (appid < 0) {
+        if (appId < 0) {
             Slog.w(TAG, "Invalid appid specified for pkg : " + pkg);
             return;
         }
@@ -5731,8 +5731,8 @@
         if (UserHandle.getAppId(callerUid) == Process.SYSTEM_UID) {
             // Post an aysnc message to kill the application
             Message msg = mHandler.obtainMessage(KILL_APPLICATION_MSG);
-            msg.arg1 = appid;
-            msg.arg2 = 0;
+            msg.arg1 = appId;
+            msg.arg2 = userId;
             Bundle bundle = new Bundle();
             bundle.putString("pkg", pkg);
             bundle.putString("reason", reason);
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 96513b9..0019973 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -9534,6 +9534,10 @@
     }
 
     private void killApplication(String pkgName, int appId, String reason) {
+        killApplication(pkgName, appId, UserHandle.USER_ALL, reason);
+    }
+
+    private void killApplication(String pkgName, int appId, int userId, String reason) {
         // Request the ActivityManager to kill the process(only for existing packages)
         // so that we do not end up in a confused state while the user is still using the older
         // version of the application while the new one gets installed.
@@ -9542,7 +9546,7 @@
             IActivityManager am = ActivityManagerNative.getDefault();
             if (am != null) {
                 try {
-                    am.killApplicationWithAppId(pkgName, appId, reason);
+                    am.killApplication(pkgName, appId, userId, reason);
                 } catch (RemoteException e) {
                 }
             }
@@ -15555,10 +15559,10 @@
         final PackageRemovedInfo info = new PackageRemovedInfo();
         final boolean res;
 
-        final UserHandle removeForUser = (deleteFlags & PackageManager.DELETE_ALL_USERS) != 0
-                ? UserHandle.ALL : new UserHandle(userId);
+        final int removeUser = (deleteFlags & PackageManager.DELETE_ALL_USERS) != 0
+                ? UserHandle.USER_ALL : userId;
 
-        if (isPackageDeviceAdmin(packageName, removeForUser.getIdentifier())) {
+        if (isPackageDeviceAdmin(packageName, removeUser)) {
             Slog.w(TAG, "Not removing package " + packageName + ": has active device admin");
             return PackageManager.DELETE_FAILED_DEVICE_POLICY_MANAGER;
         }
@@ -15578,11 +15582,21 @@
             info.origUsers = uninstalledPs.queryInstalledUsers(allUsers, true);
         }
 
+        final int freezeUser;
+        if (isUpdatedSystemApp(uninstalledPs)
+                && ((deleteFlags & PackageManager.DELETE_SYSTEM_APP) == 0)) {
+            // We're downgrading a system app, which will apply to all users, so
+            // freeze them all during the downgrade
+            freezeUser = UserHandle.USER_ALL;
+        } else {
+            freezeUser = removeUser;
+        }
+
         synchronized (mInstallLock) {
             if (DEBUG_REMOVE) Slog.d(TAG, "deletePackageX: pkg=" + packageName + " user=" + userId);
-            try (PackageFreezer freezer = freezePackageForDelete(packageName, deleteFlags,
-                    "deletePackageX")) {
-                res = deletePackageLIF(packageName, removeForUser, true, allUsers,
+            try (PackageFreezer freezer = freezePackageForDelete(packageName, freezeUser,
+                    deleteFlags, "deletePackageX")) {
+                res = deletePackageLIF(packageName, UserHandle.of(removeUser), true, allUsers,
                         deleteFlags | REMOVE_CHATTY, info, true, null);
             }
             synchronized (mPackages) {
@@ -19837,24 +19851,38 @@
     }
 
     public PackageFreezer freezePackage(String packageName, String killReason) {
-        return new PackageFreezer(packageName, killReason);
+        return freezePackage(packageName, UserHandle.USER_ALL, killReason);
+    }
+
+    public PackageFreezer freezePackage(String packageName, int userId, String killReason) {
+        return new PackageFreezer(packageName, userId, killReason);
     }
 
     public PackageFreezer freezePackageForInstall(String packageName, int installFlags,
             String killReason) {
+        return freezePackageForInstall(packageName, UserHandle.USER_ALL, installFlags, killReason);
+    }
+
+    public PackageFreezer freezePackageForInstall(String packageName, int userId, int installFlags,
+            String killReason) {
         if ((installFlags & PackageManager.INSTALL_DONT_KILL_APP) != 0) {
             return new PackageFreezer();
         } else {
-            return freezePackage(packageName, killReason);
+            return freezePackage(packageName, userId, killReason);
         }
     }
 
     public PackageFreezer freezePackageForDelete(String packageName, int deleteFlags,
             String killReason) {
+        return freezePackageForDelete(packageName, UserHandle.USER_ALL, deleteFlags, killReason);
+    }
+
+    public PackageFreezer freezePackageForDelete(String packageName, int userId, int deleteFlags,
+            String killReason) {
         if ((deleteFlags & PackageManager.DELETE_DONT_KILL_APP) != 0) {
             return new PackageFreezer();
         } else {
-            return freezePackage(packageName, killReason);
+            return freezePackage(packageName, userId, killReason);
         }
     }
 
@@ -19885,14 +19913,14 @@
             mCloseGuard.open("close");
         }
 
-        public PackageFreezer(String packageName, String killReason) {
+        public PackageFreezer(String packageName, int userId, String killReason) {
             synchronized (mPackages) {
                 mPackageName = packageName;
                 mWeFroze = mFrozenPackages.add(mPackageName);
 
                 final PackageSetting ps = mSettings.mPackages.get(mPackageName);
                 if (ps != null) {
-                    killApplication(ps.name, ps.appId, killReason);
+                    killApplication(ps.name, ps.appId, userId, killReason);
                 }
 
                 final PackageParser.Package p = mPackages.get(packageName);
@@ -19901,7 +19929,7 @@
                     mChildren = new PackageFreezer[N];
                     for (int i = 0; i < N; i++) {
                         mChildren[i] = new PackageFreezer(p.childPackages.get(i).packageName,
-                                killReason);
+                                userId, killReason);
                     }
                 } else {
                     mChildren = null;
@@ -20040,7 +20068,7 @@
             seinfo = pkg.applicationInfo.seinfo;
             label = String.valueOf(pm.getApplicationLabel(pkg.applicationInfo));
             targetSdkVersion = pkg.applicationInfo.targetSdkVersion;
-            freezer = new PackageFreezer(packageName, "movePackageInternal");
+            freezer = freezePackage(packageName, "movePackageInternal");
             installedUserIds = ps.queryInstalledUsers(sUserManager.getUserIds(), true);
         }