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