blob: 903060701fc3d97fe497bc754ee0d3bfc2bc6007 [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
2 * Copyright (C) 2007 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
17package android.os;
18
San Mehatb1043402010-02-05 08:26:50 -080019import android.os.storage.IMountService;
Jeff Sharkeyb049e212012-09-07 23:16:01 -070020import android.os.storage.StorageManager;
Mike Lockwood2f6a3882011-05-09 19:08:06 -070021import android.os.storage.StorageVolume;
Jeff Sharkeyb049e212012-09-07 23:16:01 -070022import android.text.TextUtils;
Kenny Rootb2278dc2011-01-18 13:03:28 -080023import android.util.Log;
San Mehat7fd0fee2009-12-17 07:12:23 -080024
Gilles Debunneee1d6302011-05-13 10:09:32 -070025import java.io.File;
26
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080027/**
28 * Provides access to environment variables.
29 */
30public class Environment {
Kenny Rootb2278dc2011-01-18 13:03:28 -080031 private static final String TAG = "Environment";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080032
Jeff Sharkeyb049e212012-09-07 23:16:01 -070033 private static final String ENV_EXTERNAL_STORAGE = "EXTERNAL_STORAGE";
Jeff Sharkey4fbbda42012-09-24 18:34:07 -070034 private static final String ENV_EMULATED_STORAGE_SOURCE = "EMULATED_STORAGE_SOURCE";
Jeff Sharkeyb049e212012-09-07 23:16:01 -070035 private static final String ENV_EMULATED_STORAGE_TARGET = "EMULATED_STORAGE_TARGET";
Jeff Sharkey3fe5bf62012-09-18 15:54:52 -070036 private static final String ENV_MEDIA_STORAGE = "MEDIA_STORAGE";
Jeff Sharkeyb049e212012-09-07 23:16:01 -070037
Jeff Sharkeydfa45302012-09-12 16:25:22 -070038 /** {@hide} */
39 public static String DIRECTORY_ANDROID = "Android";
40
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080041 private static final File ROOT_DIRECTORY
42 = getDirectory("ANDROID_ROOT", "/system");
43
Oscar Montemayora8529f62009-11-18 10:14:20 -080044 private static final String SYSTEM_PROPERTY_EFS_ENABLED = "persist.security.efs.enabled";
45
Jeff Sharkeyb049e212012-09-07 23:16:01 -070046 private static UserEnvironment sCurrentUser;
Kenny Roote1ff2142010-10-12 11:20:01 -070047
Jeff Sharkeyb049e212012-09-07 23:16:01 -070048 private static final Object sLock = new Object();
49
50 // @GuardedBy("sLock")
51 private static volatile StorageVolume sPrimaryVolume;
Mike Lockwood2f6a3882011-05-09 19:08:06 -070052
53 private static StorageVolume getPrimaryVolume() {
Jeff Sharkeyb049e212012-09-07 23:16:01 -070054 if (sPrimaryVolume == null) {
55 synchronized (sLock) {
56 if (sPrimaryVolume == null) {
Mike Lockwood2f6a3882011-05-09 19:08:06 -070057 try {
58 IMountService mountService = IMountService.Stub.asInterface(ServiceManager
59 .getService("mount"));
Jeff Sharkeyb049e212012-09-07 23:16:01 -070060 final StorageVolume[] volumes = mountService.getVolumeList();
61 sPrimaryVolume = StorageManager.getPrimaryVolume(volumes);
Mike Lockwood2f6a3882011-05-09 19:08:06 -070062 } catch (Exception e) {
63 Log.e(TAG, "couldn't talk to MountService", e);
64 }
65 }
66 }
67 }
Jeff Sharkeyb049e212012-09-07 23:16:01 -070068 return sPrimaryVolume;
69 }
70
71 static {
72 initForCurrentUser();
73 }
74
75 /** {@hide} */
76 public static void initForCurrentUser() {
77 final int userId = UserHandle.myUserId();
78 sCurrentUser = new UserEnvironment(userId);
79
80 synchronized (sLock) {
81 sPrimaryVolume = null;
82 }
83 }
84
85 /** {@hide} */
86 public static class UserEnvironment {
87 // TODO: generalize further to create package-specific environment
88
89 private final File mExternalStorage;
90 private final File mExternalStorageAndroidData;
91 private final File mExternalStorageAndroidMedia;
92 private final File mExternalStorageAndroidObb;
Jeff Sharkey3fe5bf62012-09-18 15:54:52 -070093 private final File mMediaStorage;
Jeff Sharkeyb049e212012-09-07 23:16:01 -070094
95 public UserEnvironment(int userId) {
96 // See storage config details at http://source.android.com/tech/storage/
97 String rawExternalStorage = System.getenv(ENV_EXTERNAL_STORAGE);
98 String rawEmulatedStorageTarget = System.getenv(ENV_EMULATED_STORAGE_TARGET);
Jeff Sharkey3fe5bf62012-09-18 15:54:52 -070099 String rawMediaStorage = System.getenv(ENV_MEDIA_STORAGE);
100 if (TextUtils.isEmpty(rawMediaStorage)) {
101 rawMediaStorage = "/data/media";
102 }
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700103
104 if (!TextUtils.isEmpty(rawEmulatedStorageTarget)) {
105 // Device has emulated storage; external storage paths should have
106 // userId burned into them.
Jeff Sharkey3fe5bf62012-09-18 15:54:52 -0700107 final String rawUserId = Integer.toString(userId);
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700108 final File emulatedBase = new File(rawEmulatedStorageTarget);
Jeff Sharkey3fe5bf62012-09-18 15:54:52 -0700109 final File mediaBase = new File(rawMediaStorage);
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700110
111 // /storage/emulated/0
Jeff Sharkey3fe5bf62012-09-18 15:54:52 -0700112 mExternalStorage = buildPath(emulatedBase, rawUserId);
Jeff Sharkey3fe5bf62012-09-18 15:54:52 -0700113 // /data/media/0
114 mMediaStorage = buildPath(mediaBase, rawUserId);
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700115
116 } else {
117 // Device has physical external storage; use plain paths.
118 if (TextUtils.isEmpty(rawExternalStorage)) {
119 Log.w(TAG, "EXTERNAL_STORAGE undefined; falling back to default");
120 rawExternalStorage = "/storage/sdcard0";
121 }
122
123 // /storage/sdcard0
124 mExternalStorage = new File(rawExternalStorage);
Jeff Sharkey3fe5bf62012-09-18 15:54:52 -0700125 // /data/media
126 mMediaStorage = new File(rawMediaStorage);
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700127 }
128
Jeff Sharkey7d8bcb42012-09-24 13:03:35 -0700129 mExternalStorageAndroidObb = buildPath(mExternalStorage, DIRECTORY_ANDROID, "obb");
Jeff Sharkeydfa45302012-09-12 16:25:22 -0700130 mExternalStorageAndroidData = buildPath(mExternalStorage, DIRECTORY_ANDROID, "data");
131 mExternalStorageAndroidMedia = buildPath(mExternalStorage, DIRECTORY_ANDROID, "media");
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700132 }
133
134 public File getExternalStorageDirectory() {
135 return mExternalStorage;
136 }
137
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700138 public File getExternalStorageObbDirectory() {
139 return mExternalStorageAndroidObb;
140 }
141
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700142 public File getExternalStoragePublicDirectory(String type) {
143 return new File(mExternalStorage, type);
144 }
145
146 public File getExternalStorageAndroidDataDir() {
147 return mExternalStorageAndroidData;
148 }
149
150 public File getExternalStorageAppDataDirectory(String packageName) {
151 return new File(mExternalStorageAndroidData, packageName);
152 }
153
154 public File getExternalStorageAppMediaDirectory(String packageName) {
155 return new File(mExternalStorageAndroidMedia, packageName);
156 }
157
158 public File getExternalStorageAppObbDirectory(String packageName) {
159 return new File(mExternalStorageAndroidObb, packageName);
160 }
161
162 public File getExternalStorageAppFilesDirectory(String packageName) {
163 return new File(new File(mExternalStorageAndroidData, packageName), "files");
164 }
165
166 public File getExternalStorageAppCacheDirectory(String packageName) {
167 return new File(new File(mExternalStorageAndroidData, packageName), "cache");
168 }
Jeff Sharkey3fe5bf62012-09-18 15:54:52 -0700169
170 public File getMediaStorageDirectory() {
171 return mMediaStorage;
172 }
Mike Lockwood2f6a3882011-05-09 19:08:06 -0700173 }
San Mehat7fd0fee2009-12-17 07:12:23 -0800174
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800175 /**
176 * Gets the Android root directory.
177 */
178 public static File getRootDirectory() {
179 return ROOT_DIRECTORY;
180 }
181
Jason parksa3cdaa52011-01-13 14:15:43 -0600182 /**
183 * Gets the system directory available for secure storage.
184 * If Encrypted File system is enabled, it returns an encrypted directory (/data/secure/system).
185 * Otherwise, it returns the unencrypted /data/system directory.
186 * @return File object representing the secure storage system directory.
187 * @hide
188 */
189 public static File getSystemSecureDirectory() {
190 if (isEncryptedFilesystemEnabled()) {
191 return new File(SECURE_DATA_DIRECTORY, "system");
192 } else {
193 return new File(DATA_DIRECTORY, "system");
194 }
195 }
196
197 /**
198 * Gets the data directory for secure storage.
199 * If Encrypted File system is enabled, it returns an encrypted directory (/data/secure).
200 * Otherwise, it returns the unencrypted /data directory.
201 * @return File object representing the data directory for secure storage.
202 * @hide
203 */
204 public static File getSecureDataDirectory() {
205 if (isEncryptedFilesystemEnabled()) {
206 return SECURE_DATA_DIRECTORY;
207 } else {
208 return DATA_DIRECTORY;
209 }
210 }
211
212 /**
Jeff Sharkeyd525baa2012-05-22 18:25:32 -0700213 * Return directory used for internal media storage, which is protected by
214 * {@link android.Manifest.permission#WRITE_MEDIA_STORAGE}.
215 *
216 * @hide
217 */
218 public static File getMediaStorageDirectory() {
Jeff Sharkey3fe5bf62012-09-18 15:54:52 -0700219 throwIfSystem();
220 return sCurrentUser.getMediaStorageDirectory();
Jeff Sharkeyd525baa2012-05-22 18:25:32 -0700221 }
222
223 /**
Amith Yamasani61f57372012-08-31 12:12:28 -0700224 * Return the system directory for a user. This is for use by system services to store
225 * files relating to the user. This directory will be automatically deleted when the user
226 * is removed.
227 *
228 * @hide
229 */
230 public static File getUserSystemDirectory(int userId) {
231 return new File(new File(getSystemSecureDirectory(), "users"), Integer.toString(userId));
232 }
233
234 /**
Jason parksa3cdaa52011-01-13 14:15:43 -0600235 * Returns whether the Encrypted File System feature is enabled on the device or not.
236 * @return <code>true</code> if Encrypted File System feature is enabled, <code>false</code>
237 * if disabled.
238 * @hide
239 */
240 public static boolean isEncryptedFilesystemEnabled() {
241 return SystemProperties.getBoolean(SYSTEM_PROPERTY_EFS_ENABLED, false);
242 }
243
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800244 private static final File DATA_DIRECTORY
245 = getDirectory("ANDROID_DATA", "/data");
246
Oscar Montemayora8529f62009-11-18 10:14:20 -0800247 /**
248 * @hide
249 */
250 private static final File SECURE_DATA_DIRECTORY
251 = getDirectory("ANDROID_SECURE_DATA", "/data/secure");
252
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700253 private static final File DOWNLOAD_CACHE_DIRECTORY = getDirectory("DOWNLOAD_CACHE", "/cache");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800254
255 /**
256 * Gets the Android data directory.
257 */
258 public static File getDataDirectory() {
259 return DATA_DIRECTORY;
260 }
261
262 /**
Dianne Hackborne83cefce2010-02-04 17:38:14 -0800263 * Gets the Android external storage directory. This directory may not
264 * currently be accessible if it has been mounted by the user on their
265 * computer, has been removed from the device, or some other problem has
266 * happened. You can determine its current state with
267 * {@link #getExternalStorageState()}.
268 *
Dianne Hackborn407f6252010-10-04 11:31:17 -0700269 * <p><em>Note: don't be confused by the word "external" here. This
270 * directory can better be thought as media/shared storage. It is a
271 * filesystem that can hold a relatively large amount of data and that
272 * is shared across all applications (does not enforce permissions).
273 * Traditionally this is an SD card, but it may also be implemented as
274 * built-in storage in a device that is distinct from the protected
275 * internal storage and can be mounted as a filesystem on a computer.</em></p>
276 *
Jeff Sharkey8c165792012-10-22 14:08:29 -0700277 * <p>On devices with multiple users (as described by {@link UserManager}),
278 * each user has their own isolated external storage. Applications only
279 * have access to the external storage for the user they're running as.</p>
280 *
Dianne Hackborn407f6252010-10-04 11:31:17 -0700281 * <p>In devices with multiple "external" storage directories (such as
282 * both secure app storage and mountable shared storage), this directory
283 * represents the "primary" external storage that the user will interact
284 * with.</p>
285 *
Dianne Hackbornacaf0282010-03-30 14:39:35 -0700286 * <p>Applications should not directly use this top-level directory, in
287 * order to avoid polluting the user's root namespace. Any files that are
288 * private to the application should be placed in a directory returned
289 * by {@link android.content.Context#getExternalFilesDir
290 * Context.getExternalFilesDir}, which the system will take care of deleting
291 * if the application is uninstalled. Other shared files should be placed
292 * in one of the directories returned by
Jeff Sharkey8c165792012-10-22 14:08:29 -0700293 * {@link #getExternalStoragePublicDirectory}.</p>
294 *
295 * <p>Writing to this path requires the
296 * {@link android.Manifest.permission#WRITE_EXTERNAL_STORAGE} permission. In
297 * a future platform release, access to this path will require the
298 * {@link android.Manifest.permission#READ_EXTERNAL_STORAGE} permission,
299 * which is automatically granted if you hold the write permission.</p>
300 *
301 * <p>This path may change between platform versions, so applications
302 * should only persist relative paths.</p>
Dianne Hackbornacaf0282010-03-30 14:39:35 -0700303 *
Dianne Hackborne83cefce2010-02-04 17:38:14 -0800304 * <p>Here is an example of typical code to monitor the state of
305 * external storage:</p>
306 *
307 * {@sample development/samples/ApiDemos/src/com/example/android/apis/content/ExternalStorage.java
308 * monitor_storage}
Dianne Hackborn407f6252010-10-04 11:31:17 -0700309 *
310 * @see #getExternalStorageState()
311 * @see #isExternalStorageRemovable()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800312 */
313 public static File getExternalStorageDirectory() {
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700314 throwIfSystem();
315 return sCurrentUser.getExternalStorageDirectory();
316 }
317
318 /** {@hide} */
319 public static File getLegacyExternalStorageDirectory() {
320 return new File(System.getenv(ENV_EXTERNAL_STORAGE));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800321 }
322
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700323 /** {@hide} */
324 public static File getLegacyExternalStorageObbDirectory() {
325 return buildPath(getLegacyExternalStorageDirectory(), DIRECTORY_ANDROID, "obb");
326 }
327
328 /** {@hide} */
329 public static File getEmulatedStorageSource(int userId) {
330 // /mnt/shell/emulated/0
331 return new File(System.getenv(ENV_EMULATED_STORAGE_SOURCE), String.valueOf(userId));
332 }
333
334 /** {@hide} */
335 public static File getEmulatedStorageObbSource() {
336 // /mnt/shell/emulated/obb
337 return new File(System.getenv(ENV_EMULATED_STORAGE_SOURCE), "obb");
338 }
339
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800340 /**
Dianne Hackborne83cefce2010-02-04 17:38:14 -0800341 * Standard directory in which to place any audio files that should be
342 * in the regular list of music for the user.
343 * This may be combined with
344 * {@link #DIRECTORY_PODCASTS}, {@link #DIRECTORY_NOTIFICATIONS},
345 * {@link #DIRECTORY_ALARMS}, and {@link #DIRECTORY_RINGTONES} as a series
346 * of directories to categories a particular audio file as more than one
347 * type.
348 */
349 public static String DIRECTORY_MUSIC = "Music";
350
351 /**
352 * Standard directory in which to place any audio files that should be
353 * in the list of podcasts that the user can select (not as regular
354 * music).
355 * This may be combined with {@link #DIRECTORY_MUSIC},
356 * {@link #DIRECTORY_NOTIFICATIONS},
357 * {@link #DIRECTORY_ALARMS}, and {@link #DIRECTORY_RINGTONES} as a series
358 * of directories to categories a particular audio file as more than one
359 * type.
360 */
361 public static String DIRECTORY_PODCASTS = "Podcasts";
362
363 /**
364 * Standard directory in which to place any audio files that should be
365 * in the list of ringtones that the user can select (not as regular
366 * music).
367 * This may be combined with {@link #DIRECTORY_MUSIC},
368 * {@link #DIRECTORY_PODCASTS}, {@link #DIRECTORY_NOTIFICATIONS}, and
369 * {@link #DIRECTORY_ALARMS} as a series
370 * of directories to categories a particular audio file as more than one
371 * type.
372 */
373 public static String DIRECTORY_RINGTONES = "Ringtones";
374
375 /**
376 * Standard directory in which to place any audio files that should be
377 * in the list of alarms that the user can select (not as regular
378 * music).
379 * This may be combined with {@link #DIRECTORY_MUSIC},
380 * {@link #DIRECTORY_PODCASTS}, {@link #DIRECTORY_NOTIFICATIONS},
381 * and {@link #DIRECTORY_RINGTONES} as a series
382 * of directories to categories a particular audio file as more than one
383 * type.
384 */
385 public static String DIRECTORY_ALARMS = "Alarms";
386
387 /**
388 * Standard directory in which to place any audio files that should be
389 * in the list of notifications that the user can select (not as regular
390 * music).
391 * This may be combined with {@link #DIRECTORY_MUSIC},
392 * {@link #DIRECTORY_PODCASTS},
393 * {@link #DIRECTORY_ALARMS}, and {@link #DIRECTORY_RINGTONES} as a series
394 * of directories to categories a particular audio file as more than one
395 * type.
396 */
397 public static String DIRECTORY_NOTIFICATIONS = "Notifications";
398
399 /**
400 * Standard directory in which to place pictures that are available to
401 * the user. Note that this is primarily a convention for the top-level
402 * public directory, as the media scanner will find and collect pictures
403 * in any directory.
404 */
405 public static String DIRECTORY_PICTURES = "Pictures";
406
407 /**
408 * Standard directory in which to place movies that are available to
409 * the user. Note that this is primarily a convention for the top-level
410 * public directory, as the media scanner will find and collect movies
411 * in any directory.
412 */
413 public static String DIRECTORY_MOVIES = "Movies";
414
415 /**
416 * Standard directory in which to place files that have been downloaded by
417 * the user. Note that this is primarily a convention for the top-level
418 * public directory, you are free to download files anywhere in your own
Dianne Hackbornce59fb82010-04-07 17:19:04 -0700419 * private directories. Also note that though the constant here is
420 * named DIRECTORY_DOWNLOADS (plural), the actual file name is non-plural for
421 * backwards compatibility reasons.
Dianne Hackborne83cefce2010-02-04 17:38:14 -0800422 */
Dianne Hackbornce59fb82010-04-07 17:19:04 -0700423 public static String DIRECTORY_DOWNLOADS = "Download";
Dianne Hackborne83cefce2010-02-04 17:38:14 -0800424
425 /**
426 * The traditional location for pictures and videos when mounting the
427 * device as a camera. Note that this is primarily a convention for the
428 * top-level public directory, as this convention makes no sense elsewhere.
429 */
430 public static String DIRECTORY_DCIM = "DCIM";
431
432 /**
433 * Get a top-level public external storage directory for placing files of
434 * a particular type. This is where the user will typically place and
435 * manage their own files, so you should be careful about what you put here
436 * to ensure you don't erase their files or get in the way of their own
437 * organization.
438 *
Jeff Sharkey8c165792012-10-22 14:08:29 -0700439 * <p>On devices with multiple users (as described by {@link UserManager}),
440 * each user has their own isolated external storage. Applications only
441 * have access to the external storage for the user they're running as.</p>
442 *
Dianne Hackborne83cefce2010-02-04 17:38:14 -0800443 * <p>Here is an example of typical code to manipulate a picture on
444 * the public external storage:</p>
445 *
446 * {@sample development/samples/ApiDemos/src/com/example/android/apis/content/ExternalStorage.java
447 * public_picture}
448 *
449 * @param type The type of storage directory to return. Should be one of
450 * {@link #DIRECTORY_MUSIC}, {@link #DIRECTORY_PODCASTS},
451 * {@link #DIRECTORY_RINGTONES}, {@link #DIRECTORY_ALARMS},
452 * {@link #DIRECTORY_NOTIFICATIONS}, {@link #DIRECTORY_PICTURES},
453 * {@link #DIRECTORY_MOVIES}, {@link #DIRECTORY_DOWNLOADS}, or
454 * {@link #DIRECTORY_DCIM}. May not be null.
455 *
456 * @return Returns the File path for the directory. Note that this
457 * directory may not yet exist, so you must make sure it exists before
458 * using it such as with {@link File#mkdirs File.mkdirs()}.
459 */
460 public static File getExternalStoragePublicDirectory(String type) {
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700461 throwIfSystem();
462 return sCurrentUser.getExternalStoragePublicDirectory(type);
Dianne Hackborne83cefce2010-02-04 17:38:14 -0800463 }
464
465 /**
466 * Returns the path for android-specific data on the SD card.
467 * @hide
468 */
469 public static File getExternalStorageAndroidDataDir() {
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700470 throwIfSystem();
471 return sCurrentUser.getExternalStorageAndroidDataDir();
Dianne Hackborne83cefce2010-02-04 17:38:14 -0800472 }
473
474 /**
475 * Generates the raw path to an application's data
476 * @hide
477 */
478 public static File getExternalStorageAppDataDirectory(String packageName) {
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700479 throwIfSystem();
480 return sCurrentUser.getExternalStorageAppDataDirectory(packageName);
Dianne Hackborne83cefce2010-02-04 17:38:14 -0800481 }
482
483 /**
484 * Generates the raw path to an application's media
485 * @hide
486 */
487 public static File getExternalStorageAppMediaDirectory(String packageName) {
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700488 throwIfSystem();
489 return sCurrentUser.getExternalStorageAppMediaDirectory(packageName);
Dianne Hackborne83cefce2010-02-04 17:38:14 -0800490 }
491
492 /**
Dianne Hackborn805fd7e2011-01-16 18:30:29 -0800493 * Generates the raw path to an application's OBB files
494 * @hide
495 */
496 public static File getExternalStorageAppObbDirectory(String packageName) {
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700497 throwIfSystem();
498 return sCurrentUser.getExternalStorageAppObbDirectory(packageName);
Dianne Hackborn805fd7e2011-01-16 18:30:29 -0800499 }
500
501 /**
Dianne Hackborne83cefce2010-02-04 17:38:14 -0800502 * Generates the path to an application's files.
503 * @hide
504 */
505 public static File getExternalStorageAppFilesDirectory(String packageName) {
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700506 throwIfSystem();
507 return sCurrentUser.getExternalStorageAppFilesDirectory(packageName);
Dianne Hackborne83cefce2010-02-04 17:38:14 -0800508 }
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700509
Dianne Hackborne83cefce2010-02-04 17:38:14 -0800510 /**
511 * Generates the path to an application's cache.
512 * @hide
513 */
514 public static File getExternalStorageAppCacheDirectory(String packageName) {
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700515 throwIfSystem();
516 return sCurrentUser.getExternalStorageAppCacheDirectory(packageName);
Dianne Hackborne83cefce2010-02-04 17:38:14 -0800517 }
518
519 /**
Jeff Sharkey8c165792012-10-22 14:08:29 -0700520 * Gets the Android download/cache content directory.
521 * <p>
522 * Access to this path requires the
523 * {@link android.Manifest.permission#ACCESS_CACHE_FILESYSTEM} permission.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800524 */
525 public static File getDownloadCacheDirectory() {
526 return DOWNLOAD_CACHE_DIRECTORY;
527 }
528
529 /**
Gilles Debunneee1d6302011-05-13 10:09:32 -0700530 * {@link #getExternalStorageState()} returns MEDIA_REMOVED if the media is not present.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800531 */
532 public static final String MEDIA_REMOVED = "removed";
533
534 /**
Gilles Debunneee1d6302011-05-13 10:09:32 -0700535 * {@link #getExternalStorageState()} returns MEDIA_UNMOUNTED if the media is present
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800536 * but not mounted.
537 */
538 public static final String MEDIA_UNMOUNTED = "unmounted";
539
540 /**
Gilles Debunneee1d6302011-05-13 10:09:32 -0700541 * {@link #getExternalStorageState()} returns MEDIA_CHECKING if the media is present
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800542 * and being disk-checked
543 */
544 public static final String MEDIA_CHECKING = "checking";
545
546 /**
Gilles Debunneee1d6302011-05-13 10:09:32 -0700547 * {@link #getExternalStorageState()} returns MEDIA_NOFS if the media is present
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800548 * but is blank or is using an unsupported filesystem
549 */
550 public static final String MEDIA_NOFS = "nofs";
551
552 /**
Gilles Debunneee1d6302011-05-13 10:09:32 -0700553 * {@link #getExternalStorageState()} returns MEDIA_MOUNTED if the media is present
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800554 * and mounted at its mount point with read/write access.
555 */
556 public static final String MEDIA_MOUNTED = "mounted";
557
558 /**
Gilles Debunneee1d6302011-05-13 10:09:32 -0700559 * {@link #getExternalStorageState()} returns MEDIA_MOUNTED_READ_ONLY if the media is present
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800560 * and mounted at its mount point with read only access.
561 */
562 public static final String MEDIA_MOUNTED_READ_ONLY = "mounted_ro";
563
564 /**
Gilles Debunneee1d6302011-05-13 10:09:32 -0700565 * {@link #getExternalStorageState()} returns MEDIA_SHARED if the media is present
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800566 * not mounted, and shared via USB mass storage.
567 */
568 public static final String MEDIA_SHARED = "shared";
569
570 /**
Gilles Debunneee1d6302011-05-13 10:09:32 -0700571 * {@link #getExternalStorageState()} returns MEDIA_BAD_REMOVAL if the media was
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800572 * removed before it was unmounted.
573 */
574 public static final String MEDIA_BAD_REMOVAL = "bad_removal";
575
576 /**
Gilles Debunneee1d6302011-05-13 10:09:32 -0700577 * {@link #getExternalStorageState()} returns MEDIA_UNMOUNTABLE if the media is present
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800578 * but cannot be mounted. Typically this happens if the file system on the
579 * media is corrupted.
580 */
581 public static final String MEDIA_UNMOUNTABLE = "unmountable";
582
583 /**
Dianne Hackborn407f6252010-10-04 11:31:17 -0700584 * Gets the current state of the primary "external" storage device.
Dianne Hackborne83cefce2010-02-04 17:38:14 -0800585 *
Jeff Sharkey8c165792012-10-22 14:08:29 -0700586 * @see #getExternalStorageDirectory()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800587 */
588 public static String getExternalStorageState() {
San Mehat7fd0fee2009-12-17 07:12:23 -0800589 try {
Kenny Rootb2278dc2011-01-18 13:03:28 -0800590 IMountService mountService = IMountService.Stub.asInterface(ServiceManager
591 .getService("mount"));
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700592 final StorageVolume primary = getPrimaryVolume();
593 return mountService.getVolumeState(primary.getPath());
594 } catch (RemoteException rex) {
595 Log.w(TAG, "Failed to read external storage state; assuming REMOVED: " + rex);
San Mehat7fd0fee2009-12-17 07:12:23 -0800596 return Environment.MEDIA_REMOVED;
597 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800598 }
599
Dianne Hackborn407f6252010-10-04 11:31:17 -0700600 /**
601 * Returns whether the primary "external" storage device is removable.
602 * If true is returned, this device is for example an SD card that the
603 * user can remove. If false is returned, the storage is built into
604 * the device and can not be physically removed.
605 *
606 * <p>See {@link #getExternalStorageDirectory()} for more information.
607 */
608 public static boolean isExternalStorageRemovable() {
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700609 final StorageVolume primary = getPrimaryVolume();
610 return (primary != null && primary.isRemovable());
Dianne Hackborn407f6252010-10-04 11:31:17 -0700611 }
612
Kenny Roote1ff2142010-10-12 11:20:01 -0700613 /**
614 * Returns whether the device has an external storage device which is
Andy Stadler50c294f2011-03-07 19:13:42 -0800615 * emulated. If true, the device does not have real external storage, and the directory
616 * returned by {@link #getExternalStorageDirectory()} will be allocated using a portion of
617 * the internal storage system.
618 *
619 * <p>Certain system services, such as the package manager, use this
Kenny Roote1ff2142010-10-12 11:20:01 -0700620 * to determine where to install an application.
Andy Stadler50c294f2011-03-07 19:13:42 -0800621 *
622 * <p>Emulated external storage may also be encrypted - see
623 * {@link android.app.admin.DevicePolicyManager#setStorageEncryption(
624 * android.content.ComponentName, boolean)} for additional details.
Kenny Roote1ff2142010-10-12 11:20:01 -0700625 */
626 public static boolean isExternalStorageEmulated() {
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700627 final StorageVolume primary = getPrimaryVolume();
628 return (primary != null && primary.isEmulated());
Kenny Roote1ff2142010-10-12 11:20:01 -0700629 }
630
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800631 static File getDirectory(String variableName, String defaultPath) {
632 String path = System.getenv(variableName);
633 return path == null ? new File(defaultPath) : new File(path);
634 }
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700635
636 private static void throwIfSystem() {
637 if (Process.myUid() == Process.SYSTEM_UID) {
638 Log.wtf(TAG, "Static storage paths aren't available from AID_SYSTEM", new Throwable());
639 }
640 }
641
642 private static File buildPath(File base, String... segments) {
643 File cur = base;
644 for (String segment : segments) {
645 if (cur == null) {
646 cur = new File(segment);
647 } else {
648 cur = new File(cur, segment);
649 }
650 }
651 return cur;
652 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800653}