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