Loading packages/SystemUI/src/com/android/systemui/statusbar/car/CarBatteryController.java 0 → 100644 +271 −0 Original line number Diff line number Diff line /* * Copyright (C) 2016 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.systemui.statusbar.car; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothHeadsetClient; import android.bluetooth.BluetoothProfile; import android.bluetooth.BluetoothProfile.ServiceListener; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.os.Bundle; import android.util.Log; import com.android.systemui.statusbar.policy.BatteryController; import java.io.FileDescriptor; import java.io.PrintWriter; import java.util.ArrayList; /** * A {@link BatteryController} that is specific to the Auto use-case. For Auto, the battery icon * displays the battery status of a device that is connected via bluetooth and not the system's * battery. */ public class CarBatteryController extends BroadcastReceiver implements BatteryController { private static final String TAG = "CarBatteryController"; // According to the Bluetooth HFP 1.5 specification, battery levels are indicated by a // value from 1-5, where these values represent the following: // 0%% - 0, 1-25%% - 1, 26-50%% - 2, 51-75%% - 3, 76-99%% - 4, 100%% - 5 // As a result, set the level as the average within that range. private static final int BATTERY_LEVEL_EMPTY = 0; private static final int BATTERY_LEVEL_1 = 12; private static final int BATTERY_LEVEL_2 = 28; private static final int BATTERY_LEVEL_3 = 63; private static final int BATTERY_LEVEL_4 = 87; private static final int BATTERY_LEVEL_FULL = 100; private static final int INVALID_BATTERY_LEVEL = -1; private final Context mContext; private final BluetoothAdapter mAdapter = BluetoothAdapter.getDefaultAdapter(); private BluetoothHeadsetClient mBluetoothHeadsetClient; private final ArrayList<BatteryStateChangeCallback> mChangeCallbacks = new ArrayList<>(); private int mLevel; /** * An interface indicating the container of a View that will display what the information * in the {@link CarBatteryController}. */ public interface BatteryViewHandler { void hideBatteryView(); void showBatteryView(); } private BatteryViewHandler mBatteryViewHandler; public CarBatteryController(Context context) { mContext = context; mAdapter.getProfileProxy(context.getApplicationContext(), mHfpServiceListener, BluetoothProfile.HEADSET_CLIENT); } @Override public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { pw.println("CarBatteryController state:"); pw.print(" mLevel="); pw.println(mLevel); } @Override public void setPowerSaveMode(boolean powerSave) { // No-op. No power save mode for the car. } @Override public void addStateChangedCallback(BatteryController.BatteryStateChangeCallback cb) { mChangeCallbacks.add(cb); // There is no way to know if the phone is plugged in or charging via bluetooth, so pass // false for these values. cb.onBatteryLevelChanged(mLevel, false /* pluggedIn */, false /* charging */); cb.onPowerSaveChanged(false /* isPowerSave */); } @Override public void removeStateChangedCallback(BatteryController.BatteryStateChangeCallback cb) { mChangeCallbacks.remove(cb); } public void addBatteryViewHandler(BatteryViewHandler batteryViewHandler) { mBatteryViewHandler = batteryViewHandler; } public void startListening() { IntentFilter filter = new IntentFilter(); filter.addAction(BluetoothHeadsetClient.ACTION_CONNECTION_STATE_CHANGED); filter.addAction(BluetoothHeadsetClient.ACTION_AG_EVENT); mContext.registerReceiver(this, filter); } public void stopListening() { mContext.unregisterReceiver(this); } @Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); if (Log.isLoggable(TAG, Log.DEBUG)) { Log.d(TAG, "onReceive(). action: " + action); } if (BluetoothHeadsetClient.ACTION_AG_EVENT.equals(action)) { if (Log.isLoggable(TAG, Log.DEBUG)) { Log.d(TAG, "Received ACTION_AG_EVENT"); } int batteryLevel = intent.getIntExtra(BluetoothHeadsetClient.EXTRA_BATTERY_LEVEL, INVALID_BATTERY_LEVEL); updateBatteryLevel(batteryLevel); if (batteryLevel != INVALID_BATTERY_LEVEL && mBatteryViewHandler != null) { mBatteryViewHandler.showBatteryView(); } } else if (BluetoothHeadsetClient.ACTION_CONNECTION_STATE_CHANGED.equals(action)) { int newState = intent.getIntExtra(BluetoothProfile.EXTRA_STATE, -1); if (Log.isLoggable(TAG, Log.DEBUG)) { int oldState = intent.getIntExtra(BluetoothProfile.EXTRA_PREVIOUS_STATE, -1); Log.d(TAG, "ACTION_CONNECTION_STATE_CHANGED event: " + oldState + " -> " + newState); } BluetoothDevice device = (BluetoothDevice)intent.getExtra(BluetoothDevice.EXTRA_DEVICE); updateBatteryIcon(device, newState); } } /** * Converts the battery level to a percentage that can be displayed on-screen and notifies * any {@link BatteryStateChangeCallback}s of this. */ private void updateBatteryLevel(int batteryLevel) { if (batteryLevel == INVALID_BATTERY_LEVEL) { if (Log.isLoggable(TAG, Log.DEBUG)) { Log.d(TAG, "Battery level invalid. Ignoring."); } return; } // The battery level is a value between 0-5. Let the default battery level be 0. switch (batteryLevel) { case 5: mLevel = BATTERY_LEVEL_FULL; break; case 4: mLevel = BATTERY_LEVEL_4; break; case 3: mLevel = BATTERY_LEVEL_3; break; case 2: mLevel = BATTERY_LEVEL_2; break; case 1: mLevel = BATTERY_LEVEL_1; break; case 0: default: mLevel = BATTERY_LEVEL_EMPTY; } if (Log.isLoggable(TAG, Log.DEBUG)) { Log.d(TAG, "Battery level: " + batteryLevel + "; setting mLevel as: " + mLevel); } notifyBatteryLevelChanged(); } /** * Updates the display of the battery icon depending on the given connection state from the * given {@link BluetoothDevice}. */ private void updateBatteryIcon(BluetoothDevice device, int newState) { if (newState == BluetoothProfile.STATE_CONNECTED) { if (Log.isLoggable(TAG, Log.DEBUG)) { Log.d(TAG, "Device connected"); } if (mBatteryViewHandler != null) { mBatteryViewHandler.showBatteryView(); } if (mBluetoothHeadsetClient == null || device == null) { return; } // Check if battery information is available and immediately update. Bundle featuresBundle = mBluetoothHeadsetClient.getCurrentAgEvents(device); if (featuresBundle == null) { return; } int batteryLevel = featuresBundle.getInt(BluetoothHeadsetClient.EXTRA_BATTERY_LEVEL, INVALID_BATTERY_LEVEL); updateBatteryLevel(batteryLevel); } else if (newState == BluetoothProfile.STATE_DISCONNECTED) { if (Log.isLoggable(TAG, Log.DEBUG)) { Log.d(TAG, "Device disconnected"); } if (mBatteryViewHandler != null) { mBatteryViewHandler.hideBatteryView(); } } } @Override public boolean isPowerSave() { // Power save is not valid for the car, so always return false. return false; } private void notifyBatteryLevelChanged() { for (int i = 0, size = mChangeCallbacks.size(); i < size; i++) { mChangeCallbacks.get(i) .onBatteryLevelChanged(mLevel, false /* pluggedIn */, false /* charging */); } } private final ServiceListener mHfpServiceListener = new ServiceListener() { @Override public void onServiceConnected(int profile, BluetoothProfile proxy) { if (profile == BluetoothProfile.HEADSET_CLIENT) { mBluetoothHeadsetClient = (BluetoothHeadsetClient) proxy; } } @Override public void onServiceDisconnected(int profile) { if (profile == BluetoothProfile.HEADSET_CLIENT) { mBluetoothHeadsetClient = null; } } }; } packages/SystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java +65 −5 Original line number Diff line number Diff line Loading @@ -22,37 +22,75 @@ import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.graphics.PixelFormat; import android.os.Handler; import android.os.Looper; import android.os.RemoteException; import android.util.Log; import android.view.View; import android.view.ViewGroup.LayoutParams; import android.view.ViewStub; import android.view.WindowManager; import com.android.systemui.BatteryMeterView; import com.android.systemui.R; import com.android.systemui.recents.Recents; import com.android.systemui.recents.misc.SystemServicesProxy; import com.android.systemui.recents.misc.SystemServicesProxy.TaskStackListener; import com.android.systemui.statusbar.StatusBarState; import com.android.systemui.statusbar.phone.PhoneStatusBar; import com.android.systemui.statusbar.phone.PhoneStatusBarView; import com.android.systemui.statusbar.policy.BatteryController; /** * A status bar (and navigation bar) tailored for the automotive use case. */ public class CarStatusBar extends PhoneStatusBar { public class CarStatusBar extends PhoneStatusBar implements CarBatteryController.BatteryViewHandler { private static final String TAG = "CarStatusBar"; private TaskStackListenerImpl mTaskStackListener; private CarNavigationBarView mCarNavigationBar; private CarNavigationBarController mController; private FullscreenUserSwitcher mFullscreenUserSwitcher; private CarBatteryController mCarBatteryController; private BatteryMeterView mBatteryMeterView; @Override public void start() { super.start(); mTaskStackListener = new TaskStackListenerImpl(); SystemServicesProxy.getInstance(mContext).registerTaskStackListener(mTaskStackListener); registerPackageChangeReceivers(); mCarBatteryController.startListening(); } @Override public void destroy() { mCarBatteryController.stopListening(); super.destroy(); } @Override protected PhoneStatusBarView makeStatusBarView() { PhoneStatusBarView statusBarView = super.makeStatusBarView(); mBatteryMeterView = ((BatteryMeterView) statusBarView.findViewById(R.id.battery)); // By default, the BatteryMeterView should not be visible. It will be toggled visible // when a device has connected by bluetooth. mBatteryMeterView.setVisibility(View.GONE); if (Log.isLoggable(TAG, Log.DEBUG)) { Log.d(TAG, "makeStatusBarView(). mBatteryMeterView: " + mBatteryMeterView); } return statusBarView; } @Override protected BatteryController createBatteryController() { mCarBatteryController = new CarBatteryController(mContext); mCarBatteryController.addBatteryViewHandler(this); return mCarBatteryController; } @Override Loading Loading @@ -85,6 +123,28 @@ public class CarStatusBar extends PhoneStatusBar { } @Override public void showBatteryView() { if (Log.isLoggable(TAG, Log.DEBUG)) { Log.d(TAG, "showBatteryView(). mBatteryMeterView: " + mBatteryMeterView); } if (mBatteryMeterView != null) { mBatteryMeterView.setVisibility(View.VISIBLE); } } @Override public void hideBatteryView() { if (Log.isLoggable(TAG, Log.DEBUG)) { Log.d(TAG, "hideBatteryView(). mBatteryMeterView: " + mBatteryMeterView); } if (mBatteryMeterView != null) { mBatteryMeterView.setVisibility(View.GONE); } } private BroadcastReceiver mPackageChangeReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { Loading packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java +6 −3 Original line number Diff line number Diff line Loading @@ -21,9 +21,7 @@ import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.annotation.NonNull; import android.app.ActivityManager; import android.app.ActivityManager.StackId; import android.app.ActivityManagerNative; import android.app.ActivityOptions; import android.app.IActivityManager; import android.app.Notification; import android.app.PendingIntent; Loading Loading @@ -147,6 +145,7 @@ import com.android.systemui.statusbar.phone.UnlockMethodCache.OnUnlockMethodChan import com.android.systemui.statusbar.policy.AccessibilityController; import com.android.systemui.statusbar.policy.BatteryController; import com.android.systemui.statusbar.policy.BatteryController.BatteryStateChangeCallback; import com.android.systemui.statusbar.policy.BatteryControllerImpl; import com.android.systemui.statusbar.policy.BluetoothControllerImpl; import com.android.systemui.statusbar.policy.BrightnessMirrorController; import com.android.systemui.statusbar.policy.CastControllerImpl; Loading Loading @@ -826,7 +825,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, // Other icons mLocationController = new LocationControllerImpl(mContext, mHandlerThread.getLooper()); // will post a notification mBatteryController = new BatteryController(mContext); mBatteryController = createBatteryController(); mBatteryController.addStateChangedCallback(new BatteryStateChangeCallback() { @Override public void onPowerSaveChanged(boolean isPowerSave) { Loading Loading @@ -943,6 +942,10 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, return mStatusBarView; } protected BatteryController createBatteryController() { return new BatteryControllerImpl(mContext); } @Override protected void reInflateViews() { super.reInflateViews(); Loading packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryController.java +24 −149 Original line number Diff line number Diff line Loading @@ -16,158 +16,33 @@ package com.android.systemui.statusbar.policy; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.os.BatteryManager; import android.os.Handler; import android.os.PowerManager; import android.util.Log; import java.io.FileDescriptor; import java.io.PrintWriter; import java.util.ArrayList; public class BatteryController extends BroadcastReceiver { private static final String TAG = "BatteryController"; public static final String ACTION_LEVEL_TEST = "com.android.systemui.BATTERY_LEVEL_TEST"; private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); private final ArrayList<BatteryStateChangeCallback> mChangeCallbacks = new ArrayList<>(); private final PowerManager mPowerManager; private final Handler mHandler; private int mLevel; private boolean mPluggedIn; private boolean mCharging; private boolean mCharged; private boolean mPowerSave; private boolean mTestmode = false; public BatteryController(Context context) { mHandler = new Handler(); mPowerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE); IntentFilter filter = new IntentFilter(); filter.addAction(Intent.ACTION_BATTERY_CHANGED); filter.addAction(PowerManager.ACTION_POWER_SAVE_MODE_CHANGED); filter.addAction(PowerManager.ACTION_POWER_SAVE_MODE_CHANGING); filter.addAction(ACTION_LEVEL_TEST); context.registerReceiver(this, filter); updatePowerSave(); } public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { pw.println("BatteryController state:"); pw.print(" mLevel="); pw.println(mLevel); pw.print(" mPluggedIn="); pw.println(mPluggedIn); pw.print(" mCharging="); pw.println(mCharging); pw.print(" mCharged="); pw.println(mCharged); pw.print(" mPowerSave="); pw.println(mPowerSave); } public void setPowerSaveMode(boolean powerSave) { mPowerManager.setPowerSaveMode(powerSave); } public void addStateChangedCallback(BatteryStateChangeCallback cb) { mChangeCallbacks.add(cb); cb.onBatteryLevelChanged(mLevel, mPluggedIn, mCharging); cb.onPowerSaveChanged(mPowerSave); } public void removeStateChangedCallback(BatteryStateChangeCallback cb) { mChangeCallbacks.remove(cb); } public void onReceive(final Context context, Intent intent) { final String action = intent.getAction(); if (action.equals(Intent.ACTION_BATTERY_CHANGED)) { if (mTestmode && !intent.getBooleanExtra("testmode", false)) return; mLevel = (int)(100f * intent.getIntExtra(BatteryManager.EXTRA_LEVEL, 0) / intent.getIntExtra(BatteryManager.EXTRA_SCALE, 100)); mPluggedIn = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, 0) != 0; final int status = intent.getIntExtra(BatteryManager.EXTRA_STATUS, BatteryManager.BATTERY_STATUS_UNKNOWN); mCharged = status == BatteryManager.BATTERY_STATUS_FULL; mCharging = mCharged || status == BatteryManager.BATTERY_STATUS_CHARGING; fireBatteryLevelChanged(); } else if (action.equals(PowerManager.ACTION_POWER_SAVE_MODE_CHANGED)) { updatePowerSave(); } else if (action.equals(PowerManager.ACTION_POWER_SAVE_MODE_CHANGING)) { setPowerSave(intent.getBooleanExtra(PowerManager.EXTRA_POWER_SAVE_MODE, false)); } else if (action.equals(ACTION_LEVEL_TEST)) { mTestmode = true; mHandler.post(new Runnable() { int curLevel = 0; int incr = 1; int saveLevel = mLevel; boolean savePlugged = mPluggedIn; Intent dummy = new Intent(Intent.ACTION_BATTERY_CHANGED); @Override public void run() { if (curLevel < 0) { mTestmode = false; dummy.putExtra("level", saveLevel); dummy.putExtra("plugged", savePlugged); dummy.putExtra("testmode", false); } else { dummy.putExtra("level", curLevel); dummy.putExtra("plugged", incr > 0 ? BatteryManager.BATTERY_PLUGGED_AC : 0); dummy.putExtra("testmode", true); } context.sendBroadcast(dummy); if (!mTestmode) return; curLevel += incr; if (curLevel == 100) { incr *= -1; } mHandler.postDelayed(this, 200); } }); } } public boolean isPowerSave() { return mPowerSave; } private void updatePowerSave() { setPowerSave(mPowerManager.isPowerSaveMode()); } public interface BatteryController { /** * Prints the current state of the {@link BatteryController} to the given {@link PrintWriter}. */ void dump(FileDescriptor fd, PrintWriter pw, String[] args); private void setPowerSave(boolean powerSave) { if (powerSave == mPowerSave) return; mPowerSave = powerSave; if (DEBUG) Log.d(TAG, "Power save is " + (mPowerSave ? "on" : "off")); firePowerSaveChanged(); } /** * Sets if the current device is in power save mode. */ void setPowerSaveMode(boolean powerSave); private void fireBatteryLevelChanged() { final int N = mChangeCallbacks.size(); for (int i = 0; i < N; i++) { mChangeCallbacks.get(i).onBatteryLevelChanged(mLevel, mPluggedIn, mCharging); } } /** * Returns {@code true} if the device is currently in power save mode. */ boolean isPowerSave(); private void firePowerSaveChanged() { final int N = mChangeCallbacks.size(); for (int i = 0; i < N; i++) { mChangeCallbacks.get(i).onPowerSaveChanged(mPowerSave); } } void addStateChangedCallback(BatteryStateChangeCallback cb); void removeStateChangedCallback(BatteryStateChangeCallback cb); public interface BatteryStateChangeCallback { /** * A listener that will be notified whenever a change in battery level or power save mode * has occurred. */ interface BatteryStateChangeCallback { void onBatteryLevelChanged(int level, boolean pluggedIn, boolean charging); void onPowerSaveChanged(boolean isPowerSave); } Loading packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerImpl.java 0 → 100644 +179 −0 File added.Preview size limit exceeded, changes collapsed. Show changes Loading
packages/SystemUI/src/com/android/systemui/statusbar/car/CarBatteryController.java 0 → 100644 +271 −0 Original line number Diff line number Diff line /* * Copyright (C) 2016 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.systemui.statusbar.car; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothHeadsetClient; import android.bluetooth.BluetoothProfile; import android.bluetooth.BluetoothProfile.ServiceListener; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.os.Bundle; import android.util.Log; import com.android.systemui.statusbar.policy.BatteryController; import java.io.FileDescriptor; import java.io.PrintWriter; import java.util.ArrayList; /** * A {@link BatteryController} that is specific to the Auto use-case. For Auto, the battery icon * displays the battery status of a device that is connected via bluetooth and not the system's * battery. */ public class CarBatteryController extends BroadcastReceiver implements BatteryController { private static final String TAG = "CarBatteryController"; // According to the Bluetooth HFP 1.5 specification, battery levels are indicated by a // value from 1-5, where these values represent the following: // 0%% - 0, 1-25%% - 1, 26-50%% - 2, 51-75%% - 3, 76-99%% - 4, 100%% - 5 // As a result, set the level as the average within that range. private static final int BATTERY_LEVEL_EMPTY = 0; private static final int BATTERY_LEVEL_1 = 12; private static final int BATTERY_LEVEL_2 = 28; private static final int BATTERY_LEVEL_3 = 63; private static final int BATTERY_LEVEL_4 = 87; private static final int BATTERY_LEVEL_FULL = 100; private static final int INVALID_BATTERY_LEVEL = -1; private final Context mContext; private final BluetoothAdapter mAdapter = BluetoothAdapter.getDefaultAdapter(); private BluetoothHeadsetClient mBluetoothHeadsetClient; private final ArrayList<BatteryStateChangeCallback> mChangeCallbacks = new ArrayList<>(); private int mLevel; /** * An interface indicating the container of a View that will display what the information * in the {@link CarBatteryController}. */ public interface BatteryViewHandler { void hideBatteryView(); void showBatteryView(); } private BatteryViewHandler mBatteryViewHandler; public CarBatteryController(Context context) { mContext = context; mAdapter.getProfileProxy(context.getApplicationContext(), mHfpServiceListener, BluetoothProfile.HEADSET_CLIENT); } @Override public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { pw.println("CarBatteryController state:"); pw.print(" mLevel="); pw.println(mLevel); } @Override public void setPowerSaveMode(boolean powerSave) { // No-op. No power save mode for the car. } @Override public void addStateChangedCallback(BatteryController.BatteryStateChangeCallback cb) { mChangeCallbacks.add(cb); // There is no way to know if the phone is plugged in or charging via bluetooth, so pass // false for these values. cb.onBatteryLevelChanged(mLevel, false /* pluggedIn */, false /* charging */); cb.onPowerSaveChanged(false /* isPowerSave */); } @Override public void removeStateChangedCallback(BatteryController.BatteryStateChangeCallback cb) { mChangeCallbacks.remove(cb); } public void addBatteryViewHandler(BatteryViewHandler batteryViewHandler) { mBatteryViewHandler = batteryViewHandler; } public void startListening() { IntentFilter filter = new IntentFilter(); filter.addAction(BluetoothHeadsetClient.ACTION_CONNECTION_STATE_CHANGED); filter.addAction(BluetoothHeadsetClient.ACTION_AG_EVENT); mContext.registerReceiver(this, filter); } public void stopListening() { mContext.unregisterReceiver(this); } @Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); if (Log.isLoggable(TAG, Log.DEBUG)) { Log.d(TAG, "onReceive(). action: " + action); } if (BluetoothHeadsetClient.ACTION_AG_EVENT.equals(action)) { if (Log.isLoggable(TAG, Log.DEBUG)) { Log.d(TAG, "Received ACTION_AG_EVENT"); } int batteryLevel = intent.getIntExtra(BluetoothHeadsetClient.EXTRA_BATTERY_LEVEL, INVALID_BATTERY_LEVEL); updateBatteryLevel(batteryLevel); if (batteryLevel != INVALID_BATTERY_LEVEL && mBatteryViewHandler != null) { mBatteryViewHandler.showBatteryView(); } } else if (BluetoothHeadsetClient.ACTION_CONNECTION_STATE_CHANGED.equals(action)) { int newState = intent.getIntExtra(BluetoothProfile.EXTRA_STATE, -1); if (Log.isLoggable(TAG, Log.DEBUG)) { int oldState = intent.getIntExtra(BluetoothProfile.EXTRA_PREVIOUS_STATE, -1); Log.d(TAG, "ACTION_CONNECTION_STATE_CHANGED event: " + oldState + " -> " + newState); } BluetoothDevice device = (BluetoothDevice)intent.getExtra(BluetoothDevice.EXTRA_DEVICE); updateBatteryIcon(device, newState); } } /** * Converts the battery level to a percentage that can be displayed on-screen and notifies * any {@link BatteryStateChangeCallback}s of this. */ private void updateBatteryLevel(int batteryLevel) { if (batteryLevel == INVALID_BATTERY_LEVEL) { if (Log.isLoggable(TAG, Log.DEBUG)) { Log.d(TAG, "Battery level invalid. Ignoring."); } return; } // The battery level is a value between 0-5. Let the default battery level be 0. switch (batteryLevel) { case 5: mLevel = BATTERY_LEVEL_FULL; break; case 4: mLevel = BATTERY_LEVEL_4; break; case 3: mLevel = BATTERY_LEVEL_3; break; case 2: mLevel = BATTERY_LEVEL_2; break; case 1: mLevel = BATTERY_LEVEL_1; break; case 0: default: mLevel = BATTERY_LEVEL_EMPTY; } if (Log.isLoggable(TAG, Log.DEBUG)) { Log.d(TAG, "Battery level: " + batteryLevel + "; setting mLevel as: " + mLevel); } notifyBatteryLevelChanged(); } /** * Updates the display of the battery icon depending on the given connection state from the * given {@link BluetoothDevice}. */ private void updateBatteryIcon(BluetoothDevice device, int newState) { if (newState == BluetoothProfile.STATE_CONNECTED) { if (Log.isLoggable(TAG, Log.DEBUG)) { Log.d(TAG, "Device connected"); } if (mBatteryViewHandler != null) { mBatteryViewHandler.showBatteryView(); } if (mBluetoothHeadsetClient == null || device == null) { return; } // Check if battery information is available and immediately update. Bundle featuresBundle = mBluetoothHeadsetClient.getCurrentAgEvents(device); if (featuresBundle == null) { return; } int batteryLevel = featuresBundle.getInt(BluetoothHeadsetClient.EXTRA_BATTERY_LEVEL, INVALID_BATTERY_LEVEL); updateBatteryLevel(batteryLevel); } else if (newState == BluetoothProfile.STATE_DISCONNECTED) { if (Log.isLoggable(TAG, Log.DEBUG)) { Log.d(TAG, "Device disconnected"); } if (mBatteryViewHandler != null) { mBatteryViewHandler.hideBatteryView(); } } } @Override public boolean isPowerSave() { // Power save is not valid for the car, so always return false. return false; } private void notifyBatteryLevelChanged() { for (int i = 0, size = mChangeCallbacks.size(); i < size; i++) { mChangeCallbacks.get(i) .onBatteryLevelChanged(mLevel, false /* pluggedIn */, false /* charging */); } } private final ServiceListener mHfpServiceListener = new ServiceListener() { @Override public void onServiceConnected(int profile, BluetoothProfile proxy) { if (profile == BluetoothProfile.HEADSET_CLIENT) { mBluetoothHeadsetClient = (BluetoothHeadsetClient) proxy; } } @Override public void onServiceDisconnected(int profile) { if (profile == BluetoothProfile.HEADSET_CLIENT) { mBluetoothHeadsetClient = null; } } }; }
packages/SystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java +65 −5 Original line number Diff line number Diff line Loading @@ -22,37 +22,75 @@ import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.graphics.PixelFormat; import android.os.Handler; import android.os.Looper; import android.os.RemoteException; import android.util.Log; import android.view.View; import android.view.ViewGroup.LayoutParams; import android.view.ViewStub; import android.view.WindowManager; import com.android.systemui.BatteryMeterView; import com.android.systemui.R; import com.android.systemui.recents.Recents; import com.android.systemui.recents.misc.SystemServicesProxy; import com.android.systemui.recents.misc.SystemServicesProxy.TaskStackListener; import com.android.systemui.statusbar.StatusBarState; import com.android.systemui.statusbar.phone.PhoneStatusBar; import com.android.systemui.statusbar.phone.PhoneStatusBarView; import com.android.systemui.statusbar.policy.BatteryController; /** * A status bar (and navigation bar) tailored for the automotive use case. */ public class CarStatusBar extends PhoneStatusBar { public class CarStatusBar extends PhoneStatusBar implements CarBatteryController.BatteryViewHandler { private static final String TAG = "CarStatusBar"; private TaskStackListenerImpl mTaskStackListener; private CarNavigationBarView mCarNavigationBar; private CarNavigationBarController mController; private FullscreenUserSwitcher mFullscreenUserSwitcher; private CarBatteryController mCarBatteryController; private BatteryMeterView mBatteryMeterView; @Override public void start() { super.start(); mTaskStackListener = new TaskStackListenerImpl(); SystemServicesProxy.getInstance(mContext).registerTaskStackListener(mTaskStackListener); registerPackageChangeReceivers(); mCarBatteryController.startListening(); } @Override public void destroy() { mCarBatteryController.stopListening(); super.destroy(); } @Override protected PhoneStatusBarView makeStatusBarView() { PhoneStatusBarView statusBarView = super.makeStatusBarView(); mBatteryMeterView = ((BatteryMeterView) statusBarView.findViewById(R.id.battery)); // By default, the BatteryMeterView should not be visible. It will be toggled visible // when a device has connected by bluetooth. mBatteryMeterView.setVisibility(View.GONE); if (Log.isLoggable(TAG, Log.DEBUG)) { Log.d(TAG, "makeStatusBarView(). mBatteryMeterView: " + mBatteryMeterView); } return statusBarView; } @Override protected BatteryController createBatteryController() { mCarBatteryController = new CarBatteryController(mContext); mCarBatteryController.addBatteryViewHandler(this); return mCarBatteryController; } @Override Loading Loading @@ -85,6 +123,28 @@ public class CarStatusBar extends PhoneStatusBar { } @Override public void showBatteryView() { if (Log.isLoggable(TAG, Log.DEBUG)) { Log.d(TAG, "showBatteryView(). mBatteryMeterView: " + mBatteryMeterView); } if (mBatteryMeterView != null) { mBatteryMeterView.setVisibility(View.VISIBLE); } } @Override public void hideBatteryView() { if (Log.isLoggable(TAG, Log.DEBUG)) { Log.d(TAG, "hideBatteryView(). mBatteryMeterView: " + mBatteryMeterView); } if (mBatteryMeterView != null) { mBatteryMeterView.setVisibility(View.GONE); } } private BroadcastReceiver mPackageChangeReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { Loading
packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java +6 −3 Original line number Diff line number Diff line Loading @@ -21,9 +21,7 @@ import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.annotation.NonNull; import android.app.ActivityManager; import android.app.ActivityManager.StackId; import android.app.ActivityManagerNative; import android.app.ActivityOptions; import android.app.IActivityManager; import android.app.Notification; import android.app.PendingIntent; Loading Loading @@ -147,6 +145,7 @@ import com.android.systemui.statusbar.phone.UnlockMethodCache.OnUnlockMethodChan import com.android.systemui.statusbar.policy.AccessibilityController; import com.android.systemui.statusbar.policy.BatteryController; import com.android.systemui.statusbar.policy.BatteryController.BatteryStateChangeCallback; import com.android.systemui.statusbar.policy.BatteryControllerImpl; import com.android.systemui.statusbar.policy.BluetoothControllerImpl; import com.android.systemui.statusbar.policy.BrightnessMirrorController; import com.android.systemui.statusbar.policy.CastControllerImpl; Loading Loading @@ -826,7 +825,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, // Other icons mLocationController = new LocationControllerImpl(mContext, mHandlerThread.getLooper()); // will post a notification mBatteryController = new BatteryController(mContext); mBatteryController = createBatteryController(); mBatteryController.addStateChangedCallback(new BatteryStateChangeCallback() { @Override public void onPowerSaveChanged(boolean isPowerSave) { Loading Loading @@ -943,6 +942,10 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, return mStatusBarView; } protected BatteryController createBatteryController() { return new BatteryControllerImpl(mContext); } @Override protected void reInflateViews() { super.reInflateViews(); Loading
packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryController.java +24 −149 Original line number Diff line number Diff line Loading @@ -16,158 +16,33 @@ package com.android.systemui.statusbar.policy; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.os.BatteryManager; import android.os.Handler; import android.os.PowerManager; import android.util.Log; import java.io.FileDescriptor; import java.io.PrintWriter; import java.util.ArrayList; public class BatteryController extends BroadcastReceiver { private static final String TAG = "BatteryController"; public static final String ACTION_LEVEL_TEST = "com.android.systemui.BATTERY_LEVEL_TEST"; private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); private final ArrayList<BatteryStateChangeCallback> mChangeCallbacks = new ArrayList<>(); private final PowerManager mPowerManager; private final Handler mHandler; private int mLevel; private boolean mPluggedIn; private boolean mCharging; private boolean mCharged; private boolean mPowerSave; private boolean mTestmode = false; public BatteryController(Context context) { mHandler = new Handler(); mPowerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE); IntentFilter filter = new IntentFilter(); filter.addAction(Intent.ACTION_BATTERY_CHANGED); filter.addAction(PowerManager.ACTION_POWER_SAVE_MODE_CHANGED); filter.addAction(PowerManager.ACTION_POWER_SAVE_MODE_CHANGING); filter.addAction(ACTION_LEVEL_TEST); context.registerReceiver(this, filter); updatePowerSave(); } public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { pw.println("BatteryController state:"); pw.print(" mLevel="); pw.println(mLevel); pw.print(" mPluggedIn="); pw.println(mPluggedIn); pw.print(" mCharging="); pw.println(mCharging); pw.print(" mCharged="); pw.println(mCharged); pw.print(" mPowerSave="); pw.println(mPowerSave); } public void setPowerSaveMode(boolean powerSave) { mPowerManager.setPowerSaveMode(powerSave); } public void addStateChangedCallback(BatteryStateChangeCallback cb) { mChangeCallbacks.add(cb); cb.onBatteryLevelChanged(mLevel, mPluggedIn, mCharging); cb.onPowerSaveChanged(mPowerSave); } public void removeStateChangedCallback(BatteryStateChangeCallback cb) { mChangeCallbacks.remove(cb); } public void onReceive(final Context context, Intent intent) { final String action = intent.getAction(); if (action.equals(Intent.ACTION_BATTERY_CHANGED)) { if (mTestmode && !intent.getBooleanExtra("testmode", false)) return; mLevel = (int)(100f * intent.getIntExtra(BatteryManager.EXTRA_LEVEL, 0) / intent.getIntExtra(BatteryManager.EXTRA_SCALE, 100)); mPluggedIn = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, 0) != 0; final int status = intent.getIntExtra(BatteryManager.EXTRA_STATUS, BatteryManager.BATTERY_STATUS_UNKNOWN); mCharged = status == BatteryManager.BATTERY_STATUS_FULL; mCharging = mCharged || status == BatteryManager.BATTERY_STATUS_CHARGING; fireBatteryLevelChanged(); } else if (action.equals(PowerManager.ACTION_POWER_SAVE_MODE_CHANGED)) { updatePowerSave(); } else if (action.equals(PowerManager.ACTION_POWER_SAVE_MODE_CHANGING)) { setPowerSave(intent.getBooleanExtra(PowerManager.EXTRA_POWER_SAVE_MODE, false)); } else if (action.equals(ACTION_LEVEL_TEST)) { mTestmode = true; mHandler.post(new Runnable() { int curLevel = 0; int incr = 1; int saveLevel = mLevel; boolean savePlugged = mPluggedIn; Intent dummy = new Intent(Intent.ACTION_BATTERY_CHANGED); @Override public void run() { if (curLevel < 0) { mTestmode = false; dummy.putExtra("level", saveLevel); dummy.putExtra("plugged", savePlugged); dummy.putExtra("testmode", false); } else { dummy.putExtra("level", curLevel); dummy.putExtra("plugged", incr > 0 ? BatteryManager.BATTERY_PLUGGED_AC : 0); dummy.putExtra("testmode", true); } context.sendBroadcast(dummy); if (!mTestmode) return; curLevel += incr; if (curLevel == 100) { incr *= -1; } mHandler.postDelayed(this, 200); } }); } } public boolean isPowerSave() { return mPowerSave; } private void updatePowerSave() { setPowerSave(mPowerManager.isPowerSaveMode()); } public interface BatteryController { /** * Prints the current state of the {@link BatteryController} to the given {@link PrintWriter}. */ void dump(FileDescriptor fd, PrintWriter pw, String[] args); private void setPowerSave(boolean powerSave) { if (powerSave == mPowerSave) return; mPowerSave = powerSave; if (DEBUG) Log.d(TAG, "Power save is " + (mPowerSave ? "on" : "off")); firePowerSaveChanged(); } /** * Sets if the current device is in power save mode. */ void setPowerSaveMode(boolean powerSave); private void fireBatteryLevelChanged() { final int N = mChangeCallbacks.size(); for (int i = 0; i < N; i++) { mChangeCallbacks.get(i).onBatteryLevelChanged(mLevel, mPluggedIn, mCharging); } } /** * Returns {@code true} if the device is currently in power save mode. */ boolean isPowerSave(); private void firePowerSaveChanged() { final int N = mChangeCallbacks.size(); for (int i = 0; i < N; i++) { mChangeCallbacks.get(i).onPowerSaveChanged(mPowerSave); } } void addStateChangedCallback(BatteryStateChangeCallback cb); void removeStateChangedCallback(BatteryStateChangeCallback cb); public interface BatteryStateChangeCallback { /** * A listener that will be notified whenever a change in battery level or power save mode * has occurred. */ interface BatteryStateChangeCallback { void onBatteryLevelChanged(int level, boolean pluggedIn, boolean charging); void onPowerSaveChanged(boolean isPowerSave); } Loading
packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerImpl.java 0 → 100644 +179 −0 File added.Preview size limit exceeded, changes collapsed. Show changes