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 Lifecycle(Context context)210 public Lifecycle(Context context) { 211 super(context); 212 } 213 214 @Override onStart()215 public void onStart() { 216 mStorageManagerService = new StorageManagerService(getContext()); 217 publishBinderService("mount", mStorageManagerService); 218 mStorageManagerService.start(); 219 } 220 221 @Override onBootPhase(int phase)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 onSwitchUser(int userHandle)233 public void onSwitchUser(int userHandle) { 234 mStorageManagerService.mCurrentUserId = userHandle; 235 } 236 237 @Override onUnlockUser(int userHandle)238 public void onUnlockUser(int userHandle) { 239 mStorageManagerService.onUnlockUser(userHandle); 240 } 241 242 @Override onCleanupUser(int userHandle)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 findVolumeByIdOrThrow(String id)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 findVolumeIdForPathOrThrow(String path)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 findRecordForPath(String path)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 scrubPath(String path)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 findStorageForUuid(String volumeUuid)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 shouldBenchmark()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 findOrCreateDiskScanLatch(String diskId)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 { ObbState(String rawPath, String canonicalPath, int callingUid, IObbActionListener token, int nonce, String volId)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 getBinder()525 public IBinder getBinder() { 526 return token.asBinder(); 527 } 528 529 @Override binderDied()530 public void binderDied() { 531 ObbAction action = new UnmountObbAction(this, true); 532 mObbActionHandler.sendMessage(mObbActionHandler.obtainMessage(OBB_RUN_ACTION, action)); 533 } 534 link()535 public void link() throws RemoteException { 536 getBinder().linkToDeath(this, 0); 537 } 538 unlink()539 public void unlink() { 540 getBinder().unlinkToDeath(this, 0); 541 } 542 543 @Override toString()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 { StorageManagerServiceHandler(Looper looper)586 public StorageManagerServiceHandler(Looper looper) { 587 super(looper); 588 } 589 590 @Override handleMessage(Message msg)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 waitForLatch(CountDownLatch latch, String condition, long timeoutMillis)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 handleSystemReady()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 */ refreshZramSettings()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 refreshIsolatedStorageSettings()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 killMediaProvider(List<UserInfo> users)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") addInternalVolumeLocked()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 initIfBootedAndConnected()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 resetIfBootedAndConnected()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 onUnlockUser(int userId)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 completeUnlockUser(int userId)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 onCleanupUser(int userId)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 supportsBlockCheckpoint()1028 private boolean supportsBlockCheckpoint() throws RemoteException { 1029 enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS); 1030 return mVold.supportsBlockCheckpoint(); 1031 } 1032 1033 @Override onAwakeStateChanged(boolean isAwake)1034 public void onAwakeStateChanged(boolean isAwake) { 1035 // Ignored 1036 } 1037 1038 @Override onKeyguardStateChanged(boolean isShowing)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 runIdleMaintenance(Runnable callback)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 runMaintenance()1057 public void runMaintenance() { 1058 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS); 1059 runIdleMaintenance(null); 1060 } 1061 1062 @Override lastMaintenance()1063 public long lastMaintenance() { 1064 return mLastMaintenance; 1065 } 1066 onDaemonConnected()1067 public void onDaemonConnected() { 1068 mDaemonConnected = true; 1069 mHandler.obtainMessage(H_DAEMON_CONNECTED).sendToTarget(); 1070 } 1071 handleDaemonConnected()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 copyLocaleFromMountService()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") onDiskScannedLocked(DiskInfo disk)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") onVolumeCreatedLocked(VolumeInfo vol)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 isBroadcastWorthy(VolumeInfo vol)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") onVolumeStateChangedLocked(VolumeInfo vol, int oldState, int newState)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 maybeLogMediaMount(VolumeInfo vol, int newState)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") onMoveStatusLocked(int status)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 enforcePermission(String perm)1452 private void enforcePermission(String perm) { 1453 mContext.enforceCallingOrSelfPermission(perm, perm); 1454 } 1455 1456 /** 1457 * Decide if volume is mountable per device policies. 1458 */ isMountDisallowed(VolumeInfo vol)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 enforceAdminUser()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 */ StorageManagerService(Context context)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 start()1559 private void start() { 1560 connectStoraged(); 1561 connectVold(); 1562 } 1563 connectStoraged()1564 private void connectStoraged() { 1565 IBinder binder = ServiceManager.getService("storaged"); 1566 if (binder != null) { 1567 try { 1568 binder.linkToDeath(new DeathRecipient() { 1569 @Override 1570 public void binderDied() { 1571 Slog.w(TAG, "storaged died; reconnecting"); 1572 mStoraged = null; 1573 connectStoraged(); 1574 } 1575 }, 0); 1576 } catch (RemoteException e) { 1577 binder = null; 1578 } 1579 } 1580 1581 if (binder != null) { 1582 mStoraged = IStoraged.Stub.asInterface(binder); 1583 } else { 1584 Slog.w(TAG, "storaged not found; trying again"); 1585 } 1586 1587 if (mStoraged == null) { 1588 BackgroundThread.getHandler().postDelayed(() -> { 1589 connectStoraged(); 1590 }, DateUtils.SECOND_IN_MILLIS); 1591 } else { 1592 onDaemonConnected(); 1593 } 1594 } 1595 connectVold()1596 private void connectVold() { 1597 IBinder binder = ServiceManager.getService("vold"); 1598 if (binder != null) { 1599 try { 1600 binder.linkToDeath(new DeathRecipient() { 1601 @Override 1602 public void binderDied() { 1603 Slog.w(TAG, "vold died; reconnecting"); 1604 mVold = null; 1605 connectVold(); 1606 } 1607 }, 0); 1608 } catch (RemoteException e) { 1609 binder = null; 1610 } 1611 } 1612 1613 if (binder != null) { 1614 mVold = IVold.Stub.asInterface(binder); 1615 try { 1616 mVold.setListener(mListener); 1617 } catch (RemoteException e) { 1618 mVold = null; 1619 Slog.w(TAG, "vold listener rejected; trying again", e); 1620 } 1621 } else { 1622 Slog.w(TAG, "vold not found; trying again"); 1623 } 1624 1625 if (mVold == null) { 1626 BackgroundThread.getHandler().postDelayed(() -> { 1627 connectVold(); 1628 }, DateUtils.SECOND_IN_MILLIS); 1629 } else { 1630 onDaemonConnected(); 1631 } 1632 } 1633 servicesReady()1634 private void servicesReady() { 1635 mPmInternal = LocalServices.getService(PackageManagerInternal.class); 1636 1637 mIPackageManager = IPackageManager.Stub.asInterface( 1638 ServiceManager.getService("package")); 1639 mIAppOpsService = IAppOpsService.Stub.asInterface( 1640 ServiceManager.getService(Context.APP_OPS_SERVICE)); 1641 try { 1642 mIAppOpsService.startWatchingMode(OP_REQUEST_INSTALL_PACKAGES, null, mAppOpsCallback); 1643 mIAppOpsService.startWatchingMode(OP_LEGACY_STORAGE, null, mAppOpsCallback); 1644 } catch (RemoteException e) { 1645 } 1646 } 1647 getLastAccessTime(AppOpsManager manager, int uid, String packageName, int[] ops)1648 private static long getLastAccessTime(AppOpsManager manager, 1649 int uid, String packageName, int[] ops) { 1650 long maxTime = 0; 1651 final List<AppOpsManager.PackageOps> pkgs = manager.getOpsForPackage(uid, packageName, ops); 1652 for (AppOpsManager.PackageOps pkg : CollectionUtils.emptyIfNull(pkgs)) { 1653 for (AppOpsManager.OpEntry op : CollectionUtils.emptyIfNull(pkg.getOps())) { 1654 maxTime = Math.max(maxTime, op.getLastAccessTime( 1655 AppOpsManager.OP_FLAGS_ALL_TRUSTED)); 1656 } 1657 } 1658 return maxTime; 1659 } 1660 systemReady()1661 private void systemReady() { 1662 LocalServices.getService(ActivityTaskManagerInternal.class) 1663 .registerScreenObserver(this); 1664 1665 mHandler.obtainMessage(H_SYSTEM_READY).sendToTarget(); 1666 } 1667 bootCompleted()1668 private void bootCompleted() { 1669 mBootCompleted = true; 1670 mHandler.obtainMessage(H_BOOT_COMPLETED).sendToTarget(); 1671 } 1672 handleBootCompleted()1673 private void handleBootCompleted() { 1674 initIfBootedAndConnected(); 1675 resetIfBootedAndConnected(); 1676 } 1677 getDefaultPrimaryStorageUuid()1678 private String getDefaultPrimaryStorageUuid() { 1679 if (SystemProperties.getBoolean(StorageManager.PROP_PRIMARY_PHYSICAL, false)) { 1680 return StorageManager.UUID_PRIMARY_PHYSICAL; 1681 } else { 1682 return StorageManager.UUID_PRIVATE_INTERNAL; 1683 } 1684 } 1685 1686 @GuardedBy("mLock") readSettingsLocked()1687 private void readSettingsLocked() { 1688 mRecords.clear(); 1689 mPrimaryStorageUuid = getDefaultPrimaryStorageUuid(); 1690 1691 FileInputStream fis = null; 1692 try { 1693 fis = mSettingsFile.openRead(); 1694 final XmlPullParser in = Xml.newPullParser(); 1695 in.setInput(fis, StandardCharsets.UTF_8.name()); 1696 1697 int type; 1698 while ((type = in.next()) != END_DOCUMENT) { 1699 if (type == START_TAG) { 1700 final String tag = in.getName(); 1701 if (TAG_VOLUMES.equals(tag)) { 1702 final int version = readIntAttribute(in, ATTR_VERSION, VERSION_INIT); 1703 final boolean primaryPhysical = SystemProperties.getBoolean( 1704 StorageManager.PROP_PRIMARY_PHYSICAL, false); 1705 final boolean validAttr = (version >= VERSION_FIX_PRIMARY) 1706 || (version >= VERSION_ADD_PRIMARY && !primaryPhysical); 1707 if (validAttr) { 1708 mPrimaryStorageUuid = readStringAttribute(in, 1709 ATTR_PRIMARY_STORAGE_UUID); 1710 } 1711 } else if (TAG_VOLUME.equals(tag)) { 1712 final VolumeRecord rec = readVolumeRecord(in); 1713 mRecords.put(rec.fsUuid, rec); 1714 } 1715 } 1716 } 1717 } catch (FileNotFoundException e) { 1718 // Missing metadata is okay, probably first boot 1719 } catch (IOException e) { 1720 Slog.wtf(TAG, "Failed reading metadata", e); 1721 } catch (XmlPullParserException e) { 1722 Slog.wtf(TAG, "Failed reading metadata", e); 1723 } finally { 1724 IoUtils.closeQuietly(fis); 1725 } 1726 } 1727 1728 @GuardedBy("mLock") writeSettingsLocked()1729 private void writeSettingsLocked() { 1730 FileOutputStream fos = null; 1731 try { 1732 fos = mSettingsFile.startWrite(); 1733 1734 XmlSerializer out = new FastXmlSerializer(); 1735 out.setOutput(fos, StandardCharsets.UTF_8.name()); 1736 out.startDocument(null, true); 1737 out.startTag(null, TAG_VOLUMES); 1738 writeIntAttribute(out, ATTR_VERSION, VERSION_FIX_PRIMARY); 1739 writeStringAttribute(out, ATTR_PRIMARY_STORAGE_UUID, mPrimaryStorageUuid); 1740 final int size = mRecords.size(); 1741 for (int i = 0; i < size; i++) { 1742 final VolumeRecord rec = mRecords.valueAt(i); 1743 writeVolumeRecord(out, rec); 1744 } 1745 out.endTag(null, TAG_VOLUMES); 1746 out.endDocument(); 1747 1748 mSettingsFile.finishWrite(fos); 1749 } catch (IOException e) { 1750 if (fos != null) { 1751 mSettingsFile.failWrite(fos); 1752 } 1753 } 1754 } 1755 readVolumeRecord(XmlPullParser in)1756 public static VolumeRecord readVolumeRecord(XmlPullParser in) throws IOException { 1757 final int type = readIntAttribute(in, ATTR_TYPE); 1758 final String fsUuid = readStringAttribute(in, ATTR_FS_UUID); 1759 final VolumeRecord meta = new VolumeRecord(type, fsUuid); 1760 meta.partGuid = readStringAttribute(in, ATTR_PART_GUID); 1761 meta.nickname = readStringAttribute(in, ATTR_NICKNAME); 1762 meta.userFlags = readIntAttribute(in, ATTR_USER_FLAGS); 1763 meta.createdMillis = readLongAttribute(in, ATTR_CREATED_MILLIS, 0); 1764 meta.lastSeenMillis = readLongAttribute(in, ATTR_LAST_SEEN_MILLIS, 0); 1765 meta.lastTrimMillis = readLongAttribute(in, ATTR_LAST_TRIM_MILLIS, 0); 1766 meta.lastBenchMillis = readLongAttribute(in, ATTR_LAST_BENCH_MILLIS, 0); 1767 return meta; 1768 } 1769 writeVolumeRecord(XmlSerializer out, VolumeRecord rec)1770 public static void writeVolumeRecord(XmlSerializer out, VolumeRecord rec) throws IOException { 1771 out.startTag(null, TAG_VOLUME); 1772 writeIntAttribute(out, ATTR_TYPE, rec.type); 1773 writeStringAttribute(out, ATTR_FS_UUID, rec.fsUuid); 1774 writeStringAttribute(out, ATTR_PART_GUID, rec.partGuid); 1775 writeStringAttribute(out, ATTR_NICKNAME, rec.nickname); 1776 writeIntAttribute(out, ATTR_USER_FLAGS, rec.userFlags); 1777 writeLongAttribute(out, ATTR_CREATED_MILLIS, rec.createdMillis); 1778 writeLongAttribute(out, ATTR_LAST_SEEN_MILLIS, rec.lastSeenMillis); 1779 writeLongAttribute(out, ATTR_LAST_TRIM_MILLIS, rec.lastTrimMillis); 1780 writeLongAttribute(out, ATTR_LAST_BENCH_MILLIS, rec.lastBenchMillis); 1781 out.endTag(null, TAG_VOLUME); 1782 } 1783 1784 /** 1785 * Exposed API calls below here 1786 */ 1787 1788 @Override registerListener(IStorageEventListener listener)1789 public void registerListener(IStorageEventListener listener) { 1790 mCallbacks.register(listener); 1791 } 1792 1793 @Override unregisterListener(IStorageEventListener listener)1794 public void unregisterListener(IStorageEventListener listener) { 1795 mCallbacks.unregister(listener); 1796 } 1797 1798 @Override shutdown(final IStorageShutdownObserver observer)1799 public void shutdown(final IStorageShutdownObserver observer) { 1800 enforcePermission(android.Manifest.permission.SHUTDOWN); 1801 1802 Slog.i(TAG, "Shutting down"); 1803 mHandler.obtainMessage(H_SHUTDOWN, observer).sendToTarget(); 1804 } 1805 1806 @Override mount(String volId)1807 public void mount(String volId) { 1808 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS); 1809 1810 final VolumeInfo vol = findVolumeByIdOrThrow(volId); 1811 if (isMountDisallowed(vol)) { 1812 throw new SecurityException("Mounting " + volId + " restricted by policy"); 1813 } 1814 mount(vol); 1815 } 1816 mount(VolumeInfo vol)1817 private void mount(VolumeInfo vol) { 1818 try { 1819 mVold.mount(vol.id, vol.mountFlags, vol.mountUserId); 1820 } catch (Exception e) { 1821 Slog.wtf(TAG, e); 1822 } 1823 } 1824 1825 @Override unmount(String volId)1826 public void unmount(String volId) { 1827 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS); 1828 1829 final VolumeInfo vol = findVolumeByIdOrThrow(volId); 1830 unmount(vol); 1831 } 1832 unmount(VolumeInfo vol)1833 private void unmount(VolumeInfo vol) { 1834 try { 1835 mVold.unmount(vol.id); 1836 } catch (Exception e) { 1837 Slog.wtf(TAG, e); 1838 } 1839 } 1840 1841 @Override format(String volId)1842 public void format(String volId) { 1843 enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS); 1844 1845 final VolumeInfo vol = findVolumeByIdOrThrow(volId); 1846 try { 1847 mVold.format(vol.id, "auto"); 1848 } catch (Exception e) { 1849 Slog.wtf(TAG, e); 1850 } 1851 } 1852 1853 @Override benchmark(String volId, IVoldTaskListener listener)1854 public void benchmark(String volId, IVoldTaskListener listener) { 1855 enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS); 1856 1857 try { 1858 mVold.benchmark(volId, new IVoldTaskListener.Stub() { 1859 @Override 1860 public void onStatus(int status, PersistableBundle extras) { 1861 dispatchOnStatus(listener, status, extras); 1862 } 1863 1864 @Override 1865 public void onFinished(int status, PersistableBundle extras) { 1866 dispatchOnFinished(listener, status, extras); 1867 1868 final String path = extras.getString("path"); 1869 final String ident = extras.getString("ident"); 1870 final long create = extras.getLong("create"); 1871 final long run = extras.getLong("run"); 1872 final long destroy = extras.getLong("destroy"); 1873 1874 final DropBoxManager dropBox = mContext.getSystemService(DropBoxManager.class); 1875 dropBox.addText(TAG_STORAGE_BENCHMARK, scrubPath(path) 1876 + " " + ident + " " + create + " " + run + " " + destroy); 1877 1878 synchronized (mLock) { 1879 final VolumeRecord rec = findRecordForPath(path); 1880 if (rec != null) { 1881 rec.lastBenchMillis = System.currentTimeMillis(); 1882 writeSettingsLocked(); 1883 } 1884 } 1885 } 1886 }); 1887 } catch (RemoteException e) { 1888 throw e.rethrowAsRuntimeException(); 1889 } 1890 } 1891 1892 @Override partitionPublic(String diskId)1893 public void partitionPublic(String diskId) { 1894 enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS); 1895 1896 final CountDownLatch latch = findOrCreateDiskScanLatch(diskId); 1897 try { 1898 mVold.partition(diskId, IVold.PARTITION_TYPE_PUBLIC, -1); 1899 waitForLatch(latch, "partitionPublic", 3 * DateUtils.MINUTE_IN_MILLIS); 1900 } catch (Exception e) { 1901 Slog.wtf(TAG, e); 1902 } 1903 } 1904 1905 @Override partitionPrivate(String diskId)1906 public void partitionPrivate(String diskId) { 1907 enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS); 1908 enforceAdminUser(); 1909 1910 final CountDownLatch latch = findOrCreateDiskScanLatch(diskId); 1911 try { 1912 mVold.partition(diskId, IVold.PARTITION_TYPE_PRIVATE, -1); 1913 waitForLatch(latch, "partitionPrivate", 3 * DateUtils.MINUTE_IN_MILLIS); 1914 } catch (Exception e) { 1915 Slog.wtf(TAG, e); 1916 } 1917 } 1918 1919 @Override partitionMixed(String diskId, int ratio)1920 public void partitionMixed(String diskId, int ratio) { 1921 enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS); 1922 enforceAdminUser(); 1923 1924 final CountDownLatch latch = findOrCreateDiskScanLatch(diskId); 1925 try { 1926 mVold.partition(diskId, IVold.PARTITION_TYPE_MIXED, ratio); 1927 waitForLatch(latch, "partitionMixed", 3 * DateUtils.MINUTE_IN_MILLIS); 1928 } catch (Exception e) { 1929 Slog.wtf(TAG, e); 1930 } 1931 } 1932 1933 @Override setVolumeNickname(String fsUuid, String nickname)1934 public void setVolumeNickname(String fsUuid, String nickname) { 1935 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS); 1936 1937 Objects.requireNonNull(fsUuid); 1938 synchronized (mLock) { 1939 final VolumeRecord rec = mRecords.get(fsUuid); 1940 rec.nickname = nickname; 1941 mCallbacks.notifyVolumeRecordChanged(rec); 1942 writeSettingsLocked(); 1943 } 1944 } 1945 1946 @Override setVolumeUserFlags(String fsUuid, int flags, int mask)1947 public void setVolumeUserFlags(String fsUuid, int flags, int mask) { 1948 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS); 1949 1950 Objects.requireNonNull(fsUuid); 1951 synchronized (mLock) { 1952 final VolumeRecord rec = mRecords.get(fsUuid); 1953 rec.userFlags = (rec.userFlags & ~mask) | (flags & mask); 1954 mCallbacks.notifyVolumeRecordChanged(rec); 1955 writeSettingsLocked(); 1956 } 1957 } 1958 1959 @Override forgetVolume(String fsUuid)1960 public void forgetVolume(String fsUuid) { 1961 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS); 1962 1963 Objects.requireNonNull(fsUuid); 1964 1965 synchronized (mLock) { 1966 final VolumeRecord rec = mRecords.remove(fsUuid); 1967 if (rec != null && !TextUtils.isEmpty(rec.partGuid)) { 1968 mHandler.obtainMessage(H_PARTITION_FORGET, rec).sendToTarget(); 1969 } 1970 mCallbacks.notifyVolumeForgotten(fsUuid); 1971 1972 // If this had been primary storage, revert back to internal and 1973 // reset vold so we bind into new volume into place. 1974 if (Objects.equals(mPrimaryStorageUuid, fsUuid)) { 1975 mPrimaryStorageUuid = getDefaultPrimaryStorageUuid(); 1976 mHandler.obtainMessage(H_RESET).sendToTarget(); 1977 } 1978 1979 writeSettingsLocked(); 1980 } 1981 } 1982 1983 @Override forgetAllVolumes()1984 public void forgetAllVolumes() { 1985 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS); 1986 1987 synchronized (mLock) { 1988 for (int i = 0; i < mRecords.size(); i++) { 1989 final String fsUuid = mRecords.keyAt(i); 1990 final VolumeRecord rec = mRecords.valueAt(i); 1991 if (!TextUtils.isEmpty(rec.partGuid)) { 1992 mHandler.obtainMessage(H_PARTITION_FORGET, rec).sendToTarget(); 1993 } 1994 mCallbacks.notifyVolumeForgotten(fsUuid); 1995 } 1996 mRecords.clear(); 1997 1998 if (!Objects.equals(StorageManager.UUID_PRIVATE_INTERNAL, mPrimaryStorageUuid)) { 1999 mPrimaryStorageUuid = getDefaultPrimaryStorageUuid(); 2000 } 2001 2002 writeSettingsLocked(); 2003 mHandler.obtainMessage(H_RESET).sendToTarget(); 2004 } 2005 } 2006 forgetPartition(String partGuid, String fsUuid)2007 private void forgetPartition(String partGuid, String fsUuid) { 2008 try { 2009 mVold.forgetPartition(partGuid, fsUuid); 2010 } catch (Exception e) { 2011 Slog.wtf(TAG, e); 2012 } 2013 } 2014 2015 @Override fstrim(int flags, IVoldTaskListener listener)2016 public void fstrim(int flags, IVoldTaskListener listener) { 2017 enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS); 2018 2019 try { 2020 // Block based checkpoint process runs fstrim. So, if checkpoint is in progress 2021 // (first boot after OTA), We skip idle maintenance and make sure the last 2022 // fstrim time is still updated. If file based checkpoints are used, we run 2023 // idle maintenance (GC + fstrim) regardless of checkpoint status. 2024 if (!needsCheckpoint() || !supportsBlockCheckpoint()) { 2025 mVold.fstrim(flags, new IVoldTaskListener.Stub() { 2026 @Override 2027 public void onStatus(int status, PersistableBundle extras) { 2028 dispatchOnStatus(listener, status, extras); 2029 2030 // Ignore trim failures 2031 if (status != 0) return; 2032 2033 final String path = extras.getString("path"); 2034 final long bytes = extras.getLong("bytes"); 2035 final long time = extras.getLong("time"); 2036 2037 final DropBoxManager dropBox = mContext.getSystemService(DropBoxManager.class); 2038 dropBox.addText(TAG_STORAGE_TRIM, scrubPath(path) + " " + bytes + " " + time); 2039 2040 synchronized (mLock) { 2041 final VolumeRecord rec = findRecordForPath(path); 2042 if (rec != null) { 2043 rec.lastTrimMillis = System.currentTimeMillis(); 2044 writeSettingsLocked(); 2045 } 2046 } 2047 } 2048 2049 @Override 2050 public void onFinished(int status, PersistableBundle extras) { 2051 dispatchOnFinished(listener, status, extras); 2052 2053 // TODO: benchmark when desired 2054 } 2055 }); 2056 } else { 2057 Slog.i(TAG, "Skipping fstrim - block based checkpoint in progress"); 2058 } 2059 } catch (RemoteException e) { 2060 throw e.rethrowAsRuntimeException(); 2061 } 2062 } 2063 runIdleMaint(Runnable callback)2064 void runIdleMaint(Runnable callback) { 2065 enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS); 2066 2067 try { 2068 // Block based checkpoint process runs fstrim. So, if checkpoint is in progress 2069 // (first boot after OTA), We skip idle maintenance and make sure the last 2070 // fstrim time is still updated. If file based checkpoints are used, we run 2071 // idle maintenance (GC + fstrim) regardless of checkpoint status. 2072 if (!needsCheckpoint() || !supportsBlockCheckpoint()) { 2073 mVold.runIdleMaint(new IVoldTaskListener.Stub() { 2074 @Override 2075 public void onStatus(int status, PersistableBundle extras) { 2076 // Not currently used 2077 } 2078 @Override 2079 public void onFinished(int status, PersistableBundle extras) { 2080 if (callback != null) { 2081 BackgroundThread.getHandler().post(callback); 2082 } 2083 } 2084 }); 2085 } else { 2086 Slog.i(TAG, "Skipping idle maintenance - block based checkpoint in progress"); 2087 } 2088 } catch (Exception e) { 2089 Slog.wtf(TAG, e); 2090 } 2091 } 2092 2093 @Override runIdleMaintenance()2094 public void runIdleMaintenance() { 2095 runIdleMaint(null); 2096 } 2097 abortIdleMaint(Runnable callback)2098 void abortIdleMaint(Runnable callback) { 2099 enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS); 2100 2101 try { 2102 mVold.abortIdleMaint(new IVoldTaskListener.Stub() { 2103 @Override 2104 public void onStatus(int status, PersistableBundle extras) { 2105 // Not currently used 2106 } 2107 @Override 2108 public void onFinished(int status, PersistableBundle extras) { 2109 if (callback != null) { 2110 BackgroundThread.getHandler().post(callback); 2111 } 2112 } 2113 }); 2114 } catch (Exception e) { 2115 Slog.wtf(TAG, e); 2116 } 2117 } 2118 2119 @Override abortIdleMaintenance()2120 public void abortIdleMaintenance() { 2121 abortIdleMaint(null); 2122 } 2123 remountUidExternalStorage(int uid, int mode)2124 private void remountUidExternalStorage(int uid, int mode) { 2125 try { 2126 mVold.remountUid(uid, mode); 2127 } catch (Exception e) { 2128 Slog.wtf(TAG, e); 2129 } 2130 } 2131 2132 @Override setDebugFlags(int flags, int mask)2133 public void setDebugFlags(int flags, int mask) { 2134 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS); 2135 2136 if ((mask & StorageManager.DEBUG_EMULATE_FBE) != 0) { 2137 if (!EMULATE_FBE_SUPPORTED) { 2138 throw new IllegalStateException( 2139 "Emulation not supported on this device"); 2140 } 2141 if (StorageManager.isFileEncryptedNativeOnly()) { 2142 throw new IllegalStateException( 2143 "Emulation not supported on device with native FBE"); 2144 } 2145 if (mLockPatternUtils.isCredentialRequiredToDecrypt(false)) { 2146 throw new IllegalStateException( 2147 "Emulation requires disabling 'Secure start-up' in Settings > Security"); 2148 } 2149 2150 final long token = Binder.clearCallingIdentity(); 2151 try { 2152 final boolean emulateFbe = (flags & StorageManager.DEBUG_EMULATE_FBE) != 0; 2153 SystemProperties.set(StorageManager.PROP_EMULATE_FBE, Boolean.toString(emulateFbe)); 2154 2155 // Perform hard reboot to kick policy into place 2156 mContext.getSystemService(PowerManager.class).reboot(null); 2157 } finally { 2158 Binder.restoreCallingIdentity(token); 2159 } 2160 } 2161 2162 if ((mask & (StorageManager.DEBUG_ADOPTABLE_FORCE_ON 2163 | StorageManager.DEBUG_ADOPTABLE_FORCE_OFF)) != 0) { 2164 final String value; 2165 if ((flags & StorageManager.DEBUG_ADOPTABLE_FORCE_ON) != 0) { 2166 value = "force_on"; 2167 } else if ((flags & StorageManager.DEBUG_ADOPTABLE_FORCE_OFF) != 0) { 2168 value = "force_off"; 2169 } else { 2170 value = ""; 2171 } 2172 2173 final long token = Binder.clearCallingIdentity(); 2174 try { 2175 SystemProperties.set(StorageManager.PROP_ADOPTABLE, value); 2176 2177 // Reset storage to kick new setting into place 2178 mHandler.obtainMessage(H_RESET).sendToTarget(); 2179 } finally { 2180 Binder.restoreCallingIdentity(token); 2181 } 2182 } 2183 2184 if ((mask & (StorageManager.DEBUG_SDCARDFS_FORCE_ON 2185 | StorageManager.DEBUG_SDCARDFS_FORCE_OFF)) != 0) { 2186 final String value; 2187 if ((flags & StorageManager.DEBUG_SDCARDFS_FORCE_ON) != 0) { 2188 value = "force_on"; 2189 } else if ((flags & StorageManager.DEBUG_SDCARDFS_FORCE_OFF) != 0) { 2190 value = "force_off"; 2191 } else { 2192 value = ""; 2193 } 2194 2195 final long token = Binder.clearCallingIdentity(); 2196 try { 2197 SystemProperties.set(StorageManager.PROP_SDCARDFS, value); 2198 2199 // Reset storage to kick new setting into place 2200 mHandler.obtainMessage(H_RESET).sendToTarget(); 2201 } finally { 2202 Binder.restoreCallingIdentity(token); 2203 } 2204 } 2205 2206 if ((mask & StorageManager.DEBUG_VIRTUAL_DISK) != 0) { 2207 final boolean enabled = (flags & StorageManager.DEBUG_VIRTUAL_DISK) != 0; 2208 2209 final long token = Binder.clearCallingIdentity(); 2210 try { 2211 SystemProperties.set(StorageManager.PROP_VIRTUAL_DISK, Boolean.toString(enabled)); 2212 2213 // Reset storage to kick new setting into place 2214 mHandler.obtainMessage(H_RESET).sendToTarget(); 2215 } finally { 2216 Binder.restoreCallingIdentity(token); 2217 } 2218 } 2219 2220 if ((mask & (StorageManager.DEBUG_ISOLATED_STORAGE_FORCE_ON 2221 | StorageManager.DEBUG_ISOLATED_STORAGE_FORCE_OFF)) != 0) { 2222 final int value; 2223 if ((flags & StorageManager.DEBUG_ISOLATED_STORAGE_FORCE_ON) != 0) { 2224 value = 1; 2225 } else if ((flags & StorageManager.DEBUG_ISOLATED_STORAGE_FORCE_OFF) != 0) { 2226 value = -1; 2227 } else { 2228 value = 0; 2229 } 2230 2231 final long token = Binder.clearCallingIdentity(); 2232 try { 2233 Settings.Global.putInt(mContext.getContentResolver(), 2234 Settings.Global.ISOLATED_STORAGE_LOCAL, value); 2235 refreshIsolatedStorageSettings(); 2236 2237 // Perform hard reboot to kick policy into place 2238 mHandler.post(() -> { 2239 mContext.getSystemService(PowerManager.class).reboot(null); 2240 }); 2241 } finally { 2242 Binder.restoreCallingIdentity(token); 2243 } 2244 } 2245 } 2246 2247 @Override getPrimaryStorageUuid()2248 public String getPrimaryStorageUuid() { 2249 synchronized (mLock) { 2250 return mPrimaryStorageUuid; 2251 } 2252 } 2253 2254 @Override setPrimaryStorageUuid(String volumeUuid, IPackageMoveObserver callback)2255 public void setPrimaryStorageUuid(String volumeUuid, IPackageMoveObserver callback) { 2256 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS); 2257 2258 final VolumeInfo from; 2259 final VolumeInfo to; 2260 2261 synchronized (mLock) { 2262 if (Objects.equals(mPrimaryStorageUuid, volumeUuid)) { 2263 throw new IllegalArgumentException("Primary storage already at " + volumeUuid); 2264 } 2265 2266 if (mMoveCallback != null) { 2267 throw new IllegalStateException("Move already in progress"); 2268 } 2269 mMoveCallback = callback; 2270 mMoveTargetUuid = volumeUuid; 2271 2272 // We need all the users unlocked to move their primary storage 2273 final List<UserInfo> users = mContext.getSystemService(UserManager.class).getUsers(); 2274 for (UserInfo user : users) { 2275 if (StorageManager.isFileEncryptedNativeOrEmulated() 2276 && !isUserKeyUnlocked(user.id)) { 2277 Slog.w(TAG, "Failing move due to locked user " + user.id); 2278 onMoveStatusLocked(PackageManager.MOVE_FAILED_LOCKED_USER); 2279 return; 2280 } 2281 } 2282 2283 // When moving to/from primary physical volume, we probably just nuked 2284 // the current storage location, so we have nothing to move. 2285 if (Objects.equals(StorageManager.UUID_PRIMARY_PHYSICAL, mPrimaryStorageUuid) 2286 || Objects.equals(StorageManager.UUID_PRIMARY_PHYSICAL, volumeUuid)) { 2287 Slog.d(TAG, "Skipping move to/from primary physical"); 2288 onMoveStatusLocked(MOVE_STATUS_COPY_FINISHED); 2289 onMoveStatusLocked(PackageManager.MOVE_SUCCEEDED); 2290 mHandler.obtainMessage(H_RESET).sendToTarget(); 2291 return; 2292 2293 } else { 2294 from = findStorageForUuid(mPrimaryStorageUuid); 2295 to = findStorageForUuid(volumeUuid); 2296 2297 if (from == null) { 2298 Slog.w(TAG, "Failing move due to missing from volume " + mPrimaryStorageUuid); 2299 onMoveStatusLocked(PackageManager.MOVE_FAILED_INTERNAL_ERROR); 2300 return; 2301 } else if (to == null) { 2302 Slog.w(TAG, "Failing move due to missing to volume " + volumeUuid); 2303 onMoveStatusLocked(PackageManager.MOVE_FAILED_INTERNAL_ERROR); 2304 return; 2305 } 2306 } 2307 } 2308 2309 try { 2310 mVold.moveStorage(from.id, to.id, new IVoldTaskListener.Stub() { 2311 @Override 2312 public void onStatus(int status, PersistableBundle extras) { 2313 synchronized (mLock) { 2314 onMoveStatusLocked(status); 2315 } 2316 } 2317 2318 @Override 2319 public void onFinished(int status, PersistableBundle extras) { 2320 // Not currently used 2321 } 2322 }); 2323 } catch (Exception e) { 2324 Slog.wtf(TAG, e); 2325 } 2326 } 2327 warnOnNotMounted()2328 private void warnOnNotMounted() { 2329 synchronized (mLock) { 2330 for (int i = 0; i < mVolumes.size(); i++) { 2331 final VolumeInfo vol = mVolumes.valueAt(i); 2332 if (vol.isPrimary() && vol.isMountedWritable()) { 2333 // Cool beans, we have a mounted primary volume 2334 return; 2335 } 2336 } 2337 } 2338 2339 Slog.w(TAG, "No primary storage mounted!"); 2340 } 2341 isUidOwnerOfPackageOrSystem(String packageName, int callerUid)2342 private boolean isUidOwnerOfPackageOrSystem(String packageName, int callerUid) { 2343 if (callerUid == android.os.Process.SYSTEM_UID) { 2344 return true; 2345 } 2346 2347 if (packageName == null) { 2348 return false; 2349 } 2350 2351 final int packageUid = mPmInternal.getPackageUid(packageName, 2352 PackageManager.MATCH_DEBUG_TRIAGED_MISSING, UserHandle.getUserId(callerUid)); 2353 2354 if (DEBUG_OBB) { 2355 Slog.d(TAG, "packageName = " + packageName + ", packageUid = " + 2356 packageUid + ", callerUid = " + callerUid); 2357 } 2358 2359 return callerUid == packageUid; 2360 } 2361 2362 @Override getMountedObbPath(String rawPath)2363 public String getMountedObbPath(String rawPath) { 2364 Objects.requireNonNull(rawPath, "rawPath cannot be null"); 2365 2366 warnOnNotMounted(); 2367 2368 final ObbState state; 2369 synchronized (mObbMounts) { 2370 state = mObbPathToStateMap.get(rawPath); 2371 } 2372 if (state == null) { 2373 Slog.w(TAG, "Failed to find OBB mounted at " + rawPath); 2374 return null; 2375 } 2376 2377 return findVolumeByIdOrThrow(state.volId).getPath().getAbsolutePath(); 2378 } 2379 2380 @Override isObbMounted(String rawPath)2381 public boolean isObbMounted(String rawPath) { 2382 Objects.requireNonNull(rawPath, "rawPath cannot be null"); 2383 synchronized (mObbMounts) { 2384 return mObbPathToStateMap.containsKey(rawPath); 2385 } 2386 } 2387 2388 @Override mountObb(String rawPath, String canonicalPath, String key, IObbActionListener token, int nonce, ObbInfo obbInfo)2389 public void mountObb(String rawPath, String canonicalPath, String key, 2390 IObbActionListener token, int nonce, ObbInfo obbInfo) { 2391 Objects.requireNonNull(rawPath, "rawPath cannot be null"); 2392 Objects.requireNonNull(canonicalPath, "canonicalPath cannot be null"); 2393 Objects.requireNonNull(token, "token cannot be null"); 2394 Objects.requireNonNull(obbInfo, "obbIfno cannot be null"); 2395 2396 final int callingUid = Binder.getCallingUid(); 2397 final ObbState obbState = new ObbState(rawPath, canonicalPath, 2398 callingUid, token, nonce, null); 2399 final ObbAction action = new MountObbAction(obbState, key, callingUid, obbInfo); 2400 mObbActionHandler.sendMessage(mObbActionHandler.obtainMessage(OBB_RUN_ACTION, action)); 2401 2402 if (DEBUG_OBB) 2403 Slog.i(TAG, "Send to OBB handler: " + action.toString()); 2404 } 2405 2406 @Override unmountObb(String rawPath, boolean force, IObbActionListener token, int nonce)2407 public void unmountObb(String rawPath, boolean force, IObbActionListener token, int nonce) { 2408 Objects.requireNonNull(rawPath, "rawPath cannot be null"); 2409 2410 final ObbState existingState; 2411 synchronized (mObbMounts) { 2412 existingState = mObbPathToStateMap.get(rawPath); 2413 } 2414 2415 if (existingState != null) { 2416 // TODO: separate state object from request data 2417 final int callingUid = Binder.getCallingUid(); 2418 final ObbState newState = new ObbState(rawPath, existingState.canonicalPath, 2419 callingUid, token, nonce, existingState.volId); 2420 final ObbAction action = new UnmountObbAction(newState, force); 2421 mObbActionHandler.sendMessage(mObbActionHandler.obtainMessage(OBB_RUN_ACTION, action)); 2422 2423 if (DEBUG_OBB) 2424 Slog.i(TAG, "Send to OBB handler: " + action.toString()); 2425 } else { 2426 Slog.w(TAG, "Unknown OBB mount at " + rawPath); 2427 } 2428 } 2429 2430 @Override getEncryptionState()2431 public int getEncryptionState() { 2432 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER, 2433 "no permission to access the crypt keeper"); 2434 2435 try { 2436 return mVold.fdeComplete(); 2437 } catch (Exception e) { 2438 Slog.wtf(TAG, e); 2439 return StorageManager.ENCRYPTION_STATE_ERROR_UNKNOWN; 2440 } 2441 } 2442 2443 @Override decryptStorage(String password)2444 public int decryptStorage(String password) { 2445 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER, 2446 "no permission to access the crypt keeper"); 2447 2448 if (TextUtils.isEmpty(password)) { 2449 throw new IllegalArgumentException("password cannot be empty"); 2450 } 2451 2452 if (DEBUG_EVENTS) { 2453 Slog.i(TAG, "decrypting storage..."); 2454 } 2455 2456 try { 2457 mVold.fdeCheckPassword(password); 2458 mHandler.postDelayed(() -> { 2459 try { 2460 mVold.fdeRestart(); 2461 } catch (Exception e) { 2462 Slog.wtf(TAG, e); 2463 } 2464 }, DateUtils.SECOND_IN_MILLIS); 2465 return 0; 2466 } catch (ServiceSpecificException e) { 2467 Slog.e(TAG, "fdeCheckPassword failed", e); 2468 return e.errorCode; 2469 } catch (Exception e) { 2470 Slog.wtf(TAG, e); 2471 return StorageManager.ENCRYPTION_STATE_ERROR_UNKNOWN; 2472 } 2473 } 2474 2475 @Override encryptStorage(int type, String password)2476 public int encryptStorage(int type, String password) { 2477 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER, 2478 "no permission to access the crypt keeper"); 2479 2480 if (type == StorageManager.CRYPT_TYPE_DEFAULT) { 2481 password = ""; 2482 } else if (TextUtils.isEmpty(password)) { 2483 throw new IllegalArgumentException("password cannot be empty"); 2484 } 2485 2486 if (DEBUG_EVENTS) { 2487 Slog.i(TAG, "encrypting storage..."); 2488 } 2489 2490 try { 2491 mVold.fdeEnable(type, password, 0); 2492 } catch (Exception e) { 2493 Slog.wtf(TAG, e); 2494 return -1; 2495 } 2496 2497 return 0; 2498 } 2499 2500 /** Set the password for encrypting the master key. 2501 * @param type One of the CRYPTO_TYPE_XXX consts defined in StorageManager. 2502 * @param password The password to set. 2503 */ 2504 @Override changeEncryptionPassword(int type, String password)2505 public int changeEncryptionPassword(int type, String password) { 2506 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER, 2507 "no permission to access the crypt keeper"); 2508 2509 if (StorageManager.isFileEncryptedNativeOnly()) { 2510 // Not supported on FBE devices 2511 return -1; 2512 } 2513 2514 if (type == StorageManager.CRYPT_TYPE_DEFAULT) { 2515 password = ""; 2516 } else if (TextUtils.isEmpty(password)) { 2517 throw new IllegalArgumentException("password cannot be empty"); 2518 } 2519 2520 if (DEBUG_EVENTS) { 2521 Slog.i(TAG, "changing encryption password..."); 2522 } 2523 2524 try { 2525 mVold.fdeChangePassword(type, password); 2526 return 0; 2527 } catch (Exception e) { 2528 Slog.wtf(TAG, e); 2529 return -1; 2530 } 2531 } 2532 2533 /** 2534 * Validate a user-supplied password string with cryptfs 2535 */ 2536 @Override verifyEncryptionPassword(String password)2537 public int verifyEncryptionPassword(String password) throws RemoteException { 2538 // Only the system process is permitted to validate passwords 2539 if (Binder.getCallingUid() != android.os.Process.SYSTEM_UID) { 2540 throw new SecurityException("no permission to access the crypt keeper"); 2541 } 2542 2543 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER, 2544 "no permission to access the crypt keeper"); 2545 2546 if (TextUtils.isEmpty(password)) { 2547 throw new IllegalArgumentException("password cannot be empty"); 2548 } 2549 2550 if (DEBUG_EVENTS) { 2551 Slog.i(TAG, "validating encryption password..."); 2552 } 2553 2554 try { 2555 mVold.fdeVerifyPassword(password); 2556 return 0; 2557 } catch (Exception e) { 2558 Slog.wtf(TAG, e); 2559 return -1; 2560 } 2561 } 2562 2563 /** 2564 * Get the type of encryption used to encrypt the master key. 2565 * @return The type, one of the CRYPT_TYPE_XXX consts from StorageManager. 2566 */ 2567 @Override getPasswordType()2568 public int getPasswordType() { 2569 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER, 2570 "no permission to access the crypt keeper"); 2571 2572 try { 2573 return mVold.fdeGetPasswordType(); 2574 } catch (Exception e) { 2575 Slog.wtf(TAG, e); 2576 return -1; 2577 } 2578 } 2579 2580 /** 2581 * Set a field in the crypto header. 2582 * @param field field to set 2583 * @param contents contents to set in field 2584 */ 2585 @Override setField(String field, String contents)2586 public void setField(String field, String contents) throws RemoteException { 2587 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER, 2588 "no permission to access the crypt keeper"); 2589 2590 if (!StorageManager.isBlockEncrypted()) { 2591 // Only supported on FDE devices 2592 return; 2593 } 2594 2595 try { 2596 mVold.fdeSetField(field, contents); 2597 return; 2598 } catch (Exception e) { 2599 Slog.wtf(TAG, e); 2600 return; 2601 } 2602 } 2603 2604 /** 2605 * Gets a field from the crypto header. 2606 * @param field field to get 2607 * @return contents of field 2608 */ 2609 @Override getField(String field)2610 public String getField(String field) throws RemoteException { 2611 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER, 2612 "no permission to access the crypt keeper"); 2613 2614 if (!StorageManager.isBlockEncrypted()) { 2615 // Only supported on FDE devices 2616 return null; 2617 } 2618 2619 try { 2620 return mVold.fdeGetField(field); 2621 } catch (Exception e) { 2622 Slog.wtf(TAG, e); 2623 return null; 2624 } 2625 } 2626 2627 /** 2628 * Is userdata convertible to file based encryption? 2629 * @return non zero for convertible 2630 */ 2631 @Override isConvertibleToFBE()2632 public boolean isConvertibleToFBE() throws RemoteException { 2633 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER, 2634 "no permission to access the crypt keeper"); 2635 2636 try { 2637 return mVold.isConvertibleToFbe(); 2638 } catch (Exception e) { 2639 Slog.wtf(TAG, e); 2640 return false; 2641 } 2642 } 2643 2644 /** 2645 * Check whether the device supports filesystem checkpointing. 2646 * 2647 * @return true if the device supports filesystem checkpointing, false otherwise. 2648 */ 2649 @Override supportsCheckpoint()2650 public boolean supportsCheckpoint() throws RemoteException { 2651 return mVold.supportsCheckpoint(); 2652 } 2653 2654 /** 2655 * Signal that checkpointing partitions should start a checkpoint on the next boot. 2656 * 2657 * @param numTries Number of times to try booting in checkpoint mode, before we will boot 2658 * non-checkpoint mode and commit all changes immediately. Callers are 2659 * responsible for ensuring that boot is safe (eg, by rolling back updates). 2660 */ 2661 @Override startCheckpoint(int numTries)2662 public void startCheckpoint(int numTries) throws RemoteException { 2663 // Only the root, system_server and shell processes are permitted to start checkpoints 2664 final int callingUid = Binder.getCallingUid(); 2665 if (callingUid != Process.SYSTEM_UID && callingUid != Process.ROOT_UID 2666 && callingUid != Process.SHELL_UID) { 2667 throw new SecurityException("no permission to start filesystem checkpoint"); 2668 } 2669 2670 mVold.startCheckpoint(numTries); 2671 } 2672 2673 /** 2674 * Signal that checkpointing partitions should commit changes 2675 */ 2676 @Override commitChanges()2677 public void commitChanges() throws RemoteException { 2678 // Only the system process is permitted to commit checkpoints 2679 if (Binder.getCallingUid() != android.os.Process.SYSTEM_UID) { 2680 throw new SecurityException("no permission to commit checkpoint changes"); 2681 } 2682 2683 mVold.commitChanges(); 2684 } 2685 2686 /** 2687 * Check if we should be mounting with checkpointing or are checkpointing now 2688 */ 2689 @Override needsCheckpoint()2690 public boolean needsCheckpoint() throws RemoteException { 2691 enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS); 2692 return mVold.needsCheckpoint(); 2693 } 2694 2695 /** 2696 * Abort the current set of changes and either try again, or abort entirely 2697 */ 2698 @Override abortChanges(String message, boolean retry)2699 public void abortChanges(String message, boolean retry) throws RemoteException { 2700 // Only the system process is permitted to abort checkpoints 2701 if (Binder.getCallingUid() != android.os.Process.SYSTEM_UID) { 2702 throw new SecurityException("no permission to commit checkpoint changes"); 2703 } 2704 2705 mVold.abortChanges(message, retry); 2706 } 2707 2708 @Override getPassword()2709 public String getPassword() throws RemoteException { 2710 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER, 2711 "only keyguard can retrieve password"); 2712 2713 try { 2714 return mVold.fdeGetPassword(); 2715 } catch (Exception e) { 2716 Slog.wtf(TAG, e); 2717 return null; 2718 } 2719 } 2720 2721 @Override clearPassword()2722 public void clearPassword() throws RemoteException { 2723 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER, 2724 "only keyguard can clear password"); 2725 2726 try { 2727 mVold.fdeClearPassword(); 2728 return; 2729 } catch (Exception e) { 2730 Slog.wtf(TAG, e); 2731 return; 2732 } 2733 } 2734 2735 @Override createUserKey(int userId, int serialNumber, boolean ephemeral)2736 public void createUserKey(int userId, int serialNumber, boolean ephemeral) { 2737 enforcePermission(android.Manifest.permission.STORAGE_INTERNAL); 2738 2739 try { 2740 mVold.createUserKey(userId, serialNumber, ephemeral); 2741 } catch (Exception e) { 2742 Slog.wtf(TAG, e); 2743 } 2744 } 2745 2746 @Override destroyUserKey(int userId)2747 public void destroyUserKey(int userId) { 2748 enforcePermission(android.Manifest.permission.STORAGE_INTERNAL); 2749 2750 try { 2751 mVold.destroyUserKey(userId); 2752 } catch (Exception e) { 2753 Slog.wtf(TAG, e); 2754 } 2755 } 2756 encodeBytes(byte[] bytes)2757 private String encodeBytes(byte[] bytes) { 2758 if (ArrayUtils.isEmpty(bytes)) { 2759 return "!"; 2760 } else { 2761 return HexDump.toHexString(bytes); 2762 } 2763 } 2764 2765 /* 2766 * Add this token/secret pair to the set of ways we can recover a disk encryption key. 2767 * Changing the token/secret for a disk encryption key is done in two phases: first, adding 2768 * a new token/secret pair with this call, then delting all other pairs with 2769 * fixateNewestUserKeyAuth. This allows other places where a credential is used, such as 2770 * Gatekeeper, to be updated between the two calls. 2771 */ 2772 @Override addUserKeyAuth(int userId, int serialNumber, byte[] token, byte[] secret)2773 public void addUserKeyAuth(int userId, int serialNumber, byte[] token, byte[] secret) { 2774 enforcePermission(android.Manifest.permission.STORAGE_INTERNAL); 2775 2776 try { 2777 mVold.addUserKeyAuth(userId, serialNumber, encodeBytes(token), encodeBytes(secret)); 2778 } catch (Exception e) { 2779 Slog.wtf(TAG, e); 2780 } 2781 } 2782 2783 /* 2784 * Clear disk encryption key bound to the associated token / secret pair. Removing the user 2785 * binding of the Disk encryption key is done in two phases: first, this call will retrieve 2786 * the disk encryption key using the provided token / secret pair and store it by 2787 * encrypting it with a keymaster key not bound to the user, then fixateNewestUserKeyAuth 2788 * is called to delete all other bindings of the disk encryption key. 2789 */ 2790 @Override clearUserKeyAuth(int userId, int serialNumber, byte[] token, byte[] secret)2791 public void clearUserKeyAuth(int userId, int serialNumber, byte[] token, byte[] secret) { 2792 enforcePermission(android.Manifest.permission.STORAGE_INTERNAL); 2793 2794 try { 2795 mVold.clearUserKeyAuth(userId, serialNumber, encodeBytes(token), encodeBytes(secret)); 2796 } catch (Exception e) { 2797 Slog.wtf(TAG, e); 2798 } 2799 } 2800 2801 /* 2802 * Delete all disk encryption token/secret pairs except the most recently added one 2803 */ 2804 @Override fixateNewestUserKeyAuth(int userId)2805 public void fixateNewestUserKeyAuth(int userId) { 2806 enforcePermission(android.Manifest.permission.STORAGE_INTERNAL); 2807 2808 try { 2809 mVold.fixateNewestUserKeyAuth(userId); 2810 } catch (Exception e) { 2811 Slog.wtf(TAG, e); 2812 } 2813 } 2814 2815 @Override unlockUserKey(int userId, int serialNumber, byte[] token, byte[] secret)2816 public void unlockUserKey(int userId, int serialNumber, byte[] token, byte[] secret) { 2817 Slog.d(TAG, "unlockUserKey: " + userId); 2818 enforcePermission(android.Manifest.permission.STORAGE_INTERNAL); 2819 2820 if (StorageManager.isFileEncryptedNativeOrEmulated()) { 2821 try { 2822 mVold.unlockUserKey(userId, serialNumber, encodeBytes(token), 2823 encodeBytes(secret)); 2824 } catch (Exception e) { 2825 Slog.wtf(TAG, e); 2826 return; 2827 } 2828 } 2829 2830 synchronized (mLock) { 2831 mLocalUnlockedUsers = ArrayUtils.appendInt(mLocalUnlockedUsers, userId); 2832 } 2833 } 2834 2835 @Override lockUserKey(int userId)2836 public void lockUserKey(int userId) { 2837 enforcePermission(android.Manifest.permission.STORAGE_INTERNAL); 2838 2839 try { 2840 mVold.lockUserKey(userId); 2841 } catch (Exception e) { 2842 Slog.wtf(TAG, e); 2843 return; 2844 } 2845 2846 synchronized (mLock) { 2847 mLocalUnlockedUsers = ArrayUtils.removeInt(mLocalUnlockedUsers, userId); 2848 } 2849 } 2850 2851 @Override isUserKeyUnlocked(int userId)2852 public boolean isUserKeyUnlocked(int userId) { 2853 synchronized (mLock) { 2854 return ArrayUtils.contains(mLocalUnlockedUsers, userId); 2855 } 2856 } 2857 isSystemUnlocked(int userId)2858 private boolean isSystemUnlocked(int userId) { 2859 synchronized (mLock) { 2860 return ArrayUtils.contains(mSystemUnlockedUsers, userId); 2861 } 2862 } 2863 2864 @Override prepareUserStorage(String volumeUuid, int userId, int serialNumber, int flags)2865 public void prepareUserStorage(String volumeUuid, int userId, int serialNumber, int flags) { 2866 enforcePermission(android.Manifest.permission.STORAGE_INTERNAL); 2867 2868 try { 2869 mVold.prepareUserStorage(volumeUuid, userId, serialNumber, flags); 2870 } catch (Exception e) { 2871 Slog.wtf(TAG, e); 2872 } 2873 } 2874 2875 @Override destroyUserStorage(String volumeUuid, int userId, int flags)2876 public void destroyUserStorage(String volumeUuid, int userId, int flags) { 2877 enforcePermission(android.Manifest.permission.STORAGE_INTERNAL); 2878 2879 try { 2880 mVold.destroyUserStorage(volumeUuid, userId, flags); 2881 } catch (Exception e) { 2882 Slog.wtf(TAG, e); 2883 } 2884 } 2885 2886 /** Not thread safe */ 2887 class AppFuseMountScope extends AppFuseBridge.MountScope { 2888 private boolean mMounted = false; 2889 AppFuseMountScope(int uid, int mountId)2890 public AppFuseMountScope(int uid, int mountId) { 2891 super(uid, mountId); 2892 } 2893 2894 @Override open()2895 public ParcelFileDescriptor open() throws NativeDaemonConnectorException { 2896 try { 2897 final FileDescriptor fd = mVold.mountAppFuse(uid, mountId); 2898 mMounted = true; 2899 return new ParcelFileDescriptor(fd); 2900 } catch (Exception e) { 2901 throw new NativeDaemonConnectorException("Failed to mount", e); 2902 } 2903 } 2904 2905 @Override openFile(int mountId, int fileId, int flags)2906 public ParcelFileDescriptor openFile(int mountId, int fileId, int flags) 2907 throws NativeDaemonConnectorException { 2908 try { 2909 return new ParcelFileDescriptor( 2910 mVold.openAppFuseFile(uid, mountId, fileId, flags)); 2911 } catch (Exception e) { 2912 throw new NativeDaemonConnectorException("Failed to open", e); 2913 } 2914 } 2915 2916 @Override close()2917 public void close() throws Exception { 2918 if (mMounted) { 2919 mVold.unmountAppFuse(uid, mountId); 2920 mMounted = false; 2921 } 2922 } 2923 } 2924 2925 @Override mountProxyFileDescriptorBridge()2926 public @Nullable AppFuseMount mountProxyFileDescriptorBridge() { 2927 Slog.v(TAG, "mountProxyFileDescriptorBridge"); 2928 final int uid = Binder.getCallingUid(); 2929 2930 while (true) { 2931 synchronized (mAppFuseLock) { 2932 boolean newlyCreated = false; 2933 if (mAppFuseBridge == null) { 2934 mAppFuseBridge = new AppFuseBridge(); 2935 new Thread(mAppFuseBridge, AppFuseBridge.TAG).start(); 2936 newlyCreated = true; 2937 } 2938 try { 2939 final int name = mNextAppFuseName++; 2940 try { 2941 return new AppFuseMount( 2942 name, mAppFuseBridge.addBridge(new AppFuseMountScope(uid, name))); 2943 } catch (FuseUnavailableMountException e) { 2944 if (newlyCreated) { 2945 // If newly created bridge fails, it's a real error. 2946 Slog.e(TAG, "", e); 2947 return null; 2948 } 2949 // It seems the thread of mAppFuseBridge has already been terminated. 2950 mAppFuseBridge = null; 2951 } 2952 } catch (NativeDaemonConnectorException e) { 2953 throw e.rethrowAsParcelableException(); 2954 } 2955 } 2956 } 2957 } 2958 2959 @Override openProxyFileDescriptor( int mountId, int fileId, int mode)2960 public @Nullable ParcelFileDescriptor openProxyFileDescriptor( 2961 int mountId, int fileId, int mode) { 2962 Slog.v(TAG, "mountProxyFileDescriptor"); 2963 2964 // We only support a narrow set of incoming mode flags 2965 mode &= MODE_READ_WRITE; 2966 2967 try { 2968 synchronized (mAppFuseLock) { 2969 if (mAppFuseBridge == null) { 2970 Slog.e(TAG, "FuseBridge has not been created"); 2971 return null; 2972 } 2973 return mAppFuseBridge.openFile(mountId, fileId, mode); 2974 } 2975 } catch (FuseUnavailableMountException | InterruptedException error) { 2976 Slog.v(TAG, "The mount point has already been invalid", error); 2977 return null; 2978 } 2979 } 2980 2981 @Override mkdirs(String callingPkg, String appPath)2982 public void mkdirs(String callingPkg, String appPath) { 2983 final int callingUid = Binder.getCallingUid(); 2984 final int userId = UserHandle.getUserId(callingUid); 2985 final UserEnvironment userEnv = new UserEnvironment(userId); 2986 final String propertyName = "sys.user." + userId + ".ce_available"; 2987 2988 // Ignore requests to create directories while storage is locked 2989 if (!isUserKeyUnlocked(userId)) { 2990 throw new IllegalStateException("Failed to prepare " + appPath); 2991 } 2992 2993 // Ignore requests to create directories if CE storage is not available 2994 if ((userId == UserHandle.USER_SYSTEM) 2995 && !SystemProperties.getBoolean(propertyName, false)) { 2996 throw new IllegalStateException("Failed to prepare " + appPath); 2997 } 2998 2999 // Validate that reported package name belongs to caller 3000 final AppOpsManager appOps = (AppOpsManager) mContext.getSystemService( 3001 Context.APP_OPS_SERVICE); 3002 appOps.checkPackage(callingUid, callingPkg); 3003 3004 File appFile = null; 3005 try { 3006 appFile = new File(appPath).getCanonicalFile(); 3007 } catch (IOException e) { 3008 throw new IllegalStateException("Failed to resolve " + appPath + ": " + e); 3009 } 3010 3011 // Try translating the app path into a vold path, but require that it 3012 // belong to the calling package. 3013 if (FileUtils.contains(userEnv.buildExternalStorageAppDataDirs(callingPkg), appFile) || 3014 FileUtils.contains(userEnv.buildExternalStorageAppObbDirs(callingPkg), appFile) || 3015 FileUtils.contains(userEnv.buildExternalStorageAppMediaDirs(callingPkg), appFile)) { 3016 appPath = appFile.getAbsolutePath(); 3017 if (!appPath.endsWith("/")) { 3018 appPath = appPath + "/"; 3019 } 3020 3021 try { 3022 mVold.mkdirs(appPath); 3023 return; 3024 } catch (Exception e) { 3025 throw new IllegalStateException("Failed to prepare " + appPath + ": " + e); 3026 } 3027 } 3028 3029 throw new SecurityException("Invalid mkdirs path: " + appFile); 3030 } 3031 3032 @Override getVolumeList(int uid, String packageName, int flags)3033 public StorageVolume[] getVolumeList(int uid, String packageName, int flags) { 3034 final int userId = UserHandle.getUserId(uid); 3035 3036 final boolean forWrite = (flags & StorageManager.FLAG_FOR_WRITE) != 0; 3037 final boolean realState = (flags & StorageManager.FLAG_REAL_STATE) != 0; 3038 final boolean includeInvisible = (flags & StorageManager.FLAG_INCLUDE_INVISIBLE) != 0; 3039 3040 // Report all volumes as unmounted until we've recorded that user 0 has unlocked. There 3041 // are no guarantees that callers will see a consistent view of the volume before that 3042 // point 3043 final boolean systemUserUnlocked = isSystemUnlocked(UserHandle.USER_SYSTEM); 3044 3045 final boolean userKeyUnlocked; 3046 final boolean storagePermission; 3047 final long token = Binder.clearCallingIdentity(); 3048 try { 3049 userKeyUnlocked = isUserKeyUnlocked(userId); 3050 storagePermission = mStorageManagerInternal.hasExternalStorage(uid, packageName); 3051 } finally { 3052 Binder.restoreCallingIdentity(token); 3053 } 3054 3055 boolean foundPrimary = false; 3056 3057 final ArrayList<StorageVolume> res = new ArrayList<>(); 3058 synchronized (mLock) { 3059 for (int i = 0; i < mVolumes.size(); i++) { 3060 final VolumeInfo vol = mVolumes.valueAt(i); 3061 switch (vol.getType()) { 3062 case VolumeInfo.TYPE_PUBLIC: 3063 case VolumeInfo.TYPE_STUB: 3064 case VolumeInfo.TYPE_EMULATED: 3065 break; 3066 default: 3067 continue; 3068 } 3069 3070 boolean match = false; 3071 if (forWrite) { 3072 match = vol.isVisibleForWrite(userId); 3073 } else { 3074 match = vol.isVisibleForRead(userId) 3075 || (includeInvisible && vol.getPath() != null); 3076 } 3077 if (!match) continue; 3078 3079 boolean reportUnmounted = false; 3080 if (!systemUserUnlocked) { 3081 reportUnmounted = true; 3082 } else if ((vol.getType() == VolumeInfo.TYPE_EMULATED) && !userKeyUnlocked) { 3083 reportUnmounted = true; 3084 } else if (!storagePermission && !realState) { 3085 reportUnmounted = true; 3086 } 3087 3088 final StorageVolume userVol = vol.buildStorageVolume(mContext, userId, 3089 reportUnmounted); 3090 if (vol.isPrimary()) { 3091 res.add(0, userVol); 3092 foundPrimary = true; 3093 } else { 3094 res.add(userVol); 3095 } 3096 } 3097 } 3098 3099 if (!foundPrimary) { 3100 Slog.w(TAG, "No primary storage defined yet; hacking together a stub"); 3101 3102 final boolean primaryPhysical = SystemProperties.getBoolean( 3103 StorageManager.PROP_PRIMARY_PHYSICAL, false); 3104 3105 final String id = "stub_primary"; 3106 final File path = Environment.getLegacyExternalStorageDirectory(); 3107 final String description = mContext.getString(android.R.string.unknownName); 3108 final boolean primary = true; 3109 final boolean removable = primaryPhysical; 3110 final boolean emulated = !primaryPhysical; 3111 final boolean allowMassStorage = false; 3112 final long maxFileSize = 0L; 3113 final UserHandle owner = new UserHandle(userId); 3114 final String uuid = null; 3115 final String state = Environment.MEDIA_REMOVED; 3116 3117 res.add(0, new StorageVolume(id, path, path, 3118 description, primary, removable, emulated, 3119 allowMassStorage, maxFileSize, owner, uuid, state)); 3120 } 3121 3122 return res.toArray(new StorageVolume[res.size()]); 3123 } 3124 3125 @Override getDisks()3126 public DiskInfo[] getDisks() { 3127 synchronized (mLock) { 3128 final DiskInfo[] res = new DiskInfo[mDisks.size()]; 3129 for (int i = 0; i < mDisks.size(); i++) { 3130 res[i] = mDisks.valueAt(i); 3131 } 3132 return res; 3133 } 3134 } 3135 3136 @Override getVolumes(int flags)3137 public VolumeInfo[] getVolumes(int flags) { 3138 synchronized (mLock) { 3139 final VolumeInfo[] res = new VolumeInfo[mVolumes.size()]; 3140 for (int i = 0; i < mVolumes.size(); i++) { 3141 res[i] = mVolumes.valueAt(i); 3142 } 3143 return res; 3144 } 3145 } 3146 3147 @Override getVolumeRecords(int flags)3148 public VolumeRecord[] getVolumeRecords(int flags) { 3149 synchronized (mLock) { 3150 final VolumeRecord[] res = new VolumeRecord[mRecords.size()]; 3151 for (int i = 0; i < mRecords.size(); i++) { 3152 res[i] = mRecords.valueAt(i); 3153 } 3154 return res; 3155 } 3156 } 3157 3158 @Override getCacheQuotaBytes(String volumeUuid, int uid)3159 public long getCacheQuotaBytes(String volumeUuid, int uid) { 3160 if (uid != Binder.getCallingUid()) { 3161 mContext.enforceCallingPermission(android.Manifest.permission.STORAGE_INTERNAL, TAG); 3162 } 3163 final long token = Binder.clearCallingIdentity(); 3164 final StorageStatsManager stats = mContext.getSystemService(StorageStatsManager.class); 3165 try { 3166 return stats.getCacheQuotaBytes(volumeUuid, uid); 3167 } finally { 3168 Binder.restoreCallingIdentity(token); 3169 } 3170 } 3171 3172 @Override getCacheSizeBytes(String volumeUuid, int uid)3173 public long getCacheSizeBytes(String volumeUuid, int uid) { 3174 if (uid != Binder.getCallingUid()) { 3175 mContext.enforceCallingPermission(android.Manifest.permission.STORAGE_INTERNAL, TAG); 3176 } 3177 final long token = Binder.clearCallingIdentity(); 3178 try { 3179 return mContext.getSystemService(StorageStatsManager.class) 3180 .queryStatsForUid(volumeUuid, uid).getCacheBytes(); 3181 } catch (IOException e) { 3182 throw new ParcelableException(e); 3183 } finally { 3184 Binder.restoreCallingIdentity(token); 3185 } 3186 } 3187 adjustAllocateFlags(int flags, int callingUid, String callingPackage)3188 private int adjustAllocateFlags(int flags, int callingUid, String callingPackage) { 3189 // Require permission to allocate aggressively 3190 if ((flags & StorageManager.FLAG_ALLOCATE_AGGRESSIVE) != 0) { 3191 mContext.enforceCallingOrSelfPermission( 3192 android.Manifest.permission.ALLOCATE_AGGRESSIVE, TAG); 3193 } 3194 3195 // Apps normally can't directly defy reserved space 3196 flags &= ~StorageManager.FLAG_ALLOCATE_DEFY_ALL_RESERVED; 3197 flags &= ~StorageManager.FLAG_ALLOCATE_DEFY_HALF_RESERVED; 3198 3199 // However, if app is actively using the camera, then we're willing to 3200 // clear up to half of the reserved cache space, since the user might be 3201 // trying to capture an important memory. 3202 final AppOpsManager appOps = mContext.getSystemService(AppOpsManager.class); 3203 final long token = Binder.clearCallingIdentity(); 3204 try { 3205 if (appOps.isOperationActive(AppOpsManager.OP_CAMERA, callingUid, callingPackage)) { 3206 Slog.d(TAG, "UID " + callingUid + " is actively using camera;" 3207 + " letting them defy reserved cached data"); 3208 flags |= StorageManager.FLAG_ALLOCATE_DEFY_HALF_RESERVED; 3209 } 3210 } finally { 3211 Binder.restoreCallingIdentity(token); 3212 } 3213 3214 return flags; 3215 } 3216 3217 @Override getAllocatableBytes(String volumeUuid, int flags, String callingPackage)3218 public long getAllocatableBytes(String volumeUuid, int flags, String callingPackage) { 3219 flags = adjustAllocateFlags(flags, Binder.getCallingUid(), callingPackage); 3220 3221 final StorageManager storage = mContext.getSystemService(StorageManager.class); 3222 final StorageStatsManager stats = mContext.getSystemService(StorageStatsManager.class); 3223 final long token = Binder.clearCallingIdentity(); 3224 try { 3225 // In general, apps can allocate as much space as they want, except 3226 // we never let them eat into either the minimum cache space or into 3227 // the low disk warning space. To avoid user confusion, this logic 3228 // should be kept in sync with getFreeBytes(). 3229 final File path = storage.findPathForUuid(volumeUuid); 3230 3231 final long usable = path.getUsableSpace(); 3232 final long lowReserved = storage.getStorageLowBytes(path); 3233 final long fullReserved = storage.getStorageFullBytes(path); 3234 3235 if (stats.isQuotaSupported(volumeUuid)) { 3236 final long cacheTotal = stats.getCacheBytes(volumeUuid); 3237 final long cacheReserved = storage.getStorageCacheBytes(path, flags); 3238 final long cacheClearable = Math.max(0, cacheTotal - cacheReserved); 3239 3240 if ((flags & StorageManager.FLAG_ALLOCATE_AGGRESSIVE) != 0) { 3241 return Math.max(0, (usable + cacheClearable) - fullReserved); 3242 } else { 3243 return Math.max(0, (usable + cacheClearable) - lowReserved); 3244 } 3245 } else { 3246 // When we don't have fast quota information, we ignore cached 3247 // data and only consider unused bytes. 3248 if ((flags & StorageManager.FLAG_ALLOCATE_AGGRESSIVE) != 0) { 3249 return Math.max(0, usable - fullReserved); 3250 } else { 3251 return Math.max(0, usable - lowReserved); 3252 } 3253 } 3254 } catch (IOException e) { 3255 throw new ParcelableException(e); 3256 } finally { 3257 Binder.restoreCallingIdentity(token); 3258 } 3259 } 3260 3261 @Override allocateBytes(String volumeUuid, long bytes, int flags, String callingPackage)3262 public void allocateBytes(String volumeUuid, long bytes, int flags, String callingPackage) { 3263 flags = adjustAllocateFlags(flags, Binder.getCallingUid(), callingPackage); 3264 3265 final long allocatableBytes = getAllocatableBytes(volumeUuid, flags, callingPackage); 3266 if (bytes > allocatableBytes) { 3267 throw new ParcelableException(new IOException("Failed to allocate " + bytes 3268 + " because only " + allocatableBytes + " allocatable")); 3269 } 3270 3271 final StorageManager storage = mContext.getSystemService(StorageManager.class); 3272 final long token = Binder.clearCallingIdentity(); 3273 try { 3274 // Free up enough disk space to satisfy both the requested allocation 3275 // and our low disk warning space. 3276 final File path = storage.findPathForUuid(volumeUuid); 3277 if ((flags & StorageManager.FLAG_ALLOCATE_AGGRESSIVE) != 0) { 3278 bytes += storage.getStorageFullBytes(path); 3279 } else { 3280 bytes += storage.getStorageLowBytes(path); 3281 } 3282 3283 mPmInternal.freeStorage(volumeUuid, bytes, flags); 3284 } catch (IOException e) { 3285 throw new ParcelableException(e); 3286 } finally { 3287 Binder.restoreCallingIdentity(token); 3288 } 3289 } 3290 3291 private IAppOpsCallback.Stub mAppOpsCallback = new IAppOpsCallback.Stub() { 3292 @Override 3293 public void opChanged(int op, int uid, String packageName) throws RemoteException { 3294 if (!ENABLE_ISOLATED_STORAGE) return; 3295 3296 remountUidExternalStorage(uid, getMountMode(uid, packageName)); 3297 } 3298 }; 3299 addObbStateLocked(ObbState obbState)3300 private void addObbStateLocked(ObbState obbState) throws RemoteException { 3301 final IBinder binder = obbState.getBinder(); 3302 List<ObbState> obbStates = mObbMounts.get(binder); 3303 3304 if (obbStates == null) { 3305 obbStates = new ArrayList<ObbState>(); 3306 mObbMounts.put(binder, obbStates); 3307 } else { 3308 for (final ObbState o : obbStates) { 3309 if (o.rawPath.equals(obbState.rawPath)) { 3310 throw new IllegalStateException("Attempt to add ObbState twice. " 3311 + "This indicates an error in the StorageManagerService logic."); 3312 } 3313 } 3314 } 3315 3316 obbStates.add(obbState); 3317 try { 3318 obbState.link(); 3319 } catch (RemoteException e) { 3320 /* 3321 * The binder died before we could link it, so clean up our state 3322 * and return failure. 3323 */ 3324 obbStates.remove(obbState); 3325 if (obbStates.isEmpty()) { 3326 mObbMounts.remove(binder); 3327 } 3328 3329 // Rethrow the error so mountObb can get it 3330 throw e; 3331 } 3332 3333 mObbPathToStateMap.put(obbState.rawPath, obbState); 3334 } 3335 removeObbStateLocked(ObbState obbState)3336 private void removeObbStateLocked(ObbState obbState) { 3337 final IBinder binder = obbState.getBinder(); 3338 final List<ObbState> obbStates = mObbMounts.get(binder); 3339 if (obbStates != null) { 3340 if (obbStates.remove(obbState)) { 3341 obbState.unlink(); 3342 } 3343 if (obbStates.isEmpty()) { 3344 mObbMounts.remove(binder); 3345 } 3346 } 3347 3348 mObbPathToStateMap.remove(obbState.rawPath); 3349 } 3350 3351 private class ObbActionHandler extends Handler { 3352 ObbActionHandler(Looper l)3353 ObbActionHandler(Looper l) { 3354 super(l); 3355 } 3356 3357 @Override handleMessage(Message msg)3358 public void handleMessage(Message msg) { 3359 switch (msg.what) { 3360 case OBB_RUN_ACTION: { 3361 final ObbAction action = (ObbAction) msg.obj; 3362 3363 if (DEBUG_OBB) 3364 Slog.i(TAG, "OBB_RUN_ACTION: " + action.toString()); 3365 3366 action.execute(this); 3367 break; 3368 } 3369 case OBB_FLUSH_MOUNT_STATE: { 3370 final String path = (String) msg.obj; 3371 3372 if (DEBUG_OBB) 3373 Slog.i(TAG, "Flushing all OBB state for path " + path); 3374 3375 synchronized (mObbMounts) { 3376 final List<ObbState> obbStatesToRemove = new LinkedList<ObbState>(); 3377 3378 final Iterator<ObbState> i = mObbPathToStateMap.values().iterator(); 3379 while (i.hasNext()) { 3380 final ObbState state = i.next(); 3381 3382 /* 3383 * If this entry's source file is in the volume path 3384 * that got unmounted, remove it because it's no 3385 * longer valid. 3386 */ 3387 if (state.canonicalPath.startsWith(path)) { 3388 obbStatesToRemove.add(state); 3389 } 3390 } 3391 3392 for (final ObbState obbState : obbStatesToRemove) { 3393 if (DEBUG_OBB) 3394 Slog.i(TAG, "Removing state for " + obbState.rawPath); 3395 3396 removeObbStateLocked(obbState); 3397 3398 try { 3399 obbState.token.onObbResult(obbState.rawPath, obbState.nonce, 3400 OnObbStateChangeListener.UNMOUNTED); 3401 } catch (RemoteException e) { 3402 Slog.i(TAG, "Couldn't send unmount notification for OBB: " 3403 + obbState.rawPath); 3404 } 3405 } 3406 } 3407 break; 3408 } 3409 } 3410 } 3411 } 3412 3413 private static class ObbException extends Exception { 3414 public final int status; 3415 ObbException(int status, String message)3416 public ObbException(int status, String message) { 3417 super(message); 3418 this.status = status; 3419 } 3420 ObbException(int status, Throwable cause)3421 public ObbException(int status, Throwable cause) { 3422 super(cause.getMessage(), cause); 3423 this.status = status; 3424 } 3425 } 3426 3427 abstract class ObbAction { 3428 3429 ObbState mObbState; 3430 ObbAction(ObbState obbState)3431 ObbAction(ObbState obbState) { 3432 mObbState = obbState; 3433 } 3434 execute(ObbActionHandler handler)3435 public void execute(ObbActionHandler handler) { 3436 try { 3437 if (DEBUG_OBB) 3438 Slog.i(TAG, "Starting to execute action: " + toString()); 3439 handleExecute(); 3440 } catch (ObbException e) { 3441 notifyObbStateChange(e); 3442 } 3443 } 3444 handleExecute()3445 abstract void handleExecute() throws ObbException; 3446 notifyObbStateChange(ObbException e)3447 protected void notifyObbStateChange(ObbException e) { 3448 Slog.w(TAG, e); 3449 notifyObbStateChange(e.status); 3450 } 3451 notifyObbStateChange(int status)3452 protected void notifyObbStateChange(int status) { 3453 if (mObbState == null || mObbState.token == null) { 3454 return; 3455 } 3456 3457 try { 3458 mObbState.token.onObbResult(mObbState.rawPath, mObbState.nonce, status); 3459 } catch (RemoteException e) { 3460 Slog.w(TAG, "StorageEventListener went away while calling onObbStateChanged"); 3461 } 3462 } 3463 } 3464 3465 class MountObbAction extends ObbAction { 3466 private final String mKey; 3467 private final int mCallingUid; 3468 private ObbInfo mObbInfo; 3469 MountObbAction(ObbState obbState, String key, int callingUid, ObbInfo obbInfo)3470 MountObbAction(ObbState obbState, String key, int callingUid, ObbInfo obbInfo) { 3471 super(obbState); 3472 mKey = key; 3473 mCallingUid = callingUid; 3474 mObbInfo = obbInfo; 3475 } 3476 3477 @Override handleExecute()3478 public void handleExecute() throws ObbException { 3479 warnOnNotMounted(); 3480 3481 if (!isUidOwnerOfPackageOrSystem(mObbInfo.packageName, mCallingUid)) { 3482 throw new ObbException(ERROR_PERMISSION_DENIED, "Denied attempt to mount OBB " 3483 + mObbInfo.filename + " which is owned by " + mObbInfo.packageName); 3484 } 3485 3486 final boolean isMounted; 3487 synchronized (mObbMounts) { 3488 isMounted = mObbPathToStateMap.containsKey(mObbState.rawPath); 3489 } 3490 if (isMounted) { 3491 throw new ObbException(ERROR_ALREADY_MOUNTED, 3492 "Attempt to mount OBB which is already mounted: " + mObbInfo.filename); 3493 } 3494 3495 final String hashedKey; 3496 final String binderKey; 3497 if (mKey == null) { 3498 hashedKey = "none"; 3499 binderKey = ""; 3500 } else { 3501 try { 3502 SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1"); 3503 3504 KeySpec ks = new PBEKeySpec(mKey.toCharArray(), mObbInfo.salt, 3505 PBKDF2_HASH_ROUNDS, CRYPTO_ALGORITHM_KEY_SIZE); 3506 SecretKey key = factory.generateSecret(ks); 3507 BigInteger bi = new BigInteger(key.getEncoded()); 3508 hashedKey = bi.toString(16); 3509 binderKey = hashedKey; 3510 } catch (GeneralSecurityException e) { 3511 throw new ObbException(ERROR_INTERNAL, e); 3512 } 3513 } 3514 3515 try { 3516 mObbState.volId = mVold.createObb(mObbState.canonicalPath, binderKey, 3517 mObbState.ownerGid); 3518 mVold.mount(mObbState.volId, 0, -1); 3519 3520 if (DEBUG_OBB) 3521 Slog.d(TAG, "Successfully mounted OBB " + mObbState.canonicalPath); 3522 3523 synchronized (mObbMounts) { 3524 addObbStateLocked(mObbState); 3525 } 3526 3527 notifyObbStateChange(MOUNTED); 3528 } catch (Exception e) { 3529 throw new ObbException(ERROR_COULD_NOT_MOUNT, e); 3530 } 3531 } 3532 3533 @Override toString()3534 public String toString() { 3535 StringBuilder sb = new StringBuilder(); 3536 sb.append("MountObbAction{"); 3537 sb.append(mObbState); 3538 sb.append('}'); 3539 return sb.toString(); 3540 } 3541 } 3542 3543 class UnmountObbAction extends ObbAction { 3544 private final boolean mForceUnmount; 3545 UnmountObbAction(ObbState obbState, boolean force)3546 UnmountObbAction(ObbState obbState, boolean force) { 3547 super(obbState); 3548 mForceUnmount = force; 3549 } 3550 3551 @Override handleExecute()3552 public void handleExecute() throws ObbException { 3553 warnOnNotMounted(); 3554 3555 final ObbState existingState; 3556 synchronized (mObbMounts) { 3557 existingState = mObbPathToStateMap.get(mObbState.rawPath); 3558 } 3559 3560 if (existingState == null) { 3561 throw new ObbException(ERROR_NOT_MOUNTED, "Missing existingState"); 3562 } 3563 3564 if (existingState.ownerGid != mObbState.ownerGid) { 3565 notifyObbStateChange(new ObbException(ERROR_PERMISSION_DENIED, 3566 "Permission denied to unmount OBB " + existingState.rawPath 3567 + " (owned by GID " + existingState.ownerGid + ")")); 3568 return; 3569 } 3570 3571 try { 3572 mVold.unmount(mObbState.volId); 3573 mVold.destroyObb(mObbState.volId); 3574 mObbState.volId = null; 3575 3576 synchronized (mObbMounts) { 3577 removeObbStateLocked(existingState); 3578 } 3579 3580 notifyObbStateChange(UNMOUNTED); 3581 } catch (Exception e) { 3582 throw new ObbException(ERROR_COULD_NOT_UNMOUNT, e); 3583 } 3584 } 3585 3586 @Override toString()3587 public String toString() { 3588 StringBuilder sb = new StringBuilder(); 3589 sb.append("UnmountObbAction{"); 3590 sb.append(mObbState); 3591 sb.append(",force="); 3592 sb.append(mForceUnmount); 3593 sb.append('}'); 3594 return sb.toString(); 3595 } 3596 } 3597 dispatchOnStatus(IVoldTaskListener listener, int status, PersistableBundle extras)3598 private void dispatchOnStatus(IVoldTaskListener listener, int status, 3599 PersistableBundle extras) { 3600 if (listener != null) { 3601 try { 3602 listener.onStatus(status, extras); 3603 } catch (RemoteException ignored) { 3604 } 3605 } 3606 } 3607 dispatchOnFinished(IVoldTaskListener listener, int status, PersistableBundle extras)3608 private void dispatchOnFinished(IVoldTaskListener listener, int status, 3609 PersistableBundle extras) { 3610 if (listener != null) { 3611 try { 3612 listener.onFinished(status, extras); 3613 } catch (RemoteException ignored) { 3614 } 3615 } 3616 } 3617 getMountMode(int uid, String packageName)3618 private int getMountMode(int uid, String packageName) { 3619 final int mode = getMountModeInternal(uid, packageName); 3620 if (LOCAL_LOGV) { 3621 Slog.v(TAG, "Resolved mode " + mode + " for " + packageName + "/" 3622 + UserHandle.formatUid(uid)); 3623 } 3624 return mode; 3625 } 3626 getMountModeInternal(int uid, String packageName)3627 private int getMountModeInternal(int uid, String packageName) { 3628 try { 3629 // Get some easy cases out of the way first 3630 if (Process.isIsolated(uid)) { 3631 return Zygote.MOUNT_EXTERNAL_NONE; 3632 } 3633 3634 final String[] packagesForUid = mIPackageManager.getPackagesForUid(uid); 3635 if (ArrayUtils.isEmpty(packagesForUid)) { 3636 // It's possible the package got uninstalled already, so just ignore. 3637 return Zygote.MOUNT_EXTERNAL_NONE; 3638 } 3639 if (packageName == null) { 3640 packageName = packagesForUid[0]; 3641 } 3642 3643 if (mPmInternal.isInstantApp(packageName, UserHandle.getUserId(uid))) { 3644 return Zygote.MOUNT_EXTERNAL_NONE; 3645 } 3646 3647 // Determine if caller is holding runtime permission 3648 final boolean hasRead = StorageManager.checkPermissionAndCheckOp(mContext, false, 0, 3649 uid, packageName, READ_EXTERNAL_STORAGE, OP_READ_EXTERNAL_STORAGE); 3650 final boolean hasWrite = StorageManager.checkPermissionAndCheckOp(mContext, false, 0, 3651 uid, packageName, WRITE_EXTERNAL_STORAGE, OP_WRITE_EXTERNAL_STORAGE); 3652 3653 // We're only willing to give out broad access if they also hold 3654 // runtime permission; this is a firm CDD requirement 3655 final boolean hasFull = mIPackageManager.checkUidPermission(WRITE_MEDIA_STORAGE, 3656 uid) == PERMISSION_GRANTED; 3657 if (hasFull && hasWrite) { 3658 return Zygote.MOUNT_EXTERNAL_FULL; 3659 } 3660 3661 // We're only willing to give out installer access if they also hold 3662 // runtime permission; this is a firm CDD requirement 3663 final boolean hasInstall = mIPackageManager.checkUidPermission(INSTALL_PACKAGES, 3664 uid) == PERMISSION_GRANTED; 3665 boolean hasInstallOp = false; 3666 // OP_REQUEST_INSTALL_PACKAGES is granted/denied per package but vold can't 3667 // update mountpoints of a specific package. So, check the appop for all packages 3668 // sharing the uid and allow same level of storage access for all packages even if 3669 // one of the packages has the appop granted. 3670 for (String uidPackageName : packagesForUid) { 3671 if (mIAppOpsService.checkOperation( 3672 OP_REQUEST_INSTALL_PACKAGES, uid, uidPackageName) == MODE_ALLOWED) { 3673 hasInstallOp = true; 3674 break; 3675 } 3676 } 3677 if ((hasInstall || hasInstallOp) && hasWrite) { 3678 return Zygote.MOUNT_EXTERNAL_WRITE; 3679 } 3680 3681 // Otherwise we're willing to give out sandboxed or non-sandboxed if 3682 // they hold the runtime permission 3683 final boolean hasLegacy = mIAppOpsService.checkOperation(OP_LEGACY_STORAGE, 3684 uid, packageName) == MODE_ALLOWED; 3685 if (hasLegacy && hasWrite) { 3686 return Zygote.MOUNT_EXTERNAL_WRITE; 3687 } else if (hasLegacy && hasRead) { 3688 return Zygote.MOUNT_EXTERNAL_READ; 3689 } else { 3690 return Zygote.MOUNT_EXTERNAL_DEFAULT; 3691 } 3692 } catch (RemoteException e) { 3693 // Should not happen 3694 } 3695 return Zygote.MOUNT_EXTERNAL_NONE; 3696 } 3697 3698 private static class Callbacks extends Handler { 3699 private static final int MSG_STORAGE_STATE_CHANGED = 1; 3700 private static final int MSG_VOLUME_STATE_CHANGED = 2; 3701 private static final int MSG_VOLUME_RECORD_CHANGED = 3; 3702 private static final int MSG_VOLUME_FORGOTTEN = 4; 3703 private static final int MSG_DISK_SCANNED = 5; 3704 private static final int MSG_DISK_DESTROYED = 6; 3705 3706 private final RemoteCallbackList<IStorageEventListener> 3707 mCallbacks = new RemoteCallbackList<>(); 3708 Callbacks(Looper looper)3709 public Callbacks(Looper looper) { 3710 super(looper); 3711 } 3712 register(IStorageEventListener callback)3713 public void register(IStorageEventListener callback) { 3714 mCallbacks.register(callback); 3715 } 3716 unregister(IStorageEventListener callback)3717 public void unregister(IStorageEventListener callback) { 3718 mCallbacks.unregister(callback); 3719 } 3720 3721 @Override handleMessage(Message msg)3722 public void handleMessage(Message msg) { 3723 final SomeArgs args = (SomeArgs) msg.obj; 3724 final int n = mCallbacks.beginBroadcast(); 3725 for (int i = 0; i < n; i++) { 3726 final IStorageEventListener callback = mCallbacks.getBroadcastItem(i); 3727 try { 3728 invokeCallback(callback, msg.what, args); 3729 } catch (RemoteException ignored) { 3730 } 3731 } 3732 mCallbacks.finishBroadcast(); 3733 args.recycle(); 3734 } 3735 invokeCallback(IStorageEventListener callback, int what, SomeArgs args)3736 private void invokeCallback(IStorageEventListener callback, int what, SomeArgs args) 3737 throws RemoteException { 3738 switch (what) { 3739 case MSG_STORAGE_STATE_CHANGED: { 3740 callback.onStorageStateChanged((String) args.arg1, (String) args.arg2, 3741 (String) args.arg3); 3742 break; 3743 } 3744 case MSG_VOLUME_STATE_CHANGED: { 3745 callback.onVolumeStateChanged((VolumeInfo) args.arg1, args.argi2, args.argi3); 3746 break; 3747 } 3748 case MSG_VOLUME_RECORD_CHANGED: { 3749 callback.onVolumeRecordChanged((VolumeRecord) args.arg1); 3750 break; 3751 } 3752 case MSG_VOLUME_FORGOTTEN: { 3753 callback.onVolumeForgotten((String) args.arg1); 3754 break; 3755 } 3756 case MSG_DISK_SCANNED: { 3757 callback.onDiskScanned((DiskInfo) args.arg1, args.argi2); 3758 break; 3759 } 3760 case MSG_DISK_DESTROYED: { 3761 callback.onDiskDestroyed((DiskInfo) args.arg1); 3762 break; 3763 } 3764 } 3765 } 3766 notifyStorageStateChanged(String path, String oldState, String newState)3767 private void notifyStorageStateChanged(String path, String oldState, String newState) { 3768 final SomeArgs args = SomeArgs.obtain(); 3769 args.arg1 = path; 3770 args.arg2 = oldState; 3771 args.arg3 = newState; 3772 obtainMessage(MSG_STORAGE_STATE_CHANGED, args).sendToTarget(); 3773 } 3774 notifyVolumeStateChanged(VolumeInfo vol, int oldState, int newState)3775 private void notifyVolumeStateChanged(VolumeInfo vol, int oldState, int newState) { 3776 final SomeArgs args = SomeArgs.obtain(); 3777 args.arg1 = vol.clone(); 3778 args.argi2 = oldState; 3779 args.argi3 = newState; 3780 obtainMessage(MSG_VOLUME_STATE_CHANGED, args).sendToTarget(); 3781 } 3782 notifyVolumeRecordChanged(VolumeRecord rec)3783 private void notifyVolumeRecordChanged(VolumeRecord rec) { 3784 final SomeArgs args = SomeArgs.obtain(); 3785 args.arg1 = rec.clone(); 3786 obtainMessage(MSG_VOLUME_RECORD_CHANGED, args).sendToTarget(); 3787 } 3788 notifyVolumeForgotten(String fsUuid)3789 private void notifyVolumeForgotten(String fsUuid) { 3790 final SomeArgs args = SomeArgs.obtain(); 3791 args.arg1 = fsUuid; 3792 obtainMessage(MSG_VOLUME_FORGOTTEN, args).sendToTarget(); 3793 } 3794 notifyDiskScanned(DiskInfo disk, int volumeCount)3795 private void notifyDiskScanned(DiskInfo disk, int volumeCount) { 3796 final SomeArgs args = SomeArgs.obtain(); 3797 args.arg1 = disk.clone(); 3798 args.argi2 = volumeCount; 3799 obtainMessage(MSG_DISK_SCANNED, args).sendToTarget(); 3800 } 3801 notifyDiskDestroyed(DiskInfo disk)3802 private void notifyDiskDestroyed(DiskInfo disk) { 3803 final SomeArgs args = SomeArgs.obtain(); 3804 args.arg1 = disk.clone(); 3805 obtainMessage(MSG_DISK_DESTROYED, args).sendToTarget(); 3806 } 3807 } 3808 3809 @Override dump(FileDescriptor fd, PrintWriter writer, String[] args)3810 protected void dump(FileDescriptor fd, PrintWriter writer, String[] args) { 3811 if (!DumpUtils.checkDumpPermission(mContext, TAG, writer)) return; 3812 3813 final IndentingPrintWriter pw = new IndentingPrintWriter(writer, " ", 160); 3814 synchronized (mLock) { 3815 pw.println("Disks:"); 3816 pw.increaseIndent(); 3817 for (int i = 0; i < mDisks.size(); i++) { 3818 final DiskInfo disk = mDisks.valueAt(i); 3819 disk.dump(pw); 3820 } 3821 pw.decreaseIndent(); 3822 3823 pw.println(); 3824 pw.println("Volumes:"); 3825 pw.increaseIndent(); 3826 for (int i = 0; i < mVolumes.size(); i++) { 3827 final VolumeInfo vol = mVolumes.valueAt(i); 3828 if (VolumeInfo.ID_PRIVATE_INTERNAL.equals(vol.id)) continue; 3829 vol.dump(pw); 3830 } 3831 pw.decreaseIndent(); 3832 3833 pw.println(); 3834 pw.println("Records:"); 3835 pw.increaseIndent(); 3836 for (int i = 0; i < mRecords.size(); i++) { 3837 final VolumeRecord note = mRecords.valueAt(i); 3838 note.dump(pw); 3839 } 3840 pw.decreaseIndent(); 3841 3842 pw.println(); 3843 pw.println("Primary storage UUID: " + mPrimaryStorageUuid); 3844 3845 pw.println(); 3846 final Pair<String, Long> pair = StorageManager.getPrimaryStoragePathAndSize(); 3847 if (pair == null) { 3848 pw.println("Internal storage total size: N/A"); 3849 } else { 3850 pw.print("Internal storage ("); 3851 pw.print(pair.first); 3852 pw.print(") total size: "); 3853 pw.print(pair.second); 3854 pw.print(" ("); 3855 pw.print(DataUnit.MEBIBYTES.toBytes(pair.second)); 3856 pw.println(" MiB)"); 3857 } 3858 3859 pw.println(); 3860 pw.println("Local unlocked users: " + Arrays.toString(mLocalUnlockedUsers)); 3861 pw.println("System unlocked users: " + Arrays.toString(mSystemUnlockedUsers)); 3862 3863 final ContentResolver cr = mContext.getContentResolver(); 3864 pw.println(); 3865 pw.println("Isolated storage, local feature flag: " 3866 + Settings.Global.getInt(cr, Settings.Global.ISOLATED_STORAGE_LOCAL, 0)); 3867 pw.println("Isolated storage, remote feature flag: " 3868 + Settings.Global.getInt(cr, Settings.Global.ISOLATED_STORAGE_REMOTE, 0)); 3869 pw.println("Isolated storage, resolved: " + StorageManager.hasIsolatedStorage()); 3870 } 3871 3872 synchronized (mObbMounts) { 3873 pw.println(); 3874 pw.println("mObbMounts:"); 3875 pw.increaseIndent(); 3876 final Iterator<Entry<IBinder, List<ObbState>>> binders = mObbMounts.entrySet() 3877 .iterator(); 3878 while (binders.hasNext()) { 3879 Entry<IBinder, List<ObbState>> e = binders.next(); 3880 pw.println(e.getKey() + ":"); 3881 pw.increaseIndent(); 3882 final List<ObbState> obbStates = e.getValue(); 3883 for (final ObbState obbState : obbStates) { 3884 pw.println(obbState); 3885 } 3886 pw.decreaseIndent(); 3887 } 3888 pw.decreaseIndent(); 3889 3890 pw.println(); 3891 pw.println("mObbPathToStateMap:"); 3892 pw.increaseIndent(); 3893 final Iterator<Entry<String, ObbState>> maps = mObbPathToStateMap.entrySet().iterator(); 3894 while (maps.hasNext()) { 3895 final Entry<String, ObbState> e = maps.next(); 3896 pw.print(e.getKey()); 3897 pw.print(" -> "); 3898 pw.println(e.getValue()); 3899 } 3900 pw.decreaseIndent(); 3901 } 3902 3903 pw.println(); 3904 pw.print("Last maintenance: "); 3905 pw.println(TimeUtils.formatForLogging(mLastMaintenance)); 3906 } 3907 3908 /** {@inheritDoc} */ 3909 @Override monitor()3910 public void monitor() { 3911 try { 3912 mVold.monitor(); 3913 } catch (Exception e) { 3914 Slog.wtf(TAG, e); 3915 } 3916 } 3917 3918 private final class StorageManagerInternalImpl extends StorageManagerInternal { 3919 // Not guarded by a lock. 3920 private final CopyOnWriteArrayList<ExternalStorageMountPolicy> mPolicies = 3921 new CopyOnWriteArrayList<>(); 3922 3923 @GuardedBy("mResetListeners") 3924 private final List<StorageManagerInternal.ResetListener> mResetListeners = 3925 new ArrayList<>(); 3926 3927 @Override addExternalStoragePolicy(ExternalStorageMountPolicy policy)3928 public void addExternalStoragePolicy(ExternalStorageMountPolicy policy) { 3929 // No locking - CopyOnWriteArrayList 3930 mPolicies.add(policy); 3931 } 3932 3933 @Override onExternalStoragePolicyChanged(int uid, String packageName)3934 public void onExternalStoragePolicyChanged(int uid, String packageName) { 3935 final int mountMode = getExternalStorageMountMode(uid, packageName); 3936 remountUidExternalStorage(uid, mountMode); 3937 } 3938 3939 @Override getExternalStorageMountMode(int uid, String packageName)3940 public int getExternalStorageMountMode(int uid, String packageName) { 3941 if (ENABLE_ISOLATED_STORAGE) { 3942 return getMountMode(uid, packageName); 3943 } 3944 try { 3945 if (packageName == null) { 3946 final String[] packagesForUid = mIPackageManager.getPackagesForUid(uid); 3947 packageName = packagesForUid[0]; 3948 } 3949 } catch (RemoteException e) { 3950 // Should not happen - same process 3951 } 3952 // No locking - CopyOnWriteArrayList 3953 int mountMode = Integer.MAX_VALUE; 3954 for (ExternalStorageMountPolicy policy : mPolicies) { 3955 final int policyMode = policy.getMountMode(uid, packageName); 3956 if (policyMode == Zygote.MOUNT_EXTERNAL_NONE) { 3957 return Zygote.MOUNT_EXTERNAL_NONE; 3958 } 3959 mountMode = Math.min(mountMode, policyMode); 3960 } 3961 if (mountMode == Integer.MAX_VALUE) { 3962 return Zygote.MOUNT_EXTERNAL_NONE; 3963 } 3964 return mountMode; 3965 } 3966 3967 @Override addResetListener(StorageManagerInternal.ResetListener listener)3968 public void addResetListener(StorageManagerInternal.ResetListener listener) { 3969 synchronized (mResetListeners) { 3970 mResetListeners.add(listener); 3971 } 3972 } 3973 onReset(IVold vold)3974 public void onReset(IVold vold) { 3975 synchronized (mResetListeners) { 3976 for (StorageManagerInternal.ResetListener listener : mResetListeners) { 3977 listener.onReset(vold); 3978 } 3979 } 3980 } 3981 hasExternalStorage(int uid, String packageName)3982 public boolean hasExternalStorage(int uid, String packageName) { 3983 // No need to check for system uid. This avoids a deadlock between 3984 // PackageManagerService and AppOpsService. 3985 if (uid == Process.SYSTEM_UID) { 3986 return true; 3987 } 3988 if (ENABLE_ISOLATED_STORAGE) { 3989 return getMountMode(uid, packageName) != Zygote.MOUNT_EXTERNAL_NONE; 3990 } 3991 // No locking - CopyOnWriteArrayList 3992 for (ExternalStorageMountPolicy policy : mPolicies) { 3993 final boolean policyHasStorage = policy.hasExternalStorage(uid, packageName); 3994 if (!policyHasStorage) { 3995 return false; 3996 } 3997 } 3998 return true; 3999 } 4000 onAppOpsChanged(int code, int uid, @Nullable String packageName, int mode)4001 public void onAppOpsChanged(int code, int uid, 4002 @Nullable String packageName, int mode) { 4003 if (mode == MODE_ALLOWED && (code == OP_READ_EXTERNAL_STORAGE 4004 || code == OP_WRITE_EXTERNAL_STORAGE 4005 || code == OP_REQUEST_INSTALL_PACKAGES)) { 4006 final long token = Binder.clearCallingIdentity(); 4007 try { 4008 final UserManagerInternal userManagerInternal = 4009 LocalServices.getService(UserManagerInternal.class); 4010 if (userManagerInternal.isUserInitialized(UserHandle.getUserId(uid))) { 4011 onExternalStoragePolicyChanged(uid, packageName); 4012 } 4013 } finally { 4014 Binder.restoreCallingIdentity(token); 4015 } 4016 } 4017 } 4018 } 4019 } 4020