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