Fixes to idle alarm scheduling, package importance.

- Add new API to ask the activity manager what the current
  importance of a particular package name is (along with a few
  new useful importance levels).

- Fix my last alarm manager change to actually execute the
  alarms we have now decided should run even while we are idle.

Change-Id: I1f14712b4e390770d53b185c96a1b36f6aadd687
diff --git a/api/current.txt b/api/current.txt
index 87cd2d6..028c0ca 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -3555,6 +3555,7 @@
     method public int getMemoryClass();
     method public void getMemoryInfo(android.app.ActivityManager.MemoryInfo);
     method public static void getMyMemoryState(android.app.ActivityManager.RunningAppProcessInfo);
+    method public int getPackageImportance(java.lang.String);
     method public android.os.Debug.MemoryInfo[] getProcessMemoryInfo(int[]);
     method public java.util.List<android.app.ActivityManager.ProcessErrorStateInfo> getProcessesInErrorState();
     method public deprecated java.util.List<android.app.ActivityManager.RecentTaskInfo> getRecentTasks(int, int) throws java.lang.SecurityException;
@@ -3647,9 +3648,11 @@
     field public static final int IMPORTANCE_BACKGROUND = 400; // 0x190
     field public static final int IMPORTANCE_EMPTY = 500; // 0x1f4
     field public static final int IMPORTANCE_FOREGROUND = 100; // 0x64
+    field public static final int IMPORTANCE_FOREGROUND_SERVICE = 125; // 0x7d
     field public static final int IMPORTANCE_GONE = 1000; // 0x3e8
     field public static final int IMPORTANCE_PERCEPTIBLE = 130; // 0x82
     field public static final int IMPORTANCE_SERVICE = 300; // 0x12c
+    field public static final int IMPORTANCE_TOP_SLEEPING = 150; // 0x96
     field public static final int IMPORTANCE_VISIBLE = 200; // 0xc8
     field public static final int REASON_PROVIDER_IN_USE = 1; // 0x1
     field public static final int REASON_SERVICE_IN_USE = 2; // 0x2
@@ -28640,7 +28643,7 @@
     field public static final int START_WITH_SCREENSHOT = 2; // 0x2
   }
 
-  public abstract class VoiceInteractionSession implements android.view.KeyEvent.Callback {
+  public abstract class VoiceInteractionSession implements android.content.ComponentCallbacks2 android.view.KeyEvent.Callback {
     ctor public VoiceInteractionSession(android.content.Context);
     ctor public VoiceInteractionSession(android.content.Context, android.os.Handler);
     method public void finish();
@@ -28656,6 +28659,7 @@
     method public abstract void onCommand(android.service.voice.VoiceInteractionSession.Caller, android.service.voice.VoiceInteractionSession.Request, java.lang.String, android.os.Bundle);
     method public void onCompleteVoice(android.service.voice.VoiceInteractionSession.Caller, android.service.voice.VoiceInteractionSession.Request, java.lang.CharSequence, android.os.Bundle);
     method public void onComputeInsets(android.service.voice.VoiceInteractionSession.Insets);
+    method public void onConfigurationChanged(android.content.res.Configuration);
     method public abstract void onConfirm(android.service.voice.VoiceInteractionSession.Caller, android.service.voice.VoiceInteractionSession.Request, java.lang.CharSequence, android.os.Bundle);
     method public void onCreate(android.os.Bundle, int);
     method public android.view.View onCreateContentView();
@@ -28668,10 +28672,12 @@
     method public boolean onKeyLongPress(int, android.view.KeyEvent);
     method public boolean onKeyMultiple(int, int, android.view.KeyEvent);
     method public boolean onKeyUp(int, android.view.KeyEvent);
+    method public void onLowMemory();
     method public abstract void onPickOption(android.service.voice.VoiceInteractionSession.Caller, android.service.voice.VoiceInteractionSession.Request, java.lang.CharSequence, android.app.VoiceInteractor.PickOptionRequest.Option[], android.os.Bundle);
     method public void onShow(android.os.Bundle, int);
     method public void onTaskFinished(android.content.Intent, int);
     method public void onTaskStarted(android.content.Intent, int);
+    method public void onTrimMemory(int);
     method public void setContentView(android.view.View);
     method public void setKeepAwake(boolean);
     method public void setTheme(int);
diff --git a/api/system-current.txt b/api/system-current.txt
index 9e635bf..c1bc9d3 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -3644,6 +3644,7 @@
     method public int getMemoryClass();
     method public void getMemoryInfo(android.app.ActivityManager.MemoryInfo);
     method public static void getMyMemoryState(android.app.ActivityManager.RunningAppProcessInfo);
+    method public int getPackageImportance(java.lang.String);
     method public android.os.Debug.MemoryInfo[] getProcessMemoryInfo(int[]);
     method public java.util.List<android.app.ActivityManager.ProcessErrorStateInfo> getProcessesInErrorState();
     method public deprecated java.util.List<android.app.ActivityManager.RecentTaskInfo> getRecentTasks(int, int) throws java.lang.SecurityException;
@@ -3736,9 +3737,11 @@
     field public static final int IMPORTANCE_BACKGROUND = 400; // 0x190
     field public static final int IMPORTANCE_EMPTY = 500; // 0x1f4
     field public static final int IMPORTANCE_FOREGROUND = 100; // 0x64
+    field public static final int IMPORTANCE_FOREGROUND_SERVICE = 125; // 0x7d
     field public static final int IMPORTANCE_GONE = 1000; // 0x3e8
     field public static final int IMPORTANCE_PERCEPTIBLE = 130; // 0x82
     field public static final int IMPORTANCE_SERVICE = 300; // 0x12c
+    field public static final int IMPORTANCE_TOP_SLEEPING = 150; // 0x96
     field public static final int IMPORTANCE_VISIBLE = 200; // 0xc8
     field public static final int REASON_PROVIDER_IN_USE = 1; // 0x1
     field public static final int REASON_SERVICE_IN_USE = 2; // 0x2
@@ -30736,7 +30739,7 @@
     field public static final int START_WITH_SCREENSHOT = 2; // 0x2
   }
 
-  public abstract class VoiceInteractionSession implements android.view.KeyEvent.Callback {
+  public abstract class VoiceInteractionSession implements android.content.ComponentCallbacks2 android.view.KeyEvent.Callback {
     ctor public VoiceInteractionSession(android.content.Context);
     ctor public VoiceInteractionSession(android.content.Context, android.os.Handler);
     method public void finish();
@@ -30752,6 +30755,7 @@
     method public abstract void onCommand(android.service.voice.VoiceInteractionSession.Caller, android.service.voice.VoiceInteractionSession.Request, java.lang.String, android.os.Bundle);
     method public void onCompleteVoice(android.service.voice.VoiceInteractionSession.Caller, android.service.voice.VoiceInteractionSession.Request, java.lang.CharSequence, android.os.Bundle);
     method public void onComputeInsets(android.service.voice.VoiceInteractionSession.Insets);
+    method public void onConfigurationChanged(android.content.res.Configuration);
     method public abstract void onConfirm(android.service.voice.VoiceInteractionSession.Caller, android.service.voice.VoiceInteractionSession.Request, java.lang.CharSequence, android.os.Bundle);
     method public void onCreate(android.os.Bundle, int);
     method public android.view.View onCreateContentView();
@@ -30764,10 +30768,12 @@
     method public boolean onKeyLongPress(int, android.view.KeyEvent);
     method public boolean onKeyMultiple(int, int, android.view.KeyEvent);
     method public boolean onKeyUp(int, android.view.KeyEvent);
+    method public void onLowMemory();
     method public abstract void onPickOption(android.service.voice.VoiceInteractionSession.Caller, android.service.voice.VoiceInteractionSession.Request, java.lang.CharSequence, android.app.VoiceInteractor.PickOptionRequest.Option[], android.os.Bundle);
     method public void onShow(android.os.Bundle, int);
     method public void onTaskFinished(android.content.Intent, int);
     method public void onTaskStarted(android.content.Intent, int);
+    method public void onTrimMemory(int);
     method public void setContentView(android.view.View);
     method public void setKeepAwake(boolean);
     method public void setTheme(int);
diff --git a/cmds/am/src/com/android/commands/am/Am.java b/cmds/am/src/com/android/commands/am/Am.java
index 908d46e..fa28143 100644
--- a/cmds/am/src/com/android/commands/am/Am.java
+++ b/cmds/am/src/com/android/commands/am/Am.java
@@ -124,6 +124,7 @@
                 "       am restart\n" +
                 "       am idle-maintenance\n" +
                 "       am screen-compat [on|off] <PACKAGE>\n" +
+                "       am package-importance <PACKAGE>\n" +
                 "       am to-uri [INTENT]\n" +
                 "       am to-intent-uri [INTENT]\n" +
                 "       am to-app-uri [INTENT]\n" +
@@ -233,6 +234,8 @@
                 "\n" +
                 "am screen-compat: control screen compatibility mode of <PACKAGE>.\n" +
                 "\n" +
+                "am package-importance: print current importance of <PACKAGE>.\n" +
+                "\n" +
                 "am to-uri: print the given Intent specification as a URI.\n" +
                 "\n" +
                 "am to-intent-uri: print the given Intent specification as an intent: URI.\n" +
@@ -365,6 +368,8 @@
             runIdleMaintenance();
         } else if (op.equals("screen-compat")) {
             runScreenCompat();
+        } else if (op.equals("package-importance")) {
+            runPackageImportance();
         } else if (op.equals("to-uri")) {
             runToUri(0);
         } else if (op.equals("to-intent-uri")) {
@@ -1604,6 +1609,16 @@
         } while (packageName != null);
     }
 
+    private void runPackageImportance() throws Exception {
+        String packageName = nextArgRequired();
+        try {
+            int procState = mAm.getPackageProcessState(packageName);
+            System.out.println(
+                    ActivityManager.RunningAppProcessInfo.procStateToImportance(procState));
+        } catch (RemoteException e) {
+        }
+    }
+
     private void runToUri(int flags) throws Exception {
         Intent intent = makeIntent(UserHandle.USER_CURRENT);
         System.out.println(intent.toUri(flags));
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index 2b35cd4..51ececc 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -2010,27 +2010,47 @@
         public int lastTrimLevel;
 
         /**
-         * Constant for {@link #importance}: this process is running the
-         * foreground UI.
+         * Constant for {@link #importance}: This process is running the
+         * foreground UI; that is, it is the thing currently at the top of the screen
+         * that the user is interacting with.
          */
         public static final int IMPORTANCE_FOREGROUND = 100;
         
         /**
-         * Constant for {@link #importance}: this process is running something
+         * Constant for {@link #importance}: This process is running a foreground
+         * service, for example to perform music playback even while the user is
+         * not immediately in the app.  This generally indicates that the process
+         * is doing something the user actively cares about.
+         */
+        public static final int IMPORTANCE_FOREGROUND_SERVICE = 125;
+
+        /**
+         * Constant for {@link #importance}: This process is running the foreground
+         * UI, but the device is asleep so it is not visible to the user.  This means
+         * the user is not really aware of the process, because they can not see or
+         * interact with it, but it is quite important because it what they expect to
+         * return to once unlocking the device.
+         */
+        public static final int IMPORTANCE_TOP_SLEEPING = 150;
+
+        /**
+         * Constant for {@link #importance}: This process is running something
          * that is actively visible to the user, though not in the immediate
-         * foreground.
+         * foreground.  This may be running a window that is behind the current
+         * foreground (so paused and with its state saved, not interacting with
+         * the user, but visible to them to some degree); it may also be running
+         * other services under the system's control that it inconsiders important.
          */
         public static final int IMPORTANCE_VISIBLE = 200;
         
         /**
-         * Constant for {@link #importance}: this process is running something
-         * that is considered to be actively perceptible to the user.  An
-         * example would be an application performing background music playback.
+         * Constant for {@link #importance}: This process is not something the user
+         * is directly aware of, but is otherwise perceptable to them to some degree.
          */
         public static final int IMPORTANCE_PERCEPTIBLE = 130;
         
         /**
-         * Constant for {@link #importance}: this process is running an
+         * Constant for {@link #importance}: This process is running an
          * application that can not save its state, and thus can't be killed
          * while in the background.
          * @hide
@@ -2038,42 +2058,51 @@
         public static final int IMPORTANCE_CANT_SAVE_STATE = 170;
         
         /**
-         * Constant for {@link #importance}: this process is contains services
-         * that should remain running.
+         * Constant for {@link #importance}: This process is contains services
+         * that should remain running.  These are background services apps have
+         * started, not something the user is aware of, so they may be killed by
+         * the system relatively freely (though it is generally desired that they
+         * stay running as long as they want to).
          */
         public static final int IMPORTANCE_SERVICE = 300;
         
         /**
-         * Constant for {@link #importance}: this process process contains
+         * Constant for {@link #importance}: This process process contains
          * background code that is expendable.
          */
         public static final int IMPORTANCE_BACKGROUND = 400;
         
         /**
-         * Constant for {@link #importance}: this process is empty of any
+         * Constant for {@link #importance}: This process is empty of any
          * actively running code.
          */
         public static final int IMPORTANCE_EMPTY = 500;
 
         /**
-         * Constant for {@link #importance}: this process does not exist.
+         * Constant for {@link #importance}: This process does not exist.
          */
         public static final int IMPORTANCE_GONE = 1000;
 
         /** @hide */
         public static int procStateToImportance(int procState) {
-            if (procState >= ActivityManager.PROCESS_STATE_HOME) {
-                return ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
-            } else if (procState >= ActivityManager.PROCESS_STATE_SERVICE) {
-                return ActivityManager.RunningAppProcessInfo.IMPORTANCE_SERVICE;
-            } else if (procState > ActivityManager.PROCESS_STATE_HEAVY_WEIGHT) {
-                return ActivityManager.RunningAppProcessInfo.IMPORTANCE_CANT_SAVE_STATE;
-            } else if (procState >= ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND) {
-                return ActivityManager.RunningAppProcessInfo.IMPORTANCE_PERCEPTIBLE;
-            } else if (procState >= ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE) {
-                return ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE;
+            if (procState == PROCESS_STATE_NONEXISTENT) {
+                return IMPORTANCE_GONE;
+            } else if (procState >= PROCESS_STATE_HOME) {
+                return IMPORTANCE_BACKGROUND;
+            } else if (procState >= PROCESS_STATE_SERVICE) {
+                return IMPORTANCE_SERVICE;
+            } else if (procState > PROCESS_STATE_HEAVY_WEIGHT) {
+                return IMPORTANCE_CANT_SAVE_STATE;
+            } else if (procState >= PROCESS_STATE_IMPORTANT_BACKGROUND) {
+                return IMPORTANCE_PERCEPTIBLE;
+            } else if (procState >= PROCESS_STATE_IMPORTANT_FOREGROUND) {
+                return IMPORTANCE_VISIBLE;
+            } else if (procState >= PROCESS_STATE_TOP_SLEEPING) {
+                return IMPORTANCE_TOP_SLEEPING;
+            } else if (procState >= PROCESS_STATE_FOREGROUND_SERVICE) {
+                return IMPORTANCE_FOREGROUND_SERVICE;
             } else {
-                return ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND;
+                return IMPORTANCE_FOREGROUND;
             }
         }
 
@@ -2253,6 +2282,22 @@
     }
 
     /**
+     * Return the importance of a given package name, based on the processes that are
+     * currently running.  The return value is one of the importance constants defined
+     * in {@link RunningAppProcessInfo}, giving you the highest importance of all the
+     * processes that this package has code running inside of.  If there are no processes
+     * running its code, {@link RunningAppProcessInfo#IMPORTANCE_GONE} is returned.
+     */
+    public int getPackageImportance(String packageName) {
+        try {
+            int procState = ActivityManagerNative.getDefault().getPackageProcessState(packageName);
+            return RunningAppProcessInfo.procStateToImportance(procState);
+        } catch (RemoteException e) {
+            return RunningAppProcessInfo.IMPORTANCE_GONE;
+        }
+    }
+
+    /**
      * Return global memory state information for the calling process.  This
      * does not fill in all fields of the {@link RunningAppProcessInfo}.  The
      * only fields that will be filled in are
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index f63d13c..256d87d 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -106,9 +106,24 @@
         }
     }
 
-    static public void noteWakeupAlarm(PendingIntent ps, int sourceUid, String sourcePkg) {
+    static public void noteWakeupAlarm(PendingIntent ps, int sourceUid, String sourcePkg,
+            String tag) {
         try {
-            getDefault().noteWakeupAlarm(ps.getTarget(), sourceUid, sourcePkg);
+            getDefault().noteWakeupAlarm(ps.getTarget(), sourceUid, sourcePkg, tag);
+        } catch (RemoteException ex) {
+        }
+    }
+
+    static public void noteAlarmStart(PendingIntent ps, int sourceUid, String tag) {
+        try {
+            getDefault().noteAlarmStart(ps.getTarget(), sourceUid, tag);
+        } catch (RemoteException ex) {
+        }
+    }
+
+    static public void noteAlarmFinish(PendingIntent ps, int sourceUid, String tag) {
+        try {
+            getDefault().noteAlarmFinish(ps.getTarget(), sourceUid, tag);
         } catch (RemoteException ex) {
         }
     }
@@ -1375,7 +1390,30 @@
                     data.readStrongBinder());
             int sourceUid = data.readInt();
             String sourcePkg = data.readString();
-            noteWakeupAlarm(is, sourceUid, sourcePkg);
+            String tag = data.readString();
+            noteWakeupAlarm(is, sourceUid, sourcePkg, tag);
+            reply.writeNoException();
+            return true;
+        }
+
+        case NOTE_ALARM_START_TRANSACTION: {
+            data.enforceInterface(IActivityManager.descriptor);
+            IIntentSender is = IIntentSender.Stub.asInterface(
+                    data.readStrongBinder());
+            int sourceUid = data.readInt();
+            String tag = data.readString();
+            noteAlarmStart(is, sourceUid, tag);
+            reply.writeNoException();
+            return true;
+        }
+
+        case NOTE_ALARM_FINISH_TRANSACTION: {
+            data.enforceInterface(IActivityManager.descriptor);
+            IIntentSender is = IIntentSender.Stub.asInterface(
+                    data.readStrongBinder());
+            int sourceUid = data.readInt();
+            String tag = data.readString();
+            noteAlarmFinish(is, sourceUid, tag);
             reply.writeNoException();
             return true;
         }
@@ -2461,6 +2499,15 @@
             reply.writeNoException();
             return true;
         }
+
+        case GET_PACKAGE_PROCESS_STATE_TRANSACTION: {
+            data.enforceInterface(IActivityManager.descriptor);
+            String pkg = data.readString();
+            int res = getPackageProcessState(pkg);
+            reply.writeNoException();
+            reply.writeInt(res);
+            return true;
+        }
         }
 
         return super.onTransact(code, data, reply, flags);
@@ -3304,7 +3351,7 @@
         data.writeInterfaceToken(IActivityManager.descriptor);
         data.writeInt(stackBoxId);
         r.writeToParcel(data, 0);
-        mRemote.transact(RESIZE_STACK_TRANSACTION, data, reply, IBinder.FLAG_ONEWAY);
+        mRemote.transact(RESIZE_STACK_TRANSACTION, data, reply, 0);
         reply.readException();
         data.recycle();
         reply.recycle();
@@ -3360,7 +3407,7 @@
         Parcel reply = Parcel.obtain();
         data.writeInterfaceToken(IActivityManager.descriptor);
         data.writeInt(stackId);
-        mRemote.transact(SET_FOCUSED_STACK_TRANSACTION, data, reply, IBinder.FLAG_ONEWAY);
+        mRemote.transact(SET_FOCUSED_STACK_TRANSACTION, data, reply, 0);
         reply.readException();
         data.recycle();
         reply.recycle();
@@ -3384,7 +3431,7 @@
         Parcel reply = Parcel.obtain();
         data.writeInterfaceToken(IActivityManager.descriptor);
         data.writeStrongBinder(listener.asBinder());
-        mRemote.transact(REGISTER_TASK_STACK_LISTENER_TRANSACTION, data, reply, IBinder.FLAG_ONEWAY);
+        mRemote.transact(REGISTER_TASK_STACK_LISTENER_TRANSACTION, data, reply, 0);
         reply.readException();
         data.recycle();
         reply.recycle();
@@ -4214,16 +4261,37 @@
         mRemote.transact(ENTER_SAFE_MODE_TRANSACTION, data, null, 0);
         data.recycle();
     }
-    public void noteWakeupAlarm(IIntentSender sender, int sourceUid, String sourcePkg)
+    public void noteWakeupAlarm(IIntentSender sender, int sourceUid, String sourcePkg, String tag)
             throws RemoteException {
         Parcel data = Parcel.obtain();
         data.writeInterfaceToken(IActivityManager.descriptor);
         data.writeStrongBinder(sender.asBinder());
         data.writeInt(sourceUid);
         data.writeString(sourcePkg);
+        data.writeString(tag);
         mRemote.transact(NOTE_WAKEUP_ALARM_TRANSACTION, data, null, 0);
         data.recycle();
     }
+    public void noteAlarmStart(IIntentSender sender, int sourceUid, String tag)
+            throws RemoteException {
+        Parcel data = Parcel.obtain();
+        data.writeInterfaceToken(IActivityManager.descriptor);
+        data.writeStrongBinder(sender.asBinder());
+        data.writeInt(sourceUid);
+        data.writeString(tag);
+        mRemote.transact(NOTE_ALARM_START_TRANSACTION, data, null, 0);
+        data.recycle();
+    }
+    public void noteAlarmFinish(IIntentSender sender, int sourceUid, String tag)
+            throws RemoteException {
+        Parcel data = Parcel.obtain();
+        data.writeInterfaceToken(IActivityManager.descriptor);
+        data.writeStrongBinder(sender.asBinder());
+        data.writeInt(sourceUid);
+        data.writeString(tag);
+        mRemote.transact(NOTE_ALARM_FINISH_TRANSACTION, data, null, 0);
+        data.recycle();
+    }
     public boolean killPids(int[] pids, String reason, boolean secure) throws RemoteException {
         Parcel data = Parcel.obtain();
         Parcel reply = Parcel.obtain();
@@ -5486,7 +5554,7 @@
         data.writeInterfaceToken(IActivityManager.descriptor);
         data.writeStrongBinder(token);
         values.writeToParcel(data, 0);
-        mRemote.transact(SET_TASK_DESCRIPTION_TRANSACTION, data, reply, IBinder.FLAG_ONEWAY);
+        mRemote.transact(SET_TASK_DESCRIPTION_TRANSACTION, data, reply, 0);
         reply.readException();
         data.recycle();
         reply.recycle();
@@ -5499,7 +5567,7 @@
         data.writeInterfaceToken(IActivityManager.descriptor);
         data.writeInt(taskId);
         data.writeInt(resizeable ? 1 : 0);
-        mRemote.transact(SET_TASK_RESIZEABLE_TRANSACTION, data, reply, IBinder.FLAG_ONEWAY);
+        mRemote.transact(SET_TASK_RESIZEABLE_TRANSACTION, data, reply, 0);
         reply.readException();
         data.recycle();
         reply.recycle();
@@ -5513,7 +5581,7 @@
         data.writeInterfaceToken(IActivityManager.descriptor);
         data.writeInt(taskId);
         r.writeToParcel(data, 0);
-        mRemote.transact(RESIZE_TASK_TRANSACTION, data, reply, IBinder.FLAG_ONEWAY);
+        mRemote.transact(RESIZE_TASK_TRANSACTION, data, reply, 0);
         reply.readException();
         data.recycle();
         reply.recycle();
@@ -5545,7 +5613,7 @@
             data.writeInt(1);
             data.writeBundle(options.toBundle());
         }
-        mRemote.transact(START_IN_PLACE_ANIMATION_TRANSACTION, data, reply, IBinder.FLAG_ONEWAY);
+        mRemote.transact(START_IN_PLACE_ANIMATION_TRANSACTION, data, reply, 0);
         reply.readException();
         data.recycle();
         reply.recycle();
@@ -5586,8 +5654,7 @@
         Parcel reply = Parcel.obtain();
         data.writeInterfaceToken(IActivityManager.descriptor);
         data.writeStrongBinder(token);
-        mRemote.transact(BACKGROUND_RESOURCES_RELEASED_TRANSACTION, data, reply,
-                IBinder.FLAG_ONEWAY);
+        mRemote.transact(BACKGROUND_RESOURCES_RELEASED_TRANSACTION, data, reply, 0);
         reply.readException();
         data.recycle();
         reply.recycle();
@@ -5599,8 +5666,7 @@
         Parcel reply = Parcel.obtain();
         data.writeInterfaceToken(IActivityManager.descriptor);
         data.writeStrongBinder(token);
-        mRemote.transact(NOTIFY_LAUNCH_TASK_BEHIND_COMPLETE_TRANSACTION, data, reply,
-                IBinder.FLAG_ONEWAY);
+        mRemote.transact(NOTIFY_LAUNCH_TASK_BEHIND_COMPLETE_TRANSACTION, data, reply, 0);
         reply.readException();
         data.recycle();
         reply.recycle();
@@ -5612,8 +5678,7 @@
         Parcel reply = Parcel.obtain();
         data.writeInterfaceToken(IActivityManager.descriptor);
         data.writeStrongBinder(token);
-        mRemote.transact(NOTIFY_ENTER_ANIMATION_COMPLETE_TRANSACTION, data, reply,
-                IBinder.FLAG_ONEWAY);
+        mRemote.transact(NOTIFY_ENTER_ANIMATION_COMPLETE_TRANSACTION, data, reply, 0);
         reply.readException();
         data.recycle();
         reply.recycle();
@@ -5703,11 +5768,25 @@
         data.writeInterfaceToken(IActivityManager.descriptor);
         data.writeInt(userId);
         data.writeStringArray(packages);
-        mRemote.transact(UPDATE_LOCK_TASK_PACKAGES_TRANSACTION, data, reply, IBinder.FLAG_ONEWAY);
+        mRemote.transact(UPDATE_LOCK_TASK_PACKAGES_TRANSACTION, data, reply, 0);
         reply.readException();
         data.recycle();
         reply.recycle();
     }
 
+    @Override
+    public int getPackageProcessState(String packageName) throws RemoteException {
+        Parcel data = Parcel.obtain();
+        Parcel reply = Parcel.obtain();
+        data.writeInterfaceToken(IActivityManager.descriptor);
+        data.writeString(packageName);
+        mRemote.transact(GET_PACKAGE_PROCESS_STATE_TRANSACTION, data, reply, 0);
+        reply.readException();
+        int res = reply.readInt();
+        data.recycle();
+        reply.recycle();
+        return res;
+    }
+
     private IBinder mRemote;
 }
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
index 4a1d6ff..59de281 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -262,7 +262,11 @@
 
     public void enterSafeMode() throws RemoteException;
     
-    public void noteWakeupAlarm(IIntentSender sender, int sourceUid, String sourcePkg)
+    public void noteWakeupAlarm(IIntentSender sender, int sourceUid, String sourcePkg, String tag)
+            throws RemoteException;
+    public void noteAlarmStart(IIntentSender sender, int sourceUid, String tag)
+            throws RemoteException;
+    public void noteAlarmFinish(IIntentSender sender, int sourceUid, String tag)
             throws RemoteException;
 
     public boolean killPids(int[] pids, String reason, boolean secure) throws RemoteException;
@@ -490,6 +494,8 @@
             throws RemoteException;
     public void updateLockTaskPackages(int userId, String[] packages) throws RemoteException;
 
+    public int getPackageProcessState(String packageName) throws RemoteException;
+
     /*
      * Private non-Binder interfaces
      */
@@ -825,4 +831,7 @@
     int DUMP_HEAP_FINISHED_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+288;
     int SET_VOICE_KEEP_AWAKE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+289;
     int UPDATE_LOCK_TASK_PACKAGES_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+290;
+    int NOTE_ALARM_START_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+291;
+    int NOTE_ALARM_FINISH_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+292;
+    int GET_PACKAGE_PROCESS_STATE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+293;
 }
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index c7edb1a..7c5ddee 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -1135,8 +1135,10 @@
         public static final int EVENT_PACKAGE_INSTALLED = 0x000c;
         // Event for a package being uninstalled.
         public static final int EVENT_PACKAGE_UNINSTALLED = 0x000d;
+        // Event for a package being uninstalled.
+        public static final int EVENT_ALARM = 0x000e;
         // Number of event types.
-        public static final int EVENT_COUNT = 0x000e;
+        public static final int EVENT_COUNT = 0x000f;
         // Mask to extract out only the type part of the event.
         public static final int EVENT_TYPE_MASK = ~(EVENT_FLAG_START|EVENT_FLAG_FINISH);
 
@@ -1158,6 +1160,8 @@
                 EVENT_USER_FOREGROUND | EVENT_FLAG_START;
         public static final int EVENT_USER_FOREGROUND_FINISH =
                 EVENT_USER_FOREGROUND | EVENT_FLAG_FINISH;
+        public static final int EVENT_ALARM_START = EVENT_ALARM | EVENT_FLAG_START;
+        public static final int EVENT_ALARM_FINISH = EVENT_ALARM | EVENT_FLAG_FINISH;
 
         // For CMD_EVENT.
         public int eventCode;
@@ -1789,12 +1793,12 @@
 
     public static final String[] HISTORY_EVENT_NAMES = new String[] {
             "null", "proc", "fg", "top", "sync", "wake_lock_in", "job", "user", "userfg", "conn",
-            "motion", "active", "pkginst", "pkgunin"
+            "motion", "active", "pkginst", "pkgunin", "alarm"
     };
 
     public static final String[] HISTORY_EVENT_CHECKIN_NAMES = new String[] {
             "Enl", "Epr", "Efg", "Etp", "Esy", "Ewl", "Ejb", "Eur", "Euf", "Ecn",
-            "Esm", "Eac", "Epi", "Epu"
+            "Esm", "Eac", "Epi", "Epu", "Eal"
     };
 
     /**
diff --git a/core/java/android/service/voice/VoiceInteractionSession.java b/core/java/android/service/voice/VoiceInteractionSession.java
index 20d7079..71b7f76 100644
--- a/core/java/android/service/voice/VoiceInteractionSession.java
+++ b/core/java/android/service/voice/VoiceInteractionSession.java
@@ -20,8 +20,10 @@
 import android.app.Dialog;
 import android.app.Instrumentation;
 import android.app.VoiceInteractor;
+import android.content.ComponentCallbacks2;
 import android.content.Context;
 import android.content.Intent;
+import android.content.res.Configuration;
 import android.content.res.TypedArray;
 import android.graphics.Bitmap;
 import android.graphics.Rect;
@@ -65,7 +67,8 @@
  * when done.  It can also initiate voice interactions with applications by calling
  * {@link #startVoiceActivity}</p>.
  */
-public abstract class VoiceInteractionSession implements KeyEvent.Callback {
+public abstract class VoiceInteractionSession implements KeyEvent.Callback,
+        ComponentCallbacks2 {
     static final String TAG = "VoiceInteractionSession";
     static final boolean DEBUG = true;
 
@@ -855,6 +858,18 @@
         hide();
     }
 
+    @Override
+    public void onConfigurationChanged(Configuration newConfig) {
+    }
+
+    @Override
+    public void onLowMemory() {
+    }
+
+    @Override
+    public void onTrimMemory(int level) {
+    }
+
     /**
      * Compute the interesting insets into your UI.  The default implementation
      * sets {@link Insets#contentInsets outInsets.contentInsets.top} to the height
diff --git a/core/java/android/service/voice/VoiceInteractionSessionService.java b/core/java/android/service/voice/VoiceInteractionSessionService.java
index 008d55f..8f988f3 100644
--- a/core/java/android/service/voice/VoiceInteractionSessionService.java
+++ b/core/java/android/service/voice/VoiceInteractionSessionService.java
@@ -19,6 +19,7 @@
 import android.app.Service;
 import android.content.Context;
 import android.content.Intent;
+import android.content.res.Configuration;
 import android.os.Bundle;
 import android.os.IBinder;
 import android.os.Looper;
@@ -76,6 +77,30 @@
         return mInterface.asBinder();
     }
 
+    @Override
+    public void onConfigurationChanged(Configuration newConfig) {
+        super.onConfigurationChanged(newConfig);
+        if (mSession != null) {
+            mSession.onConfigurationChanged(newConfig);
+        }
+    }
+
+    @Override
+    public void onLowMemory() {
+        super.onLowMemory();
+        if (mSession != null) {
+            mSession.onLowMemory();
+        }
+    }
+
+    @Override
+    public void onTrimMemory(int level) {
+        super.onTrimMemory(level);
+        if (mSession != null) {
+            mSession.onTrimMemory(level);
+        }
+    }
+
     void doNewSession(IBinder token, Bundle args, int startFlags) {
         if (mSession != null) {
             mSession.doDestroy();
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index fbb2dfc..87605f6 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -2692,6 +2692,32 @@
         addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_JOB_FINISH, name, uid);
     }
 
+    public void noteAlarmStartLocked(String name, int uid) {
+        if (!mRecordAllHistory) {
+            return;
+        }
+        uid = mapUid(uid);
+        final long elapsedRealtime = SystemClock.elapsedRealtime();
+        final long uptime = SystemClock.uptimeMillis();
+        if (!mActiveEvents.updateState(HistoryItem.EVENT_ALARM_START, name, uid, 0)) {
+            return;
+        }
+        addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_ALARM_START, name, uid);
+    }
+
+    public void noteAlarmFinishLocked(String name, int uid) {
+        if (!mRecordAllHistory) {
+            return;
+        }
+        uid = mapUid(uid);
+        final long elapsedRealtime = SystemClock.elapsedRealtime();
+        final long uptime = SystemClock.uptimeMillis();
+        if (!mActiveEvents.updateState(HistoryItem.EVENT_ALARM_FINISH, name, uid, 0)) {
+            return;
+        }
+        addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_ALARM_FINISH, name, uid);
+    }
+
     private void requestWakelockCpuUpdate() {
         if (!mHandler.hasMessages(MSG_UPDATE_WAKELOCKS)) {
             Message m = mHandler.obtainMessage(MSG_UPDATE_WAKELOCKS);
@@ -2709,6 +2735,7 @@
         if (!enabled) {
             // Clear out any existing state.
             mActiveEvents.removeEvents(HistoryItem.EVENT_WAKE_LOCK);
+            mActiveEvents.removeEvents(HistoryItem.EVENT_ALARM);
             // Record the currently running processes as stopping, now that we are no
             // longer tracking them.
             HashMap<String, SparseIntArray> active = mActiveEvents.getStateForEvent(
diff --git a/services/core/java/com/android/server/AlarmManagerService.java b/services/core/java/com/android/server/AlarmManagerService.java
index 34e8b78..9f80fd8 100644
--- a/services/core/java/com/android/server/AlarmManagerService.java
+++ b/services/core/java/com/android/server/AlarmManagerService.java
@@ -99,6 +99,7 @@
     static final boolean DEBUG_BATCH = localLOGV || false;
     static final boolean DEBUG_VALIDATE = localLOGV || false;
     static final boolean DEBUG_ALARM_CLOCK = localLOGV || false;
+    static final boolean RECORD_ALARMS_IN_HISTORY = true;
     static final int ALARM_EVENT = 1;
     static final String TIMEZONE_PROPERTY = "persist.sys.timezone";
 
@@ -1345,15 +1346,6 @@
     }
 
     void rescheduleKernelAlarmsLocked() {
-        if (mPendingIdleUntil != null) {
-            // If we have a pending "idle until" alarm, we will just blindly wait until
-            // it is time for that alarm to go off.  We don't want to wake up for any
-            // other reasons.
-            mNextWakeup = mNextNonWakeup = mPendingIdleUntil.whenElapsed;
-            setLocked(ELAPSED_REALTIME_WAKEUP, mNextWakeup);
-            setLocked(ELAPSED_REALTIME, mNextNonWakeup);
-            return;
-        }
         // Schedule the next upcoming wakeup alarm.  If there is a deliverable batch
         // prior to that which contains no wakeups, we schedule that as well.
         long nextNonWakeup = 0;
@@ -1574,13 +1566,6 @@
     boolean triggerAlarmsLocked(ArrayList<Alarm> triggerList, final long nowELAPSED,
             final long nowRTC) {
         boolean hasWakeup = false;
-        if (mPendingIdleUntil != null) {
-            // If we have a pending "idle until" alarm, don't trigger any alarms
-            // until we are past the idle period.
-            if (nowELAPSED < mPendingIdleUntil.whenElapsed) {
-                return false;
-            }
-        }
         // batches are temporally sorted, so we need only pull from the
         // start of the list until we either empty it or hit a batch
         // that is not yet deliverable
@@ -1816,6 +1801,17 @@
                 if (localLOGV) {
                     Slog.v(TAG, "sending alarm " + alarm);
                 }
+                if (RECORD_ALARMS_IN_HISTORY) {
+                    if (alarm.workSource != null && alarm.workSource.size() > 0) {
+                        for (int wi=0; wi<alarm.workSource.size(); wi++) {
+                            ActivityManagerNative.noteAlarmStart(
+                                    alarm.operation, alarm.workSource.get(wi), alarm.tag);
+                        }
+                    } else {
+                        ActivityManagerNative.noteAlarmStart(
+                                alarm.operation, -1, alarm.tag);
+                    }
+                }
                 alarm.operation.send(getContext(), 0,
                         mBackgroundIntent.putExtra(
                                 Intent.EXTRA_ALARM_COUNT, alarm.count),
@@ -1856,11 +1852,11 @@
                         for (int wi=0; wi<alarm.workSource.size(); wi++) {
                             ActivityManagerNative.noteWakeupAlarm(
                                     alarm.operation, alarm.workSource.get(wi),
-                                    alarm.workSource.getName(wi));
+                                    alarm.workSource.getName(wi), alarm.tag);
                         }
                     } else {
                         ActivityManagerNative.noteWakeupAlarm(
-                                alarm.operation, -1, null);
+                                alarm.operation, -1, null, alarm.tag);
                     }
                 }
             } catch (PendingIntent.CanceledException e) {
@@ -2222,6 +2218,17 @@
                         fs.nesting = 0;
                         fs.aggregateTime += nowELAPSED - fs.startTime;
                     }
+                    if (RECORD_ALARMS_IN_HISTORY) {
+                        if (inflight.mWorkSource != null && inflight.mWorkSource.size() > 0) {
+                            for (int wi=0; wi<inflight.mWorkSource.size(); wi++) {
+                                ActivityManagerNative.noteAlarmFinish(
+                                        pi, inflight.mWorkSource.get(wi), inflight.mTag);
+                            }
+                        } else {
+                            ActivityManagerNative.noteAlarmFinish(
+                                    pi, -1, inflight.mTag);
+                        }
+                    }
                 } else {
                     mLog.w("No in-flight alarm for " + pi + " " + intent);
                 }
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 6341807..b606353 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -42,7 +42,6 @@
 import android.app.ITaskStackListener;
 import android.app.ProfilerInfo;
 import android.app.usage.UsageEvents;
-import android.app.usage.UsageStats;
 import android.app.usage.UsageStatsManagerInternal;
 import android.appwidget.AppWidgetManager;
 import android.content.res.Resources;
@@ -3449,6 +3448,35 @@
         }
     }
 
+    @Override
+    public int getPackageProcessState(String packageName) {
+        int procState = ActivityManager.PROCESS_STATE_NONEXISTENT;
+        synchronized (this) {
+            for (int i=mLruProcesses.size()-1; i>=0; i--) {
+                final ProcessRecord proc = mLruProcesses.get(i);
+                if (procState == ActivityManager.PROCESS_STATE_NONEXISTENT
+                        || procState > proc.setProcState) {
+                    boolean found = false;
+                    for (int j=proc.pkgList.size()-1; j>=0 && !found; j--) {
+                        if (proc.pkgList.keyAt(j).equals(packageName)) {
+                            procState = proc.setProcState;
+                            found = true;
+                        }
+                    }
+                    if (proc.pkgDeps != null && !found) {
+                        for (int j=proc.pkgDeps.size()-1; j>=0; j--) {
+                            if (proc.pkgDeps.valueAt(j).equals(packageName)) {
+                                procState = proc.setProcState;
+                                break;
+                            }
+                        }
+                    }
+                }
+            }
+        }
+        return procState;
+    }
+
     private void dispatchProcessesChanged() {
         int N;
         synchronized (this) {
@@ -10501,15 +10529,11 @@
                 Context.WINDOW_SERVICE)).addView(v, lp);
     }
 
-    public void noteWakeupAlarm(IIntentSender sender, int sourceUid, String sourcePkg) {
+    public void noteWakeupAlarm(IIntentSender sender, int sourceUid, String sourcePkg, String tag) {
         if (!(sender instanceof PendingIntentRecord)) {
             return;
         }
         final PendingIntentRecord rec = (PendingIntentRecord)sender;
-        final String tag;
-        synchronized (this) {
-            tag = getTagForIntentSenderLocked(rec, "*walarm*:");
-        }
         final BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
         synchronized (stats) {
             if (mBatteryStatsService.isOnBattery()) {
@@ -10524,6 +10548,34 @@
         }
     }
 
+    public void noteAlarmStart(IIntentSender sender, int sourceUid, String tag) {
+        if (!(sender instanceof PendingIntentRecord)) {
+            return;
+        }
+        final PendingIntentRecord rec = (PendingIntentRecord)sender;
+        final BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
+        synchronized (stats) {
+            mBatteryStatsService.enforceCallingPermission();
+            int MY_UID = Binder.getCallingUid();
+            int uid = rec.uid == MY_UID ? Process.SYSTEM_UID : rec.uid;
+            mBatteryStatsService.noteAlarmStart(tag, sourceUid >= 0 ? sourceUid : uid);
+        }
+    }
+
+    public void noteAlarmFinish(IIntentSender sender, int sourceUid, String tag) {
+        if (!(sender instanceof PendingIntentRecord)) {
+            return;
+        }
+        final PendingIntentRecord rec = (PendingIntentRecord)sender;
+        final BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
+        synchronized (stats) {
+            mBatteryStatsService.enforceCallingPermission();
+            int MY_UID = Binder.getCallingUid();
+            int uid = rec.uid == MY_UID ? Process.SYSTEM_UID : rec.uid;
+            mBatteryStatsService.noteAlarmFinish(tag, sourceUid >= 0 ? sourceUid : uid);
+        }
+    }
+
     public boolean killPids(int[] pids, String pReason, boolean secure) {
         if (Binder.getCallingUid() != Process.SYSTEM_UID) {
             throw new SecurityException("killPids only available to the system");
diff --git a/services/core/java/com/android/server/am/BatteryStatsService.java b/services/core/java/com/android/server/am/BatteryStatsService.java
index ed108c2..bfc4fc7 100644
--- a/services/core/java/com/android/server/am/BatteryStatsService.java
+++ b/services/core/java/com/android/server/am/BatteryStatsService.java
@@ -315,6 +315,20 @@
         }
     }
 
+    public void noteAlarmStart(String name, int uid) {
+        enforceCallingPermission();
+        synchronized (mStats) {
+            mStats.noteAlarmStartLocked(name, uid);
+        }
+    }
+
+    public void noteAlarmFinish(String name, int uid) {
+        enforceCallingPermission();
+        synchronized (mStats) {
+            mStats.noteAlarmFinishLocked(name, uid);
+        }
+    }
+
     public void noteStartWakelock(int uid, int pid, String name, String historyName, int type,
             boolean unimportantForLogging) {
         enforceCallingPermission();
@@ -884,7 +898,7 @@
         pw.println("    Enable or disable a running option.  Option state is not saved across boots.");
         pw.println("    Options are:");
         pw.println("      full-history: include additional detailed events in battery history:");
-        pw.println("          wake_lock_in and proc events");
+        pw.println("          wake_lock_in, alarms and proc events");
         pw.println("      no-auto-reset: don't automatically reset stats when unplugged");
     }
 
diff --git a/services/core/java/com/android/server/job/controllers/AppIdleController.java b/services/core/java/com/android/server/job/controllers/AppIdleController.java
index 8a9f3e1..23d5c05 100644
--- a/services/core/java/com/android/server/job/controllers/AppIdleController.java
+++ b/services/core/java/com/android/server/job/controllers/AppIdleController.java
@@ -49,16 +49,12 @@
     private static volatile AppIdleController sController;
     final ArrayList<JobStatus> mTrackedTasks = new ArrayList<JobStatus>();
     private final UsageStatsManagerInternal mUsageStatsInternal;
-    private final BatteryManagerInternal mBatteryManagerInternal;
+    private final BatteryManager mBatteryManager;
     private boolean mPluggedIn;
 
     private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
         @Override public void onReceive(Context context, Intent intent) {
-            if (Intent.ACTION_BATTERY_CHANGED.equals(intent.getAction())) {
-                int plugged = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, 0);
-                // TODO: Allow any charger type
-                onPluggedIn((plugged & BatteryManager.BATTERY_PLUGGED_AC) != 0);
-            }
+            onPluggedIn(mBatteryManager.isCharging());
         }
     };
 
@@ -74,23 +70,19 @@
     private AppIdleController(StateChangedListener stateChangedListener, Context context) {
         super(stateChangedListener, context);
         mUsageStatsInternal = LocalServices.getService(UsageStatsManagerInternal.class);
-        mBatteryManagerInternal = LocalServices.getService(BatteryManagerInternal.class);
-        mPluggedIn = isPowered();
+        mBatteryManager = context.getSystemService(BatteryManager.class);
+        mPluggedIn = mBatteryManager.isCharging();
         mUsageStatsInternal.addAppIdleStateChangeListener(this);
         registerReceivers();
     }
 
     private void registerReceivers() {
         // Monitor battery charging state
-        IntentFilter filter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
+        IntentFilter filter = new IntentFilter(BatteryManager.ACTION_CHARGING);
+        filter.addAction(BatteryManager.ACTION_DISCHARGING);
         mContext.registerReceiver(mReceiver, filter);
     }
 
-    private boolean isPowered() {
-        // TODO: Allow any charger type
-        return mBatteryManagerInternal.isPowered(BatteryManager.BATTERY_PLUGGED_AC);
-    }
-
     @Override
     public void maybeStartTrackingJob(JobStatus jobStatus) {
         synchronized (mTrackedTasks) {