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