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.os.storage.IMountService; 20 import android.os.storage.StorageManager; 21 import android.os.storage.StorageVolume; 22 import android.text.TextUtils; 23 import android.util.Log; 24 25 import java.io.File; 26 27 /** 28 * Provides access to environment variables. 29 */ 30 public class Environment { 31 private static final String TAG = "Environment"; 32 33 private static final String ENV_EXTERNAL_STORAGE = "EXTERNAL_STORAGE"; 34 private static final String ENV_EMULATED_STORAGE_SOURCE = "EMULATED_STORAGE_SOURCE"; 35 private static final String ENV_EMULATED_STORAGE_TARGET = "EMULATED_STORAGE_TARGET"; 36 private static final String ENV_MEDIA_STORAGE = "MEDIA_STORAGE"; 37 38 /** {@hide} */ 39 public static String DIRECTORY_ANDROID = "Android"; 40 41 private static final File ROOT_DIRECTORY 42 = getDirectory("ANDROID_ROOT", "/system"); 43 44 private static final String SYSTEM_PROPERTY_EFS_ENABLED = "persist.security.efs.enabled"; 45 46 private static UserEnvironment sCurrentUser; 47 48 private static final Object sLock = new Object(); 49 50 // @GuardedBy("sLock") 51 private static volatile StorageVolume sPrimaryVolume; 52 53 private static StorageVolume getPrimaryVolume() { 54 if (sPrimaryVolume == null) { 55 synchronized (sLock) { 56 if (sPrimaryVolume == null) { 57 try { 58 IMountService mountService = IMountService.Stub.asInterface(ServiceManager 59 .getService("mount")); 60 final StorageVolume[] volumes = mountService.getVolumeList(); 61 sPrimaryVolume = StorageManager.getPrimaryVolume(volumes); 62 } catch (Exception e) { 63 Log.e(TAG, "couldn't talk to MountService", e); 64 } 65 } 66 } 67 } 68 return sPrimaryVolume; 69 } 70 71 static { 72 initForCurrentUser(); 73 } 74 75 /** {@hide} */ 76 public static void initForCurrentUser() { 77 final int userId = UserHandle.myUserId(); 78 sCurrentUser = new UserEnvironment(userId); 79 80 synchronized (sLock) { 81 sPrimaryVolume = null; 82 } 83 } 84 85 /** {@hide} */ 86 public static class UserEnvironment { 87 // TODO: generalize further to create package-specific environment 88 89 private final File mExternalStorage; 90 private final File mExternalStorageAndroidData; 91 private final File mExternalStorageAndroidMedia; 92 private final File mExternalStorageAndroidObb; 93 private final File mMediaStorage; 94 95 public UserEnvironment(int userId) { 96 // See storage config details at http://source.android.com/tech/storage/ 97 String rawExternalStorage = System.getenv(ENV_EXTERNAL_STORAGE); 98 String rawEmulatedStorageTarget = System.getenv(ENV_EMULATED_STORAGE_TARGET); 99 String rawMediaStorage = System.getenv(ENV_MEDIA_STORAGE); 100 if (TextUtils.isEmpty(rawMediaStorage)) { 101 rawMediaStorage = "/data/media"; 102 } 103 104 if (!TextUtils.isEmpty(rawEmulatedStorageTarget)) { 105 // Device has emulated storage; external storage paths should have 106 // userId burned into them. 107 final String rawUserId = Integer.toString(userId); 108 final File emulatedBase = new File(rawEmulatedStorageTarget); 109 final File mediaBase = new File(rawMediaStorage); 110 111 // /storage/emulated/0 112 mExternalStorage = buildPath(emulatedBase, rawUserId); 113 // /data/media/0 114 mMediaStorage = buildPath(mediaBase, rawUserId); 115 116 } else { 117 // Device has physical external storage; use plain paths. 118 if (TextUtils.isEmpty(rawExternalStorage)) { 119 Log.w(TAG, "EXTERNAL_STORAGE undefined; falling back to default"); 120 rawExternalStorage = "/storage/sdcard0"; 121 } 122 123 // /storage/sdcard0 124 mExternalStorage = new File(rawExternalStorage); 125 // /data/media 126 mMediaStorage = new File(rawMediaStorage); 127 } 128 129 mExternalStorageAndroidObb = buildPath(mExternalStorage, DIRECTORY_ANDROID, "obb"); 130 mExternalStorageAndroidData = buildPath(mExternalStorage, DIRECTORY_ANDROID, "data"); 131 mExternalStorageAndroidMedia = buildPath(mExternalStorage, DIRECTORY_ANDROID, "media"); 132 } 133 134 public File getExternalStorageDirectory() { 135 return mExternalStorage; 136 } 137 138 public File getExternalStorageObbDirectory() { 139 return mExternalStorageAndroidObb; 140 } 141 142 public File getExternalStoragePublicDirectory(String type) { 143 return new File(mExternalStorage, type); 144 } 145 146 public File getExternalStorageAndroidDataDir() { 147 return mExternalStorageAndroidData; 148 } 149 150 public File getExternalStorageAppDataDirectory(String packageName) { 151 return new File(mExternalStorageAndroidData, packageName); 152 } 153 154 public File getExternalStorageAppMediaDirectory(String packageName) { 155 return new File(mExternalStorageAndroidMedia, packageName); 156 } 157 158 public File getExternalStorageAppObbDirectory(String packageName) { 159 return new File(mExternalStorageAndroidObb, packageName); 160 } 161 162 public File getExternalStorageAppFilesDirectory(String packageName) { 163 return new File(new File(mExternalStorageAndroidData, packageName), "files"); 164 } 165 166 public File getExternalStorageAppCacheDirectory(String packageName) { 167 return new File(new File(mExternalStorageAndroidData, packageName), "cache"); 168 } 169 170 public File getMediaStorageDirectory() { 171 return mMediaStorage; 172 } 173 } 174 175 /** 176 * Gets the Android root directory. 177 */ 178 public static File getRootDirectory() { 179 return ROOT_DIRECTORY; 180 } 181 182 /** 183 * Gets the system directory available for secure storage. 184 * If Encrypted File system is enabled, it returns an encrypted directory (/data/secure/system). 185 * Otherwise, it returns the unencrypted /data/system directory. 186 * @return File object representing the secure storage system directory. 187 * @hide 188 */ 189 public static File getSystemSecureDirectory() { 190 if (isEncryptedFilesystemEnabled()) { 191 return new File(SECURE_DATA_DIRECTORY, "system"); 192 } else { 193 return new File(DATA_DIRECTORY, "system"); 194 } 195 } 196 197 /** 198 * Gets the data directory for secure storage. 199 * If Encrypted File system is enabled, it returns an encrypted directory (/data/secure). 200 * Otherwise, it returns the unencrypted /data directory. 201 * @return File object representing the data directory for secure storage. 202 * @hide 203 */ 204 public static File getSecureDataDirectory() { 205 if (isEncryptedFilesystemEnabled()) { 206 return SECURE_DATA_DIRECTORY; 207 } else { 208 return DATA_DIRECTORY; 209 } 210 } 211 212 /** 213 * Return directory used for internal media storage, which is protected by 214 * {@link android.Manifest.permission#WRITE_MEDIA_STORAGE}. 215 * 216 * @hide 217 */ 218 public static File getMediaStorageDirectory() { 219 throwIfSystem(); 220 return sCurrentUser.getMediaStorageDirectory(); 221 } 222 223 /** 224 * Return the system directory for a user. This is for use by system services to store 225 * files relating to the user. This directory will be automatically deleted when the user 226 * is removed. 227 * 228 * @hide 229 */ 230 public static File getUserSystemDirectory(int userId) { 231 return new File(new File(getSystemSecureDirectory(), "users"), Integer.toString(userId)); 232 } 233 234 /** 235 * Returns whether the Encrypted File System feature is enabled on the device or not. 236 * @return <code>true</code> if Encrypted File System feature is enabled, <code>false</code> 237 * if disabled. 238 * @hide 239 */ 240 public static boolean isEncryptedFilesystemEnabled() { 241 return SystemProperties.getBoolean(SYSTEM_PROPERTY_EFS_ENABLED, false); 242 } 243 244 private static final File DATA_DIRECTORY 245 = getDirectory("ANDROID_DATA", "/data"); 246 247 /** 248 * @hide 249 */ 250 private static final File SECURE_DATA_DIRECTORY 251 = getDirectory("ANDROID_SECURE_DATA", "/data/secure"); 252 253 private static final File DOWNLOAD_CACHE_DIRECTORY = getDirectory("DOWNLOAD_CACHE", "/cache"); 254 255 /** 256 * Gets the Android data directory. 257 */ 258 public static File getDataDirectory() { 259 return DATA_DIRECTORY; 260 } 261 262 /** 263 * Gets the Android external storage directory. This directory may not 264 * currently be accessible if it has been mounted by the user on their 265 * computer, has been removed from the device, or some other problem has 266 * happened. You can determine its current state with 267 * {@link #getExternalStorageState()}. 268 * 269 * <p><em>Note: don't be confused by the word "external" here. This 270 * directory can better be thought as media/shared storage. It is a 271 * filesystem that can hold a relatively large amount of data and that 272 * is shared across all applications (does not enforce permissions). 273 * Traditionally this is an SD card, but it may also be implemented as 274 * built-in storage in a device that is distinct from the protected 275 * internal storage and can be mounted as a filesystem on a computer.</em></p> 276 * 277 * <p>On devices with multiple users (as described by {@link UserManager}), 278 * each user has their own isolated external storage. Applications only 279 * have access to the external storage for the user they're running as.</p> 280 * 281 * <p>In devices with multiple "external" storage directories (such as 282 * both secure app storage and mountable shared storage), this directory 283 * represents the "primary" external storage that the user will interact 284 * with.</p> 285 * 286 * <p>Applications should not directly use this top-level directory, in 287 * order to avoid polluting the user's root namespace. Any files that are 288 * private to the application should be placed in a directory returned 289 * by {@link android.content.Context#getExternalFilesDir 290 * Context.getExternalFilesDir}, which the system will take care of deleting 291 * if the application is uninstalled. Other shared files should be placed 292 * in one of the directories returned by 293 * {@link #getExternalStoragePublicDirectory}.</p> 294 * 295 * <p>Writing to this path requires the 296 * {@link android.Manifest.permission#WRITE_EXTERNAL_STORAGE} permission. In 297 * a future platform release, access to this path will require the 298 * {@link android.Manifest.permission#READ_EXTERNAL_STORAGE} permission, 299 * which is automatically granted if you hold the write permission.</p> 300 * 301 * <p>This path may change between platform versions, so applications 302 * should only persist relative paths.</p> 303 * 304 * <p>Here is an example of typical code to monitor the state of 305 * external storage:</p> 306 * 307 * {@sample development/samples/ApiDemos/src/com/example/android/apis/content/ExternalStorage.java 308 * monitor_storage} 309 * 310 * @see #getExternalStorageState() 311 * @see #isExternalStorageRemovable() 312 */ 313 public static File getExternalStorageDirectory() { 314 throwIfSystem(); 315 return sCurrentUser.getExternalStorageDirectory(); 316 } 317 318 /** {@hide} */ 319 public static File getLegacyExternalStorageDirectory() { 320 return new File(System.getenv(ENV_EXTERNAL_STORAGE)); 321 } 322 323 /** {@hide} */ 324 public static File getLegacyExternalStorageObbDirectory() { 325 return buildPath(getLegacyExternalStorageDirectory(), DIRECTORY_ANDROID, "obb"); 326 } 327 328 /** {@hide} */ 329 public static File getEmulatedStorageSource(int userId) { 330 // /mnt/shell/emulated/0 331 return new File(System.getenv(ENV_EMULATED_STORAGE_SOURCE), String.valueOf(userId)); 332 } 333 334 /** {@hide} */ 335 public static File getEmulatedStorageObbSource() { 336 // /mnt/shell/emulated/obb 337 return new File(System.getenv(ENV_EMULATED_STORAGE_SOURCE), "obb"); 338 } 339 340 /** 341 * Standard directory in which to place any audio files that should be 342 * in the regular list of music for the user. 343 * This may be combined with 344 * {@link #DIRECTORY_PODCASTS}, {@link #DIRECTORY_NOTIFICATIONS}, 345 * {@link #DIRECTORY_ALARMS}, and {@link #DIRECTORY_RINGTONES} as a series 346 * of directories to categories a particular audio file as more than one 347 * type. 348 */ 349 public static String DIRECTORY_MUSIC = "Music"; 350 351 /** 352 * Standard directory in which to place any audio files that should be 353 * in the list of podcasts that the user can select (not as regular 354 * music). 355 * This may be combined with {@link #DIRECTORY_MUSIC}, 356 * {@link #DIRECTORY_NOTIFICATIONS}, 357 * {@link #DIRECTORY_ALARMS}, and {@link #DIRECTORY_RINGTONES} as a series 358 * of directories to categories a particular audio file as more than one 359 * type. 360 */ 361 public static String DIRECTORY_PODCASTS = "Podcasts"; 362 363 /** 364 * Standard directory in which to place any audio files that should be 365 * in the list of ringtones that the user can select (not as regular 366 * music). 367 * This may be combined with {@link #DIRECTORY_MUSIC}, 368 * {@link #DIRECTORY_PODCASTS}, {@link #DIRECTORY_NOTIFICATIONS}, and 369 * {@link #DIRECTORY_ALARMS} as a series 370 * of directories to categories a particular audio file as more than one 371 * type. 372 */ 373 public static String DIRECTORY_RINGTONES = "Ringtones"; 374 375 /** 376 * Standard directory in which to place any audio files that should be 377 * in the list of alarms that the user can select (not as regular 378 * music). 379 * This may be combined with {@link #DIRECTORY_MUSIC}, 380 * {@link #DIRECTORY_PODCASTS}, {@link #DIRECTORY_NOTIFICATIONS}, 381 * and {@link #DIRECTORY_RINGTONES} as a series 382 * of directories to categories a particular audio file as more than one 383 * type. 384 */ 385 public static String DIRECTORY_ALARMS = "Alarms"; 386 387 /** 388 * Standard directory in which to place any audio files that should be 389 * in the list of notifications that the user can select (not as regular 390 * music). 391 * This may be combined with {@link #DIRECTORY_MUSIC}, 392 * {@link #DIRECTORY_PODCASTS}, 393 * {@link #DIRECTORY_ALARMS}, and {@link #DIRECTORY_RINGTONES} as a series 394 * of directories to categories a particular audio file as more than one 395 * type. 396 */ 397 public static String DIRECTORY_NOTIFICATIONS = "Notifications"; 398 399 /** 400 * Standard directory in which to place pictures that are available to 401 * the user. Note that this is primarily a convention for the top-level 402 * public directory, as the media scanner will find and collect pictures 403 * in any directory. 404 */ 405 public static String DIRECTORY_PICTURES = "Pictures"; 406 407 /** 408 * Standard directory in which to place movies that are available to 409 * the user. Note that this is primarily a convention for the top-level 410 * public directory, as the media scanner will find and collect movies 411 * in any directory. 412 */ 413 public static String DIRECTORY_MOVIES = "Movies"; 414 415 /** 416 * Standard directory in which to place files that have been downloaded by 417 * the user. Note that this is primarily a convention for the top-level 418 * public directory, you are free to download files anywhere in your own 419 * private directories. Also note that though the constant here is 420 * named DIRECTORY_DOWNLOADS (plural), the actual file name is non-plural for 421 * backwards compatibility reasons. 422 */ 423 public static String DIRECTORY_DOWNLOADS = "Download"; 424 425 /** 426 * The traditional location for pictures and videos when mounting the 427 * device as a camera. Note that this is primarily a convention for the 428 * top-level public directory, as this convention makes no sense elsewhere. 429 */ 430 public static String DIRECTORY_DCIM = "DCIM"; 431 432 /** 433 * Get a top-level public external storage directory for placing files of 434 * a particular type. This is where the user will typically place and 435 * manage their own files, so you should be careful about what you put here 436 * to ensure you don't erase their files or get in the way of their own 437 * organization. 438 * 439 * <p>On devices with multiple users (as described by {@link UserManager}), 440 * each user has their own isolated external storage. Applications only 441 * have access to the external storage for the user they're running as.</p> 442 * 443 * <p>Here is an example of typical code to manipulate a picture on 444 * the public external storage:</p> 445 * 446 * {@sample development/samples/ApiDemos/src/com/example/android/apis/content/ExternalStorage.java 447 * public_picture} 448 * 449 * @param type The type of storage directory to return. Should be one of 450 * {@link #DIRECTORY_MUSIC}, {@link #DIRECTORY_PODCASTS}, 451 * {@link #DIRECTORY_RINGTONES}, {@link #DIRECTORY_ALARMS}, 452 * {@link #DIRECTORY_NOTIFICATIONS}, {@link #DIRECTORY_PICTURES}, 453 * {@link #DIRECTORY_MOVIES}, {@link #DIRECTORY_DOWNLOADS}, or 454 * {@link #DIRECTORY_DCIM}. May not be null. 455 * 456 * @return Returns the File path for the directory. Note that this 457 * directory may not yet exist, so you must make sure it exists before 458 * using it such as with {@link File#mkdirs File.mkdirs()}. 459 */ 460 public static File getExternalStoragePublicDirectory(String type) { 461 throwIfSystem(); 462 return sCurrentUser.getExternalStoragePublicDirectory(type); 463 } 464 465 /** 466 * Returns the path for android-specific data on the SD card. 467 * @hide 468 */ 469 public static File getExternalStorageAndroidDataDir() { 470 throwIfSystem(); 471 return sCurrentUser.getExternalStorageAndroidDataDir(); 472 } 473 474 /** 475 * Generates the raw path to an application's data 476 * @hide 477 */ 478 public static File getExternalStorageAppDataDirectory(String packageName) { 479 throwIfSystem(); 480 return sCurrentUser.getExternalStorageAppDataDirectory(packageName); 481 } 482 483 /** 484 * Generates the raw path to an application's media 485 * @hide 486 */ 487 public static File getExternalStorageAppMediaDirectory(String packageName) { 488 throwIfSystem(); 489 return sCurrentUser.getExternalStorageAppMediaDirectory(packageName); 490 } 491 492 /** 493 * Generates the raw path to an application's OBB files 494 * @hide 495 */ 496 public static File getExternalStorageAppObbDirectory(String packageName) { 497 throwIfSystem(); 498 return sCurrentUser.getExternalStorageAppObbDirectory(packageName); 499 } 500 501 /** 502 * Generates the path to an application's files. 503 * @hide 504 */ 505 public static File getExternalStorageAppFilesDirectory(String packageName) { 506 throwIfSystem(); 507 return sCurrentUser.getExternalStorageAppFilesDirectory(packageName); 508 } 509 510 /** 511 * Generates the path to an application's cache. 512 * @hide 513 */ 514 public static File getExternalStorageAppCacheDirectory(String packageName) { 515 throwIfSystem(); 516 return sCurrentUser.getExternalStorageAppCacheDirectory(packageName); 517 } 518 519 /** 520 * Gets the Android download/cache content directory. 521 */ 522 public static File getDownloadCacheDirectory() { 523 return DOWNLOAD_CACHE_DIRECTORY; 524 } 525 526 /** 527 * {@link #getExternalStorageState()} returns MEDIA_REMOVED if the media is not present. 528 */ 529 public static final String MEDIA_REMOVED = "removed"; 530 531 /** 532 * {@link #getExternalStorageState()} returns MEDIA_UNMOUNTED if the media is present 533 * but not mounted. 534 */ 535 public static final String MEDIA_UNMOUNTED = "unmounted"; 536 537 /** 538 * {@link #getExternalStorageState()} returns MEDIA_CHECKING if the media is present 539 * and being disk-checked 540 */ 541 public static final String MEDIA_CHECKING = "checking"; 542 543 /** 544 * {@link #getExternalStorageState()} returns MEDIA_NOFS if the media is present 545 * but is blank or is using an unsupported filesystem 546 */ 547 public static final String MEDIA_NOFS = "nofs"; 548 549 /** 550 * {@link #getExternalStorageState()} returns MEDIA_MOUNTED if the media is present 551 * and mounted at its mount point with read/write access. 552 */ 553 public static final String MEDIA_MOUNTED = "mounted"; 554 555 /** 556 * {@link #getExternalStorageState()} returns MEDIA_MOUNTED_READ_ONLY if the media is present 557 * and mounted at its mount point with read only access. 558 */ 559 public static final String MEDIA_MOUNTED_READ_ONLY = "mounted_ro"; 560 561 /** 562 * {@link #getExternalStorageState()} returns MEDIA_SHARED if the media is present 563 * not mounted, and shared via USB mass storage. 564 */ 565 public static final String MEDIA_SHARED = "shared"; 566 567 /** 568 * {@link #getExternalStorageState()} returns MEDIA_BAD_REMOVAL if the media was 569 * removed before it was unmounted. 570 */ 571 public static final String MEDIA_BAD_REMOVAL = "bad_removal"; 572 573 /** 574 * {@link #getExternalStorageState()} returns MEDIA_UNMOUNTABLE if the media is present 575 * but cannot be mounted. Typically this happens if the file system on the 576 * media is corrupted. 577 */ 578 public static final String MEDIA_UNMOUNTABLE = "unmountable"; 579 580 /** 581 * Gets the current state of the primary "external" storage device. 582 * 583 * @see #getExternalStorageDirectory() 584 */ 585 public static String getExternalStorageState() { 586 try { 587 IMountService mountService = IMountService.Stub.asInterface(ServiceManager 588 .getService("mount")); 589 final StorageVolume primary = getPrimaryVolume(); 590 return mountService.getVolumeState(primary.getPath()); 591 } catch (RemoteException rex) { 592 Log.w(TAG, "Failed to read external storage state; assuming REMOVED: " + rex); 593 return Environment.MEDIA_REMOVED; 594 } 595 } 596 597 /** 598 * Returns whether the primary "external" storage device is removable. 599 * If true is returned, this device is for example an SD card that the 600 * user can remove. If false is returned, the storage is built into 601 * the device and can not be physically removed. 602 * 603 * <p>See {@link #getExternalStorageDirectory()} for more information. 604 */ 605 public static boolean isExternalStorageRemovable() { 606 final StorageVolume primary = getPrimaryVolume(); 607 return (primary != null && primary.isRemovable()); 608 } 609 610 /** 611 * Returns whether the device has an external storage device which is 612 * emulated. If true, the device does not have real external storage, and the directory 613 * returned by {@link #getExternalStorageDirectory()} will be allocated using a portion of 614 * the internal storage system. 615 * 616 * <p>Certain system services, such as the package manager, use this 617 * to determine where to install an application. 618 * 619 * <p>Emulated external storage may also be encrypted - see 620 * {@link android.app.admin.DevicePolicyManager#setStorageEncryption( 621 * android.content.ComponentName, boolean)} for additional details. 622 */ 623 public static boolean isExternalStorageEmulated() { 624 final StorageVolume primary = getPrimaryVolume(); 625 return (primary != null && primary.isEmulated()); 626 } 627 628 static File getDirectory(String variableName, String defaultPath) { 629 String path = System.getenv(variableName); 630 return path == null ? new File(defaultPath) : new File(path); 631 } 632 633 private static void throwIfSystem() { 634 if (Process.myUid() == Process.SYSTEM_UID) { 635 Log.wtf(TAG, "Static storage paths aren't available from AID_SYSTEM", new Throwable()); 636 } 637 } 638 639 private static File buildPath(File base, String... segments) { 640 File cur = base; 641 for (String segment : segments) { 642 if (cur == null) { 643 cur = new File(segment); 644 } else { 645 cur = new File(cur, segment); 646 } 647 } 648 return cur; 649 } 650 } 651