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