Environment.java revision 6e16714c688ed9c52763696f5a5e7b90802a471b
1/*
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
19import android.app.admin.DevicePolicyManager;
20import android.content.Context;
21import android.os.storage.StorageManager;
22import android.os.storage.StorageVolume;
23import android.text.TextUtils;
24import android.util.Log;
25
26import java.io.File;
27
28/**
29 * Provides access to environment variables.
30 */
31public class Environment {
32    private static final String TAG = "Environment";
33
34    private static final String ENV_EXTERNAL_STORAGE = "EXTERNAL_STORAGE";
35    private static final String ENV_ANDROID_ROOT = "ANDROID_ROOT";
36    private static final String ENV_ANDROID_DATA = "ANDROID_DATA";
37    private static final String ENV_ANDROID_EXPAND = "ANDROID_EXPAND";
38    private static final String ENV_ANDROID_STORAGE = "ANDROID_STORAGE";
39    private static final String ENV_DOWNLOAD_CACHE = "DOWNLOAD_CACHE";
40    private static final String ENV_OEM_ROOT = "OEM_ROOT";
41    private static final String ENV_ODM_ROOT = "ODM_ROOT";
42    private static final String ENV_VENDOR_ROOT = "VENDOR_ROOT";
43
44    /** {@hide} */
45    public static final String DIR_ANDROID = "Android";
46    private static final String DIR_DATA = "data";
47    private static final String DIR_MEDIA = "media";
48    private static final String DIR_OBB = "obb";
49    private static final String DIR_FILES = "files";
50    private static final String DIR_CACHE = "cache";
51
52    /** {@hide} */
53    @Deprecated
54    public static final String DIRECTORY_ANDROID = DIR_ANDROID;
55
56    private static final File DIR_ANDROID_ROOT = getDirectory(ENV_ANDROID_ROOT, "/system");
57    private static final File DIR_ANDROID_DATA = getDirectory(ENV_ANDROID_DATA, "/data");
58    private static final File DIR_ANDROID_EXPAND = getDirectory(ENV_ANDROID_EXPAND, "/mnt/expand");
59    private static final File DIR_ANDROID_STORAGE = getDirectory(ENV_ANDROID_STORAGE, "/storage");
60    private static final File DIR_DOWNLOAD_CACHE = getDirectory(ENV_DOWNLOAD_CACHE, "/cache");
61    private static final File DIR_OEM_ROOT = getDirectory(ENV_OEM_ROOT, "/oem");
62    private static final File DIR_ODM_ROOT = getDirectory(ENV_ODM_ROOT, "/odm");
63    private static final File DIR_VENDOR_ROOT = getDirectory(ENV_VENDOR_ROOT, "/vendor");
64
65    // NoPreloadHolder to separate shared data from user-specific data, and to be able to initialize
66    // Environment without side effect (allowing a lazy init of the data where possible).
67    private static class NoPreloadHolder {
68        public final static UserEnvironment sCurrentUser;
69        public static boolean sUserRequired;
70
71        static {
72            sCurrentUser = new UserEnvironment(UserHandle.myUserId());
73        }
74
75        // Empty function to be able to trigger static initialization.
76        public static void init() {
77        }
78
79        // Disallow allocation.
80        private NoPreloadHolder() {
81        }
82    }
83
84    /** {@hide} */
85    public static void init() {
86        NoPreloadHolder.init();
87
88        // Check for expected outcome. We only allow one initialization, this will trigger if
89        // somebody tried to re-initialize.
90        if (NoPreloadHolder.sCurrentUser.mUserId != UserHandle.myUserId()) {
91            throw new IllegalStateException();
92        }
93    }
94
95    /** {@hide} */
96    public static class UserEnvironment {
97        private final int mUserId;
98
99        public UserEnvironment(int userId) {
100            mUserId = userId;
101        }
102
103        public File[] getExternalDirs() {
104            final StorageVolume[] volumes = StorageManager.getVolumeList(mUserId,
105                    StorageManager.FLAG_FOR_WRITE);
106            final File[] files = new File[volumes.length];
107            for (int i = 0; i < volumes.length; i++) {
108                files[i] = volumes[i].getPathFile();
109            }
110            return files;
111        }
112
113        @Deprecated
114        public File getExternalStorageDirectory() {
115            return getExternalDirs()[0];
116        }
117
118        @Deprecated
119        public File getExternalStoragePublicDirectory(String type) {
120            return buildExternalStoragePublicDirs(type)[0];
121        }
122
123        public File[] buildExternalStoragePublicDirs(String type) {
124            return buildPaths(getExternalDirs(), type);
125        }
126
127        public File[] buildExternalStorageAndroidDataDirs() {
128            return buildPaths(getExternalDirs(), DIR_ANDROID, DIR_DATA);
129        }
130
131        public File[] buildExternalStorageAndroidObbDirs() {
132            return buildPaths(getExternalDirs(), DIR_ANDROID, DIR_OBB);
133        }
134
135        public File[] buildExternalStorageAppDataDirs(String packageName) {
136            return buildPaths(getExternalDirs(), DIR_ANDROID, DIR_DATA, packageName);
137        }
138
139        public File[] buildExternalStorageAppMediaDirs(String packageName) {
140            return buildPaths(getExternalDirs(), DIR_ANDROID, DIR_MEDIA, packageName);
141        }
142
143        public File[] buildExternalStorageAppObbDirs(String packageName) {
144            return buildPaths(getExternalDirs(), DIR_ANDROID, DIR_OBB, packageName);
145        }
146
147        public File[] buildExternalStorageAppFilesDirs(String packageName) {
148            return buildPaths(getExternalDirs(), DIR_ANDROID, DIR_DATA, packageName, DIR_FILES);
149        }
150
151        public File[] buildExternalStorageAppCacheDirs(String packageName) {
152            return buildPaths(getExternalDirs(), DIR_ANDROID, DIR_DATA, packageName, DIR_CACHE);
153        }
154    }
155
156    /**
157     * Return root of the "system" partition holding the core Android OS.
158     * Always present and mounted read-only.
159     */
160    public static File getRootDirectory() {
161        return DIR_ANDROID_ROOT;
162    }
163
164    /** {@hide} */
165    public static File getStorageDirectory() {
166        return DIR_ANDROID_STORAGE;
167    }
168
169    /**
170     * Return root directory of the "oem" partition holding OEM customizations,
171     * if any. If present, the partition is mounted read-only.
172     *
173     * @hide
174     */
175    public static File getOemDirectory() {
176        return DIR_OEM_ROOT;
177    }
178
179    /**
180     * Return root directory of the "odm" partition holding ODM customizations,
181     * if any. If present, the partition is mounted read-only.
182     *
183     * @hide
184     */
185    public static File getOdmDirectory() {
186        return DIR_ODM_ROOT;
187    }
188
189    /**
190     * Return root directory of the "vendor" partition that holds vendor-provided
191     * software that should persist across simple reflashing of the "system" partition.
192     * @hide
193     */
194    public static File getVendorDirectory() {
195        return DIR_VENDOR_ROOT;
196    }
197
198    /**
199     * Return the system directory for a user. This is for use by system
200     * services to store files relating to the user. This directory will be
201     * automatically deleted when the user is removed.
202     *
203     * @deprecated This directory is valid and still exists, but callers should
204     *             <em>strongly</em> consider switching to
205     *             {@link #getDataSystemCeDirectory(int)} which is protected
206     *             with user credentials or
207     *             {@link #getDataSystemDeDirectory(int)} which supports fast
208     *             user wipe.
209     * @hide
210     */
211    @Deprecated
212    public static File getUserSystemDirectory(int userId) {
213        return new File(new File(getDataSystemDirectory(), "users"), Integer.toString(userId));
214    }
215
216    /**
217     * Returns the config directory for a user. This is for use by system
218     * services to store files relating to the user which should be readable by
219     * any app running as that user.
220     *
221     * @deprecated This directory is valid and still exists, but callers should
222     *             <em>strongly</em> consider switching to
223     *             {@link #getDataMiscCeDirectory(int)} which is protected with
224     *             user credentials or {@link #getDataMiscDeDirectory(int)}
225     *             which supports fast user wipe.
226     * @hide
227     */
228    @Deprecated
229    public static File getUserConfigDirectory(int userId) {
230        return new File(new File(new File(
231                getDataDirectory(), "misc"), "user"), Integer.toString(userId));
232    }
233
234    /**
235     * Return the user data directory.
236     */
237    public static File getDataDirectory() {
238        return DIR_ANDROID_DATA;
239    }
240
241    /** {@hide} */
242    public static File getDataDirectory(String volumeUuid) {
243        if (TextUtils.isEmpty(volumeUuid)) {
244            return DIR_ANDROID_DATA;
245        } else {
246            return new File("/mnt/expand/" + volumeUuid);
247        }
248    }
249
250    /** {@hide} */
251    public static File getExpandDirectory() {
252        return DIR_ANDROID_EXPAND;
253    }
254
255    /** {@hide} */
256    public static File getDataSystemDirectory() {
257        return new File(getDataDirectory(), "system");
258    }
259
260    /**
261     * Returns the base directory for per-user system directory, device encrypted.
262     * {@hide}
263     */
264    public static File getDataSystemDeDirectory() {
265        return buildPath(getDataDirectory(), "system_de");
266    }
267
268    /**
269     * Returns the base directory for per-user system directory, credential encrypted.
270     * {@hide}
271     */
272    public static File getDataSystemCeDirectory() {
273        return buildPath(getDataDirectory(), "system_ce");
274    }
275
276    /** {@hide} */
277    public static File getDataSystemCeDirectory(int userId) {
278        return buildPath(getDataDirectory(), "system_ce", String.valueOf(userId));
279    }
280
281    /** {@hide} */
282    public static File getDataSystemDeDirectory(int userId) {
283        return buildPath(getDataDirectory(), "system_de", String.valueOf(userId));
284    }
285
286    /** {@hide} */
287    public static File getDataMiscDirectory() {
288        return new File(getDataDirectory(), "misc");
289    }
290
291    /** {@hide} */
292    public static File getDataMiscCeDirectory(int userId) {
293        return buildPath(getDataDirectory(), "misc_ce", String.valueOf(userId));
294    }
295
296    /** {@hide} */
297    public static File getDataMiscDeDirectory(int userId) {
298        return buildPath(getDataDirectory(), "misc_de", String.valueOf(userId));
299    }
300
301    private static File getDataProfilesDeDirectory(int userId) {
302        return buildPath(getDataDirectory(), "misc", "profiles", "cur", String.valueOf(userId));
303    }
304
305    /** {@hide} */
306    public static File getDataProfilesDePackageDirectory(int userId, String packageName) {
307        return buildPath(getDataProfilesDeDirectory(userId), packageName);
308    }
309
310    /** {@hide} */
311    public static File getDataProfilesDeForeignDexDirectory(int userId) {
312        return buildPath(getDataProfilesDeDirectory(userId), "foreign-dex");
313    }
314
315    /** {@hide} */
316    public static File getDataAppDirectory(String volumeUuid) {
317        return new File(getDataDirectory(volumeUuid), "app");
318    }
319
320    /** {@hide} */
321    public static File getDataAppEphemeralDirectory(String volumeUuid) {
322        return new File(getDataDirectory(volumeUuid), "app-ephemeral");
323    }
324
325    /** {@hide} */
326    public static File getDataUserCeDirectory(String volumeUuid) {
327        return new File(getDataDirectory(volumeUuid), "user");
328    }
329
330    /** {@hide} */
331    public static File getDataUserCeDirectory(String volumeUuid, int userId) {
332        return new File(getDataUserCeDirectory(volumeUuid), String.valueOf(userId));
333    }
334
335    /** {@hide} */
336    public static File getDataUserCePackageDirectory(String volumeUuid, int userId,
337            String packageName) {
338        // TODO: keep consistent with installd
339        return new File(getDataUserCeDirectory(volumeUuid, userId), packageName);
340    }
341
342    /** {@hide} */
343    public static File getDataUserDeDirectory(String volumeUuid) {
344        return new File(getDataDirectory(volumeUuid), "user_de");
345    }
346
347    /** {@hide} */
348    public static File getDataUserDeDirectory(String volumeUuid, int userId) {
349        return new File(getDataUserDeDirectory(volumeUuid), String.valueOf(userId));
350    }
351
352    /** {@hide} */
353    public static File getDataUserDePackageDirectory(String volumeUuid, int userId,
354            String packageName) {
355        // TODO: keep consistent with installd
356        return new File(getDataUserDeDirectory(volumeUuid, userId), packageName);
357    }
358
359    /**
360     * Return preloads directory.
361     * <p>This directory may contain pre-loaded content such as
362     * {@link #getDataPreloadsDemoDirectory() demo videos} and
363     * {@link #getDataPreloadsAppsDirectory() APK files} .
364     * {@hide}
365     */
366    public static File getDataPreloadsDirectory() {
367        return new File(getDataDirectory(), "preloads");
368    }
369
370    /**
371     * @see #getDataPreloadsDirectory()
372     * {@hide}
373     */
374    public static File getDataPreloadsDemoDirectory() {
375        return new File(getDataPreloadsDirectory(), "demo");
376    }
377
378    /**
379     * @see #getDataPreloadsDirectory()
380     * {@hide}
381     */
382    public static File getDataPreloadsAppsDirectory() {
383        return new File(getDataPreloadsDirectory(), "apps");
384    }
385
386    /**
387     * Return the primary shared/external storage directory. This directory may
388     * not currently be accessible if it has been mounted by the user on their
389     * computer, has been removed from the device, or some other problem has
390     * happened. You can determine its current state with
391     * {@link #getExternalStorageState()}.
392     * <p>
393     * <em>Note: don't be confused by the word "external" here. This directory
394     * can better be thought as media/shared storage. It is a filesystem that
395     * can hold a relatively large amount of data and that is shared across all
396     * applications (does not enforce permissions). Traditionally this is an SD
397     * card, but it may also be implemented as built-in storage in a device that
398     * is distinct from the protected internal storage and can be mounted as a
399     * filesystem on a computer.</em>
400     * <p>
401     * On devices with multiple users (as described by {@link UserManager}),
402     * each user has their own isolated shared storage. Applications only have
403     * access to the shared storage for the user they're running as.
404     * <p>
405     * In devices with multiple shared/external storage directories, this
406     * directory represents the primary storage that the user will interact
407     * with. Access to secondary storage is available through
408     * {@link Context#getExternalFilesDirs(String)},
409     * {@link Context#getExternalCacheDirs()}, and
410     * {@link Context#getExternalMediaDirs()}.
411     * <p>
412     * Applications should not directly use this top-level directory, in order
413     * to avoid polluting the user's root namespace. Any files that are private
414     * to the application should be placed in a directory returned by
415     * {@link android.content.Context#getExternalFilesDir
416     * Context.getExternalFilesDir}, which the system will take care of deleting
417     * if the application is uninstalled. Other shared files should be placed in
418     * one of the directories returned by
419     * {@link #getExternalStoragePublicDirectory}.
420     * <p>
421     * Writing to this path requires the
422     * {@link android.Manifest.permission#WRITE_EXTERNAL_STORAGE} permission,
423     * and starting in {@link android.os.Build.VERSION_CODES#KITKAT}, read access requires the
424     * {@link android.Manifest.permission#READ_EXTERNAL_STORAGE} permission,
425     * which is automatically granted if you hold the write permission.
426     * <p>
427     * Starting in {@link android.os.Build.VERSION_CODES#KITKAT}, if your
428     * application only needs to store internal data, consider using
429     * {@link Context#getExternalFilesDir(String)},
430     * {@link Context#getExternalCacheDir()}, or
431     * {@link Context#getExternalMediaDirs()}, which require no permissions to
432     * read or write.
433     * <p>
434     * This path may change between platform versions, so applications should
435     * only persist relative paths.
436     * <p>
437     * Here is an example of typical code to monitor the state of external
438     * storage:
439     * <p>
440     * {@sample development/samples/ApiDemos/src/com/example/android/apis/content/ExternalStorage.java
441     * monitor_storage}
442     *
443     * @see #getExternalStorageState()
444     * @see #isExternalStorageRemovable()
445     */
446    public static File getExternalStorageDirectory() {
447        throwIfUserRequired();
448        return NoPreloadHolder.sCurrentUser.getExternalDirs()[0];
449    }
450
451    /** {@hide} */
452    public static File getLegacyExternalStorageDirectory() {
453        return new File(System.getenv(ENV_EXTERNAL_STORAGE));
454    }
455
456    /** {@hide} */
457    public static File getLegacyExternalStorageObbDirectory() {
458        return buildPath(getLegacyExternalStorageDirectory(), DIR_ANDROID, DIR_OBB);
459    }
460
461    /**
462     * Standard directory in which to place any audio files that should be
463     * in the regular list of music for the user.
464     * This may be combined with
465     * {@link #DIRECTORY_PODCASTS}, {@link #DIRECTORY_NOTIFICATIONS},
466     * {@link #DIRECTORY_ALARMS}, and {@link #DIRECTORY_RINGTONES} as a series
467     * of directories to categories a particular audio file as more than one
468     * type.
469     */
470    public static String DIRECTORY_MUSIC = "Music";
471
472    /**
473     * Standard directory in which to place any audio files that should be
474     * in the list of podcasts that the user can select (not as regular
475     * music).
476     * This may be combined with {@link #DIRECTORY_MUSIC},
477     * {@link #DIRECTORY_NOTIFICATIONS},
478     * {@link #DIRECTORY_ALARMS}, and {@link #DIRECTORY_RINGTONES} as a series
479     * of directories to categories a particular audio file as more than one
480     * type.
481     */
482    public static String DIRECTORY_PODCASTS = "Podcasts";
483
484    /**
485     * Standard directory in which to place any audio files that should be
486     * in the list of ringtones that the user can select (not as regular
487     * music).
488     * This may be combined with {@link #DIRECTORY_MUSIC},
489     * {@link #DIRECTORY_PODCASTS}, {@link #DIRECTORY_NOTIFICATIONS}, and
490     * {@link #DIRECTORY_ALARMS} as a series
491     * of directories to categories a particular audio file as more than one
492     * type.
493     */
494    public static String DIRECTORY_RINGTONES = "Ringtones";
495
496    /**
497     * Standard directory in which to place any audio files that should be
498     * in the list of alarms that the user can select (not as regular
499     * music).
500     * This may be combined with {@link #DIRECTORY_MUSIC},
501     * {@link #DIRECTORY_PODCASTS}, {@link #DIRECTORY_NOTIFICATIONS},
502     * and {@link #DIRECTORY_RINGTONES} as a series
503     * of directories to categories a particular audio file as more than one
504     * type.
505     */
506    public static String DIRECTORY_ALARMS = "Alarms";
507
508    /**
509     * Standard directory in which to place any audio files that should be
510     * in the list of notifications that the user can select (not as regular
511     * music).
512     * This may be combined with {@link #DIRECTORY_MUSIC},
513     * {@link #DIRECTORY_PODCASTS},
514     * {@link #DIRECTORY_ALARMS}, and {@link #DIRECTORY_RINGTONES} as a series
515     * of directories to categories a particular audio file as more than one
516     * type.
517     */
518    public static String DIRECTORY_NOTIFICATIONS = "Notifications";
519
520    /**
521     * Standard directory in which to place pictures that are available to
522     * the user.  Note that this is primarily a convention for the top-level
523     * public directory, as the media scanner will find and collect pictures
524     * in any directory.
525     */
526    public static String DIRECTORY_PICTURES = "Pictures";
527
528    /**
529     * Standard directory in which to place movies that are available to
530     * the user.  Note that this is primarily a convention for the top-level
531     * public directory, as the media scanner will find and collect movies
532     * in any directory.
533     */
534    public static String DIRECTORY_MOVIES = "Movies";
535
536    /**
537     * Standard directory in which to place files that have been downloaded by
538     * the user.  Note that this is primarily a convention for the top-level
539     * public directory, you are free to download files anywhere in your own
540     * private directories.  Also note that though the constant here is
541     * named DIRECTORY_DOWNLOADS (plural), the actual file name is non-plural for
542     * backwards compatibility reasons.
543     */
544    public static String DIRECTORY_DOWNLOADS = "Download";
545
546    /**
547     * The traditional location for pictures and videos when mounting the
548     * device as a camera.  Note that this is primarily a convention for the
549     * top-level public directory, as this convention makes no sense elsewhere.
550     */
551    public static String DIRECTORY_DCIM = "DCIM";
552
553    /**
554     * Standard directory in which to place documents that have been created by
555     * the user.
556     */
557    public static String DIRECTORY_DOCUMENTS = "Documents";
558
559    /**
560     * List of standard storage directories.
561     * <p>
562     * Each of its values have its own constant:
563     * <ul>
564     *   <li>{@link #DIRECTORY_MUSIC}
565     *   <li>{@link #DIRECTORY_PODCASTS}
566     *   <li>{@link #DIRECTORY_ALARMS}
567     *   <li>{@link #DIRECTORY_RINGTONES}
568     *   <li>{@link #DIRECTORY_NOTIFICATIONS}
569     *   <li>{@link #DIRECTORY_PICTURES}
570     *   <li>{@link #DIRECTORY_MOVIES}
571     *   <li>{@link #DIRECTORY_DOWNLOADS}
572     *   <li>{@link #DIRECTORY_DCIM}
573     *   <li>{@link #DIRECTORY_DOCUMENTS}
574     * </ul>
575     * @hide
576     */
577    public static final String[] STANDARD_DIRECTORIES = {
578            DIRECTORY_MUSIC,
579            DIRECTORY_PODCASTS,
580            DIRECTORY_RINGTONES,
581            DIRECTORY_ALARMS,
582            DIRECTORY_NOTIFICATIONS,
583            DIRECTORY_PICTURES,
584            DIRECTORY_MOVIES,
585            DIRECTORY_DOWNLOADS,
586            DIRECTORY_DCIM,
587            DIRECTORY_DOCUMENTS
588    };
589
590    /**
591     * @hide
592     */
593    public static boolean isStandardDirectory(String dir) {
594        for (String valid : STANDARD_DIRECTORIES) {
595            if (valid.equals(dir)) {
596                return true;
597            }
598        }
599        return false;
600    }
601
602    /**
603     * Get a top-level shared/external storage directory for placing files of a
604     * particular type. This is where the user will typically place and manage
605     * their own files, so you should be careful about what you put here to
606     * ensure you don't erase their files or get in the way of their own
607     * organization.
608     * <p>
609     * On devices with multiple users (as described by {@link UserManager}),
610     * each user has their own isolated shared storage. Applications only have
611     * access to the shared storage for the user they're running as.
612     * </p>
613     * <p>
614     * Here is an example of typical code to manipulate a picture on the public
615     * shared storage:
616     * </p>
617     * {@sample development/samples/ApiDemos/src/com/example/android/apis/content/ExternalStorage.java
618     * public_picture}
619     *
620     * @param type The type of storage directory to return. Should be one of
621     *            {@link #DIRECTORY_MUSIC}, {@link #DIRECTORY_PODCASTS},
622     *            {@link #DIRECTORY_RINGTONES}, {@link #DIRECTORY_ALARMS},
623     *            {@link #DIRECTORY_NOTIFICATIONS}, {@link #DIRECTORY_PICTURES},
624     *            {@link #DIRECTORY_MOVIES}, {@link #DIRECTORY_DOWNLOADS},
625     *            {@link #DIRECTORY_DCIM}, or {@link #DIRECTORY_DOCUMENTS}. May not be null.
626     * @return Returns the File path for the directory. Note that this directory
627     *         may not yet exist, so you must make sure it exists before using
628     *         it such as with {@link File#mkdirs File.mkdirs()}.
629     */
630    public static File getExternalStoragePublicDirectory(String type) {
631        throwIfUserRequired();
632        return NoPreloadHolder.sCurrentUser.buildExternalStoragePublicDirs(type)[0];
633    }
634
635    /**
636     * Returns the path for android-specific data on the SD card.
637     * @hide
638     */
639    public static File[] buildExternalStorageAndroidDataDirs() {
640        throwIfUserRequired();
641        return NoPreloadHolder.sCurrentUser.buildExternalStorageAndroidDataDirs();
642    }
643
644    /**
645     * Generates the raw path to an application's data
646     * @hide
647     */
648    public static File[] buildExternalStorageAppDataDirs(String packageName) {
649        throwIfUserRequired();
650        return NoPreloadHolder.sCurrentUser.buildExternalStorageAppDataDirs(packageName);
651    }
652
653    /**
654     * Generates the raw path to an application's media
655     * @hide
656     */
657    public static File[] buildExternalStorageAppMediaDirs(String packageName) {
658        throwIfUserRequired();
659        return NoPreloadHolder.sCurrentUser.buildExternalStorageAppMediaDirs(packageName);
660    }
661
662    /**
663     * Generates the raw path to an application's OBB files
664     * @hide
665     */
666    public static File[] buildExternalStorageAppObbDirs(String packageName) {
667        throwIfUserRequired();
668        return NoPreloadHolder.sCurrentUser.buildExternalStorageAppObbDirs(packageName);
669    }
670
671    /**
672     * Generates the path to an application's files.
673     * @hide
674     */
675    public static File[] buildExternalStorageAppFilesDirs(String packageName) {
676        throwIfUserRequired();
677        return NoPreloadHolder.sCurrentUser.buildExternalStorageAppFilesDirs(packageName);
678    }
679
680    /**
681     * Generates the path to an application's cache.
682     * @hide
683     */
684    public static File[] buildExternalStorageAppCacheDirs(String packageName) {
685        throwIfUserRequired();
686        return NoPreloadHolder.sCurrentUser.buildExternalStorageAppCacheDirs(packageName);
687    }
688
689    /**
690     * Return the download/cache content directory.
691     */
692    public static File getDownloadCacheDirectory() {
693        return DIR_DOWNLOAD_CACHE;
694    }
695
696    /**
697     * Unknown storage state, such as when a path isn't backed by known storage
698     * media.
699     *
700     * @see #getExternalStorageState(File)
701     */
702    public static final String MEDIA_UNKNOWN = "unknown";
703
704    /**
705     * Storage state if the media is not present.
706     *
707     * @see #getExternalStorageState(File)
708     */
709    public static final String MEDIA_REMOVED = "removed";
710
711    /**
712     * Storage state if the media is present but not mounted.
713     *
714     * @see #getExternalStorageState(File)
715     */
716    public static final String MEDIA_UNMOUNTED = "unmounted";
717
718    /**
719     * Storage state if the media is present and being disk-checked.
720     *
721     * @see #getExternalStorageState(File)
722     */
723    public static final String MEDIA_CHECKING = "checking";
724
725    /**
726     * Storage state if the media is present but is blank or is using an
727     * unsupported filesystem.
728     *
729     * @see #getExternalStorageState(File)
730     */
731    public static final String MEDIA_NOFS = "nofs";
732
733    /**
734     * Storage state if the media is present and mounted at its mount point with
735     * read/write access.
736     *
737     * @see #getExternalStorageState(File)
738     */
739    public static final String MEDIA_MOUNTED = "mounted";
740
741    /**
742     * Storage state if the media is present and mounted at its mount point with
743     * read-only access.
744     *
745     * @see #getExternalStorageState(File)
746     */
747    public static final String MEDIA_MOUNTED_READ_ONLY = "mounted_ro";
748
749    /**
750     * Storage state if the media is present not mounted, and shared via USB
751     * mass storage.
752     *
753     * @see #getExternalStorageState(File)
754     */
755    public static final String MEDIA_SHARED = "shared";
756
757    /**
758     * Storage state if the media was removed before it was unmounted.
759     *
760     * @see #getExternalStorageState(File)
761     */
762    public static final String MEDIA_BAD_REMOVAL = "bad_removal";
763
764    /**
765     * Storage state if the media is present but cannot be mounted. Typically
766     * this happens if the file system on the media is corrupted.
767     *
768     * @see #getExternalStorageState(File)
769     */
770    public static final String MEDIA_UNMOUNTABLE = "unmountable";
771
772    /**
773     * Storage state if the media is in the process of being ejected.
774     *
775     * @see #getExternalStorageState(File)
776     */
777    public static final String MEDIA_EJECTING = "ejecting";
778
779    /**
780     * Returns the current state of the primary shared/external storage media.
781     *
782     * @see #getExternalStorageDirectory()
783     * @return one of {@link #MEDIA_UNKNOWN}, {@link #MEDIA_REMOVED},
784     *         {@link #MEDIA_UNMOUNTED}, {@link #MEDIA_CHECKING},
785     *         {@link #MEDIA_NOFS}, {@link #MEDIA_MOUNTED},
786     *         {@link #MEDIA_MOUNTED_READ_ONLY}, {@link #MEDIA_SHARED},
787     *         {@link #MEDIA_BAD_REMOVAL}, or {@link #MEDIA_UNMOUNTABLE}.
788     */
789    public static String getExternalStorageState() {
790        final File externalDir = NoPreloadHolder.sCurrentUser.getExternalDirs()[0];
791        return getExternalStorageState(externalDir);
792    }
793
794    /**
795     * @deprecated use {@link #getExternalStorageState(File)}
796     */
797    @Deprecated
798    public static String getStorageState(File path) {
799        return getExternalStorageState(path);
800    }
801
802    /**
803     * Returns the current state of the shared/external storage media at the
804     * given path.
805     *
806     * @return one of {@link #MEDIA_UNKNOWN}, {@link #MEDIA_REMOVED},
807     *         {@link #MEDIA_UNMOUNTED}, {@link #MEDIA_CHECKING},
808     *         {@link #MEDIA_NOFS}, {@link #MEDIA_MOUNTED},
809     *         {@link #MEDIA_MOUNTED_READ_ONLY}, {@link #MEDIA_SHARED},
810     *         {@link #MEDIA_BAD_REMOVAL}, or {@link #MEDIA_UNMOUNTABLE}.
811     */
812    public static String getExternalStorageState(File path) {
813        final StorageVolume volume = StorageManager.getStorageVolume(path, UserHandle.myUserId());
814        if (volume != null) {
815            return volume.getState();
816        } else {
817            return MEDIA_UNKNOWN;
818        }
819    }
820
821    /**
822     * Returns whether the primary shared/external storage media is physically
823     * removable.
824     *
825     * @return true if the storage device can be removed (such as an SD card),
826     *         or false if the storage device is built in and cannot be
827     *         physically removed.
828     */
829    public static boolean isExternalStorageRemovable() {
830        if (isStorageDisabled()) return false;
831        final File externalDir = NoPreloadHolder.sCurrentUser.getExternalDirs()[0];
832        return isExternalStorageRemovable(externalDir);
833    }
834
835    /**
836     * Returns whether the shared/external storage media at the given path is
837     * physically removable.
838     *
839     * @return true if the storage device can be removed (such as an SD card),
840     *         or false if the storage device is built in and cannot be
841     *         physically removed.
842     * @throws IllegalArgumentException if the path is not a valid storage
843     *             device.
844     */
845    public static boolean isExternalStorageRemovable(File path) {
846        final StorageVolume volume = StorageManager.getStorageVolume(path, UserHandle.myUserId());
847        if (volume != null) {
848            return volume.isRemovable();
849        } else {
850            throw new IllegalArgumentException("Failed to find storage device at " + path);
851        }
852    }
853
854    /**
855     * Returns whether the primary shared/external storage media is emulated.
856     * <p>
857     * The contents of emulated storage devices are backed by a private user
858     * data partition, which means there is little benefit to apps storing data
859     * here instead of the private directories returned by
860     * {@link Context#getFilesDir()}, etc.
861     * <p>
862     * This returns true when emulated storage is backed by either internal
863     * storage or an adopted storage device.
864     *
865     * @see DevicePolicyManager#setStorageEncryption(android.content.ComponentName,
866     *      boolean)
867     */
868    public static boolean isExternalStorageEmulated() {
869        if (isStorageDisabled()) return false;
870        final File externalDir = NoPreloadHolder.sCurrentUser.getExternalDirs()[0];
871        return isExternalStorageEmulated(externalDir);
872    }
873
874    /**
875     * Returns whether the shared/external storage media at the given path is
876     * emulated.
877     * <p>
878     * The contents of emulated storage devices are backed by a private user
879     * data partition, which means there is little benefit to apps storing data
880     * here instead of the private directories returned by
881     * {@link Context#getFilesDir()}, etc.
882     * <p>
883     * This returns true when emulated storage is backed by either internal
884     * storage or an adopted storage device.
885     *
886     * @throws IllegalArgumentException if the path is not a valid storage
887     *             device.
888     */
889    public static boolean isExternalStorageEmulated(File path) {
890        final StorageVolume volume = StorageManager.getStorageVolume(path, UserHandle.myUserId());
891        if (volume != null) {
892            return volume.isEmulated();
893        } else {
894            throw new IllegalArgumentException("Failed to find storage device at " + path);
895        }
896    }
897
898    static File getDirectory(String variableName, String defaultPath) {
899        String path = System.getenv(variableName);
900        return path == null ? new File(defaultPath) : new File(path);
901    }
902
903    /** {@hide} */
904    public static void setUserRequired(boolean userRequired) {
905        NoPreloadHolder.sUserRequired = userRequired;
906    }
907
908    private static void throwIfUserRequired() {
909        if (NoPreloadHolder.sUserRequired) {
910            Log.wtf(TAG, "Path requests must specify a user by using UserEnvironment",
911                    new Throwable());
912        }
913    }
914
915    /**
916     * Append path segments to each given base path, returning result.
917     *
918     * @hide
919     */
920    public static File[] buildPaths(File[] base, String... segments) {
921        File[] result = new File[base.length];
922        for (int i = 0; i < base.length; i++) {
923            result[i] = buildPath(base[i], segments);
924        }
925        return result;
926    }
927
928    /**
929     * Append path segments to given base path, returning result.
930     *
931     * @hide
932     */
933    public static File buildPath(File base, String... segments) {
934        File cur = base;
935        for (String segment : segments) {
936            if (cur == null) {
937                cur = new File(segment);
938            } else {
939                cur = new File(cur, segment);
940            }
941        }
942        return cur;
943    }
944
945    private static boolean isStorageDisabled() {
946        return SystemProperties.getBoolean("config.disable_storage", false);
947    }
948
949    /**
950     * If the given path exists on emulated external storage, return the
951     * translated backing path hosted on internal storage. This bypasses any
952     * emulation later, improving performance. This is <em>only</em> suitable
953     * for read-only access.
954     * <p>
955     * Returns original path if given path doesn't meet these criteria. Callers
956     * must hold {@link android.Manifest.permission#WRITE_MEDIA_STORAGE}
957     * permission.
958     *
959     * @hide
960     */
961    public static File maybeTranslateEmulatedPathToInternal(File path) {
962        return StorageManager.maybeTranslateEmulatedPathToInternal(path);
963    }
964}
965