diff --git a/services/core/java/com/android/server/power/BatterySaverPolicy.java b/services/core/java/com/android/server/power/BatterySaverPolicy.java index 38101926c0d0e..8a40b4dd49fbb 100644 --- a/services/core/java/com/android/server/power/BatterySaverPolicy.java +++ b/services/core/java/com/android/server/power/BatterySaverPolicy.java @@ -49,11 +49,21 @@ public class BatterySaverPolicy extends ContentObserver { public static final boolean DEBUG = false; // DO NOT SUBMIT WITH TRUE. - // Value of batterySaverGpsMode such that GPS isn't affected by battery saver mode. + /** Value of batterySaverGpsMode such that GPS isn't affected by battery saver mode. */ public static final int GPS_MODE_NO_CHANGE = 0; - // Value of batterySaverGpsMode such that GPS is disabled when battery saver mode - // is enabled and the screen is off. + + /** + * Value of batterySaverGpsMode such that GPS is disabled when battery saver mode + * is enabled and the screen is off. + */ public static final int GPS_MODE_DISABLED_WHEN_SCREEN_OFF = 1; + + /** + * Value of batterySaverGpsMode such that location should be disabled altogether + * when battery saver mode is enabled and the screen is off. + */ + public static final int GPS_MODE_ALL_DISABLED_WHEN_SCREEN_OFF = 2; + // Secure setting for GPS behavior when battery saver mode is on. public static final String SECURE_KEY_GPS_MODE = "batterySaverGpsMode"; @@ -344,7 +354,7 @@ public class BatterySaverPolicy extends ContentObserver { // Get default value from Settings.Secure final int defaultGpsMode = Settings.Secure.getInt(mContentResolver, SECURE_KEY_GPS_MODE, - GPS_MODE_NO_CHANGE); + GPS_MODE_ALL_DISABLED_WHEN_SCREEN_OFF); mGpsMode = parser.getInt(KEY_GPS_MODE, defaultGpsMode); // Non-device-specific parameters. @@ -446,6 +456,12 @@ public class BatterySaverPolicy extends ContentObserver { } } + public int getGpsMode() { + synchronized (mLock) { + return mGpsMode; + } + } + public ArrayMap getFileValues(boolean interactive) { synchronized (mLock) { return interactive ? mFilesForInteractive : mFilesForNoninteractive; diff --git a/services/core/java/com/android/server/power/batterysaver/BatterySaverController.java b/services/core/java/com/android/server/power/batterysaver/BatterySaverController.java index a6bca0bf6c4ca..d4627c2da07ec 100644 --- a/services/core/java/com/android/server/power/batterysaver/BatterySaverController.java +++ b/services/core/java/com/android/server/power/batterysaver/BatterySaverController.java @@ -84,6 +84,23 @@ public class BatterySaverController implements BatterySaverPolicyListener { */ private boolean mPreviouslyEnabled; + @GuardedBy("mLock") + private boolean mIsInteractive; + + /** + * Read-only list of plugins. No need for synchronization. + */ + private final Plugin[] mPlugins; + + /** + * Plugin interface. All methods are guaranteed to be called on the same (handler) thread. + */ + public interface Plugin { + void onSystemReady(BatterySaverController caller); + + void onBatterySaverChanged(BatterySaverController caller); + } + private final BroadcastReceiver mReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { @@ -109,6 +126,12 @@ public class BatterySaverController implements BatterySaverPolicyListener { mBatterySaverPolicy = policy; mBatterySaverPolicy.addListener(this); mFileUpdater = new FileUpdater(context); + + // Initialize plugins. + final ArrayList plugins = new ArrayList<>(); + plugins.add(new BatterySaverLocationPlugin(mContext)); + + mPlugins = plugins.toArray(new Plugin[plugins.size()]); } /** @@ -121,7 +144,7 @@ public class BatterySaverController implements BatterySaverPolicyListener { } /** - * Called by {@link PowerManagerService} on system ready.. + * Called by {@link PowerManagerService} on system ready. */ public void systemReady() { final IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_ON); @@ -130,6 +153,7 @@ public class BatterySaverController implements BatterySaverPolicyListener { mFileUpdater.systemReady(LocalServices.getService(ActivityManagerInternal.class) .isRuntimeRestarted()); + mHandler.postSystemReady(); } private PowerManager getPowerManager() { @@ -154,6 +178,8 @@ public class BatterySaverController implements BatterySaverPolicyListener { private static final int ARG_DONT_SEND_BROADCAST = 0; private static final int ARG_SEND_BROADCAST = 1; + private static final int MSG_SYSTEM_READY = 2; + public MyHandler(Looper looper) { super(looper); } @@ -163,12 +189,22 @@ public class BatterySaverController implements BatterySaverPolicyListener { ARG_SEND_BROADCAST : ARG_DONT_SEND_BROADCAST, 0).sendToTarget(); } + public void postSystemReady() { + obtainMessage(MSG_SYSTEM_READY, 0, 0).sendToTarget(); + } + @Override public void dispatchMessage(Message msg) { switch (msg.what) { case MSG_STATE_CHANGED: handleBatterySaverStateChanged(msg.arg1 == ARG_SEND_BROADCAST); break; + + case MSG_SYSTEM_READY: + for (Plugin p : mPlugins) { + p.onSystemReady(BatterySaverController.this); + } + break; } } } @@ -188,12 +224,24 @@ public class BatterySaverController implements BatterySaverPolicyListener { } /** @return whether battery saver is enabled or not. */ - boolean isEnabled() { + public boolean isEnabled() { synchronized (mLock) { return mEnabled; } } + /** @return whether device is in interactive state. */ + public boolean isInteractive() { + synchronized (mLock) { + return mIsInteractive; + } + } + + /** @return Battery saver policy. */ + public BatterySaverPolicy getBatterySaverPolicy() { + return mBatterySaverPolicy; + } + /** * @return true if launch boost should currently be disabled. */ @@ -230,6 +278,7 @@ public class BatterySaverController implements BatterySaverPolicyListener { listeners = mListeners.toArray(new LowPowerModeListener[mListeners.size()]); enabled = mEnabled; + mIsInteractive = isInteractive; if (enabled) { @@ -250,6 +299,10 @@ public class BatterySaverController implements BatterySaverPolicyListener { mFileUpdater.writeFiles(fileValues); } + for (Plugin p : mPlugins) { + p.onBatterySaverChanged(this); + } + if (sendBroadcast) { if (enabled) { // STOPSHIP Remove the toast. diff --git a/services/core/java/com/android/server/power/batterysaver/BatterySaverLocationPlugin.java b/services/core/java/com/android/server/power/batterysaver/BatterySaverLocationPlugin.java new file mode 100644 index 0000000000000..0af19b6f2c5dc --- /dev/null +++ b/services/core/java/com/android/server/power/batterysaver/BatterySaverLocationPlugin.java @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2017 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 com.android.server.power.batterysaver; + +import android.content.Context; +import android.provider.Settings; +import android.provider.Settings.Global; +import android.util.Slog; + +import com.android.server.power.BatterySaverPolicy; +import com.android.server.power.batterysaver.BatterySaverController.Plugin; + +public class BatterySaverLocationPlugin implements Plugin { + private static final String TAG = "BatterySaverLocationPlugin"; + + private static final boolean DEBUG = BatterySaverController.DEBUG; + + private final Context mContext; + + public BatterySaverLocationPlugin(Context context) { + mContext = context; + } + + @Override + public void onBatterySaverChanged(BatterySaverController caller) { + if (DEBUG) { + Slog.d(TAG, "onBatterySaverChanged"); + } + updateLocationState(caller); + } + + @Override + public void onSystemReady(BatterySaverController caller) { + if (DEBUG) { + Slog.d(TAG, "onSystemReady"); + } + updateLocationState(caller); + } + + private void updateLocationState(BatterySaverController caller) { + final boolean kill = + (caller.getBatterySaverPolicy().getGpsMode() + == BatterySaverPolicy.GPS_MODE_ALL_DISABLED_WHEN_SCREEN_OFF) && + caller.isEnabled() && !caller.isInteractive(); + + if (DEBUG) { + Slog.d(TAG, "Battery saver " + (kill ? "stopping" : "restoring") + " location."); + } + Settings.Global.putInt(mContext.getContentResolver(), + Global.LOCATION_GLOBAL_KILL_SWITCH, kill ? 1 : 0); + } +}