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 com.android.server; 18 19 import static android.Manifest.permission.ACCESS_MTP; 20 import static android.Manifest.permission.INSTALL_PACKAGES; 21 import static android.Manifest.permission.READ_EXTERNAL_STORAGE; 22 import static android.Manifest.permission.WRITE_EXTERNAL_STORAGE; 23 import static android.Manifest.permission.WRITE_MEDIA_STORAGE; 24 import static android.app.ActivityManager.PROCESS_STATE_NONEXISTENT; 25 import static android.app.AppOpsManager.MODE_ALLOWED; 26 import static android.app.AppOpsManager.OP_LEGACY_STORAGE; 27 import static android.app.AppOpsManager.OP_MANAGE_EXTERNAL_STORAGE; 28 import static android.app.AppOpsManager.OP_READ_EXTERNAL_STORAGE; 29 import static android.app.AppOpsManager.OP_REQUEST_INSTALL_PACKAGES; 30 import static android.app.AppOpsManager.OP_WRITE_EXTERNAL_STORAGE; 31 import static android.content.pm.PackageManager.MATCH_ANY_USER; 32 import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_AWARE; 33 import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_UNAWARE; 34 import static android.content.pm.PackageManager.MATCH_UNINSTALLED_PACKAGES; 35 import static android.content.pm.PackageManager.PERMISSION_GRANTED; 36 import static android.os.ParcelFileDescriptor.MODE_READ_WRITE; 37 import static android.os.storage.OnObbStateChangeListener.ERROR_ALREADY_MOUNTED; 38 import static android.os.storage.OnObbStateChangeListener.ERROR_COULD_NOT_MOUNT; 39 import static android.os.storage.OnObbStateChangeListener.ERROR_COULD_NOT_UNMOUNT; 40 import static android.os.storage.OnObbStateChangeListener.ERROR_INTERNAL; 41 import static android.os.storage.OnObbStateChangeListener.ERROR_NOT_MOUNTED; 42 import static android.os.storage.OnObbStateChangeListener.ERROR_PERMISSION_DENIED; 43 import static android.os.storage.OnObbStateChangeListener.MOUNTED; 44 import static android.os.storage.OnObbStateChangeListener.UNMOUNTED; 45 import static android.os.storage.StorageManager.PROP_FORCED_SCOPED_STORAGE_WHITELIST; 46 import static android.os.storage.StorageManager.PROP_FUSE; 47 import static android.os.storage.StorageManager.PROP_SETTINGS_FUSE; 48 49 import static com.android.internal.util.XmlUtils.readIntAttribute; 50 import static com.android.internal.util.XmlUtils.readLongAttribute; 51 import static com.android.internal.util.XmlUtils.readStringAttribute; 52 import static com.android.internal.util.XmlUtils.writeIntAttribute; 53 import static com.android.internal.util.XmlUtils.writeLongAttribute; 54 import static com.android.internal.util.XmlUtils.writeStringAttribute; 55 56 import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT; 57 import static org.xmlpull.v1.XmlPullParser.START_TAG; 58 59 import android.Manifest; 60 import android.annotation.Nullable; 61 import android.app.ActivityManager; 62 import android.app.ActivityManagerInternal; 63 import android.app.AppOpsManager; 64 import android.app.IActivityManager; 65 import android.app.KeyguardManager; 66 import android.app.admin.SecurityLog; 67 import android.app.usage.StorageStatsManager; 68 import android.content.BroadcastReceiver; 69 import android.content.ContentResolver; 70 import android.content.Context; 71 import android.content.Intent; 72 import android.content.IntentFilter; 73 import android.content.pm.ApplicationInfo; 74 import android.content.pm.IPackageManager; 75 import android.content.pm.IPackageMoveObserver; 76 import android.content.pm.PackageManager; 77 import android.content.pm.PackageManagerInternal; 78 import android.content.pm.ProviderInfo; 79 import android.content.pm.UserInfo; 80 import android.content.res.Configuration; 81 import android.content.res.ObbInfo; 82 import android.database.ContentObserver; 83 import android.net.Uri; 84 import android.os.Binder; 85 import android.os.DropBoxManager; 86 import android.os.Environment; 87 import android.os.Handler; 88 import android.os.HandlerThread; 89 import android.os.IBinder; 90 import android.os.IStoraged; 91 import android.os.IVold; 92 import android.os.IVoldListener; 93 import android.os.IVoldMountCallback; 94 import android.os.IVoldTaskListener; 95 import android.os.Looper; 96 import android.os.Message; 97 import android.os.ParcelFileDescriptor; 98 import android.os.ParcelableException; 99 import android.os.PersistableBundle; 100 import android.os.PowerManager; 101 import android.os.Process; 102 import android.os.RemoteCallbackList; 103 import android.os.RemoteException; 104 import android.os.ServiceManager; 105 import android.os.ServiceSpecificException; 106 import android.os.SystemClock; 107 import android.os.SystemProperties; 108 import android.os.UserHandle; 109 import android.os.UserManager; 110 import android.os.UserManagerInternal; 111 import android.os.storage.DiskInfo; 112 import android.os.storage.IObbActionListener; 113 import android.os.storage.IStorageEventListener; 114 import android.os.storage.IStorageManager; 115 import android.os.storage.IStorageShutdownObserver; 116 import android.os.storage.OnObbStateChangeListener; 117 import android.os.storage.StorageManager; 118 import android.os.storage.StorageManagerInternal; 119 import android.os.storage.StorageVolume; 120 import android.os.storage.VolumeInfo; 121 import android.os.storage.VolumeRecord; 122 import android.provider.DeviceConfig; 123 import android.provider.DocumentsContract; 124 import android.provider.Downloads; 125 import android.provider.MediaStore; 126 import android.provider.Settings; 127 import android.sysprop.VoldProperties; 128 import android.text.TextUtils; 129 import android.text.format.DateUtils; 130 import android.util.ArrayMap; 131 import android.util.ArraySet; 132 import android.util.AtomicFile; 133 import android.util.DataUnit; 134 import android.util.FeatureFlagUtils; 135 import android.util.Log; 136 import android.util.Pair; 137 import android.util.Slog; 138 import android.util.TimeUtils; 139 import android.util.Xml; 140 141 import com.android.internal.annotations.GuardedBy; 142 import com.android.internal.app.IAppOpsCallback; 143 import com.android.internal.app.IAppOpsService; 144 import com.android.internal.content.PackageMonitor; 145 import com.android.internal.os.AppFuseMount; 146 import com.android.internal.os.BackgroundThread; 147 import com.android.internal.os.FuseUnavailableMountException; 148 import com.android.internal.os.SomeArgs; 149 import com.android.internal.os.Zygote; 150 import com.android.internal.util.ArrayUtils; 151 import com.android.internal.util.CollectionUtils; 152 import com.android.internal.util.DumpUtils; 153 import com.android.internal.util.FastXmlSerializer; 154 import com.android.internal.util.HexDump; 155 import com.android.internal.util.IndentingPrintWriter; 156 import com.android.internal.util.Preconditions; 157 import com.android.internal.widget.LockPatternUtils; 158 import com.android.server.pm.Installer; 159 import com.android.server.storage.AppFuseBridge; 160 import com.android.server.storage.StorageSessionController; 161 import com.android.server.storage.StorageSessionController.ExternalStorageServiceException; 162 import com.android.server.wm.ActivityTaskManagerInternal; 163 import com.android.server.wm.ActivityTaskManagerInternal.ScreenObserver; 164 165 import libcore.io.IoUtils; 166 import libcore.util.EmptyArray; 167 168 import org.xmlpull.v1.XmlPullParser; 169 import org.xmlpull.v1.XmlPullParserException; 170 import org.xmlpull.v1.XmlSerializer; 171 172 import java.io.File; 173 import java.io.FileDescriptor; 174 import java.io.FileInputStream; 175 import java.io.FileNotFoundException; 176 import java.io.FileOutputStream; 177 import java.io.IOException; 178 import java.io.PrintWriter; 179 import java.math.BigInteger; 180 import java.nio.charset.StandardCharsets; 181 import java.security.GeneralSecurityException; 182 import java.security.spec.KeySpec; 183 import java.util.ArrayList; 184 import java.util.Arrays; 185 import java.util.HashMap; 186 import java.util.Iterator; 187 import java.util.LinkedList; 188 import java.util.List; 189 import java.util.Locale; 190 import java.util.Map; 191 import java.util.Map.Entry; 192 import java.util.Objects; 193 import java.util.Set; 194 import java.util.concurrent.CopyOnWriteArrayList; 195 import java.util.concurrent.CountDownLatch; 196 import java.util.concurrent.TimeUnit; 197 import java.util.concurrent.TimeoutException; 198 import java.util.regex.Matcher; 199 import java.util.regex.Pattern; 200 201 import javax.crypto.SecretKey; 202 import javax.crypto.SecretKeyFactory; 203 import javax.crypto.spec.PBEKeySpec; 204 205 /** 206 * Service responsible for various storage media. Connects to {@code vold} to 207 * watch for and manage dynamically added storage, such as SD cards and USB mass 208 * storage. Also decides how storage should be presented to users on the device. 209 */ 210 class StorageManagerService extends IStorageManager.Stub 211 implements Watchdog.Monitor, ScreenObserver { 212 213 // Static direct instance pointer for the tightly-coupled idle service to use 214 static StorageManagerService sSelf = null; 215 216 /* Read during boot to decide whether to enable zram when available */ 217 private static final String ZRAM_ENABLED_PROPERTY = 218 "persist.sys.zram_enabled"; 219 220 private static final boolean ENABLE_ISOLATED_STORAGE = StorageManager.hasIsolatedStorage(); 221 222 // A system property to control if obb app data isolation is enabled in vold. 223 private static final String ANDROID_VOLD_APP_DATA_ISOLATION_ENABLED_PROPERTY = 224 "persist.sys.vold_app_data_isolation_enabled"; 225 226 // How long we wait to reset storage, if we failed to call onMount on the 227 // external storage service. 228 public static final int FAILED_MOUNT_RESET_TIMEOUT_SECONDS = 10; 229 /** 230 * If {@code 1}, enables the isolated storage feature. If {@code -1}, 231 * disables the isolated storage feature. If {@code 0}, uses the default 232 * value from the build system. 233 */ 234 private static final String ISOLATED_STORAGE_ENABLED = "isolated_storage_enabled"; 235 236 /** 237 * If {@code 1}, enables FuseDaemon to intercept file system ops. If {@code -1}, 238 * disables FuseDaemon. If {@code 0}, uses the default value from the build system. 239 */ 240 private static final String FUSE_ENABLED = "fuse_enabled"; 241 private static final boolean DEFAULT_FUSE_ENABLED = true; 242 243 @GuardedBy("mLock") 244 private final Set<Integer> mFuseMountedUser = new ArraySet<>(); 245 246 public static class Lifecycle extends SystemService { 247 private StorageManagerService mStorageManagerService; 248 Lifecycle(Context context)249 public Lifecycle(Context context) { 250 super(context); 251 } 252 253 @Override onStart()254 public void onStart() { 255 mStorageManagerService = new StorageManagerService(getContext()); 256 publishBinderService("mount", mStorageManagerService); 257 mStorageManagerService.start(); 258 } 259 260 @Override onBootPhase(int phase)261 public void onBootPhase(int phase) { 262 if (phase == SystemService.PHASE_SYSTEM_SERVICES_READY) { 263 mStorageManagerService.servicesReady(); 264 } else if (phase == SystemService.PHASE_ACTIVITY_MANAGER_READY) { 265 mStorageManagerService.systemReady(); 266 } else if (phase == SystemService.PHASE_BOOT_COMPLETED) { 267 mStorageManagerService.bootCompleted(); 268 } 269 } 270 271 @Override onSwitchUser(int userHandle)272 public void onSwitchUser(int userHandle) { 273 mStorageManagerService.mCurrentUserId = userHandle; 274 } 275 276 @Override onUnlockUser(int userHandle)277 public void onUnlockUser(int userHandle) { 278 mStorageManagerService.onUnlockUser(userHandle); 279 } 280 281 @Override onCleanupUser(int userHandle)282 public void onCleanupUser(int userHandle) { 283 mStorageManagerService.onCleanupUser(userHandle); 284 } 285 286 @Override onStopUser(int userHandle)287 public void onStopUser(int userHandle) { 288 mStorageManagerService.onStopUser(userHandle); 289 } 290 291 @Override onUserStarting(TargetUser user)292 public void onUserStarting(TargetUser user) { 293 mStorageManagerService.snapshotAndMonitorLegacyStorageAppOp(user.getUserHandle()); 294 } 295 } 296 297 private static final boolean DEBUG_EVENTS = false; 298 private static final boolean DEBUG_OBB = false; 299 300 /** 301 * We now talk to vold over Binder, and it has its own internal lock to 302 * serialize certain calls. All long-running operations have been migrated 303 * to be async with callbacks, so we want watchdog to fire if vold wedges. 304 */ 305 private static final boolean WATCHDOG_ENABLE = true; 306 307 /** 308 * Our goal is for all Android devices to be usable as development devices, 309 * which includes the new Direct Boot mode added in N. For devices that 310 * don't have native FBE support, we offer an emulation mode for developer 311 * testing purposes, but if it's prohibitively difficult to support this 312 * mode, it can be disabled for specific products using this flag. 313 */ 314 private static final boolean EMULATE_FBE_SUPPORTED = true; 315 316 private static final String TAG = "StorageManagerService"; 317 private static final boolean LOCAL_LOGV = Log.isLoggable(TAG, Log.VERBOSE); 318 319 private static final String TAG_STORAGE_BENCHMARK = "storage_benchmark"; 320 private static final String TAG_STORAGE_TRIM = "storage_trim"; 321 322 /** Magic value sent by MoveTask.cpp */ 323 private static final int MOVE_STATUS_COPY_FINISHED = 82; 324 325 private static final int VERSION_INIT = 1; 326 private static final int VERSION_ADD_PRIMARY = 2; 327 private static final int VERSION_FIX_PRIMARY = 3; 328 329 private static final String TAG_VOLUMES = "volumes"; 330 private static final String ATTR_VERSION = "version"; 331 private static final String ATTR_PRIMARY_STORAGE_UUID = "primaryStorageUuid"; 332 private static final String TAG_VOLUME = "volume"; 333 private static final String ATTR_TYPE = "type"; 334 private static final String ATTR_FS_UUID = "fsUuid"; 335 private static final String ATTR_PART_GUID = "partGuid"; 336 private static final String ATTR_NICKNAME = "nickname"; 337 private static final String ATTR_USER_FLAGS = "userFlags"; 338 private static final String ATTR_CREATED_MILLIS = "createdMillis"; 339 private static final String ATTR_LAST_SEEN_MILLIS = "lastSeenMillis"; 340 private static final String ATTR_LAST_TRIM_MILLIS = "lastTrimMillis"; 341 private static final String ATTR_LAST_BENCH_MILLIS = "lastBenchMillis"; 342 343 private static final String[] ALL_STORAGE_PERMISSIONS = { 344 Manifest.permission.READ_EXTERNAL_STORAGE, 345 Manifest.permission.WRITE_EXTERNAL_STORAGE 346 }; 347 348 @Nullable public static String sMediaStoreAuthorityProcessName; 349 350 private final AtomicFile mSettingsFile; 351 352 /** 353 * <em>Never</em> hold the lock while performing downcalls into vold, since 354 * unsolicited events can suddenly appear to update data structures. 355 */ 356 private final Object mLock = LockGuard.installNewLock(LockGuard.INDEX_STORAGE); 357 358 /** 359 * Similar to {@link #mLock}, never hold this lock while performing downcalls into vold. 360 * Also, never hold this while calling into PackageManagerService since it is used in callbacks 361 * from PackageManagerService. 362 * 363 * If both {@link #mLock} and this lock need to be held, {@link #mLock} should be acquired 364 * before this. 365 * 366 * Use -PL suffix for methods that need to called with this lock held. 367 */ 368 private final Object mPackagesLock = new Object(); 369 370 /** 371 * mLocalUnlockedUsers affects the return value of isUserUnlocked. If 372 * any value in the array changes, then the binder cache for 373 * isUserUnlocked must be invalidated. When adding mutating methods to 374 * WatchedLockedUsers, be sure to invalidate the cache in the new 375 * methods. 376 */ 377 private class WatchedLockedUsers { 378 private int[] users = EmptyArray.INT; WatchedLockedUsers()379 public WatchedLockedUsers() { 380 invalidateIsUserUnlockedCache(); 381 } append(int userId)382 public void append(int userId) { 383 users = ArrayUtils.appendInt(users, userId); 384 invalidateIsUserUnlockedCache(); 385 } remove(int userId)386 public void remove(int userId) { 387 users = ArrayUtils.removeInt(users, userId); 388 invalidateIsUserUnlockedCache(); 389 } contains(int userId)390 public boolean contains(int userId) { 391 return ArrayUtils.contains(users, userId); 392 } all()393 public int[] all() { 394 return users; 395 } 396 @Override toString()397 public String toString() { 398 return Arrays.toString(users); 399 } invalidateIsUserUnlockedCache()400 private void invalidateIsUserUnlockedCache() { 401 UserManager.invalidateIsUserUnlockedCache(); 402 } 403 } 404 405 /** Set of users that we know are unlocked. */ 406 @GuardedBy("mLock") 407 private WatchedLockedUsers mLocalUnlockedUsers = new WatchedLockedUsers(); 408 /** Set of users that system knows are unlocked. */ 409 @GuardedBy("mLock") 410 private int[] mSystemUnlockedUsers = EmptyArray.INT; 411 412 /** Map from disk ID to disk */ 413 @GuardedBy("mLock") 414 private ArrayMap<String, DiskInfo> mDisks = new ArrayMap<>(); 415 /** Map from volume ID to disk */ 416 @GuardedBy("mLock") 417 private final ArrayMap<String, VolumeInfo> mVolumes = new ArrayMap<>(); 418 419 /** Map from UUID to record */ 420 @GuardedBy("mLock") 421 private ArrayMap<String, VolumeRecord> mRecords = new ArrayMap<>(); 422 @GuardedBy("mLock") 423 private String mPrimaryStorageUuid; 424 425 /** Map from disk ID to latches */ 426 @GuardedBy("mLock") 427 private ArrayMap<String, CountDownLatch> mDiskScanLatches = new ArrayMap<>(); 428 429 @GuardedBy("mLock") 430 private IPackageMoveObserver mMoveCallback; 431 @GuardedBy("mLock") 432 private String mMoveTargetUuid; 433 434 private volatile int mMediaStoreAuthorityAppId = -1; 435 436 private volatile int mDownloadsAuthorityAppId = -1; 437 438 private volatile int mExternalStorageAuthorityAppId = -1; 439 440 private volatile int mCurrentUserId = UserHandle.USER_SYSTEM; 441 442 private final Installer mInstaller; 443 444 /** Holding lock for AppFuse business */ 445 private final Object mAppFuseLock = new Object(); 446 447 @GuardedBy("mAppFuseLock") 448 private int mNextAppFuseName = 0; 449 450 @GuardedBy("mAppFuseLock") 451 private AppFuseBridge mAppFuseBridge = null; 452 453 /** Matches known application dir paths. The first group contains the generic part of the path, 454 * the second group contains the user id (or null if it's a public volume without users), the 455 * third group contains the package name, and the fourth group the remainder of the path. 456 */ 457 public static final Pattern KNOWN_APP_DIR_PATHS = Pattern.compile( 458 "(?i)(^/storage/[^/]+/(?:([0-9]+)/)?Android/(?:data|media|obb|sandbox)/)([^/]+)(/.*)?"); 459 460 461 /** Automotive device unlockes users before system boot complete and this requires special 462 * handling as vold reset can lead into race conditions. When this is set, all users unlocked 463 * in {@code UserManager} level are unlocked after vold reset. 464 */ 465 private final boolean mIsAutomotive; 466 findVolumeByIdOrThrow(String id)467 private VolumeInfo findVolumeByIdOrThrow(String id) { 468 synchronized (mLock) { 469 final VolumeInfo vol = mVolumes.get(id); 470 if (vol != null) { 471 return vol; 472 } 473 } 474 throw new IllegalArgumentException("No volume found for ID " + id); 475 } 476 findVolumeIdForPathOrThrow(String path)477 private String findVolumeIdForPathOrThrow(String path) { 478 synchronized (mLock) { 479 for (int i = 0; i < mVolumes.size(); i++) { 480 final VolumeInfo vol = mVolumes.valueAt(i); 481 if (vol.path != null && path.startsWith(vol.path)) { 482 return vol.id; 483 } 484 } 485 } 486 throw new IllegalArgumentException("No volume found for path " + path); 487 } 488 findRecordForPath(String path)489 private VolumeRecord findRecordForPath(String path) { 490 synchronized (mLock) { 491 for (int i = 0; i < mVolumes.size(); i++) { 492 final VolumeInfo vol = mVolumes.valueAt(i); 493 if (vol.path != null && path.startsWith(vol.path)) { 494 return mRecords.get(vol.fsUuid); 495 } 496 } 497 } 498 return null; 499 } 500 scrubPath(String path)501 private String scrubPath(String path) { 502 if (path.startsWith(Environment.getDataDirectory().getAbsolutePath())) { 503 return "internal"; 504 } 505 final VolumeRecord rec = findRecordForPath(path); 506 if (rec == null || rec.createdMillis == 0) { 507 return "unknown"; 508 } else { 509 return "ext:" + (int) ((System.currentTimeMillis() - rec.createdMillis) 510 / DateUtils.WEEK_IN_MILLIS) + "w"; 511 } 512 } 513 findStorageForUuid(String volumeUuid)514 private @Nullable VolumeInfo findStorageForUuid(String volumeUuid) { 515 final StorageManager storage = mContext.getSystemService(StorageManager.class); 516 if (Objects.equals(StorageManager.UUID_PRIVATE_INTERNAL, volumeUuid)) { 517 return storage.findVolumeById(VolumeInfo.ID_EMULATED_INTERNAL + ";" + 0); 518 } else if (Objects.equals(StorageManager.UUID_PRIMARY_PHYSICAL, volumeUuid)) { 519 return storage.getPrimaryPhysicalVolume(); 520 } else { 521 return storage.findEmulatedForPrivate(storage.findVolumeByUuid(volumeUuid)); 522 } 523 } 524 shouldBenchmark()525 private boolean shouldBenchmark() { 526 final long benchInterval = Settings.Global.getLong(mContext.getContentResolver(), 527 Settings.Global.STORAGE_BENCHMARK_INTERVAL, DateUtils.WEEK_IN_MILLIS); 528 if (benchInterval == -1) { 529 return false; 530 } else if (benchInterval == 0) { 531 return true; 532 } 533 534 synchronized (mLock) { 535 for (int i = 0; i < mVolumes.size(); i++) { 536 final VolumeInfo vol = mVolumes.valueAt(i); 537 final VolumeRecord rec = mRecords.get(vol.fsUuid); 538 if (vol.isMountedWritable() && rec != null) { 539 final long benchAge = System.currentTimeMillis() - rec.lastBenchMillis; 540 if (benchAge >= benchInterval) { 541 return true; 542 } 543 } 544 } 545 return false; 546 } 547 } 548 findOrCreateDiskScanLatch(String diskId)549 private CountDownLatch findOrCreateDiskScanLatch(String diskId) { 550 synchronized (mLock) { 551 CountDownLatch latch = mDiskScanLatches.get(diskId); 552 if (latch == null) { 553 latch = new CountDownLatch(1); 554 mDiskScanLatches.put(diskId, latch); 555 } 556 return latch; 557 } 558 } 559 560 /** List of crypto types. 561 * These must match CRYPT_TYPE_XXX in cryptfs.h AND their 562 * corresponding commands in CommandListener.cpp */ 563 public static final String[] CRYPTO_TYPES 564 = { "password", "default", "pattern", "pin" }; 565 566 private final Context mContext; 567 private final ContentResolver mResolver; 568 569 private volatile IVold mVold; 570 private volatile IStoraged mStoraged; 571 572 private volatile boolean mBootCompleted = false; 573 private volatile boolean mDaemonConnected = false; 574 private volatile boolean mSecureKeyguardShowing = true; 575 576 private PackageManagerInternal mPmInternal; 577 578 private IPackageManager mIPackageManager; 579 private IAppOpsService mIAppOpsService; 580 581 private final Callbacks mCallbacks; 582 private final LockPatternUtils mLockPatternUtils; 583 584 /** 585 * The size of the crypto algorithm key in bits for OBB files. Currently 586 * Twofish is used which takes 128-bit keys. 587 */ 588 private static final int CRYPTO_ALGORITHM_KEY_SIZE = 128; 589 590 /** 591 * The number of times to run SHA1 in the PBKDF2 function for OBB files. 592 * 1024 is reasonably secure and not too slow. 593 */ 594 private static final int PBKDF2_HASH_ROUNDS = 1024; 595 596 /** 597 * Mounted OBB tracking information. Used to track the current state of all 598 * OBBs. 599 */ 600 final private Map<IBinder, List<ObbState>> mObbMounts = new HashMap<IBinder, List<ObbState>>(); 601 602 /** Map from raw paths to {@link ObbState}. */ 603 final private Map<String, ObbState> mObbPathToStateMap = new HashMap<String, ObbState>(); 604 605 // Not guarded by a lock. 606 private final StorageManagerInternalImpl mStorageManagerInternal 607 = new StorageManagerInternalImpl(); 608 609 // Not guarded by a lock. 610 private final StorageSessionController mStorageSessionController; 611 612 private final boolean mIsFuseEnabled; 613 614 private final boolean mVoldAppDataIsolationEnabled; 615 616 @GuardedBy("mLock") 617 private final Set<Integer> mUidsWithLegacyExternalStorage = new ArraySet<>(); 618 // Not guarded by lock, always used on the ActivityManager thread 619 private final Map<Integer, PackageMonitor> mPackageMonitorsForUser = new ArrayMap<>(); 620 621 622 class ObbState implements IBinder.DeathRecipient { ObbState(String rawPath, String canonicalPath, int callingUid, IObbActionListener token, int nonce, String volId)623 public ObbState(String rawPath, String canonicalPath, int callingUid, 624 IObbActionListener token, int nonce, String volId) { 625 this.rawPath = rawPath; 626 this.canonicalPath = canonicalPath; 627 this.ownerGid = UserHandle.getSharedAppGid(callingUid); 628 this.token = token; 629 this.nonce = nonce; 630 this.volId = volId; 631 } 632 633 final String rawPath; 634 final String canonicalPath; 635 636 final int ownerGid; 637 638 // Token of remote Binder caller 639 final IObbActionListener token; 640 641 // Identifier to pass back to the token 642 final int nonce; 643 644 String volId; 645 getBinder()646 public IBinder getBinder() { 647 return token.asBinder(); 648 } 649 650 @Override binderDied()651 public void binderDied() { 652 ObbAction action = new UnmountObbAction(this, true); 653 mObbActionHandler.sendMessage(mObbActionHandler.obtainMessage(OBB_RUN_ACTION, action)); 654 } 655 link()656 public void link() throws RemoteException { 657 getBinder().linkToDeath(this, 0); 658 } 659 unlink()660 public void unlink() { 661 getBinder().unlinkToDeath(this, 0); 662 } 663 664 @Override toString()665 public String toString() { 666 StringBuilder sb = new StringBuilder("ObbState{"); 667 sb.append("rawPath=").append(rawPath); 668 sb.append(",canonicalPath=").append(canonicalPath); 669 sb.append(",ownerGid=").append(ownerGid); 670 sb.append(",token=").append(token); 671 sb.append(",binder=").append(getBinder()); 672 sb.append(",volId=").append(volId); 673 sb.append('}'); 674 return sb.toString(); 675 } 676 } 677 678 // OBB Action Handler 679 final private ObbActionHandler mObbActionHandler; 680 681 // OBB action handler messages 682 private static final int OBB_RUN_ACTION = 1; 683 private static final int OBB_FLUSH_MOUNT_STATE = 2; 684 685 // Last fstrim operation tracking 686 private static final String LAST_FSTRIM_FILE = "last-fstrim"; 687 private final File mLastMaintenanceFile; 688 private long mLastMaintenance; 689 690 // Handler messages 691 private static final int H_SYSTEM_READY = 1; 692 private static final int H_DAEMON_CONNECTED = 2; 693 private static final int H_SHUTDOWN = 3; 694 private static final int H_FSTRIM = 4; 695 private static final int H_VOLUME_MOUNT = 5; 696 private static final int H_VOLUME_BROADCAST = 6; 697 private static final int H_INTERNAL_BROADCAST = 7; 698 private static final int H_VOLUME_UNMOUNT = 8; 699 private static final int H_PARTITION_FORGET = 9; 700 private static final int H_RESET = 10; 701 private static final int H_RUN_IDLE_MAINT = 11; 702 private static final int H_ABORT_IDLE_MAINT = 12; 703 private static final int H_BOOT_COMPLETED = 13; 704 private static final int H_COMPLETE_UNLOCK_USER = 14; 705 private static final int H_VOLUME_STATE_CHANGED = 15; 706 707 class StorageManagerServiceHandler extends Handler { StorageManagerServiceHandler(Looper looper)708 public StorageManagerServiceHandler(Looper looper) { 709 super(looper); 710 } 711 712 @Override handleMessage(Message msg)713 public void handleMessage(Message msg) { 714 switch (msg.what) { 715 case H_SYSTEM_READY: { 716 handleSystemReady(); 717 break; 718 } 719 case H_BOOT_COMPLETED: { 720 handleBootCompleted(); 721 break; 722 } 723 case H_DAEMON_CONNECTED: { 724 handleDaemonConnected(); 725 break; 726 } 727 case H_FSTRIM: { 728 Slog.i(TAG, "Running fstrim idle maintenance"); 729 730 // Remember when we kicked it off 731 try { 732 mLastMaintenance = System.currentTimeMillis(); 733 mLastMaintenanceFile.setLastModified(mLastMaintenance); 734 } catch (Exception e) { 735 Slog.e(TAG, "Unable to record last fstrim!"); 736 } 737 738 // TODO: Reintroduce shouldBenchmark() test 739 fstrim(0, null); 740 741 // invoke the completion callback, if any 742 // TODO: fstrim is non-blocking, so remove this useless callback 743 Runnable callback = (Runnable) msg.obj; 744 if (callback != null) { 745 callback.run(); 746 } 747 break; 748 } 749 case H_SHUTDOWN: { 750 final IStorageShutdownObserver obs = (IStorageShutdownObserver) msg.obj; 751 boolean success = false; 752 try { 753 mVold.shutdown(); 754 success = true; 755 } catch (Exception e) { 756 Slog.wtf(TAG, e); 757 } 758 if (obs != null) { 759 try { 760 obs.onShutDownComplete(success ? 0 : -1); 761 } catch (Exception ignored) { 762 } 763 } 764 break; 765 } 766 case H_VOLUME_MOUNT: { 767 final VolumeInfo vol = (VolumeInfo) msg.obj; 768 if (isMountDisallowed(vol)) { 769 Slog.i(TAG, "Ignoring mount " + vol.getId() + " due to policy"); 770 break; 771 } 772 773 mount(vol); 774 break; 775 } 776 case H_VOLUME_UNMOUNT: { 777 final VolumeInfo vol = (VolumeInfo) msg.obj; 778 unmount(vol); 779 break; 780 } 781 case H_VOLUME_BROADCAST: { 782 final StorageVolume userVol = (StorageVolume) msg.obj; 783 final String envState = userVol.getState(); 784 Slog.d(TAG, "Volume " + userVol.getId() + " broadcasting " + envState + " to " 785 + userVol.getOwner()); 786 787 final String action = VolumeInfo.getBroadcastForEnvironment(envState); 788 if (action != null) { 789 final Intent intent = new Intent(action, 790 Uri.fromFile(userVol.getPathFile())); 791 intent.putExtra(StorageVolume.EXTRA_STORAGE_VOLUME, userVol); 792 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT 793 | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND); 794 mContext.sendBroadcastAsUser(intent, userVol.getOwner()); 795 } 796 break; 797 } 798 case H_INTERNAL_BROADCAST: { 799 // Internal broadcasts aimed at system components, not for 800 // third-party apps. 801 final Intent intent = (Intent) msg.obj; 802 mContext.sendBroadcastAsUser(intent, UserHandle.ALL, 803 android.Manifest.permission.WRITE_MEDIA_STORAGE); 804 break; 805 } 806 case H_PARTITION_FORGET: { 807 final VolumeRecord rec = (VolumeRecord) msg.obj; 808 forgetPartition(rec.partGuid, rec.fsUuid); 809 break; 810 } 811 case H_RESET: { 812 resetIfBootedAndConnected(); 813 break; 814 } 815 case H_RUN_IDLE_MAINT: { 816 Slog.i(TAG, "Running idle maintenance"); 817 runIdleMaint((Runnable)msg.obj); 818 break; 819 } 820 case H_ABORT_IDLE_MAINT: { 821 Slog.i(TAG, "Aborting idle maintenance"); 822 abortIdleMaint((Runnable)msg.obj); 823 break; 824 } 825 case H_COMPLETE_UNLOCK_USER: { 826 completeUnlockUser((int) msg.obj); 827 break; 828 } 829 case H_VOLUME_STATE_CHANGED: { 830 final SomeArgs args = (SomeArgs) msg.obj; 831 onVolumeStateChangedAsync((VolumeInfo) args.arg1, (int) args.arg2, 832 (int) args.arg3); 833 } 834 } 835 } 836 } 837 838 private final Handler mHandler; 839 840 private BroadcastReceiver mUserReceiver = new BroadcastReceiver() { 841 @Override 842 public void onReceive(Context context, Intent intent) { 843 final String action = intent.getAction(); 844 final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1); 845 Preconditions.checkArgument(userId >= 0); 846 847 try { 848 if (Intent.ACTION_USER_ADDED.equals(action)) { 849 final UserManager um = mContext.getSystemService(UserManager.class); 850 final int userSerialNumber = um.getUserSerialNumber(userId); 851 mVold.onUserAdded(userId, userSerialNumber); 852 } else if (Intent.ACTION_USER_REMOVED.equals(action)) { 853 synchronized (mVolumes) { 854 final int size = mVolumes.size(); 855 for (int i = 0; i < size; i++) { 856 final VolumeInfo vol = mVolumes.valueAt(i); 857 if (vol.mountUserId == userId) { 858 vol.mountUserId = UserHandle.USER_NULL; 859 mHandler.obtainMessage(H_VOLUME_UNMOUNT, vol).sendToTarget(); 860 } 861 } 862 } 863 mVold.onUserRemoved(userId); 864 } 865 } catch (Exception e) { 866 Slog.wtf(TAG, e); 867 } 868 } 869 }; 870 waitForLatch(CountDownLatch latch, String condition, long timeoutMillis)871 private void waitForLatch(CountDownLatch latch, String condition, long timeoutMillis) 872 throws TimeoutException { 873 final long startMillis = SystemClock.elapsedRealtime(); 874 while (true) { 875 try { 876 if (latch.await(5000, TimeUnit.MILLISECONDS)) { 877 return; 878 } else { 879 Slog.w(TAG, "Thread " + Thread.currentThread().getName() 880 + " still waiting for " + condition + "..."); 881 } 882 } catch (InterruptedException e) { 883 Slog.w(TAG, "Interrupt while waiting for " + condition); 884 } 885 if (timeoutMillis > 0 && SystemClock.elapsedRealtime() > startMillis + timeoutMillis) { 886 throw new TimeoutException("Thread " + Thread.currentThread().getName() 887 + " gave up waiting for " + condition + " after " + timeoutMillis + "ms"); 888 } 889 } 890 } 891 handleSystemReady()892 private void handleSystemReady() { 893 // Start scheduling nominally-daily fstrim operations 894 MountServiceIdler.scheduleIdlePass(mContext); 895 896 // Toggle zram-enable system property in response to settings 897 mContext.getContentResolver().registerContentObserver( 898 Settings.Global.getUriFor(Settings.Global.ZRAM_ENABLED), 899 false /*notifyForDescendants*/, 900 new ContentObserver(null /* current thread */) { 901 @Override 902 public void onChange(boolean selfChange) { 903 refreshZramSettings(); 904 } 905 }); 906 refreshZramSettings(); 907 908 // Schedule zram writeback unless zram is disabled by persist.sys.zram_enabled 909 String zramPropValue = SystemProperties.get(ZRAM_ENABLED_PROPERTY); 910 if (!zramPropValue.equals("0") 911 && mContext.getResources().getBoolean( 912 com.android.internal.R.bool.config_zramWriteback)) { 913 ZramWriteback.scheduleZramWriteback(mContext); 914 } 915 // Toggle isolated-enable system property in response to settings 916 mContext.getContentResolver().registerContentObserver( 917 Settings.Global.getUriFor(Settings.Global.ISOLATED_STORAGE_REMOTE), 918 false /*notifyForDescendants*/, 919 new ContentObserver(null /* current thread */) { 920 @Override 921 public void onChange(boolean selfChange) { 922 refreshIsolatedStorageSettings(); 923 } 924 }); 925 // For now, simply clone property when it changes 926 DeviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_STORAGE_NATIVE_BOOT, 927 mContext.getMainExecutor(), (properties) -> { 928 refreshIsolatedStorageSettings(); 929 refreshFuseSettings(); 930 }); 931 refreshIsolatedStorageSettings(); 932 } 933 934 /** 935 * Update the zram_enabled system property (which init reads to 936 * decide whether to enable zram) to reflect the zram_enabled 937 * preference (which we can change for experimentation purposes). 938 */ refreshZramSettings()939 private void refreshZramSettings() { 940 String propertyValue = SystemProperties.get(ZRAM_ENABLED_PROPERTY); 941 if ("".equals(propertyValue)) { 942 return; // System doesn't have zram toggling support 943 } 944 String desiredPropertyValue = 945 Settings.Global.getInt(mContext.getContentResolver(), 946 Settings.Global.ZRAM_ENABLED, 947 1) != 0 948 ? "1" : "0"; 949 if (!desiredPropertyValue.equals(propertyValue)) { 950 // Avoid redundant disk writes by setting only if we're 951 // changing the property value. There's no race: we're the 952 // sole writer. 953 SystemProperties.set(ZRAM_ENABLED_PROPERTY, desiredPropertyValue); 954 // Schedule writeback only if zram is being enabled. 955 if (desiredPropertyValue.equals("1") 956 && mContext.getResources().getBoolean( 957 com.android.internal.R.bool.config_zramWriteback)) { 958 ZramWriteback.scheduleZramWriteback(mContext); 959 } 960 } 961 } 962 refreshIsolatedStorageSettings()963 private void refreshIsolatedStorageSettings() { 964 // Always copy value from newer DeviceConfig location 965 Settings.Global.putString(mResolver, 966 Settings.Global.ISOLATED_STORAGE_REMOTE, 967 DeviceConfig.getProperty(DeviceConfig.NAMESPACE_STORAGE_NATIVE_BOOT, 968 ISOLATED_STORAGE_ENABLED)); 969 970 final int local = Settings.Global.getInt(mContext.getContentResolver(), 971 Settings.Global.ISOLATED_STORAGE_LOCAL, 0); 972 final int remote = Settings.Global.getInt(mContext.getContentResolver(), 973 Settings.Global.ISOLATED_STORAGE_REMOTE, 0); 974 975 // Walk down precedence chain; we prefer local settings first, then 976 // remote settings, before finally falling back to hard-coded default. 977 final boolean res; 978 if (local == -1) { 979 res = false; 980 } else if (local == 1) { 981 res = true; 982 } else if (remote == -1) { 983 res = false; 984 } else if (remote == 1) { 985 res = true; 986 } else { 987 res = true; 988 } 989 990 Slog.d(TAG, "Isolated storage local flag " + local + " and remote flag " 991 + remote + " resolved to " + res); 992 SystemProperties.set(StorageManager.PROP_ISOLATED_STORAGE, Boolean.toString(res)); 993 } 994 995 /** 996 * The most recent flag change takes precedence. Change fuse Settings flag if Device Config is 997 * changed. Settings flag change will in turn change fuse system property (persist.sys.fuse) 998 * whenever the user reboots. 999 */ refreshFuseSettings()1000 private void refreshFuseSettings() { 1001 int isFuseEnabled = DeviceConfig.getInt(DeviceConfig.NAMESPACE_STORAGE_NATIVE_BOOT, 1002 FUSE_ENABLED, 0); 1003 if (isFuseEnabled == 1) { 1004 Slog.d(TAG, "Device Config flag for FUSE is enabled, turn Settings fuse flag on"); 1005 SystemProperties.set(FeatureFlagUtils.PERSIST_PREFIX 1006 + FeatureFlagUtils.SETTINGS_FUSE_FLAG, "true"); 1007 } else if (isFuseEnabled == -1) { 1008 Slog.d(TAG, "Device Config flag for FUSE is disabled, turn Settings fuse flag off"); 1009 SystemProperties.set(FeatureFlagUtils.PERSIST_PREFIX 1010 + FeatureFlagUtils.SETTINGS_FUSE_FLAG, "false"); 1011 } 1012 // else, keep the build config. 1013 // This can be overridden by direct adjustment of persist.sys.fflag.override.settings_fuse 1014 } 1015 1016 /** 1017 * MediaProvider has a ton of code that makes assumptions about storage 1018 * paths never changing, so we outright kill them to pick up new state. 1019 */ 1020 @Deprecated killMediaProvider(List<UserInfo> users)1021 private void killMediaProvider(List<UserInfo> users) { 1022 if (users == null) return; 1023 1024 final long token = Binder.clearCallingIdentity(); 1025 try { 1026 for (UserInfo user : users) { 1027 // System user does not have media provider, so skip. 1028 if (user.isSystemOnly()) continue; 1029 1030 final ProviderInfo provider = mPmInternal.resolveContentProvider( 1031 MediaStore.AUTHORITY, PackageManager.MATCH_DIRECT_BOOT_AWARE 1032 | PackageManager.MATCH_DIRECT_BOOT_UNAWARE, 1033 user.id); 1034 if (provider != null) { 1035 final IActivityManager am = ActivityManager.getService(); 1036 try { 1037 am.killApplication(provider.applicationInfo.packageName, 1038 UserHandle.getAppId(provider.applicationInfo.uid), 1039 UserHandle.USER_ALL, "vold reset"); 1040 // We only need to run this once. It will kill all users' media processes. 1041 break; 1042 } catch (RemoteException e) { 1043 } 1044 } 1045 } 1046 } finally { 1047 Binder.restoreCallingIdentity(token); 1048 } 1049 } 1050 1051 @GuardedBy("mLock") addInternalVolumeLocked()1052 private void addInternalVolumeLocked() { 1053 // Create a stub volume that represents internal storage 1054 final VolumeInfo internal = new VolumeInfo(VolumeInfo.ID_PRIVATE_INTERNAL, 1055 VolumeInfo.TYPE_PRIVATE, null, null); 1056 internal.state = VolumeInfo.STATE_MOUNTED; 1057 internal.path = Environment.getDataDirectory().getAbsolutePath(); 1058 mVolumes.put(internal.id, internal); 1059 } 1060 initIfBootedAndConnected()1061 private void initIfBootedAndConnected() { 1062 Slog.d(TAG, "Thinking about init, mBootCompleted=" + mBootCompleted 1063 + ", mDaemonConnected=" + mDaemonConnected); 1064 if (mBootCompleted && mDaemonConnected 1065 && !StorageManager.isFileEncryptedNativeOnly()) { 1066 // When booting a device without native support, make sure that our 1067 // user directories are locked or unlocked based on the current 1068 // emulation status. 1069 final boolean initLocked = StorageManager.isFileEncryptedEmulatedOnly(); 1070 Slog.d(TAG, "Setting up emulation state, initlocked=" + initLocked); 1071 final List<UserInfo> users = mContext.getSystemService(UserManager.class).getUsers(); 1072 for (UserInfo user : users) { 1073 try { 1074 if (initLocked) { 1075 mVold.lockUserKey(user.id); 1076 } else { 1077 mVold.unlockUserKey(user.id, user.serialNumber, encodeBytes(null), 1078 encodeBytes(null)); 1079 } 1080 } catch (Exception e) { 1081 Slog.wtf(TAG, e); 1082 } 1083 } 1084 } 1085 } 1086 resetIfBootedAndConnected()1087 private void resetIfBootedAndConnected() { 1088 Slog.d(TAG, "Thinking about reset, mBootCompleted=" + mBootCompleted 1089 + ", mDaemonConnected=" + mDaemonConnected); 1090 if (mBootCompleted && mDaemonConnected) { 1091 final UserManager userManager = mContext.getSystemService(UserManager.class); 1092 final List<UserInfo> users = userManager.getUsers(); 1093 1094 if (mIsFuseEnabled) { 1095 mStorageSessionController.onReset(mVold, () -> { 1096 mHandler.removeCallbacksAndMessages(null); 1097 }); 1098 } else { 1099 killMediaProvider(users); 1100 } 1101 1102 final int[] systemUnlockedUsers; 1103 synchronized (mLock) { 1104 // make copy as sorting can change order 1105 systemUnlockedUsers = Arrays.copyOf(mSystemUnlockedUsers, 1106 mSystemUnlockedUsers.length); 1107 1108 mDisks.clear(); 1109 mVolumes.clear(); 1110 1111 addInternalVolumeLocked(); 1112 } 1113 1114 try { 1115 // TODO(b/135341433): Remove paranoid logging when FUSE is stable 1116 Slog.i(TAG, "Resetting vold..."); 1117 mVold.reset(); 1118 Slog.i(TAG, "Reset vold"); 1119 1120 // Tell vold about all existing and started users 1121 for (UserInfo user : users) { 1122 mVold.onUserAdded(user.id, user.serialNumber); 1123 } 1124 for (int userId : systemUnlockedUsers) { 1125 mVold.onUserStarted(userId); 1126 mStoraged.onUserStarted(userId); 1127 } 1128 if (mIsAutomotive) { 1129 restoreAllUnlockedUsers(userManager, users, systemUnlockedUsers); 1130 } 1131 mVold.onSecureKeyguardStateChanged(mSecureKeyguardShowing); 1132 mStorageManagerInternal.onReset(mVold); 1133 } catch (Exception e) { 1134 Slog.wtf(TAG, e); 1135 } 1136 } 1137 } 1138 restoreAllUnlockedUsers(UserManager userManager, List<UserInfo> allUsers, int[] systemUnlockedUsers)1139 private void restoreAllUnlockedUsers(UserManager userManager, List<UserInfo> allUsers, 1140 int[] systemUnlockedUsers) throws Exception { 1141 Arrays.sort(systemUnlockedUsers); 1142 UserManager.invalidateIsUserUnlockedCache(); 1143 for (UserInfo user : allUsers) { 1144 int userId = user.id; 1145 if (!userManager.isUserRunning(userId)) { 1146 continue; 1147 } 1148 if (Arrays.binarySearch(systemUnlockedUsers, userId) >= 0) { 1149 continue; 1150 } 1151 boolean unlockingOrUnlocked = userManager.isUserUnlockingOrUnlocked(userId); 1152 if (!unlockingOrUnlocked) { 1153 continue; 1154 } 1155 Slog.w(TAG, "UNLOCK_USER lost from vold reset, will retry, user:" + userId); 1156 mVold.onUserStarted(userId); 1157 mStoraged.onUserStarted(userId); 1158 mHandler.obtainMessage(H_COMPLETE_UNLOCK_USER, userId).sendToTarget(); 1159 } 1160 } 1161 onUnlockUser(int userId)1162 private void onUnlockUser(int userId) { 1163 Slog.d(TAG, "onUnlockUser " + userId); 1164 1165 // We purposefully block here to make sure that user-specific 1166 // staging area is ready so it's ready for zygote-forked apps to 1167 // bind mount against. 1168 try { 1169 mStorageSessionController.onUnlockUser(userId); 1170 mVold.onUserStarted(userId); 1171 mStoraged.onUserStarted(userId); 1172 } catch (Exception e) { 1173 Slog.wtf(TAG, e); 1174 } 1175 1176 mHandler.obtainMessage(H_COMPLETE_UNLOCK_USER, userId).sendToTarget(); 1177 } 1178 completeUnlockUser(int userId)1179 private void completeUnlockUser(int userId) { 1180 // If user 0 has completed unlock, perform a one-time migration of legacy obb data 1181 // to its new location. This may take time depending on the size of the data to be copied 1182 // so it's done on the StorageManager handler thread. 1183 if (userId == 0) { 1184 mPmInternal.migrateLegacyObbData(); 1185 } 1186 1187 onKeyguardStateChanged(false); 1188 1189 // Record user as started so newly mounted volumes kick off events 1190 // correctly, then synthesize events for any already-mounted volumes. 1191 synchronized (mLock) { 1192 if (mIsAutomotive) { 1193 for (int unlockedUser : mSystemUnlockedUsers) { 1194 if (unlockedUser == userId) { 1195 // This can happen as restoreAllUnlockedUsers can double post the message. 1196 Log.i(TAG, "completeUnlockUser called for already unlocked user:" + userId); 1197 return; 1198 } 1199 } 1200 } 1201 for (int i = 0; i < mVolumes.size(); i++) { 1202 final VolumeInfo vol = mVolumes.valueAt(i); 1203 if (vol.isVisibleForRead(userId) && vol.isMountedReadable()) { 1204 final StorageVolume userVol = vol.buildStorageVolume(mContext, userId, false); 1205 mHandler.obtainMessage(H_VOLUME_BROADCAST, userVol).sendToTarget(); 1206 1207 final String envState = VolumeInfo.getEnvironmentForState(vol.getState()); 1208 mCallbacks.notifyStorageStateChanged(userVol.getPath(), envState, envState); 1209 } 1210 } 1211 mSystemUnlockedUsers = ArrayUtils.appendInt(mSystemUnlockedUsers, userId); 1212 } 1213 } 1214 onCleanupUser(int userId)1215 private void onCleanupUser(int userId) { 1216 Slog.d(TAG, "onCleanupUser " + userId); 1217 1218 try { 1219 mVold.onUserStopped(userId); 1220 mStoraged.onUserStopped(userId); 1221 } catch (Exception e) { 1222 Slog.wtf(TAG, e); 1223 } 1224 1225 synchronized (mLock) { 1226 mSystemUnlockedUsers = ArrayUtils.removeInt(mSystemUnlockedUsers, userId); 1227 } 1228 } 1229 onStopUser(int userId)1230 private void onStopUser(int userId) { 1231 Slog.i(TAG, "onStopUser " + userId); 1232 try { 1233 mStorageSessionController.onUserStopping(userId); 1234 } catch (Exception e) { 1235 Slog.wtf(TAG, e); 1236 } 1237 PackageMonitor monitor = mPackageMonitorsForUser.remove(userId); 1238 if (monitor != null) { 1239 monitor.unregister(); 1240 } 1241 } 1242 supportsBlockCheckpoint()1243 private boolean supportsBlockCheckpoint() throws RemoteException { 1244 enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS); 1245 return mVold.supportsBlockCheckpoint(); 1246 } 1247 1248 @Override onAwakeStateChanged(boolean isAwake)1249 public void onAwakeStateChanged(boolean isAwake) { 1250 // Ignored 1251 } 1252 1253 @Override onKeyguardStateChanged(boolean isShowing)1254 public void onKeyguardStateChanged(boolean isShowing) { 1255 // Push down current secure keyguard status so that we ignore malicious 1256 // USB devices while locked. 1257 mSecureKeyguardShowing = isShowing 1258 && mContext.getSystemService(KeyguardManager.class).isDeviceSecure(mCurrentUserId); 1259 try { 1260 mVold.onSecureKeyguardStateChanged(mSecureKeyguardShowing); 1261 } catch (Exception e) { 1262 Slog.wtf(TAG, e); 1263 } 1264 } 1265 runIdleMaintenance(Runnable callback)1266 void runIdleMaintenance(Runnable callback) { 1267 mHandler.sendMessage(mHandler.obtainMessage(H_FSTRIM, callback)); 1268 } 1269 1270 // Binder entry point for kicking off an immediate fstrim 1271 @Override runMaintenance()1272 public void runMaintenance() { 1273 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS); 1274 runIdleMaintenance(null); 1275 } 1276 1277 @Override lastMaintenance()1278 public long lastMaintenance() { 1279 return mLastMaintenance; 1280 } 1281 onDaemonConnected()1282 public void onDaemonConnected() { 1283 mDaemonConnected = true; 1284 mHandler.obtainMessage(H_DAEMON_CONNECTED).sendToTarget(); 1285 } 1286 handleDaemonConnected()1287 private void handleDaemonConnected() { 1288 initIfBootedAndConnected(); 1289 resetIfBootedAndConnected(); 1290 1291 // On an encrypted device we can't see system properties yet, so pull 1292 // the system locale out of the mount service. 1293 if ("".equals(VoldProperties.encrypt_progress().orElse(""))) { 1294 copyLocaleFromMountService(); 1295 } 1296 } 1297 copyLocaleFromMountService()1298 private void copyLocaleFromMountService() { 1299 String systemLocale; 1300 try { 1301 systemLocale = getField(StorageManager.SYSTEM_LOCALE_KEY); 1302 } catch (RemoteException e) { 1303 return; 1304 } 1305 if (TextUtils.isEmpty(systemLocale)) { 1306 return; 1307 } 1308 1309 Slog.d(TAG, "Got locale " + systemLocale + " from mount service"); 1310 Locale locale = Locale.forLanguageTag(systemLocale); 1311 Configuration config = new Configuration(); 1312 config.setLocale(locale); 1313 try { 1314 ActivityManager.getService().updatePersistentConfiguration(config); 1315 } catch (RemoteException e) { 1316 Slog.e(TAG, "Error setting system locale from mount service", e); 1317 } 1318 1319 // Temporary workaround for http://b/17945169. 1320 Slog.d(TAG, "Setting system properties to " + systemLocale + " from mount service"); 1321 SystemProperties.set("persist.sys.locale", locale.toLanguageTag()); 1322 } 1323 1324 private final IVoldListener mListener = new IVoldListener.Stub() { 1325 @Override 1326 public void onDiskCreated(String diskId, int flags) { 1327 synchronized (mLock) { 1328 final String value = SystemProperties.get(StorageManager.PROP_ADOPTABLE); 1329 switch (value) { 1330 case "force_on": 1331 flags |= DiskInfo.FLAG_ADOPTABLE; 1332 break; 1333 case "force_off": 1334 flags &= ~DiskInfo.FLAG_ADOPTABLE; 1335 break; 1336 } 1337 mDisks.put(diskId, new DiskInfo(diskId, flags)); 1338 } 1339 } 1340 1341 @Override 1342 public void onDiskScanned(String diskId) { 1343 synchronized (mLock) { 1344 final DiskInfo disk = mDisks.get(diskId); 1345 if (disk != null) { 1346 onDiskScannedLocked(disk); 1347 } 1348 } 1349 } 1350 1351 @Override 1352 public void onDiskMetadataChanged(String diskId, long sizeBytes, String label, 1353 String sysPath) { 1354 synchronized (mLock) { 1355 final DiskInfo disk = mDisks.get(diskId); 1356 if (disk != null) { 1357 disk.size = sizeBytes; 1358 disk.label = label; 1359 disk.sysPath = sysPath; 1360 } 1361 } 1362 } 1363 1364 @Override 1365 public void onDiskDestroyed(String diskId) { 1366 synchronized (mLock) { 1367 final DiskInfo disk = mDisks.remove(diskId); 1368 if (disk != null) { 1369 mCallbacks.notifyDiskDestroyed(disk); 1370 } 1371 } 1372 } 1373 1374 @Override 1375 public void onVolumeCreated(String volId, int type, String diskId, String partGuid, 1376 int userId) { 1377 synchronized (mLock) { 1378 final DiskInfo disk = mDisks.get(diskId); 1379 final VolumeInfo vol = new VolumeInfo(volId, type, disk, partGuid); 1380 vol.mountUserId = userId; 1381 mVolumes.put(volId, vol); 1382 onVolumeCreatedLocked(vol); 1383 } 1384 } 1385 1386 @Override 1387 public void onVolumeStateChanged(String volId, int state) { 1388 synchronized (mLock) { 1389 final VolumeInfo vol = mVolumes.get(volId); 1390 if (vol != null) { 1391 final int oldState = vol.state; 1392 final int newState = state; 1393 vol.state = newState; 1394 final SomeArgs args = SomeArgs.obtain(); 1395 args.arg1 = vol; 1396 args.arg2 = oldState; 1397 args.arg3 = newState; 1398 mHandler.obtainMessage(H_VOLUME_STATE_CHANGED, args).sendToTarget(); 1399 onVolumeStateChangedLocked(vol, oldState, newState); 1400 } 1401 } 1402 } 1403 1404 @Override 1405 public void onVolumeMetadataChanged(String volId, String fsType, String fsUuid, 1406 String fsLabel) { 1407 synchronized (mLock) { 1408 final VolumeInfo vol = mVolumes.get(volId); 1409 if (vol != null) { 1410 vol.fsType = fsType; 1411 vol.fsUuid = fsUuid; 1412 vol.fsLabel = fsLabel; 1413 } 1414 } 1415 } 1416 1417 @Override 1418 public void onVolumePathChanged(String volId, String path) { 1419 synchronized (mLock) { 1420 final VolumeInfo vol = mVolumes.get(volId); 1421 if (vol != null) { 1422 vol.path = path; 1423 } 1424 } 1425 } 1426 1427 @Override 1428 public void onVolumeInternalPathChanged(String volId, String internalPath) { 1429 synchronized (mLock) { 1430 final VolumeInfo vol = mVolumes.get(volId); 1431 if (vol != null) { 1432 vol.internalPath = internalPath; 1433 } 1434 } 1435 } 1436 1437 @Override 1438 public void onVolumeDestroyed(String volId) { 1439 VolumeInfo vol = null; 1440 synchronized (mLock) { 1441 vol = mVolumes.remove(volId); 1442 } 1443 1444 if (vol != null) { 1445 mStorageSessionController.onVolumeRemove(vol); 1446 try { 1447 if (vol.type == VolumeInfo.TYPE_PRIVATE) { 1448 mInstaller.onPrivateVolumeRemoved(vol.getFsUuid()); 1449 } 1450 } catch (Installer.InstallerException e) { 1451 Slog.i(TAG, "Failed when private volume unmounted " + vol, e); 1452 } 1453 } 1454 } 1455 }; 1456 1457 @GuardedBy("mLock") onDiskScannedLocked(DiskInfo disk)1458 private void onDiskScannedLocked(DiskInfo disk) { 1459 int volumeCount = 0; 1460 for (int i = 0; i < mVolumes.size(); i++) { 1461 final VolumeInfo vol = mVolumes.valueAt(i); 1462 if (Objects.equals(disk.id, vol.getDiskId())) { 1463 volumeCount++; 1464 } 1465 } 1466 1467 final Intent intent = new Intent(DiskInfo.ACTION_DISK_SCANNED); 1468 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT 1469 | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND); 1470 intent.putExtra(DiskInfo.EXTRA_DISK_ID, disk.id); 1471 intent.putExtra(DiskInfo.EXTRA_VOLUME_COUNT, volumeCount); 1472 mHandler.obtainMessage(H_INTERNAL_BROADCAST, intent).sendToTarget(); 1473 1474 final CountDownLatch latch = mDiskScanLatches.remove(disk.id); 1475 if (latch != null) { 1476 latch.countDown(); 1477 } 1478 1479 disk.volumeCount = volumeCount; 1480 mCallbacks.notifyDiskScanned(disk, volumeCount); 1481 } 1482 1483 @GuardedBy("mLock") onVolumeCreatedLocked(VolumeInfo vol)1484 private void onVolumeCreatedLocked(VolumeInfo vol) { 1485 if (mPmInternal.isOnlyCoreApps()) { 1486 Slog.d(TAG, "System booted in core-only mode; ignoring volume " + vol.getId()); 1487 return; 1488 } 1489 final ActivityManagerInternal amInternal = 1490 LocalServices.getService(ActivityManagerInternal.class); 1491 1492 if (mIsFuseEnabled && vol.mountUserId >= 0 1493 && !amInternal.isUserRunning(vol.mountUserId, 0)) { 1494 Slog.d(TAG, "Ignoring volume " + vol.getId() + " because user " 1495 + Integer.toString(vol.mountUserId) + " is no longer running."); 1496 return; 1497 } 1498 1499 if (vol.type == VolumeInfo.TYPE_EMULATED) { 1500 final StorageManager storage = mContext.getSystemService(StorageManager.class); 1501 final VolumeInfo privateVol = storage.findPrivateForEmulated(vol); 1502 1503 if (Objects.equals(StorageManager.UUID_PRIVATE_INTERNAL, mPrimaryStorageUuid) 1504 && VolumeInfo.ID_PRIVATE_INTERNAL.equals(privateVol.id)) { 1505 Slog.v(TAG, "Found primary storage at " + vol); 1506 vol.mountFlags |= VolumeInfo.MOUNT_FLAG_PRIMARY; 1507 vol.mountFlags |= VolumeInfo.MOUNT_FLAG_VISIBLE; 1508 mHandler.obtainMessage(H_VOLUME_MOUNT, vol).sendToTarget(); 1509 1510 } else if (Objects.equals(privateVol.fsUuid, mPrimaryStorageUuid)) { 1511 Slog.v(TAG, "Found primary storage at " + vol); 1512 vol.mountFlags |= VolumeInfo.MOUNT_FLAG_PRIMARY; 1513 vol.mountFlags |= VolumeInfo.MOUNT_FLAG_VISIBLE; 1514 mHandler.obtainMessage(H_VOLUME_MOUNT, vol).sendToTarget(); 1515 } 1516 1517 } else if (vol.type == VolumeInfo.TYPE_PUBLIC) { 1518 // TODO: only look at first public partition 1519 if (Objects.equals(StorageManager.UUID_PRIMARY_PHYSICAL, mPrimaryStorageUuid) 1520 && vol.disk.isDefaultPrimary()) { 1521 Slog.v(TAG, "Found primary storage at " + vol); 1522 vol.mountFlags |= VolumeInfo.MOUNT_FLAG_PRIMARY; 1523 vol.mountFlags |= VolumeInfo.MOUNT_FLAG_VISIBLE; 1524 } 1525 1526 // Adoptable public disks are visible to apps, since they meet 1527 // public API requirement of being in a stable location. 1528 if (vol.disk.isAdoptable()) { 1529 vol.mountFlags |= VolumeInfo.MOUNT_FLAG_VISIBLE; 1530 } 1531 1532 vol.mountUserId = mCurrentUserId; 1533 mHandler.obtainMessage(H_VOLUME_MOUNT, vol).sendToTarget(); 1534 1535 } else if (vol.type == VolumeInfo.TYPE_PRIVATE) { 1536 mHandler.obtainMessage(H_VOLUME_MOUNT, vol).sendToTarget(); 1537 1538 } else if (vol.type == VolumeInfo.TYPE_STUB) { 1539 vol.mountUserId = mCurrentUserId; 1540 mHandler.obtainMessage(H_VOLUME_MOUNT, vol).sendToTarget(); 1541 } else { 1542 Slog.d(TAG, "Skipping automatic mounting of " + vol); 1543 } 1544 } 1545 isBroadcastWorthy(VolumeInfo vol)1546 private boolean isBroadcastWorthy(VolumeInfo vol) { 1547 switch (vol.getType()) { 1548 case VolumeInfo.TYPE_PRIVATE: 1549 case VolumeInfo.TYPE_PUBLIC: 1550 case VolumeInfo.TYPE_EMULATED: 1551 case VolumeInfo.TYPE_STUB: 1552 break; 1553 default: 1554 return false; 1555 } 1556 1557 switch (vol.getState()) { 1558 case VolumeInfo.STATE_MOUNTED: 1559 case VolumeInfo.STATE_MOUNTED_READ_ONLY: 1560 case VolumeInfo.STATE_EJECTING: 1561 case VolumeInfo.STATE_UNMOUNTED: 1562 case VolumeInfo.STATE_UNMOUNTABLE: 1563 case VolumeInfo.STATE_BAD_REMOVAL: 1564 break; 1565 default: 1566 return false; 1567 } 1568 1569 return true; 1570 } 1571 1572 onVolumeStateChangedLocked(VolumeInfo vol, int oldState, int newState)1573 private void onVolumeStateChangedLocked(VolumeInfo vol, int oldState, int newState) { 1574 if (vol.type == VolumeInfo.TYPE_EMULATED) { 1575 if (newState != VolumeInfo.STATE_MOUNTED) { 1576 mFuseMountedUser.remove(vol.getMountUserId()); 1577 } else if (mVoldAppDataIsolationEnabled){ 1578 final int userId = vol.getMountUserId(); 1579 mFuseMountedUser.add(userId); 1580 // Async remount app storage so it won't block the main thread. 1581 new Thread(() -> { 1582 Map<Integer, String> pidPkgMap = null; 1583 // getProcessesWithPendingBindMounts() could fail when a new app process is 1584 // starting and it's not planning to mount storage dirs in zygote, but it's 1585 // rare, so we retry 5 times and hope we can get the result successfully. 1586 for (int i = 0; i < 5; i++) { 1587 try { 1588 pidPkgMap = LocalServices.getService(ActivityManagerInternal.class) 1589 .getProcessesWithPendingBindMounts(vol.getMountUserId()); 1590 break; 1591 } catch (IllegalStateException e) { 1592 Slog.i(TAG, "Some processes are starting, retry"); 1593 // Wait 100ms and retry so hope the pending process is started. 1594 SystemClock.sleep(100); 1595 } 1596 } 1597 if (pidPkgMap != null) { 1598 remountAppStorageDirs(pidPkgMap, userId); 1599 } else { 1600 Slog.wtf(TAG, "Not able to getStorageNotOptimizedProcesses() after" 1601 + " 5 retries"); 1602 } 1603 }).start(); 1604 } 1605 } 1606 } 1607 1608 onVolumeStateChangedAsync(VolumeInfo vol, int oldState, int newState)1609 private void onVolumeStateChangedAsync(VolumeInfo vol, int oldState, int newState) { 1610 synchronized (mLock) { 1611 // Remember that we saw this volume so we're ready to accept user 1612 // metadata, or so we can annoy them when a private volume is ejected 1613 if (!TextUtils.isEmpty(vol.fsUuid)) { 1614 VolumeRecord rec = mRecords.get(vol.fsUuid); 1615 if (rec == null) { 1616 rec = new VolumeRecord(vol.type, vol.fsUuid); 1617 rec.partGuid = vol.partGuid; 1618 rec.createdMillis = System.currentTimeMillis(); 1619 if (vol.type == VolumeInfo.TYPE_PRIVATE) { 1620 rec.nickname = vol.disk.getDescription(); 1621 } 1622 mRecords.put(rec.fsUuid, rec); 1623 } else { 1624 // Handle upgrade case where we didn't store partition GUID 1625 if (TextUtils.isEmpty(rec.partGuid)) { 1626 rec.partGuid = vol.partGuid; 1627 } 1628 } 1629 1630 rec.lastSeenMillis = System.currentTimeMillis(); 1631 writeSettingsLocked(); 1632 } 1633 } 1634 1635 if (newState == VolumeInfo.STATE_MOUNTED) { 1636 // Private volumes can be unmounted and re-mounted even after a user has 1637 // been unlocked; on devices that support encryption keys tied to the filesystem, 1638 // this requires setting up the keys again. 1639 prepareUserStorageIfNeeded(vol); 1640 } 1641 1642 // This is a blocking call to Storage Service which needs to process volume state changed 1643 // before notifying other listeners. 1644 // Intentionally called without the mLock to avoid deadlocking from the Storage Service. 1645 try { 1646 mStorageSessionController.notifyVolumeStateChanged(vol); 1647 } catch (ExternalStorageServiceException e) { 1648 Log.e(TAG, "Failed to notify volume state changed to the Storage Service", e); 1649 } 1650 synchronized (mLock) { 1651 mCallbacks.notifyVolumeStateChanged(vol, oldState, newState); 1652 1653 // Do not broadcast before boot has completed to avoid launching the 1654 // processes that receive the intent unnecessarily. 1655 if (mBootCompleted && isBroadcastWorthy(vol)) { 1656 final Intent intent = new Intent(VolumeInfo.ACTION_VOLUME_STATE_CHANGED); 1657 intent.putExtra(VolumeInfo.EXTRA_VOLUME_ID, vol.id); 1658 intent.putExtra(VolumeInfo.EXTRA_VOLUME_STATE, newState); 1659 intent.putExtra(VolumeRecord.EXTRA_FS_UUID, vol.fsUuid); 1660 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT 1661 | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND); 1662 mHandler.obtainMessage(H_INTERNAL_BROADCAST, intent).sendToTarget(); 1663 } 1664 1665 final String oldStateEnv = VolumeInfo.getEnvironmentForState(oldState); 1666 final String newStateEnv = VolumeInfo.getEnvironmentForState(newState); 1667 1668 if (!Objects.equals(oldStateEnv, newStateEnv)) { 1669 // Kick state changed event towards all started users. Any users 1670 // started after this point will trigger additional 1671 // user-specific broadcasts. 1672 for (int userId : mSystemUnlockedUsers) { 1673 if (vol.isVisibleForRead(userId)) { 1674 final StorageVolume userVol = vol.buildStorageVolume(mContext, userId, 1675 false); 1676 mHandler.obtainMessage(H_VOLUME_BROADCAST, userVol).sendToTarget(); 1677 1678 mCallbacks.notifyStorageStateChanged(userVol.getPath(), oldStateEnv, 1679 newStateEnv); 1680 } 1681 } 1682 } 1683 1684 if ((vol.type == VolumeInfo.TYPE_PUBLIC || vol.type == VolumeInfo.TYPE_STUB) 1685 && vol.state == VolumeInfo.STATE_EJECTING) { 1686 // TODO: this should eventually be handled by new ObbVolume state changes 1687 /* 1688 * Some OBBs might have been unmounted when this volume was 1689 * unmounted, so send a message to the handler to let it know to 1690 * remove those from the list of mounted OBBS. 1691 */ 1692 mObbActionHandler.sendMessage(mObbActionHandler.obtainMessage( 1693 OBB_FLUSH_MOUNT_STATE, vol.path)); 1694 } 1695 maybeLogMediaMount(vol, newState); 1696 } 1697 } 1698 maybeLogMediaMount(VolumeInfo vol, int newState)1699 private void maybeLogMediaMount(VolumeInfo vol, int newState) { 1700 if (!SecurityLog.isLoggingEnabled()) { 1701 return; 1702 } 1703 1704 final DiskInfo disk = vol.getDisk(); 1705 if (disk == null || (disk.flags & (DiskInfo.FLAG_SD | DiskInfo.FLAG_USB)) == 0) { 1706 return; 1707 } 1708 1709 // Sometimes there is a newline character. 1710 final String label = disk.label != null ? disk.label.trim() : ""; 1711 1712 if (newState == VolumeInfo.STATE_MOUNTED 1713 || newState == VolumeInfo.STATE_MOUNTED_READ_ONLY) { 1714 SecurityLog.writeEvent(SecurityLog.TAG_MEDIA_MOUNT, vol.path, label); 1715 } else if (newState == VolumeInfo.STATE_UNMOUNTED 1716 || newState == VolumeInfo.STATE_BAD_REMOVAL) { 1717 SecurityLog.writeEvent(SecurityLog.TAG_MEDIA_UNMOUNT, vol.path, label); 1718 } 1719 } 1720 1721 @GuardedBy("mLock") onMoveStatusLocked(int status)1722 private void onMoveStatusLocked(int status) { 1723 if (mMoveCallback == null) { 1724 Slog.w(TAG, "Odd, status but no move requested"); 1725 return; 1726 } 1727 1728 // TODO: estimate remaining time 1729 try { 1730 mMoveCallback.onStatusChanged(-1, status, -1); 1731 } catch (RemoteException ignored) { 1732 } 1733 1734 // We've finished copying and we're about to clean up old data, so 1735 // remember that move was successful if we get rebooted 1736 if (status == MOVE_STATUS_COPY_FINISHED) { 1737 Slog.d(TAG, "Move to " + mMoveTargetUuid + " copy phase finshed; persisting"); 1738 1739 mPrimaryStorageUuid = mMoveTargetUuid; 1740 writeSettingsLocked(); 1741 } 1742 1743 if (PackageManager.isMoveStatusFinished(status)) { 1744 Slog.d(TAG, "Move to " + mMoveTargetUuid + " finished with status " + status); 1745 1746 mMoveCallback = null; 1747 mMoveTargetUuid = null; 1748 } 1749 } 1750 enforcePermission(String perm)1751 private void enforcePermission(String perm) { 1752 mContext.enforceCallingOrSelfPermission(perm, perm); 1753 } 1754 1755 /** 1756 * Decide if volume is mountable per device policies. 1757 */ isMountDisallowed(VolumeInfo vol)1758 private boolean isMountDisallowed(VolumeInfo vol) { 1759 UserManager userManager = mContext.getSystemService(UserManager.class); 1760 1761 boolean isUsbRestricted = false; 1762 if (vol.disk != null && vol.disk.isUsb()) { 1763 isUsbRestricted = userManager.hasUserRestriction(UserManager.DISALLOW_USB_FILE_TRANSFER, 1764 Binder.getCallingUserHandle()); 1765 } 1766 1767 boolean isTypeRestricted = false; 1768 if (vol.type == VolumeInfo.TYPE_PUBLIC || vol.type == VolumeInfo.TYPE_PRIVATE 1769 || vol.type == VolumeInfo.TYPE_STUB) { 1770 isTypeRestricted = userManager 1771 .hasUserRestriction(UserManager.DISALLOW_MOUNT_PHYSICAL_MEDIA, 1772 Binder.getCallingUserHandle()); 1773 } 1774 1775 return isUsbRestricted || isTypeRestricted; 1776 } 1777 enforceAdminUser()1778 private void enforceAdminUser() { 1779 UserManager um = (UserManager) mContext.getSystemService(Context.USER_SERVICE); 1780 final int callingUserId = UserHandle.getCallingUserId(); 1781 boolean isAdmin; 1782 long token = Binder.clearCallingIdentity(); 1783 try { 1784 isAdmin = um.getUserInfo(callingUserId).isAdmin(); 1785 } finally { 1786 Binder.restoreCallingIdentity(token); 1787 } 1788 if (!isAdmin) { 1789 throw new SecurityException("Only admin users can adopt sd cards"); 1790 } 1791 } 1792 1793 /** 1794 * Constructs a new StorageManagerService instance 1795 * 1796 * @param context Binder context for this service 1797 */ StorageManagerService(Context context)1798 public StorageManagerService(Context context) { 1799 sSelf = this; 1800 1801 // Snapshot feature flag used for this boot 1802 SystemProperties.set(StorageManager.PROP_ISOLATED_STORAGE_SNAPSHOT, Boolean.toString( 1803 SystemProperties.getBoolean(StorageManager.PROP_ISOLATED_STORAGE, true))); 1804 1805 // If there is no value in the property yet (first boot after data wipe), this value may be 1806 // incorrect until #updateFusePropFromSettings where we set the correct value and reboot if 1807 // different 1808 mIsFuseEnabled = SystemProperties.getBoolean(PROP_FUSE, DEFAULT_FUSE_ENABLED); 1809 mVoldAppDataIsolationEnabled = mIsFuseEnabled && SystemProperties.getBoolean( 1810 ANDROID_VOLD_APP_DATA_ISOLATION_ENABLED_PROPERTY, false); 1811 mContext = context; 1812 mResolver = mContext.getContentResolver(); 1813 mCallbacks = new Callbacks(FgThread.get().getLooper()); 1814 mLockPatternUtils = new LockPatternUtils(mContext); 1815 1816 HandlerThread hthread = new HandlerThread(TAG); 1817 hthread.start(); 1818 mHandler = new StorageManagerServiceHandler(hthread.getLooper()); 1819 1820 // Add OBB Action Handler to StorageManagerService thread. 1821 mObbActionHandler = new ObbActionHandler(IoThread.get().getLooper()); 1822 1823 mStorageSessionController = new StorageSessionController(mContext, mIsFuseEnabled); 1824 1825 mInstaller = new Installer(mContext); 1826 mInstaller.onStart(); 1827 1828 // Initialize the last-fstrim tracking if necessary 1829 File dataDir = Environment.getDataDirectory(); 1830 File systemDir = new File(dataDir, "system"); 1831 mLastMaintenanceFile = new File(systemDir, LAST_FSTRIM_FILE); 1832 if (!mLastMaintenanceFile.exists()) { 1833 // Not setting mLastMaintenance here means that we will force an 1834 // fstrim during reboot following the OTA that installs this code. 1835 try { 1836 (new FileOutputStream(mLastMaintenanceFile)).close(); 1837 } catch (IOException e) { 1838 Slog.e(TAG, "Unable to create fstrim record " + mLastMaintenanceFile.getPath()); 1839 } 1840 } else { 1841 mLastMaintenance = mLastMaintenanceFile.lastModified(); 1842 } 1843 1844 mSettingsFile = new AtomicFile( 1845 new File(Environment.getDataSystemDirectory(), "storage.xml"), "storage-settings"); 1846 1847 synchronized (mLock) { 1848 readSettingsLocked(); 1849 } 1850 1851 LocalServices.addService(StorageManagerInternal.class, mStorageManagerInternal); 1852 1853 final IntentFilter userFilter = new IntentFilter(); 1854 userFilter.addAction(Intent.ACTION_USER_ADDED); 1855 userFilter.addAction(Intent.ACTION_USER_REMOVED); 1856 mContext.registerReceiver(mUserReceiver, userFilter, null, mHandler); 1857 1858 synchronized (mLock) { 1859 addInternalVolumeLocked(); 1860 } 1861 1862 // Add ourself to the Watchdog monitors if enabled. 1863 if (WATCHDOG_ENABLE) { 1864 Watchdog.getInstance().addMonitor(this); 1865 } 1866 1867 mIsAutomotive = context.getPackageManager().hasSystemFeature( 1868 PackageManager.FEATURE_AUTOMOTIVE); 1869 } 1870 1871 /** 1872 * Checks if user changed the persistent settings_fuse flag from Settings UI 1873 * and updates PROP_FUSE (reboots if changed). 1874 */ updateFusePropFromSettings()1875 private void updateFusePropFromSettings() { 1876 boolean settingsFuseFlag = SystemProperties.getBoolean(PROP_SETTINGS_FUSE, 1877 DEFAULT_FUSE_ENABLED); 1878 Slog.d(TAG, "FUSE flags. Settings: " + settingsFuseFlag 1879 + ". Default: " + DEFAULT_FUSE_ENABLED); 1880 1881 if (mIsFuseEnabled != settingsFuseFlag) { 1882 Slog.i(TAG, "Toggling persist.sys.fuse to " + settingsFuseFlag); 1883 // Set prop_fuse to match prop_settings_fuse because it is used by native daemons like 1884 // init, zygote, installd and vold 1885 SystemProperties.set(PROP_FUSE, Boolean.toString(settingsFuseFlag)); 1886 // Then perform hard reboot to kick policy into place 1887 mContext.getSystemService(PowerManager.class).reboot("fuse_prop"); 1888 } 1889 } 1890 start()1891 private void start() { 1892 connectStoraged(); 1893 connectVold(); 1894 } 1895 connectStoraged()1896 private void connectStoraged() { 1897 IBinder binder = ServiceManager.getService("storaged"); 1898 if (binder != null) { 1899 try { 1900 binder.linkToDeath(new DeathRecipient() { 1901 @Override 1902 public void binderDied() { 1903 Slog.w(TAG, "storaged died; reconnecting"); 1904 mStoraged = null; 1905 connectStoraged(); 1906 } 1907 }, 0); 1908 } catch (RemoteException e) { 1909 binder = null; 1910 } 1911 } 1912 1913 if (binder != null) { 1914 mStoraged = IStoraged.Stub.asInterface(binder); 1915 } else { 1916 Slog.w(TAG, "storaged not found; trying again"); 1917 } 1918 1919 if (mStoraged == null) { 1920 BackgroundThread.getHandler().postDelayed(() -> { 1921 connectStoraged(); 1922 }, DateUtils.SECOND_IN_MILLIS); 1923 } else { 1924 onDaemonConnected(); 1925 } 1926 } 1927 connectVold()1928 private void connectVold() { 1929 IBinder binder = ServiceManager.getService("vold"); 1930 if (binder != null) { 1931 try { 1932 binder.linkToDeath(new DeathRecipient() { 1933 @Override 1934 public void binderDied() { 1935 Slog.w(TAG, "vold died; reconnecting"); 1936 mVold = null; 1937 connectVold(); 1938 } 1939 }, 0); 1940 } catch (RemoteException e) { 1941 binder = null; 1942 } 1943 } 1944 1945 if (binder != null) { 1946 mVold = IVold.Stub.asInterface(binder); 1947 try { 1948 mVold.setListener(mListener); 1949 } catch (RemoteException e) { 1950 mVold = null; 1951 Slog.w(TAG, "vold listener rejected; trying again", e); 1952 } 1953 } else { 1954 Slog.w(TAG, "vold not found; trying again"); 1955 } 1956 1957 if (mVold == null) { 1958 BackgroundThread.getHandler().postDelayed(() -> { 1959 connectVold(); 1960 }, DateUtils.SECOND_IN_MILLIS); 1961 } else { 1962 onDaemonConnected(); 1963 } 1964 } 1965 servicesReady()1966 private void servicesReady() { 1967 mPmInternal = LocalServices.getService(PackageManagerInternal.class); 1968 1969 mIPackageManager = IPackageManager.Stub.asInterface( 1970 ServiceManager.getService("package")); 1971 mIAppOpsService = IAppOpsService.Stub.asInterface( 1972 ServiceManager.getService(Context.APP_OPS_SERVICE)); 1973 1974 ProviderInfo provider = getProviderInfo(MediaStore.AUTHORITY); 1975 if (provider != null) { 1976 mMediaStoreAuthorityAppId = UserHandle.getAppId(provider.applicationInfo.uid); 1977 sMediaStoreAuthorityProcessName = provider.applicationInfo.processName; 1978 } 1979 1980 provider = getProviderInfo(Downloads.Impl.AUTHORITY); 1981 if (provider != null) { 1982 mDownloadsAuthorityAppId = UserHandle.getAppId(provider.applicationInfo.uid); 1983 } 1984 1985 provider = getProviderInfo(DocumentsContract.EXTERNAL_STORAGE_PROVIDER_AUTHORITY); 1986 if (provider != null) { 1987 mExternalStorageAuthorityAppId = UserHandle.getAppId(provider.applicationInfo.uid); 1988 } 1989 1990 if (!mIsFuseEnabled) { 1991 try { 1992 mIAppOpsService.startWatchingMode(OP_REQUEST_INSTALL_PACKAGES, null, 1993 mAppOpsCallback); 1994 mIAppOpsService.startWatchingMode(OP_LEGACY_STORAGE, null, mAppOpsCallback); 1995 } catch (RemoteException e) { 1996 } 1997 } 1998 } 1999 getProviderInfo(String authority)2000 private ProviderInfo getProviderInfo(String authority) { 2001 return mPmInternal.resolveContentProvider( 2002 authority, PackageManager.MATCH_DIRECT_BOOT_AWARE 2003 | PackageManager.MATCH_DIRECT_BOOT_UNAWARE, 2004 UserHandle.getUserId(UserHandle.USER_SYSTEM)); 2005 } 2006 updateLegacyStorageApps(String packageName, int uid, boolean hasLegacy)2007 private void updateLegacyStorageApps(String packageName, int uid, boolean hasLegacy) { 2008 synchronized (mLock) { 2009 if (hasLegacy) { 2010 Slog.v(TAG, "Package " + packageName + " has legacy storage"); 2011 mUidsWithLegacyExternalStorage.add(uid); 2012 } else { 2013 // TODO(b/149391976): Handle shared user id. Check if there's any other 2014 // installed app with legacy external storage before removing 2015 Slog.v(TAG, "Package " + packageName + " does not have legacy storage"); 2016 mUidsWithLegacyExternalStorage.remove(uid); 2017 } 2018 } 2019 } 2020 snapshotAndMonitorLegacyStorageAppOp(UserHandle user)2021 private void snapshotAndMonitorLegacyStorageAppOp(UserHandle user) { 2022 int userId = user.getIdentifier(); 2023 2024 // TODO(b/149391976): Use mIAppOpsService.getPackagesForOps instead of iterating below 2025 // It should improve performance but the AppOps method doesn't return any app here :( 2026 // This operation currently takes about ~20ms on a freshly flashed device 2027 for (ApplicationInfo ai : mPmInternal.getInstalledApplications(MATCH_DIRECT_BOOT_AWARE 2028 | MATCH_DIRECT_BOOT_UNAWARE | MATCH_UNINSTALLED_PACKAGES | MATCH_ANY_USER, 2029 userId, Process.myUid())) { 2030 try { 2031 boolean hasLegacy = mIAppOpsService.checkOperation(OP_LEGACY_STORAGE, ai.uid, 2032 ai.packageName) == MODE_ALLOWED; 2033 updateLegacyStorageApps(ai.packageName, ai.uid, hasLegacy); 2034 } catch (RemoteException e) { 2035 Slog.e(TAG, "Failed to check legacy op for package " + ai.packageName, e); 2036 } 2037 } 2038 2039 PackageMonitor monitor = new PackageMonitor() { 2040 @Override 2041 public void onPackageRemoved(String packageName, int uid) { 2042 updateLegacyStorageApps(packageName, uid, false); 2043 } 2044 }; 2045 // TODO(b/149391976): Use different handler? 2046 monitor.register(mContext, user, true, mHandler); 2047 mPackageMonitorsForUser.put(userId, monitor); 2048 } 2049 getLastAccessTime(AppOpsManager manager, int uid, String packageName, int[] ops)2050 private static long getLastAccessTime(AppOpsManager manager, 2051 int uid, String packageName, int[] ops) { 2052 long maxTime = 0; 2053 final List<AppOpsManager.PackageOps> pkgs = manager.getOpsForPackage(uid, packageName, ops); 2054 for (AppOpsManager.PackageOps pkg : CollectionUtils.emptyIfNull(pkgs)) { 2055 for (AppOpsManager.OpEntry op : CollectionUtils.emptyIfNull(pkg.getOps())) { 2056 maxTime = Math.max(maxTime, op.getLastAccessTime( 2057 AppOpsManager.OP_FLAGS_ALL_TRUSTED)); 2058 } 2059 } 2060 return maxTime; 2061 } 2062 systemReady()2063 private void systemReady() { 2064 LocalServices.getService(ActivityTaskManagerInternal.class) 2065 .registerScreenObserver(this); 2066 2067 mHandler.obtainMessage(H_SYSTEM_READY).sendToTarget(); 2068 } 2069 bootCompleted()2070 private void bootCompleted() { 2071 mBootCompleted = true; 2072 mHandler.obtainMessage(H_BOOT_COMPLETED).sendToTarget(); 2073 updateFusePropFromSettings(); 2074 } 2075 handleBootCompleted()2076 private void handleBootCompleted() { 2077 initIfBootedAndConnected(); 2078 resetIfBootedAndConnected(); 2079 } 2080 getDefaultPrimaryStorageUuid()2081 private String getDefaultPrimaryStorageUuid() { 2082 if (SystemProperties.getBoolean(StorageManager.PROP_PRIMARY_PHYSICAL, false)) { 2083 return StorageManager.UUID_PRIMARY_PHYSICAL; 2084 } else { 2085 return StorageManager.UUID_PRIVATE_INTERNAL; 2086 } 2087 } 2088 2089 @GuardedBy("mLock") readSettingsLocked()2090 private void readSettingsLocked() { 2091 mRecords.clear(); 2092 mPrimaryStorageUuid = getDefaultPrimaryStorageUuid(); 2093 2094 FileInputStream fis = null; 2095 try { 2096 fis = mSettingsFile.openRead(); 2097 final XmlPullParser in = Xml.newPullParser(); 2098 in.setInput(fis, StandardCharsets.UTF_8.name()); 2099 2100 int type; 2101 while ((type = in.next()) != END_DOCUMENT) { 2102 if (type == START_TAG) { 2103 final String tag = in.getName(); 2104 if (TAG_VOLUMES.equals(tag)) { 2105 final int version = readIntAttribute(in, ATTR_VERSION, VERSION_INIT); 2106 final boolean primaryPhysical = SystemProperties.getBoolean( 2107 StorageManager.PROP_PRIMARY_PHYSICAL, false); 2108 final boolean validAttr = (version >= VERSION_FIX_PRIMARY) 2109 || (version >= VERSION_ADD_PRIMARY && !primaryPhysical); 2110 if (validAttr) { 2111 mPrimaryStorageUuid = readStringAttribute(in, 2112 ATTR_PRIMARY_STORAGE_UUID); 2113 } 2114 } else if (TAG_VOLUME.equals(tag)) { 2115 final VolumeRecord rec = readVolumeRecord(in); 2116 mRecords.put(rec.fsUuid, rec); 2117 } 2118 } 2119 } 2120 } catch (FileNotFoundException e) { 2121 // Missing metadata is okay, probably first boot 2122 } catch (IOException e) { 2123 Slog.wtf(TAG, "Failed reading metadata", e); 2124 } catch (XmlPullParserException e) { 2125 Slog.wtf(TAG, "Failed reading metadata", e); 2126 } finally { 2127 IoUtils.closeQuietly(fis); 2128 } 2129 } 2130 2131 @GuardedBy("mLock") writeSettingsLocked()2132 private void writeSettingsLocked() { 2133 FileOutputStream fos = null; 2134 try { 2135 fos = mSettingsFile.startWrite(); 2136 2137 XmlSerializer out = new FastXmlSerializer(); 2138 out.setOutput(fos, StandardCharsets.UTF_8.name()); 2139 out.startDocument(null, true); 2140 out.startTag(null, TAG_VOLUMES); 2141 writeIntAttribute(out, ATTR_VERSION, VERSION_FIX_PRIMARY); 2142 writeStringAttribute(out, ATTR_PRIMARY_STORAGE_UUID, mPrimaryStorageUuid); 2143 final int size = mRecords.size(); 2144 for (int i = 0; i < size; i++) { 2145 final VolumeRecord rec = mRecords.valueAt(i); 2146 writeVolumeRecord(out, rec); 2147 } 2148 out.endTag(null, TAG_VOLUMES); 2149 out.endDocument(); 2150 2151 mSettingsFile.finishWrite(fos); 2152 } catch (IOException e) { 2153 if (fos != null) { 2154 mSettingsFile.failWrite(fos); 2155 } 2156 } 2157 } 2158 readVolumeRecord(XmlPullParser in)2159 public static VolumeRecord readVolumeRecord(XmlPullParser in) throws IOException { 2160 final int type = readIntAttribute(in, ATTR_TYPE); 2161 final String fsUuid = readStringAttribute(in, ATTR_FS_UUID); 2162 final VolumeRecord meta = new VolumeRecord(type, fsUuid); 2163 meta.partGuid = readStringAttribute(in, ATTR_PART_GUID); 2164 meta.nickname = readStringAttribute(in, ATTR_NICKNAME); 2165 meta.userFlags = readIntAttribute(in, ATTR_USER_FLAGS); 2166 meta.createdMillis = readLongAttribute(in, ATTR_CREATED_MILLIS, 0); 2167 meta.lastSeenMillis = readLongAttribute(in, ATTR_LAST_SEEN_MILLIS, 0); 2168 meta.lastTrimMillis = readLongAttribute(in, ATTR_LAST_TRIM_MILLIS, 0); 2169 meta.lastBenchMillis = readLongAttribute(in, ATTR_LAST_BENCH_MILLIS, 0); 2170 return meta; 2171 } 2172 writeVolumeRecord(XmlSerializer out, VolumeRecord rec)2173 public static void writeVolumeRecord(XmlSerializer out, VolumeRecord rec) throws IOException { 2174 out.startTag(null, TAG_VOLUME); 2175 writeIntAttribute(out, ATTR_TYPE, rec.type); 2176 writeStringAttribute(out, ATTR_FS_UUID, rec.fsUuid); 2177 writeStringAttribute(out, ATTR_PART_GUID, rec.partGuid); 2178 writeStringAttribute(out, ATTR_NICKNAME, rec.nickname); 2179 writeIntAttribute(out, ATTR_USER_FLAGS, rec.userFlags); 2180 writeLongAttribute(out, ATTR_CREATED_MILLIS, rec.createdMillis); 2181 writeLongAttribute(out, ATTR_LAST_SEEN_MILLIS, rec.lastSeenMillis); 2182 writeLongAttribute(out, ATTR_LAST_TRIM_MILLIS, rec.lastTrimMillis); 2183 writeLongAttribute(out, ATTR_LAST_BENCH_MILLIS, rec.lastBenchMillis); 2184 out.endTag(null, TAG_VOLUME); 2185 } 2186 2187 /** 2188 * Exposed API calls below here 2189 */ 2190 2191 @Override registerListener(IStorageEventListener listener)2192 public void registerListener(IStorageEventListener listener) { 2193 mCallbacks.register(listener); 2194 } 2195 2196 @Override unregisterListener(IStorageEventListener listener)2197 public void unregisterListener(IStorageEventListener listener) { 2198 mCallbacks.unregister(listener); 2199 } 2200 2201 @Override shutdown(final IStorageShutdownObserver observer)2202 public void shutdown(final IStorageShutdownObserver observer) { 2203 enforcePermission(android.Manifest.permission.SHUTDOWN); 2204 2205 Slog.i(TAG, "Shutting down"); 2206 mHandler.obtainMessage(H_SHUTDOWN, observer).sendToTarget(); 2207 } 2208 2209 @Override mount(String volId)2210 public void mount(String volId) { 2211 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS); 2212 2213 final VolumeInfo vol = findVolumeByIdOrThrow(volId); 2214 if (isMountDisallowed(vol)) { 2215 throw new SecurityException("Mounting " + volId + " restricted by policy"); 2216 } 2217 2218 mount(vol); 2219 } 2220 remountAppStorageDirs(Map<Integer, String> pidPkgMap, int userId)2221 private void remountAppStorageDirs(Map<Integer, String> pidPkgMap, int userId) { 2222 for (Entry<Integer, String> entry : pidPkgMap.entrySet()) { 2223 final int pid = entry.getKey(); 2224 final String packageName = entry.getValue(); 2225 Slog.i(TAG, "Remounting storage for pid: " + pid); 2226 final String[] sharedPackages = 2227 mPmInternal.getSharedUserPackagesForPackage(packageName, userId); 2228 final int uid = mPmInternal.getPackageUidInternal(packageName, 0, userId); 2229 final String[] packages = 2230 sharedPackages.length != 0 ? sharedPackages : new String[]{packageName}; 2231 try { 2232 mVold.remountAppStorageDirs(uid, pid, packages); 2233 } catch (RemoteException e) { 2234 throw e.rethrowAsRuntimeException(); 2235 } 2236 } 2237 } 2238 mount(VolumeInfo vol)2239 private void mount(VolumeInfo vol) { 2240 try { 2241 // TODO(b/135341433): Remove paranoid logging when FUSE is stable 2242 Slog.i(TAG, "Mounting volume " + vol); 2243 mVold.mount(vol.id, vol.mountFlags, vol.mountUserId, new IVoldMountCallback.Stub() { 2244 @Override 2245 public boolean onVolumeChecking(FileDescriptor fd, String path, 2246 String internalPath) { 2247 vol.path = path; 2248 vol.internalPath = internalPath; 2249 ParcelFileDescriptor pfd = new ParcelFileDescriptor(fd); 2250 try { 2251 mStorageSessionController.onVolumeMount(pfd, vol); 2252 return true; 2253 } catch (ExternalStorageServiceException e) { 2254 Slog.e(TAG, "Failed to mount volume " + vol, e); 2255 2256 int nextResetSeconds = FAILED_MOUNT_RESET_TIMEOUT_SECONDS; 2257 Slog.i(TAG, "Scheduling reset in " + nextResetSeconds + "s"); 2258 mHandler.removeMessages(H_RESET); 2259 mHandler.sendMessageDelayed(mHandler.obtainMessage(H_RESET), 2260 TimeUnit.SECONDS.toMillis(nextResetSeconds)); 2261 return false; 2262 } finally { 2263 try { 2264 pfd.close(); 2265 } catch (Exception e) { 2266 Slog.e(TAG, "Failed to close FUSE device fd", e); 2267 } 2268 } 2269 } 2270 }); 2271 Slog.i(TAG, "Mounted volume " + vol); 2272 } catch (Exception e) { 2273 Slog.wtf(TAG, e); 2274 } 2275 } 2276 2277 @Override unmount(String volId)2278 public void unmount(String volId) { 2279 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS); 2280 2281 final VolumeInfo vol = findVolumeByIdOrThrow(volId); 2282 unmount(vol); 2283 } 2284 unmount(VolumeInfo vol)2285 private void unmount(VolumeInfo vol) { 2286 try { 2287 try { 2288 if (vol.type == VolumeInfo.TYPE_PRIVATE) { 2289 mInstaller.onPrivateVolumeRemoved(vol.getFsUuid()); 2290 } 2291 } catch (Installer.InstallerException e) { 2292 Slog.e(TAG, "Failed unmount mirror data", e); 2293 } 2294 mVold.unmount(vol.id); 2295 mStorageSessionController.onVolumeUnmount(vol); 2296 } catch (Exception e) { 2297 Slog.wtf(TAG, e); 2298 } 2299 } 2300 2301 @Override format(String volId)2302 public void format(String volId) { 2303 enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS); 2304 2305 final VolumeInfo vol = findVolumeByIdOrThrow(volId); 2306 final String fsUuid = vol.fsUuid; 2307 try { 2308 mVold.format(vol.id, "auto"); 2309 2310 // After a successful format above, we should forget about any 2311 // records for the old partition, since it'll never appear again 2312 if (!TextUtils.isEmpty(fsUuid)) { 2313 forgetVolume(fsUuid); 2314 } 2315 } catch (Exception e) { 2316 Slog.wtf(TAG, e); 2317 } 2318 } 2319 2320 @Override benchmark(String volId, IVoldTaskListener listener)2321 public void benchmark(String volId, IVoldTaskListener listener) { 2322 enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS); 2323 2324 try { 2325 mVold.benchmark(volId, new IVoldTaskListener.Stub() { 2326 @Override 2327 public void onStatus(int status, PersistableBundle extras) { 2328 dispatchOnStatus(listener, status, extras); 2329 } 2330 2331 @Override 2332 public void onFinished(int status, PersistableBundle extras) { 2333 dispatchOnFinished(listener, status, extras); 2334 2335 final String path = extras.getString("path"); 2336 final String ident = extras.getString("ident"); 2337 final long create = extras.getLong("create"); 2338 final long run = extras.getLong("run"); 2339 final long destroy = extras.getLong("destroy"); 2340 2341 final DropBoxManager dropBox = mContext.getSystemService(DropBoxManager.class); 2342 dropBox.addText(TAG_STORAGE_BENCHMARK, scrubPath(path) 2343 + " " + ident + " " + create + " " + run + " " + destroy); 2344 2345 synchronized (mLock) { 2346 final VolumeRecord rec = findRecordForPath(path); 2347 if (rec != null) { 2348 rec.lastBenchMillis = System.currentTimeMillis(); 2349 writeSettingsLocked(); 2350 } 2351 } 2352 } 2353 }); 2354 } catch (RemoteException e) { 2355 throw e.rethrowAsRuntimeException(); 2356 } 2357 } 2358 2359 @Override partitionPublic(String diskId)2360 public void partitionPublic(String diskId) { 2361 enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS); 2362 2363 final CountDownLatch latch = findOrCreateDiskScanLatch(diskId); 2364 try { 2365 mVold.partition(diskId, IVold.PARTITION_TYPE_PUBLIC, -1); 2366 waitForLatch(latch, "partitionPublic", 3 * DateUtils.MINUTE_IN_MILLIS); 2367 } catch (Exception e) { 2368 Slog.wtf(TAG, e); 2369 } 2370 } 2371 2372 @Override partitionPrivate(String diskId)2373 public void partitionPrivate(String diskId) { 2374 enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS); 2375 enforceAdminUser(); 2376 2377 final CountDownLatch latch = findOrCreateDiskScanLatch(diskId); 2378 try { 2379 mVold.partition(diskId, IVold.PARTITION_TYPE_PRIVATE, -1); 2380 waitForLatch(latch, "partitionPrivate", 3 * DateUtils.MINUTE_IN_MILLIS); 2381 } catch (Exception e) { 2382 Slog.wtf(TAG, e); 2383 } 2384 } 2385 2386 @Override partitionMixed(String diskId, int ratio)2387 public void partitionMixed(String diskId, int ratio) { 2388 enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS); 2389 enforceAdminUser(); 2390 2391 final CountDownLatch latch = findOrCreateDiskScanLatch(diskId); 2392 try { 2393 mVold.partition(diskId, IVold.PARTITION_TYPE_MIXED, ratio); 2394 waitForLatch(latch, "partitionMixed", 3 * DateUtils.MINUTE_IN_MILLIS); 2395 } catch (Exception e) { 2396 Slog.wtf(TAG, e); 2397 } 2398 } 2399 2400 @Override setVolumeNickname(String fsUuid, String nickname)2401 public void setVolumeNickname(String fsUuid, String nickname) { 2402 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS); 2403 2404 Objects.requireNonNull(fsUuid); 2405 synchronized (mLock) { 2406 final VolumeRecord rec = mRecords.get(fsUuid); 2407 rec.nickname = nickname; 2408 mCallbacks.notifyVolumeRecordChanged(rec); 2409 writeSettingsLocked(); 2410 } 2411 } 2412 2413 @Override setVolumeUserFlags(String fsUuid, int flags, int mask)2414 public void setVolumeUserFlags(String fsUuid, int flags, int mask) { 2415 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS); 2416 2417 Objects.requireNonNull(fsUuid); 2418 synchronized (mLock) { 2419 final VolumeRecord rec = mRecords.get(fsUuid); 2420 rec.userFlags = (rec.userFlags & ~mask) | (flags & mask); 2421 mCallbacks.notifyVolumeRecordChanged(rec); 2422 writeSettingsLocked(); 2423 } 2424 } 2425 2426 @Override forgetVolume(String fsUuid)2427 public void forgetVolume(String fsUuid) { 2428 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS); 2429 2430 Objects.requireNonNull(fsUuid); 2431 2432 synchronized (mLock) { 2433 final VolumeRecord rec = mRecords.remove(fsUuid); 2434 if (rec != null && !TextUtils.isEmpty(rec.partGuid)) { 2435 mHandler.obtainMessage(H_PARTITION_FORGET, rec).sendToTarget(); 2436 } 2437 mCallbacks.notifyVolumeForgotten(fsUuid); 2438 2439 // If this had been primary storage, revert back to internal and 2440 // reset vold so we bind into new volume into place. 2441 if (Objects.equals(mPrimaryStorageUuid, fsUuid)) { 2442 mPrimaryStorageUuid = getDefaultPrimaryStorageUuid(); 2443 mHandler.obtainMessage(H_RESET).sendToTarget(); 2444 } 2445 2446 writeSettingsLocked(); 2447 } 2448 } 2449 2450 @Override forgetAllVolumes()2451 public void forgetAllVolumes() { 2452 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS); 2453 2454 synchronized (mLock) { 2455 for (int i = 0; i < mRecords.size(); i++) { 2456 final String fsUuid = mRecords.keyAt(i); 2457 final VolumeRecord rec = mRecords.valueAt(i); 2458 if (!TextUtils.isEmpty(rec.partGuid)) { 2459 mHandler.obtainMessage(H_PARTITION_FORGET, rec).sendToTarget(); 2460 } 2461 mCallbacks.notifyVolumeForgotten(fsUuid); 2462 } 2463 mRecords.clear(); 2464 2465 if (!Objects.equals(StorageManager.UUID_PRIVATE_INTERNAL, mPrimaryStorageUuid)) { 2466 mPrimaryStorageUuid = getDefaultPrimaryStorageUuid(); 2467 } 2468 2469 writeSettingsLocked(); 2470 mHandler.obtainMessage(H_RESET).sendToTarget(); 2471 } 2472 } 2473 forgetPartition(String partGuid, String fsUuid)2474 private void forgetPartition(String partGuid, String fsUuid) { 2475 try { 2476 mVold.forgetPartition(partGuid, fsUuid); 2477 } catch (Exception e) { 2478 Slog.wtf(TAG, e); 2479 } 2480 } 2481 2482 @Override fstrim(int flags, IVoldTaskListener listener)2483 public void fstrim(int flags, IVoldTaskListener listener) { 2484 enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS); 2485 2486 try { 2487 // Block based checkpoint process runs fstrim. So, if checkpoint is in progress 2488 // (first boot after OTA), We skip idle maintenance and make sure the last 2489 // fstrim time is still updated. If file based checkpoints are used, we run 2490 // idle maintenance (GC + fstrim) regardless of checkpoint status. 2491 if (!needsCheckpoint() || !supportsBlockCheckpoint()) { 2492 mVold.fstrim(flags, new IVoldTaskListener.Stub() { 2493 @Override 2494 public void onStatus(int status, PersistableBundle extras) { 2495 dispatchOnStatus(listener, status, extras); 2496 2497 // Ignore trim failures 2498 if (status != 0) return; 2499 2500 final String path = extras.getString("path"); 2501 final long bytes = extras.getLong("bytes"); 2502 final long time = extras.getLong("time"); 2503 2504 final DropBoxManager dropBox = mContext.getSystemService(DropBoxManager.class); 2505 dropBox.addText(TAG_STORAGE_TRIM, scrubPath(path) + " " + bytes + " " + time); 2506 2507 synchronized (mLock) { 2508 final VolumeRecord rec = findRecordForPath(path); 2509 if (rec != null) { 2510 rec.lastTrimMillis = System.currentTimeMillis(); 2511 writeSettingsLocked(); 2512 } 2513 } 2514 } 2515 2516 @Override 2517 public void onFinished(int status, PersistableBundle extras) { 2518 dispatchOnFinished(listener, status, extras); 2519 2520 // TODO: benchmark when desired 2521 } 2522 }); 2523 } else { 2524 Slog.i(TAG, "Skipping fstrim - block based checkpoint in progress"); 2525 } 2526 } catch (RemoteException e) { 2527 throw e.rethrowAsRuntimeException(); 2528 } 2529 } 2530 runIdleMaint(Runnable callback)2531 void runIdleMaint(Runnable callback) { 2532 enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS); 2533 2534 try { 2535 // Block based checkpoint process runs fstrim. So, if checkpoint is in progress 2536 // (first boot after OTA), We skip idle maintenance and make sure the last 2537 // fstrim time is still updated. If file based checkpoints are used, we run 2538 // idle maintenance (GC + fstrim) regardless of checkpoint status. 2539 if (!needsCheckpoint() || !supportsBlockCheckpoint()) { 2540 mVold.runIdleMaint(new IVoldTaskListener.Stub() { 2541 @Override 2542 public void onStatus(int status, PersistableBundle extras) { 2543 // Not currently used 2544 } 2545 @Override 2546 public void onFinished(int status, PersistableBundle extras) { 2547 if (callback != null) { 2548 BackgroundThread.getHandler().post(callback); 2549 } 2550 } 2551 }); 2552 } else { 2553 Slog.i(TAG, "Skipping idle maintenance - block based checkpoint in progress"); 2554 } 2555 } catch (Exception e) { 2556 Slog.wtf(TAG, e); 2557 } 2558 } 2559 2560 @Override runIdleMaintenance()2561 public void runIdleMaintenance() { 2562 runIdleMaint(null); 2563 } 2564 abortIdleMaint(Runnable callback)2565 void abortIdleMaint(Runnable callback) { 2566 enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS); 2567 2568 try { 2569 mVold.abortIdleMaint(new IVoldTaskListener.Stub() { 2570 @Override 2571 public void onStatus(int status, PersistableBundle extras) { 2572 // Not currently used 2573 } 2574 @Override 2575 public void onFinished(int status, PersistableBundle extras) { 2576 if (callback != null) { 2577 BackgroundThread.getHandler().post(callback); 2578 } 2579 } 2580 }); 2581 } catch (Exception e) { 2582 Slog.wtf(TAG, e); 2583 } 2584 } 2585 2586 @Override abortIdleMaintenance()2587 public void abortIdleMaintenance() { 2588 abortIdleMaint(null); 2589 } 2590 remountUidExternalStorage(int uid, int mode)2591 private void remountUidExternalStorage(int uid, int mode) { 2592 if (uid == Process.SYSTEM_UID) { 2593 // No need to remount uid for system because it has all access anyways 2594 return; 2595 } 2596 2597 try { 2598 mVold.remountUid(uid, mode); 2599 } catch (Exception e) { 2600 Slog.wtf(TAG, e); 2601 } 2602 } 2603 2604 @Override setDebugFlags(int flags, int mask)2605 public void setDebugFlags(int flags, int mask) { 2606 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS); 2607 2608 if ((mask & StorageManager.DEBUG_EMULATE_FBE) != 0) { 2609 if (!EMULATE_FBE_SUPPORTED) { 2610 throw new IllegalStateException( 2611 "Emulation not supported on this device"); 2612 } 2613 if (StorageManager.isFileEncryptedNativeOnly()) { 2614 throw new IllegalStateException( 2615 "Emulation not supported on device with native FBE"); 2616 } 2617 if (mLockPatternUtils.isCredentialRequiredToDecrypt(false)) { 2618 throw new IllegalStateException( 2619 "Emulation requires disabling 'Secure start-up' in Settings > Security"); 2620 } 2621 2622 final long token = Binder.clearCallingIdentity(); 2623 try { 2624 final boolean emulateFbe = (flags & StorageManager.DEBUG_EMULATE_FBE) != 0; 2625 SystemProperties.set(StorageManager.PROP_EMULATE_FBE, Boolean.toString(emulateFbe)); 2626 2627 // Perform hard reboot to kick policy into place 2628 mContext.getSystemService(PowerManager.class).reboot(null); 2629 } finally { 2630 Binder.restoreCallingIdentity(token); 2631 } 2632 } 2633 2634 if ((mask & (StorageManager.DEBUG_ADOPTABLE_FORCE_ON 2635 | StorageManager.DEBUG_ADOPTABLE_FORCE_OFF)) != 0) { 2636 final String value; 2637 if ((flags & StorageManager.DEBUG_ADOPTABLE_FORCE_ON) != 0) { 2638 value = "force_on"; 2639 } else if ((flags & StorageManager.DEBUG_ADOPTABLE_FORCE_OFF) != 0) { 2640 value = "force_off"; 2641 } else { 2642 value = ""; 2643 } 2644 2645 final long token = Binder.clearCallingIdentity(); 2646 try { 2647 SystemProperties.set(StorageManager.PROP_ADOPTABLE, value); 2648 2649 // Reset storage to kick new setting into place 2650 mHandler.obtainMessage(H_RESET).sendToTarget(); 2651 } finally { 2652 Binder.restoreCallingIdentity(token); 2653 } 2654 } 2655 2656 if ((mask & (StorageManager.DEBUG_SDCARDFS_FORCE_ON 2657 | StorageManager.DEBUG_SDCARDFS_FORCE_OFF)) != 0) { 2658 final String value; 2659 if ((flags & StorageManager.DEBUG_SDCARDFS_FORCE_ON) != 0) { 2660 value = "force_on"; 2661 } else if ((flags & StorageManager.DEBUG_SDCARDFS_FORCE_OFF) != 0) { 2662 value = "force_off"; 2663 } else { 2664 value = ""; 2665 } 2666 2667 final long token = Binder.clearCallingIdentity(); 2668 try { 2669 SystemProperties.set(StorageManager.PROP_SDCARDFS, value); 2670 2671 // Reset storage to kick new setting into place 2672 mHandler.obtainMessage(H_RESET).sendToTarget(); 2673 } finally { 2674 Binder.restoreCallingIdentity(token); 2675 } 2676 } 2677 2678 if ((mask & StorageManager.DEBUG_VIRTUAL_DISK) != 0) { 2679 final boolean enabled = (flags & StorageManager.DEBUG_VIRTUAL_DISK) != 0; 2680 2681 final long token = Binder.clearCallingIdentity(); 2682 try { 2683 SystemProperties.set(StorageManager.PROP_VIRTUAL_DISK, Boolean.toString(enabled)); 2684 2685 // Reset storage to kick new setting into place 2686 mHandler.obtainMessage(H_RESET).sendToTarget(); 2687 } finally { 2688 Binder.restoreCallingIdentity(token); 2689 } 2690 } 2691 2692 if ((mask & (StorageManager.DEBUG_ISOLATED_STORAGE_FORCE_ON 2693 | StorageManager.DEBUG_ISOLATED_STORAGE_FORCE_OFF)) != 0) { 2694 final int value; 2695 if ((flags & StorageManager.DEBUG_ISOLATED_STORAGE_FORCE_ON) != 0) { 2696 value = 1; 2697 } else if ((flags & StorageManager.DEBUG_ISOLATED_STORAGE_FORCE_OFF) != 0) { 2698 value = -1; 2699 } else { 2700 value = 0; 2701 } 2702 2703 final long token = Binder.clearCallingIdentity(); 2704 try { 2705 Settings.Global.putInt(mContext.getContentResolver(), 2706 Settings.Global.ISOLATED_STORAGE_LOCAL, value); 2707 refreshIsolatedStorageSettings(); 2708 2709 // Perform hard reboot to kick policy into place 2710 mHandler.post(() -> { 2711 mContext.getSystemService(PowerManager.class).reboot(null); 2712 }); 2713 } finally { 2714 Binder.restoreCallingIdentity(token); 2715 } 2716 } 2717 } 2718 2719 @Override getPrimaryStorageUuid()2720 public String getPrimaryStorageUuid() { 2721 synchronized (mLock) { 2722 return mPrimaryStorageUuid; 2723 } 2724 } 2725 2726 @Override setPrimaryStorageUuid(String volumeUuid, IPackageMoveObserver callback)2727 public void setPrimaryStorageUuid(String volumeUuid, IPackageMoveObserver callback) { 2728 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS); 2729 2730 final VolumeInfo from; 2731 final VolumeInfo to; 2732 2733 synchronized (mLock) { 2734 if (Objects.equals(mPrimaryStorageUuid, volumeUuid)) { 2735 throw new IllegalArgumentException("Primary storage already at " + volumeUuid); 2736 } 2737 2738 if (mMoveCallback != null) { 2739 throw new IllegalStateException("Move already in progress"); 2740 } 2741 mMoveCallback = callback; 2742 mMoveTargetUuid = volumeUuid; 2743 2744 // We need all the users unlocked to move their primary storage 2745 final List<UserInfo> users = mContext.getSystemService(UserManager.class).getUsers(); 2746 for (UserInfo user : users) { 2747 if (StorageManager.isFileEncryptedNativeOrEmulated() 2748 && !isUserKeyUnlocked(user.id)) { 2749 Slog.w(TAG, "Failing move due to locked user " + user.id); 2750 onMoveStatusLocked(PackageManager.MOVE_FAILED_LOCKED_USER); 2751 return; 2752 } 2753 } 2754 2755 // When moving to/from primary physical volume, we probably just nuked 2756 // the current storage location, so we have nothing to move. 2757 if (Objects.equals(StorageManager.UUID_PRIMARY_PHYSICAL, mPrimaryStorageUuid) 2758 || Objects.equals(StorageManager.UUID_PRIMARY_PHYSICAL, volumeUuid)) { 2759 Slog.d(TAG, "Skipping move to/from primary physical"); 2760 onMoveStatusLocked(MOVE_STATUS_COPY_FINISHED); 2761 onMoveStatusLocked(PackageManager.MOVE_SUCCEEDED); 2762 mHandler.obtainMessage(H_RESET).sendToTarget(); 2763 return; 2764 2765 } else { 2766 from = findStorageForUuid(mPrimaryStorageUuid); 2767 to = findStorageForUuid(volumeUuid); 2768 2769 if (from == null) { 2770 Slog.w(TAG, "Failing move due to missing from volume " + mPrimaryStorageUuid); 2771 onMoveStatusLocked(PackageManager.MOVE_FAILED_INTERNAL_ERROR); 2772 return; 2773 } else if (to == null) { 2774 Slog.w(TAG, "Failing move due to missing to volume " + volumeUuid); 2775 onMoveStatusLocked(PackageManager.MOVE_FAILED_INTERNAL_ERROR); 2776 return; 2777 } 2778 } 2779 } 2780 2781 try { 2782 mVold.moveStorage(from.id, to.id, new IVoldTaskListener.Stub() { 2783 @Override 2784 public void onStatus(int status, PersistableBundle extras) { 2785 synchronized (mLock) { 2786 onMoveStatusLocked(status); 2787 } 2788 } 2789 2790 @Override 2791 public void onFinished(int status, PersistableBundle extras) { 2792 // Not currently used 2793 } 2794 }); 2795 } catch (Exception e) { 2796 Slog.wtf(TAG, e); 2797 } 2798 } 2799 warnOnNotMounted()2800 private void warnOnNotMounted() { 2801 synchronized (mLock) { 2802 for (int i = 0; i < mVolumes.size(); i++) { 2803 final VolumeInfo vol = mVolumes.valueAt(i); 2804 if (vol.isPrimary() && vol.isMountedWritable()) { 2805 // Cool beans, we have a mounted primary volume 2806 return; 2807 } 2808 } 2809 } 2810 2811 Slog.w(TAG, "No primary storage mounted!"); 2812 } 2813 isUidOwnerOfPackageOrSystem(String packageName, int callerUid)2814 private boolean isUidOwnerOfPackageOrSystem(String packageName, int callerUid) { 2815 if (callerUid == android.os.Process.SYSTEM_UID) { 2816 return true; 2817 } 2818 2819 if (packageName == null) { 2820 return false; 2821 } 2822 2823 final int packageUid = mPmInternal.getPackageUid(packageName, 2824 PackageManager.MATCH_DEBUG_TRIAGED_MISSING, UserHandle.getUserId(callerUid)); 2825 2826 if (DEBUG_OBB) { 2827 Slog.d(TAG, "packageName = " + packageName + ", packageUid = " + 2828 packageUid + ", callerUid = " + callerUid); 2829 } 2830 2831 return callerUid == packageUid; 2832 } 2833 2834 @Override getMountedObbPath(String rawPath)2835 public String getMountedObbPath(String rawPath) { 2836 Objects.requireNonNull(rawPath, "rawPath cannot be null"); 2837 2838 warnOnNotMounted(); 2839 2840 final ObbState state; 2841 synchronized (mObbMounts) { 2842 state = mObbPathToStateMap.get(rawPath); 2843 } 2844 if (state == null) { 2845 Slog.w(TAG, "Failed to find OBB mounted at " + rawPath); 2846 return null; 2847 } 2848 2849 return findVolumeByIdOrThrow(state.volId).getPath().getAbsolutePath(); 2850 } 2851 2852 @Override isObbMounted(String rawPath)2853 public boolean isObbMounted(String rawPath) { 2854 Objects.requireNonNull(rawPath, "rawPath cannot be null"); 2855 synchronized (mObbMounts) { 2856 return mObbPathToStateMap.containsKey(rawPath); 2857 } 2858 } 2859 2860 @Override mountObb(String rawPath, String canonicalPath, String key, IObbActionListener token, int nonce, ObbInfo obbInfo)2861 public void mountObb(String rawPath, String canonicalPath, String key, 2862 IObbActionListener token, int nonce, ObbInfo obbInfo) { 2863 Objects.requireNonNull(rawPath, "rawPath cannot be null"); 2864 Objects.requireNonNull(canonicalPath, "canonicalPath cannot be null"); 2865 Objects.requireNonNull(token, "token cannot be null"); 2866 Objects.requireNonNull(obbInfo, "obbIfno cannot be null"); 2867 2868 final int callingUid = Binder.getCallingUid(); 2869 final ObbState obbState = new ObbState(rawPath, canonicalPath, 2870 callingUid, token, nonce, null); 2871 final ObbAction action = new MountObbAction(obbState, key, callingUid, obbInfo); 2872 mObbActionHandler.sendMessage(mObbActionHandler.obtainMessage(OBB_RUN_ACTION, action)); 2873 2874 if (DEBUG_OBB) 2875 Slog.i(TAG, "Send to OBB handler: " + action.toString()); 2876 } 2877 2878 @Override unmountObb(String rawPath, boolean force, IObbActionListener token, int nonce)2879 public void unmountObb(String rawPath, boolean force, IObbActionListener token, int nonce) { 2880 Objects.requireNonNull(rawPath, "rawPath cannot be null"); 2881 2882 final ObbState existingState; 2883 synchronized (mObbMounts) { 2884 existingState = mObbPathToStateMap.get(rawPath); 2885 } 2886 2887 if (existingState != null) { 2888 // TODO: separate state object from request data 2889 final int callingUid = Binder.getCallingUid(); 2890 final ObbState newState = new ObbState(rawPath, existingState.canonicalPath, 2891 callingUid, token, nonce, existingState.volId); 2892 final ObbAction action = new UnmountObbAction(newState, force); 2893 mObbActionHandler.sendMessage(mObbActionHandler.obtainMessage(OBB_RUN_ACTION, action)); 2894 2895 if (DEBUG_OBB) 2896 Slog.i(TAG, "Send to OBB handler: " + action.toString()); 2897 } else { 2898 Slog.w(TAG, "Unknown OBB mount at " + rawPath); 2899 } 2900 } 2901 2902 @Override getEncryptionState()2903 public int getEncryptionState() { 2904 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER, 2905 "no permission to access the crypt keeper"); 2906 2907 try { 2908 return mVold.fdeComplete(); 2909 } catch (Exception e) { 2910 Slog.wtf(TAG, e); 2911 return StorageManager.ENCRYPTION_STATE_ERROR_UNKNOWN; 2912 } 2913 } 2914 2915 @Override decryptStorage(String password)2916 public int decryptStorage(String password) { 2917 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER, 2918 "no permission to access the crypt keeper"); 2919 2920 if (TextUtils.isEmpty(password)) { 2921 throw new IllegalArgumentException("password cannot be empty"); 2922 } 2923 2924 if (DEBUG_EVENTS) { 2925 Slog.i(TAG, "decrypting storage..."); 2926 } 2927 2928 try { 2929 mVold.fdeCheckPassword(password); 2930 mHandler.postDelayed(() -> { 2931 try { 2932 mVold.fdeRestart(); 2933 } catch (Exception e) { 2934 Slog.wtf(TAG, e); 2935 } 2936 }, DateUtils.SECOND_IN_MILLIS); 2937 return 0; 2938 } catch (ServiceSpecificException e) { 2939 Slog.e(TAG, "fdeCheckPassword failed", e); 2940 return e.errorCode; 2941 } catch (Exception e) { 2942 Slog.wtf(TAG, e); 2943 return StorageManager.ENCRYPTION_STATE_ERROR_UNKNOWN; 2944 } 2945 } 2946 2947 @Override encryptStorage(int type, String password)2948 public int encryptStorage(int type, String password) { 2949 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER, 2950 "no permission to access the crypt keeper"); 2951 2952 if (type == StorageManager.CRYPT_TYPE_DEFAULT) { 2953 password = ""; 2954 } else if (TextUtils.isEmpty(password)) { 2955 throw new IllegalArgumentException("password cannot be empty"); 2956 } 2957 2958 if (DEBUG_EVENTS) { 2959 Slog.i(TAG, "encrypting storage..."); 2960 } 2961 2962 try { 2963 mVold.fdeEnable(type, password, 0); 2964 } catch (Exception e) { 2965 Slog.wtf(TAG, e); 2966 return -1; 2967 } 2968 2969 return 0; 2970 } 2971 2972 /** Set the password for encrypting the master key. 2973 * @param type One of the CRYPTO_TYPE_XXX consts defined in StorageManager. 2974 * @param password The password to set. 2975 */ 2976 @Override changeEncryptionPassword(int type, String password)2977 public int changeEncryptionPassword(int type, String password) { 2978 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER, 2979 "no permission to access the crypt keeper"); 2980 2981 if (StorageManager.isFileEncryptedNativeOnly()) { 2982 // Not supported on FBE devices 2983 return -1; 2984 } 2985 2986 if (type == StorageManager.CRYPT_TYPE_DEFAULT) { 2987 password = ""; 2988 } else if (TextUtils.isEmpty(password)) { 2989 throw new IllegalArgumentException("password cannot be empty"); 2990 } 2991 2992 if (DEBUG_EVENTS) { 2993 Slog.i(TAG, "changing encryption password..."); 2994 } 2995 2996 try { 2997 mVold.fdeChangePassword(type, password); 2998 return 0; 2999 } catch (Exception e) { 3000 Slog.wtf(TAG, e); 3001 return -1; 3002 } 3003 } 3004 3005 /** 3006 * Validate a user-supplied password string with cryptfs 3007 */ 3008 @Override verifyEncryptionPassword(String password)3009 public int verifyEncryptionPassword(String password) throws RemoteException { 3010 // Only the system process is permitted to validate passwords 3011 if (Binder.getCallingUid() != android.os.Process.SYSTEM_UID) { 3012 throw new SecurityException("no permission to access the crypt keeper"); 3013 } 3014 3015 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER, 3016 "no permission to access the crypt keeper"); 3017 3018 if (TextUtils.isEmpty(password)) { 3019 throw new IllegalArgumentException("password cannot be empty"); 3020 } 3021 3022 if (DEBUG_EVENTS) { 3023 Slog.i(TAG, "validating encryption password..."); 3024 } 3025 3026 try { 3027 mVold.fdeVerifyPassword(password); 3028 return 0; 3029 } catch (Exception e) { 3030 Slog.wtf(TAG, e); 3031 return -1; 3032 } 3033 } 3034 3035 /** 3036 * Get the type of encryption used to encrypt the master key. 3037 * @return The type, one of the CRYPT_TYPE_XXX consts from StorageManager. 3038 */ 3039 @Override getPasswordType()3040 public int getPasswordType() { 3041 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER, 3042 "no permission to access the crypt keeper"); 3043 3044 try { 3045 return mVold.fdeGetPasswordType(); 3046 } catch (Exception e) { 3047 Slog.wtf(TAG, e); 3048 return -1; 3049 } 3050 } 3051 3052 /** 3053 * Set a field in the crypto header. 3054 * @param field field to set 3055 * @param contents contents to set in field 3056 */ 3057 @Override setField(String field, String contents)3058 public void setField(String field, String contents) throws RemoteException { 3059 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER, 3060 "no permission to access the crypt keeper"); 3061 3062 if (!StorageManager.isBlockEncrypted()) { 3063 // Only supported on FDE devices 3064 return; 3065 } 3066 3067 try { 3068 mVold.fdeSetField(field, contents); 3069 return; 3070 } catch (Exception e) { 3071 Slog.wtf(TAG, e); 3072 return; 3073 } 3074 } 3075 3076 /** 3077 * Gets a field from the crypto header. 3078 * @param field field to get 3079 * @return contents of field 3080 */ 3081 @Override getField(String field)3082 public String getField(String field) throws RemoteException { 3083 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER, 3084 "no permission to access the crypt keeper"); 3085 3086 if (!StorageManager.isBlockEncrypted()) { 3087 // Only supported on FDE devices 3088 return null; 3089 } 3090 3091 try { 3092 return mVold.fdeGetField(field); 3093 } catch (Exception e) { 3094 Slog.wtf(TAG, e); 3095 return null; 3096 } 3097 } 3098 3099 /** 3100 * Is userdata convertible to file based encryption? 3101 * @return non zero for convertible 3102 */ 3103 @Override isConvertibleToFBE()3104 public boolean isConvertibleToFBE() throws RemoteException { 3105 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER, 3106 "no permission to access the crypt keeper"); 3107 3108 try { 3109 return mVold.isConvertibleToFbe(); 3110 } catch (Exception e) { 3111 Slog.wtf(TAG, e); 3112 return false; 3113 } 3114 } 3115 3116 /** 3117 * Check whether the device supports filesystem checkpointing. 3118 * 3119 * @return true if the device supports filesystem checkpointing, false otherwise. 3120 */ 3121 @Override supportsCheckpoint()3122 public boolean supportsCheckpoint() throws RemoteException { 3123 return mVold.supportsCheckpoint(); 3124 } 3125 3126 /** 3127 * Signal that checkpointing partitions should start a checkpoint on the next boot. 3128 * 3129 * @param numTries Number of times to try booting in checkpoint mode, before we will boot 3130 * non-checkpoint mode and commit all changes immediately. Callers are 3131 * responsible for ensuring that boot is safe (eg, by rolling back updates). 3132 */ 3133 @Override startCheckpoint(int numTries)3134 public void startCheckpoint(int numTries) throws RemoteException { 3135 // Only the root, system_server and shell processes are permitted to start checkpoints 3136 final int callingUid = Binder.getCallingUid(); 3137 if (callingUid != Process.SYSTEM_UID && callingUid != Process.ROOT_UID 3138 && callingUid != Process.SHELL_UID) { 3139 throw new SecurityException("no permission to start filesystem checkpoint"); 3140 } 3141 3142 mVold.startCheckpoint(numTries); 3143 } 3144 3145 /** 3146 * Signal that checkpointing partitions should commit changes 3147 */ 3148 @Override commitChanges()3149 public void commitChanges() throws RemoteException { 3150 // Only the system process is permitted to commit checkpoints 3151 if (Binder.getCallingUid() != android.os.Process.SYSTEM_UID) { 3152 throw new SecurityException("no permission to commit checkpoint changes"); 3153 } 3154 3155 mVold.commitChanges(); 3156 } 3157 3158 /** 3159 * Check if we should be mounting with checkpointing or are checkpointing now 3160 */ 3161 @Override needsCheckpoint()3162 public boolean needsCheckpoint() throws RemoteException { 3163 enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS); 3164 return mVold.needsCheckpoint(); 3165 } 3166 3167 /** 3168 * Abort the current set of changes and either try again, or abort entirely 3169 */ 3170 @Override abortChanges(String message, boolean retry)3171 public void abortChanges(String message, boolean retry) throws RemoteException { 3172 // Only the system process is permitted to abort checkpoints 3173 if (Binder.getCallingUid() != android.os.Process.SYSTEM_UID) { 3174 throw new SecurityException("no permission to commit checkpoint changes"); 3175 } 3176 3177 mVold.abortChanges(message, retry); 3178 } 3179 3180 @Override getPassword()3181 public String getPassword() throws RemoteException { 3182 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER, 3183 "only keyguard can retrieve password"); 3184 3185 try { 3186 return mVold.fdeGetPassword(); 3187 } catch (Exception e) { 3188 Slog.wtf(TAG, e); 3189 return null; 3190 } 3191 } 3192 3193 @Override clearPassword()3194 public void clearPassword() throws RemoteException { 3195 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER, 3196 "only keyguard can clear password"); 3197 3198 try { 3199 mVold.fdeClearPassword(); 3200 return; 3201 } catch (Exception e) { 3202 Slog.wtf(TAG, e); 3203 return; 3204 } 3205 } 3206 3207 @Override createUserKey(int userId, int serialNumber, boolean ephemeral)3208 public void createUserKey(int userId, int serialNumber, boolean ephemeral) { 3209 enforcePermission(android.Manifest.permission.STORAGE_INTERNAL); 3210 3211 try { 3212 mVold.createUserKey(userId, serialNumber, ephemeral); 3213 } catch (Exception e) { 3214 Slog.wtf(TAG, e); 3215 } 3216 } 3217 3218 @Override destroyUserKey(int userId)3219 public void destroyUserKey(int userId) { 3220 enforcePermission(android.Manifest.permission.STORAGE_INTERNAL); 3221 3222 try { 3223 mVold.destroyUserKey(userId); 3224 } catch (Exception e) { 3225 Slog.wtf(TAG, e); 3226 } 3227 } 3228 encodeBytes(byte[] bytes)3229 private String encodeBytes(byte[] bytes) { 3230 if (ArrayUtils.isEmpty(bytes)) { 3231 return "!"; 3232 } else { 3233 return HexDump.toHexString(bytes); 3234 } 3235 } 3236 3237 /* 3238 * Add this token/secret pair to the set of ways we can recover a disk encryption key. 3239 * Changing the token/secret for a disk encryption key is done in two phases: first, adding 3240 * a new token/secret pair with this call, then delting all other pairs with 3241 * fixateNewestUserKeyAuth. This allows other places where a credential is used, such as 3242 * Gatekeeper, to be updated between the two calls. 3243 */ 3244 @Override addUserKeyAuth(int userId, int serialNumber, byte[] token, byte[] secret)3245 public void addUserKeyAuth(int userId, int serialNumber, byte[] token, byte[] secret) { 3246 enforcePermission(android.Manifest.permission.STORAGE_INTERNAL); 3247 3248 try { 3249 mVold.addUserKeyAuth(userId, serialNumber, encodeBytes(token), encodeBytes(secret)); 3250 } catch (Exception e) { 3251 Slog.wtf(TAG, e); 3252 } 3253 } 3254 3255 /* 3256 * Clear disk encryption key bound to the associated token / secret pair. Removing the user 3257 * binding of the Disk encryption key is done in two phases: first, this call will retrieve 3258 * the disk encryption key using the provided token / secret pair and store it by 3259 * encrypting it with a keymaster key not bound to the user, then fixateNewestUserKeyAuth 3260 * is called to delete all other bindings of the disk encryption key. 3261 */ 3262 @Override clearUserKeyAuth(int userId, int serialNumber, byte[] token, byte[] secret)3263 public void clearUserKeyAuth(int userId, int serialNumber, byte[] token, byte[] secret) { 3264 enforcePermission(android.Manifest.permission.STORAGE_INTERNAL); 3265 3266 try { 3267 mVold.clearUserKeyAuth(userId, serialNumber, encodeBytes(token), encodeBytes(secret)); 3268 } catch (Exception e) { 3269 Slog.wtf(TAG, e); 3270 } 3271 } 3272 3273 /* 3274 * Delete all disk encryption token/secret pairs except the most recently added one 3275 */ 3276 @Override fixateNewestUserKeyAuth(int userId)3277 public void fixateNewestUserKeyAuth(int userId) { 3278 enforcePermission(android.Manifest.permission.STORAGE_INTERNAL); 3279 3280 try { 3281 mVold.fixateNewestUserKeyAuth(userId); 3282 } catch (Exception e) { 3283 Slog.wtf(TAG, e); 3284 } 3285 } 3286 3287 @Override unlockUserKey(int userId, int serialNumber, byte[] token, byte[] secret)3288 public void unlockUserKey(int userId, int serialNumber, byte[] token, byte[] secret) { 3289 boolean isFsEncrypted = StorageManager.isFileEncryptedNativeOrEmulated(); 3290 Slog.d(TAG, "unlockUserKey: " + userId 3291 + " isFileEncryptedNativeOrEmulated: " + isFsEncrypted 3292 + " hasToken: " + (token != null) 3293 + " hasSecret: " + (secret != null)); 3294 enforcePermission(android.Manifest.permission.STORAGE_INTERNAL); 3295 3296 if (isFsEncrypted) { 3297 try { 3298 mVold.unlockUserKey(userId, serialNumber, encodeBytes(token), 3299 encodeBytes(secret)); 3300 } catch (Exception e) { 3301 Slog.wtf(TAG, e); 3302 return; 3303 } 3304 } 3305 3306 synchronized (mLock) { 3307 mLocalUnlockedUsers.append(userId); 3308 } 3309 } 3310 3311 @Override lockUserKey(int userId)3312 public void lockUserKey(int userId) { 3313 enforcePermission(android.Manifest.permission.STORAGE_INTERNAL); 3314 3315 try { 3316 mVold.lockUserKey(userId); 3317 } catch (Exception e) { 3318 Slog.wtf(TAG, e); 3319 return; 3320 } 3321 3322 synchronized (mLock) { 3323 mLocalUnlockedUsers.remove(userId); 3324 } 3325 } 3326 3327 @Override isUserKeyUnlocked(int userId)3328 public boolean isUserKeyUnlocked(int userId) { 3329 synchronized (mLock) { 3330 return mLocalUnlockedUsers.contains(userId); 3331 } 3332 } 3333 isSystemUnlocked(int userId)3334 private boolean isSystemUnlocked(int userId) { 3335 synchronized (mLock) { 3336 return ArrayUtils.contains(mSystemUnlockedUsers, userId); 3337 } 3338 } 3339 prepareUserStorageIfNeeded(VolumeInfo vol)3340 private void prepareUserStorageIfNeeded(VolumeInfo vol) { 3341 if (vol.type != VolumeInfo.TYPE_PRIVATE) { 3342 return; 3343 } 3344 3345 final UserManager um = mContext.getSystemService(UserManager.class); 3346 final UserManagerInternal umInternal = 3347 LocalServices.getService(UserManagerInternal.class); 3348 3349 for (UserInfo user : um.getUsers(false /* includeDying */)) { 3350 final int flags; 3351 if (umInternal.isUserUnlockingOrUnlocked(user.id)) { 3352 flags = StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE; 3353 } else if (umInternal.isUserRunning(user.id)) { 3354 flags = StorageManager.FLAG_STORAGE_DE; 3355 } else { 3356 continue; 3357 } 3358 3359 prepareUserStorageInternal(vol.fsUuid, user.id, user.serialNumber, flags); 3360 } 3361 } 3362 3363 @Override prepareUserStorage(String volumeUuid, int userId, int serialNumber, int flags)3364 public void prepareUserStorage(String volumeUuid, int userId, int serialNumber, int flags) { 3365 enforcePermission(android.Manifest.permission.STORAGE_INTERNAL); 3366 3367 prepareUserStorageInternal(volumeUuid, userId, serialNumber, flags); 3368 } 3369 prepareUserStorageInternal(String volumeUuid, int userId, int serialNumber, int flags)3370 private void prepareUserStorageInternal(String volumeUuid, int userId, int serialNumber, 3371 int flags) { 3372 try { 3373 mVold.prepareUserStorage(volumeUuid, userId, serialNumber, flags); 3374 // After preparing user storage, we should check if we should mount data mirror again, 3375 // and we do it for user 0 only as we only need to do once for all users. 3376 if (volumeUuid != null) { 3377 final StorageManager storage = mContext.getSystemService(StorageManager.class); 3378 VolumeInfo info = storage.findVolumeByUuid(volumeUuid); 3379 if (info != null && userId == 0 && info.type == VolumeInfo.TYPE_PRIVATE) { 3380 mInstaller.tryMountDataMirror(volumeUuid); 3381 } 3382 } 3383 } catch (Exception e) { 3384 Slog.wtf(TAG, e); 3385 } 3386 } 3387 3388 @Override destroyUserStorage(String volumeUuid, int userId, int flags)3389 public void destroyUserStorage(String volumeUuid, int userId, int flags) { 3390 enforcePermission(android.Manifest.permission.STORAGE_INTERNAL); 3391 3392 try { 3393 mVold.destroyUserStorage(volumeUuid, userId, flags); 3394 } catch (Exception e) { 3395 Slog.wtf(TAG, e); 3396 } 3397 } 3398 3399 @Override fixupAppDir(String path)3400 public void fixupAppDir(String path) { 3401 final Matcher matcher = KNOWN_APP_DIR_PATHS.matcher(path); 3402 if (matcher.matches()) { 3403 if (matcher.group(2) == null) { 3404 Log.e(TAG, "Asked to fixup an app dir without a userId: " + path); 3405 return; 3406 } 3407 try { 3408 int userId = Integer.parseInt(matcher.group(2)); 3409 String packageName = matcher.group(3); 3410 int uid = mContext.getPackageManager().getPackageUidAsUser(packageName, userId); 3411 try { 3412 mVold.fixupAppDir(path + "/", uid); 3413 } catch (RemoteException | ServiceSpecificException e) { 3414 Log.e(TAG, "Failed to fixup app dir for " + packageName, e); 3415 } 3416 } catch (NumberFormatException e) { 3417 Log.e(TAG, "Invalid userId in path: " + path, e); 3418 } catch (PackageManager.NameNotFoundException e) { 3419 Log.e(TAG, "Couldn't find package to fixup app dir " + path, e); 3420 } 3421 } else { 3422 Log.e(TAG, "Path " + path + " is not a valid application-specific directory"); 3423 } 3424 } 3425 3426 /** Not thread safe */ 3427 class AppFuseMountScope extends AppFuseBridge.MountScope { 3428 private boolean mMounted = false; 3429 AppFuseMountScope(int uid, int mountId)3430 public AppFuseMountScope(int uid, int mountId) { 3431 super(uid, mountId); 3432 } 3433 3434 @Override open()3435 public ParcelFileDescriptor open() throws NativeDaemonConnectorException { 3436 try { 3437 final FileDescriptor fd = mVold.mountAppFuse(uid, mountId); 3438 mMounted = true; 3439 return new ParcelFileDescriptor(fd); 3440 } catch (Exception e) { 3441 throw new NativeDaemonConnectorException("Failed to mount", e); 3442 } 3443 } 3444 3445 @Override openFile(int mountId, int fileId, int flags)3446 public ParcelFileDescriptor openFile(int mountId, int fileId, int flags) 3447 throws NativeDaemonConnectorException { 3448 try { 3449 return new ParcelFileDescriptor( 3450 mVold.openAppFuseFile(uid, mountId, fileId, flags)); 3451 } catch (Exception e) { 3452 throw new NativeDaemonConnectorException("Failed to open", e); 3453 } 3454 } 3455 3456 @Override close()3457 public void close() throws Exception { 3458 if (mMounted) { 3459 mVold.unmountAppFuse(uid, mountId); 3460 mMounted = false; 3461 } 3462 } 3463 } 3464 3465 @Override mountProxyFileDescriptorBridge()3466 public @Nullable AppFuseMount mountProxyFileDescriptorBridge() { 3467 Slog.v(TAG, "mountProxyFileDescriptorBridge"); 3468 final int uid = Binder.getCallingUid(); 3469 3470 while (true) { 3471 synchronized (mAppFuseLock) { 3472 boolean newlyCreated = false; 3473 if (mAppFuseBridge == null) { 3474 mAppFuseBridge = new AppFuseBridge(); 3475 new Thread(mAppFuseBridge, AppFuseBridge.TAG).start(); 3476 newlyCreated = true; 3477 } 3478 try { 3479 final int name = mNextAppFuseName++; 3480 try { 3481 return new AppFuseMount( 3482 name, mAppFuseBridge.addBridge(new AppFuseMountScope(uid, name))); 3483 } catch (FuseUnavailableMountException e) { 3484 if (newlyCreated) { 3485 // If newly created bridge fails, it's a real error. 3486 Slog.e(TAG, "", e); 3487 return null; 3488 } 3489 // It seems the thread of mAppFuseBridge has already been terminated. 3490 mAppFuseBridge = null; 3491 } 3492 } catch (NativeDaemonConnectorException e) { 3493 throw e.rethrowAsParcelableException(); 3494 } 3495 } 3496 } 3497 } 3498 3499 @Override openProxyFileDescriptor( int mountId, int fileId, int mode)3500 public @Nullable ParcelFileDescriptor openProxyFileDescriptor( 3501 int mountId, int fileId, int mode) { 3502 Slog.v(TAG, "mountProxyFileDescriptor"); 3503 3504 // We only support a narrow set of incoming mode flags 3505 mode &= MODE_READ_WRITE; 3506 3507 try { 3508 synchronized (mAppFuseLock) { 3509 if (mAppFuseBridge == null) { 3510 Slog.e(TAG, "FuseBridge has not been created"); 3511 return null; 3512 } 3513 return mAppFuseBridge.openFile(mountId, fileId, mode); 3514 } 3515 } catch (FuseUnavailableMountException | InterruptedException error) { 3516 Slog.v(TAG, "The mount point has already been invalid", error); 3517 return null; 3518 } 3519 } 3520 3521 @Override mkdirs(String callingPkg, String appPath)3522 public void mkdirs(String callingPkg, String appPath) { 3523 final int callingUid = Binder.getCallingUid(); 3524 final int userId = UserHandle.getUserId(callingUid); 3525 final String propertyName = "sys.user." + userId + ".ce_available"; 3526 3527 // Ignore requests to create directories while storage is locked 3528 if (!isUserKeyUnlocked(userId)) { 3529 throw new IllegalStateException("Failed to prepare " + appPath); 3530 } 3531 3532 // Ignore requests to create directories if CE storage is not available 3533 if ((userId == UserHandle.USER_SYSTEM) 3534 && !SystemProperties.getBoolean(propertyName, false)) { 3535 throw new IllegalStateException("Failed to prepare " + appPath); 3536 } 3537 3538 // Validate that reported package name belongs to caller 3539 final AppOpsManager appOps = (AppOpsManager) mContext.getSystemService( 3540 Context.APP_OPS_SERVICE); 3541 appOps.checkPackage(callingUid, callingPkg); 3542 3543 File appFile = null; 3544 try { 3545 appFile = new File(appPath).getCanonicalFile(); 3546 } catch (IOException e) { 3547 throw new IllegalStateException("Failed to resolve " + appPath + ": " + e); 3548 } 3549 3550 appPath = appFile.getAbsolutePath(); 3551 if (!appPath.endsWith("/")) { 3552 appPath = appPath + "/"; 3553 } 3554 // Ensure that the path we're asked to create is a known application directory 3555 // path. 3556 final Matcher matcher = KNOWN_APP_DIR_PATHS.matcher(appPath); 3557 if (matcher.matches()) { 3558 // And that the package dir matches the calling package 3559 if (!matcher.group(3).equals(callingPkg)) { 3560 throw new SecurityException("Invalid mkdirs path: " + appFile 3561 + " does not contain calling package " + callingPkg); 3562 } 3563 // And that the user id part of the path (if any) matches the calling user id, 3564 // or if for a public volume (no user id), the user matches the current user 3565 if ((matcher.group(2) != null && !matcher.group(2).equals(Integer.toString(userId))) 3566 || (matcher.group(2) == null && userId != mCurrentUserId)) { 3567 throw new SecurityException("Invalid mkdirs path: " + appFile 3568 + " does not match calling user id " + userId); 3569 } 3570 try { 3571 mVold.setupAppDir(appPath, callingUid); 3572 } catch (RemoteException e) { 3573 throw new IllegalStateException("Failed to prepare " + appPath + ": " + e); 3574 } 3575 3576 return; 3577 } 3578 throw new SecurityException("Invalid mkdirs path: " + appFile 3579 + " is not a known app path."); 3580 } 3581 3582 @Override getVolumeList(int uid, String packageName, int flags)3583 public StorageVolume[] getVolumeList(int uid, String packageName, int flags) { 3584 final int userId = UserHandle.getUserId(uid); 3585 3586 final boolean forWrite = (flags & StorageManager.FLAG_FOR_WRITE) != 0; 3587 final boolean realState = (flags & StorageManager.FLAG_REAL_STATE) != 0; 3588 final boolean includeInvisible = (flags & StorageManager.FLAG_INCLUDE_INVISIBLE) != 0; 3589 final boolean includeRecent = (flags & StorageManager.FLAG_INCLUDE_RECENT) != 0; 3590 3591 // Report all volumes as unmounted until we've recorded that user 0 has unlocked. There 3592 // are no guarantees that callers will see a consistent view of the volume before that 3593 // point 3594 final boolean systemUserUnlocked = isSystemUnlocked(UserHandle.USER_SYSTEM); 3595 3596 // When the caller is the app actually hosting external storage, we 3597 // should never attempt to augment the actual storage volume state, 3598 // otherwise we risk confusing it with race conditions as users go 3599 // through various unlocked states 3600 final boolean callerIsMediaStore = UserHandle.isSameApp(Binder.getCallingUid(), 3601 mMediaStoreAuthorityAppId); 3602 3603 final boolean userIsDemo; 3604 final boolean userKeyUnlocked; 3605 final boolean storagePermission; 3606 final long token = Binder.clearCallingIdentity(); 3607 try { 3608 userIsDemo = LocalServices.getService(UserManagerInternal.class) 3609 .getUserInfo(userId).isDemo(); 3610 userKeyUnlocked = isUserKeyUnlocked(userId); 3611 storagePermission = mStorageManagerInternal.hasExternalStorage(uid, packageName); 3612 } finally { 3613 Binder.restoreCallingIdentity(token); 3614 } 3615 3616 boolean foundPrimary = false; 3617 3618 final ArrayList<StorageVolume> res = new ArrayList<>(); 3619 final ArraySet<String> resUuids = new ArraySet<>(); 3620 synchronized (mLock) { 3621 for (int i = 0; i < mVolumes.size(); i++) { 3622 final String volId = mVolumes.keyAt(i); 3623 final VolumeInfo vol = mVolumes.valueAt(i); 3624 switch (vol.getType()) { 3625 case VolumeInfo.TYPE_PUBLIC: 3626 case VolumeInfo.TYPE_STUB: 3627 break; 3628 case VolumeInfo.TYPE_EMULATED: 3629 if (vol.getMountUserId() == userId) { 3630 break; 3631 } 3632 // Skip if emulated volume not for userId 3633 default: 3634 continue; 3635 } 3636 3637 boolean match = false; 3638 if (forWrite) { 3639 match = vol.isVisibleForWrite(userId); 3640 } else { 3641 match = vol.isVisibleForRead(userId) 3642 || (includeInvisible && vol.getPath() != null); 3643 } 3644 if (!match) continue; 3645 3646 boolean reportUnmounted = false; 3647 if (callerIsMediaStore) { 3648 // When the caller is the app actually hosting external storage, we 3649 // should never attempt to augment the actual storage volume state, 3650 // otherwise we risk confusing it with race conditions as users go 3651 // through various unlocked states 3652 } else if (!systemUserUnlocked) { 3653 reportUnmounted = true; 3654 Slog.w(TAG, "Reporting " + volId + " unmounted due to system locked"); 3655 } else if ((vol.getType() == VolumeInfo.TYPE_EMULATED) && !userKeyUnlocked) { 3656 reportUnmounted = true; 3657 Slog.w(TAG, "Reporting " + volId + "unmounted due to " + userId + " locked"); 3658 } else if (!storagePermission && !realState) { 3659 Slog.w(TAG, "Reporting " + volId + "unmounted due to missing permissions"); 3660 reportUnmounted = true; 3661 } 3662 3663 final StorageVolume userVol = vol.buildStorageVolume(mContext, userId, 3664 reportUnmounted); 3665 if (vol.isPrimary()) { 3666 res.add(0, userVol); 3667 foundPrimary = true; 3668 } else { 3669 res.add(userVol); 3670 } 3671 resUuids.add(userVol.getUuid()); 3672 } 3673 3674 if (includeRecent) { 3675 final long lastWeek = System.currentTimeMillis() - DateUtils.WEEK_IN_MILLIS; 3676 for (int i = 0; i < mRecords.size(); i++) { 3677 final VolumeRecord rec = mRecords.valueAt(i); 3678 3679 // Skip if we've already included it above 3680 if (resUuids.contains(rec.fsUuid)) continue; 3681 3682 // Treat as recent if mounted within the last week 3683 if (rec.lastSeenMillis > 0 && rec.lastSeenMillis < lastWeek) { 3684 final StorageVolume userVol = rec.buildStorageVolume(mContext); 3685 res.add(userVol); 3686 resUuids.add(userVol.getUuid()); 3687 } 3688 } 3689 } 3690 } 3691 3692 // Synthesize a volume for preloaded media under demo users, so that 3693 // it's scanned into MediaStore 3694 if (userIsDemo) { 3695 final String id = "demo"; 3696 final File path = Environment.getDataPreloadsMediaDirectory(); 3697 final boolean primary = false; 3698 final boolean removable = false; 3699 final boolean emulated = true; 3700 final boolean allowMassStorage = false; 3701 final long maxFileSize = 0; 3702 final UserHandle user = new UserHandle(userId); 3703 final String envState = Environment.MEDIA_MOUNTED_READ_ONLY; 3704 final String description = mContext.getString(android.R.string.unknownName); 3705 3706 res.add(new StorageVolume(id, path, path, description, primary, removable, 3707 emulated, allowMassStorage, maxFileSize, user, id, envState)); 3708 } 3709 3710 if (!foundPrimary) { 3711 Slog.w(TAG, "No primary storage defined yet; hacking together a stub"); 3712 3713 final boolean primaryPhysical = SystemProperties.getBoolean( 3714 StorageManager.PROP_PRIMARY_PHYSICAL, false); 3715 3716 final String id = "stub_primary"; 3717 final File path = Environment.getLegacyExternalStorageDirectory(); 3718 final String description = mContext.getString(android.R.string.unknownName); 3719 final boolean primary = true; 3720 final boolean removable = primaryPhysical; 3721 final boolean emulated = !primaryPhysical; 3722 final boolean allowMassStorage = false; 3723 final long maxFileSize = 0L; 3724 final UserHandle owner = new UserHandle(userId); 3725 final String uuid = null; 3726 final String state = Environment.MEDIA_REMOVED; 3727 3728 res.add(0, new StorageVolume(id, path, path, 3729 description, primary, removable, emulated, 3730 allowMassStorage, maxFileSize, owner, uuid, state)); 3731 } 3732 3733 return res.toArray(new StorageVolume[res.size()]); 3734 } 3735 3736 @Override getDisks()3737 public DiskInfo[] getDisks() { 3738 synchronized (mLock) { 3739 final DiskInfo[] res = new DiskInfo[mDisks.size()]; 3740 for (int i = 0; i < mDisks.size(); i++) { 3741 res[i] = mDisks.valueAt(i); 3742 } 3743 return res; 3744 } 3745 } 3746 3747 @Override getVolumes(int flags)3748 public VolumeInfo[] getVolumes(int flags) { 3749 synchronized (mLock) { 3750 final VolumeInfo[] res = new VolumeInfo[mVolumes.size()]; 3751 for (int i = 0; i < mVolumes.size(); i++) { 3752 res[i] = mVolumes.valueAt(i); 3753 } 3754 return res; 3755 } 3756 } 3757 3758 @Override getVolumeRecords(int flags)3759 public VolumeRecord[] getVolumeRecords(int flags) { 3760 synchronized (mLock) { 3761 final VolumeRecord[] res = new VolumeRecord[mRecords.size()]; 3762 for (int i = 0; i < mRecords.size(); i++) { 3763 res[i] = mRecords.valueAt(i); 3764 } 3765 return res; 3766 } 3767 } 3768 3769 @Override getCacheQuotaBytes(String volumeUuid, int uid)3770 public long getCacheQuotaBytes(String volumeUuid, int uid) { 3771 if (uid != Binder.getCallingUid()) { 3772 mContext.enforceCallingPermission(android.Manifest.permission.STORAGE_INTERNAL, TAG); 3773 } 3774 final long token = Binder.clearCallingIdentity(); 3775 final StorageStatsManager stats = mContext.getSystemService(StorageStatsManager.class); 3776 try { 3777 return stats.getCacheQuotaBytes(volumeUuid, uid); 3778 } finally { 3779 Binder.restoreCallingIdentity(token); 3780 } 3781 } 3782 3783 @Override getCacheSizeBytes(String volumeUuid, int uid)3784 public long getCacheSizeBytes(String volumeUuid, int uid) { 3785 if (uid != Binder.getCallingUid()) { 3786 mContext.enforceCallingPermission(android.Manifest.permission.STORAGE_INTERNAL, TAG); 3787 } 3788 final long token = Binder.clearCallingIdentity(); 3789 try { 3790 return mContext.getSystemService(StorageStatsManager.class) 3791 .queryStatsForUid(volumeUuid, uid).getCacheBytes(); 3792 } catch (IOException e) { 3793 throw new ParcelableException(e); 3794 } finally { 3795 Binder.restoreCallingIdentity(token); 3796 } 3797 } 3798 adjustAllocateFlags(int flags, int callingUid, String callingPackage)3799 private int adjustAllocateFlags(int flags, int callingUid, String callingPackage) { 3800 // Require permission to allocate aggressively 3801 if ((flags & StorageManager.FLAG_ALLOCATE_AGGRESSIVE) != 0) { 3802 mContext.enforceCallingOrSelfPermission( 3803 android.Manifest.permission.ALLOCATE_AGGRESSIVE, TAG); 3804 } 3805 3806 // Apps normally can't directly defy reserved space 3807 flags &= ~StorageManager.FLAG_ALLOCATE_DEFY_ALL_RESERVED; 3808 flags &= ~StorageManager.FLAG_ALLOCATE_DEFY_HALF_RESERVED; 3809 3810 // However, if app is actively using the camera, then we're willing to 3811 // clear up to half of the reserved cache space, since the user might be 3812 // trying to capture an important memory. 3813 final AppOpsManager appOps = mContext.getSystemService(AppOpsManager.class); 3814 final long token = Binder.clearCallingIdentity(); 3815 try { 3816 if (appOps.isOperationActive(AppOpsManager.OP_CAMERA, callingUid, callingPackage)) { 3817 Slog.d(TAG, "UID " + callingUid + " is actively using camera;" 3818 + " letting them defy reserved cached data"); 3819 flags |= StorageManager.FLAG_ALLOCATE_DEFY_HALF_RESERVED; 3820 } 3821 } finally { 3822 Binder.restoreCallingIdentity(token); 3823 } 3824 3825 return flags; 3826 } 3827 3828 @Override getAllocatableBytes(String volumeUuid, int flags, String callingPackage)3829 public long getAllocatableBytes(String volumeUuid, int flags, String callingPackage) { 3830 flags = adjustAllocateFlags(flags, Binder.getCallingUid(), callingPackage); 3831 3832 final StorageManager storage = mContext.getSystemService(StorageManager.class); 3833 final StorageStatsManager stats = mContext.getSystemService(StorageStatsManager.class); 3834 final long token = Binder.clearCallingIdentity(); 3835 try { 3836 // In general, apps can allocate as much space as they want, except 3837 // we never let them eat into either the minimum cache space or into 3838 // the low disk warning space. To avoid user confusion, this logic 3839 // should be kept in sync with getFreeBytes(). 3840 final File path = storage.findPathForUuid(volumeUuid); 3841 3842 long usable = 0; 3843 long lowReserved = 0; 3844 long fullReserved = 0; 3845 long cacheClearable = 0; 3846 3847 if ((flags & StorageManager.FLAG_ALLOCATE_CACHE_ONLY) == 0) { 3848 usable = path.getUsableSpace(); 3849 lowReserved = storage.getStorageLowBytes(path); 3850 fullReserved = storage.getStorageFullBytes(path); 3851 } 3852 3853 if ((flags & StorageManager.FLAG_ALLOCATE_NON_CACHE_ONLY) == 0 3854 && stats.isQuotaSupported(volumeUuid)) { 3855 final long cacheTotal = stats.getCacheBytes(volumeUuid); 3856 final long cacheReserved = storage.getStorageCacheBytes(path, flags); 3857 cacheClearable = Math.max(0, cacheTotal - cacheReserved); 3858 } 3859 3860 if ((flags & StorageManager.FLAG_ALLOCATE_AGGRESSIVE) != 0) { 3861 return Math.max(0, (usable + cacheClearable) - fullReserved); 3862 } else { 3863 return Math.max(0, (usable + cacheClearable) - lowReserved); 3864 } 3865 } catch (IOException e) { 3866 throw new ParcelableException(e); 3867 } finally { 3868 Binder.restoreCallingIdentity(token); 3869 } 3870 } 3871 3872 @Override allocateBytes(String volumeUuid, long bytes, int flags, String callingPackage)3873 public void allocateBytes(String volumeUuid, long bytes, int flags, String callingPackage) { 3874 flags = adjustAllocateFlags(flags, Binder.getCallingUid(), callingPackage); 3875 3876 final long allocatableBytes = getAllocatableBytes(volumeUuid, 3877 flags | StorageManager.FLAG_ALLOCATE_NON_CACHE_ONLY, callingPackage); 3878 if (bytes > allocatableBytes) { 3879 // If we don't have room without taking cache into account, check to see if we'd have 3880 // room if we included freeable cache space. 3881 final long cacheClearable = getAllocatableBytes(volumeUuid, 3882 flags | StorageManager.FLAG_ALLOCATE_CACHE_ONLY, callingPackage); 3883 if (bytes > allocatableBytes + cacheClearable) { 3884 throw new ParcelableException(new IOException("Failed to allocate " + bytes 3885 + " because only " + (allocatableBytes + cacheClearable) + " allocatable")); 3886 } 3887 } 3888 3889 final StorageManager storage = mContext.getSystemService(StorageManager.class); 3890 final long token = Binder.clearCallingIdentity(); 3891 try { 3892 // Free up enough disk space to satisfy both the requested allocation 3893 // and our low disk warning space. 3894 final File path = storage.findPathForUuid(volumeUuid); 3895 if ((flags & StorageManager.FLAG_ALLOCATE_AGGRESSIVE) != 0) { 3896 bytes += storage.getStorageFullBytes(path); 3897 } else { 3898 bytes += storage.getStorageLowBytes(path); 3899 } 3900 3901 mPmInternal.freeStorage(volumeUuid, bytes, flags); 3902 } catch (IOException e) { 3903 throw new ParcelableException(e); 3904 } finally { 3905 Binder.restoreCallingIdentity(token); 3906 } 3907 } 3908 3909 private IAppOpsCallback.Stub mAppOpsCallback = new IAppOpsCallback.Stub() { 3910 @Override 3911 public void opChanged(int op, int uid, String packageName) throws RemoteException { 3912 if (!ENABLE_ISOLATED_STORAGE) return; 3913 3914 int mountMode = getMountMode(uid, packageName); 3915 boolean isUidActive = LocalServices.getService(ActivityManagerInternal.class) 3916 .getUidProcessState(uid) != PROCESS_STATE_NONEXISTENT; 3917 3918 if (isUidActive) { 3919 remountUidExternalStorage(uid, mountMode); 3920 } 3921 } 3922 }; 3923 addObbStateLocked(ObbState obbState)3924 private void addObbStateLocked(ObbState obbState) throws RemoteException { 3925 final IBinder binder = obbState.getBinder(); 3926 List<ObbState> obbStates = mObbMounts.get(binder); 3927 3928 if (obbStates == null) { 3929 obbStates = new ArrayList<ObbState>(); 3930 mObbMounts.put(binder, obbStates); 3931 } else { 3932 for (final ObbState o : obbStates) { 3933 if (o.rawPath.equals(obbState.rawPath)) { 3934 throw new IllegalStateException("Attempt to add ObbState twice. " 3935 + "This indicates an error in the StorageManagerService logic."); 3936 } 3937 } 3938 } 3939 3940 obbStates.add(obbState); 3941 try { 3942 obbState.link(); 3943 } catch (RemoteException e) { 3944 /* 3945 * The binder died before we could link it, so clean up our state 3946 * and return failure. 3947 */ 3948 obbStates.remove(obbState); 3949 if (obbStates.isEmpty()) { 3950 mObbMounts.remove(binder); 3951 } 3952 3953 // Rethrow the error so mountObb can get it 3954 throw e; 3955 } 3956 3957 mObbPathToStateMap.put(obbState.rawPath, obbState); 3958 } 3959 removeObbStateLocked(ObbState obbState)3960 private void removeObbStateLocked(ObbState obbState) { 3961 final IBinder binder = obbState.getBinder(); 3962 final List<ObbState> obbStates = mObbMounts.get(binder); 3963 if (obbStates != null) { 3964 if (obbStates.remove(obbState)) { 3965 obbState.unlink(); 3966 } 3967 if (obbStates.isEmpty()) { 3968 mObbMounts.remove(binder); 3969 } 3970 } 3971 3972 mObbPathToStateMap.remove(obbState.rawPath); 3973 } 3974 3975 private class ObbActionHandler extends Handler { 3976 ObbActionHandler(Looper l)3977 ObbActionHandler(Looper l) { 3978 super(l); 3979 } 3980 3981 @Override handleMessage(Message msg)3982 public void handleMessage(Message msg) { 3983 switch (msg.what) { 3984 case OBB_RUN_ACTION: { 3985 final ObbAction action = (ObbAction) msg.obj; 3986 3987 if (DEBUG_OBB) 3988 Slog.i(TAG, "OBB_RUN_ACTION: " + action.toString()); 3989 3990 action.execute(this); 3991 break; 3992 } 3993 case OBB_FLUSH_MOUNT_STATE: { 3994 final String path = (String) msg.obj; 3995 3996 if (DEBUG_OBB) 3997 Slog.i(TAG, "Flushing all OBB state for path " + path); 3998 3999 synchronized (mObbMounts) { 4000 final List<ObbState> obbStatesToRemove = new LinkedList<ObbState>(); 4001 4002 final Iterator<ObbState> i = mObbPathToStateMap.values().iterator(); 4003 while (i.hasNext()) { 4004 final ObbState state = i.next(); 4005 4006 /* 4007 * If this entry's source file is in the volume path 4008 * that got unmounted, remove it because it's no 4009 * longer valid. 4010 */ 4011 if (state.canonicalPath.startsWith(path)) { 4012 obbStatesToRemove.add(state); 4013 } 4014 } 4015 4016 for (final ObbState obbState : obbStatesToRemove) { 4017 if (DEBUG_OBB) 4018 Slog.i(TAG, "Removing state for " + obbState.rawPath); 4019 4020 removeObbStateLocked(obbState); 4021 4022 try { 4023 obbState.token.onObbResult(obbState.rawPath, obbState.nonce, 4024 OnObbStateChangeListener.UNMOUNTED); 4025 } catch (RemoteException e) { 4026 Slog.i(TAG, "Couldn't send unmount notification for OBB: " 4027 + obbState.rawPath); 4028 } 4029 } 4030 } 4031 break; 4032 } 4033 } 4034 } 4035 } 4036 4037 private static class ObbException extends Exception { 4038 public final int status; 4039 ObbException(int status, String message)4040 public ObbException(int status, String message) { 4041 super(message); 4042 this.status = status; 4043 } 4044 ObbException(int status, Throwable cause)4045 public ObbException(int status, Throwable cause) { 4046 super(cause.getMessage(), cause); 4047 this.status = status; 4048 } 4049 } 4050 4051 abstract class ObbAction { 4052 4053 ObbState mObbState; 4054 ObbAction(ObbState obbState)4055 ObbAction(ObbState obbState) { 4056 mObbState = obbState; 4057 } 4058 execute(ObbActionHandler handler)4059 public void execute(ObbActionHandler handler) { 4060 try { 4061 if (DEBUG_OBB) 4062 Slog.i(TAG, "Starting to execute action: " + toString()); 4063 handleExecute(); 4064 } catch (ObbException e) { 4065 notifyObbStateChange(e); 4066 } 4067 } 4068 handleExecute()4069 abstract void handleExecute() throws ObbException; 4070 notifyObbStateChange(ObbException e)4071 protected void notifyObbStateChange(ObbException e) { 4072 Slog.w(TAG, e); 4073 notifyObbStateChange(e.status); 4074 } 4075 notifyObbStateChange(int status)4076 protected void notifyObbStateChange(int status) { 4077 if (mObbState == null || mObbState.token == null) { 4078 return; 4079 } 4080 4081 try { 4082 mObbState.token.onObbResult(mObbState.rawPath, mObbState.nonce, status); 4083 } catch (RemoteException e) { 4084 Slog.w(TAG, "StorageEventListener went away while calling onObbStateChanged"); 4085 } 4086 } 4087 } 4088 4089 class MountObbAction extends ObbAction { 4090 private final String mKey; 4091 private final int mCallingUid; 4092 private ObbInfo mObbInfo; 4093 MountObbAction(ObbState obbState, String key, int callingUid, ObbInfo obbInfo)4094 MountObbAction(ObbState obbState, String key, int callingUid, ObbInfo obbInfo) { 4095 super(obbState); 4096 mKey = key; 4097 mCallingUid = callingUid; 4098 mObbInfo = obbInfo; 4099 } 4100 4101 @Override handleExecute()4102 public void handleExecute() throws ObbException { 4103 warnOnNotMounted(); 4104 4105 if (!isUidOwnerOfPackageOrSystem(mObbInfo.packageName, mCallingUid)) { 4106 throw new ObbException(ERROR_PERMISSION_DENIED, "Denied attempt to mount OBB " 4107 + mObbInfo.filename + " which is owned by " + mObbInfo.packageName); 4108 } 4109 4110 final boolean isMounted; 4111 synchronized (mObbMounts) { 4112 isMounted = mObbPathToStateMap.containsKey(mObbState.rawPath); 4113 } 4114 if (isMounted) { 4115 throw new ObbException(ERROR_ALREADY_MOUNTED, 4116 "Attempt to mount OBB which is already mounted: " + mObbInfo.filename); 4117 } 4118 4119 final String hashedKey; 4120 final String binderKey; 4121 if (mKey == null) { 4122 hashedKey = "none"; 4123 binderKey = ""; 4124 } else { 4125 try { 4126 SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1"); 4127 4128 KeySpec ks = new PBEKeySpec(mKey.toCharArray(), mObbInfo.salt, 4129 PBKDF2_HASH_ROUNDS, CRYPTO_ALGORITHM_KEY_SIZE); 4130 SecretKey key = factory.generateSecret(ks); 4131 BigInteger bi = new BigInteger(key.getEncoded()); 4132 hashedKey = bi.toString(16); 4133 binderKey = hashedKey; 4134 } catch (GeneralSecurityException e) { 4135 throw new ObbException(ERROR_INTERNAL, e); 4136 } 4137 } 4138 4139 try { 4140 mObbState.volId = mVold.createObb(mObbState.canonicalPath, binderKey, 4141 mObbState.ownerGid); 4142 mVold.mount(mObbState.volId, 0, -1, null); 4143 4144 if (DEBUG_OBB) 4145 Slog.d(TAG, "Successfully mounted OBB " + mObbState.canonicalPath); 4146 4147 synchronized (mObbMounts) { 4148 addObbStateLocked(mObbState); 4149 } 4150 4151 notifyObbStateChange(MOUNTED); 4152 } catch (Exception e) { 4153 throw new ObbException(ERROR_COULD_NOT_MOUNT, e); 4154 } 4155 } 4156 4157 @Override toString()4158 public String toString() { 4159 StringBuilder sb = new StringBuilder(); 4160 sb.append("MountObbAction{"); 4161 sb.append(mObbState); 4162 sb.append('}'); 4163 return sb.toString(); 4164 } 4165 } 4166 4167 class UnmountObbAction extends ObbAction { 4168 private final boolean mForceUnmount; 4169 UnmountObbAction(ObbState obbState, boolean force)4170 UnmountObbAction(ObbState obbState, boolean force) { 4171 super(obbState); 4172 mForceUnmount = force; 4173 } 4174 4175 @Override handleExecute()4176 public void handleExecute() throws ObbException { 4177 warnOnNotMounted(); 4178 4179 final ObbState existingState; 4180 synchronized (mObbMounts) { 4181 existingState = mObbPathToStateMap.get(mObbState.rawPath); 4182 } 4183 4184 if (existingState == null) { 4185 throw new ObbException(ERROR_NOT_MOUNTED, "Missing existingState"); 4186 } 4187 4188 if (existingState.ownerGid != mObbState.ownerGid) { 4189 notifyObbStateChange(new ObbException(ERROR_PERMISSION_DENIED, 4190 "Permission denied to unmount OBB " + existingState.rawPath 4191 + " (owned by GID " + existingState.ownerGid + ")")); 4192 return; 4193 } 4194 4195 try { 4196 mVold.unmount(mObbState.volId); 4197 mVold.destroyObb(mObbState.volId); 4198 mObbState.volId = null; 4199 4200 synchronized (mObbMounts) { 4201 removeObbStateLocked(existingState); 4202 } 4203 4204 notifyObbStateChange(UNMOUNTED); 4205 } catch (Exception e) { 4206 throw new ObbException(ERROR_COULD_NOT_UNMOUNT, e); 4207 } 4208 } 4209 4210 @Override toString()4211 public String toString() { 4212 StringBuilder sb = new StringBuilder(); 4213 sb.append("UnmountObbAction{"); 4214 sb.append(mObbState); 4215 sb.append(",force="); 4216 sb.append(mForceUnmount); 4217 sb.append('}'); 4218 return sb.toString(); 4219 } 4220 } 4221 dispatchOnStatus(IVoldTaskListener listener, int status, PersistableBundle extras)4222 private void dispatchOnStatus(IVoldTaskListener listener, int status, 4223 PersistableBundle extras) { 4224 if (listener != null) { 4225 try { 4226 listener.onStatus(status, extras); 4227 } catch (RemoteException ignored) { 4228 } 4229 } 4230 } 4231 dispatchOnFinished(IVoldTaskListener listener, int status, PersistableBundle extras)4232 private void dispatchOnFinished(IVoldTaskListener listener, int status, 4233 PersistableBundle extras) { 4234 if (listener != null) { 4235 try { 4236 listener.onFinished(status, extras); 4237 } catch (RemoteException ignored) { 4238 } 4239 } 4240 } 4241 getMountMode(int uid, String packageName)4242 private int getMountMode(int uid, String packageName) { 4243 final int mode = getMountModeInternal(uid, packageName); 4244 if (LOCAL_LOGV) { 4245 Slog.v(TAG, "Resolved mode " + mode + " for " + packageName + "/" 4246 + UserHandle.formatUid(uid)); 4247 } 4248 return mode; 4249 } 4250 getMountModeInternal(int uid, String packageName)4251 private int getMountModeInternal(int uid, String packageName) { 4252 try { 4253 // Get some easy cases out of the way first 4254 if (Process.isIsolated(uid)) { 4255 return Zygote.MOUNT_EXTERNAL_NONE; 4256 } 4257 4258 final String[] packagesForUid = mIPackageManager.getPackagesForUid(uid); 4259 if (ArrayUtils.isEmpty(packagesForUid)) { 4260 // It's possible the package got uninstalled already, so just ignore. 4261 return Zygote.MOUNT_EXTERNAL_NONE; 4262 } 4263 if (packageName == null) { 4264 packageName = packagesForUid[0]; 4265 } 4266 4267 if (mPmInternal.isInstantApp(packageName, UserHandle.getUserId(uid))) { 4268 return Zygote.MOUNT_EXTERNAL_NONE; 4269 } 4270 4271 if (mIsFuseEnabled && mStorageManagerInternal.isExternalStorageService(uid)) { 4272 // Determine if caller requires pass_through mount; note that we do this for 4273 // all processes that share a UID with MediaProvider; but this is fine, since 4274 // those processes anyway share the same rights as MediaProvider. 4275 return Zygote.MOUNT_EXTERNAL_PASS_THROUGH; 4276 } 4277 4278 if (mIsFuseEnabled && (mDownloadsAuthorityAppId == UserHandle.getAppId(uid) 4279 || mExternalStorageAuthorityAppId == UserHandle.getAppId(uid))) { 4280 // DownloadManager can write in app-private directories on behalf of apps; 4281 // give it write access to Android/ 4282 // ExternalStorageProvider can access Android/{data,obb} dirs in managed mode 4283 return Zygote.MOUNT_EXTERNAL_ANDROID_WRITABLE; 4284 } 4285 4286 final boolean hasMtp = mIPackageManager.checkUidPermission(ACCESS_MTP, uid) == 4287 PERMISSION_GRANTED; 4288 if (mIsFuseEnabled && hasMtp) { 4289 ApplicationInfo ai = mIPackageManager.getApplicationInfo(packageName, 4290 0, UserHandle.getUserId(uid)); 4291 if (ai != null && ai.isSignedWithPlatformKey()) { 4292 // Platform processes hosting the MTP server should be able to write in Android/ 4293 return Zygote.MOUNT_EXTERNAL_ANDROID_WRITABLE; 4294 } 4295 } 4296 4297 // Determine if caller is holding runtime permission 4298 final boolean hasRead = StorageManager.checkPermissionAndCheckOp(mContext, false, 0, 4299 uid, packageName, READ_EXTERNAL_STORAGE, OP_READ_EXTERNAL_STORAGE); 4300 final boolean hasWrite = StorageManager.checkPermissionAndCheckOp(mContext, false, 0, 4301 uid, packageName, WRITE_EXTERNAL_STORAGE, OP_WRITE_EXTERNAL_STORAGE); 4302 4303 // We're only willing to give out broad access if they also hold 4304 // runtime permission; this is a firm CDD requirement 4305 final boolean hasFull = mIPackageManager.checkUidPermission(WRITE_MEDIA_STORAGE, 4306 uid) == PERMISSION_GRANTED; 4307 if (hasFull && hasWrite) { 4308 return Zygote.MOUNT_EXTERNAL_FULL; 4309 } 4310 4311 // We're only willing to give out installer access if they also hold 4312 // runtime permission; this is a firm CDD requirement 4313 final boolean hasInstall = mIPackageManager.checkUidPermission(INSTALL_PACKAGES, 4314 uid) == PERMISSION_GRANTED; 4315 boolean hasInstallOp = false; 4316 // OP_REQUEST_INSTALL_PACKAGES is granted/denied per package but vold can't 4317 // update mountpoints of a specific package. So, check the appop for all packages 4318 // sharing the uid and allow same level of storage access for all packages even if 4319 // one of the packages has the appop granted. 4320 for (String uidPackageName : packagesForUid) { 4321 if (mIAppOpsService.checkOperation( 4322 OP_REQUEST_INSTALL_PACKAGES, uid, uidPackageName) == MODE_ALLOWED) { 4323 hasInstallOp = true; 4324 break; 4325 } 4326 } 4327 if ((hasInstall || hasInstallOp) && hasWrite) { 4328 return Zygote.MOUNT_EXTERNAL_INSTALLER; 4329 } 4330 4331 // Otherwise we're willing to give out sandboxed or non-sandboxed if 4332 // they hold the runtime permission 4333 boolean hasLegacy = mIAppOpsService.checkOperation(OP_LEGACY_STORAGE, 4334 uid, packageName) == MODE_ALLOWED; 4335 4336 if (hasLegacy && hasWrite) { 4337 return Zygote.MOUNT_EXTERNAL_WRITE; 4338 } else if (hasLegacy && hasRead) { 4339 return Zygote.MOUNT_EXTERNAL_READ; 4340 } else { 4341 return Zygote.MOUNT_EXTERNAL_DEFAULT; 4342 } 4343 } catch (RemoteException e) { 4344 // Should not happen 4345 } 4346 return Zygote.MOUNT_EXTERNAL_NONE; 4347 } 4348 4349 private static class Callbacks extends Handler { 4350 private static final int MSG_STORAGE_STATE_CHANGED = 1; 4351 private static final int MSG_VOLUME_STATE_CHANGED = 2; 4352 private static final int MSG_VOLUME_RECORD_CHANGED = 3; 4353 private static final int MSG_VOLUME_FORGOTTEN = 4; 4354 private static final int MSG_DISK_SCANNED = 5; 4355 private static final int MSG_DISK_DESTROYED = 6; 4356 4357 private final RemoteCallbackList<IStorageEventListener> 4358 mCallbacks = new RemoteCallbackList<>(); 4359 Callbacks(Looper looper)4360 public Callbacks(Looper looper) { 4361 super(looper); 4362 } 4363 register(IStorageEventListener callback)4364 public void register(IStorageEventListener callback) { 4365 mCallbacks.register(callback); 4366 } 4367 unregister(IStorageEventListener callback)4368 public void unregister(IStorageEventListener callback) { 4369 mCallbacks.unregister(callback); 4370 } 4371 4372 @Override handleMessage(Message msg)4373 public void handleMessage(Message msg) { 4374 final SomeArgs args = (SomeArgs) msg.obj; 4375 final int n = mCallbacks.beginBroadcast(); 4376 for (int i = 0; i < n; i++) { 4377 final IStorageEventListener callback = mCallbacks.getBroadcastItem(i); 4378 try { 4379 invokeCallback(callback, msg.what, args); 4380 } catch (RemoteException ignored) { 4381 } 4382 } 4383 mCallbacks.finishBroadcast(); 4384 args.recycle(); 4385 } 4386 invokeCallback(IStorageEventListener callback, int what, SomeArgs args)4387 private void invokeCallback(IStorageEventListener callback, int what, SomeArgs args) 4388 throws RemoteException { 4389 switch (what) { 4390 case MSG_STORAGE_STATE_CHANGED: { 4391 callback.onStorageStateChanged((String) args.arg1, (String) args.arg2, 4392 (String) args.arg3); 4393 break; 4394 } 4395 case MSG_VOLUME_STATE_CHANGED: { 4396 callback.onVolumeStateChanged((VolumeInfo) args.arg1, args.argi2, args.argi3); 4397 break; 4398 } 4399 case MSG_VOLUME_RECORD_CHANGED: { 4400 callback.onVolumeRecordChanged((VolumeRecord) args.arg1); 4401 break; 4402 } 4403 case MSG_VOLUME_FORGOTTEN: { 4404 callback.onVolumeForgotten((String) args.arg1); 4405 break; 4406 } 4407 case MSG_DISK_SCANNED: { 4408 callback.onDiskScanned((DiskInfo) args.arg1, args.argi2); 4409 break; 4410 } 4411 case MSG_DISK_DESTROYED: { 4412 callback.onDiskDestroyed((DiskInfo) args.arg1); 4413 break; 4414 } 4415 } 4416 } 4417 notifyStorageStateChanged(String path, String oldState, String newState)4418 private void notifyStorageStateChanged(String path, String oldState, String newState) { 4419 final SomeArgs args = SomeArgs.obtain(); 4420 args.arg1 = path; 4421 args.arg2 = oldState; 4422 args.arg3 = newState; 4423 obtainMessage(MSG_STORAGE_STATE_CHANGED, args).sendToTarget(); 4424 } 4425 notifyVolumeStateChanged(VolumeInfo vol, int oldState, int newState)4426 private void notifyVolumeStateChanged(VolumeInfo vol, int oldState, int newState) { 4427 final SomeArgs args = SomeArgs.obtain(); 4428 args.arg1 = vol.clone(); 4429 args.argi2 = oldState; 4430 args.argi3 = newState; 4431 obtainMessage(MSG_VOLUME_STATE_CHANGED, args).sendToTarget(); 4432 } 4433 notifyVolumeRecordChanged(VolumeRecord rec)4434 private void notifyVolumeRecordChanged(VolumeRecord rec) { 4435 final SomeArgs args = SomeArgs.obtain(); 4436 args.arg1 = rec.clone(); 4437 obtainMessage(MSG_VOLUME_RECORD_CHANGED, args).sendToTarget(); 4438 } 4439 notifyVolumeForgotten(String fsUuid)4440 private void notifyVolumeForgotten(String fsUuid) { 4441 final SomeArgs args = SomeArgs.obtain(); 4442 args.arg1 = fsUuid; 4443 obtainMessage(MSG_VOLUME_FORGOTTEN, args).sendToTarget(); 4444 } 4445 notifyDiskScanned(DiskInfo disk, int volumeCount)4446 private void notifyDiskScanned(DiskInfo disk, int volumeCount) { 4447 final SomeArgs args = SomeArgs.obtain(); 4448 args.arg1 = disk.clone(); 4449 args.argi2 = volumeCount; 4450 obtainMessage(MSG_DISK_SCANNED, args).sendToTarget(); 4451 } 4452 notifyDiskDestroyed(DiskInfo disk)4453 private void notifyDiskDestroyed(DiskInfo disk) { 4454 final SomeArgs args = SomeArgs.obtain(); 4455 args.arg1 = disk.clone(); 4456 obtainMessage(MSG_DISK_DESTROYED, args).sendToTarget(); 4457 } 4458 } 4459 4460 @Override dump(FileDescriptor fd, PrintWriter writer, String[] args)4461 protected void dump(FileDescriptor fd, PrintWriter writer, String[] args) { 4462 if (!DumpUtils.checkDumpPermission(mContext, TAG, writer)) return; 4463 4464 final IndentingPrintWriter pw = new IndentingPrintWriter(writer, " ", 160); 4465 synchronized (mLock) { 4466 pw.println("Disks:"); 4467 pw.increaseIndent(); 4468 for (int i = 0; i < mDisks.size(); i++) { 4469 final DiskInfo disk = mDisks.valueAt(i); 4470 disk.dump(pw); 4471 } 4472 pw.decreaseIndent(); 4473 4474 pw.println(); 4475 pw.println("Volumes:"); 4476 pw.increaseIndent(); 4477 for (int i = 0; i < mVolumes.size(); i++) { 4478 final VolumeInfo vol = mVolumes.valueAt(i); 4479 if (VolumeInfo.ID_PRIVATE_INTERNAL.equals(vol.id)) continue; 4480 vol.dump(pw); 4481 } 4482 pw.decreaseIndent(); 4483 4484 pw.println(); 4485 pw.println("Records:"); 4486 pw.increaseIndent(); 4487 for (int i = 0; i < mRecords.size(); i++) { 4488 final VolumeRecord note = mRecords.valueAt(i); 4489 note.dump(pw); 4490 } 4491 pw.decreaseIndent(); 4492 4493 pw.println(); 4494 pw.println("Primary storage UUID: " + mPrimaryStorageUuid); 4495 4496 pw.println(); 4497 final Pair<String, Long> pair = StorageManager.getPrimaryStoragePathAndSize(); 4498 if (pair == null) { 4499 pw.println("Internal storage total size: N/A"); 4500 } else { 4501 pw.print("Internal storage ("); 4502 pw.print(pair.first); 4503 pw.print(") total size: "); 4504 pw.print(pair.second); 4505 pw.print(" ("); 4506 pw.print(DataUnit.MEBIBYTES.toBytes(pair.second)); 4507 pw.println(" MiB)"); 4508 } 4509 4510 pw.println(); 4511 pw.println("Local unlocked users: " + mLocalUnlockedUsers); 4512 pw.println("System unlocked users: " + Arrays.toString(mSystemUnlockedUsers)); 4513 4514 final ContentResolver cr = mContext.getContentResolver(); 4515 pw.println(); 4516 pw.println("Isolated storage, local feature flag: " 4517 + Settings.Global.getInt(cr, Settings.Global.ISOLATED_STORAGE_LOCAL, 0)); 4518 pw.println("Isolated storage, remote feature flag: " 4519 + Settings.Global.getInt(cr, Settings.Global.ISOLATED_STORAGE_REMOTE, 0)); 4520 pw.println("Isolated storage, resolved: " + StorageManager.hasIsolatedStorage()); 4521 pw.println("Forced scoped storage app list: " 4522 + DeviceConfig.getProperty(DeviceConfig.NAMESPACE_STORAGE_NATIVE_BOOT, 4523 PROP_FORCED_SCOPED_STORAGE_WHITELIST)); 4524 pw.println("isAutomotive:" + mIsAutomotive); 4525 } 4526 4527 synchronized (mObbMounts) { 4528 pw.println(); 4529 pw.println("mObbMounts:"); 4530 pw.increaseIndent(); 4531 final Iterator<Entry<IBinder, List<ObbState>>> binders = mObbMounts.entrySet() 4532 .iterator(); 4533 while (binders.hasNext()) { 4534 Entry<IBinder, List<ObbState>> e = binders.next(); 4535 pw.println(e.getKey() + ":"); 4536 pw.increaseIndent(); 4537 final List<ObbState> obbStates = e.getValue(); 4538 for (final ObbState obbState : obbStates) { 4539 pw.println(obbState); 4540 } 4541 pw.decreaseIndent(); 4542 } 4543 pw.decreaseIndent(); 4544 4545 pw.println(); 4546 pw.println("mObbPathToStateMap:"); 4547 pw.increaseIndent(); 4548 final Iterator<Entry<String, ObbState>> maps = 4549 mObbPathToStateMap.entrySet().iterator(); 4550 while (maps.hasNext()) { 4551 final Entry<String, ObbState> e = maps.next(); 4552 pw.print(e.getKey()); 4553 pw.print(" -> "); 4554 pw.println(e.getValue()); 4555 } 4556 pw.decreaseIndent(); 4557 } 4558 4559 pw.println(); 4560 pw.print("Last maintenance: "); 4561 pw.println(TimeUtils.formatForLogging(mLastMaintenance)); 4562 } 4563 4564 /** {@inheritDoc} */ 4565 @Override monitor()4566 public void monitor() { 4567 try { 4568 mVold.monitor(); 4569 } catch (Exception e) { 4570 Slog.wtf(TAG, e); 4571 } 4572 } 4573 4574 private final class StorageManagerInternalImpl extends StorageManagerInternal { 4575 // Not guarded by a lock. 4576 private final CopyOnWriteArrayList<ExternalStorageMountPolicy> mPolicies = 4577 new CopyOnWriteArrayList<>(); 4578 4579 @GuardedBy("mResetListeners") 4580 private final List<StorageManagerInternal.ResetListener> mResetListeners = 4581 new ArrayList<>(); 4582 4583 @Override addExternalStoragePolicy(ExternalStorageMountPolicy policy)4584 public void addExternalStoragePolicy(ExternalStorageMountPolicy policy) { 4585 // No locking - CopyOnWriteArrayList 4586 mPolicies.add(policy); 4587 } 4588 4589 /** 4590 * Check if fuse is running in target user, if it's running then setup its storage dirs. 4591 * Return true if storage dirs are mounted. 4592 */ 4593 @Override prepareStorageDirs(int userId, Set<String> packageList, String processName)4594 public boolean prepareStorageDirs(int userId, Set<String> packageList, 4595 String processName) { 4596 synchronized (mLock) { 4597 if (!mFuseMountedUser.contains(userId)) { 4598 Slog.w(TAG, "User " + userId + " is not unlocked yet so skip mounting obb"); 4599 return false; 4600 } 4601 } 4602 try { 4603 final IVold vold = IVold.Stub.asInterface( 4604 ServiceManager.getServiceOrThrow("vold")); 4605 for (String pkg : packageList) { 4606 final String packageObbDir = 4607 String.format("/storage/emulated/%d/Android/obb/%s/", userId, pkg); 4608 final String packageDataDir = 4609 String.format("/storage/emulated/%d/Android/data/%s/", 4610 userId, pkg); 4611 4612 // Create package obb and data dir if it doesn't exist. 4613 int appUid = UserHandle.getUid(userId, mPmInternal.getPackage(pkg).getUid()); 4614 File file = new File(packageObbDir); 4615 if (!file.exists()) { 4616 vold.setupAppDir(packageObbDir, appUid); 4617 } 4618 file = new File(packageDataDir); 4619 if (!file.exists()) { 4620 vold.setupAppDir(packageDataDir, appUid); 4621 } 4622 } 4623 } catch (ServiceManager.ServiceNotFoundException | RemoteException e) { 4624 Slog.e(TAG, "Unable to create obb and data directories for " + processName,e); 4625 return false; 4626 } 4627 return true; 4628 } 4629 4630 @Override onExternalStoragePolicyChanged(int uid, String packageName)4631 public void onExternalStoragePolicyChanged(int uid, String packageName) { 4632 final int mountMode = getExternalStorageMountMode(uid, packageName); 4633 remountUidExternalStorage(uid, mountMode); 4634 } 4635 4636 @Override getExternalStorageMountMode(int uid, String packageName)4637 public int getExternalStorageMountMode(int uid, String packageName) { 4638 if (ENABLE_ISOLATED_STORAGE) { 4639 return getMountMode(uid, packageName); 4640 } 4641 try { 4642 if (packageName == null) { 4643 final String[] packagesForUid = mIPackageManager.getPackagesForUid(uid); 4644 packageName = packagesForUid[0]; 4645 } 4646 } catch (RemoteException e) { 4647 // Should not happen - same process 4648 } 4649 // No locking - CopyOnWriteArrayList 4650 int mountMode = Integer.MAX_VALUE; 4651 for (ExternalStorageMountPolicy policy : mPolicies) { 4652 final int policyMode = policy.getMountMode(uid, packageName); 4653 if (policyMode == Zygote.MOUNT_EXTERNAL_NONE) { 4654 return Zygote.MOUNT_EXTERNAL_NONE; 4655 } 4656 mountMode = Math.min(mountMode, policyMode); 4657 } 4658 if (mountMode == Integer.MAX_VALUE) { 4659 return Zygote.MOUNT_EXTERNAL_NONE; 4660 } 4661 return mountMode; 4662 } 4663 4664 @Override addResetListener(StorageManagerInternal.ResetListener listener)4665 public void addResetListener(StorageManagerInternal.ResetListener listener) { 4666 synchronized (mResetListeners) { 4667 mResetListeners.add(listener); 4668 } 4669 } 4670 onReset(IVold vold)4671 public void onReset(IVold vold) { 4672 synchronized (mResetListeners) { 4673 for (StorageManagerInternal.ResetListener listener : mResetListeners) { 4674 listener.onReset(vold); 4675 } 4676 } 4677 } 4678 4679 @Override resetUser(int userId)4680 public void resetUser(int userId) { 4681 // TODO(b/145931219): ideally, we only reset storage for the user in question, 4682 // but for now, reset everything. 4683 mHandler.obtainMessage(H_RESET).sendToTarget(); 4684 } 4685 4686 @Override hasLegacyExternalStorage(int uid)4687 public boolean hasLegacyExternalStorage(int uid) { 4688 synchronized (mLock) { 4689 return mUidsWithLegacyExternalStorage.contains(uid); 4690 } 4691 } 4692 4693 @Override prepareAppDataAfterInstall(String packageName, int uid)4694 public void prepareAppDataAfterInstall(String packageName, int uid) { 4695 int userId = UserHandle.getUserId(uid); 4696 final Environment.UserEnvironment userEnv = new Environment.UserEnvironment(userId); 4697 4698 // The installer may have downloaded OBBs for this newly installed application; 4699 // make sure the OBB dir for the application is setup correctly, if it exists. 4700 File[] packageObbDirs = userEnv.buildExternalStorageAppObbDirs(packageName); 4701 for (File packageObbDir : packageObbDirs) { 4702 try { 4703 mVold.fixupAppDir(packageObbDir.getCanonicalPath() + "/", uid); 4704 } catch (IOException e) { 4705 Log.e(TAG, "Failed to get canonical path for " + packageName); 4706 } catch (RemoteException | ServiceSpecificException e) { 4707 // TODO(b/149975102) there is a known case where this fails, when a new 4708 // user is setup and we try to fixup app dirs for some existing apps. 4709 // For now catch the exception and don't crash. 4710 Log.e(TAG, "Failed to fixup app dir for " + packageName, e); 4711 } 4712 } 4713 } 4714 4715 @Override isExternalStorageService(int uid)4716 public boolean isExternalStorageService(int uid) { 4717 return mMediaStoreAuthorityAppId == UserHandle.getAppId(uid); 4718 } 4719 hasExternalStorage(int uid, String packageName)4720 public boolean hasExternalStorage(int uid, String packageName) { 4721 // No need to check for system uid. This avoids a deadlock between 4722 // PackageManagerService and AppOpsService. 4723 if (uid == Process.SYSTEM_UID) { 4724 return true; 4725 } 4726 if (ENABLE_ISOLATED_STORAGE) { 4727 return getMountMode(uid, packageName) != Zygote.MOUNT_EXTERNAL_NONE; 4728 } 4729 // No locking - CopyOnWriteArrayList 4730 for (ExternalStorageMountPolicy policy : mPolicies) { 4731 final boolean policyHasStorage = policy.hasExternalStorage(uid, packageName); 4732 if (!policyHasStorage) { 4733 return false; 4734 } 4735 } 4736 return true; 4737 } 4738 killAppForOpChange(int code, int uid)4739 private void killAppForOpChange(int code, int uid) { 4740 final IActivityManager am = ActivityManager.getService(); 4741 try { 4742 am.killUid(UserHandle.getAppId(uid), UserHandle.USER_ALL, 4743 AppOpsManager.opToName(code) + " changed."); 4744 } catch (RemoteException e) { 4745 } 4746 } 4747 onAppOpsChanged(int code, int uid, @Nullable String packageName, int mode)4748 public void onAppOpsChanged(int code, int uid, @Nullable String packageName, int mode) { 4749 final long token = Binder.clearCallingIdentity(); 4750 try { 4751 if (mIsFuseEnabled) { 4752 // When using FUSE, we may need to kill the app if the op changes 4753 switch(code) { 4754 case OP_REQUEST_INSTALL_PACKAGES: 4755 // Always kill regardless of op change, to remount apps /storage 4756 killAppForOpChange(code, uid); 4757 return; 4758 case OP_MANAGE_EXTERNAL_STORAGE: 4759 if (mode != MODE_ALLOWED) { 4760 // Only kill if op is denied, to lose external_storage gid 4761 // Killing when op is granted to pickup the gid automatically, 4762 // results in a bad UX, especially since the gid only gives access 4763 // to unreliable volumes, USB OTGs that are rarely mounted. The app 4764 // will get the external_storage gid on next organic restart. 4765 killAppForOpChange(code, uid); 4766 } 4767 return; 4768 case OP_LEGACY_STORAGE: 4769 updateLegacyStorageApps(packageName, uid, mode == MODE_ALLOWED); 4770 return; 4771 } 4772 } 4773 4774 if (mode == MODE_ALLOWED && (code == OP_READ_EXTERNAL_STORAGE 4775 || code == OP_WRITE_EXTERNAL_STORAGE 4776 || code == OP_REQUEST_INSTALL_PACKAGES)) { 4777 final UserManagerInternal userManagerInternal = 4778 LocalServices.getService(UserManagerInternal.class); 4779 if (userManagerInternal.isUserInitialized(UserHandle.getUserId(uid))) { 4780 onExternalStoragePolicyChanged(uid, packageName); 4781 } 4782 } 4783 } finally { 4784 Binder.restoreCallingIdentity(token); 4785 } 4786 } 4787 } 4788 } 4789