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