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