Surface user action events when un/installing.

This will be used shortly to connect up with permissions
confirmation UI.

Bug: 16515814
Change-Id: If28cecc28549900d960ac107a1fba0b10ce5bd7b
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index edcfd74..84b5516 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -28,6 +28,7 @@
 import android.content.pm.FeatureInfo;
 import android.content.pm.IPackageDataObserver;
 import android.content.pm.IPackageDeleteObserver;
+import android.content.pm.IPackageDeleteObserver2;
 import android.content.pm.IPackageInstallObserver;
 import android.content.pm.IPackageManager;
 import android.content.pm.IPackageMoveObserver;
@@ -1287,6 +1288,7 @@
             // Should never happen!
         }
     }
+
     @Override
     public void clearApplicationUserData(String packageName,
                                          IPackageDataObserver observer) {
@@ -1661,7 +1663,8 @@
         }
 
         @Override
-        public void packageInstalled(String basePackageName, Bundle extras, int returnCode) {
+        public void onPackageInstalled(String basePackageName, int returnCode, String msg,
+                Bundle extras) {
             try {
                 mLegacy.packageInstalled(basePackageName, returnCode);
             } catch (RemoteException ignored) {
@@ -1669,6 +1672,22 @@
         }
     }
 
+    private static class LegacyPackageDeleteObserver extends PackageDeleteObserver {
+        private final IPackageDeleteObserver mLegacy;
+
+        public LegacyPackageDeleteObserver(IPackageDeleteObserver legacy) {
+            mLegacy = legacy;
+        }
+
+        @Override
+        public void onPackageDeleted(String basePackageName, int returnCode, String msg) {
+            try {
+                mLegacy.packageDeleted(basePackageName, returnCode);
+            } catch (RemoteException ignored) {
+            }
+        }
+    }
+
     private final ContextImpl mContext;
     private final IPackageManager mPM;
 
diff --git a/core/java/android/app/PackageDeleteObserver.java b/core/java/android/app/PackageDeleteObserver.java
new file mode 100644
index 0000000..9b83ec1
--- /dev/null
+++ b/core/java/android/app/PackageDeleteObserver.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.app;
+
+import android.content.Intent;
+import android.content.pm.IPackageDeleteObserver2;
+
+/** {@hide} */
+public class PackageDeleteObserver {
+    private final IPackageDeleteObserver2.Stub mBinder = new IPackageDeleteObserver2.Stub() {
+        @Override
+        public void onUserActionRequired(Intent intent) {
+            PackageDeleteObserver.this.onUserActionRequired(intent);
+        }
+
+        @Override
+        public void onPackageDeleted(String basePackageName, int returnCode, String msg) {
+            PackageDeleteObserver.this.onPackageDeleted(basePackageName, returnCode, msg);
+        }
+    };
+
+    /** {@hide} */
+    public IPackageDeleteObserver2 getBinder() {
+        return mBinder;
+    }
+
+    public void onUserActionRequired(Intent intent) {
+    }
+
+    public void onPackageDeleted(String basePackageName, int returnCode, String msg) {
+    }
+}
diff --git a/core/java/android/app/PackageInstallObserver.java b/core/java/android/app/PackageInstallObserver.java
index 1b2504e..ff28679 100644
--- a/core/java/android/app/PackageInstallObserver.java
+++ b/core/java/android/app/PackageInstallObserver.java
@@ -16,6 +16,7 @@
 
 package android.app;
 
+import android.content.Intent;
 import android.content.pm.IPackageInstallObserver2;
 import android.os.Bundle;
 
@@ -23,9 +24,15 @@
 public class PackageInstallObserver {
     private final IPackageInstallObserver2.Stub mBinder = new IPackageInstallObserver2.Stub() {
         @Override
-        public void packageInstalled(String basePackageName, Bundle extras, int returnCode,
-                String msg) {
-            PackageInstallObserver.this.packageInstalled(basePackageName, extras, returnCode, msg);
+        public void onUserActionRequired(Intent intent) {
+            PackageInstallObserver.this.onUserActionRequired(intent);
+        }
+
+        @Override
+        public void onPackageInstalled(String basePackageName, int returnCode,
+                String msg, Bundle extras) {
+            PackageInstallObserver.this.onPackageInstalled(basePackageName, returnCode, msg,
+                    extras);
         }
     };
 
@@ -34,6 +41,9 @@
         return mBinder;
     }
 
+    public void onUserActionRequired(Intent intent) {
+    }
+
     /**
      * This method will be called to report the result of the package
      * installation attempt.
@@ -49,11 +59,7 @@
      *            basic outcome
      * @hide
      */
-    public void packageInstalled(String basePackageName, Bundle extras, int returnCode) {
-    }
-
-    public void packageInstalled(String basePackageName, Bundle extras, int returnCode,
-            String msg) {
-        packageInstalled(basePackageName, extras, returnCode);
+    public void onPackageInstalled(String basePackageName, int returnCode, String msg,
+            Bundle extras) {
     }
 }
diff --git a/core/java/android/app/PackageUninstallObserver.java b/core/java/android/app/PackageUninstallObserver.java
deleted file mode 100644
index 83fc380..0000000
--- a/core/java/android/app/PackageUninstallObserver.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.app;
-
-import android.content.pm.IPackageDeleteObserver;
-
-/** {@hide} */
-public class PackageUninstallObserver {
-    private final IPackageDeleteObserver.Stub mBinder = new IPackageDeleteObserver.Stub() {
-        @Override
-        public void packageDeleted(String basePackageName, int returnCode) {
-            PackageUninstallObserver.this.onUninstallFinished(basePackageName, returnCode);
-        }
-    };
-
-    /** {@hide} */
-    public IPackageDeleteObserver getBinder() {
-        return mBinder;
-    }
-
-    public void onUninstallFinished(String basePackageName, int returnCode) {
-    }
-}
diff --git a/core/java/android/content/pm/IPackageDeleteObserver2.aidl b/core/java/android/content/pm/IPackageDeleteObserver2.aidl
new file mode 100644
index 0000000..bff3baa
--- /dev/null
+++ b/core/java/android/content/pm/IPackageDeleteObserver2.aidl
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.content.pm;
+
+import android.content.Intent;
+
+/** {@hide} */
+oneway interface IPackageDeleteObserver2 {
+    void onUserActionRequired(in Intent intent);
+    void onPackageDeleted(String packageName, int returnCode, String msg);
+}
diff --git a/core/java/android/content/pm/IPackageInstallObserver2.aidl b/core/java/android/content/pm/IPackageInstallObserver2.aidl
index 824d730..bb5f22a 100644
--- a/core/java/android/content/pm/IPackageInstallObserver2.aidl
+++ b/core/java/android/content/pm/IPackageInstallObserver2.aidl
@@ -16,7 +16,7 @@
 
 package android.content.pm;
 
-import android.content.IntentSender;
+import android.content.Intent;
 import android.os.Bundle;
 
 /**
@@ -25,6 +25,8 @@
  * @hide
  */
 oneway interface IPackageInstallObserver2 {
+    void onUserActionRequired(in Intent intent);
+
     /**
      * The install operation has completed.  {@code returnCode} holds a numeric code
      * indicating success or failure.  In certain cases the {@code extras} Bundle will
@@ -40,5 +42,5 @@
      * </tr>
      * </table>
      */
-    void packageInstalled(String basePackageName, in Bundle extras, int returnCode, String msg);
+    void onPackageInstalled(String basePackageName, int returnCode, String msg, in Bundle extras);
 }
diff --git a/core/java/android/content/pm/IPackageInstaller.aidl b/core/java/android/content/pm/IPackageInstaller.aidl
index 0c65034..176a81c 100644
--- a/core/java/android/content/pm/IPackageInstaller.aidl
+++ b/core/java/android/content/pm/IPackageInstaller.aidl
@@ -16,7 +16,7 @@
 
 package android.content.pm;
 
-import android.content.pm.IPackageDeleteObserver;
+import android.content.pm.IPackageDeleteObserver2;
 import android.content.pm.IPackageInstallerCallback;
 import android.content.pm.IPackageInstallerSession;
 import android.content.pm.InstallSessionInfo;
@@ -35,6 +35,6 @@
     void registerCallback(IPackageInstallerCallback callback, int userId);
     void unregisterCallback(IPackageInstallerCallback callback);
 
-    void uninstall(String packageName, int flags, in IPackageDeleteObserver observer, int userId);
-    void uninstallSplit(String packageName, String splitName, int flags, in IPackageDeleteObserver observer, int userId);
+    void uninstall(String packageName, int flags, in IPackageDeleteObserver2 observer, int userId);
+    void uninstallSplit(String packageName, String splitName, int flags, in IPackageDeleteObserver2 observer, int userId);
 }
diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl
index 2d6d3c9..44478d4 100644
--- a/core/java/android/content/pm/IPackageManager.aidl
+++ b/core/java/android/content/pm/IPackageManager.aidl
@@ -24,10 +24,10 @@
 import android.content.pm.ApplicationInfo;
 import android.content.pm.ContainerEncryptionParams;
 import android.content.pm.FeatureInfo;
-import android.content.pm.IPackageInstallObserver;
 import android.content.pm.IPackageInstallObserver2;
 import android.content.pm.IPackageInstaller;
 import android.content.pm.IPackageDeleteObserver;
+import android.content.pm.IPackageDeleteObserver2;
 import android.content.pm.IPackageDataObserver;
 import android.content.pm.IPackageMoveObserver;
 import android.content.pm.IPackageStatsObserver;
@@ -202,6 +202,10 @@
 
     void setInstallerPackageName(in String targetPackage, in String installerPackageName);
 
+    /** @deprecated rawr, don't call AIDL methods directly! */
+    void deletePackageAsUser(in String packageName, IPackageDeleteObserver observer,
+            int userId, int flags);
+
     /**
      * Delete a package for a specific user.
      *
@@ -210,8 +214,7 @@
      * @param userId the id of the user for whom to delete the package
      * @param flags - possible values: {@link #DONT_DELETE_DATA}
      */
-    void deletePackageAsUser(in String packageName, IPackageDeleteObserver observer,
-            int userId, int flags);
+    void deletePackage(in String packageName, IPackageDeleteObserver2 observer, int userId, int flags);
 
     String getInstallerPackageName(in String packageName);
 
diff --git a/core/java/android/content/pm/PackageInstaller.java b/core/java/android/content/pm/PackageInstaller.java
index 299afff..01c080d 100644
--- a/core/java/android/content/pm/PackageInstaller.java
+++ b/core/java/android/content/pm/PackageInstaller.java
@@ -20,8 +20,9 @@
 import android.annotation.Nullable;
 import android.annotation.SdkConstant;
 import android.annotation.SdkConstant.SdkConstantType;
+import android.app.PackageDeleteObserver;
 import android.app.PackageInstallObserver;
-import android.app.PackageUninstallObserver;
+import android.content.Intent;
 import android.os.Bundle;
 import android.os.FileBridge;
 import android.os.Handler;
@@ -536,15 +537,25 @@
     }
 
     /**
-     * Final result of an uninstall request.
+     * Events for a specific uninstall request.
      */
     public static abstract class UninstallCallback {
+        /**
+         * User action is required to proceed. You can start the given intent
+         * activity to involve the user and continue.
+         * <p>
+         * You may choose to immediately launch the intent if the user is
+         * actively using your app. However, you should use a notification to
+         * guide the user back into your app if not currently active.
+         */
+        public abstract void onUserActionRequired(Intent intent);
+
         public abstract void onSuccess();
         public abstract void onFailure(String msg);
     }
 
     /** {@hide} */
-    private static class UninstallCallbackDelegate extends PackageUninstallObserver {
+    private static class UninstallCallbackDelegate extends PackageDeleteObserver {
         private final UninstallCallback target;
 
         public UninstallCallbackDelegate(UninstallCallback target) {
@@ -552,11 +563,16 @@
         }
 
         @Override
-        public void onUninstallFinished(String basePackageName, int returnCode) {
+        public void onUserActionRequired(Intent intent) {
+            target.onUserActionRequired(intent);
+        }
+
+        @Override
+        public void onPackageDeleted(String basePackageName, int returnCode, String msg) {
             if (returnCode == PackageManager.DELETE_SUCCEEDED) {
                 target.onSuccess();
             } else {
-                final String msg = PackageManager.deleteStatusToString(returnCode);
+                msg = PackageManager.deleteStatusToString(returnCode) + ": " + msg;
                 target.onFailure(msg);
             }
         }
@@ -612,6 +628,16 @@
 
         public static final String EXTRA_PACKAGE_NAME = "android.content.pm.extra.PACKAGE_NAME";
 
+        /**
+         * User action is required to proceed. You can start the given intent
+         * activity to involve the user and continue.
+         * <p>
+         * You may choose to immediately launch the intent if the user is
+         * actively using your app. However, you should use a notification to
+         * guide the user back into your app if not currently active.
+         */
+        public abstract void onUserActionRequired(Intent intent);
+
         public abstract void onSuccess();
         public abstract void onFailure(int failureReason, String msg, Bundle extras);
     }
@@ -625,8 +651,13 @@
         }
 
         @Override
-        public void packageInstalled(String basePackageName, Bundle extras, int returnCode,
-                String msg) {
+        public void onUserActionRequired(Intent intent) {
+            target.onUserActionRequired(intent);
+        }
+
+        @Override
+        public void onPackageInstalled(String basePackageName, int returnCode, String msg,
+                Bundle extras) {
             if (returnCode == PackageManager.INSTALL_SUCCEEDED) {
                 target.onSuccess();
             } else {