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.app.admin.DevicePolicyManager; 20 import android.content.Context; 21 import android.os.storage.IMountService; 22 import android.os.storage.StorageVolume; 23 import android.text.TextUtils; 24 import android.util.Log; 25 26 import com.google.android.collect.Lists; 27 28 import java.io.File; 29 import java.io.IOException; 30 import java.util.ArrayList; 31 32 /** 33 * Provides access to environment variables. 34 */ 35 public class Environment { 36 private static final String TAG = "Environment"; 37 38 private static final String ENV_EXTERNAL_STORAGE = "EXTERNAL_STORAGE"; 39 private static final String ENV_EMULATED_STORAGE_SOURCE = "EMULATED_STORAGE_SOURCE"; 40 private static final String ENV_EMULATED_STORAGE_TARGET = "EMULATED_STORAGE_TARGET"; 41 private static final String ENV_MEDIA_STORAGE = "MEDIA_STORAGE"; 42 private static final String ENV_SECONDARY_STORAGE = "SECONDARY_STORAGE"; 43 private static final String ENV_ANDROID_ROOT = "ANDROID_ROOT"; 44 private static final String ENV_OEM_ROOT = "OEM_ROOT"; 45 private static final String ENV_VENDOR_ROOT = "VENDOR_ROOT"; 46 47 /** {@hide} */ 48 public static final String DIR_ANDROID = "Android"; 49 private static final String DIR_DATA = "data"; 50 private static final String DIR_MEDIA = "media"; 51 private static final String DIR_OBB = "obb"; 52 private static final String DIR_FILES = "files"; 53 private static final String DIR_CACHE = "cache"; 54 55 /** {@hide} */ 56 @Deprecated 57 public static final String DIRECTORY_ANDROID = DIR_ANDROID; 58 59 private static final File DIR_ANDROID_ROOT = getDirectory(ENV_ANDROID_ROOT, "/system"); 60 private static final File DIR_OEM_ROOT = getDirectory(ENV_OEM_ROOT, "/oem"); 61 private static final File DIR_VENDOR_ROOT = getDirectory(ENV_VENDOR_ROOT, "/vendor"); 62 private static final File DIR_MEDIA_STORAGE = getDirectory(ENV_MEDIA_STORAGE, "/data/media"); 63 64 private static final String CANONCIAL_EMULATED_STORAGE_TARGET = getCanonicalPathOrNull( 65 ENV_EMULATED_STORAGE_TARGET); 66 67 private static final String SYSTEM_PROPERTY_EFS_ENABLED = "persist.security.efs.enabled"; 68 69 private static UserEnvironment sCurrentUser; 70 private static boolean sUserRequired; 71 72 static { initForCurrentUser()73 initForCurrentUser(); 74 } 75 76 /** {@hide} */ initForCurrentUser()77 public static void initForCurrentUser() { 78 final int userId = UserHandle.myUserId(); 79 sCurrentUser = new UserEnvironment(userId); 80 } 81 82 /** {@hide} */ 83 public static class UserEnvironment { 84 // TODO: generalize further to create package-specific environment 85 86 /** External storage dirs, as visible to vold */ 87 private final File[] mExternalDirsForVold; 88 /** External storage dirs, as visible to apps */ 89 private final File[] mExternalDirsForApp; 90 /** Primary emulated storage dir for direct access */ 91 private final File mEmulatedDirForDirect; 92 UserEnvironment(int userId)93 public UserEnvironment(int userId) { 94 // See storage config details at http://source.android.com/tech/storage/ 95 String rawExternalStorage = System.getenv(ENV_EXTERNAL_STORAGE); 96 String rawEmulatedSource = System.getenv(ENV_EMULATED_STORAGE_SOURCE); 97 String rawEmulatedTarget = System.getenv(ENV_EMULATED_STORAGE_TARGET); 98 99 String rawMediaStorage = System.getenv(ENV_MEDIA_STORAGE); 100 if (TextUtils.isEmpty(rawMediaStorage)) { 101 rawMediaStorage = "/data/media"; 102 } 103 104 ArrayList<File> externalForVold = Lists.newArrayList(); 105 ArrayList<File> externalForApp = Lists.newArrayList(); 106 107 if (!TextUtils.isEmpty(rawEmulatedTarget)) { 108 // Device has emulated storage; external storage paths should have 109 // userId burned into them. 110 final String rawUserId = Integer.toString(userId); 111 final File emulatedSourceBase = new File(rawEmulatedSource); 112 final File emulatedTargetBase = new File(rawEmulatedTarget); 113 final File mediaBase = new File(rawMediaStorage); 114 115 // /storage/emulated/0 116 externalForVold.add(buildPath(emulatedSourceBase, rawUserId)); 117 externalForApp.add(buildPath(emulatedTargetBase, rawUserId)); 118 // /data/media/0 119 mEmulatedDirForDirect = buildPath(mediaBase, rawUserId); 120 121 } else { 122 // Device has physical external storage; use plain paths. 123 if (TextUtils.isEmpty(rawExternalStorage)) { 124 Log.w(TAG, "EXTERNAL_STORAGE undefined; falling back to default"); 125 rawExternalStorage = "/storage/sdcard0"; 126 } 127 128 // /storage/sdcard0 129 externalForVold.add(new File(rawExternalStorage)); 130 externalForApp.add(new File(rawExternalStorage)); 131 // /data/media 132 mEmulatedDirForDirect = new File(rawMediaStorage); 133 } 134 135 // Splice in any secondary storage paths, but only for owner 136 final String rawSecondaryStorage = System.getenv(ENV_SECONDARY_STORAGE); 137 if (!TextUtils.isEmpty(rawSecondaryStorage) && userId == UserHandle.USER_OWNER) { 138 for (String secondaryPath : rawSecondaryStorage.split(":")) { 139 externalForVold.add(new File(secondaryPath)); 140 externalForApp.add(new File(secondaryPath)); 141 } 142 } 143 144 mExternalDirsForVold = externalForVold.toArray(new File[externalForVold.size()]); 145 mExternalDirsForApp = externalForApp.toArray(new File[externalForApp.size()]); 146 } 147 148 @Deprecated getExternalStorageDirectory()149 public File getExternalStorageDirectory() { 150 return mExternalDirsForApp[0]; 151 } 152 153 @Deprecated getExternalStoragePublicDirectory(String type)154 public File getExternalStoragePublicDirectory(String type) { 155 return buildExternalStoragePublicDirs(type)[0]; 156 } 157 getExternalDirsForVold()158 public File[] getExternalDirsForVold() { 159 return mExternalDirsForVold; 160 } 161 getExternalDirsForApp()162 public File[] getExternalDirsForApp() { 163 return mExternalDirsForApp; 164 } 165 getMediaDir()166 public File getMediaDir() { 167 return mEmulatedDirForDirect; 168 } 169 buildExternalStoragePublicDirs(String type)170 public File[] buildExternalStoragePublicDirs(String type) { 171 return buildPaths(mExternalDirsForApp, type); 172 } 173 buildExternalStorageAndroidDataDirs()174 public File[] buildExternalStorageAndroidDataDirs() { 175 return buildPaths(mExternalDirsForApp, DIR_ANDROID, DIR_DATA); 176 } 177 buildExternalStorageAndroidObbDirs()178 public File[] buildExternalStorageAndroidObbDirs() { 179 return buildPaths(mExternalDirsForApp, DIR_ANDROID, DIR_OBB); 180 } 181 buildExternalStorageAppDataDirs(String packageName)182 public File[] buildExternalStorageAppDataDirs(String packageName) { 183 return buildPaths(mExternalDirsForApp, DIR_ANDROID, DIR_DATA, packageName); 184 } 185 buildExternalStorageAppDataDirsForVold(String packageName)186 public File[] buildExternalStorageAppDataDirsForVold(String packageName) { 187 return buildPaths(mExternalDirsForVold, DIR_ANDROID, DIR_DATA, packageName); 188 } 189 buildExternalStorageAppMediaDirs(String packageName)190 public File[] buildExternalStorageAppMediaDirs(String packageName) { 191 return buildPaths(mExternalDirsForApp, DIR_ANDROID, DIR_MEDIA, packageName); 192 } 193 buildExternalStorageAppMediaDirsForVold(String packageName)194 public File[] buildExternalStorageAppMediaDirsForVold(String packageName) { 195 return buildPaths(mExternalDirsForVold, DIR_ANDROID, DIR_MEDIA, packageName); 196 } 197 buildExternalStorageAppObbDirs(String packageName)198 public File[] buildExternalStorageAppObbDirs(String packageName) { 199 return buildPaths(mExternalDirsForApp, DIR_ANDROID, DIR_OBB, packageName); 200 } 201 buildExternalStorageAppObbDirsForVold(String packageName)202 public File[] buildExternalStorageAppObbDirsForVold(String packageName) { 203 return buildPaths(mExternalDirsForVold, DIR_ANDROID, DIR_OBB, packageName); 204 } 205 buildExternalStorageAppFilesDirs(String packageName)206 public File[] buildExternalStorageAppFilesDirs(String packageName) { 207 return buildPaths(mExternalDirsForApp, DIR_ANDROID, DIR_DATA, packageName, DIR_FILES); 208 } 209 buildExternalStorageAppCacheDirs(String packageName)210 public File[] buildExternalStorageAppCacheDirs(String packageName) { 211 return buildPaths(mExternalDirsForApp, DIR_ANDROID, DIR_DATA, packageName, DIR_CACHE); 212 } 213 } 214 215 /** 216 * Return root of the "system" partition holding the core Android OS. 217 * Always present and mounted read-only. 218 */ getRootDirectory()219 public static File getRootDirectory() { 220 return DIR_ANDROID_ROOT; 221 } 222 223 /** 224 * Return root directory of the "oem" partition holding OEM customizations, 225 * if any. If present, the partition is mounted read-only. 226 * 227 * @hide 228 */ getOemDirectory()229 public static File getOemDirectory() { 230 return DIR_OEM_ROOT; 231 } 232 233 /** 234 * Return root directory of the "vendor" partition that holds vendor-provided 235 * software that should persist across simple reflashing of the "system" partition. 236 * @hide 237 */ getVendorDirectory()238 public static File getVendorDirectory() { 239 return DIR_VENDOR_ROOT; 240 } 241 242 /** 243 * Gets the system directory available for secure storage. 244 * If Encrypted File system is enabled, it returns an encrypted directory (/data/secure/system). 245 * Otherwise, it returns the unencrypted /data/system directory. 246 * @return File object representing the secure storage system directory. 247 * @hide 248 */ getSystemSecureDirectory()249 public static File getSystemSecureDirectory() { 250 if (isEncryptedFilesystemEnabled()) { 251 return new File(SECURE_DATA_DIRECTORY, "system"); 252 } else { 253 return new File(DATA_DIRECTORY, "system"); 254 } 255 } 256 257 /** 258 * Gets the data directory for secure storage. 259 * If Encrypted File system is enabled, it returns an encrypted directory (/data/secure). 260 * Otherwise, it returns the unencrypted /data directory. 261 * @return File object representing the data directory for secure storage. 262 * @hide 263 */ getSecureDataDirectory()264 public static File getSecureDataDirectory() { 265 if (isEncryptedFilesystemEnabled()) { 266 return SECURE_DATA_DIRECTORY; 267 } else { 268 return DATA_DIRECTORY; 269 } 270 } 271 272 /** 273 * Return directory used for internal media storage, which is protected by 274 * {@link android.Manifest.permission#WRITE_MEDIA_STORAGE}. 275 * 276 * @hide 277 */ getMediaStorageDirectory()278 public static File getMediaStorageDirectory() { 279 throwIfUserRequired(); 280 return sCurrentUser.getMediaDir(); 281 } 282 283 /** 284 * Return the system directory for a user. This is for use by system services to store 285 * files relating to the user. This directory will be automatically deleted when the user 286 * is removed. 287 * 288 * @hide 289 */ getUserSystemDirectory(int userId)290 public static File getUserSystemDirectory(int userId) { 291 return new File(new File(getSystemSecureDirectory(), "users"), Integer.toString(userId)); 292 } 293 294 /** 295 * Returns the config directory for a user. This is for use by system services to store files 296 * relating to the user which should be readable by any app running as that user. 297 * 298 * @hide 299 */ getUserConfigDirectory(int userId)300 public static File getUserConfigDirectory(int userId) { 301 return new File(new File(new File( 302 getDataDirectory(), "misc"), "user"), Integer.toString(userId)); 303 } 304 305 /** 306 * Returns whether the Encrypted File System feature is enabled on the device or not. 307 * @return <code>true</code> if Encrypted File System feature is enabled, <code>false</code> 308 * if disabled. 309 * @hide 310 */ isEncryptedFilesystemEnabled()311 public static boolean isEncryptedFilesystemEnabled() { 312 return SystemProperties.getBoolean(SYSTEM_PROPERTY_EFS_ENABLED, false); 313 } 314 315 private static final File DATA_DIRECTORY 316 = getDirectory("ANDROID_DATA", "/data"); 317 318 /** 319 * @hide 320 */ 321 private static final File SECURE_DATA_DIRECTORY 322 = getDirectory("ANDROID_SECURE_DATA", "/data/secure"); 323 324 private static final File DOWNLOAD_CACHE_DIRECTORY = getDirectory("DOWNLOAD_CACHE", "/cache"); 325 326 /** 327 * Return the user data directory. 328 */ getDataDirectory()329 public static File getDataDirectory() { 330 return DATA_DIRECTORY; 331 } 332 333 /** 334 * Return the primary external storage directory. This directory may not 335 * currently be accessible if it has been mounted by the user on their 336 * computer, has been removed from the device, or some other problem has 337 * happened. You can determine its current state with 338 * {@link #getExternalStorageState()}. 339 * <p> 340 * <em>Note: don't be confused by the word "external" here. This directory 341 * can better be thought as media/shared storage. It is a filesystem that 342 * can hold a relatively large amount of data and that is shared across all 343 * applications (does not enforce permissions). Traditionally this is an SD 344 * card, but it may also be implemented as built-in storage in a device that 345 * is distinct from the protected internal storage and can be mounted as a 346 * filesystem on a computer.</em> 347 * <p> 348 * On devices with multiple users (as described by {@link UserManager}), 349 * each user has their own isolated external storage. Applications only have 350 * access to the external storage for the user they're running as. 351 * <p> 352 * In devices with multiple "external" storage directories, this directory 353 * represents the "primary" external storage that the user will interact 354 * with. Access to secondary storage is available through 355 * <p> 356 * Applications should not directly use this top-level directory, in order 357 * to avoid polluting the user's root namespace. Any files that are private 358 * to the application should be placed in a directory returned by 359 * {@link android.content.Context#getExternalFilesDir 360 * Context.getExternalFilesDir}, which the system will take care of deleting 361 * if the application is uninstalled. Other shared files should be placed in 362 * one of the directories returned by 363 * {@link #getExternalStoragePublicDirectory}. 364 * <p> 365 * Writing to this path requires the 366 * {@link android.Manifest.permission#WRITE_EXTERNAL_STORAGE} permission, 367 * and starting in read access requires the 368 * {@link android.Manifest.permission#READ_EXTERNAL_STORAGE} permission, 369 * which is automatically granted if you hold the write permission. 370 * <p> 371 * Starting in {@link android.os.Build.VERSION_CODES#KITKAT}, if your 372 * application only needs to store internal data, consider using 373 * {@link Context#getExternalFilesDir(String)} or 374 * {@link Context#getExternalCacheDir()}, which require no permissions to 375 * read or write. 376 * <p> 377 * This path may change between platform versions, so applications should 378 * only persist relative paths. 379 * <p> 380 * Here is an example of typical code to monitor the state of external 381 * storage: 382 * <p> 383 * {@sample 384 * development/samples/ApiDemos/src/com/example/android/apis/content/ExternalStorage.java 385 * monitor_storage} 386 * 387 * @see #getExternalStorageState() 388 * @see #isExternalStorageRemovable() 389 */ getExternalStorageDirectory()390 public static File getExternalStorageDirectory() { 391 throwIfUserRequired(); 392 return sCurrentUser.getExternalDirsForApp()[0]; 393 } 394 395 /** {@hide} */ getLegacyExternalStorageDirectory()396 public static File getLegacyExternalStorageDirectory() { 397 return new File(System.getenv(ENV_EXTERNAL_STORAGE)); 398 } 399 400 /** {@hide} */ getLegacyExternalStorageObbDirectory()401 public static File getLegacyExternalStorageObbDirectory() { 402 return buildPath(getLegacyExternalStorageDirectory(), DIR_ANDROID, DIR_OBB); 403 } 404 405 /** {@hide} */ getEmulatedStorageSource(int userId)406 public static File getEmulatedStorageSource(int userId) { 407 // /mnt/shell/emulated/0 408 return new File(System.getenv(ENV_EMULATED_STORAGE_SOURCE), String.valueOf(userId)); 409 } 410 411 /** {@hide} */ getEmulatedStorageObbSource()412 public static File getEmulatedStorageObbSource() { 413 // /mnt/shell/emulated/obb 414 return new File(System.getenv(ENV_EMULATED_STORAGE_SOURCE), DIR_OBB); 415 } 416 417 /** 418 * Standard directory in which to place any audio files that should be 419 * in the regular list of music for the user. 420 * This may be combined with 421 * {@link #DIRECTORY_PODCASTS}, {@link #DIRECTORY_NOTIFICATIONS}, 422 * {@link #DIRECTORY_ALARMS}, and {@link #DIRECTORY_RINGTONES} as a series 423 * of directories to categories a particular audio file as more than one 424 * type. 425 */ 426 public static String DIRECTORY_MUSIC = "Music"; 427 428 /** 429 * Standard directory in which to place any audio files that should be 430 * in the list of podcasts that the user can select (not as regular 431 * music). 432 * This may be combined with {@link #DIRECTORY_MUSIC}, 433 * {@link #DIRECTORY_NOTIFICATIONS}, 434 * {@link #DIRECTORY_ALARMS}, and {@link #DIRECTORY_RINGTONES} as a series 435 * of directories to categories a particular audio file as more than one 436 * type. 437 */ 438 public static String DIRECTORY_PODCASTS = "Podcasts"; 439 440 /** 441 * Standard directory in which to place any audio files that should be 442 * in the list of ringtones that the user can select (not as regular 443 * music). 444 * This may be combined with {@link #DIRECTORY_MUSIC}, 445 * {@link #DIRECTORY_PODCASTS}, {@link #DIRECTORY_NOTIFICATIONS}, and 446 * {@link #DIRECTORY_ALARMS} as a series 447 * of directories to categories a particular audio file as more than one 448 * type. 449 */ 450 public static String DIRECTORY_RINGTONES = "Ringtones"; 451 452 /** 453 * Standard directory in which to place any audio files that should be 454 * in the list of alarms that the user can select (not as regular 455 * music). 456 * This may be combined with {@link #DIRECTORY_MUSIC}, 457 * {@link #DIRECTORY_PODCASTS}, {@link #DIRECTORY_NOTIFICATIONS}, 458 * and {@link #DIRECTORY_RINGTONES} as a series 459 * of directories to categories a particular audio file as more than one 460 * type. 461 */ 462 public static String DIRECTORY_ALARMS = "Alarms"; 463 464 /** 465 * Standard directory in which to place any audio files that should be 466 * in the list of notifications that the user can select (not as regular 467 * music). 468 * This may be combined with {@link #DIRECTORY_MUSIC}, 469 * {@link #DIRECTORY_PODCASTS}, 470 * {@link #DIRECTORY_ALARMS}, and {@link #DIRECTORY_RINGTONES} as a series 471 * of directories to categories a particular audio file as more than one 472 * type. 473 */ 474 public static String DIRECTORY_NOTIFICATIONS = "Notifications"; 475 476 /** 477 * Standard directory in which to place pictures that are available to 478 * the user. Note that this is primarily a convention for the top-level 479 * public directory, as the media scanner will find and collect pictures 480 * in any directory. 481 */ 482 public static String DIRECTORY_PICTURES = "Pictures"; 483 484 /** 485 * Standard directory in which to place movies that are available to 486 * the user. Note that this is primarily a convention for the top-level 487 * public directory, as the media scanner will find and collect movies 488 * in any directory. 489 */ 490 public static String DIRECTORY_MOVIES = "Movies"; 491 492 /** 493 * Standard directory in which to place files that have been downloaded by 494 * the user. Note that this is primarily a convention for the top-level 495 * public directory, you are free to download files anywhere in your own 496 * private directories. Also note that though the constant here is 497 * named DIRECTORY_DOWNLOADS (plural), the actual file name is non-plural for 498 * backwards compatibility reasons. 499 */ 500 public static String DIRECTORY_DOWNLOADS = "Download"; 501 502 /** 503 * The traditional location for pictures and videos when mounting the 504 * device as a camera. Note that this is primarily a convention for the 505 * top-level public directory, as this convention makes no sense elsewhere. 506 */ 507 public static String DIRECTORY_DCIM = "DCIM"; 508 509 /** 510 * Standard directory in which to place documents that have been created by 511 * the user. 512 */ 513 public static String DIRECTORY_DOCUMENTS = "Documents"; 514 515 /** 516 * Get a top-level public external storage directory for placing files of 517 * a particular type. This is where the user will typically place and 518 * manage their own files, so you should be careful about what you put here 519 * to ensure you don't erase their files or get in the way of their own 520 * organization. 521 * 522 * <p>On devices with multiple users (as described by {@link UserManager}), 523 * each user has their own isolated external storage. Applications only 524 * have access to the external storage for the user they're running as.</p> 525 * 526 * <p>Here is an example of typical code to manipulate a picture on 527 * the public external storage:</p> 528 * 529 * {@sample development/samples/ApiDemos/src/com/example/android/apis/content/ExternalStorage.java 530 * public_picture} 531 * 532 * @param type The type of storage directory to return. Should be one of 533 * {@link #DIRECTORY_MUSIC}, {@link #DIRECTORY_PODCASTS}, 534 * {@link #DIRECTORY_RINGTONES}, {@link #DIRECTORY_ALARMS}, 535 * {@link #DIRECTORY_NOTIFICATIONS}, {@link #DIRECTORY_PICTURES}, 536 * {@link #DIRECTORY_MOVIES}, {@link #DIRECTORY_DOWNLOADS}, or 537 * {@link #DIRECTORY_DCIM}. May not be null. 538 * 539 * @return Returns the File path for the directory. Note that this 540 * directory may not yet exist, so you must make sure it exists before 541 * using it such as with {@link File#mkdirs File.mkdirs()}. 542 */ getExternalStoragePublicDirectory(String type)543 public static File getExternalStoragePublicDirectory(String type) { 544 throwIfUserRequired(); 545 return sCurrentUser.buildExternalStoragePublicDirs(type)[0]; 546 } 547 548 /** 549 * Returns the path for android-specific data on the SD card. 550 * @hide 551 */ buildExternalStorageAndroidDataDirs()552 public static File[] buildExternalStorageAndroidDataDirs() { 553 throwIfUserRequired(); 554 return sCurrentUser.buildExternalStorageAndroidDataDirs(); 555 } 556 557 /** 558 * Generates the raw path to an application's data 559 * @hide 560 */ buildExternalStorageAppDataDirs(String packageName)561 public static File[] buildExternalStorageAppDataDirs(String packageName) { 562 throwIfUserRequired(); 563 return sCurrentUser.buildExternalStorageAppDataDirs(packageName); 564 } 565 566 /** 567 * Generates the raw path to an application's media 568 * @hide 569 */ buildExternalStorageAppMediaDirs(String packageName)570 public static File[] buildExternalStorageAppMediaDirs(String packageName) { 571 throwIfUserRequired(); 572 return sCurrentUser.buildExternalStorageAppMediaDirs(packageName); 573 } 574 575 /** 576 * Generates the raw path to an application's OBB files 577 * @hide 578 */ buildExternalStorageAppObbDirs(String packageName)579 public static File[] buildExternalStorageAppObbDirs(String packageName) { 580 throwIfUserRequired(); 581 return sCurrentUser.buildExternalStorageAppObbDirs(packageName); 582 } 583 584 /** 585 * Generates the path to an application's files. 586 * @hide 587 */ buildExternalStorageAppFilesDirs(String packageName)588 public static File[] buildExternalStorageAppFilesDirs(String packageName) { 589 throwIfUserRequired(); 590 return sCurrentUser.buildExternalStorageAppFilesDirs(packageName); 591 } 592 593 /** 594 * Generates the path to an application's cache. 595 * @hide 596 */ buildExternalStorageAppCacheDirs(String packageName)597 public static File[] buildExternalStorageAppCacheDirs(String packageName) { 598 throwIfUserRequired(); 599 return sCurrentUser.buildExternalStorageAppCacheDirs(packageName); 600 } 601 602 /** 603 * Return the download/cache content directory. 604 */ getDownloadCacheDirectory()605 public static File getDownloadCacheDirectory() { 606 return DOWNLOAD_CACHE_DIRECTORY; 607 } 608 609 /** 610 * Unknown storage state, such as when a path isn't backed by known storage 611 * media. 612 * 613 * @see #getExternalStorageState(File) 614 */ 615 public static final String MEDIA_UNKNOWN = "unknown"; 616 617 /** 618 * Storage state if the media is not present. 619 * 620 * @see #getExternalStorageState(File) 621 */ 622 public static final String MEDIA_REMOVED = "removed"; 623 624 /** 625 * Storage state if the media is present but not mounted. 626 * 627 * @see #getExternalStorageState(File) 628 */ 629 public static final String MEDIA_UNMOUNTED = "unmounted"; 630 631 /** 632 * Storage state if the media is present and being disk-checked. 633 * 634 * @see #getExternalStorageState(File) 635 */ 636 public static final String MEDIA_CHECKING = "checking"; 637 638 /** 639 * Storage state if the media is present but is blank or is using an 640 * unsupported filesystem. 641 * 642 * @see #getExternalStorageState(File) 643 */ 644 public static final String MEDIA_NOFS = "nofs"; 645 646 /** 647 * Storage state if the media is present and mounted at its mount point with 648 * read/write access. 649 * 650 * @see #getExternalStorageState(File) 651 */ 652 public static final String MEDIA_MOUNTED = "mounted"; 653 654 /** 655 * Storage state if the media is present and mounted at its mount point with 656 * read-only access. 657 * 658 * @see #getExternalStorageState(File) 659 */ 660 public static final String MEDIA_MOUNTED_READ_ONLY = "mounted_ro"; 661 662 /** 663 * Storage state if the media is present not mounted, and shared via USB 664 * mass storage. 665 * 666 * @see #getExternalStorageState(File) 667 */ 668 public static final String MEDIA_SHARED = "shared"; 669 670 /** 671 * Storage state if the media was removed before it was unmounted. 672 * 673 * @see #getExternalStorageState(File) 674 */ 675 public static final String MEDIA_BAD_REMOVAL = "bad_removal"; 676 677 /** 678 * Storage state if the media is present but cannot be mounted. Typically 679 * this happens if the file system on the media is corrupted. 680 * 681 * @see #getExternalStorageState(File) 682 */ 683 public static final String MEDIA_UNMOUNTABLE = "unmountable"; 684 685 /** 686 * Returns the current state of the primary "external" storage device. 687 * 688 * @see #getExternalStorageDirectory() 689 * @return one of {@link #MEDIA_UNKNOWN}, {@link #MEDIA_REMOVED}, 690 * {@link #MEDIA_UNMOUNTED}, {@link #MEDIA_CHECKING}, 691 * {@link #MEDIA_NOFS}, {@link #MEDIA_MOUNTED}, 692 * {@link #MEDIA_MOUNTED_READ_ONLY}, {@link #MEDIA_SHARED}, 693 * {@link #MEDIA_BAD_REMOVAL}, or {@link #MEDIA_UNMOUNTABLE}. 694 */ getExternalStorageState()695 public static String getExternalStorageState() { 696 final File externalDir = sCurrentUser.getExternalDirsForApp()[0]; 697 return getExternalStorageState(externalDir); 698 } 699 700 /** 701 * @deprecated use {@link #getExternalStorageState(File)} 702 */ 703 @Deprecated getStorageState(File path)704 public static String getStorageState(File path) { 705 return getExternalStorageState(path); 706 } 707 708 /** 709 * Returns the current state of the storage device that provides the given 710 * path. 711 * 712 * @return one of {@link #MEDIA_UNKNOWN}, {@link #MEDIA_REMOVED}, 713 * {@link #MEDIA_UNMOUNTED}, {@link #MEDIA_CHECKING}, 714 * {@link #MEDIA_NOFS}, {@link #MEDIA_MOUNTED}, 715 * {@link #MEDIA_MOUNTED_READ_ONLY}, {@link #MEDIA_SHARED}, 716 * {@link #MEDIA_BAD_REMOVAL}, or {@link #MEDIA_UNMOUNTABLE}. 717 */ getExternalStorageState(File path)718 public static String getExternalStorageState(File path) { 719 final StorageVolume volume = getStorageVolume(path); 720 if (volume != null) { 721 final IMountService mountService = IMountService.Stub.asInterface( 722 ServiceManager.getService("mount")); 723 try { 724 return mountService.getVolumeState(volume.getPath()); 725 } catch (RemoteException e) { 726 } 727 } 728 729 return Environment.MEDIA_UNKNOWN; 730 } 731 732 /** 733 * Returns whether the primary "external" storage device is removable. 734 * 735 * @return true if the storage device can be removed (such as an SD card), 736 * or false if the storage device is built in and cannot be 737 * physically removed. 738 */ isExternalStorageRemovable()739 public static boolean isExternalStorageRemovable() { 740 if (isStorageDisabled()) return false; 741 final File externalDir = sCurrentUser.getExternalDirsForApp()[0]; 742 return isExternalStorageRemovable(externalDir); 743 } 744 745 /** 746 * Returns whether the storage device that provides the given path is 747 * removable. 748 * 749 * @return true if the storage device can be removed (such as an SD card), 750 * or false if the storage device is built in and cannot be 751 * physically removed. 752 * @throws IllegalArgumentException if the path is not a valid storage 753 * device. 754 */ isExternalStorageRemovable(File path)755 public static boolean isExternalStorageRemovable(File path) { 756 final StorageVolume volume = getStorageVolume(path); 757 if (volume != null) { 758 return volume.isRemovable(); 759 } else { 760 throw new IllegalArgumentException("Failed to find storage device at " + path); 761 } 762 } 763 764 /** 765 * Returns whether the primary "external" storage device is emulated. If 766 * true, data stored on this device will be stored on a portion of the 767 * internal storage system. 768 * 769 * @see DevicePolicyManager#setStorageEncryption(android.content.ComponentName, 770 * boolean) 771 */ isExternalStorageEmulated()772 public static boolean isExternalStorageEmulated() { 773 if (isStorageDisabled()) return false; 774 final File externalDir = sCurrentUser.getExternalDirsForApp()[0]; 775 return isExternalStorageEmulated(externalDir); 776 } 777 778 /** 779 * Returns whether the storage device that provides the given path is 780 * emulated. If true, data stored on this device will be stored on a portion 781 * of the internal storage system. 782 * 783 * @throws IllegalArgumentException if the path is not a valid storage 784 * device. 785 */ isExternalStorageEmulated(File path)786 public static boolean isExternalStorageEmulated(File path) { 787 final StorageVolume volume = getStorageVolume(path); 788 if (volume != null) { 789 return volume.isEmulated(); 790 } else { 791 throw new IllegalArgumentException("Failed to find storage device at " + path); 792 } 793 } 794 getDirectory(String variableName, String defaultPath)795 static File getDirectory(String variableName, String defaultPath) { 796 String path = System.getenv(variableName); 797 return path == null ? new File(defaultPath) : new File(path); 798 } 799 getCanonicalPathOrNull(String variableName)800 private static String getCanonicalPathOrNull(String variableName) { 801 String path = System.getenv(variableName); 802 if (path == null) { 803 return null; 804 } 805 try { 806 return new File(path).getCanonicalPath(); 807 } catch (IOException e) { 808 Log.w(TAG, "Unable to resolve canonical path for " + path); 809 return null; 810 } 811 } 812 813 /** {@hide} */ setUserRequired(boolean userRequired)814 public static void setUserRequired(boolean userRequired) { 815 sUserRequired = userRequired; 816 } 817 throwIfUserRequired()818 private static void throwIfUserRequired() { 819 if (sUserRequired) { 820 Log.wtf(TAG, "Path requests must specify a user by using UserEnvironment", 821 new Throwable()); 822 } 823 } 824 825 /** 826 * Append path segments to each given base path, returning result. 827 * 828 * @hide 829 */ buildPaths(File[] base, String... segments)830 public static File[] buildPaths(File[] base, String... segments) { 831 File[] result = new File[base.length]; 832 for (int i = 0; i < base.length; i++) { 833 result[i] = buildPath(base[i], segments); 834 } 835 return result; 836 } 837 838 /** 839 * Append path segments to given base path, returning result. 840 * 841 * @hide 842 */ buildPath(File base, String... segments)843 public static File buildPath(File base, String... segments) { 844 File cur = base; 845 for (String segment : segments) { 846 if (cur == null) { 847 cur = new File(segment); 848 } else { 849 cur = new File(cur, segment); 850 } 851 } 852 return cur; 853 } 854 isStorageDisabled()855 private static boolean isStorageDisabled() { 856 return SystemProperties.getBoolean("config.disable_storage", false); 857 } 858 getStorageVolume(File path)859 private static StorageVolume getStorageVolume(File path) { 860 try { 861 path = path.getCanonicalFile(); 862 } catch (IOException e) { 863 return null; 864 } 865 866 try { 867 final IMountService mountService = IMountService.Stub.asInterface( 868 ServiceManager.getService("mount")); 869 final StorageVolume[] volumes = mountService.getVolumeList(); 870 for (StorageVolume volume : volumes) { 871 if (FileUtils.contains(volume.getPathFile(), path)) { 872 return volume; 873 } 874 } 875 } catch (RemoteException e) { 876 } 877 878 return null; 879 } 880 881 /** 882 * If the given path exists on emulated external storage, return the 883 * translated backing path hosted on internal storage. This bypasses any 884 * emulation later, improving performance. This is <em>only</em> suitable 885 * for read-only access. 886 * <p> 887 * Returns original path if given path doesn't meet these criteria. Callers 888 * must hold {@link android.Manifest.permission#WRITE_MEDIA_STORAGE} 889 * permission. 890 * 891 * @hide 892 */ maybeTranslateEmulatedPathToInternal(File path)893 public static File maybeTranslateEmulatedPathToInternal(File path) { 894 // Fast return if not emulated, or missing variables 895 if (!Environment.isExternalStorageEmulated() 896 || CANONCIAL_EMULATED_STORAGE_TARGET == null) { 897 return path; 898 } 899 900 try { 901 final String rawPath = path.getCanonicalPath(); 902 if (rawPath.startsWith(CANONCIAL_EMULATED_STORAGE_TARGET)) { 903 final File internalPath = new File(DIR_MEDIA_STORAGE, 904 rawPath.substring(CANONCIAL_EMULATED_STORAGE_TARGET.length())); 905 if (internalPath.exists()) { 906 return internalPath; 907 } 908 } 909 } catch (IOException e) { 910 Log.w(TAG, "Failed to resolve canonical path for " + path); 911 } 912 913 // Unable to translate to internal path; use original 914 return path; 915 } 916 } 917