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