Environment.java revision b2278dc1853241b4868c89ba3dab6b86b1c7ec53
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 java.io.File;
20
21import android.content.res.Resources;
22import android.os.storage.IMountService;
23import android.util.Log;
24
25/**
26 * Provides access to environment variables.
27 */
28public class Environment {
29    private static final String TAG = "Environment";
30
31    private static final File ROOT_DIRECTORY
32            = getDirectory("ANDROID_ROOT", "/system");
33
34    private static final String SYSTEM_PROPERTY_EFS_ENABLED = "persist.security.efs.enabled";
35
36    private static final Object mLock = new Object();
37
38    private volatile static Boolean mIsExternalStorageEmulated = null;
39
40    /**
41     * Gets the Android root directory.
42     */
43    public static File getRootDirectory() {
44        return ROOT_DIRECTORY;
45    }
46
47    /**
48     * Gets the system directory available for secure storage.
49     * If Encrypted File system is enabled, it returns an encrypted directory (/data/secure/system).
50     * Otherwise, it returns the unencrypted /data/system directory.
51     * @return File object representing the secure storage system directory.
52     * @hide
53     */
54    public static File getSystemSecureDirectory() {
55        if (isEncryptedFilesystemEnabled()) {
56            return new File(SECURE_DATA_DIRECTORY, "system");
57        } else {
58            return new File(DATA_DIRECTORY, "system");
59        }
60    }
61
62    /**
63     * Gets the data directory for secure storage.
64     * If Encrypted File system is enabled, it returns an encrypted directory (/data/secure).
65     * Otherwise, it returns the unencrypted /data directory.
66     * @return File object representing the data directory for secure storage.
67     * @hide
68     */
69    public static File getSecureDataDirectory() {
70        if (isEncryptedFilesystemEnabled()) {
71            return SECURE_DATA_DIRECTORY;
72        } else {
73            return DATA_DIRECTORY;
74        }
75    }
76
77    /**
78     * Returns whether the Encrypted File System feature is enabled on the device or not.
79     * @return <code>true</code> if Encrypted File System feature is enabled, <code>false</code>
80     * if disabled.
81     * @hide
82     */
83    public static boolean isEncryptedFilesystemEnabled() {
84        return SystemProperties.getBoolean(SYSTEM_PROPERTY_EFS_ENABLED, false);
85    }
86
87    private static final File DATA_DIRECTORY
88            = getDirectory("ANDROID_DATA", "/data");
89
90    /**
91     * @hide
92     */
93    private static final File SECURE_DATA_DIRECTORY
94            = getDirectory("ANDROID_SECURE_DATA", "/data/secure");
95
96    private static final File EXTERNAL_STORAGE_DIRECTORY
97            = getDirectory("EXTERNAL_STORAGE", "/sdcard");
98
99    private static final File EXTERNAL_STORAGE_ANDROID_DATA_DIRECTORY
100            = new File (new File(getDirectory("EXTERNAL_STORAGE", "/sdcard"),
101                    "Android"), "data");
102
103    private static final File EXTERNAL_STORAGE_ANDROID_MEDIA_DIRECTORY
104            = new File (new File(getDirectory("EXTERNAL_STORAGE", "/sdcard"),
105                    "Android"), "media");
106
107    private static final File EXTERNAL_STORAGE_ANDROID_OBB_DIRECTORY
108            = new File (new File(getDirectory("EXTERNAL_STORAGE", "/sdcard"),
109                    "Android"), "obb");
110
111    private static final File DOWNLOAD_CACHE_DIRECTORY
112            = getDirectory("DOWNLOAD_CACHE", "/cache");
113
114    /**
115     * Gets the Android data directory.
116     */
117    public static File getDataDirectory() {
118        return DATA_DIRECTORY;
119    }
120
121    /**
122     * Gets the Android external storage directory.  This directory may not
123     * currently be accessible if it has been mounted by the user on their
124     * computer, has been removed from the device, or some other problem has
125     * happened.  You can determine its current state with
126     * {@link #getExternalStorageState()}.
127     *
128     * <p><em>Note: don't be confused by the word "external" here.  This
129     * directory can better be thought as media/shared storage.  It is a
130     * filesystem that can hold a relatively large amount of data and that
131     * is shared across all applications (does not enforce permissions).
132     * Traditionally this is an SD card, but it may also be implemented as
133     * built-in storage in a device that is distinct from the protected
134     * internal storage and can be mounted as a filesystem on a computer.</em></p>
135     *
136     * <p>In devices with multiple "external" storage directories (such as
137     * both secure app storage and mountable shared storage), this directory
138     * represents the "primary" external storage that the user will interact
139     * with.</p>
140     *
141     * <p>Applications should not directly use this top-level directory, in
142     * order to avoid polluting the user's root namespace.  Any files that are
143     * private to the application should be placed in a directory returned
144     * by {@link android.content.Context#getExternalFilesDir
145     * Context.getExternalFilesDir}, which the system will take care of deleting
146     * if the application is uninstalled.  Other shared files should be placed
147     * in one of the directories returned by
148     * {@link #getExternalStoragePublicDirectory}.
149     *
150     * <p>Here is an example of typical code to monitor the state of
151     * external storage:</p>
152     *
153     * {@sample development/samples/ApiDemos/src/com/example/android/apis/content/ExternalStorage.java
154     * monitor_storage}
155     *
156     * @see #getExternalStorageState()
157     * @see #isExternalStorageRemovable()
158     */
159    public static File getExternalStorageDirectory() {
160        return EXTERNAL_STORAGE_DIRECTORY;
161    }
162
163    /**
164     * Standard directory in which to place any audio files that should be
165     * in the regular list of music for the user.
166     * This may be combined with
167     * {@link #DIRECTORY_PODCASTS}, {@link #DIRECTORY_NOTIFICATIONS},
168     * {@link #DIRECTORY_ALARMS}, and {@link #DIRECTORY_RINGTONES} as a series
169     * of directories to categories a particular audio file as more than one
170     * type.
171     */
172    public static String DIRECTORY_MUSIC = "Music";
173
174    /**
175     * Standard directory in which to place any audio files that should be
176     * in the list of podcasts that the user can select (not as regular
177     * music).
178     * This may be combined with {@link #DIRECTORY_MUSIC},
179     * {@link #DIRECTORY_NOTIFICATIONS},
180     * {@link #DIRECTORY_ALARMS}, and {@link #DIRECTORY_RINGTONES} as a series
181     * of directories to categories a particular audio file as more than one
182     * type.
183     */
184    public static String DIRECTORY_PODCASTS = "Podcasts";
185
186    /**
187     * Standard directory in which to place any audio files that should be
188     * in the list of ringtones that the user can select (not as regular
189     * music).
190     * This may be combined with {@link #DIRECTORY_MUSIC},
191     * {@link #DIRECTORY_PODCASTS}, {@link #DIRECTORY_NOTIFICATIONS}, and
192     * {@link #DIRECTORY_ALARMS} as a series
193     * of directories to categories a particular audio file as more than one
194     * type.
195     */
196    public static String DIRECTORY_RINGTONES = "Ringtones";
197
198    /**
199     * Standard directory in which to place any audio files that should be
200     * in the list of alarms that the user can select (not as regular
201     * music).
202     * This may be combined with {@link #DIRECTORY_MUSIC},
203     * {@link #DIRECTORY_PODCASTS}, {@link #DIRECTORY_NOTIFICATIONS},
204     * and {@link #DIRECTORY_RINGTONES} as a series
205     * of directories to categories a particular audio file as more than one
206     * type.
207     */
208    public static String DIRECTORY_ALARMS = "Alarms";
209
210    /**
211     * Standard directory in which to place any audio files that should be
212     * in the list of notifications that the user can select (not as regular
213     * music).
214     * This may be combined with {@link #DIRECTORY_MUSIC},
215     * {@link #DIRECTORY_PODCASTS},
216     * {@link #DIRECTORY_ALARMS}, and {@link #DIRECTORY_RINGTONES} as a series
217     * of directories to categories a particular audio file as more than one
218     * type.
219     */
220    public static String DIRECTORY_NOTIFICATIONS = "Notifications";
221
222    /**
223     * Standard directory in which to place pictures that are available to
224     * the user.  Note that this is primarily a convention for the top-level
225     * public directory, as the media scanner will find and collect pictures
226     * in any directory.
227     */
228    public static String DIRECTORY_PICTURES = "Pictures";
229
230    /**
231     * Standard directory in which to place movies that are available to
232     * the user.  Note that this is primarily a convention for the top-level
233     * public directory, as the media scanner will find and collect movies
234     * in any directory.
235     */
236    public static String DIRECTORY_MOVIES = "Movies";
237
238    /**
239     * Standard directory in which to place files that have been downloaded by
240     * the user.  Note that this is primarily a convention for the top-level
241     * public directory, you are free to download files anywhere in your own
242     * private directories.  Also note that though the constant here is
243     * named DIRECTORY_DOWNLOADS (plural), the actual file name is non-plural for
244     * backwards compatibility reasons.
245     */
246    public static String DIRECTORY_DOWNLOADS = "Download";
247
248    /**
249     * The traditional location for pictures and videos when mounting the
250     * device as a camera.  Note that this is primarily a convention for the
251     * top-level public directory, as this convention makes no sense elsewhere.
252     */
253    public static String DIRECTORY_DCIM = "DCIM";
254
255    /**
256     * Get a top-level public external storage directory for placing files of
257     * a particular type.  This is where the user will typically place and
258     * manage their own files, so you should be careful about what you put here
259     * to ensure you don't erase their files or get in the way of their own
260     * organization.
261     *
262     * <p>Here is an example of typical code to manipulate a picture on
263     * the public external storage:</p>
264     *
265     * {@sample development/samples/ApiDemos/src/com/example/android/apis/content/ExternalStorage.java
266     * public_picture}
267     *
268     * @param type The type of storage directory to return.  Should be one of
269     * {@link #DIRECTORY_MUSIC}, {@link #DIRECTORY_PODCASTS},
270     * {@link #DIRECTORY_RINGTONES}, {@link #DIRECTORY_ALARMS},
271     * {@link #DIRECTORY_NOTIFICATIONS}, {@link #DIRECTORY_PICTURES},
272     * {@link #DIRECTORY_MOVIES}, {@link #DIRECTORY_DOWNLOADS}, or
273     * {@link #DIRECTORY_DCIM}.  May not be null.
274     *
275     * @return Returns the File path for the directory.  Note that this
276     * directory may not yet exist, so you must make sure it exists before
277     * using it such as with {@link File#mkdirs File.mkdirs()}.
278     */
279    public static File getExternalStoragePublicDirectory(String type) {
280        return new File(getExternalStorageDirectory(), type);
281    }
282
283    /**
284     * Returns the path for android-specific data on the SD card.
285     * @hide
286     */
287    public static File getExternalStorageAndroidDataDir() {
288        return EXTERNAL_STORAGE_ANDROID_DATA_DIRECTORY;
289    }
290
291    /**
292     * Generates the raw path to an application's data
293     * @hide
294     */
295    public static File getExternalStorageAppDataDirectory(String packageName) {
296        return new File(EXTERNAL_STORAGE_ANDROID_DATA_DIRECTORY, packageName);
297    }
298
299    /**
300     * Generates the raw path to an application's media
301     * @hide
302     */
303    public static File getExternalStorageAppMediaDirectory(String packageName) {
304        return new File(EXTERNAL_STORAGE_ANDROID_MEDIA_DIRECTORY, packageName);
305    }
306
307    /**
308     * Generates the raw path to an application's OBB files
309     * @hide
310     */
311    public static File getExternalStorageAppObbDirectory(String packageName) {
312        return new File(EXTERNAL_STORAGE_ANDROID_OBB_DIRECTORY, packageName);
313    }
314
315    /**
316     * Generates the path to an application's files.
317     * @hide
318     */
319    public static File getExternalStorageAppFilesDirectory(String packageName) {
320        return new File(new File(EXTERNAL_STORAGE_ANDROID_DATA_DIRECTORY,
321                packageName), "files");
322    }
323
324    /**
325     * Generates the path to an application's cache.
326     * @hide
327     */
328    public static File getExternalStorageAppCacheDirectory(String packageName) {
329        return new File(new File(EXTERNAL_STORAGE_ANDROID_DATA_DIRECTORY,
330                packageName), "cache");
331    }
332
333    /**
334     * Gets the Android Download/Cache content directory.
335     */
336    public static File getDownloadCacheDirectory() {
337        return DOWNLOAD_CACHE_DIRECTORY;
338    }
339
340    /**
341     * getExternalStorageState() returns MEDIA_REMOVED if the media is not present.
342     */
343    public static final String MEDIA_REMOVED = "removed";
344
345    /**
346     * getExternalStorageState() returns MEDIA_UNMOUNTED if the media is present
347     * but not mounted.
348     */
349    public static final String MEDIA_UNMOUNTED = "unmounted";
350
351    /**
352     * getExternalStorageState() returns MEDIA_CHECKING if the media is present
353     * and being disk-checked
354     */
355    public static final String MEDIA_CHECKING = "checking";
356
357    /**
358     * getExternalStorageState() returns MEDIA_NOFS if the media is present
359     * but is blank or is using an unsupported filesystem
360     */
361    public static final String MEDIA_NOFS = "nofs";
362
363    /**
364     * getExternalStorageState() returns MEDIA_MOUNTED if the media is present
365     * and mounted at its mount point with read/write access.
366     */
367    public static final String MEDIA_MOUNTED = "mounted";
368
369    /**
370     * getExternalStorageState() returns MEDIA_MOUNTED_READ_ONLY if the media is present
371     * and mounted at its mount point with read only access.
372     */
373    public static final String MEDIA_MOUNTED_READ_ONLY = "mounted_ro";
374
375    /**
376     * getExternalStorageState() returns MEDIA_SHARED if the media is present
377     * not mounted, and shared via USB mass storage.
378     */
379    public static final String MEDIA_SHARED = "shared";
380
381    /**
382     * getExternalStorageState() returns MEDIA_BAD_REMOVAL if the media was
383     * removed before it was unmounted.
384     */
385    public static final String MEDIA_BAD_REMOVAL = "bad_removal";
386
387    /**
388     * getExternalStorageState() returns MEDIA_UNMOUNTABLE if the media is present
389     * but cannot be mounted.  Typically this happens if the file system on the
390     * media is corrupted.
391     */
392    public static final String MEDIA_UNMOUNTABLE = "unmountable";
393
394    /**
395     * Gets the current state of the primary "external" storage device.
396     *
397     * <p>See {@link #getExternalStorageDirectory()} for more information.
398     */
399    public static String getExternalStorageState() {
400        try {
401            IMountService mountService = IMountService.Stub.asInterface(ServiceManager
402                    .getService("mount"));
403            return mountService.getVolumeState(getExternalStorageDirectory()
404                    .toString());
405        } catch (Exception rex) {
406            return Environment.MEDIA_REMOVED;
407        }
408    }
409
410    /**
411     * Returns whether the primary "external" storage device is removable.
412     * If true is returned, this device is for example an SD card that the
413     * user can remove.  If false is returned, the storage is built into
414     * the device and can not be physically removed.
415     *
416     * <p>See {@link #getExternalStorageDirectory()} for more information.
417     */
418    public static boolean isExternalStorageRemovable() {
419        return Resources.getSystem().getBoolean(
420                com.android.internal.R.bool.config_externalStorageRemovable);
421    }
422
423    /**
424     * Returns whether the device has an external storage device which is
425     * emulated. If true, the device does not have real external storage
426     * and certain system services such as the package manager use this
427     * to determine where to install an application.
428     */
429    public static boolean isExternalStorageEmulated() {
430        if (mIsExternalStorageEmulated == null) {
431            synchronized (mLock) {
432                if (mIsExternalStorageEmulated == null) {
433                    boolean externalStorageEmulated;
434                    try {
435                        IMountService mountService = IMountService.Stub.asInterface(ServiceManager
436                                .getService("mount"));
437                        externalStorageEmulated = mountService.isExternalStorageEmulated();
438                        mIsExternalStorageEmulated = Boolean.valueOf(externalStorageEmulated);
439                    } catch (Exception e) {
440                        Log.e(TAG, "couldn't talk to MountService", e);
441                        return false;
442                    }
443                }
444            }
445        }
446        return mIsExternalStorageEmulated;
447    }
448
449    static File getDirectory(String variableName, String defaultPath) {
450        String path = System.getenv(variableName);
451        return path == null ? new File(defaultPath) : new File(path);
452    }
453}
454