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