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 package com.android.settings.fuelgauge.batteryusage; 17 18 import static com.android.settings.fuelgauge.BatteryBroadcastReceiver.BatteryUpdateType; 19 20 import android.app.Activity; 21 import android.content.Context; 22 import android.os.BatteryUsageStats; 23 import android.os.Bundle; 24 import android.os.UserManager; 25 import android.util.Log; 26 27 import androidx.annotation.IntDef; 28 import androidx.annotation.NonNull; 29 import androidx.annotation.VisibleForTesting; 30 import androidx.loader.app.LoaderManager; 31 import androidx.loader.content.Loader; 32 33 import com.android.settings.dashboard.DashboardFragment; 34 import com.android.settings.fuelgauge.BatteryBroadcastReceiver; 35 import com.android.settings.fuelgauge.BatteryUtils; 36 37 import java.lang.annotation.Retention; 38 import java.lang.annotation.RetentionPolicy; 39 40 /** 41 * Common base class for things that need to show the battery usage graph. 42 */ 43 public abstract class PowerUsageBase extends DashboardFragment { 44 private static final String TAG = "PowerUsageBase"; 45 46 @VisibleForTesting 47 static final String KEY_REFRESH_TYPE = "refresh_type"; 48 @VisibleForTesting 49 static final String KEY_INCLUDE_HISTORY = "include_history"; 50 @VisibleForTesting 51 BatteryUsageStats mBatteryUsageStats; 52 53 protected UserManager mUm; 54 protected boolean mIsBatteryPresent = true; 55 private BatteryBroadcastReceiver mBatteryBroadcastReceiver; 56 57 @VisibleForTesting 58 final BatteryUsageStatsLoaderCallbacks mBatteryUsageStatsLoaderCallbacks = 59 new BatteryUsageStatsLoaderCallbacks(); 60 61 @Retention(RetentionPolicy.SOURCE) 62 @IntDef({ 63 LoaderIndex.BATTERY_USAGE_STATS_LOADER, 64 LoaderIndex.BATTERY_INFO_LOADER, 65 LoaderIndex.BATTERY_TIP_LOADER, 66 LoaderIndex.BATTERY_HISTORY_LOADER 67 68 }) 69 public @interface LoaderIndex { 70 int BATTERY_USAGE_STATS_LOADER = 0; 71 int BATTERY_INFO_LOADER = 1; 72 int BATTERY_TIP_LOADER = 2; 73 int BATTERY_HISTORY_LOADER = 3; 74 } 75 76 @Override onAttach(Activity activity)77 public void onAttach(Activity activity) { 78 super.onAttach(activity); 79 mUm = (UserManager) activity.getSystemService(Context.USER_SERVICE); 80 } 81 82 @Override onCreate(Bundle icicle)83 public void onCreate(Bundle icicle) { 84 super.onCreate(icicle); 85 86 mBatteryBroadcastReceiver = new BatteryBroadcastReceiver(getContext()); 87 mBatteryBroadcastReceiver.setBatteryChangedListener(type -> { 88 if (type == BatteryBroadcastReceiver.BatteryUpdateType.BATTERY_NOT_PRESENT) { 89 mIsBatteryPresent = false; 90 } 91 restartBatteryStatsLoader(type); 92 }); 93 } 94 95 @Override onStart()96 public void onStart() { 97 super.onStart(); 98 mBatteryBroadcastReceiver.register(); 99 } 100 101 @Override onStop()102 public void onStop() { 103 super.onStop(); 104 mBatteryBroadcastReceiver.unRegister(); 105 closeBatteryUsageStatsIfNeeded(); 106 } 107 restartBatteryStatsLoader(int refreshType)108 protected void restartBatteryStatsLoader(int refreshType) { 109 final Bundle bundle = new Bundle(); 110 bundle.putInt(KEY_REFRESH_TYPE, refreshType); 111 bundle.putBoolean(KEY_INCLUDE_HISTORY, isBatteryHistoryNeeded()); 112 restartLoader(LoaderIndex.BATTERY_USAGE_STATS_LOADER, bundle, 113 mBatteryUsageStatsLoaderCallbacks); 114 } 115 getLoaderManagerForCurrentFragment()116 protected LoaderManager getLoaderManagerForCurrentFragment() { 117 return LoaderManager.getInstance(this); 118 } 119 restartLoader(int loaderId, Bundle bundle, LoaderManager.LoaderCallbacks<?> loaderCallbacks)120 protected void restartLoader(int loaderId, Bundle bundle, 121 LoaderManager.LoaderCallbacks<?> loaderCallbacks) { 122 LoaderManager loaderManager = getLoaderManagerForCurrentFragment(); 123 Loader<?> loader = loaderManager.getLoader( 124 loaderId); 125 if (loader != null && !loader.isReset()) { 126 loaderManager.restartLoader(loaderId, bundle, 127 loaderCallbacks); 128 } else { 129 loaderManager.initLoader(loaderId, bundle, 130 loaderCallbacks); 131 } 132 } 133 onLoadFinished(@atteryUpdateType int refreshType)134 protected void onLoadFinished(@BatteryUpdateType int refreshType) { 135 refreshUi(refreshType); 136 } 137 refreshUi(@atteryUpdateType int refreshType)138 protected abstract void refreshUi(@BatteryUpdateType int refreshType); 139 isBatteryHistoryNeeded()140 protected abstract boolean isBatteryHistoryNeeded(); 141 updatePreference(BatteryHistoryPreference historyPref)142 protected void updatePreference(BatteryHistoryPreference historyPref) { 143 final long startTime = System.currentTimeMillis(); 144 historyPref.setBatteryUsageStats(mBatteryUsageStats); 145 BatteryUtils.logRuntime(TAG, "updatePreference", startTime); 146 } 147 148 private class BatteryUsageStatsLoaderCallbacks 149 implements LoaderManager.LoaderCallbacks<BatteryUsageStats> { 150 private int mRefreshType; 151 152 @Override 153 @NonNull onCreateLoader(int id, Bundle args)154 public Loader<BatteryUsageStats> onCreateLoader(int id, Bundle args) { 155 mRefreshType = args.getInt(KEY_REFRESH_TYPE); 156 return new BatteryUsageStatsLoader(getContext(), args.getBoolean(KEY_INCLUDE_HISTORY)); 157 } 158 159 @Override onLoadFinished(Loader<BatteryUsageStats> loader, BatteryUsageStats batteryUsageStats)160 public void onLoadFinished(Loader<BatteryUsageStats> loader, 161 BatteryUsageStats batteryUsageStats) { 162 closeBatteryUsageStatsIfNeeded(); 163 mBatteryUsageStats = batteryUsageStats; 164 PowerUsageBase.this.onLoadFinished(mRefreshType); 165 } 166 167 @Override onLoaderReset(Loader<BatteryUsageStats> loader)168 public void onLoaderReset(Loader<BatteryUsageStats> loader) { 169 } 170 } 171 closeBatteryUsageStatsIfNeeded()172 private void closeBatteryUsageStatsIfNeeded() { 173 if (mBatteryUsageStats == null) { 174 return; 175 } 176 try { 177 mBatteryUsageStats.close(); 178 } catch (Exception e) { 179 Log.e(TAG, "BatteryUsageStats.close() failed", e); 180 } finally { 181 mBatteryUsageStats = null; 182 } 183 } 184 } 185