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