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 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