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