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