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