• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2009 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;
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.batterytip.BatteryTipLoader;
38 import com.android.settings.fuelgauge.batterytip.BatteryTipPreferenceController;
39 import com.android.settings.fuelgauge.batterytip.tips.BatteryTip;
40 import com.android.settings.overlay.FeatureFactory;
41 import com.android.settings.search.BaseSearchIndexProvider;
42 import com.android.settingslib.search.SearchIndexable;
43 import com.android.settingslib.widget.LayoutPreference;
44 
45 import java.util.List;
46 
47 /**
48  * Displays a list of apps and subsystems that consume power, ordered by how much power was consumed
49  * since the last time it was unplugged.
50  */
51 @SearchIndexable(forTarget = SearchIndexable.ALL & ~SearchIndexable.ARC)
52 public class PowerUsageSummary extends PowerUsageBase implements
53         BatteryTipPreferenceController.BatteryTipListener {
54 
55     static final String TAG = "PowerUsageSummary";
56 
57     @VisibleForTesting
58     static final String KEY_BATTERY_ERROR = "battery_help_message";
59     @VisibleForTesting
60     static final String KEY_BATTERY_USAGE = "battery_usage_summary";
61 
62     @VisibleForTesting
63     static final int BATTERY_INFO_LOADER = 1;
64     @VisibleForTesting
65     static final int BATTERY_TIP_LOADER = 2;
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         getLoaderManager().restartLoader(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(
258                 mPowerFeatureProvider.isChartGraphEnabled(getContext()) ?
259                         getString(R.string.advanced_battery_preference_summary_with_hours) :
260                         getString(R.string.advanced_battery_preference_summary));
261 
262         mHelpPreference = findPreference(KEY_BATTERY_ERROR);
263         mHelpPreference.setVisible(false);
264     }
265 
266     @VisibleForTesting
restartBatteryInfoLoader()267     void restartBatteryInfoLoader() {
268         if (getContext() == null) {
269             return;
270         }
271         // Skip restartBatteryInfoLoader if battery is not present.
272         if (!mIsBatteryPresent) {
273             return;
274         }
275         getLoaderManager().restartLoader(BATTERY_INFO_LOADER, Bundle.EMPTY,
276                 mBatteryInfoLoaderCallbacks);
277     }
278 
279     @VisibleForTesting
updateBatteryTipFlag(Bundle icicle)280     void updateBatteryTipFlag(Bundle icicle) {
281         mNeedUpdateBatteryTip = icicle == null || mBatteryTipPreferenceController.needUpdate();
282     }
283 
284     @Override
restartBatteryStatsLoader(@atteryUpdateType int refreshType)285     protected void restartBatteryStatsLoader(@BatteryUpdateType int refreshType) {
286         super.restartBatteryStatsLoader(refreshType);
287         // Update battery header if battery is present.
288         if (mIsBatteryPresent) {
289             mBatteryHeaderPreferenceController.quickUpdateHeaderPreference();
290         }
291     }
292 
293     @Override
onSaveInstanceState(Bundle outState)294     public void onSaveInstanceState(Bundle outState) {
295         super.onSaveInstanceState(outState);
296         mBatteryTipPreferenceController.saveInstanceState(outState);
297     }
298 
299     @Override
onBatteryTipHandled(BatteryTip batteryTip)300     public void onBatteryTipHandled(BatteryTip batteryTip) {
301         restartBatteryTipLoader();
302     }
303 
304     public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
305             new BaseSearchIndexProvider(R.xml.power_usage_summary);
306 }
307