Merge "Update API for launcher apps to use abstract class."
diff --git a/api/current.txt b/api/current.txt
index 1906e7b..cd58b21 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -8265,15 +8265,26 @@
   }
 
   public class LauncherApps {
+    method public void addOnAppsChangedCallback(android.content.pm.LauncherApps.OnAppsChangedCallback);
     method public void addOnAppsChangedListener(android.content.pm.LauncherApps.OnAppsChangedListener);
     method public java.util.List<android.content.pm.LauncherActivityInfo> getActivityList(java.lang.String, android.os.UserHandle);
     method public boolean isActivityEnabledForProfile(android.content.ComponentName, android.os.UserHandle);
     method public boolean isPackageEnabledForProfile(java.lang.String, android.os.UserHandle);
+    method public void removeOnAppsChangedCallback(android.content.pm.LauncherApps.OnAppsChangedCallback);
     method public void removeOnAppsChangedListener(android.content.pm.LauncherApps.OnAppsChangedListener);
     method public android.content.pm.LauncherActivityInfo resolveActivity(android.content.Intent, android.os.UserHandle);
     method public void startActivityForProfile(android.content.ComponentName, android.os.UserHandle, android.graphics.Rect, android.os.Bundle);
   }
 
+  public static abstract class LauncherApps.OnAppsChangedCallback {
+    ctor public LauncherApps.OnAppsChangedCallback();
+    method public abstract void onPackageAdded(java.lang.String, android.os.UserHandle);
+    method public abstract void onPackageChanged(java.lang.String, android.os.UserHandle);
+    method public abstract void onPackageRemoved(java.lang.String, android.os.UserHandle);
+    method public abstract void onPackagesAvailable(java.lang.String[], android.os.UserHandle, boolean);
+    method public abstract void onPackagesUnavailable(java.lang.String[], android.os.UserHandle, boolean);
+  }
+
   public static abstract interface LauncherApps.OnAppsChangedListener {
     method public abstract void onPackageAdded(android.os.UserHandle, java.lang.String);
     method public abstract void onPackageChanged(android.os.UserHandle, java.lang.String);
diff --git a/core/java/android/content/pm/LauncherApps.java b/core/java/android/content/pm/LauncherApps.java
index 69fa408..6c10bb8 100644
--- a/core/java/android/content/pm/LauncherApps.java
+++ b/core/java/android/content/pm/LauncherApps.java
@@ -57,6 +57,65 @@
 
     private List<OnAppsChangedListener> mListeners
             = new ArrayList<OnAppsChangedListener>();
+    private List<OnAppsChangedCallback> mCallbacks
+            = new ArrayList<OnAppsChangedCallback>();
+
+    /**
+     * Callbacks for package changes to this and related managed profiles.
+     */
+    public static abstract class OnAppsChangedCallback {
+        /**
+         * Indicates that a package was removed from the specified profile.
+         *
+         * @param packageName The name of the package that was removed.
+         * @param user The UserHandle of the profile that generated the change.
+         */
+        abstract public void onPackageRemoved(String packageName, UserHandle user);
+
+        /**
+         * Indicates that a package was added to the specified profile.
+         *
+         * @param packageName The name of the package that was added.
+         * @param user The UserHandle of the profile that generated the change.
+         */
+        abstract public void onPackageAdded(String packageName, UserHandle user);
+
+        /**
+         * Indicates that a package was modified in the specified profile.
+         *
+         * @param packageName The name of the package that has changed.
+         * @param user The UserHandle of the profile that generated the change.
+         */
+        abstract public void onPackageChanged(String packageName, UserHandle user);
+
+        /**
+         * Indicates that one or more packages have become available. For
+         * example, this can happen when a removable storage card has
+         * reappeared.
+         *
+         * @param packageNames The names of the packages that have become
+         *            available.
+         * @param user The UserHandle of the profile that generated the change.
+         * @param replacing Indicates whether these packages are replacing
+         *            existing ones.
+         */
+        abstract public void onPackagesAvailable(String[] packageNames, UserHandle user,
+                boolean replacing);
+
+        /**
+         * Indicates that one or more packages have become unavailable. For
+         * example, this can happen when a removable storage card has been
+         * removed.
+         *
+         * @param packageNames The names of the packages that have become
+         *            unavailable.
+         * @param user The UserHandle of the profile that generated the change.
+         * @param replacing Indicates whether the packages are about to be
+         *            replaced with new versions.
+         */
+        abstract public void onPackagesUnavailable(String[] packageNames, UserHandle user,
+                boolean replacing);
+    }
 
     /**
      * Callbacks for package changes to this and related managed profiles.
@@ -270,7 +329,7 @@
         synchronized (this) {
             if (listener != null && !mListeners.contains(listener)) {
                 mListeners.add(listener);
-                if (mListeners.size() == 1) {
+                if (mListeners.size() == 1 && mCallbacks.size() == 0) {
                     try {
                         mService.addOnAppsChangedListener(mAppsChangedListener);
                     } catch (RemoteException re) {
@@ -289,7 +348,44 @@
     public void removeOnAppsChangedListener(OnAppsChangedListener listener) {
         synchronized (this) {
             mListeners.remove(listener);
-            if (mListeners.size() == 0) {
+            if (mListeners.size() == 0 && mCallbacks.size() == 0) {
+                try {
+                    mService.removeOnAppsChangedListener(mAppsChangedListener);
+                } catch (RemoteException re) {
+                }
+            }
+        }
+    }
+
+    /**
+     * Adds a callback for changes to packages in current and managed profiles.
+     *
+     * @param callback The callback to add.
+     */
+    public void addOnAppsChangedCallback(OnAppsChangedCallback callback) {
+        synchronized (this) {
+            if (callback != null && !mCallbacks.contains(callback)) {
+                mCallbacks.add(callback);
+                if (mCallbacks.size() == 1 && mListeners.size() == 0) {
+                    try {
+                        mService.addOnAppsChangedListener(mAppsChangedListener);
+                    } catch (RemoteException re) {
+                    }
+                }
+            }
+        }
+    }
+
+    /**
+     * Removes a callback that was previously added.
+     *
+     * @param callback The callback to remove.
+     * @see #addOnAppsChangedListener(OnAppsChangedCallback)
+     */
+    public void removeOnAppsChangedCallback(OnAppsChangedCallback callback) {
+        synchronized (this) {
+            mListeners.remove(callback);
+            if (mListeners.size() == 0 && mCallbacks.size() == 0) {
                 try {
                     mService.removeOnAppsChangedListener(mAppsChangedListener);
                 } catch (RemoteException re) {
@@ -309,6 +405,9 @@
                 for (OnAppsChangedListener listener : mListeners) {
                     listener.onPackageRemoved(user, packageName);
                 }
+                for (OnAppsChangedCallback callback : mCallbacks) {
+                    callback.onPackageRemoved(packageName, user);
+                }
             }
         }
 
@@ -321,6 +420,9 @@
                 for (OnAppsChangedListener listener : mListeners) {
                     listener.onPackageChanged(user, packageName);
                 }
+                for (OnAppsChangedCallback callback : mCallbacks) {
+                    callback.onPackageChanged(packageName, user);
+                }
             }
         }
 
@@ -333,6 +435,9 @@
                 for (OnAppsChangedListener listener : mListeners) {
                     listener.onPackageAdded(user, packageName);
                 }
+                for (OnAppsChangedCallback callback : mCallbacks) {
+                    callback.onPackageAdded(packageName, user);
+                }
             }
         }
 
@@ -346,6 +451,9 @@
                 for (OnAppsChangedListener listener : mListeners) {
                     listener.onPackagesAvailable(user, packageNames, replacing);
                 }
+                for (OnAppsChangedCallback callback : mCallbacks) {
+                    callback.onPackagesAvailable(packageNames, user, replacing);
+                }
             }
         }
 
@@ -359,7 +467,10 @@
                 for (OnAppsChangedListener listener : mListeners) {
                     listener.onPackagesUnavailable(user, packageNames, replacing);
                 }
-            }
+                for (OnAppsChangedCallback callback : mCallbacks) {
+                    callback.onPackagesUnavailable(packageNames, user, replacing);
+                }
+           }
         }
     };
 }