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