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