• 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 
17 package android.app.usage;
18 
19 import static android.os.storage.StorageManager.convert;
20 
21 import android.annotation.BytesLong;
22 import android.annotation.NonNull;
23 import android.annotation.SystemService;
24 import android.annotation.TestApi;
25 import android.annotation.WorkerThread;
26 import android.content.Context;
27 import android.content.pm.ApplicationInfo;
28 import android.content.pm.PackageInfo;
29 import android.content.pm.PackageManager;
30 import android.os.ParcelableException;
31 import android.os.RemoteException;
32 import android.os.UserHandle;
33 import android.os.storage.StorageManager;
34 
35 import com.android.internal.util.Preconditions;
36 
37 import java.io.File;
38 import java.io.IOException;
39 import java.util.UUID;
40 
41 /**
42  * Access to detailed storage statistics. This provides a summary of how apps,
43  * users, and external/shared storage is utilizing disk space.
44  * <p class="note">
45  * Note: no permissions are required when calling these APIs for your own
46  * package or UID. However, requesting details for any other package requires
47  * the {@code android.Manifest.permission#PACKAGE_USAGE_STATS} permission, which
48  * is a system-level permission that will not be granted to normal apps.
49  * Declaring that permission expresses your intention to use this API and an end
50  * user can then choose to grant this permission through the Settings
51  * application.
52  * </p>
53  */
54 @SystemService(Context.STORAGE_STATS_SERVICE)
55 public class StorageStatsManager {
56     private final Context mContext;
57     private final IStorageStatsManager mService;
58 
59     /** {@hide} */
StorageStatsManager(Context context, IStorageStatsManager service)60     public StorageStatsManager(Context context, IStorageStatsManager service) {
61         mContext = Preconditions.checkNotNull(context);
62         mService = Preconditions.checkNotNull(service);
63     }
64 
65     /** {@hide} */
66     @TestApi
isQuotaSupported(@onNull UUID storageUuid)67     public boolean isQuotaSupported(@NonNull UUID storageUuid) {
68         try {
69             return mService.isQuotaSupported(convert(storageUuid), mContext.getOpPackageName());
70         } catch (RemoteException e) {
71             throw e.rethrowFromSystemServer();
72         }
73     }
74 
75     /** @removed */
76     @Deprecated
isQuotaSupported(String uuid)77     public boolean isQuotaSupported(String uuid) {
78         return isQuotaSupported(convert(uuid));
79     }
80 
81     /**
82      * Return the total size of the underlying physical media that is hosting
83      * this storage volume.
84      * <p>
85      * This value is best suited for visual display to end users, since it's
86      * designed to reflect the total storage size advertised in a retail
87      * environment.
88      * <p>
89      * Apps making logical decisions about disk space should always use
90      * {@link File#getTotalSpace()} instead of this value.
91      *
92      * @param storageUuid the UUID of the storage volume you're interested in,
93      *            such as {@link StorageManager#UUID_DEFAULT}.
94      * @throws IOException when the storage device isn't present.
95      */
96     @WorkerThread
getTotalBytes(@onNull UUID storageUuid)97     public @BytesLong long getTotalBytes(@NonNull UUID storageUuid) throws IOException {
98         try {
99             return mService.getTotalBytes(convert(storageUuid), mContext.getOpPackageName());
100         } catch (ParcelableException e) {
101             e.maybeRethrow(IOException.class);
102             throw new RuntimeException(e);
103         } catch (RemoteException e) {
104             throw e.rethrowFromSystemServer();
105         }
106     }
107 
108     /** @removed */
109     @Deprecated
getTotalBytes(String uuid)110     public long getTotalBytes(String uuid) throws IOException {
111         return getTotalBytes(convert(uuid));
112     }
113 
114     /**
115      * Return the free space on the requested storage volume.
116      * <p>
117      * This value is best suited for visual display to end users, since it's
118      * designed to reflect both unused space <em>and</em> and cached space that
119      * could be reclaimed by the system.
120      * <p>
121      * Apps making logical decisions about disk space should always use
122      * {@link StorageManager#getAllocatableBytes(UUID, int)} instead of this
123      * value.
124      *
125      * @param storageUuid the UUID of the storage volume you're interested in,
126      *            such as {@link StorageManager#UUID_DEFAULT}.
127      * @throws IOException when the storage device isn't present.
128      */
129     @WorkerThread
getFreeBytes(@onNull UUID storageUuid)130     public @BytesLong long getFreeBytes(@NonNull UUID storageUuid) throws IOException {
131         try {
132             return mService.getFreeBytes(convert(storageUuid), mContext.getOpPackageName());
133         } catch (ParcelableException e) {
134             e.maybeRethrow(IOException.class);
135             throw new RuntimeException(e);
136         } catch (RemoteException e) {
137             throw e.rethrowFromSystemServer();
138         }
139     }
140 
141     /** @removed */
142     @Deprecated
getFreeBytes(String uuid)143     public long getFreeBytes(String uuid) throws IOException {
144         return getFreeBytes(convert(uuid));
145     }
146 
147     /** {@hide} */
getCacheBytes(@onNull UUID storageUuid)148     public @BytesLong long getCacheBytes(@NonNull UUID storageUuid) throws IOException {
149         try {
150             return mService.getCacheBytes(convert(storageUuid), mContext.getOpPackageName());
151         } catch (ParcelableException e) {
152             e.maybeRethrow(IOException.class);
153             throw new RuntimeException(e);
154         } catch (RemoteException e) {
155             throw e.rethrowFromSystemServer();
156         }
157     }
158 
159     /** {@hide} */
160     @Deprecated
getCacheBytes(String uuid)161     public long getCacheBytes(String uuid) throws IOException {
162         return getCacheBytes(convert(uuid));
163     }
164 
165     /**
166      * Return storage statistics for a specific package on the requested storage
167      * volume.
168      * <p class="note">
169      * Note: no permissions are required when calling this API for your own
170      * package. However, requesting details for any other package requires the
171      * {@code android.Manifest.permission#PACKAGE_USAGE_STATS} permission, which
172      * is a system-level permission that will not be granted to normal apps.
173      * Declaring that permission expresses your intention to use this API and an
174      * end user can then choose to grant this permission through the Settings
175      * application.
176      * </p>
177      * <p class="note">
178      * Note: if the requested package uses the {@code android:sharedUserId}
179      * manifest feature, this call will be forced into a slower manual
180      * calculation path. If possible, consider always using
181      * {@link #queryStatsForUid(UUID, int)}, which is typically faster.
182      * </p>
183      *
184      * @param storageUuid the UUID of the storage volume you're interested in,
185      *            such as {@link StorageManager#UUID_DEFAULT}.
186      * @param packageName the package name you're interested in.
187      * @param user the user you're interested in.
188      * @throws PackageManager.NameNotFoundException when the requested package
189      *             name isn't installed for the requested user.
190      * @throws IOException when the storage device isn't present.
191      * @see ApplicationInfo#storageUuid
192      * @see PackageInfo#packageName
193      */
194     @WorkerThread
queryStatsForPackage(@onNull UUID storageUuid, @NonNull String packageName, @NonNull UserHandle user)195     public @NonNull StorageStats queryStatsForPackage(@NonNull UUID storageUuid,
196             @NonNull String packageName, @NonNull UserHandle user)
197             throws PackageManager.NameNotFoundException, IOException {
198         try {
199             return mService.queryStatsForPackage(convert(storageUuid), packageName,
200                     user.getIdentifier(), mContext.getOpPackageName());
201         } catch (ParcelableException e) {
202             e.maybeRethrow(PackageManager.NameNotFoundException.class);
203             e.maybeRethrow(IOException.class);
204             throw new RuntimeException(e);
205         } catch (RemoteException e) {
206             throw e.rethrowFromSystemServer();
207         }
208     }
209 
210     /** @removed */
211     @Deprecated
queryStatsForPackage(String uuid, String packageName, UserHandle user)212     public StorageStats queryStatsForPackage(String uuid, String packageName,
213             UserHandle user) throws PackageManager.NameNotFoundException, IOException {
214         return queryStatsForPackage(convert(uuid), packageName, user);
215     }
216 
217     /**
218      * Return storage statistics for a specific UID on the requested storage
219      * volume.
220      * <p class="note">
221      * Note: no permissions are required when calling this API for your own UID.
222      * However, requesting details for any other UID requires the
223      * {@code android.Manifest.permission#PACKAGE_USAGE_STATS} permission, which
224      * is a system-level permission that will not be granted to normal apps.
225      * Declaring that permission expresses your intention to use this API and an
226      * end user can then choose to grant this permission through the Settings
227      * application.
228      * </p>
229      *
230      * @param storageUuid the UUID of the storage volume you're interested in,
231      *            such as {@link StorageManager#UUID_DEFAULT}.
232      * @param uid the UID you're interested in.
233      * @throws IOException when the storage device isn't present.
234      * @see ApplicationInfo#storageUuid
235      * @see ApplicationInfo#uid
236      */
237     @WorkerThread
queryStatsForUid(@onNull UUID storageUuid, int uid)238     public @NonNull StorageStats queryStatsForUid(@NonNull UUID storageUuid, int uid)
239             throws IOException {
240         try {
241             return mService.queryStatsForUid(convert(storageUuid), uid,
242                     mContext.getOpPackageName());
243         } catch (ParcelableException e) {
244             e.maybeRethrow(IOException.class);
245             throw new RuntimeException(e);
246         } catch (RemoteException e) {
247             throw e.rethrowFromSystemServer();
248         }
249     }
250 
251     /** @removed */
252     @Deprecated
queryStatsForUid(String uuid, int uid)253     public StorageStats queryStatsForUid(String uuid, int uid) throws IOException {
254         return queryStatsForUid(convert(uuid), uid);
255     }
256 
257     /**
258      * Return storage statistics for a specific {@link UserHandle} on the
259      * requested storage volume.
260      * <p class="note">
261      * Note: this API requires the
262      * {@code android.Manifest.permission#PACKAGE_USAGE_STATS} permission, which
263      * is a system-level permission that will not be granted to normal apps.
264      * Declaring that permission expresses your intention to use this API and an
265      * end user can then choose to grant this permission through the Settings
266      * application.
267      * </p>
268      *
269      * @param storageUuid the UUID of the storage volume you're interested in,
270      *            such as {@link StorageManager#UUID_DEFAULT}.
271      * @param user the user you're interested in.
272      * @throws IOException when the storage device isn't present.
273      * @see android.os.Process#myUserHandle()
274      */
275     @WorkerThread
queryStatsForUser(@onNull UUID storageUuid, @NonNull UserHandle user)276     public @NonNull StorageStats queryStatsForUser(@NonNull UUID storageUuid,
277             @NonNull UserHandle user) throws IOException {
278         try {
279             return mService.queryStatsForUser(convert(storageUuid), user.getIdentifier(),
280                     mContext.getOpPackageName());
281         } catch (ParcelableException e) {
282             e.maybeRethrow(IOException.class);
283             throw new RuntimeException(e);
284         } catch (RemoteException e) {
285             throw e.rethrowFromSystemServer();
286         }
287     }
288 
289     /** @removed */
290     @Deprecated
queryStatsForUser(String uuid, UserHandle user)291     public StorageStats queryStatsForUser(String uuid, UserHandle user) throws IOException {
292         return queryStatsForUser(convert(uuid), user);
293     }
294 
295     /**
296      * Return shared/external storage statistics for a specific
297      * {@link UserHandle} on the requested storage volume.
298      * <p class="note">
299      * Note: this API requires the
300      * {@code android.Manifest.permission#PACKAGE_USAGE_STATS} permission, which
301      * is a system-level permission that will not be granted to normal apps.
302      * Declaring that permission expresses your intention to use this API and an
303      * end user can then choose to grant this permission through the Settings
304      * application.
305      * </p>
306      *
307      * @param storageUuid the UUID of the storage volume you're interested in,
308      *            such as {@link StorageManager#UUID_DEFAULT}.
309      * @throws IOException when the storage device isn't present.
310      * @see android.os.Process#myUserHandle()
311      */
312     @WorkerThread
queryExternalStatsForUser(@onNull UUID storageUuid, @NonNull UserHandle user)313     public @NonNull ExternalStorageStats queryExternalStatsForUser(@NonNull UUID storageUuid,
314             @NonNull UserHandle user) throws IOException {
315         try {
316             return mService.queryExternalStatsForUser(convert(storageUuid), user.getIdentifier(),
317                     mContext.getOpPackageName());
318         } catch (ParcelableException e) {
319             e.maybeRethrow(IOException.class);
320             throw new RuntimeException(e);
321         } catch (RemoteException e) {
322             throw e.rethrowFromSystemServer();
323         }
324     }
325 
326     /** @removed */
327     @Deprecated
queryExternalStatsForUser(String uuid, UserHandle user)328     public ExternalStorageStats queryExternalStatsForUser(String uuid, UserHandle user)
329             throws IOException {
330         return queryExternalStatsForUser(convert(uuid), user);
331     }
332 
333     /** {@hide} */
getCacheQuotaBytes(String volumeUuid, int uid)334     public long getCacheQuotaBytes(String volumeUuid, int uid) {
335         try {
336             return mService.getCacheQuotaBytes(volumeUuid, uid, mContext.getOpPackageName());
337         } catch (RemoteException e) {
338             throw e.rethrowFromSystemServer();
339         }
340     }
341 }
342