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