Improvements to low power mode.

Add new public API for monitoring low power mode.

BatteryService now puts device in to low power mode when
battery level is low.

Window manager now watches low power mode to turn off
animations.

Modifying the animator scale now gets propagated to all
processes.

Change-Id: I8fa566994764ddd4e1977631e28381ab9409f8ee
diff --git a/core/java/android/os/IPowerManager.aidl b/core/java/android/os/IPowerManager.aidl
index 61194e9..658180b 100644
--- a/core/java/android/os/IPowerManager.aidl
+++ b/core/java/android/os/IPowerManager.aidl
@@ -41,6 +41,7 @@
     void goToSleep(long time, int reason, int flags);
     void nap(long time);
     boolean isInteractive();
+    boolean isPowerSaveMode();
 
     void reboot(boolean confirm, String reason, boolean wait);
     void shutdown(boolean confirm, boolean wait);
diff --git a/core/java/android/os/PowerManager.java b/core/java/android/os/PowerManager.java
index d5177e8..92e80a5 100644
--- a/core/java/android/os/PowerManager.java
+++ b/core/java/android/os/PowerManager.java
@@ -16,6 +16,7 @@
 
 package android.os;
 
+import android.annotation.SdkConstant;
 import android.content.Context;
 import android.util.Log;
 
@@ -685,6 +686,30 @@
     }
 
     /**
+     * Returns true if the device is currently in power save mode.  When in this mode,
+     * applications should reduce their functionality in order to conserve battery as
+     * much as possible.  You can monitor for changes to this state with
+     * {@link #ACTION_POWER_SAVE_MODE_CHANGED}.
+     *
+     * @return Returns true if currently in low power mode, else false.
+     */
+    public boolean isPowerSaveMode() {
+        try {
+            return mService.isPowerSaveMode();
+        } catch (RemoteException e) {
+            return false;
+        }
+    }
+
+    /**
+     * Intent that is broadcast when the state of {@link #isPowerSaveMode()} changes.
+     * This broadcast is only sent to registered receivers.
+     */
+    @SdkConstant(SdkConstant.SdkConstantType.BROADCAST_INTENT_ACTION)
+    public static final String ACTION_POWER_SAVE_MODE_CHANGED
+            = "android.os.action.POWER_SAVE_MODE_CHANGED";
+
+    /**
      * A wake lock is a mechanism to indicate that your application needs
      * to have the device stay on.
      * <p>
diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl
index a52ccdf..ae59bbc 100644
--- a/core/java/android/view/IWindowManager.aidl
+++ b/core/java/android/view/IWindowManager.aidl
@@ -30,6 +30,7 @@
 import android.view.IOnKeyguardExitResult;
 import android.view.IRotationWatcher;
 import android.view.IWindowSession;
+import android.view.IWindowSessionCallback;
 import android.view.KeyEvent;
 import android.view.InputEvent;
 import android.view.MagnificationSpec;
@@ -56,7 +57,7 @@
     boolean stopViewServer();            // Transaction #2
     boolean isViewServerRunning();       // Transaction #3
 
-    IWindowSession openSession(in IInputMethodClient client,
+    IWindowSession openSession(in IWindowSessionCallback callback, in IInputMethodClient client,
             in IInputContext inputContext);
     boolean inputMethodClientHasFocus(IInputMethodClient client);
 
@@ -130,6 +131,8 @@
     void setAnimationScale(int which, float scale);
     void setAnimationScales(in float[] scales);
 
+    float getCurrentAnimatorScale();
+
     // For testing
     void setInTouchMode(boolean showFocus);
 
diff --git a/core/java/android/view/IWindowSessionCallback.aidl b/core/java/android/view/IWindowSessionCallback.aidl
new file mode 100644
index 0000000..88931ce
--- /dev/null
+++ b/core/java/android/view/IWindowSessionCallback.aidl
@@ -0,0 +1,27 @@
+/*
+** Copyright 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.view;
+
+/**
+ * Callback to active sessions of the window manager
+ *
+ * {@hide}
+ */
+oneway interface IWindowSessionCallback
+{
+    void onAnimatorScaleChanged(float scale);
+}
diff --git a/core/java/android/view/WindowManagerGlobal.java b/core/java/android/view/WindowManagerGlobal.java
index b4779f4..0ebf2e1 100644
--- a/core/java/android/view/WindowManagerGlobal.java
+++ b/core/java/android/view/WindowManagerGlobal.java
@@ -147,9 +147,14 @@
                     InputMethodManager imm = InputMethodManager.getInstance();
                     IWindowManager windowManager = getWindowManagerService();
                     sWindowSession = windowManager.openSession(
+                            new IWindowSessionCallback.Stub() {
+                                @Override
+                                public void onAnimatorScaleChanged(float scale) {
+                                    ValueAnimator.setDurationScale(scale);
+                                }
+                            },
                             imm.getClient(), imm.getInputContext());
-                    float animatorScale = windowManager.getAnimationScale(2);
-                    ValueAnimator.setDurationScale(animatorScale);
+                    ValueAnimator.setDurationScale(windowManager.getCurrentAnimatorScale());
                 } catch (RemoteException e) {
                     Log.e(TAG, "Failed to open window session", e);
                 }
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index d844818..f57c3a0 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -74,6 +74,8 @@
     <protected-broadcast android:name="android.intent.action.USER_FOREGROUND" />
     <protected-broadcast android:name="android.intent.action.USER_SWITCHED" />
 
+    <protected-broadcast android:name="android.os.action.POWER_SAVE_MODE_CHANGED" />
+
     <protected-broadcast android:name="android.app.action.ENTER_CAR_MODE" />
     <protected-broadcast android:name="android.app.action.EXIT_CAR_MODE" />
     <protected-broadcast android:name="android.app.action.ENTER_DESK_MODE" />