• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package com.android.systemui.battery;
17 
18 import static android.provider.Settings.System.SHOW_BATTERY_PERCENT;
19 
20 import android.content.ContentResolver;
21 import android.content.Context;
22 import android.database.ContentObserver;
23 import android.net.Uri;
24 import android.os.Handler;
25 import android.os.HandlerExecutor;
26 import android.provider.Settings;
27 import android.text.TextUtils;
28 import android.util.ArraySet;
29 import android.view.View;
30 
31 import androidx.annotation.NonNull;
32 
33 import com.android.systemui.dagger.qualifiers.Main;
34 import com.android.systemui.flags.FeatureFlags;
35 import com.android.systemui.flags.Flags;
36 import com.android.systemui.settings.UserTracker;
37 import com.android.systemui.statusbar.phone.StatusBarIconController;
38 import com.android.systemui.statusbar.policy.BatteryController;
39 import com.android.systemui.statusbar.policy.ConfigurationController;
40 import com.android.systemui.tuner.TunerService;
41 import com.android.systemui.util.ViewController;
42 
43 import javax.inject.Inject;
44 
45 /** Controller for {@link BatteryMeterView}. **/
46 public class BatteryMeterViewController extends ViewController<BatteryMeterView> {
47     private final ConfigurationController mConfigurationController;
48     private final TunerService mTunerService;
49     private final Handler mMainHandler;
50     private final ContentResolver mContentResolver;
51     private final BatteryController mBatteryController;
52 
53     private final String mSlotBattery;
54     private final SettingObserver mSettingObserver;
55     private final UserTracker mUserTracker;
56 
57     private final ConfigurationController.ConfigurationListener mConfigurationListener =
58             new ConfigurationController.ConfigurationListener() {
59                 @Override
60                 public void onDensityOrFontScaleChanged() {
61                     mView.scaleBatteryMeterViews();
62                 }
63             };
64 
65     private final TunerService.Tunable mTunable = new TunerService.Tunable() {
66         @Override
67         public void onTuningChanged(String key, String newValue) {
68             if (StatusBarIconController.ICON_HIDE_LIST.equals(key)) {
69                 ArraySet<String> icons = StatusBarIconController.getIconHideList(
70                         getContext(), newValue);
71                 mView.setVisibility(icons.contains(mSlotBattery) ? View.GONE : View.VISIBLE);
72             }
73         }
74     };
75 
76     private final BatteryController.BatteryStateChangeCallback mBatteryStateChangeCallback =
77             new BatteryController.BatteryStateChangeCallback() {
78                 @Override
79                 public void onBatteryLevelChanged(int level, boolean pluggedIn, boolean charging) {
80                     mView.onBatteryLevelChanged(level, pluggedIn);
81                 }
82 
83                 @Override
84                 public void onPowerSaveChanged(boolean isPowerSave) {
85                     mView.onPowerSaveChanged(isPowerSave);
86                 }
87 
88                 @Override
89                 public void onBatteryUnknownStateChanged(boolean isUnknown) {
90                     mView.onBatteryUnknownStateChanged(isUnknown);
91                 }
92 
93                 @Override
94                 public void onIsOverheatedChanged(boolean isOverheated) {
95                     mView.onIsOverheatedChanged(isOverheated);
96                 }
97             };
98 
99     private final UserTracker.Callback mUserChangedCallback =
100             new UserTracker.Callback() {
101                 @Override
102                 public void onUserChanged(int newUser, @NonNull Context userContext) {
103                     mContentResolver.unregisterContentObserver(mSettingObserver);
104                     registerShowBatteryPercentObserver(newUser);
105                     mView.updateShowPercent();
106                 }
107             };
108 
109     // Some places may need to show the battery conditionally, and not obey the tuner
110     private boolean mIgnoreTunerUpdates;
111     private boolean mIsSubscribedForTunerUpdates;
112 
113     @Inject
BatteryMeterViewController( BatteryMeterView view, UserTracker userTracker, ConfigurationController configurationController, TunerService tunerService, @Main Handler mainHandler, ContentResolver contentResolver, FeatureFlags featureFlags, BatteryController batteryController)114     public BatteryMeterViewController(
115             BatteryMeterView view,
116             UserTracker userTracker,
117             ConfigurationController configurationController,
118             TunerService tunerService,
119             @Main Handler mainHandler,
120             ContentResolver contentResolver,
121             FeatureFlags featureFlags,
122             BatteryController batteryController) {
123         super(view);
124         mUserTracker = userTracker;
125         mConfigurationController = configurationController;
126         mTunerService = tunerService;
127         mMainHandler = mainHandler;
128         mContentResolver = contentResolver;
129         mBatteryController = batteryController;
130 
131         mView.setBatteryEstimateFetcher(mBatteryController::getEstimatedTimeRemainingString);
132         mView.setDisplayShieldEnabled(featureFlags.isEnabled(Flags.BATTERY_SHIELD_ICON));
133 
134         mSlotBattery = getResources().getString(com.android.internal.R.string.status_bar_battery);
135         mSettingObserver = new SettingObserver(mMainHandler);
136     }
137 
138     @Override
onViewAttached()139     protected void onViewAttached() {
140         mConfigurationController.addCallback(mConfigurationListener);
141         subscribeForTunerUpdates();
142         mBatteryController.addCallback(mBatteryStateChangeCallback);
143 
144         registerShowBatteryPercentObserver(mUserTracker.getUserId());
145         registerGlobalBatteryUpdateObserver();
146         mUserTracker.addCallback(mUserChangedCallback, new HandlerExecutor(mMainHandler));
147 
148         mView.updateShowPercent();
149     }
150 
151     @Override
onViewDetached()152     protected void onViewDetached() {
153         mConfigurationController.removeCallback(mConfigurationListener);
154         unsubscribeFromTunerUpdates();
155         mBatteryController.removeCallback(mBatteryStateChangeCallback);
156 
157         mUserTracker.removeCallback(mUserChangedCallback);
158         mContentResolver.unregisterContentObserver(mSettingObserver);
159     }
160 
161     /**
162      * Turn off {@link BatteryMeterView}'s subscribing to the tuner for updates, and thus avoid it
163      * controlling its own visibility.
164      */
ignoreTunerUpdates()165     public void ignoreTunerUpdates() {
166         mIgnoreTunerUpdates = true;
167         unsubscribeFromTunerUpdates();
168     }
169 
subscribeForTunerUpdates()170     private void subscribeForTunerUpdates() {
171         if (mIsSubscribedForTunerUpdates || mIgnoreTunerUpdates) {
172             return;
173         }
174 
175         mTunerService.addTunable(mTunable, StatusBarIconController.ICON_HIDE_LIST);
176         mIsSubscribedForTunerUpdates = true;
177     }
178 
unsubscribeFromTunerUpdates()179     private void unsubscribeFromTunerUpdates() {
180         if (!mIsSubscribedForTunerUpdates) {
181             return;
182         }
183 
184         mTunerService.removeTunable(mTunable);
185         mIsSubscribedForTunerUpdates = false;
186     }
187 
registerShowBatteryPercentObserver(int user)188     private void registerShowBatteryPercentObserver(int user) {
189         mContentResolver.registerContentObserver(
190                 Settings.System.getUriFor(SHOW_BATTERY_PERCENT),
191                 false,
192                 mSettingObserver,
193                 user);
194     }
195 
registerGlobalBatteryUpdateObserver()196     private void registerGlobalBatteryUpdateObserver() {
197         mContentResolver.registerContentObserver(
198                 Settings.Global.getUriFor(Settings.Global.BATTERY_ESTIMATES_LAST_UPDATE_TIME),
199                 false,
200                 mSettingObserver);
201     }
202 
203     private final class SettingObserver extends ContentObserver {
SettingObserver(Handler handler)204         public SettingObserver(Handler handler) {
205             super(handler);
206         }
207 
208         @Override
onChange(boolean selfChange, Uri uri)209         public void onChange(boolean selfChange, Uri uri) {
210             super.onChange(selfChange, uri);
211             mView.updateShowPercent();
212             if (TextUtils.equals(uri.getLastPathSegment(),
213                     Settings.Global.BATTERY_ESTIMATES_LAST_UPDATE_TIME)) {
214                 // update the text for sure if the estimate in the cache was updated
215                 mView.updatePercentText();
216             }
217         }
218     }
219 }
220