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