1 /* 2 * Copyright (C) 2017 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 android.car.storagemonitoring; 17 18 import android.annotation.RequiresPermission; 19 import android.annotation.SystemApi; 20 import android.car.Car; 21 import android.car.CarManagerBase; 22 import android.car.annotation.RequiredFeature; 23 import android.os.IBinder; 24 import android.os.RemoteException; 25 26 import com.android.car.internal.SingleMessageHandler; 27 28 import java.lang.ref.WeakReference; 29 import java.util.Collections; 30 import java.util.HashSet; 31 import java.util.List; 32 import java.util.Set; 33 34 /** 35 * API for retrieving information and metrics about the flash storage. 36 * 37 * @hide 38 */ 39 @SystemApi 40 @RequiredFeature(Car.STORAGE_MONITORING_SERVICE) 41 public final class CarStorageMonitoringManager extends CarManagerBase { 42 private static final String TAG = CarStorageMonitoringManager.class.getSimpleName(); 43 private static final int MSG_IO_STATS_EVENT = 0; 44 45 private final ICarStorageMonitoring mService; 46 private ListenerToService mListenerToService; 47 private final SingleMessageHandler<IoStats> mMessageHandler; 48 private final Set<IoStatsListener> mListeners = new HashSet<>(); 49 50 /** 51 * Implementers will be notified on every new I/O activity calculated stats. 52 * 53 * @deprecated use {@link android.car.watchdog.CarWatchdogManager} and its related classes 54 * for I/O related tasks. 55 */ 56 @Deprecated 57 public interface IoStatsListener { 58 59 /** 60 * Invoked when a new periodic snapshot delta of I/O activities is calculated. 61 */ onSnapshot(IoStats snapshot)62 void onSnapshot(IoStats snapshot); 63 } 64 65 private static final class ListenerToService extends IIoStatsListener.Stub { 66 private final WeakReference<CarStorageMonitoringManager> mManager; 67 ListenerToService(CarStorageMonitoringManager manager)68 ListenerToService(CarStorageMonitoringManager manager) { 69 mManager = new WeakReference<>(manager); 70 } 71 72 @Override onSnapshot(IoStats snapshot)73 public void onSnapshot(IoStats snapshot) { 74 CarStorageMonitoringManager manager = mManager.get(); 75 if (manager != null) { 76 manager.mMessageHandler.sendEvents(Collections.singletonList(snapshot)); 77 } 78 } 79 } 80 81 public static final String INTENT_EXCESSIVE_IO = "android.car.storagemonitoring.EXCESSIVE_IO"; 82 83 public static final int PRE_EOL_INFO_UNKNOWN = 0; 84 public static final int PRE_EOL_INFO_NORMAL = 1; 85 public static final int PRE_EOL_INFO_WARNING = 2; 86 public static final int PRE_EOL_INFO_URGENT = 3; 87 88 public static final long SHUTDOWN_COST_INFO_MISSING = -1; 89 90 /** 91 * @hide 92 */ CarStorageMonitoringManager(Car car, IBinder service)93 public CarStorageMonitoringManager(Car car, IBinder service) { 94 super(car); 95 mService = ICarStorageMonitoring.Stub.asInterface(service); 96 mMessageHandler = new SingleMessageHandler<IoStats>(getEventHandler(), MSG_IO_STATS_EVENT) { 97 @Override 98 protected void handleEvent(IoStats event) { 99 for (IoStatsListener listener : mListeners) { 100 listener.onSnapshot(event); 101 } 102 } 103 }; 104 } 105 106 /** 107 * @hide 108 */ 109 @Override onCarDisconnected()110 public void onCarDisconnected() { 111 mListeners.clear(); 112 mListenerToService = null; 113 } 114 115 // ICarStorageMonitoring forwards 116 117 /** 118 * This method returns the value of the "pre EOL" indicator for the flash storage 119 * as retrieved during the current boot cycle. 120 * 121 * It will return either PRE_EOL_INFO_UNKNOWN if the value can't be determined, 122 * or one of PRE_EOL_INFO_{NORMAL|WARNING|URGENT} depending on the device state. 123 */ 124 @RequiresPermission(value = Car.PERMISSION_STORAGE_MONITORING) getPreEolIndicatorStatus()125 public int getPreEolIndicatorStatus() { 126 try { 127 return mService.getPreEolIndicatorStatus(); 128 } catch (RemoteException e) { 129 return handleRemoteExceptionFromCarService(e, PRE_EOL_INFO_UNKNOWN); 130 } 131 } 132 133 /** 134 * This method returns the value of the wear estimate indicators for the flash storage 135 * as retrieved during the current boot cycle. 136 * 137 * The indicators are guaranteed to be a lower-bound on the actual wear of the storage. 138 * Current technology in common automotive usage offers estimates in 10% increments. 139 * 140 * If either or both indicators are not available, they will be reported as UNKNOWN. 141 * 142 * @deprecated wear estimate data is unreliable 143 */ 144 @Deprecated 145 @RequiresPermission(value = Car.PERMISSION_STORAGE_MONITORING) getWearEstimate()146 public WearEstimate getWearEstimate() { 147 try { 148 return mService.getWearEstimate(); 149 } catch (RemoteException e) { 150 return handleRemoteExceptionFromCarService(e, null); 151 } 152 } 153 154 /** 155 * This method returns a list of all changes in wear estimate indicators detected during the 156 * lifetime of the system. 157 * 158 * The indicators are not guaranteed to persist across a factory reset. 159 * 160 * The indicators are guaranteed to be a lower-bound on the actual wear of the storage. 161 * Current technology in common automotive usage offers estimates in 10% increments. 162 * 163 * If no indicators are available, an empty list will be returned. 164 * 165 * @deprecated wear estimate data is unreliable 166 */ 167 @Deprecated 168 @RequiresPermission(value = Car.PERMISSION_STORAGE_MONITORING) getWearEstimateHistory()169 public List<WearEstimateChange> getWearEstimateHistory() { 170 try { 171 return mService.getWearEstimateHistory(); 172 } catch (RemoteException e) { 173 return handleRemoteExceptionFromCarService(e, Collections.emptyList()); 174 } 175 } 176 177 /** 178 * This method returns a list of per user-id I/O activity metrics as collected at the end of 179 * system boot. 180 * 181 * The BOOT_COMPLETE broadcast is used as the trigger to collect this data. The implementation 182 * may impose an additional, and even variable across boot cycles, delay between the sending 183 * of the broadcast and the collection of the data. 184 * 185 * If the information is not available, an empty list will be returned. 186 * 187 * @deprecated use 188 * {@link android.car.watchdog.CarWatchdogManager#getResourceOveruseStats(int, int)} instead. 189 * WARNING: The metrics provided are aggregated through time and could include data retrieved 190 * after system boot. Also, the I/O stats are only for the calling package. 191 */ 192 @Deprecated 193 @RequiresPermission(value = Car.PERMISSION_STORAGE_MONITORING) getBootIoStats()194 public List<IoStatsEntry> getBootIoStats() { 195 try { 196 return mService.getBootIoStats(); 197 } catch (RemoteException e) { 198 return handleRemoteExceptionFromCarService(e, Collections.emptyList()); 199 } 200 } 201 202 /** 203 * This method returns an approximation of the number of bytes written to disk during 204 * the course of the previous system shutdown. 205 * 206 * <p>For purposes of this API the system shutdown is defined as starting when CarService 207 * receives the ACTION_SHUTDOWN or ACTION_REBOOT intent from the system.</p> 208 * 209 * <p>The information provided by this API does not provide attribution of the disk writes to 210 * specific applications or system daemons.</p> 211 * 212 * <p>The information returned by this call is a best effort guess, whose accuracy depends 213 * on the underlying file systems' ability to reliably track and accumulate 214 * disk write sizes.</p> 215 * 216 * <p>A corrupt file system, or one which was not cleanly unmounted during shutdown, may 217 * be unable to provide any information, or may provide incorrect data. While the API 218 * will attempt to detect these scenarios, the detection may fail and incorrect data 219 * may end up being used in calculations.</p> 220 * 221 * <p>If the information is not available, SHUTDOWN_COST_INFO_MISSING will be returned.</p>s 222 * 223 * @deprecated use 224 * {@link android.car.watchdog.CarWatchdogManager#getResourceOveruseStats(int, int)} instead. 225 * WARNING: The metrics provided are aggregated through time and could include data not related 226 * to system shutdown. Also, the I/O stats are only for the calling package. 227 */ 228 @Deprecated 229 @RequiresPermission(value = Car.PERMISSION_STORAGE_MONITORING) getShutdownDiskWriteAmount()230 public long getShutdownDiskWriteAmount() { 231 try { 232 return mService.getShutdownDiskWriteAmount(); 233 } catch (RemoteException e) { 234 return handleRemoteExceptionFromCarService(e, 0); 235 } 236 } 237 238 /** 239 * This method returns a list of per user-id I/O activity metrics as collected from kernel 240 * start until the last snapshot. 241 * 242 * The samples provided might be as old as the value of the ioStatsRefreshRateSeconds setting. 243 * 244 * If the information is not available, an empty list will be returned. 245 * 246 * @deprecated use 247 * {@link android.car.watchdog.CarWatchdogManager#getResourceOveruseStats(int, int)} instead. 248 * WARNING: The I/O stats returned are only for the calling package. 249 */ 250 @Deprecated 251 @RequiresPermission(value = Car.PERMISSION_STORAGE_MONITORING) getAggregateIoStats()252 public List<IoStatsEntry> getAggregateIoStats() { 253 try { 254 return mService.getAggregateIoStats(); 255 } catch (RemoteException e) { 256 return handleRemoteExceptionFromCarService(e, Collections.emptyList()); 257 } 258 } 259 260 /** 261 * This method returns a list of the I/O stats deltas currently stored by the system. 262 * 263 * Periodically, the system gathers I/O activity metrics and computes and stores a delta from 264 * the previous cycle. The timing and the number of these stored samples are configurable 265 * by the OEM. 266 * 267 * The samples are returned in order from the oldest to the newest. 268 * 269 * If the information is not available, an empty list will be returned. 270 * 271 * @deprecated use 272 * {@link android.car.watchdog.CarWatchdogManager#getResourceOveruseStats(int, int)} instead. 273 * WARNING: The I/O stats returned are only for the calling package. 274 */ 275 @Deprecated 276 @RequiresPermission(value = Car.PERMISSION_STORAGE_MONITORING) getIoStatsDeltas()277 public List<IoStats> getIoStatsDeltas() { 278 try { 279 return mService.getIoStatsDeltas(); 280 } catch (RemoteException e) { 281 return handleRemoteExceptionFromCarService(e, Collections.emptyList()); 282 } 283 } 284 285 /** 286 * This method registers a new listener to receive I/O stats deltas. 287 * 288 * The system periodically gathers I/O activity metrics and computes a delta of such 289 * activity. Registered listeners will receive those deltas as they are available. 290 * 291 * The timing of availability of the deltas is configurable by the OEM. 292 * 293 * @deprecated {@link IIoStatsListener} is deprecated. Use 294 * {@link android.car.watchdog.CarWatchdogManager#getResourceOveruseStats(int, int)} to obtain 295 * I/O usage metrics or 296 * {@link android.car.watchdog.CarWatchdogManager#addResourceOveruseListener( 297 * java.util.concurrent.Executor, int, 298 * android.car.watchdog.CarWatchdogManager.ResourceOveruseListener)} to be alerted when the 299 * package either overuses I/O storage or is about to overuse I/O storage. 300 * WARNING: The I/O stats returned are only for the calling package. 301 */ 302 @Deprecated 303 @RequiresPermission(value = Car.PERMISSION_STORAGE_MONITORING) registerListener(IoStatsListener listener)304 public void registerListener(IoStatsListener listener) { 305 try { 306 if (mListeners.isEmpty()) { 307 if (mListenerToService == null) { 308 mListenerToService = new ListenerToService(this); 309 } 310 mService.registerListener(mListenerToService); 311 } 312 mListeners.add(listener); 313 } catch (RemoteException e) { 314 handleRemoteExceptionFromCarService(e); 315 } 316 } 317 318 /** 319 * This method removes a registered listener of I/O stats deltas. 320 * 321 * @deprecated see {@link CarStorageMonitoringManager#registerListener(IoStatsListener)} 322 */ 323 @Deprecated 324 @RequiresPermission(value = Car.PERMISSION_STORAGE_MONITORING) unregisterListener(IoStatsListener listener)325 public void unregisterListener(IoStatsListener listener) { 326 try { 327 if (!mListeners.remove(listener)) { 328 return; 329 } 330 if (mListeners.isEmpty()) { 331 mService.unregisterListener(mListenerToService); 332 mListenerToService = null; 333 } 334 } catch (RemoteException e) { 335 handleRemoteExceptionFromCarService(e); 336 } 337 } 338 } 339