• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2022 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 
17 package com.android.settings.fuelgauge.batteryusage;
18 
19 import static com.android.settings.fuelgauge.BatteryBroadcastReceiver.BatteryUpdateType;
20 
21 import android.app.settings.SettingsEnums;
22 import android.content.Context;
23 import android.database.ContentObserver;
24 import android.net.Uri;
25 import android.os.Bundle;
26 import android.os.Handler;
27 import android.provider.Settings.Global;
28 
29 import androidx.annotation.VisibleForTesting;
30 import androidx.loader.app.LoaderManager;
31 import androidx.loader.content.Loader;
32 import androidx.preference.Preference;
33 
34 import com.android.settings.R;
35 import com.android.settings.SettingsActivity;
36 import com.android.settings.Utils;
37 import com.android.settings.fuelgauge.BatteryHeaderPreferenceController;
38 import com.android.settings.fuelgauge.BatteryInfo;
39 import com.android.settings.fuelgauge.BatteryInfoLoader;
40 import com.android.settings.fuelgauge.BatteryUtils;
41 import com.android.settings.fuelgauge.PowerUsageFeatureProvider;
42 import com.android.settings.fuelgauge.batterytip.BatteryTipLoader;
43 import com.android.settings.fuelgauge.batterytip.BatteryTipPreferenceController;
44 import com.android.settings.fuelgauge.batterytip.tips.BatteryTip;
45 import com.android.settings.overlay.FeatureFactory;
46 import com.android.settings.search.BaseSearchIndexProvider;
47 import com.android.settingslib.search.SearchIndexable;
48 
49 import java.util.List;
50 
51 /**
52  * Displays a list of apps and subsystems that consume power, ordered by how much power was consumed
53  * since the last time it was unplugged.
54  */
55 @SearchIndexable(forTarget = SearchIndexable.ALL & ~SearchIndexable.ARC)
56 public class PowerUsageSummary extends PowerUsageBase implements
57         BatteryTipPreferenceController.BatteryTipListener {
58 
59     static final String TAG = "PowerUsageSummary";
60 
61     @VisibleForTesting
62     static final String KEY_BATTERY_ERROR = "battery_help_message";
63     @VisibleForTesting
64     static final String KEY_BATTERY_USAGE = "battery_usage_summary";
65 
66     @VisibleForTesting
67     PowerUsageFeatureProvider mPowerFeatureProvider;
68     @VisibleForTesting
69     BatteryUtils mBatteryUtils;
70     @VisibleForTesting
71     BatteryInfo mBatteryInfo;
72 
73     @VisibleForTesting
74     BatteryHeaderPreferenceController mBatteryHeaderPreferenceController;
75     @VisibleForTesting
76     BatteryTipPreferenceController mBatteryTipPreferenceController;
77     @VisibleForTesting
78     boolean mNeedUpdateBatteryTip;
79     @VisibleForTesting
80     Preference mHelpPreference;
81     @VisibleForTesting
82     Preference mBatteryUsagePreference;
83 
84     @VisibleForTesting
85     final ContentObserver mSettingsObserver = new ContentObserver(new Handler()) {
86         @Override
87         public void onChange(boolean selfChange, Uri uri) {
88             restartBatteryInfoLoader();
89         }
90     };
91 
92     @VisibleForTesting
93     LoaderManager.LoaderCallbacks<BatteryInfo> mBatteryInfoLoaderCallbacks =
94             new LoaderManager.LoaderCallbacks<BatteryInfo>() {
95 
96                 @Override
97                 public Loader<BatteryInfo> onCreateLoader(int i, Bundle bundle) {
98                     return new BatteryInfoLoader(getContext());
99                 }
100 
101                 @Override
102                 public void onLoadFinished(Loader<BatteryInfo> loader, BatteryInfo batteryInfo) {
103                     mBatteryHeaderPreferenceController.updateHeaderPreference(batteryInfo);
104                     mBatteryHeaderPreferenceController.updateHeaderByBatteryTips(
105                             mBatteryTipPreferenceController.getCurrentBatteryTip(), batteryInfo);
106                     mBatteryInfo = batteryInfo;
107                 }
108 
109                 @Override
110                 public void onLoaderReset(Loader<BatteryInfo> loader) {
111                     // do nothing
112                 }
113             };
114 
115     private LoaderManager.LoaderCallbacks<List<BatteryTip>> mBatteryTipsCallbacks =
116             new LoaderManager.LoaderCallbacks<List<BatteryTip>>() {
117 
118                 @Override
119                 public Loader<List<BatteryTip>> onCreateLoader(int id, Bundle args) {
120                     return new BatteryTipLoader(getContext(), mBatteryUsageStats);
121                 }
122 
123                 @Override
124                 public void onLoadFinished(Loader<List<BatteryTip>> loader,
125                         List<BatteryTip> data) {
126                     mBatteryTipPreferenceController.updateBatteryTips(data);
127                     mBatteryHeaderPreferenceController.updateHeaderByBatteryTips(
128                             mBatteryTipPreferenceController.getCurrentBatteryTip(), mBatteryInfo);
129                 }
130 
131                 @Override
132                 public void onLoaderReset(Loader<List<BatteryTip>> loader) {
133 
134                 }
135             };
136 
137     @Override
onAttach(Context context)138     public void onAttach(Context context) {
139         super.onAttach(context);
140         final SettingsActivity activity = (SettingsActivity) getActivity();
141 
142         mBatteryHeaderPreferenceController = use(BatteryHeaderPreferenceController.class);
143         mBatteryHeaderPreferenceController.setActivity(activity);
144         mBatteryHeaderPreferenceController.setFragment(this);
145         mBatteryHeaderPreferenceController.setLifecycle(getSettingsLifecycle());
146 
147         mBatteryTipPreferenceController = use(BatteryTipPreferenceController.class);
148         mBatteryTipPreferenceController.setActivity(activity);
149         mBatteryTipPreferenceController.setFragment(this);
150         mBatteryTipPreferenceController.setBatteryTipListener(this::onBatteryTipHandled);
151     }
152 
153     @Override
onCreate(Bundle icicle)154     public void onCreate(Bundle icicle) {
155         super.onCreate(icicle);
156         setAnimationAllowed(true);
157 
158         initFeatureProvider();
159         initPreference();
160 
161         mBatteryUtils = BatteryUtils.getInstance(getContext());
162 
163         if (Utils.isBatteryPresent(getContext())) {
164             restartBatteryInfoLoader();
165         } else {
166             // Present help preference when battery is unavailable.
167             mHelpPreference.setVisible(true);
168         }
169         mBatteryTipPreferenceController.restoreInstanceState(icicle);
170         updateBatteryTipFlag(icicle);
171     }
172 
173     @Override
onResume()174     public void onResume() {
175         super.onResume();
176         getContentResolver().registerContentObserver(
177                 Global.getUriFor(Global.BATTERY_ESTIMATES_LAST_UPDATE_TIME),
178                 false,
179                 mSettingsObserver);
180     }
181 
182     @Override
onPause()183     public void onPause() {
184         getContentResolver().unregisterContentObserver(mSettingsObserver);
185         super.onPause();
186     }
187 
188     @Override
getMetricsCategory()189     public int getMetricsCategory() {
190         return SettingsEnums.FUELGAUGE_POWER_USAGE_SUMMARY_V2;
191     }
192 
193     @Override
getLogTag()194     protected String getLogTag() {
195         return TAG;
196     }
197 
198     @Override
getPreferenceScreenResId()199     protected int getPreferenceScreenResId() {
200         return R.xml.power_usage_summary;
201     }
202 
203     @Override
getHelpResource()204     public int getHelpResource() {
205         return R.string.help_url_battery;
206     }
207 
refreshUi(@atteryUpdateType int refreshType)208     protected void refreshUi(@BatteryUpdateType int refreshType) {
209         final Context context = getContext();
210         if (context == null) {
211             return;
212         }
213         // Skip refreshing UI if battery is not present.
214         if (!mIsBatteryPresent) {
215             return;
216         }
217 
218         // Skip BatteryTipLoader if device is rotated or only battery level change
219         if (mNeedUpdateBatteryTip
220                 && refreshType != BatteryUpdateType.BATTERY_LEVEL) {
221             restartBatteryTipLoader();
222         } else {
223             mNeedUpdateBatteryTip = true;
224         }
225         // reload BatteryInfo and updateUI
226         restartBatteryInfoLoader();
227     }
228 
229     @VisibleForTesting
restartBatteryTipLoader()230     void restartBatteryTipLoader() {
231         restartLoader(LoaderIndex.BATTERY_TIP_LOADER, Bundle.EMPTY, mBatteryTipsCallbacks);
232     }
233 
234     @VisibleForTesting
initFeatureProvider()235     void initFeatureProvider() {
236         final Context context = getContext();
237         mPowerFeatureProvider = FeatureFactory.getFactory(context)
238                 .getPowerUsageFeatureProvider(context);
239     }
240 
241     @VisibleForTesting
initPreference()242     void initPreference() {
243         mBatteryUsagePreference = findPreference(KEY_BATTERY_USAGE);
244         mBatteryUsagePreference.setSummary(getString(R.string.advanced_battery_preference_summary));
245         mBatteryUsagePreference.setVisible(
246                 mPowerFeatureProvider.isBatteryUsageEnabled());
247 
248         mHelpPreference = findPreference(KEY_BATTERY_ERROR);
249         mHelpPreference.setVisible(false);
250     }
251 
252     @VisibleForTesting
restartBatteryInfoLoader()253     void restartBatteryInfoLoader() {
254         if (getContext() == null) {
255             return;
256         }
257         // Skip restartBatteryInfoLoader if battery is not present.
258         if (!mIsBatteryPresent) {
259             return;
260         }
261         restartLoader(LoaderIndex.BATTERY_INFO_LOADER, Bundle.EMPTY, mBatteryInfoLoaderCallbacks);
262     }
263 
264     @VisibleForTesting
updateBatteryTipFlag(Bundle icicle)265     void updateBatteryTipFlag(Bundle icicle) {
266         mNeedUpdateBatteryTip = icicle == null || mBatteryTipPreferenceController.needUpdate();
267     }
268 
269     @Override
restartBatteryStatsLoader(@atteryUpdateType int refreshType)270     protected void restartBatteryStatsLoader(@BatteryUpdateType int refreshType) {
271         super.restartBatteryStatsLoader(refreshType);
272         // Update battery header if battery is present.
273         if (mIsBatteryPresent) {
274             mBatteryHeaderPreferenceController.quickUpdateHeaderPreference();
275         }
276     }
277 
278     @Override
onSaveInstanceState(Bundle outState)279     public void onSaveInstanceState(Bundle outState) {
280         super.onSaveInstanceState(outState);
281         mBatteryTipPreferenceController.saveInstanceState(outState);
282     }
283 
284     @Override
onBatteryTipHandled(BatteryTip batteryTip)285     public void onBatteryTipHandled(BatteryTip batteryTip) {
286         restartBatteryTipLoader();
287     }
288 
289     public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
290             new BaseSearchIndexProvider(R.xml.power_usage_summary);
291 }
292