• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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