• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
17 package android.os;
18 
19 import android.content.res.Resources;
20 import android.os.storage.IMountService;
21 import android.os.storage.StorageVolume;
22 import android.util.Log;
23 
24 import java.io.File;
25 
26 /**
27  * Provides access to environment variables.
28  */
29 public 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 
getPrimaryVolume()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      */
getRootDirectory()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      */
getSystemSecureDirectory()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      */
getSecureDataDirectory()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      */
isEncryptedFilesystemEnabled()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      */
getDataDirectory()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      */
getExternalStorageDirectory()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      */
getExternalStoragePublicDirectory(String type)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      */
getExternalStorageAndroidDataDir()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      */
getExternalStorageAppDataDirectory(String packageName)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      */
getExternalStorageAppMediaDirectory(String packageName)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      */
getExternalStorageAppObbDirectory(String packageName)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      */
getExternalStorageAppFilesDirectory(String packageName)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      */
getExternalStorageAppCacheDirectory(String packageName)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      */
getDownloadCacheDirectory()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      */
getExternalStorageState()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      */
isExternalStorageRemovable()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      */
isExternalStorageEmulated()455     public static boolean isExternalStorageEmulated() {
456         StorageVolume volume = getPrimaryVolume();
457         return (volume != null && volume.isEmulated());
458     }
459 
getDirectory(String variableName, String defaultPath)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