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.INSTALL_PACKAGES; 20 import static android.Manifest.permission.READ_EXTERNAL_STORAGE; 21 import static android.Manifest.permission.WRITE_EXTERNAL_STORAGE; 22 import static android.Manifest.permission.WRITE_MEDIA_STORAGE; 23 import static android.app.AppOpsManager.MODE_ALLOWED; 24 import static android.app.AppOpsManager.OP_LEGACY_STORAGE; 25 import static android.app.AppOpsManager.OP_READ_EXTERNAL_STORAGE; 26 import static android.app.AppOpsManager.OP_REQUEST_INSTALL_PACKAGES; 27 import static android.app.AppOpsManager.OP_WRITE_EXTERNAL_STORAGE; 28 import static android.content.pm.PackageManager.PERMISSION_GRANTED; 29 import static android.os.ParcelFileDescriptor.MODE_READ_WRITE; 30 import static android.os.storage.OnObbStateChangeListener.ERROR_ALREADY_MOUNTED; 31 import static android.os.storage.OnObbStateChangeListener.ERROR_COULD_NOT_MOUNT; 32 import static android.os.storage.OnObbStateChangeListener.ERROR_COULD_NOT_UNMOUNT; 33 import static android.os.storage.OnObbStateChangeListener.ERROR_INTERNAL; 34 import static android.os.storage.OnObbStateChangeListener.ERROR_NOT_MOUNTED; 35 import static android.os.storage.OnObbStateChangeListener.ERROR_PERMISSION_DENIED; 36 import static android.os.storage.OnObbStateChangeListener.MOUNTED; 37 import static android.os.storage.OnObbStateChangeListener.UNMOUNTED; 38 39 import static com.android.internal.util.XmlUtils.readIntAttribute; 40 import static com.android.internal.util.XmlUtils.readLongAttribute; 41 import static com.android.internal.util.XmlUtils.readStringAttribute; 42 import static com.android.internal.util.XmlUtils.writeIntAttribute; 43 import static com.android.internal.util.XmlUtils.writeLongAttribute; 44 import static com.android.internal.util.XmlUtils.writeStringAttribute; 45 46 import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT; 47 import static org.xmlpull.v1.XmlPullParser.START_TAG; 48 49 import android.Manifest; 50 import android.annotation.Nullable; 51 import android.app.ActivityManager; 52 import android.app.AppOpsManager; 53 import android.app.IActivityManager; 54 import android.app.KeyguardManager; 55 import android.app.admin.SecurityLog; 56 import android.app.usage.StorageStatsManager; 57 import android.content.BroadcastReceiver; 58 import android.content.ContentResolver; 59 import android.content.Context; 60 import android.content.Intent; 61 import android.content.IntentFilter; 62 import android.content.pm.IPackageManager; 63 import android.content.pm.IPackageMoveObserver; 64 import android.content.pm.PackageManager; 65 import android.content.pm.PackageManagerInternal; 66 import android.content.pm.ProviderInfo; 67 import android.content.pm.UserInfo; 68 import android.content.res.Configuration; 69 import android.content.res.ObbInfo; 70 import android.database.ContentObserver; 71 import android.net.Uri; 72 import android.os.Binder; 73 import android.os.DropBoxManager; 74 import android.os.Environment; 75 import android.os.Environment.UserEnvironment; 76 import android.os.FileUtils; 77 import android.os.Handler; 78 import android.os.HandlerThread; 79 import android.os.IBinder; 80 import android.os.IStoraged; 81 import android.os.IVold; 82 import android.os.IVoldListener; 83 import android.os.IVoldTaskListener; 84 import android.os.Looper; 85 import android.os.Message; 86 import android.os.ParcelFileDescriptor; 87 import android.os.ParcelableException; 88 import android.os.PersistableBundle; 89 import android.os.PowerManager; 90 import android.os.Process; 91 import android.os.RemoteCallbackList; 92 import android.os.RemoteException; 93 import android.os.ServiceManager; 94 import android.os.ServiceSpecificException; 95 import android.os.SystemClock; 96 import android.os.SystemProperties; 97 import android.os.UserHandle; 98 import android.os.UserManager; 99 import android.os.UserManagerInternal; 100 import android.os.storage.DiskInfo; 101 import android.os.storage.IObbActionListener; 102 import android.os.storage.IStorageEventListener; 103 import android.os.storage.IStorageManager; 104 import android.os.storage.IStorageShutdownObserver; 105 import android.os.storage.OnObbStateChangeListener; 106 import android.os.storage.StorageManager; 107 import android.os.storage.StorageManagerInternal; 108 import android.os.storage.StorageVolume; 109 import android.os.storage.VolumeInfo; 110 import android.os.storage.VolumeRecord; 111 import android.provider.DeviceConfig; 112 import android.provider.MediaStore; 113 import android.provider.Settings; 114 import android.sysprop.VoldProperties; 115 import android.text.TextUtils; 116 import android.text.format.DateUtils; 117 import android.util.ArrayMap; 118 import android.util.AtomicFile; 119 import android.util.DataUnit; 120 import android.util.Log; 121 import android.util.Pair; 122 import android.util.Slog; 123 import android.util.TimeUtils; 124 import android.util.Xml; 125 126 import com.android.internal.annotations.GuardedBy; 127 import com.android.internal.app.IAppOpsCallback; 128 import com.android.internal.app.IAppOpsService; 129 import com.android.internal.os.AppFuseMount; 130 import com.android.internal.os.BackgroundThread; 131 import com.android.internal.os.FuseUnavailableMountException; 132 import com.android.internal.os.SomeArgs; 133 import com.android.internal.os.Zygote; 134 import com.android.internal.util.ArrayUtils; 135 import com.android.internal.util.CollectionUtils; 136 import com.android.internal.util.DumpUtils; 137 import com.android.internal.util.FastXmlSerializer; 138 import com.android.internal.util.HexDump; 139 import com.android.internal.util.IndentingPrintWriter; 140 import com.android.internal.util.Preconditions; 141 import com.android.internal.widget.LockPatternUtils; 142 import com.android.server.storage.AppFuseBridge; 143 import com.android.server.wm.ActivityTaskManagerInternal; 144 import com.android.server.wm.ActivityTaskManagerInternal.ScreenObserver; 145 146 import libcore.io.IoUtils; 147 import libcore.util.EmptyArray; 148 149 import org.xmlpull.v1.XmlPullParser; 150 import org.xmlpull.v1.XmlPullParserException; 151 import org.xmlpull.v1.XmlSerializer; 152 153 import java.io.File; 154 import java.io.FileDescriptor; 155 import java.io.FileInputStream; 156 import java.io.FileNotFoundException; 157 import java.io.FileOutputStream; 158 import java.io.IOException; 159 import java.io.PrintWriter; 160 import java.math.BigInteger; 161 import java.nio.charset.StandardCharsets; 162 import java.security.GeneralSecurityException; 163 import java.security.spec.KeySpec; 164 import java.util.ArrayList; 165 import java.util.Arrays; 166 import java.util.HashMap; 167 import java.util.Iterator; 168 import java.util.LinkedList; 169 import java.util.List; 170 import java.util.Locale; 171 import java.util.Map; 172 import java.util.Map.Entry; 173 import java.util.Objects; 174 import java.util.concurrent.CopyOnWriteArrayList; 175 import java.util.concurrent.CountDownLatch; 176 import java.util.concurrent.TimeUnit; 177 import java.util.concurrent.TimeoutException; 178 179 import javax.crypto.SecretKey; 180 import javax.crypto.SecretKeyFactory; 181 import javax.crypto.spec.PBEKeySpec; 182 183 /** 184 * Service responsible for various storage media. Connects to {@code vold} to 185 * watch for and manage dynamically added storage, such as SD cards and USB mass 186 * storage. Also decides how storage should be presented to users on the device. 187 */ 188 class StorageManagerService extends IStorageManager.Stub 189 implements Watchdog.Monitor, ScreenObserver { 190 191 // Static direct instance pointer for the tightly-coupled idle service to use 192 static StorageManagerService sSelf = null; 193 194 /* Read during boot to decide whether to enable zram when available */ 195 private static final String ZRAM_ENABLED_PROPERTY = 196 "persist.sys.zram_enabled"; 197 198 private static final boolean ENABLE_ISOLATED_STORAGE = StorageManager.hasIsolatedStorage(); 199 200 /** 201 * If {@code 1}, enables the isolated storage feature. If {@code -1}, 202 * disables the isolated storage feature. If {@code 0}, uses the default 203 * value from the build system. 204 */ 205 private static final String ISOLATED_STORAGE_ENABLED = "isolated_storage_enabled"; 206 207 public static class Lifecycle extends SystemService { 208 private StorageManagerService mStorageManagerService; 209 210 public Lifecycle(Context context) { 211 super(context); 212 } 213 214 @Override 215 public void onStart() { 216 mStorageManagerService = new StorageManagerService(getContext()); 217 publishBinderService("mount", mStorageManagerService); 218 mStorageManagerService.start(); 219 } 220 221 @Override 222 public void onBootPhase(int phase) { 223 if (phase == SystemService.PHASE_SYSTEM_SERVICES_READY) { 224 mStorageManagerService.servicesReady(); 225 } else if (phase == SystemService.PHASE_ACTIVITY_MANAGER_READY) { 226 mStorageManagerService.systemReady(); 227 } else if (phase == SystemService.PHASE_BOOT_COMPLETED) { 228 mStorageManagerService.bootCompleted(); 229 } 230 } 231 232 @Override 233 public void onSwitchUser(int userHandle) { 234 mStorageManagerService.mCurrentUserId = userHandle; 235 } 236 237 @Override 238 public void onUnlockUser(int userHandle) { 239 mStorageManagerService.onUnlockUser(userHandle); 240 } 241 242 @Override 243 public void onCleanupUser(int userHandle) { 244 mStorageManagerService.onCleanupUser(userHandle); 245 } 246 } 247 248 private static final boolean DEBUG_EVENTS = false; 249 private static final boolean DEBUG_OBB = false; 250 251 /** 252 * We now talk to vold over Binder, and it has its own internal lock to 253 * serialize certain calls. All long-running operations have been migrated 254 * to be async with callbacks, so we want watchdog to fire if vold wedges. 255 */ 256 private static final boolean WATCHDOG_ENABLE = true; 257 258 /** 259 * Our goal is for all Android devices to be usable as development devices, 260 * which includes the new Direct Boot mode added in N. For devices that 261 * don't have native FBE support, we offer an emulation mode for developer 262 * testing purposes, but if it's prohibitively difficult to support this 263 * mode, it can be disabled for specific products using this flag. 264 */ 265 private static final boolean EMULATE_FBE_SUPPORTED = true; 266 267 private static final String TAG = "StorageManagerService"; 268 private static final boolean LOCAL_LOGV = Log.isLoggable(TAG, Log.VERBOSE); 269 270 private static final String TAG_STORAGE_BENCHMARK = "storage_benchmark"; 271 private static final String TAG_STORAGE_TRIM = "storage_trim"; 272 273 /** Magic value sent by MoveTask.cpp */ 274 private static final int MOVE_STATUS_COPY_FINISHED = 82; 275 276 private static final int VERSION_INIT = 1; 277 private static final int VERSION_ADD_PRIMARY = 2; 278 private static final int VERSION_FIX_PRIMARY = 3; 279 280 private static final String TAG_VOLUMES = "volumes"; 281 private static final String ATTR_VERSION = "version"; 282 private static final String ATTR_PRIMARY_STORAGE_UUID = "primaryStorageUuid"; 283 private static final String TAG_VOLUME = "volume"; 284 private static final String ATTR_TYPE = "type"; 285 private static final String ATTR_FS_UUID = "fsUuid"; 286 private static final String ATTR_PART_GUID = "partGuid"; 287 private static final String ATTR_NICKNAME = "nickname"; 288 private static final String ATTR_USER_FLAGS = "userFlags"; 289 private static final String ATTR_CREATED_MILLIS = "createdMillis"; 290 private static final String ATTR_LAST_SEEN_MILLIS = "lastSeenMillis"; 291 private static final String ATTR_LAST_TRIM_MILLIS = "lastTrimMillis"; 292 private static final String ATTR_LAST_BENCH_MILLIS = "lastBenchMillis"; 293 294 private static final String[] ALL_STORAGE_PERMISSIONS = { 295 Manifest.permission.READ_EXTERNAL_STORAGE, 296 Manifest.permission.WRITE_EXTERNAL_STORAGE 297 }; 298 299 private final AtomicFile mSettingsFile; 300 301 /** 302 * <em>Never</em> hold the lock while performing downcalls into vold, since 303 * unsolicited events can suddenly appear to update data structures. 304 */ 305 private final Object mLock = LockGuard.installNewLock(LockGuard.INDEX_STORAGE); 306 307 /** 308 * Similar to {@link #mLock}, never hold this lock while performing downcalls into vold. 309 * Also, never hold this while calling into PackageManagerService since it is used in callbacks 310 * from PackageManagerService. 311 * 312 * If both {@link #mLock} and this lock need to be held, {@link #mLock} should be acquired 313 * before this. 314 * 315 * Use -PL suffix for methods that need to called with this lock held. 316 */ 317 private final Object mPackagesLock = new Object(); 318 319 /** Set of users that we know are unlocked. */ 320 @GuardedBy("mLock") 321 private int[] mLocalUnlockedUsers = EmptyArray.INT; 322 /** Set of users that system knows are unlocked. */ 323 @GuardedBy("mLock") 324 private int[] mSystemUnlockedUsers = EmptyArray.INT; 325 326 /** Map from disk ID to disk */ 327 @GuardedBy("mLock") 328 private ArrayMap<String, DiskInfo> mDisks = new ArrayMap<>(); 329 /** Map from volume ID to disk */ 330 @GuardedBy("mLock") 331 private final ArrayMap<String, VolumeInfo> mVolumes = new ArrayMap<>(); 332 333 /** Map from UUID to record */ 334 @GuardedBy("mLock") 335 private ArrayMap<String, VolumeRecord> mRecords = new ArrayMap<>(); 336 @GuardedBy("mLock") 337 private String mPrimaryStorageUuid; 338 339 /** Map from disk ID to latches */ 340 @GuardedBy("mLock") 341 private ArrayMap<String, CountDownLatch> mDiskScanLatches = new ArrayMap<>(); 342 343 @GuardedBy("mLock") 344 private IPackageMoveObserver mMoveCallback; 345 @GuardedBy("mLock") 346 private String mMoveTargetUuid; 347 348 private volatile int mCurrentUserId = UserHandle.USER_SYSTEM; 349 350 /** Holding lock for AppFuse business */ 351 private final Object mAppFuseLock = new Object(); 352 353 @GuardedBy("mAppFuseLock") 354 private int mNextAppFuseName = 0; 355 356 @GuardedBy("mAppFuseLock") 357 private AppFuseBridge mAppFuseBridge = null; 358 359 private VolumeInfo findVolumeByIdOrThrow(String id) { 360 synchronized (mLock) { 361 final VolumeInfo vol = mVolumes.get(id); 362 if (vol != null) { 363 return vol; 364 } 365 } 366 throw new IllegalArgumentException("No volume found for ID " + id); 367 } 368 369 private String findVolumeIdForPathOrThrow(String path) { 370 synchronized (mLock) { 371 for (int i = 0; i < mVolumes.size(); i++) { 372 final VolumeInfo vol = mVolumes.valueAt(i); 373 if (vol.path != null && path.startsWith(vol.path)) { 374 return vol.id; 375 } 376 } 377 } 378 throw new IllegalArgumentException("No volume found for path " + path); 379 } 380 381 private VolumeRecord findRecordForPath(String path) { 382 synchronized (mLock) { 383 for (int i = 0; i < mVolumes.size(); i++) { 384 final VolumeInfo vol = mVolumes.valueAt(i); 385 if (vol.path != null && path.startsWith(vol.path)) { 386 return mRecords.get(vol.fsUuid); 387 } 388 } 389 } 390 return null; 391 } 392 393 private String scrubPath(String path) { 394 if (path.startsWith(Environment.getDataDirectory().getAbsolutePath())) { 395 return "internal"; 396 } 397 final VolumeRecord rec = findRecordForPath(path); 398 if (rec == null || rec.createdMillis == 0) { 399 return "unknown"; 400 } else { 401 return "ext:" + (int) ((System.currentTimeMillis() - rec.createdMillis) 402 / DateUtils.WEEK_IN_MILLIS) + "w"; 403 } 404 } 405 406 private @Nullable VolumeInfo findStorageForUuid(String volumeUuid) { 407 final StorageManager storage = mContext.getSystemService(StorageManager.class); 408 if (Objects.equals(StorageManager.UUID_PRIVATE_INTERNAL, volumeUuid)) { 409 return storage.findVolumeById(VolumeInfo.ID_EMULATED_INTERNAL); 410 } else if (Objects.equals(StorageManager.UUID_PRIMARY_PHYSICAL, volumeUuid)) { 411 return storage.getPrimaryPhysicalVolume(); 412 } else { 413 return storage.findEmulatedForPrivate(storage.findVolumeByUuid(volumeUuid)); 414 } 415 } 416 417 private boolean shouldBenchmark() { 418 final long benchInterval = Settings.Global.getLong(mContext.getContentResolver(), 419 Settings.Global.STORAGE_BENCHMARK_INTERVAL, DateUtils.WEEK_IN_MILLIS); 420 if (benchInterval == -1) { 421 return false; 422 } else if (benchInterval == 0) { 423 return true; 424 } 425 426 synchronized (mLock) { 427 for (int i = 0; i < mVolumes.size(); i++) { 428 final VolumeInfo vol = mVolumes.valueAt(i); 429 final VolumeRecord rec = mRecords.get(vol.fsUuid); 430 if (vol.isMountedWritable() && rec != null) { 431 final long benchAge = System.currentTimeMillis() - rec.lastBenchMillis; 432 if (benchAge >= benchInterval) { 433 return true; 434 } 435 } 436 } 437 return false; 438 } 439 } 440 441 private CountDownLatch findOrCreateDiskScanLatch(String diskId) { 442 synchronized (mLock) { 443 CountDownLatch latch = mDiskScanLatches.get(diskId); 444 if (latch == null) { 445 latch = new CountDownLatch(1); 446 mDiskScanLatches.put(diskId, latch); 447 } 448 return latch; 449 } 450 } 451 452 /** List of crypto types. 453 * These must match CRYPT_TYPE_XXX in cryptfs.h AND their 454 * corresponding commands in CommandListener.cpp */ 455 public static final String[] CRYPTO_TYPES 456 = { "password", "default", "pattern", "pin" }; 457 458 private final Context mContext; 459 private final ContentResolver mResolver; 460 461 private volatile IVold mVold; 462 private volatile IStoraged mStoraged; 463 464 private volatile boolean mBootCompleted = false; 465 private volatile boolean mDaemonConnected = false; 466 private volatile boolean mSecureKeyguardShowing = true; 467 468 private PackageManagerInternal mPmInternal; 469 470 private IPackageManager mIPackageManager; 471 private IAppOpsService mIAppOpsService; 472 473 private final Callbacks mCallbacks; 474 private final LockPatternUtils mLockPatternUtils; 475 476 /** 477 * The size of the crypto algorithm key in bits for OBB files. Currently 478 * Twofish is used which takes 128-bit keys. 479 */ 480 private static final int CRYPTO_ALGORITHM_KEY_SIZE = 128; 481 482 /** 483 * The number of times to run SHA1 in the PBKDF2 function for OBB files. 484 * 1024 is reasonably secure and not too slow. 485 */ 486 private static final int PBKDF2_HASH_ROUNDS = 1024; 487 488 /** 489 * Mounted OBB tracking information. Used to track the current state of all 490 * OBBs. 491 */ 492 final private Map<IBinder, List<ObbState>> mObbMounts = new HashMap<IBinder, List<ObbState>>(); 493 494 /** Map from raw paths to {@link ObbState}. */ 495 final private Map<String, ObbState> mObbPathToStateMap = new HashMap<String, ObbState>(); 496 497 // Not guarded by a lock. 498 private final StorageManagerInternalImpl mStorageManagerInternal 499 = new StorageManagerInternalImpl(); 500 501 class ObbState implements IBinder.DeathRecipient { 502 public ObbState(String rawPath, String canonicalPath, int callingUid, 503 IObbActionListener token, int nonce, String volId) { 504 this.rawPath = rawPath; 505 this.canonicalPath = canonicalPath; 506 this.ownerGid = UserHandle.getSharedAppGid(callingUid); 507 this.token = token; 508 this.nonce = nonce; 509 this.volId = volId; 510 } 511 512 final String rawPath; 513 final String canonicalPath; 514 515 final int ownerGid; 516 517 // Token of remote Binder caller 518 final IObbActionListener token; 519 520 // Identifier to pass back to the token 521 final int nonce; 522 523 String volId; 524 525 public IBinder getBinder() { 526 return token.asBinder(); 527 } 528 529 @Override 530 public void binderDied() { 531 ObbAction action = new UnmountObbAction(this, true); 532 mObbActionHandler.sendMessage(mObbActionHandler.obtainMessage(OBB_RUN_ACTION, action)); 533 } 534 535 public void link() throws RemoteException { 536 getBinder().linkToDeath(this, 0); 537 } 538 539 public void unlink() { 540 getBinder().unlinkToDeath(this, 0); 541 } 542 543 @Override 544 public String toString() { 545 StringBuilder sb = new StringBuilder("ObbState{"); 546 sb.append("rawPath=").append(rawPath); 547 sb.append(",canonicalPath=").append(canonicalPath); 548 sb.append(",ownerGid=").append(ownerGid); 549 sb.append(",token=").append(token); 550 sb.append(",binder=").append(getBinder()); 551 sb.append(",volId=").append(volId); 552 sb.append('}'); 553 return sb.toString(); 554 } 555 } 556 557 // OBB Action Handler 558 final private ObbActionHandler mObbActionHandler; 559 560 // OBB action handler messages 561 private static final int OBB_RUN_ACTION = 1; 562 private static final int OBB_FLUSH_MOUNT_STATE = 2; 563 564 // Last fstrim operation tracking 565 private static final String LAST_FSTRIM_FILE = "last-fstrim"; 566 private final File mLastMaintenanceFile; 567 private long mLastMaintenance; 568 569 // Handler messages 570 private static final int H_SYSTEM_READY = 1; 571 private static final int H_DAEMON_CONNECTED = 2; 572 private static final int H_SHUTDOWN = 3; 573 private static final int H_FSTRIM = 4; 574 private static final int H_VOLUME_MOUNT = 5; 575 private static final int H_VOLUME_BROADCAST = 6; 576 private static final int H_INTERNAL_BROADCAST = 7; 577 private static final int H_VOLUME_UNMOUNT = 8; 578 private static final int H_PARTITION_FORGET = 9; 579 private static final int H_RESET = 10; 580 private static final int H_RUN_IDLE_MAINT = 11; 581 private static final int H_ABORT_IDLE_MAINT = 12; 582 private static final int H_BOOT_COMPLETED = 13; 583 private static final int H_COMPLETE_UNLOCK_USER = 14; 584 585 class StorageManagerServiceHandler extends Handler { 586 public StorageManagerServiceHandler(Looper looper) { 587 super(looper); 588 } 589 590 @Override 591 public void handleMessage(Message msg) { 592 switch (msg.what) { 593 case H_SYSTEM_READY: { 594 handleSystemReady(); 595 break; 596 } 597 case H_BOOT_COMPLETED: { 598 handleBootCompleted(); 599 break; 600 } 601 case H_DAEMON_CONNECTED: { 602 handleDaemonConnected(); 603 break; 604 } 605 case H_FSTRIM: { 606 Slog.i(TAG, "Running fstrim idle maintenance"); 607 608 // Remember when we kicked it off 609 try { 610 mLastMaintenance = System.currentTimeMillis(); 611 mLastMaintenanceFile.setLastModified(mLastMaintenance); 612 } catch (Exception e) { 613 Slog.e(TAG, "Unable to record last fstrim!"); 614 } 615 616 // TODO: Reintroduce shouldBenchmark() test 617 fstrim(0, null); 618 619 // invoke the completion callback, if any 620 // TODO: fstrim is non-blocking, so remove this useless callback 621 Runnable callback = (Runnable) msg.obj; 622 if (callback != null) { 623 callback.run(); 624 } 625 break; 626 } 627 case H_SHUTDOWN: { 628 final IStorageShutdownObserver obs = (IStorageShutdownObserver) msg.obj; 629 boolean success = false; 630 try { 631 mVold.shutdown(); 632 success = true; 633 } catch (Exception e) { 634 Slog.wtf(TAG, e); 635 } 636 if (obs != null) { 637 try { 638 obs.onShutDownComplete(success ? 0 : -1); 639 } catch (Exception ignored) { 640 } 641 } 642 break; 643 } 644 case H_VOLUME_MOUNT: { 645 final VolumeInfo vol = (VolumeInfo) msg.obj; 646 if (isMountDisallowed(vol)) { 647 Slog.i(TAG, "Ignoring mount " + vol.getId() + " due to policy"); 648 break; 649 } 650 mount(vol); 651 break; 652 } 653 case H_VOLUME_UNMOUNT: { 654 final VolumeInfo vol = (VolumeInfo) msg.obj; 655 unmount(vol); 656 break; 657 } 658 case H_VOLUME_BROADCAST: { 659 final StorageVolume userVol = (StorageVolume) msg.obj; 660 final String envState = userVol.getState(); 661 Slog.d(TAG, "Volume " + userVol.getId() + " broadcasting " + envState + " to " 662 + userVol.getOwner()); 663 664 final String action = VolumeInfo.getBroadcastForEnvironment(envState); 665 if (action != null) { 666 final Intent intent = new Intent(action, 667 Uri.fromFile(userVol.getPathFile())); 668 intent.putExtra(StorageVolume.EXTRA_STORAGE_VOLUME, userVol); 669 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT 670 | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND); 671 mContext.sendBroadcastAsUser(intent, userVol.getOwner()); 672 } 673 break; 674 } 675 case H_INTERNAL_BROADCAST: { 676 // Internal broadcasts aimed at system components, not for 677 // third-party apps. 678 final Intent intent = (Intent) msg.obj; 679 mContext.sendBroadcastAsUser(intent, UserHandle.ALL, 680 android.Manifest.permission.WRITE_MEDIA_STORAGE); 681 break; 682 } 683 case H_PARTITION_FORGET: { 684 final VolumeRecord rec = (VolumeRecord) msg.obj; 685 forgetPartition(rec.partGuid, rec.fsUuid); 686 break; 687 } 688 case H_RESET: { 689 resetIfBootedAndConnected(); 690 break; 691 } 692 case H_RUN_IDLE_MAINT: { 693 Slog.i(TAG, "Running idle maintenance"); 694 runIdleMaint((Runnable)msg.obj); 695 break; 696 } 697 case H_ABORT_IDLE_MAINT: { 698 Slog.i(TAG, "Aborting idle maintenance"); 699 abortIdleMaint((Runnable)msg.obj); 700 break; 701 } 702 case H_COMPLETE_UNLOCK_USER: { 703 completeUnlockUser((int) msg.obj); 704 break; 705 } 706 } 707 } 708 } 709 710 private final Handler mHandler; 711 712 private BroadcastReceiver mUserReceiver = new BroadcastReceiver() { 713 @Override 714 public void onReceive(Context context, Intent intent) { 715 final String action = intent.getAction(); 716 final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1); 717 Preconditions.checkArgument(userId >= 0); 718 719 try { 720 if (Intent.ACTION_USER_ADDED.equals(action)) { 721 final UserManager um = mContext.getSystemService(UserManager.class); 722 final int userSerialNumber = um.getUserSerialNumber(userId); 723 mVold.onUserAdded(userId, userSerialNumber); 724 } else if (Intent.ACTION_USER_REMOVED.equals(action)) { 725 synchronized (mVolumes) { 726 final int size = mVolumes.size(); 727 for (int i = 0; i < size; i++) { 728 final VolumeInfo vol = mVolumes.valueAt(i); 729 if (vol.mountUserId == userId) { 730 vol.mountUserId = UserHandle.USER_NULL; 731 mHandler.obtainMessage(H_VOLUME_UNMOUNT, vol).sendToTarget(); 732 } 733 } 734 } 735 mVold.onUserRemoved(userId); 736 } 737 } catch (Exception e) { 738 Slog.wtf(TAG, e); 739 } 740 } 741 }; 742 743 private void waitForLatch(CountDownLatch latch, String condition, long timeoutMillis) 744 throws TimeoutException { 745 final long startMillis = SystemClock.elapsedRealtime(); 746 while (true) { 747 try { 748 if (latch.await(5000, TimeUnit.MILLISECONDS)) { 749 return; 750 } else { 751 Slog.w(TAG, "Thread " + Thread.currentThread().getName() 752 + " still waiting for " + condition + "..."); 753 } 754 } catch (InterruptedException e) { 755 Slog.w(TAG, "Interrupt while waiting for " + condition); 756 } 757 if (timeoutMillis > 0 && SystemClock.elapsedRealtime() > startMillis + timeoutMillis) { 758 throw new TimeoutException("Thread " + Thread.currentThread().getName() 759 + " gave up waiting for " + condition + " after " + timeoutMillis + "ms"); 760 } 761 } 762 } 763 764 private void handleSystemReady() { 765 // Start scheduling nominally-daily fstrim operations 766 MountServiceIdler.scheduleIdlePass(mContext); 767 768 // Toggle zram-enable system property in response to settings 769 mContext.getContentResolver().registerContentObserver( 770 Settings.Global.getUriFor(Settings.Global.ZRAM_ENABLED), 771 false /*notifyForDescendants*/, 772 new ContentObserver(null /* current thread */) { 773 @Override 774 public void onChange(boolean selfChange) { 775 refreshZramSettings(); 776 } 777 }); 778 refreshZramSettings(); 779 780 // Schedule zram writeback unless zram is disabled by persist.sys.zram_enabled 781 String zramPropValue = SystemProperties.get(ZRAM_ENABLED_PROPERTY); 782 if (!zramPropValue.equals("0") 783 && mContext.getResources().getBoolean( 784 com.android.internal.R.bool.config_zramWriteback)) { 785 ZramWriteback.scheduleZramWriteback(mContext); 786 } 787 // Toggle isolated-enable system property in response to settings 788 mContext.getContentResolver().registerContentObserver( 789 Settings.Global.getUriFor(Settings.Global.ISOLATED_STORAGE_REMOTE), 790 false /*notifyForDescendants*/, 791 new ContentObserver(null /* current thread */) { 792 @Override 793 public void onChange(boolean selfChange) { 794 refreshIsolatedStorageSettings(); 795 } 796 }); 797 // For now, simply clone property when it changes 798 DeviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_STORAGE, 799 mContext.getMainExecutor(), (properties) -> { 800 refreshIsolatedStorageSettings(); 801 }); 802 refreshIsolatedStorageSettings(); 803 } 804 805 /** 806 * Update the zram_enabled system property (which init reads to 807 * decide whether to enable zram) to reflect the zram_enabled 808 * preference (which we can change for experimentation purposes). 809 */ 810 private void refreshZramSettings() { 811 String propertyValue = SystemProperties.get(ZRAM_ENABLED_PROPERTY); 812 if ("".equals(propertyValue)) { 813 return; // System doesn't have zram toggling support 814 } 815 String desiredPropertyValue = 816 Settings.Global.getInt(mContext.getContentResolver(), 817 Settings.Global.ZRAM_ENABLED, 818 1) != 0 819 ? "1" : "0"; 820 if (!desiredPropertyValue.equals(propertyValue)) { 821 // Avoid redundant disk writes by setting only if we're 822 // changing the property value. There's no race: we're the 823 // sole writer. 824 SystemProperties.set(ZRAM_ENABLED_PROPERTY, desiredPropertyValue); 825 // Schedule writeback only if zram is being enabled. 826 if (desiredPropertyValue.equals("1") 827 && mContext.getResources().getBoolean( 828 com.android.internal.R.bool.config_zramWriteback)) { 829 ZramWriteback.scheduleZramWriteback(mContext); 830 } 831 } 832 } 833 834 private void refreshIsolatedStorageSettings() { 835 // Always copy value from newer DeviceConfig location 836 Settings.Global.putString(mResolver, 837 Settings.Global.ISOLATED_STORAGE_REMOTE, 838 DeviceConfig.getProperty(DeviceConfig.NAMESPACE_STORAGE, ISOLATED_STORAGE_ENABLED)); 839 840 final int local = Settings.Global.getInt(mContext.getContentResolver(), 841 Settings.Global.ISOLATED_STORAGE_LOCAL, 0); 842 final int remote = Settings.Global.getInt(mContext.getContentResolver(), 843 Settings.Global.ISOLATED_STORAGE_REMOTE, 0); 844 845 // Walk down precedence chain; we prefer local settings first, then 846 // remote settings, before finally falling back to hard-coded default. 847 final boolean res; 848 if (local == -1) { 849 res = false; 850 } else if (local == 1) { 851 res = true; 852 } else if (remote == -1) { 853 res = false; 854 } else if (remote == 1) { 855 res = true; 856 } else { 857 res = true; 858 } 859 860 Slog.d(TAG, "Isolated storage local flag " + local + " and remote flag " 861 + remote + " resolved to " + res); 862 SystemProperties.set(StorageManager.PROP_ISOLATED_STORAGE, Boolean.toString(res)); 863 } 864 865 /** 866 * MediaProvider has a ton of code that makes assumptions about storage 867 * paths never changing, so we outright kill them to pick up new state. 868 */ 869 @Deprecated 870 private void killMediaProvider(List<UserInfo> users) { 871 if (users == null) return; 872 873 final long token = Binder.clearCallingIdentity(); 874 try { 875 for (UserInfo user : users) { 876 // System user does not have media provider, so skip. 877 if (user.isSystemOnly()) continue; 878 879 final ProviderInfo provider = mPmInternal.resolveContentProvider( 880 MediaStore.AUTHORITY, PackageManager.MATCH_DIRECT_BOOT_AWARE 881 | PackageManager.MATCH_DIRECT_BOOT_UNAWARE, 882 user.id); 883 if (provider != null) { 884 final IActivityManager am = ActivityManager.getService(); 885 try { 886 am.killApplication(provider.applicationInfo.packageName, 887 UserHandle.getAppId(provider.applicationInfo.uid), 888 UserHandle.USER_ALL, "vold reset"); 889 // We only need to run this once. It will kill all users' media processes. 890 break; 891 } catch (RemoteException e) { 892 } 893 } 894 } 895 } finally { 896 Binder.restoreCallingIdentity(token); 897 } 898 } 899 900 @GuardedBy("mLock") 901 private void addInternalVolumeLocked() { 902 // Create a stub volume that represents internal storage 903 final VolumeInfo internal = new VolumeInfo(VolumeInfo.ID_PRIVATE_INTERNAL, 904 VolumeInfo.TYPE_PRIVATE, null, null); 905 internal.state = VolumeInfo.STATE_MOUNTED; 906 internal.path = Environment.getDataDirectory().getAbsolutePath(); 907 mVolumes.put(internal.id, internal); 908 } 909 910 private void initIfBootedAndConnected() { 911 Slog.d(TAG, "Thinking about init, mBootCompleted=" + mBootCompleted 912 + ", mDaemonConnected=" + mDaemonConnected); 913 if (mBootCompleted && mDaemonConnected 914 && !StorageManager.isFileEncryptedNativeOnly()) { 915 // When booting a device without native support, make sure that our 916 // user directories are locked or unlocked based on the current 917 // emulation status. 918 final boolean initLocked = StorageManager.isFileEncryptedEmulatedOnly(); 919 Slog.d(TAG, "Setting up emulation state, initlocked=" + initLocked); 920 final List<UserInfo> users = mContext.getSystemService(UserManager.class).getUsers(); 921 for (UserInfo user : users) { 922 try { 923 if (initLocked) { 924 mVold.lockUserKey(user.id); 925 } else { 926 mVold.unlockUserKey(user.id, user.serialNumber, encodeBytes(null), 927 encodeBytes(null)); 928 } 929 } catch (Exception e) { 930 Slog.wtf(TAG, e); 931 } 932 } 933 } 934 } 935 936 private void resetIfBootedAndConnected() { 937 Slog.d(TAG, "Thinking about reset, mBootCompleted=" + mBootCompleted 938 + ", mDaemonConnected=" + mDaemonConnected); 939 if (mBootCompleted && mDaemonConnected) { 940 final List<UserInfo> users = mContext.getSystemService(UserManager.class).getUsers(); 941 killMediaProvider(users); 942 943 final int[] systemUnlockedUsers; 944 synchronized (mLock) { 945 systemUnlockedUsers = mSystemUnlockedUsers; 946 947 mDisks.clear(); 948 mVolumes.clear(); 949 950 addInternalVolumeLocked(); 951 } 952 953 try { 954 mVold.reset(); 955 956 // Tell vold about all existing and started users 957 for (UserInfo user : users) { 958 mVold.onUserAdded(user.id, user.serialNumber); 959 } 960 for (int userId : systemUnlockedUsers) { 961 mVold.onUserStarted(userId); 962 mStoraged.onUserStarted(userId); 963 } 964 mVold.onSecureKeyguardStateChanged(mSecureKeyguardShowing); 965 mStorageManagerInternal.onReset(mVold); 966 } catch (Exception e) { 967 Slog.wtf(TAG, e); 968 } 969 } 970 } 971 972 private void onUnlockUser(int userId) { 973 Slog.d(TAG, "onUnlockUser " + userId); 974 975 // We purposefully block here to make sure that user-specific 976 // staging area is ready so it's ready for zygote-forked apps to 977 // bind mount against. 978 try { 979 mVold.onUserStarted(userId); 980 mStoraged.onUserStarted(userId); 981 } catch (Exception e) { 982 Slog.wtf(TAG, e); 983 } 984 985 mHandler.obtainMessage(H_COMPLETE_UNLOCK_USER, userId).sendToTarget(); 986 } 987 988 private void completeUnlockUser(int userId) { 989 // If user 0 has completed unlock, perform a one-time migration of legacy obb data 990 // to its new location. This may take time depending on the size of the data to be copied 991 // so it's done on the StorageManager handler thread. 992 if (userId == 0) { 993 mPmInternal.migrateLegacyObbData(); 994 } 995 996 // Record user as started so newly mounted volumes kick off events 997 // correctly, then synthesize events for any already-mounted volumes. 998 synchronized (mLock) { 999 for (int i = 0; i < mVolumes.size(); i++) { 1000 final VolumeInfo vol = mVolumes.valueAt(i); 1001 if (vol.isVisibleForRead(userId) && vol.isMountedReadable()) { 1002 final StorageVolume userVol = vol.buildStorageVolume(mContext, userId, false); 1003 mHandler.obtainMessage(H_VOLUME_BROADCAST, userVol).sendToTarget(); 1004 1005 final String envState = VolumeInfo.getEnvironmentForState(vol.getState()); 1006 mCallbacks.notifyStorageStateChanged(userVol.getPath(), envState, envState); 1007 } 1008 } 1009 mSystemUnlockedUsers = ArrayUtils.appendInt(mSystemUnlockedUsers, userId); 1010 } 1011 } 1012 1013 private void onCleanupUser(int userId) { 1014 Slog.d(TAG, "onCleanupUser " + userId); 1015 1016 try { 1017 mVold.onUserStopped(userId); 1018 mStoraged.onUserStopped(userId); 1019 } catch (Exception e) { 1020 Slog.wtf(TAG, e); 1021 } 1022 1023 synchronized (mLock) { 1024 mSystemUnlockedUsers = ArrayUtils.removeInt(mSystemUnlockedUsers, userId); 1025 } 1026 } 1027 1028 private boolean supportsBlockCheckpoint() throws RemoteException { 1029 enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS); 1030 return mVold.supportsBlockCheckpoint(); 1031 } 1032 1033 @Override 1034 public void onAwakeStateChanged(boolean isAwake) { 1035 // Ignored 1036 } 1037 1038 @Override 1039 public void onKeyguardStateChanged(boolean isShowing) { 1040 // Push down current secure keyguard status so that we ignore malicious 1041 // USB devices while locked. 1042 mSecureKeyguardShowing = isShowing 1043 && mContext.getSystemService(KeyguardManager.class).isDeviceSecure(); 1044 try { 1045 mVold.onSecureKeyguardStateChanged(mSecureKeyguardShowing); 1046 } catch (Exception e) { 1047 Slog.wtf(TAG, e); 1048 } 1049 } 1050 1051 void runIdleMaintenance(Runnable callback) { 1052 mHandler.sendMessage(mHandler.obtainMessage(H_FSTRIM, callback)); 1053 } 1054 1055 // Binder entry point for kicking off an immediate fstrim 1056 @Override 1057 public void runMaintenance() { 1058 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS); 1059 runIdleMaintenance(null); 1060 } 1061 1062 @Override 1063 public long lastMaintenance() { 1064 return mLastMaintenance; 1065 } 1066 1067 public void onDaemonConnected() { 1068 mDaemonConnected = true; 1069 mHandler.obtainMessage(H_DAEMON_CONNECTED).sendToTarget(); 1070 } 1071 1072 private void handleDaemonConnected() { 1073 initIfBootedAndConnected(); 1074 resetIfBootedAndConnected(); 1075 1076 // On an encrypted device we can't see system properties yet, so pull 1077 // the system locale out of the mount service. 1078 if ("".equals(VoldProperties.encrypt_progress().orElse(""))) { 1079 copyLocaleFromMountService(); 1080 } 1081 } 1082 1083 private void copyLocaleFromMountService() { 1084 String systemLocale; 1085 try { 1086 systemLocale = getField(StorageManager.SYSTEM_LOCALE_KEY); 1087 } catch (RemoteException e) { 1088 return; 1089 } 1090 if (TextUtils.isEmpty(systemLocale)) { 1091 return; 1092 } 1093 1094 Slog.d(TAG, "Got locale " + systemLocale + " from mount service"); 1095 Locale locale = Locale.forLanguageTag(systemLocale); 1096 Configuration config = new Configuration(); 1097 config.setLocale(locale); 1098 try { 1099 ActivityManager.getService().updatePersistentConfiguration(config); 1100 } catch (RemoteException e) { 1101 Slog.e(TAG, "Error setting system locale from mount service", e); 1102 } 1103 1104 // Temporary workaround for http://b/17945169. 1105 Slog.d(TAG, "Setting system properties to " + systemLocale + " from mount service"); 1106 SystemProperties.set("persist.sys.locale", locale.toLanguageTag()); 1107 } 1108 1109 private final IVoldListener mListener = new IVoldListener.Stub() { 1110 @Override 1111 public void onDiskCreated(String diskId, int flags) { 1112 synchronized (mLock) { 1113 final String value = SystemProperties.get(StorageManager.PROP_ADOPTABLE); 1114 switch (value) { 1115 case "force_on": 1116 flags |= DiskInfo.FLAG_ADOPTABLE; 1117 break; 1118 case "force_off": 1119 flags &= ~DiskInfo.FLAG_ADOPTABLE; 1120 break; 1121 } 1122 mDisks.put(diskId, new DiskInfo(diskId, flags)); 1123 } 1124 } 1125 1126 @Override 1127 public void onDiskScanned(String diskId) { 1128 synchronized (mLock) { 1129 final DiskInfo disk = mDisks.get(diskId); 1130 if (disk != null) { 1131 onDiskScannedLocked(disk); 1132 } 1133 } 1134 } 1135 1136 @Override 1137 public void onDiskMetadataChanged(String diskId, long sizeBytes, String label, 1138 String sysPath) { 1139 synchronized (mLock) { 1140 final DiskInfo disk = mDisks.get(diskId); 1141 if (disk != null) { 1142 disk.size = sizeBytes; 1143 disk.label = label; 1144 disk.sysPath = sysPath; 1145 } 1146 } 1147 } 1148 1149 @Override 1150 public void onDiskDestroyed(String diskId) { 1151 synchronized (mLock) { 1152 final DiskInfo disk = mDisks.remove(diskId); 1153 if (disk != null) { 1154 mCallbacks.notifyDiskDestroyed(disk); 1155 } 1156 } 1157 } 1158 1159 @Override 1160 public void onVolumeCreated(String volId, int type, String diskId, String partGuid) { 1161 synchronized (mLock) { 1162 final DiskInfo disk = mDisks.get(diskId); 1163 final VolumeInfo vol = new VolumeInfo(volId, type, disk, partGuid); 1164 mVolumes.put(volId, vol); 1165 onVolumeCreatedLocked(vol); 1166 } 1167 } 1168 1169 @Override 1170 public void onVolumeStateChanged(String volId, int state) { 1171 synchronized (mLock) { 1172 final VolumeInfo vol = mVolumes.get(volId); 1173 if (vol != null) { 1174 final int oldState = vol.state; 1175 final int newState = state; 1176 vol.state = newState; 1177 onVolumeStateChangedLocked(vol, oldState, newState); 1178 } 1179 } 1180 } 1181 1182 @Override 1183 public void onVolumeMetadataChanged(String volId, String fsType, String fsUuid, 1184 String fsLabel) { 1185 synchronized (mLock) { 1186 final VolumeInfo vol = mVolumes.get(volId); 1187 if (vol != null) { 1188 vol.fsType = fsType; 1189 vol.fsUuid = fsUuid; 1190 vol.fsLabel = fsLabel; 1191 } 1192 } 1193 } 1194 1195 @Override 1196 public void onVolumePathChanged(String volId, String path) { 1197 synchronized (mLock) { 1198 final VolumeInfo vol = mVolumes.get(volId); 1199 if (vol != null) { 1200 vol.path = path; 1201 } 1202 } 1203 } 1204 1205 @Override 1206 public void onVolumeInternalPathChanged(String volId, String internalPath) { 1207 synchronized (mLock) { 1208 final VolumeInfo vol = mVolumes.get(volId); 1209 if (vol != null) { 1210 vol.internalPath = internalPath; 1211 } 1212 } 1213 } 1214 1215 @Override 1216 public void onVolumeDestroyed(String volId) { 1217 synchronized (mLock) { 1218 mVolumes.remove(volId); 1219 } 1220 } 1221 }; 1222 1223 @GuardedBy("mLock") 1224 private void onDiskScannedLocked(DiskInfo disk) { 1225 int volumeCount = 0; 1226 for (int i = 0; i < mVolumes.size(); i++) { 1227 final VolumeInfo vol = mVolumes.valueAt(i); 1228 if (Objects.equals(disk.id, vol.getDiskId())) { 1229 volumeCount++; 1230 } 1231 } 1232 1233 final Intent intent = new Intent(DiskInfo.ACTION_DISK_SCANNED); 1234 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT 1235 | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND); 1236 intent.putExtra(DiskInfo.EXTRA_DISK_ID, disk.id); 1237 intent.putExtra(DiskInfo.EXTRA_VOLUME_COUNT, volumeCount); 1238 mHandler.obtainMessage(H_INTERNAL_BROADCAST, intent).sendToTarget(); 1239 1240 final CountDownLatch latch = mDiskScanLatches.remove(disk.id); 1241 if (latch != null) { 1242 latch.countDown(); 1243 } 1244 1245 disk.volumeCount = volumeCount; 1246 mCallbacks.notifyDiskScanned(disk, volumeCount); 1247 } 1248 1249 @GuardedBy("mLock") 1250 private void onVolumeCreatedLocked(VolumeInfo vol) { 1251 if (mPmInternal.isOnlyCoreApps()) { 1252 Slog.d(TAG, "System booted in core-only mode; ignoring volume " + vol.getId()); 1253 return; 1254 } 1255 1256 if (vol.type == VolumeInfo.TYPE_EMULATED) { 1257 final StorageManager storage = mContext.getSystemService(StorageManager.class); 1258 final VolumeInfo privateVol = storage.findPrivateForEmulated(vol); 1259 1260 if (Objects.equals(StorageManager.UUID_PRIVATE_INTERNAL, mPrimaryStorageUuid) 1261 && VolumeInfo.ID_PRIVATE_INTERNAL.equals(privateVol.id)) { 1262 Slog.v(TAG, "Found primary storage at " + vol); 1263 vol.mountFlags |= VolumeInfo.MOUNT_FLAG_PRIMARY; 1264 vol.mountFlags |= VolumeInfo.MOUNT_FLAG_VISIBLE; 1265 mHandler.obtainMessage(H_VOLUME_MOUNT, vol).sendToTarget(); 1266 1267 } else if (Objects.equals(privateVol.fsUuid, mPrimaryStorageUuid)) { 1268 Slog.v(TAG, "Found primary storage at " + vol); 1269 vol.mountFlags |= VolumeInfo.MOUNT_FLAG_PRIMARY; 1270 vol.mountFlags |= VolumeInfo.MOUNT_FLAG_VISIBLE; 1271 mHandler.obtainMessage(H_VOLUME_MOUNT, vol).sendToTarget(); 1272 } 1273 1274 } else if (vol.type == VolumeInfo.TYPE_PUBLIC) { 1275 // TODO: only look at first public partition 1276 if (Objects.equals(StorageManager.UUID_PRIMARY_PHYSICAL, mPrimaryStorageUuid) 1277 && vol.disk.isDefaultPrimary()) { 1278 Slog.v(TAG, "Found primary storage at " + vol); 1279 vol.mountFlags |= VolumeInfo.MOUNT_FLAG_PRIMARY; 1280 vol.mountFlags |= VolumeInfo.MOUNT_FLAG_VISIBLE; 1281 } 1282 1283 // Adoptable public disks are visible to apps, since they meet 1284 // public API requirement of being in a stable location. 1285 if (vol.disk.isAdoptable()) { 1286 vol.mountFlags |= VolumeInfo.MOUNT_FLAG_VISIBLE; 1287 } 1288 1289 vol.mountUserId = mCurrentUserId; 1290 mHandler.obtainMessage(H_VOLUME_MOUNT, vol).sendToTarget(); 1291 1292 } else if (vol.type == VolumeInfo.TYPE_PRIVATE) { 1293 mHandler.obtainMessage(H_VOLUME_MOUNT, vol).sendToTarget(); 1294 1295 } else if (vol.type == VolumeInfo.TYPE_STUB) { 1296 vol.mountUserId = mCurrentUserId; 1297 mHandler.obtainMessage(H_VOLUME_MOUNT, vol).sendToTarget(); 1298 } else { 1299 Slog.d(TAG, "Skipping automatic mounting of " + vol); 1300 } 1301 } 1302 1303 private boolean isBroadcastWorthy(VolumeInfo vol) { 1304 switch (vol.getType()) { 1305 case VolumeInfo.TYPE_PRIVATE: 1306 case VolumeInfo.TYPE_PUBLIC: 1307 case VolumeInfo.TYPE_EMULATED: 1308 case VolumeInfo.TYPE_STUB: 1309 break; 1310 default: 1311 return false; 1312 } 1313 1314 switch (vol.getState()) { 1315 case VolumeInfo.STATE_MOUNTED: 1316 case VolumeInfo.STATE_MOUNTED_READ_ONLY: 1317 case VolumeInfo.STATE_EJECTING: 1318 case VolumeInfo.STATE_UNMOUNTED: 1319 case VolumeInfo.STATE_UNMOUNTABLE: 1320 case VolumeInfo.STATE_BAD_REMOVAL: 1321 break; 1322 default: 1323 return false; 1324 } 1325 1326 return true; 1327 } 1328 1329 @GuardedBy("mLock") 1330 private void onVolumeStateChangedLocked(VolumeInfo vol, int oldState, int newState) { 1331 // Remember that we saw this volume so we're ready to accept user 1332 // metadata, or so we can annoy them when a private volume is ejected 1333 if (!TextUtils.isEmpty(vol.fsUuid)) { 1334 VolumeRecord rec = mRecords.get(vol.fsUuid); 1335 if (rec == null) { 1336 rec = new VolumeRecord(vol.type, vol.fsUuid); 1337 rec.partGuid = vol.partGuid; 1338 rec.createdMillis = System.currentTimeMillis(); 1339 if (vol.type == VolumeInfo.TYPE_PRIVATE) { 1340 rec.nickname = vol.disk.getDescription(); 1341 } 1342 mRecords.put(rec.fsUuid, rec); 1343 } else { 1344 // Handle upgrade case where we didn't store partition GUID 1345 if (TextUtils.isEmpty(rec.partGuid)) { 1346 rec.partGuid = vol.partGuid; 1347 } 1348 } 1349 1350 rec.lastSeenMillis = System.currentTimeMillis(); 1351 writeSettingsLocked(); 1352 } 1353 1354 mCallbacks.notifyVolumeStateChanged(vol, oldState, newState); 1355 1356 // Do not broadcast before boot has completed to avoid launching the 1357 // processes that receive the intent unnecessarily. 1358 if (mBootCompleted && isBroadcastWorthy(vol)) { 1359 final Intent intent = new Intent(VolumeInfo.ACTION_VOLUME_STATE_CHANGED); 1360 intent.putExtra(VolumeInfo.EXTRA_VOLUME_ID, vol.id); 1361 intent.putExtra(VolumeInfo.EXTRA_VOLUME_STATE, newState); 1362 intent.putExtra(VolumeRecord.EXTRA_FS_UUID, vol.fsUuid); 1363 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT 1364 | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND); 1365 mHandler.obtainMessage(H_INTERNAL_BROADCAST, intent).sendToTarget(); 1366 } 1367 1368 final String oldStateEnv = VolumeInfo.getEnvironmentForState(oldState); 1369 final String newStateEnv = VolumeInfo.getEnvironmentForState(newState); 1370 1371 if (!Objects.equals(oldStateEnv, newStateEnv)) { 1372 // Kick state changed event towards all started users. Any users 1373 // started after this point will trigger additional 1374 // user-specific broadcasts. 1375 for (int userId : mSystemUnlockedUsers) { 1376 if (vol.isVisibleForRead(userId)) { 1377 final StorageVolume userVol = vol.buildStorageVolume(mContext, userId, false); 1378 mHandler.obtainMessage(H_VOLUME_BROADCAST, userVol).sendToTarget(); 1379 1380 mCallbacks.notifyStorageStateChanged(userVol.getPath(), oldStateEnv, 1381 newStateEnv); 1382 } 1383 } 1384 } 1385 1386 if ((vol.type == VolumeInfo.TYPE_PUBLIC || vol.type == VolumeInfo.TYPE_STUB) 1387 && vol.state == VolumeInfo.STATE_EJECTING) { 1388 // TODO: this should eventually be handled by new ObbVolume state changes 1389 /* 1390 * Some OBBs might have been unmounted when this volume was 1391 * unmounted, so send a message to the handler to let it know to 1392 * remove those from the list of mounted OBBS. 1393 */ 1394 mObbActionHandler.sendMessage(mObbActionHandler.obtainMessage( 1395 OBB_FLUSH_MOUNT_STATE, vol.path)); 1396 } 1397 maybeLogMediaMount(vol, newState); 1398 } 1399 1400 private void maybeLogMediaMount(VolumeInfo vol, int newState) { 1401 if (!SecurityLog.isLoggingEnabled()) { 1402 return; 1403 } 1404 1405 final DiskInfo disk = vol.getDisk(); 1406 if (disk == null || (disk.flags & (DiskInfo.FLAG_SD | DiskInfo.FLAG_USB)) == 0) { 1407 return; 1408 } 1409 1410 // Sometimes there is a newline character. 1411 final String label = disk.label != null ? disk.label.trim() : ""; 1412 1413 if (newState == VolumeInfo.STATE_MOUNTED 1414 || newState == VolumeInfo.STATE_MOUNTED_READ_ONLY) { 1415 SecurityLog.writeEvent(SecurityLog.TAG_MEDIA_MOUNT, vol.path, label); 1416 } else if (newState == VolumeInfo.STATE_UNMOUNTED 1417 || newState == VolumeInfo.STATE_BAD_REMOVAL) { 1418 SecurityLog.writeEvent(SecurityLog.TAG_MEDIA_UNMOUNT, vol.path, label); 1419 } 1420 } 1421 1422 @GuardedBy("mLock") 1423 private void onMoveStatusLocked(int status) { 1424 if (mMoveCallback == null) { 1425 Slog.w(TAG, "Odd, status but no move requested"); 1426 return; 1427 } 1428 1429 // TODO: estimate remaining time 1430 try { 1431 mMoveCallback.onStatusChanged(-1, status, -1); 1432 } catch (RemoteException ignored) { 1433 } 1434 1435 // We've finished copying and we're about to clean up old data, so 1436 // remember that move was successful if we get rebooted 1437 if (status == MOVE_STATUS_COPY_FINISHED) { 1438 Slog.d(TAG, "Move to " + mMoveTargetUuid + " copy phase finshed; persisting"); 1439 1440 mPrimaryStorageUuid = mMoveTargetUuid; 1441 writeSettingsLocked(); 1442 } 1443 1444 if (PackageManager.isMoveStatusFinished(status)) { 1445 Slog.d(TAG, "Move to " + mMoveTargetUuid + " finished with status " + status); 1446 1447 mMoveCallback = null; 1448 mMoveTargetUuid = null; 1449 } 1450 } 1451 1452 private void enforcePermission(String perm) { 1453 mContext.enforceCallingOrSelfPermission(perm, perm); 1454 } 1455 1456 /** 1457 * Decide if volume is mountable per device policies. 1458 */ 1459 private boolean isMountDisallowed(VolumeInfo vol) { 1460 UserManager userManager = mContext.getSystemService(UserManager.class); 1461 1462 boolean isUsbRestricted = false; 1463 if (vol.disk != null && vol.disk.isUsb()) { 1464 isUsbRestricted = userManager.hasUserRestriction(UserManager.DISALLOW_USB_FILE_TRANSFER, 1465 Binder.getCallingUserHandle()); 1466 } 1467 1468 boolean isTypeRestricted = false; 1469 if (vol.type == VolumeInfo.TYPE_PUBLIC || vol.type == VolumeInfo.TYPE_PRIVATE 1470 || vol.type == VolumeInfo.TYPE_STUB) { 1471 isTypeRestricted = userManager 1472 .hasUserRestriction(UserManager.DISALLOW_MOUNT_PHYSICAL_MEDIA, 1473 Binder.getCallingUserHandle()); 1474 } 1475 1476 return isUsbRestricted || isTypeRestricted; 1477 } 1478 1479 private void enforceAdminUser() { 1480 UserManager um = (UserManager) mContext.getSystemService(Context.USER_SERVICE); 1481 final int callingUserId = UserHandle.getCallingUserId(); 1482 boolean isAdmin; 1483 long token = Binder.clearCallingIdentity(); 1484 try { 1485 isAdmin = um.getUserInfo(callingUserId).isAdmin(); 1486 } finally { 1487 Binder.restoreCallingIdentity(token); 1488 } 1489 if (!isAdmin) { 1490 throw new SecurityException("Only admin users can adopt sd cards"); 1491 } 1492 } 1493 1494 /** 1495 * Constructs a new StorageManagerService instance 1496 * 1497 * @param context Binder context for this service 1498 */ 1499 public StorageManagerService(Context context) { 1500 sSelf = this; 1501 1502 // Snapshot feature flag used for this boot 1503 SystemProperties.set(StorageManager.PROP_ISOLATED_STORAGE_SNAPSHOT, Boolean.toString( 1504 SystemProperties.getBoolean(StorageManager.PROP_ISOLATED_STORAGE, true))); 1505 1506 mContext = context; 1507 mResolver = mContext.getContentResolver(); 1508 1509 mCallbacks = new Callbacks(FgThread.get().getLooper()); 1510 mLockPatternUtils = new LockPatternUtils(mContext); 1511 1512 HandlerThread hthread = new HandlerThread(TAG); 1513 hthread.start(); 1514 mHandler = new StorageManagerServiceHandler(hthread.getLooper()); 1515 1516 // Add OBB Action Handler to StorageManagerService thread. 1517 mObbActionHandler = new ObbActionHandler(IoThread.get().getLooper()); 1518 1519 // Initialize the last-fstrim tracking if necessary 1520 File dataDir = Environment.getDataDirectory(); 1521 File systemDir = new File(dataDir, "system"); 1522 mLastMaintenanceFile = new File(systemDir, LAST_FSTRIM_FILE); 1523 if (!mLastMaintenanceFile.exists()) { 1524 // Not setting mLastMaintenance here means that we will force an 1525 // fstrim during reboot following the OTA that installs this code. 1526 try { 1527 (new FileOutputStream(mLastMaintenanceFile)).close(); 1528 } catch (IOException e) { 1529 Slog.e(TAG, "Unable to create fstrim record " + mLastMaintenanceFile.getPath()); 1530 } 1531 } else { 1532 mLastMaintenance = mLastMaintenanceFile.lastModified(); 1533 } 1534 1535 mSettingsFile = new AtomicFile( 1536 new File(Environment.getDataSystemDirectory(), "storage.xml"), "storage-settings"); 1537 1538 synchronized (mLock) { 1539 readSettingsLocked(); 1540 } 1541 1542 LocalServices.addService(StorageManagerInternal.class, mStorageManagerInternal); 1543 1544 final IntentFilter userFilter = new IntentFilter(); 1545 userFilter.addAction(Intent.ACTION_USER_ADDED); 1546 userFilter.addAction(Intent.ACTION_USER_REMOVED); 1547 mContext.registerReceiver(mUserReceiver, userFilter, null, mHandler); 1548 1549 synchronized (mLock) { 1550 addInternalVolumeLocked(); 1551 } 1552 1553 // Add ourself to the Watchdog monitors if enabled. 1554 if (WATCHDOG_ENABLE) { 1555 Watchdog.getInstance().addMonitor(this); 1556 } 1557 } 1558 1559 private void start() { 1560 connect(); 1561 } 1562 1563 private void connect() { 1564 IBinder binder = ServiceManager.getService("storaged"); 1565 if (binder != null) { 1566 try { 1567 binder.linkToDeath(new DeathRecipient() { 1568 @Override 1569 public void binderDied() { 1570 Slog.w(TAG, "storaged died; reconnecting"); 1571 mStoraged = null; 1572 connect(); 1573 } 1574 }, 0); 1575 } catch (RemoteException e) { 1576 binder = null; 1577 } 1578 } 1579 1580 if (binder != null) { 1581 mStoraged = IStoraged.Stub.asInterface(binder); 1582 } else { 1583 Slog.w(TAG, "storaged not found; trying again"); 1584 } 1585 1586 binder = ServiceManager.getService("vold"); 1587 if (binder != null) { 1588 try { 1589 binder.linkToDeath(new DeathRecipient() { 1590 @Override 1591 public void binderDied() { 1592 Slog.w(TAG, "vold died; reconnecting"); 1593 mVold = null; 1594 connect(); 1595 } 1596 }, 0); 1597 } catch (RemoteException e) { 1598 binder = null; 1599 } 1600 } 1601 1602 if (binder != null) { 1603 mVold = IVold.Stub.asInterface(binder); 1604 try { 1605 mVold.setListener(mListener); 1606 } catch (RemoteException e) { 1607 mVold = null; 1608 Slog.w(TAG, "vold listener rejected; trying again", e); 1609 } 1610 } else { 1611 Slog.w(TAG, "vold not found; trying again"); 1612 } 1613 1614 if (mStoraged == null || mVold == null) { 1615 BackgroundThread.getHandler().postDelayed(() -> { 1616 connect(); 1617 }, DateUtils.SECOND_IN_MILLIS); 1618 } else { 1619 onDaemonConnected(); 1620 } 1621 } 1622 1623 private void servicesReady() { 1624 mPmInternal = LocalServices.getService(PackageManagerInternal.class); 1625 1626 mIPackageManager = IPackageManager.Stub.asInterface( 1627 ServiceManager.getService("package")); 1628 mIAppOpsService = IAppOpsService.Stub.asInterface( 1629 ServiceManager.getService(Context.APP_OPS_SERVICE)); 1630 try { 1631 mIAppOpsService.startWatchingMode(OP_REQUEST_INSTALL_PACKAGES, null, mAppOpsCallback); 1632 mIAppOpsService.startWatchingMode(OP_LEGACY_STORAGE, null, mAppOpsCallback); 1633 } catch (RemoteException e) { 1634 } 1635 } 1636 1637 private static long getLastAccessTime(AppOpsManager manager, 1638 int uid, String packageName, int[] ops) { 1639 long maxTime = 0; 1640 final List<AppOpsManager.PackageOps> pkgs = manager.getOpsForPackage(uid, packageName, ops); 1641 for (AppOpsManager.PackageOps pkg : CollectionUtils.emptyIfNull(pkgs)) { 1642 for (AppOpsManager.OpEntry op : CollectionUtils.emptyIfNull(pkg.getOps())) { 1643 maxTime = Math.max(maxTime, op.getLastAccessTime( 1644 AppOpsManager.OP_FLAGS_ALL_TRUSTED)); 1645 } 1646 } 1647 return maxTime; 1648 } 1649 1650 private void systemReady() { 1651 LocalServices.getService(ActivityTaskManagerInternal.class) 1652 .registerScreenObserver(this); 1653 1654 mHandler.obtainMessage(H_SYSTEM_READY).sendToTarget(); 1655 } 1656 1657 private void bootCompleted() { 1658 mBootCompleted = true; 1659 mHandler.obtainMessage(H_BOOT_COMPLETED).sendToTarget(); 1660 } 1661 1662 private void handleBootCompleted() { 1663 initIfBootedAndConnected(); 1664 resetIfBootedAndConnected(); 1665 } 1666 1667 private String getDefaultPrimaryStorageUuid() { 1668 if (SystemProperties.getBoolean(StorageManager.PROP_PRIMARY_PHYSICAL, false)) { 1669 return StorageManager.UUID_PRIMARY_PHYSICAL; 1670 } else { 1671 return StorageManager.UUID_PRIVATE_INTERNAL; 1672 } 1673 } 1674 1675 @GuardedBy("mLock") 1676 private void readSettingsLocked() { 1677 mRecords.clear(); 1678 mPrimaryStorageUuid = getDefaultPrimaryStorageUuid(); 1679 1680 FileInputStream fis = null; 1681 try { 1682 fis = mSettingsFile.openRead(); 1683 final XmlPullParser in = Xml.newPullParser(); 1684 in.setInput(fis, StandardCharsets.UTF_8.name()); 1685 1686 int type; 1687 while ((type = in.next()) != END_DOCUMENT) { 1688 if (type == START_TAG) { 1689 final String tag = in.getName(); 1690 if (TAG_VOLUMES.equals(tag)) { 1691 final int version = readIntAttribute(in, ATTR_VERSION, VERSION_INIT); 1692 final boolean primaryPhysical = SystemProperties.getBoolean( 1693 StorageManager.PROP_PRIMARY_PHYSICAL, false); 1694 final boolean validAttr = (version >= VERSION_FIX_PRIMARY) 1695 || (version >= VERSION_ADD_PRIMARY && !primaryPhysical); 1696 if (validAttr) { 1697 mPrimaryStorageUuid = readStringAttribute(in, 1698 ATTR_PRIMARY_STORAGE_UUID); 1699 } 1700 } else if (TAG_VOLUME.equals(tag)) { 1701 final VolumeRecord rec = readVolumeRecord(in); 1702 mRecords.put(rec.fsUuid, rec); 1703 } 1704 } 1705 } 1706 } catch (FileNotFoundException e) { 1707 // Missing metadata is okay, probably first boot 1708 } catch (IOException e) { 1709 Slog.wtf(TAG, "Failed reading metadata", e); 1710 } catch (XmlPullParserException e) { 1711 Slog.wtf(TAG, "Failed reading metadata", e); 1712 } finally { 1713 IoUtils.closeQuietly(fis); 1714 } 1715 } 1716 1717 @GuardedBy("mLock") 1718 private void writeSettingsLocked() { 1719 FileOutputStream fos = null; 1720 try { 1721 fos = mSettingsFile.startWrite(); 1722 1723 XmlSerializer out = new FastXmlSerializer(); 1724 out.setOutput(fos, StandardCharsets.UTF_8.name()); 1725 out.startDocument(null, true); 1726 out.startTag(null, TAG_VOLUMES); 1727 writeIntAttribute(out, ATTR_VERSION, VERSION_FIX_PRIMARY); 1728 writeStringAttribute(out, ATTR_PRIMARY_STORAGE_UUID, mPrimaryStorageUuid); 1729 final int size = mRecords.size(); 1730 for (int i = 0; i < size; i++) { 1731 final VolumeRecord rec = mRecords.valueAt(i); 1732 writeVolumeRecord(out, rec); 1733 } 1734 out.endTag(null, TAG_VOLUMES); 1735 out.endDocument(); 1736 1737 mSettingsFile.finishWrite(fos); 1738 } catch (IOException e) { 1739 if (fos != null) { 1740 mSettingsFile.failWrite(fos); 1741 } 1742 } 1743 } 1744 1745 public static VolumeRecord readVolumeRecord(XmlPullParser in) throws IOException { 1746 final int type = readIntAttribute(in, ATTR_TYPE); 1747 final String fsUuid = readStringAttribute(in, ATTR_FS_UUID); 1748 final VolumeRecord meta = new VolumeRecord(type, fsUuid); 1749 meta.partGuid = readStringAttribute(in, ATTR_PART_GUID); 1750 meta.nickname = readStringAttribute(in, ATTR_NICKNAME); 1751 meta.userFlags = readIntAttribute(in, ATTR_USER_FLAGS); 1752 meta.createdMillis = readLongAttribute(in, ATTR_CREATED_MILLIS, 0); 1753 meta.lastSeenMillis = readLongAttribute(in, ATTR_LAST_SEEN_MILLIS, 0); 1754 meta.lastTrimMillis = readLongAttribute(in, ATTR_LAST_TRIM_MILLIS, 0); 1755 meta.lastBenchMillis = readLongAttribute(in, ATTR_LAST_BENCH_MILLIS, 0); 1756 return meta; 1757 } 1758 1759 public static void writeVolumeRecord(XmlSerializer out, VolumeRecord rec) throws IOException { 1760 out.startTag(null, TAG_VOLUME); 1761 writeIntAttribute(out, ATTR_TYPE, rec.type); 1762 writeStringAttribute(out, ATTR_FS_UUID, rec.fsUuid); 1763 writeStringAttribute(out, ATTR_PART_GUID, rec.partGuid); 1764 writeStringAttribute(out, ATTR_NICKNAME, rec.nickname); 1765 writeIntAttribute(out, ATTR_USER_FLAGS, rec.userFlags); 1766 writeLongAttribute(out, ATTR_CREATED_MILLIS, rec.createdMillis); 1767 writeLongAttribute(out, ATTR_LAST_SEEN_MILLIS, rec.lastSeenMillis); 1768 writeLongAttribute(out, ATTR_LAST_TRIM_MILLIS, rec.lastTrimMillis); 1769 writeLongAttribute(out, ATTR_LAST_BENCH_MILLIS, rec.lastBenchMillis); 1770 out.endTag(null, TAG_VOLUME); 1771 } 1772 1773 /** 1774 * Exposed API calls below here 1775 */ 1776 1777 @Override 1778 public void registerListener(IStorageEventListener listener) { 1779 mCallbacks.register(listener); 1780 } 1781 1782 @Override 1783 public void unregisterListener(IStorageEventListener listener) { 1784 mCallbacks.unregister(listener); 1785 } 1786 1787 @Override 1788 public void shutdown(final IStorageShutdownObserver observer) { 1789 enforcePermission(android.Manifest.permission.SHUTDOWN); 1790 1791 Slog.i(TAG, "Shutting down"); 1792 mHandler.obtainMessage(H_SHUTDOWN, observer).sendToTarget(); 1793 } 1794 1795 @Override 1796 public void mount(String volId) { 1797 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS); 1798 1799 final VolumeInfo vol = findVolumeByIdOrThrow(volId); 1800 if (isMountDisallowed(vol)) { 1801 throw new SecurityException("Mounting " + volId + " restricted by policy"); 1802 } 1803 mount(vol); 1804 } 1805 1806 private void mount(VolumeInfo vol) { 1807 try { 1808 mVold.mount(vol.id, vol.mountFlags, vol.mountUserId); 1809 } catch (Exception e) { 1810 Slog.wtf(TAG, e); 1811 } 1812 } 1813 1814 @Override 1815 public void unmount(String volId) { 1816 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS); 1817 1818 final VolumeInfo vol = findVolumeByIdOrThrow(volId); 1819 unmount(vol); 1820 } 1821 1822 private void unmount(VolumeInfo vol) { 1823 try { 1824 mVold.unmount(vol.id); 1825 } catch (Exception e) { 1826 Slog.wtf(TAG, e); 1827 } 1828 } 1829 1830 @Override 1831 public void format(String volId) { 1832 enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS); 1833 1834 final VolumeInfo vol = findVolumeByIdOrThrow(volId); 1835 try { 1836 mVold.format(vol.id, "auto"); 1837 } catch (Exception e) { 1838 Slog.wtf(TAG, e); 1839 } 1840 } 1841 1842 @Override 1843 public void benchmark(String volId, IVoldTaskListener listener) { 1844 enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS); 1845 1846 try { 1847 mVold.benchmark(volId, new IVoldTaskListener.Stub() { 1848 @Override 1849 public void onStatus(int status, PersistableBundle extras) { 1850 dispatchOnStatus(listener, status, extras); 1851 } 1852 1853 @Override 1854 public void onFinished(int status, PersistableBundle extras) { 1855 dispatchOnFinished(listener, status, extras); 1856 1857 final String path = extras.getString("path"); 1858 final String ident = extras.getString("ident"); 1859 final long create = extras.getLong("create"); 1860 final long run = extras.getLong("run"); 1861 final long destroy = extras.getLong("destroy"); 1862 1863 final DropBoxManager dropBox = mContext.getSystemService(DropBoxManager.class); 1864 dropBox.addText(TAG_STORAGE_BENCHMARK, scrubPath(path) 1865 + " " + ident + " " + create + " " + run + " " + destroy); 1866 1867 synchronized (mLock) { 1868 final VolumeRecord rec = findRecordForPath(path); 1869 if (rec != null) { 1870 rec.lastBenchMillis = System.currentTimeMillis(); 1871 writeSettingsLocked(); 1872 } 1873 } 1874 } 1875 }); 1876 } catch (RemoteException e) { 1877 throw e.rethrowAsRuntimeException(); 1878 } 1879 } 1880 1881 @Override 1882 public void partitionPublic(String diskId) { 1883 enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS); 1884 1885 final CountDownLatch latch = findOrCreateDiskScanLatch(diskId); 1886 try { 1887 mVold.partition(diskId, IVold.PARTITION_TYPE_PUBLIC, -1); 1888 waitForLatch(latch, "partitionPublic", 3 * DateUtils.MINUTE_IN_MILLIS); 1889 } catch (Exception e) { 1890 Slog.wtf(TAG, e); 1891 } 1892 } 1893 1894 @Override 1895 public void partitionPrivate(String diskId) { 1896 enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS); 1897 enforceAdminUser(); 1898 1899 final CountDownLatch latch = findOrCreateDiskScanLatch(diskId); 1900 try { 1901 mVold.partition(diskId, IVold.PARTITION_TYPE_PRIVATE, -1); 1902 waitForLatch(latch, "partitionPrivate", 3 * DateUtils.MINUTE_IN_MILLIS); 1903 } catch (Exception e) { 1904 Slog.wtf(TAG, e); 1905 } 1906 } 1907 1908 @Override 1909 public void partitionMixed(String diskId, int ratio) { 1910 enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS); 1911 enforceAdminUser(); 1912 1913 final CountDownLatch latch = findOrCreateDiskScanLatch(diskId); 1914 try { 1915 mVold.partition(diskId, IVold.PARTITION_TYPE_MIXED, ratio); 1916 waitForLatch(latch, "partitionMixed", 3 * DateUtils.MINUTE_IN_MILLIS); 1917 } catch (Exception e) { 1918 Slog.wtf(TAG, e); 1919 } 1920 } 1921 1922 @Override 1923 public void setVolumeNickname(String fsUuid, String nickname) { 1924 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS); 1925 1926 Preconditions.checkNotNull(fsUuid); 1927 synchronized (mLock) { 1928 final VolumeRecord rec = mRecords.get(fsUuid); 1929 rec.nickname = nickname; 1930 mCallbacks.notifyVolumeRecordChanged(rec); 1931 writeSettingsLocked(); 1932 } 1933 } 1934 1935 @Override 1936 public void setVolumeUserFlags(String fsUuid, int flags, int mask) { 1937 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS); 1938 1939 Preconditions.checkNotNull(fsUuid); 1940 synchronized (mLock) { 1941 final VolumeRecord rec = mRecords.get(fsUuid); 1942 rec.userFlags = (rec.userFlags & ~mask) | (flags & mask); 1943 mCallbacks.notifyVolumeRecordChanged(rec); 1944 writeSettingsLocked(); 1945 } 1946 } 1947 1948 @Override 1949 public void forgetVolume(String fsUuid) { 1950 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS); 1951 1952 Preconditions.checkNotNull(fsUuid); 1953 1954 synchronized (mLock) { 1955 final VolumeRecord rec = mRecords.remove(fsUuid); 1956 if (rec != null && !TextUtils.isEmpty(rec.partGuid)) { 1957 mHandler.obtainMessage(H_PARTITION_FORGET, rec).sendToTarget(); 1958 } 1959 mCallbacks.notifyVolumeForgotten(fsUuid); 1960 1961 // If this had been primary storage, revert back to internal and 1962 // reset vold so we bind into new volume into place. 1963 if (Objects.equals(mPrimaryStorageUuid, fsUuid)) { 1964 mPrimaryStorageUuid = getDefaultPrimaryStorageUuid(); 1965 mHandler.obtainMessage(H_RESET).sendToTarget(); 1966 } 1967 1968 writeSettingsLocked(); 1969 } 1970 } 1971 1972 @Override 1973 public void forgetAllVolumes() { 1974 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS); 1975 1976 synchronized (mLock) { 1977 for (int i = 0; i < mRecords.size(); i++) { 1978 final String fsUuid = mRecords.keyAt(i); 1979 final VolumeRecord rec = mRecords.valueAt(i); 1980 if (!TextUtils.isEmpty(rec.partGuid)) { 1981 mHandler.obtainMessage(H_PARTITION_FORGET, rec).sendToTarget(); 1982 } 1983 mCallbacks.notifyVolumeForgotten(fsUuid); 1984 } 1985 mRecords.clear(); 1986 1987 if (!Objects.equals(StorageManager.UUID_PRIVATE_INTERNAL, mPrimaryStorageUuid)) { 1988 mPrimaryStorageUuid = getDefaultPrimaryStorageUuid(); 1989 } 1990 1991 writeSettingsLocked(); 1992 mHandler.obtainMessage(H_RESET).sendToTarget(); 1993 } 1994 } 1995 1996 private void forgetPartition(String partGuid, String fsUuid) { 1997 try { 1998 mVold.forgetPartition(partGuid, fsUuid); 1999 } catch (Exception e) { 2000 Slog.wtf(TAG, e); 2001 } 2002 } 2003 2004 @Override 2005 public void fstrim(int flags, IVoldTaskListener listener) { 2006 enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS); 2007 2008 try { 2009 // Block based checkpoint process runs fstrim. So, if checkpoint is in progress 2010 // (first boot after OTA), We skip idle maintenance and make sure the last 2011 // fstrim time is still updated. If file based checkpoints are used, we run 2012 // idle maintenance (GC + fstrim) regardless of checkpoint status. 2013 if (!needsCheckpoint() || !supportsBlockCheckpoint()) { 2014 mVold.fstrim(flags, new IVoldTaskListener.Stub() { 2015 @Override 2016 public void onStatus(int status, PersistableBundle extras) { 2017 dispatchOnStatus(listener, status, extras); 2018 2019 // Ignore trim failures 2020 if (status != 0) return; 2021 2022 final String path = extras.getString("path"); 2023 final long bytes = extras.getLong("bytes"); 2024 final long time = extras.getLong("time"); 2025 2026 final DropBoxManager dropBox = mContext.getSystemService(DropBoxManager.class); 2027 dropBox.addText(TAG_STORAGE_TRIM, scrubPath(path) + " " + bytes + " " + time); 2028 2029 synchronized (mLock) { 2030 final VolumeRecord rec = findRecordForPath(path); 2031 if (rec != null) { 2032 rec.lastTrimMillis = System.currentTimeMillis(); 2033 writeSettingsLocked(); 2034 } 2035 } 2036 } 2037 2038 @Override 2039 public void onFinished(int status, PersistableBundle extras) { 2040 dispatchOnFinished(listener, status, extras); 2041 2042 // TODO: benchmark when desired 2043 } 2044 }); 2045 } else { 2046 Slog.i(TAG, "Skipping fstrim - block based checkpoint in progress"); 2047 } 2048 } catch (RemoteException e) { 2049 throw e.rethrowAsRuntimeException(); 2050 } 2051 } 2052 2053 void runIdleMaint(Runnable callback) { 2054 enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS); 2055 2056 try { 2057 // Block based checkpoint process runs fstrim. So, if checkpoint is in progress 2058 // (first boot after OTA), We skip idle maintenance and make sure the last 2059 // fstrim time is still updated. If file based checkpoints are used, we run 2060 // idle maintenance (GC + fstrim) regardless of checkpoint status. 2061 if (!needsCheckpoint() || !supportsBlockCheckpoint()) { 2062 mVold.runIdleMaint(new IVoldTaskListener.Stub() { 2063 @Override 2064 public void onStatus(int status, PersistableBundle extras) { 2065 // Not currently used 2066 } 2067 @Override 2068 public void onFinished(int status, PersistableBundle extras) { 2069 if (callback != null) { 2070 BackgroundThread.getHandler().post(callback); 2071 } 2072 } 2073 }); 2074 } else { 2075 Slog.i(TAG, "Skipping idle maintenance - block based checkpoint in progress"); 2076 } 2077 } catch (Exception e) { 2078 Slog.wtf(TAG, e); 2079 } 2080 } 2081 2082 @Override 2083 public void runIdleMaintenance() { 2084 runIdleMaint(null); 2085 } 2086 2087 void abortIdleMaint(Runnable callback) { 2088 enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS); 2089 2090 try { 2091 mVold.abortIdleMaint(new IVoldTaskListener.Stub() { 2092 @Override 2093 public void onStatus(int status, PersistableBundle extras) { 2094 // Not currently used 2095 } 2096 @Override 2097 public void onFinished(int status, PersistableBundle extras) { 2098 if (callback != null) { 2099 BackgroundThread.getHandler().post(callback); 2100 } 2101 } 2102 }); 2103 } catch (Exception e) { 2104 Slog.wtf(TAG, e); 2105 } 2106 } 2107 2108 @Override 2109 public void abortIdleMaintenance() { 2110 abortIdleMaint(null); 2111 } 2112 2113 private void remountUidExternalStorage(int uid, int mode) { 2114 try { 2115 mVold.remountUid(uid, mode); 2116 } catch (Exception e) { 2117 Slog.wtf(TAG, e); 2118 } 2119 } 2120 2121 @Override 2122 public void setDebugFlags(int flags, int mask) { 2123 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS); 2124 2125 if ((mask & StorageManager.DEBUG_EMULATE_FBE) != 0) { 2126 if (!EMULATE_FBE_SUPPORTED) { 2127 throw new IllegalStateException( 2128 "Emulation not supported on this device"); 2129 } 2130 if (StorageManager.isFileEncryptedNativeOnly()) { 2131 throw new IllegalStateException( 2132 "Emulation not supported on device with native FBE"); 2133 } 2134 if (mLockPatternUtils.isCredentialRequiredToDecrypt(false)) { 2135 throw new IllegalStateException( 2136 "Emulation requires disabling 'Secure start-up' in Settings > Security"); 2137 } 2138 2139 final long token = Binder.clearCallingIdentity(); 2140 try { 2141 final boolean emulateFbe = (flags & StorageManager.DEBUG_EMULATE_FBE) != 0; 2142 SystemProperties.set(StorageManager.PROP_EMULATE_FBE, Boolean.toString(emulateFbe)); 2143 2144 // Perform hard reboot to kick policy into place 2145 mContext.getSystemService(PowerManager.class).reboot(null); 2146 } finally { 2147 Binder.restoreCallingIdentity(token); 2148 } 2149 } 2150 2151 if ((mask & (StorageManager.DEBUG_ADOPTABLE_FORCE_ON 2152 | StorageManager.DEBUG_ADOPTABLE_FORCE_OFF)) != 0) { 2153 final String value; 2154 if ((flags & StorageManager.DEBUG_ADOPTABLE_FORCE_ON) != 0) { 2155 value = "force_on"; 2156 } else if ((flags & StorageManager.DEBUG_ADOPTABLE_FORCE_OFF) != 0) { 2157 value = "force_off"; 2158 } else { 2159 value = ""; 2160 } 2161 2162 final long token = Binder.clearCallingIdentity(); 2163 try { 2164 SystemProperties.set(StorageManager.PROP_ADOPTABLE, value); 2165 2166 // Reset storage to kick new setting into place 2167 mHandler.obtainMessage(H_RESET).sendToTarget(); 2168 } finally { 2169 Binder.restoreCallingIdentity(token); 2170 } 2171 } 2172 2173 if ((mask & (StorageManager.DEBUG_SDCARDFS_FORCE_ON 2174 | StorageManager.DEBUG_SDCARDFS_FORCE_OFF)) != 0) { 2175 final String value; 2176 if ((flags & StorageManager.DEBUG_SDCARDFS_FORCE_ON) != 0) { 2177 value = "force_on"; 2178 } else if ((flags & StorageManager.DEBUG_SDCARDFS_FORCE_OFF) != 0) { 2179 value = "force_off"; 2180 } else { 2181 value = ""; 2182 } 2183 2184 final long token = Binder.clearCallingIdentity(); 2185 try { 2186 SystemProperties.set(StorageManager.PROP_SDCARDFS, value); 2187 2188 // Reset storage to kick new setting into place 2189 mHandler.obtainMessage(H_RESET).sendToTarget(); 2190 } finally { 2191 Binder.restoreCallingIdentity(token); 2192 } 2193 } 2194 2195 if ((mask & StorageManager.DEBUG_VIRTUAL_DISK) != 0) { 2196 final boolean enabled = (flags & StorageManager.DEBUG_VIRTUAL_DISK) != 0; 2197 2198 final long token = Binder.clearCallingIdentity(); 2199 try { 2200 SystemProperties.set(StorageManager.PROP_VIRTUAL_DISK, Boolean.toString(enabled)); 2201 2202 // Reset storage to kick new setting into place 2203 mHandler.obtainMessage(H_RESET).sendToTarget(); 2204 } finally { 2205 Binder.restoreCallingIdentity(token); 2206 } 2207 } 2208 2209 if ((mask & (StorageManager.DEBUG_ISOLATED_STORAGE_FORCE_ON 2210 | StorageManager.DEBUG_ISOLATED_STORAGE_FORCE_OFF)) != 0) { 2211 final int value; 2212 if ((flags & StorageManager.DEBUG_ISOLATED_STORAGE_FORCE_ON) != 0) { 2213 value = 1; 2214 } else if ((flags & StorageManager.DEBUG_ISOLATED_STORAGE_FORCE_OFF) != 0) { 2215 value = -1; 2216 } else { 2217 value = 0; 2218 } 2219 2220 final long token = Binder.clearCallingIdentity(); 2221 try { 2222 Settings.Global.putInt(mContext.getContentResolver(), 2223 Settings.Global.ISOLATED_STORAGE_LOCAL, value); 2224 refreshIsolatedStorageSettings(); 2225 2226 // Perform hard reboot to kick policy into place 2227 mHandler.post(() -> { 2228 mContext.getSystemService(PowerManager.class).reboot(null); 2229 }); 2230 } finally { 2231 Binder.restoreCallingIdentity(token); 2232 } 2233 } 2234 } 2235 2236 @Override 2237 public String getPrimaryStorageUuid() { 2238 synchronized (mLock) { 2239 return mPrimaryStorageUuid; 2240 } 2241 } 2242 2243 @Override 2244 public void setPrimaryStorageUuid(String volumeUuid, IPackageMoveObserver callback) { 2245 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS); 2246 2247 final VolumeInfo from; 2248 final VolumeInfo to; 2249 2250 synchronized (mLock) { 2251 if (Objects.equals(mPrimaryStorageUuid, volumeUuid)) { 2252 throw new IllegalArgumentException("Primary storage already at " + volumeUuid); 2253 } 2254 2255 if (mMoveCallback != null) { 2256 throw new IllegalStateException("Move already in progress"); 2257 } 2258 mMoveCallback = callback; 2259 mMoveTargetUuid = volumeUuid; 2260 2261 // We need all the users unlocked to move their primary storage 2262 final List<UserInfo> users = mContext.getSystemService(UserManager.class).getUsers(); 2263 for (UserInfo user : users) { 2264 if (StorageManager.isFileEncryptedNativeOrEmulated() 2265 && !isUserKeyUnlocked(user.id)) { 2266 Slog.w(TAG, "Failing move due to locked user " + user.id); 2267 onMoveStatusLocked(PackageManager.MOVE_FAILED_LOCKED_USER); 2268 return; 2269 } 2270 } 2271 2272 // When moving to/from primary physical volume, we probably just nuked 2273 // the current storage location, so we have nothing to move. 2274 if (Objects.equals(StorageManager.UUID_PRIMARY_PHYSICAL, mPrimaryStorageUuid) 2275 || Objects.equals(StorageManager.UUID_PRIMARY_PHYSICAL, volumeUuid)) { 2276 Slog.d(TAG, "Skipping move to/from primary physical"); 2277 onMoveStatusLocked(MOVE_STATUS_COPY_FINISHED); 2278 onMoveStatusLocked(PackageManager.MOVE_SUCCEEDED); 2279 mHandler.obtainMessage(H_RESET).sendToTarget(); 2280 return; 2281 2282 } else { 2283 from = findStorageForUuid(mPrimaryStorageUuid); 2284 to = findStorageForUuid(volumeUuid); 2285 2286 if (from == null) { 2287 Slog.w(TAG, "Failing move due to missing from volume " + mPrimaryStorageUuid); 2288 onMoveStatusLocked(PackageManager.MOVE_FAILED_INTERNAL_ERROR); 2289 return; 2290 } else if (to == null) { 2291 Slog.w(TAG, "Failing move due to missing to volume " + volumeUuid); 2292 onMoveStatusLocked(PackageManager.MOVE_FAILED_INTERNAL_ERROR); 2293 return; 2294 } 2295 } 2296 } 2297 2298 try { 2299 mVold.moveStorage(from.id, to.id, new IVoldTaskListener.Stub() { 2300 @Override 2301 public void onStatus(int status, PersistableBundle extras) { 2302 synchronized (mLock) { 2303 onMoveStatusLocked(status); 2304 } 2305 } 2306 2307 @Override 2308 public void onFinished(int status, PersistableBundle extras) { 2309 // Not currently used 2310 } 2311 }); 2312 } catch (Exception e) { 2313 Slog.wtf(TAG, e); 2314 } 2315 } 2316 2317 private void warnOnNotMounted() { 2318 synchronized (mLock) { 2319 for (int i = 0; i < mVolumes.size(); i++) { 2320 final VolumeInfo vol = mVolumes.valueAt(i); 2321 if (vol.isPrimary() && vol.isMountedWritable()) { 2322 // Cool beans, we have a mounted primary volume 2323 return; 2324 } 2325 } 2326 } 2327 2328 Slog.w(TAG, "No primary storage mounted!"); 2329 } 2330 2331 private boolean isUidOwnerOfPackageOrSystem(String packageName, int callerUid) { 2332 if (callerUid == android.os.Process.SYSTEM_UID) { 2333 return true; 2334 } 2335 2336 if (packageName == null) { 2337 return false; 2338 } 2339 2340 final int packageUid = mPmInternal.getPackageUid(packageName, 2341 PackageManager.MATCH_DEBUG_TRIAGED_MISSING, UserHandle.getUserId(callerUid)); 2342 2343 if (DEBUG_OBB) { 2344 Slog.d(TAG, "packageName = " + packageName + ", packageUid = " + 2345 packageUid + ", callerUid = " + callerUid); 2346 } 2347 2348 return callerUid == packageUid; 2349 } 2350 2351 @Override 2352 public String getMountedObbPath(String rawPath) { 2353 Preconditions.checkNotNull(rawPath, "rawPath cannot be null"); 2354 2355 warnOnNotMounted(); 2356 2357 final ObbState state; 2358 synchronized (mObbMounts) { 2359 state = mObbPathToStateMap.get(rawPath); 2360 } 2361 if (state == null) { 2362 Slog.w(TAG, "Failed to find OBB mounted at " + rawPath); 2363 return null; 2364 } 2365 2366 return findVolumeByIdOrThrow(state.volId).getPath().getAbsolutePath(); 2367 } 2368 2369 @Override 2370 public boolean isObbMounted(String rawPath) { 2371 Preconditions.checkNotNull(rawPath, "rawPath cannot be null"); 2372 synchronized (mObbMounts) { 2373 return mObbPathToStateMap.containsKey(rawPath); 2374 } 2375 } 2376 2377 @Override 2378 public void mountObb(String rawPath, String canonicalPath, String key, 2379 IObbActionListener token, int nonce, ObbInfo obbInfo) { 2380 Preconditions.checkNotNull(rawPath, "rawPath cannot be null"); 2381 Preconditions.checkNotNull(canonicalPath, "canonicalPath cannot be null"); 2382 Preconditions.checkNotNull(token, "token cannot be null"); 2383 Preconditions.checkNotNull(obbInfo, "obbIfno cannot be null"); 2384 2385 final int callingUid = Binder.getCallingUid(); 2386 final ObbState obbState = new ObbState(rawPath, canonicalPath, 2387 callingUid, token, nonce, null); 2388 final ObbAction action = new MountObbAction(obbState, key, callingUid, obbInfo); 2389 mObbActionHandler.sendMessage(mObbActionHandler.obtainMessage(OBB_RUN_ACTION, action)); 2390 2391 if (DEBUG_OBB) 2392 Slog.i(TAG, "Send to OBB handler: " + action.toString()); 2393 } 2394 2395 @Override 2396 public void unmountObb(String rawPath, boolean force, IObbActionListener token, int nonce) { 2397 Preconditions.checkNotNull(rawPath, "rawPath cannot be null"); 2398 2399 final ObbState existingState; 2400 synchronized (mObbMounts) { 2401 existingState = mObbPathToStateMap.get(rawPath); 2402 } 2403 2404 if (existingState != null) { 2405 // TODO: separate state object from request data 2406 final int callingUid = Binder.getCallingUid(); 2407 final ObbState newState = new ObbState(rawPath, existingState.canonicalPath, 2408 callingUid, token, nonce, existingState.volId); 2409 final ObbAction action = new UnmountObbAction(newState, force); 2410 mObbActionHandler.sendMessage(mObbActionHandler.obtainMessage(OBB_RUN_ACTION, action)); 2411 2412 if (DEBUG_OBB) 2413 Slog.i(TAG, "Send to OBB handler: " + action.toString()); 2414 } else { 2415 Slog.w(TAG, "Unknown OBB mount at " + rawPath); 2416 } 2417 } 2418 2419 @Override 2420 public int getEncryptionState() { 2421 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER, 2422 "no permission to access the crypt keeper"); 2423 2424 try { 2425 return mVold.fdeComplete(); 2426 } catch (Exception e) { 2427 Slog.wtf(TAG, e); 2428 return StorageManager.ENCRYPTION_STATE_ERROR_UNKNOWN; 2429 } 2430 } 2431 2432 @Override 2433 public int decryptStorage(String password) { 2434 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER, 2435 "no permission to access the crypt keeper"); 2436 2437 if (TextUtils.isEmpty(password)) { 2438 throw new IllegalArgumentException("password cannot be empty"); 2439 } 2440 2441 if (DEBUG_EVENTS) { 2442 Slog.i(TAG, "decrypting storage..."); 2443 } 2444 2445 try { 2446 mVold.fdeCheckPassword(password); 2447 mHandler.postDelayed(() -> { 2448 try { 2449 mVold.fdeRestart(); 2450 } catch (Exception e) { 2451 Slog.wtf(TAG, e); 2452 } 2453 }, DateUtils.SECOND_IN_MILLIS); 2454 return 0; 2455 } catch (ServiceSpecificException e) { 2456 Slog.e(TAG, "fdeCheckPassword failed", e); 2457 return e.errorCode; 2458 } catch (Exception e) { 2459 Slog.wtf(TAG, e); 2460 return StorageManager.ENCRYPTION_STATE_ERROR_UNKNOWN; 2461 } 2462 } 2463 2464 @Override 2465 public int encryptStorage(int type, String password) { 2466 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER, 2467 "no permission to access the crypt keeper"); 2468 2469 if (type == StorageManager.CRYPT_TYPE_DEFAULT) { 2470 password = ""; 2471 } else if (TextUtils.isEmpty(password)) { 2472 throw new IllegalArgumentException("password cannot be empty"); 2473 } 2474 2475 if (DEBUG_EVENTS) { 2476 Slog.i(TAG, "encrypting storage..."); 2477 } 2478 2479 try { 2480 mVold.fdeEnable(type, password, 0); 2481 } catch (Exception e) { 2482 Slog.wtf(TAG, e); 2483 return -1; 2484 } 2485 2486 return 0; 2487 } 2488 2489 /** Set the password for encrypting the master key. 2490 * @param type One of the CRYPTO_TYPE_XXX consts defined in StorageManager. 2491 * @param password The password to set. 2492 */ 2493 @Override 2494 public int changeEncryptionPassword(int type, String password) { 2495 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER, 2496 "no permission to access the crypt keeper"); 2497 2498 if (StorageManager.isFileEncryptedNativeOnly()) { 2499 // Not supported on FBE devices 2500 return -1; 2501 } 2502 2503 if (type == StorageManager.CRYPT_TYPE_DEFAULT) { 2504 password = ""; 2505 } else if (TextUtils.isEmpty(password)) { 2506 throw new IllegalArgumentException("password cannot be empty"); 2507 } 2508 2509 if (DEBUG_EVENTS) { 2510 Slog.i(TAG, "changing encryption password..."); 2511 } 2512 2513 try { 2514 mVold.fdeChangePassword(type, password); 2515 return 0; 2516 } catch (Exception e) { 2517 Slog.wtf(TAG, e); 2518 return -1; 2519 } 2520 } 2521 2522 /** 2523 * Validate a user-supplied password string with cryptfs 2524 */ 2525 @Override 2526 public int verifyEncryptionPassword(String password) throws RemoteException { 2527 // Only the system process is permitted to validate passwords 2528 if (Binder.getCallingUid() != android.os.Process.SYSTEM_UID) { 2529 throw new SecurityException("no permission to access the crypt keeper"); 2530 } 2531 2532 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER, 2533 "no permission to access the crypt keeper"); 2534 2535 if (TextUtils.isEmpty(password)) { 2536 throw new IllegalArgumentException("password cannot be empty"); 2537 } 2538 2539 if (DEBUG_EVENTS) { 2540 Slog.i(TAG, "validating encryption password..."); 2541 } 2542 2543 try { 2544 mVold.fdeVerifyPassword(password); 2545 return 0; 2546 } catch (Exception e) { 2547 Slog.wtf(TAG, e); 2548 return -1; 2549 } 2550 } 2551 2552 /** 2553 * Get the type of encryption used to encrypt the master key. 2554 * @return The type, one of the CRYPT_TYPE_XXX consts from StorageManager. 2555 */ 2556 @Override 2557 public int getPasswordType() { 2558 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER, 2559 "no permission to access the crypt keeper"); 2560 2561 try { 2562 return mVold.fdeGetPasswordType(); 2563 } catch (Exception e) { 2564 Slog.wtf(TAG, e); 2565 return -1; 2566 } 2567 } 2568 2569 /** 2570 * Set a field in the crypto header. 2571 * @param field field to set 2572 * @param contents contents to set in field 2573 */ 2574 @Override 2575 public void setField(String field, String contents) throws RemoteException { 2576 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER, 2577 "no permission to access the crypt keeper"); 2578 2579 if (!StorageManager.isBlockEncrypted()) { 2580 // Only supported on FDE devices 2581 return; 2582 } 2583 2584 try { 2585 mVold.fdeSetField(field, contents); 2586 return; 2587 } catch (Exception e) { 2588 Slog.wtf(TAG, e); 2589 return; 2590 } 2591 } 2592 2593 /** 2594 * Gets a field from the crypto header. 2595 * @param field field to get 2596 * @return contents of field 2597 */ 2598 @Override 2599 public String getField(String field) throws RemoteException { 2600 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER, 2601 "no permission to access the crypt keeper"); 2602 2603 if (!StorageManager.isBlockEncrypted()) { 2604 // Only supported on FDE devices 2605 return null; 2606 } 2607 2608 try { 2609 return mVold.fdeGetField(field); 2610 } catch (Exception e) { 2611 Slog.wtf(TAG, e); 2612 return null; 2613 } 2614 } 2615 2616 /** 2617 * Is userdata convertible to file based encryption? 2618 * @return non zero for convertible 2619 */ 2620 @Override 2621 public boolean isConvertibleToFBE() throws RemoteException { 2622 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER, 2623 "no permission to access the crypt keeper"); 2624 2625 try { 2626 return mVold.isConvertibleToFbe(); 2627 } catch (Exception e) { 2628 Slog.wtf(TAG, e); 2629 return false; 2630 } 2631 } 2632 2633 /** 2634 * Check whether the device supports filesystem checkpointing. 2635 * 2636 * @return true if the device supports filesystem checkpointing, false otherwise. 2637 */ 2638 @Override 2639 public boolean supportsCheckpoint() throws RemoteException { 2640 // Only the system process is permitted to start checkpoints 2641 if (Binder.getCallingUid() != android.os.Process.SYSTEM_UID) { 2642 throw new SecurityException("no permission to check filesystem checkpoint support"); 2643 } 2644 2645 return mVold.supportsCheckpoint(); 2646 } 2647 2648 /** 2649 * Signal that checkpointing partitions should start a checkpoint on the next boot. 2650 * 2651 * @param numTries Number of times to try booting in checkpoint mode, before we will boot 2652 * non-checkpoint mode and commit all changes immediately. Callers are 2653 * responsible for ensuring that boot is safe (eg, by rolling back updates). 2654 */ 2655 @Override 2656 public void startCheckpoint(int numTries) throws RemoteException { 2657 // Only the system process is permitted to start checkpoints 2658 if (Binder.getCallingUid() != android.os.Process.SYSTEM_UID) { 2659 throw new SecurityException("no permission to start filesystem checkpoint"); 2660 } 2661 2662 mVold.startCheckpoint(numTries); 2663 } 2664 2665 /** 2666 * Signal that checkpointing partitions should commit changes 2667 */ 2668 @Override 2669 public void commitChanges() throws RemoteException { 2670 // Only the system process is permitted to commit checkpoints 2671 if (Binder.getCallingUid() != android.os.Process.SYSTEM_UID) { 2672 throw new SecurityException("no permission to commit checkpoint changes"); 2673 } 2674 2675 mVold.commitChanges(); 2676 } 2677 2678 /** 2679 * Check if we should be mounting with checkpointing or are checkpointing now 2680 */ 2681 @Override 2682 public boolean needsCheckpoint() throws RemoteException { 2683 enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS); 2684 return mVold.needsCheckpoint(); 2685 } 2686 2687 /** 2688 * Abort the current set of changes and either try again, or abort entirely 2689 */ 2690 @Override 2691 public void abortChanges(String message, boolean retry) throws RemoteException { 2692 // Only the system process is permitted to abort checkpoints 2693 if (Binder.getCallingUid() != android.os.Process.SYSTEM_UID) { 2694 throw new SecurityException("no permission to commit checkpoint changes"); 2695 } 2696 2697 mVold.abortChanges(message, retry); 2698 } 2699 2700 @Override 2701 public String getPassword() throws RemoteException { 2702 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER, 2703 "only keyguard can retrieve password"); 2704 2705 try { 2706 return mVold.fdeGetPassword(); 2707 } catch (Exception e) { 2708 Slog.wtf(TAG, e); 2709 return null; 2710 } 2711 } 2712 2713 @Override 2714 public void clearPassword() throws RemoteException { 2715 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER, 2716 "only keyguard can clear password"); 2717 2718 try { 2719 mVold.fdeClearPassword(); 2720 return; 2721 } catch (Exception e) { 2722 Slog.wtf(TAG, e); 2723 return; 2724 } 2725 } 2726 2727 @Override 2728 public void createUserKey(int userId, int serialNumber, boolean ephemeral) { 2729 enforcePermission(android.Manifest.permission.STORAGE_INTERNAL); 2730 2731 try { 2732 mVold.createUserKey(userId, serialNumber, ephemeral); 2733 } catch (Exception e) { 2734 Slog.wtf(TAG, e); 2735 } 2736 } 2737 2738 @Override 2739 public void destroyUserKey(int userId) { 2740 enforcePermission(android.Manifest.permission.STORAGE_INTERNAL); 2741 2742 try { 2743 mVold.destroyUserKey(userId); 2744 } catch (Exception e) { 2745 Slog.wtf(TAG, e); 2746 } 2747 } 2748 2749 private String encodeBytes(byte[] bytes) { 2750 if (ArrayUtils.isEmpty(bytes)) { 2751 return "!"; 2752 } else { 2753 return HexDump.toHexString(bytes); 2754 } 2755 } 2756 2757 /* 2758 * Add this token/secret pair to the set of ways we can recover a disk encryption key. 2759 * Changing the token/secret for a disk encryption key is done in two phases: first, adding 2760 * a new token/secret pair with this call, then delting all other pairs with 2761 * fixateNewestUserKeyAuth. This allows other places where a credential is used, such as 2762 * Gatekeeper, to be updated between the two calls. 2763 */ 2764 @Override 2765 public void addUserKeyAuth(int userId, int serialNumber, byte[] token, byte[] secret) { 2766 enforcePermission(android.Manifest.permission.STORAGE_INTERNAL); 2767 2768 try { 2769 mVold.addUserKeyAuth(userId, serialNumber, encodeBytes(token), encodeBytes(secret)); 2770 } catch (Exception e) { 2771 Slog.wtf(TAG, e); 2772 } 2773 } 2774 2775 /* 2776 * Delete all disk encryption token/secret pairs except the most recently added one 2777 */ 2778 @Override 2779 public void fixateNewestUserKeyAuth(int userId) { 2780 enforcePermission(android.Manifest.permission.STORAGE_INTERNAL); 2781 2782 try { 2783 mVold.fixateNewestUserKeyAuth(userId); 2784 } catch (Exception e) { 2785 Slog.wtf(TAG, e); 2786 } 2787 } 2788 2789 @Override 2790 public void unlockUserKey(int userId, int serialNumber, byte[] token, byte[] secret) { 2791 Slog.d(TAG, "unlockUserKey: " + userId); 2792 enforcePermission(android.Manifest.permission.STORAGE_INTERNAL); 2793 2794 if (StorageManager.isFileEncryptedNativeOrEmulated()) { 2795 // When a user has secure lock screen, require secret to actually unlock. 2796 // This check is mostly in place for emulation mode. 2797 if (mLockPatternUtils.isSecure(userId) && ArrayUtils.isEmpty(secret)) { 2798 throw new IllegalStateException("Secret required to unlock secure user " + userId); 2799 } 2800 2801 try { 2802 mVold.unlockUserKey(userId, serialNumber, encodeBytes(token), 2803 encodeBytes(secret)); 2804 } catch (Exception e) { 2805 Slog.wtf(TAG, e); 2806 return; 2807 } 2808 } 2809 2810 synchronized (mLock) { 2811 mLocalUnlockedUsers = ArrayUtils.appendInt(mLocalUnlockedUsers, userId); 2812 } 2813 } 2814 2815 @Override 2816 public void lockUserKey(int userId) { 2817 enforcePermission(android.Manifest.permission.STORAGE_INTERNAL); 2818 2819 try { 2820 mVold.lockUserKey(userId); 2821 } catch (Exception e) { 2822 Slog.wtf(TAG, e); 2823 return; 2824 } 2825 2826 synchronized (mLock) { 2827 mLocalUnlockedUsers = ArrayUtils.removeInt(mLocalUnlockedUsers, userId); 2828 } 2829 } 2830 2831 @Override 2832 public boolean isUserKeyUnlocked(int userId) { 2833 synchronized (mLock) { 2834 return ArrayUtils.contains(mLocalUnlockedUsers, userId); 2835 } 2836 } 2837 2838 private boolean isSystemUnlocked(int userId) { 2839 synchronized (mLock) { 2840 return ArrayUtils.contains(mSystemUnlockedUsers, userId); 2841 } 2842 } 2843 2844 @Override 2845 public void prepareUserStorage(String volumeUuid, int userId, int serialNumber, int flags) { 2846 enforcePermission(android.Manifest.permission.STORAGE_INTERNAL); 2847 2848 try { 2849 mVold.prepareUserStorage(volumeUuid, userId, serialNumber, flags); 2850 } catch (Exception e) { 2851 Slog.wtf(TAG, e); 2852 } 2853 } 2854 2855 @Override 2856 public void destroyUserStorage(String volumeUuid, int userId, int flags) { 2857 enforcePermission(android.Manifest.permission.STORAGE_INTERNAL); 2858 2859 try { 2860 mVold.destroyUserStorage(volumeUuid, userId, flags); 2861 } catch (Exception e) { 2862 Slog.wtf(TAG, e); 2863 } 2864 } 2865 2866 /** Not thread safe */ 2867 class AppFuseMountScope extends AppFuseBridge.MountScope { 2868 private boolean mMounted = false; 2869 2870 public AppFuseMountScope(int uid, int mountId) { 2871 super(uid, mountId); 2872 } 2873 2874 @Override 2875 public ParcelFileDescriptor open() throws NativeDaemonConnectorException { 2876 try { 2877 final FileDescriptor fd = mVold.mountAppFuse(uid, mountId); 2878 mMounted = true; 2879 return new ParcelFileDescriptor(fd); 2880 } catch (Exception e) { 2881 throw new NativeDaemonConnectorException("Failed to mount", e); 2882 } 2883 } 2884 2885 @Override 2886 public ParcelFileDescriptor openFile(int mountId, int fileId, int flags) 2887 throws NativeDaemonConnectorException { 2888 try { 2889 return new ParcelFileDescriptor( 2890 mVold.openAppFuseFile(uid, mountId, fileId, flags)); 2891 } catch (Exception e) { 2892 throw new NativeDaemonConnectorException("Failed to open", e); 2893 } 2894 } 2895 2896 @Override 2897 public void close() throws Exception { 2898 if (mMounted) { 2899 mVold.unmountAppFuse(uid, mountId); 2900 mMounted = false; 2901 } 2902 } 2903 } 2904 2905 @Override 2906 public @Nullable AppFuseMount mountProxyFileDescriptorBridge() { 2907 Slog.v(TAG, "mountProxyFileDescriptorBridge"); 2908 final int uid = Binder.getCallingUid(); 2909 2910 while (true) { 2911 synchronized (mAppFuseLock) { 2912 boolean newlyCreated = false; 2913 if (mAppFuseBridge == null) { 2914 mAppFuseBridge = new AppFuseBridge(); 2915 new Thread(mAppFuseBridge, AppFuseBridge.TAG).start(); 2916 newlyCreated = true; 2917 } 2918 try { 2919 final int name = mNextAppFuseName++; 2920 try { 2921 return new AppFuseMount( 2922 name, mAppFuseBridge.addBridge(new AppFuseMountScope(uid, name))); 2923 } catch (FuseUnavailableMountException e) { 2924 if (newlyCreated) { 2925 // If newly created bridge fails, it's a real error. 2926 Slog.e(TAG, "", e); 2927 return null; 2928 } 2929 // It seems the thread of mAppFuseBridge has already been terminated. 2930 mAppFuseBridge = null; 2931 } 2932 } catch (NativeDaemonConnectorException e) { 2933 throw e.rethrowAsParcelableException(); 2934 } 2935 } 2936 } 2937 } 2938 2939 @Override 2940 public @Nullable ParcelFileDescriptor openProxyFileDescriptor( 2941 int mountId, int fileId, int mode) { 2942 Slog.v(TAG, "mountProxyFileDescriptor"); 2943 2944 // We only support a narrow set of incoming mode flags 2945 mode &= MODE_READ_WRITE; 2946 2947 try { 2948 synchronized (mAppFuseLock) { 2949 if (mAppFuseBridge == null) { 2950 Slog.e(TAG, "FuseBridge has not been created"); 2951 return null; 2952 } 2953 return mAppFuseBridge.openFile(mountId, fileId, mode); 2954 } 2955 } catch (FuseUnavailableMountException | InterruptedException error) { 2956 Slog.v(TAG, "The mount point has already been invalid", error); 2957 return null; 2958 } 2959 } 2960 2961 @Override 2962 public void mkdirs(String callingPkg, String appPath) { 2963 final int callingUid = Binder.getCallingUid(); 2964 final int userId = UserHandle.getUserId(callingUid); 2965 final UserEnvironment userEnv = new UserEnvironment(userId); 2966 final String propertyName = "sys.user." + userId + ".ce_available"; 2967 2968 // Ignore requests to create directories while storage is locked 2969 if (!isUserKeyUnlocked(userId)) { 2970 throw new IllegalStateException("Failed to prepare " + appPath); 2971 } 2972 2973 // Ignore requests to create directories if CE storage is not available 2974 if ((userId == UserHandle.USER_SYSTEM) 2975 && !SystemProperties.getBoolean(propertyName, false)) { 2976 throw new IllegalStateException("Failed to prepare " + appPath); 2977 } 2978 2979 // Validate that reported package name belongs to caller 2980 final AppOpsManager appOps = (AppOpsManager) mContext.getSystemService( 2981 Context.APP_OPS_SERVICE); 2982 appOps.checkPackage(callingUid, callingPkg); 2983 2984 File appFile = null; 2985 try { 2986 appFile = new File(appPath).getCanonicalFile(); 2987 } catch (IOException e) { 2988 throw new IllegalStateException("Failed to resolve " + appPath + ": " + e); 2989 } 2990 2991 // Try translating the app path into a vold path, but require that it 2992 // belong to the calling package. 2993 if (FileUtils.contains(userEnv.buildExternalStorageAppDataDirs(callingPkg), appFile) || 2994 FileUtils.contains(userEnv.buildExternalStorageAppObbDirs(callingPkg), appFile) || 2995 FileUtils.contains(userEnv.buildExternalStorageAppMediaDirs(callingPkg), appFile)) { 2996 appPath = appFile.getAbsolutePath(); 2997 if (!appPath.endsWith("/")) { 2998 appPath = appPath + "/"; 2999 } 3000 3001 try { 3002 mVold.mkdirs(appPath); 3003 return; 3004 } catch (Exception e) { 3005 throw new IllegalStateException("Failed to prepare " + appPath + ": " + e); 3006 } 3007 } 3008 3009 throw new SecurityException("Invalid mkdirs path: " + appFile); 3010 } 3011 3012 @Override 3013 public StorageVolume[] getVolumeList(int uid, String packageName, int flags) { 3014 final int userId = UserHandle.getUserId(uid); 3015 3016 final boolean forWrite = (flags & StorageManager.FLAG_FOR_WRITE) != 0; 3017 final boolean realState = (flags & StorageManager.FLAG_REAL_STATE) != 0; 3018 final boolean includeInvisible = (flags & StorageManager.FLAG_INCLUDE_INVISIBLE) != 0; 3019 3020 // Report all volumes as unmounted until we've recorded that user 0 has unlocked. There 3021 // are no guarantees that callers will see a consistent view of the volume before that 3022 // point 3023 final boolean systemUserUnlocked = isSystemUnlocked(UserHandle.USER_SYSTEM); 3024 3025 final boolean userKeyUnlocked; 3026 final boolean storagePermission; 3027 final long token = Binder.clearCallingIdentity(); 3028 try { 3029 userKeyUnlocked = isUserKeyUnlocked(userId); 3030 storagePermission = mStorageManagerInternal.hasExternalStorage(uid, packageName); 3031 } finally { 3032 Binder.restoreCallingIdentity(token); 3033 } 3034 3035 boolean foundPrimary = false; 3036 3037 final ArrayList<StorageVolume> res = new ArrayList<>(); 3038 synchronized (mLock) { 3039 for (int i = 0; i < mVolumes.size(); i++) { 3040 final VolumeInfo vol = mVolumes.valueAt(i); 3041 switch (vol.getType()) { 3042 case VolumeInfo.TYPE_PUBLIC: 3043 case VolumeInfo.TYPE_STUB: 3044 case VolumeInfo.TYPE_EMULATED: 3045 break; 3046 default: 3047 continue; 3048 } 3049 3050 boolean match = false; 3051 if (forWrite) { 3052 match = vol.isVisibleForWrite(userId); 3053 } else { 3054 match = vol.isVisibleForRead(userId) 3055 || (includeInvisible && vol.getPath() != null); 3056 } 3057 if (!match) continue; 3058 3059 boolean reportUnmounted = false; 3060 if (!systemUserUnlocked) { 3061 reportUnmounted = true; 3062 } else if ((vol.getType() == VolumeInfo.TYPE_EMULATED) && !userKeyUnlocked) { 3063 reportUnmounted = true; 3064 } else if (!storagePermission && !realState) { 3065 reportUnmounted = true; 3066 } 3067 3068 final StorageVolume userVol = vol.buildStorageVolume(mContext, userId, 3069 reportUnmounted); 3070 if (vol.isPrimary()) { 3071 res.add(0, userVol); 3072 foundPrimary = true; 3073 } else { 3074 res.add(userVol); 3075 } 3076 } 3077 } 3078 3079 if (!foundPrimary) { 3080 Slog.w(TAG, "No primary storage defined yet; hacking together a stub"); 3081 3082 final boolean primaryPhysical = SystemProperties.getBoolean( 3083 StorageManager.PROP_PRIMARY_PHYSICAL, false); 3084 3085 final String id = "stub_primary"; 3086 final File path = Environment.getLegacyExternalStorageDirectory(); 3087 final String description = mContext.getString(android.R.string.unknownName); 3088 final boolean primary = true; 3089 final boolean removable = primaryPhysical; 3090 final boolean emulated = !primaryPhysical; 3091 final boolean allowMassStorage = false; 3092 final long maxFileSize = 0L; 3093 final UserHandle owner = new UserHandle(userId); 3094 final String uuid = null; 3095 final String state = Environment.MEDIA_REMOVED; 3096 3097 res.add(0, new StorageVolume(id, path, path, 3098 description, primary, removable, emulated, 3099 allowMassStorage, maxFileSize, owner, uuid, state)); 3100 } 3101 3102 return res.toArray(new StorageVolume[res.size()]); 3103 } 3104 3105 @Override 3106 public DiskInfo[] getDisks() { 3107 synchronized (mLock) { 3108 final DiskInfo[] res = new DiskInfo[mDisks.size()]; 3109 for (int i = 0; i < mDisks.size(); i++) { 3110 res[i] = mDisks.valueAt(i); 3111 } 3112 return res; 3113 } 3114 } 3115 3116 @Override 3117 public VolumeInfo[] getVolumes(int flags) { 3118 synchronized (mLock) { 3119 final VolumeInfo[] res = new VolumeInfo[mVolumes.size()]; 3120 for (int i = 0; i < mVolumes.size(); i++) { 3121 res[i] = mVolumes.valueAt(i); 3122 } 3123 return res; 3124 } 3125 } 3126 3127 @Override 3128 public VolumeRecord[] getVolumeRecords(int flags) { 3129 synchronized (mLock) { 3130 final VolumeRecord[] res = new VolumeRecord[mRecords.size()]; 3131 for (int i = 0; i < mRecords.size(); i++) { 3132 res[i] = mRecords.valueAt(i); 3133 } 3134 return res; 3135 } 3136 } 3137 3138 @Override 3139 public long getCacheQuotaBytes(String volumeUuid, int uid) { 3140 if (uid != Binder.getCallingUid()) { 3141 mContext.enforceCallingPermission(android.Manifest.permission.STORAGE_INTERNAL, TAG); 3142 } 3143 final long token = Binder.clearCallingIdentity(); 3144 final StorageStatsManager stats = mContext.getSystemService(StorageStatsManager.class); 3145 try { 3146 return stats.getCacheQuotaBytes(volumeUuid, uid); 3147 } finally { 3148 Binder.restoreCallingIdentity(token); 3149 } 3150 } 3151 3152 @Override 3153 public long getCacheSizeBytes(String volumeUuid, int uid) { 3154 if (uid != Binder.getCallingUid()) { 3155 mContext.enforceCallingPermission(android.Manifest.permission.STORAGE_INTERNAL, TAG); 3156 } 3157 final long token = Binder.clearCallingIdentity(); 3158 try { 3159 return mContext.getSystemService(StorageStatsManager.class) 3160 .queryStatsForUid(volumeUuid, uid).getCacheBytes(); 3161 } catch (IOException e) { 3162 throw new ParcelableException(e); 3163 } finally { 3164 Binder.restoreCallingIdentity(token); 3165 } 3166 } 3167 3168 private int adjustAllocateFlags(int flags, int callingUid, String callingPackage) { 3169 // Require permission to allocate aggressively 3170 if ((flags & StorageManager.FLAG_ALLOCATE_AGGRESSIVE) != 0) { 3171 mContext.enforceCallingOrSelfPermission( 3172 android.Manifest.permission.ALLOCATE_AGGRESSIVE, TAG); 3173 } 3174 3175 // Apps normally can't directly defy reserved space 3176 flags &= ~StorageManager.FLAG_ALLOCATE_DEFY_ALL_RESERVED; 3177 flags &= ~StorageManager.FLAG_ALLOCATE_DEFY_HALF_RESERVED; 3178 3179 // However, if app is actively using the camera, then we're willing to 3180 // clear up to half of the reserved cache space, since the user might be 3181 // trying to capture an important memory. 3182 final AppOpsManager appOps = mContext.getSystemService(AppOpsManager.class); 3183 final long token = Binder.clearCallingIdentity(); 3184 try { 3185 if (appOps.isOperationActive(AppOpsManager.OP_CAMERA, callingUid, callingPackage)) { 3186 Slog.d(TAG, "UID " + callingUid + " is actively using camera;" 3187 + " letting them defy reserved cached data"); 3188 flags |= StorageManager.FLAG_ALLOCATE_DEFY_HALF_RESERVED; 3189 } 3190 } finally { 3191 Binder.restoreCallingIdentity(token); 3192 } 3193 3194 return flags; 3195 } 3196 3197 @Override 3198 public long getAllocatableBytes(String volumeUuid, int flags, String callingPackage) { 3199 flags = adjustAllocateFlags(flags, Binder.getCallingUid(), callingPackage); 3200 3201 final StorageManager storage = mContext.getSystemService(StorageManager.class); 3202 final StorageStatsManager stats = mContext.getSystemService(StorageStatsManager.class); 3203 final long token = Binder.clearCallingIdentity(); 3204 try { 3205 // In general, apps can allocate as much space as they want, except 3206 // we never let them eat into either the minimum cache space or into 3207 // the low disk warning space. To avoid user confusion, this logic 3208 // should be kept in sync with getFreeBytes(). 3209 final File path = storage.findPathForUuid(volumeUuid); 3210 3211 final long usable = path.getUsableSpace(); 3212 final long lowReserved = storage.getStorageLowBytes(path); 3213 final long fullReserved = storage.getStorageFullBytes(path); 3214 3215 if (stats.isQuotaSupported(volumeUuid)) { 3216 final long cacheTotal = stats.getCacheBytes(volumeUuid); 3217 final long cacheReserved = storage.getStorageCacheBytes(path, flags); 3218 final long cacheClearable = Math.max(0, cacheTotal - cacheReserved); 3219 3220 if ((flags & StorageManager.FLAG_ALLOCATE_AGGRESSIVE) != 0) { 3221 return Math.max(0, (usable + cacheClearable) - fullReserved); 3222 } else { 3223 return Math.max(0, (usable + cacheClearable) - lowReserved); 3224 } 3225 } else { 3226 // When we don't have fast quota information, we ignore cached 3227 // data and only consider unused bytes. 3228 if ((flags & StorageManager.FLAG_ALLOCATE_AGGRESSIVE) != 0) { 3229 return Math.max(0, usable - fullReserved); 3230 } else { 3231 return Math.max(0, usable - lowReserved); 3232 } 3233 } 3234 } catch (IOException e) { 3235 throw new ParcelableException(e); 3236 } finally { 3237 Binder.restoreCallingIdentity(token); 3238 } 3239 } 3240 3241 @Override 3242 public void allocateBytes(String volumeUuid, long bytes, int flags, String callingPackage) { 3243 flags = adjustAllocateFlags(flags, Binder.getCallingUid(), callingPackage); 3244 3245 final long allocatableBytes = getAllocatableBytes(volumeUuid, flags, callingPackage); 3246 if (bytes > allocatableBytes) { 3247 throw new ParcelableException(new IOException("Failed to allocate " + bytes 3248 + " because only " + allocatableBytes + " allocatable")); 3249 } 3250 3251 final StorageManager storage = mContext.getSystemService(StorageManager.class); 3252 final long token = Binder.clearCallingIdentity(); 3253 try { 3254 // Free up enough disk space to satisfy both the requested allocation 3255 // and our low disk warning space. 3256 final File path = storage.findPathForUuid(volumeUuid); 3257 if ((flags & StorageManager.FLAG_ALLOCATE_AGGRESSIVE) != 0) { 3258 bytes += storage.getStorageFullBytes(path); 3259 } else { 3260 bytes += storage.getStorageLowBytes(path); 3261 } 3262 3263 mPmInternal.freeStorage(volumeUuid, bytes, flags); 3264 } catch (IOException e) { 3265 throw new ParcelableException(e); 3266 } finally { 3267 Binder.restoreCallingIdentity(token); 3268 } 3269 } 3270 3271 private IAppOpsCallback.Stub mAppOpsCallback = new IAppOpsCallback.Stub() { 3272 @Override 3273 public void opChanged(int op, int uid, String packageName) throws RemoteException { 3274 if (!ENABLE_ISOLATED_STORAGE) return; 3275 3276 remountUidExternalStorage(uid, getMountMode(uid, packageName)); 3277 } 3278 }; 3279 3280 private void addObbStateLocked(ObbState obbState) throws RemoteException { 3281 final IBinder binder = obbState.getBinder(); 3282 List<ObbState> obbStates = mObbMounts.get(binder); 3283 3284 if (obbStates == null) { 3285 obbStates = new ArrayList<ObbState>(); 3286 mObbMounts.put(binder, obbStates); 3287 } else { 3288 for (final ObbState o : obbStates) { 3289 if (o.rawPath.equals(obbState.rawPath)) { 3290 throw new IllegalStateException("Attempt to add ObbState twice. " 3291 + "This indicates an error in the StorageManagerService logic."); 3292 } 3293 } 3294 } 3295 3296 obbStates.add(obbState); 3297 try { 3298 obbState.link(); 3299 } catch (RemoteException e) { 3300 /* 3301 * The binder died before we could link it, so clean up our state 3302 * and return failure. 3303 */ 3304 obbStates.remove(obbState); 3305 if (obbStates.isEmpty()) { 3306 mObbMounts.remove(binder); 3307 } 3308 3309 // Rethrow the error so mountObb can get it 3310 throw e; 3311 } 3312 3313 mObbPathToStateMap.put(obbState.rawPath, obbState); 3314 } 3315 3316 private void removeObbStateLocked(ObbState obbState) { 3317 final IBinder binder = obbState.getBinder(); 3318 final List<ObbState> obbStates = mObbMounts.get(binder); 3319 if (obbStates != null) { 3320 if (obbStates.remove(obbState)) { 3321 obbState.unlink(); 3322 } 3323 if (obbStates.isEmpty()) { 3324 mObbMounts.remove(binder); 3325 } 3326 } 3327 3328 mObbPathToStateMap.remove(obbState.rawPath); 3329 } 3330 3331 private class ObbActionHandler extends Handler { 3332 3333 ObbActionHandler(Looper l) { 3334 super(l); 3335 } 3336 3337 @Override 3338 public void handleMessage(Message msg) { 3339 switch (msg.what) { 3340 case OBB_RUN_ACTION: { 3341 final ObbAction action = (ObbAction) msg.obj; 3342 3343 if (DEBUG_OBB) 3344 Slog.i(TAG, "OBB_RUN_ACTION: " + action.toString()); 3345 3346 action.execute(this); 3347 break; 3348 } 3349 case OBB_FLUSH_MOUNT_STATE: { 3350 final String path = (String) msg.obj; 3351 3352 if (DEBUG_OBB) 3353 Slog.i(TAG, "Flushing all OBB state for path " + path); 3354 3355 synchronized (mObbMounts) { 3356 final List<ObbState> obbStatesToRemove = new LinkedList<ObbState>(); 3357 3358 final Iterator<ObbState> i = mObbPathToStateMap.values().iterator(); 3359 while (i.hasNext()) { 3360 final ObbState state = i.next(); 3361 3362 /* 3363 * If this entry's source file is in the volume path 3364 * that got unmounted, remove it because it's no 3365 * longer valid. 3366 */ 3367 if (state.canonicalPath.startsWith(path)) { 3368 obbStatesToRemove.add(state); 3369 } 3370 } 3371 3372 for (final ObbState obbState : obbStatesToRemove) { 3373 if (DEBUG_OBB) 3374 Slog.i(TAG, "Removing state for " + obbState.rawPath); 3375 3376 removeObbStateLocked(obbState); 3377 3378 try { 3379 obbState.token.onObbResult(obbState.rawPath, obbState.nonce, 3380 OnObbStateChangeListener.UNMOUNTED); 3381 } catch (RemoteException e) { 3382 Slog.i(TAG, "Couldn't send unmount notification for OBB: " 3383 + obbState.rawPath); 3384 } 3385 } 3386 } 3387 break; 3388 } 3389 } 3390 } 3391 } 3392 3393 private static class ObbException extends Exception { 3394 public final int status; 3395 3396 public ObbException(int status, String message) { 3397 super(message); 3398 this.status = status; 3399 } 3400 3401 public ObbException(int status, Throwable cause) { 3402 super(cause.getMessage(), cause); 3403 this.status = status; 3404 } 3405 } 3406 3407 abstract class ObbAction { 3408 3409 ObbState mObbState; 3410 3411 ObbAction(ObbState obbState) { 3412 mObbState = obbState; 3413 } 3414 3415 public void execute(ObbActionHandler handler) { 3416 try { 3417 if (DEBUG_OBB) 3418 Slog.i(TAG, "Starting to execute action: " + toString()); 3419 handleExecute(); 3420 } catch (ObbException e) { 3421 notifyObbStateChange(e); 3422 } 3423 } 3424 3425 abstract void handleExecute() throws ObbException; 3426 3427 protected void notifyObbStateChange(ObbException e) { 3428 Slog.w(TAG, e); 3429 notifyObbStateChange(e.status); 3430 } 3431 3432 protected void notifyObbStateChange(int status) { 3433 if (mObbState == null || mObbState.token == null) { 3434 return; 3435 } 3436 3437 try { 3438 mObbState.token.onObbResult(mObbState.rawPath, mObbState.nonce, status); 3439 } catch (RemoteException e) { 3440 Slog.w(TAG, "StorageEventListener went away while calling onObbStateChanged"); 3441 } 3442 } 3443 } 3444 3445 class MountObbAction extends ObbAction { 3446 private final String mKey; 3447 private final int mCallingUid; 3448 private ObbInfo mObbInfo; 3449 3450 MountObbAction(ObbState obbState, String key, int callingUid, ObbInfo obbInfo) { 3451 super(obbState); 3452 mKey = key; 3453 mCallingUid = callingUid; 3454 mObbInfo = obbInfo; 3455 } 3456 3457 @Override 3458 public void handleExecute() throws ObbException { 3459 warnOnNotMounted(); 3460 3461 if (!isUidOwnerOfPackageOrSystem(mObbInfo.packageName, mCallingUid)) { 3462 throw new ObbException(ERROR_PERMISSION_DENIED, "Denied attempt to mount OBB " 3463 + mObbInfo.filename + " which is owned by " + mObbInfo.packageName); 3464 } 3465 3466 final boolean isMounted; 3467 synchronized (mObbMounts) { 3468 isMounted = mObbPathToStateMap.containsKey(mObbState.rawPath); 3469 } 3470 if (isMounted) { 3471 throw new ObbException(ERROR_ALREADY_MOUNTED, 3472 "Attempt to mount OBB which is already mounted: " + mObbInfo.filename); 3473 } 3474 3475 final String hashedKey; 3476 final String binderKey; 3477 if (mKey == null) { 3478 hashedKey = "none"; 3479 binderKey = ""; 3480 } else { 3481 try { 3482 SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1"); 3483 3484 KeySpec ks = new PBEKeySpec(mKey.toCharArray(), mObbInfo.salt, 3485 PBKDF2_HASH_ROUNDS, CRYPTO_ALGORITHM_KEY_SIZE); 3486 SecretKey key = factory.generateSecret(ks); 3487 BigInteger bi = new BigInteger(key.getEncoded()); 3488 hashedKey = bi.toString(16); 3489 binderKey = hashedKey; 3490 } catch (GeneralSecurityException e) { 3491 throw new ObbException(ERROR_INTERNAL, e); 3492 } 3493 } 3494 3495 try { 3496 mObbState.volId = mVold.createObb(mObbState.canonicalPath, binderKey, 3497 mObbState.ownerGid); 3498 mVold.mount(mObbState.volId, 0, -1); 3499 3500 if (DEBUG_OBB) 3501 Slog.d(TAG, "Successfully mounted OBB " + mObbState.canonicalPath); 3502 3503 synchronized (mObbMounts) { 3504 addObbStateLocked(mObbState); 3505 } 3506 3507 notifyObbStateChange(MOUNTED); 3508 } catch (Exception e) { 3509 throw new ObbException(ERROR_COULD_NOT_MOUNT, e); 3510 } 3511 } 3512 3513 @Override 3514 public String toString() { 3515 StringBuilder sb = new StringBuilder(); 3516 sb.append("MountObbAction{"); 3517 sb.append(mObbState); 3518 sb.append('}'); 3519 return sb.toString(); 3520 } 3521 } 3522 3523 class UnmountObbAction extends ObbAction { 3524 private final boolean mForceUnmount; 3525 3526 UnmountObbAction(ObbState obbState, boolean force) { 3527 super(obbState); 3528 mForceUnmount = force; 3529 } 3530 3531 @Override 3532 public void handleExecute() throws ObbException { 3533 warnOnNotMounted(); 3534 3535 final ObbState existingState; 3536 synchronized (mObbMounts) { 3537 existingState = mObbPathToStateMap.get(mObbState.rawPath); 3538 } 3539 3540 if (existingState == null) { 3541 throw new ObbException(ERROR_NOT_MOUNTED, "Missing existingState"); 3542 } 3543 3544 if (existingState.ownerGid != mObbState.ownerGid) { 3545 notifyObbStateChange(new ObbException(ERROR_PERMISSION_DENIED, 3546 "Permission denied to unmount OBB " + existingState.rawPath 3547 + " (owned by GID " + existingState.ownerGid + ")")); 3548 return; 3549 } 3550 3551 try { 3552 mVold.unmount(mObbState.volId); 3553 mVold.destroyObb(mObbState.volId); 3554 mObbState.volId = null; 3555 3556 synchronized (mObbMounts) { 3557 removeObbStateLocked(existingState); 3558 } 3559 3560 notifyObbStateChange(UNMOUNTED); 3561 } catch (Exception e) { 3562 throw new ObbException(ERROR_COULD_NOT_UNMOUNT, e); 3563 } 3564 } 3565 3566 @Override 3567 public String toString() { 3568 StringBuilder sb = new StringBuilder(); 3569 sb.append("UnmountObbAction{"); 3570 sb.append(mObbState); 3571 sb.append(",force="); 3572 sb.append(mForceUnmount); 3573 sb.append('}'); 3574 return sb.toString(); 3575 } 3576 } 3577 3578 private void dispatchOnStatus(IVoldTaskListener listener, int status, 3579 PersistableBundle extras) { 3580 if (listener != null) { 3581 try { 3582 listener.onStatus(status, extras); 3583 } catch (RemoteException ignored) { 3584 } 3585 } 3586 } 3587 3588 private void dispatchOnFinished(IVoldTaskListener listener, int status, 3589 PersistableBundle extras) { 3590 if (listener != null) { 3591 try { 3592 listener.onFinished(status, extras); 3593 } catch (RemoteException ignored) { 3594 } 3595 } 3596 } 3597 3598 private int getMountMode(int uid, String packageName) { 3599 final int mode = getMountModeInternal(uid, packageName); 3600 if (LOCAL_LOGV) { 3601 Slog.v(TAG, "Resolved mode " + mode + " for " + packageName + "/" 3602 + UserHandle.formatUid(uid)); 3603 } 3604 return mode; 3605 } 3606 3607 private int getMountModeInternal(int uid, String packageName) { 3608 try { 3609 // Get some easy cases out of the way first 3610 if (Process.isIsolated(uid)) { 3611 return Zygote.MOUNT_EXTERNAL_NONE; 3612 } 3613 3614 final String[] packagesForUid = mIPackageManager.getPackagesForUid(uid); 3615 if (ArrayUtils.isEmpty(packagesForUid)) { 3616 // It's possible the package got uninstalled already, so just ignore. 3617 return Zygote.MOUNT_EXTERNAL_NONE; 3618 } 3619 if (packageName == null) { 3620 packageName = packagesForUid[0]; 3621 } 3622 3623 if (mPmInternal.isInstantApp(packageName, UserHandle.getUserId(uid))) { 3624 return Zygote.MOUNT_EXTERNAL_NONE; 3625 } 3626 3627 // Determine if caller is holding runtime permission 3628 final boolean hasRead = StorageManager.checkPermissionAndCheckOp(mContext, false, 0, 3629 uid, packageName, READ_EXTERNAL_STORAGE, OP_READ_EXTERNAL_STORAGE); 3630 final boolean hasWrite = StorageManager.checkPermissionAndCheckOp(mContext, false, 0, 3631 uid, packageName, WRITE_EXTERNAL_STORAGE, OP_WRITE_EXTERNAL_STORAGE); 3632 3633 // We're only willing to give out broad access if they also hold 3634 // runtime permission; this is a firm CDD requirement 3635 final boolean hasFull = mIPackageManager.checkUidPermission(WRITE_MEDIA_STORAGE, 3636 uid) == PERMISSION_GRANTED; 3637 if (hasFull && hasWrite) { 3638 return Zygote.MOUNT_EXTERNAL_FULL; 3639 } 3640 3641 // We're only willing to give out installer access if they also hold 3642 // runtime permission; this is a firm CDD requirement 3643 final boolean hasInstall = mIPackageManager.checkUidPermission(INSTALL_PACKAGES, 3644 uid) == PERMISSION_GRANTED; 3645 boolean hasInstallOp = false; 3646 // OP_REQUEST_INSTALL_PACKAGES is granted/denied per package but vold can't 3647 // update mountpoints of a specific package. So, check the appop for all packages 3648 // sharing the uid and allow same level of storage access for all packages even if 3649 // one of the packages has the appop granted. 3650 for (String uidPackageName : packagesForUid) { 3651 if (mIAppOpsService.checkOperation( 3652 OP_REQUEST_INSTALL_PACKAGES, uid, uidPackageName) == MODE_ALLOWED) { 3653 hasInstallOp = true; 3654 break; 3655 } 3656 } 3657 if ((hasInstall || hasInstallOp) && hasWrite) { 3658 return Zygote.MOUNT_EXTERNAL_WRITE; 3659 } 3660 3661 // Otherwise we're willing to give out sandboxed or non-sandboxed if 3662 // they hold the runtime permission 3663 final boolean hasLegacy = mIAppOpsService.checkOperation(OP_LEGACY_STORAGE, 3664 uid, packageName) == MODE_ALLOWED; 3665 if (hasLegacy && hasWrite) { 3666 return Zygote.MOUNT_EXTERNAL_WRITE; 3667 } else if (hasLegacy && hasRead) { 3668 return Zygote.MOUNT_EXTERNAL_READ; 3669 } else { 3670 return Zygote.MOUNT_EXTERNAL_DEFAULT; 3671 } 3672 } catch (RemoteException e) { 3673 // Should not happen 3674 } 3675 return Zygote.MOUNT_EXTERNAL_NONE; 3676 } 3677 3678 private static class Callbacks extends Handler { 3679 private static final int MSG_STORAGE_STATE_CHANGED = 1; 3680 private static final int MSG_VOLUME_STATE_CHANGED = 2; 3681 private static final int MSG_VOLUME_RECORD_CHANGED = 3; 3682 private static final int MSG_VOLUME_FORGOTTEN = 4; 3683 private static final int MSG_DISK_SCANNED = 5; 3684 private static final int MSG_DISK_DESTROYED = 6; 3685 3686 private final RemoteCallbackList<IStorageEventListener> 3687 mCallbacks = new RemoteCallbackList<>(); 3688 3689 public Callbacks(Looper looper) { 3690 super(looper); 3691 } 3692 3693 public void register(IStorageEventListener callback) { 3694 mCallbacks.register(callback); 3695 } 3696 3697 public void unregister(IStorageEventListener callback) { 3698 mCallbacks.unregister(callback); 3699 } 3700 3701 @Override 3702 public void handleMessage(Message msg) { 3703 final SomeArgs args = (SomeArgs) msg.obj; 3704 final int n = mCallbacks.beginBroadcast(); 3705 for (int i = 0; i < n; i++) { 3706 final IStorageEventListener callback = mCallbacks.getBroadcastItem(i); 3707 try { 3708 invokeCallback(callback, msg.what, args); 3709 } catch (RemoteException ignored) { 3710 } 3711 } 3712 mCallbacks.finishBroadcast(); 3713 args.recycle(); 3714 } 3715 3716 private void invokeCallback(IStorageEventListener callback, int what, SomeArgs args) 3717 throws RemoteException { 3718 switch (what) { 3719 case MSG_STORAGE_STATE_CHANGED: { 3720 callback.onStorageStateChanged((String) args.arg1, (String) args.arg2, 3721 (String) args.arg3); 3722 break; 3723 } 3724 case MSG_VOLUME_STATE_CHANGED: { 3725 callback.onVolumeStateChanged((VolumeInfo) args.arg1, args.argi2, args.argi3); 3726 break; 3727 } 3728 case MSG_VOLUME_RECORD_CHANGED: { 3729 callback.onVolumeRecordChanged((VolumeRecord) args.arg1); 3730 break; 3731 } 3732 case MSG_VOLUME_FORGOTTEN: { 3733 callback.onVolumeForgotten((String) args.arg1); 3734 break; 3735 } 3736 case MSG_DISK_SCANNED: { 3737 callback.onDiskScanned((DiskInfo) args.arg1, args.argi2); 3738 break; 3739 } 3740 case MSG_DISK_DESTROYED: { 3741 callback.onDiskDestroyed((DiskInfo) args.arg1); 3742 break; 3743 } 3744 } 3745 } 3746 3747 private void notifyStorageStateChanged(String path, String oldState, String newState) { 3748 final SomeArgs args = SomeArgs.obtain(); 3749 args.arg1 = path; 3750 args.arg2 = oldState; 3751 args.arg3 = newState; 3752 obtainMessage(MSG_STORAGE_STATE_CHANGED, args).sendToTarget(); 3753 } 3754 3755 private void notifyVolumeStateChanged(VolumeInfo vol, int oldState, int newState) { 3756 final SomeArgs args = SomeArgs.obtain(); 3757 args.arg1 = vol.clone(); 3758 args.argi2 = oldState; 3759 args.argi3 = newState; 3760 obtainMessage(MSG_VOLUME_STATE_CHANGED, args).sendToTarget(); 3761 } 3762 3763 private void notifyVolumeRecordChanged(VolumeRecord rec) { 3764 final SomeArgs args = SomeArgs.obtain(); 3765 args.arg1 = rec.clone(); 3766 obtainMessage(MSG_VOLUME_RECORD_CHANGED, args).sendToTarget(); 3767 } 3768 3769 private void notifyVolumeForgotten(String fsUuid) { 3770 final SomeArgs args = SomeArgs.obtain(); 3771 args.arg1 = fsUuid; 3772 obtainMessage(MSG_VOLUME_FORGOTTEN, args).sendToTarget(); 3773 } 3774 3775 private void notifyDiskScanned(DiskInfo disk, int volumeCount) { 3776 final SomeArgs args = SomeArgs.obtain(); 3777 args.arg1 = disk.clone(); 3778 args.argi2 = volumeCount; 3779 obtainMessage(MSG_DISK_SCANNED, args).sendToTarget(); 3780 } 3781 3782 private void notifyDiskDestroyed(DiskInfo disk) { 3783 final SomeArgs args = SomeArgs.obtain(); 3784 args.arg1 = disk.clone(); 3785 obtainMessage(MSG_DISK_DESTROYED, args).sendToTarget(); 3786 } 3787 } 3788 3789 @Override 3790 protected void dump(FileDescriptor fd, PrintWriter writer, String[] args) { 3791 if (!DumpUtils.checkDumpPermission(mContext, TAG, writer)) return; 3792 3793 final IndentingPrintWriter pw = new IndentingPrintWriter(writer, " ", 160); 3794 synchronized (mLock) { 3795 pw.println("Disks:"); 3796 pw.increaseIndent(); 3797 for (int i = 0; i < mDisks.size(); i++) { 3798 final DiskInfo disk = mDisks.valueAt(i); 3799 disk.dump(pw); 3800 } 3801 pw.decreaseIndent(); 3802 3803 pw.println(); 3804 pw.println("Volumes:"); 3805 pw.increaseIndent(); 3806 for (int i = 0; i < mVolumes.size(); i++) { 3807 final VolumeInfo vol = mVolumes.valueAt(i); 3808 if (VolumeInfo.ID_PRIVATE_INTERNAL.equals(vol.id)) continue; 3809 vol.dump(pw); 3810 } 3811 pw.decreaseIndent(); 3812 3813 pw.println(); 3814 pw.println("Records:"); 3815 pw.increaseIndent(); 3816 for (int i = 0; i < mRecords.size(); i++) { 3817 final VolumeRecord note = mRecords.valueAt(i); 3818 note.dump(pw); 3819 } 3820 pw.decreaseIndent(); 3821 3822 pw.println(); 3823 pw.println("Primary storage UUID: " + mPrimaryStorageUuid); 3824 3825 pw.println(); 3826 final Pair<String, Long> pair = StorageManager.getPrimaryStoragePathAndSize(); 3827 if (pair == null) { 3828 pw.println("Internal storage total size: N/A"); 3829 } else { 3830 pw.print("Internal storage ("); 3831 pw.print(pair.first); 3832 pw.print(") total size: "); 3833 pw.print(pair.second); 3834 pw.print(" ("); 3835 pw.print(DataUnit.MEBIBYTES.toBytes(pair.second)); 3836 pw.println(" MiB)"); 3837 } 3838 3839 pw.println(); 3840 pw.println("Local unlocked users: " + Arrays.toString(mLocalUnlockedUsers)); 3841 pw.println("System unlocked users: " + Arrays.toString(mSystemUnlockedUsers)); 3842 3843 final ContentResolver cr = mContext.getContentResolver(); 3844 pw.println(); 3845 pw.println("Isolated storage, local feature flag: " 3846 + Settings.Global.getInt(cr, Settings.Global.ISOLATED_STORAGE_LOCAL, 0)); 3847 pw.println("Isolated storage, remote feature flag: " 3848 + Settings.Global.getInt(cr, Settings.Global.ISOLATED_STORAGE_REMOTE, 0)); 3849 pw.println("Isolated storage, resolved: " + StorageManager.hasIsolatedStorage()); 3850 } 3851 3852 synchronized (mObbMounts) { 3853 pw.println(); 3854 pw.println("mObbMounts:"); 3855 pw.increaseIndent(); 3856 final Iterator<Entry<IBinder, List<ObbState>>> binders = mObbMounts.entrySet() 3857 .iterator(); 3858 while (binders.hasNext()) { 3859 Entry<IBinder, List<ObbState>> e = binders.next(); 3860 pw.println(e.getKey() + ":"); 3861 pw.increaseIndent(); 3862 final List<ObbState> obbStates = e.getValue(); 3863 for (final ObbState obbState : obbStates) { 3864 pw.println(obbState); 3865 } 3866 pw.decreaseIndent(); 3867 } 3868 pw.decreaseIndent(); 3869 3870 pw.println(); 3871 pw.println("mObbPathToStateMap:"); 3872 pw.increaseIndent(); 3873 final Iterator<Entry<String, ObbState>> maps = mObbPathToStateMap.entrySet().iterator(); 3874 while (maps.hasNext()) { 3875 final Entry<String, ObbState> e = maps.next(); 3876 pw.print(e.getKey()); 3877 pw.print(" -> "); 3878 pw.println(e.getValue()); 3879 } 3880 pw.decreaseIndent(); 3881 } 3882 3883 pw.println(); 3884 pw.print("Last maintenance: "); 3885 pw.println(TimeUtils.formatForLogging(mLastMaintenance)); 3886 } 3887 3888 /** {@inheritDoc} */ 3889 @Override 3890 public void monitor() { 3891 try { 3892 mVold.monitor(); 3893 } catch (Exception e) { 3894 Slog.wtf(TAG, e); 3895 } 3896 } 3897 3898 private final class StorageManagerInternalImpl extends StorageManagerInternal { 3899 // Not guarded by a lock. 3900 private final CopyOnWriteArrayList<ExternalStorageMountPolicy> mPolicies = 3901 new CopyOnWriteArrayList<>(); 3902 3903 @GuardedBy("mResetListeners") 3904 private final List<StorageManagerInternal.ResetListener> mResetListeners = 3905 new ArrayList<>(); 3906 3907 @Override 3908 public void addExternalStoragePolicy(ExternalStorageMountPolicy policy) { 3909 // No locking - CopyOnWriteArrayList 3910 mPolicies.add(policy); 3911 } 3912 3913 @Override 3914 public void onExternalStoragePolicyChanged(int uid, String packageName) { 3915 final int mountMode = getExternalStorageMountMode(uid, packageName); 3916 remountUidExternalStorage(uid, mountMode); 3917 } 3918 3919 @Override 3920 public int getExternalStorageMountMode(int uid, String packageName) { 3921 if (ENABLE_ISOLATED_STORAGE) { 3922 return getMountMode(uid, packageName); 3923 } 3924 try { 3925 if (packageName == null) { 3926 final String[] packagesForUid = mIPackageManager.getPackagesForUid(uid); 3927 packageName = packagesForUid[0]; 3928 } 3929 } catch (RemoteException e) { 3930 // Should not happen - same process 3931 } 3932 // No locking - CopyOnWriteArrayList 3933 int mountMode = Integer.MAX_VALUE; 3934 for (ExternalStorageMountPolicy policy : mPolicies) { 3935 final int policyMode = policy.getMountMode(uid, packageName); 3936 if (policyMode == Zygote.MOUNT_EXTERNAL_NONE) { 3937 return Zygote.MOUNT_EXTERNAL_NONE; 3938 } 3939 mountMode = Math.min(mountMode, policyMode); 3940 } 3941 if (mountMode == Integer.MAX_VALUE) { 3942 return Zygote.MOUNT_EXTERNAL_NONE; 3943 } 3944 return mountMode; 3945 } 3946 3947 @Override 3948 public void addResetListener(StorageManagerInternal.ResetListener listener) { 3949 synchronized (mResetListeners) { 3950 mResetListeners.add(listener); 3951 } 3952 } 3953 3954 public void onReset(IVold vold) { 3955 synchronized (mResetListeners) { 3956 for (StorageManagerInternal.ResetListener listener : mResetListeners) { 3957 listener.onReset(vold); 3958 } 3959 } 3960 } 3961 3962 public boolean hasExternalStorage(int uid, String packageName) { 3963 // No need to check for system uid. This avoids a deadlock between 3964 // PackageManagerService and AppOpsService. 3965 if (uid == Process.SYSTEM_UID) { 3966 return true; 3967 } 3968 if (ENABLE_ISOLATED_STORAGE) { 3969 return getMountMode(uid, packageName) != Zygote.MOUNT_EXTERNAL_NONE; 3970 } 3971 // No locking - CopyOnWriteArrayList 3972 for (ExternalStorageMountPolicy policy : mPolicies) { 3973 final boolean policyHasStorage = policy.hasExternalStorage(uid, packageName); 3974 if (!policyHasStorage) { 3975 return false; 3976 } 3977 } 3978 return true; 3979 } 3980 3981 public void onAppOpsChanged(int code, int uid, 3982 @Nullable String packageName, int mode) { 3983 if (mode == MODE_ALLOWED && (code == OP_READ_EXTERNAL_STORAGE 3984 || code == OP_WRITE_EXTERNAL_STORAGE 3985 || code == OP_REQUEST_INSTALL_PACKAGES)) { 3986 final long token = Binder.clearCallingIdentity(); 3987 try { 3988 final UserManagerInternal userManagerInternal = 3989 LocalServices.getService(UserManagerInternal.class); 3990 if (userManagerInternal.isUserInitialized(UserHandle.getUserId(uid))) { 3991 onExternalStoragePolicyChanged(uid, packageName); 3992 } 3993 } finally { 3994 Binder.restoreCallingIdentity(token); 3995 } 3996 } 3997 } 3998 } 3999 } 4000