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