/*
 * Copyright (C) 2007 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.server;

import static android.Manifest.permission.ACCESS_MTP;
import static android.Manifest.permission.INSTALL_PACKAGES;
import static android.Manifest.permission.READ_EXTERNAL_STORAGE;
import static android.Manifest.permission.WRITE_EXTERNAL_STORAGE;
import static android.Manifest.permission.WRITE_MEDIA_STORAGE;
import static android.app.ActivityManager.PROCESS_STATE_NONEXISTENT;
import static android.app.AppOpsManager.MODE_ALLOWED;
import static android.app.AppOpsManager.OP_LEGACY_STORAGE;
import static android.app.AppOpsManager.OP_MANAGE_EXTERNAL_STORAGE;
import static android.app.AppOpsManager.OP_READ_EXTERNAL_STORAGE;
import static android.app.AppOpsManager.OP_REQUEST_INSTALL_PACKAGES;
import static android.app.AppOpsManager.OP_WRITE_EXTERNAL_STORAGE;
import static android.content.pm.PackageManager.MATCH_ANY_USER;
import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_AWARE;
import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_UNAWARE;
import static android.content.pm.PackageManager.MATCH_UNINSTALLED_PACKAGES;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import static android.os.ParcelFileDescriptor.MODE_READ_WRITE;
import static android.os.storage.OnObbStateChangeListener.ERROR_ALREADY_MOUNTED;
import static android.os.storage.OnObbStateChangeListener.ERROR_COULD_NOT_MOUNT;
import static android.os.storage.OnObbStateChangeListener.ERROR_COULD_NOT_UNMOUNT;
import static android.os.storage.OnObbStateChangeListener.ERROR_INTERNAL;
import static android.os.storage.OnObbStateChangeListener.ERROR_NOT_MOUNTED;
import static android.os.storage.OnObbStateChangeListener.ERROR_PERMISSION_DENIED;
import static android.os.storage.OnObbStateChangeListener.MOUNTED;
import static android.os.storage.OnObbStateChangeListener.UNMOUNTED;
import static android.os.storage.StorageManager.PROP_FORCED_SCOPED_STORAGE_WHITELIST;
import static android.os.storage.StorageManager.PROP_FUSE;
import static android.os.storage.StorageManager.PROP_SETTINGS_FUSE;

import static com.android.internal.util.XmlUtils.readIntAttribute;
import static com.android.internal.util.XmlUtils.readLongAttribute;
import static com.android.internal.util.XmlUtils.readStringAttribute;
import static com.android.internal.util.XmlUtils.writeIntAttribute;
import static com.android.internal.util.XmlUtils.writeLongAttribute;
import static com.android.internal.util.XmlUtils.writeStringAttribute;

import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT;
import static org.xmlpull.v1.XmlPullParser.START_TAG;

import android.Manifest;
import android.annotation.Nullable;
import android.app.ActivityManager;
import android.app.ActivityManagerInternal;
import android.app.AppOpsManager;
import android.app.IActivityManager;
import android.app.KeyguardManager;
import android.app.admin.SecurityLog;
import android.app.usage.StorageStatsManager;
import android.content.BroadcastReceiver;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.ApplicationInfo;
import android.content.pm.IPackageManager;
import android.content.pm.IPackageMoveObserver;
import android.content.pm.PackageManager;
import android.content.pm.PackageManagerInternal;
import android.content.pm.ProviderInfo;
import android.content.pm.UserInfo;
import android.content.res.Configuration;
import android.content.res.ObbInfo;
import android.database.ContentObserver;
import android.net.Uri;
import android.os.Binder;
import android.os.DropBoxManager;
import android.os.Environment;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
import android.os.IStoraged;
import android.os.IVold;
import android.os.IVoldListener;
import android.os.IVoldMountCallback;
import android.os.IVoldTaskListener;
import android.os.Looper;
import android.os.Message;
import android.os.ParcelFileDescriptor;
import android.os.ParcelableException;
import android.os.PersistableBundle;
import android.os.PowerManager;
import android.os.Process;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.ServiceSpecificException;
import android.os.SystemClock;
import android.os.SystemProperties;
import android.os.UserHandle;
import android.os.UserManager;
import android.os.UserManagerInternal;
import android.os.storage.DiskInfo;
import android.os.storage.IObbActionListener;
import android.os.storage.IStorageEventListener;
import android.os.storage.IStorageManager;
import android.os.storage.IStorageShutdownObserver;
import android.os.storage.OnObbStateChangeListener;
import android.os.storage.StorageManager;
import android.os.storage.StorageManagerInternal;
import android.os.storage.StorageVolume;
import android.os.storage.VolumeInfo;
import android.os.storage.VolumeRecord;
import android.provider.DeviceConfig;
import android.provider.DocumentsContract;
import android.provider.Downloads;
import android.provider.MediaStore;
import android.provider.Settings;
import android.sysprop.VoldProperties;
import android.text.TextUtils;
import android.text.format.DateUtils;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.AtomicFile;
import android.util.DataUnit;
import android.util.FeatureFlagUtils;
import android.util.Log;
import android.util.Pair;
import android.util.Slog;
import android.util.TimeUtils;
import android.util.Xml;

import com.android.internal.annotations.GuardedBy;
import com.android.internal.app.IAppOpsCallback;
import com.android.internal.app.IAppOpsService;
import com.android.internal.content.PackageMonitor;
import com.android.internal.os.AppFuseMount;
import com.android.internal.os.BackgroundThread;
import com.android.internal.os.FuseUnavailableMountException;
import com.android.internal.os.SomeArgs;
import com.android.internal.os.Zygote;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.CollectionUtils;
import com.android.internal.util.DumpUtils;
import com.android.internal.util.FastXmlSerializer;
import com.android.internal.util.HexDump;
import com.android.internal.util.IndentingPrintWriter;
import com.android.internal.util.Preconditions;
import com.android.internal.widget.LockPatternUtils;
import com.android.server.pm.Installer;
import com.android.server.storage.AppFuseBridge;
import com.android.server.storage.StorageSessionController;
import com.android.server.storage.StorageSessionController.ExternalStorageServiceException;
import com.android.server.wm.ActivityTaskManagerInternal;
import com.android.server.wm.ActivityTaskManagerInternal.ScreenObserver;

import libcore.io.IoUtils;
import libcore.util.EmptyArray;

import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlSerializer;

import java.io.File;
import java.io.FileDescriptor;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.math.BigInteger;
import java.nio.charset.StandardCharsets;
import java.security.GeneralSecurityException;
import java.security.spec.KeySpec;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;

/**
 * Service responsible for various storage media. Connects to {@code vold} to
 * watch for and manage dynamically added storage, such as SD cards and USB mass
 * storage. Also decides how storage should be presented to users on the device.
 */
class StorageManagerService extends IStorageManager.Stub
        implements Watchdog.Monitor, ScreenObserver {

    // Static direct instance pointer for the tightly-coupled idle service to use
    static StorageManagerService sSelf = null;

    /* Read during boot to decide whether to enable zram when available */
    private static final String ZRAM_ENABLED_PROPERTY =
            "persist.sys.zram_enabled";

    private static final boolean ENABLE_ISOLATED_STORAGE = StorageManager.hasIsolatedStorage();

    // A system property to control if obb app data isolation is enabled in vold.
    private static final String ANDROID_VOLD_APP_DATA_ISOLATION_ENABLED_PROPERTY =
            "persist.sys.vold_app_data_isolation_enabled";

    // How long we wait to reset storage, if we failed to call onMount on the
    // external storage service.
    public static final int FAILED_MOUNT_RESET_TIMEOUT_SECONDS = 10;
    /**
     * If {@code 1}, enables the isolated storage feature. If {@code -1},
     * disables the isolated storage feature. If {@code 0}, uses the default
     * value from the build system.
     */
    private static final String ISOLATED_STORAGE_ENABLED = "isolated_storage_enabled";

    /**
     * If {@code 1}, enables FuseDaemon to intercept file system ops. If {@code -1},
     * disables FuseDaemon. If {@code 0}, uses the default value from the build system.
     */
    private static final String FUSE_ENABLED = "fuse_enabled";
    private static final boolean DEFAULT_FUSE_ENABLED = true;

    @GuardedBy("mLock")
    private final Set<Integer> mFuseMountedUser = new ArraySet<>();

    public static class Lifecycle extends SystemService {
        private StorageManagerService mStorageManagerService;

        public Lifecycle(Context context) {
            super(context);
        }

        @Override
        public void onStart() {
            mStorageManagerService = new StorageManagerService(getContext());
            publishBinderService("mount", mStorageManagerService);
            mStorageManagerService.start();
        }

        @Override
        public void onBootPhase(int phase) {
            if (phase == SystemService.PHASE_SYSTEM_SERVICES_READY) {
                mStorageManagerService.servicesReady();
            } else if (phase == SystemService.PHASE_ACTIVITY_MANAGER_READY) {
                mStorageManagerService.systemReady();
            } else if (phase == SystemService.PHASE_BOOT_COMPLETED) {
                mStorageManagerService.bootCompleted();
            }
        }

        @Override
        public void onSwitchUser(int userHandle) {
            mStorageManagerService.mCurrentUserId = userHandle;
        }

        @Override
        public void onUnlockUser(int userHandle) {
            mStorageManagerService.onUnlockUser(userHandle);
        }

        @Override
        public void onCleanupUser(int userHandle) {
            mStorageManagerService.onCleanupUser(userHandle);
        }

        @Override
        public void onStopUser(int userHandle) {
            mStorageManagerService.onStopUser(userHandle);
        }

        @Override
        public void onUserStarting(TargetUser user) {
            mStorageManagerService.snapshotAndMonitorLegacyStorageAppOp(user.getUserHandle());
        }
    }

    private static final boolean DEBUG_EVENTS = false;
    private static final boolean DEBUG_OBB = false;

    /**
     * We now talk to vold over Binder, and it has its own internal lock to
     * serialize certain calls. All long-running operations have been migrated
     * to be async with callbacks, so we want watchdog to fire if vold wedges.
     */
    private static final boolean WATCHDOG_ENABLE = true;

    /**
     * Our goal is for all Android devices to be usable as development devices,
     * which includes the new Direct Boot mode added in N. For devices that
     * don't have native FBE support, we offer an emulation mode for developer
     * testing purposes, but if it's prohibitively difficult to support this
     * mode, it can be disabled for specific products using this flag.
     */
    private static final boolean EMULATE_FBE_SUPPORTED = true;

    private static final String TAG = "StorageManagerService";
    private static final boolean LOCAL_LOGV = Log.isLoggable(TAG, Log.VERBOSE);

    private static final String TAG_STORAGE_BENCHMARK = "storage_benchmark";
    private static final String TAG_STORAGE_TRIM = "storage_trim";

    /** Magic value sent by MoveTask.cpp */
    private static final int MOVE_STATUS_COPY_FINISHED = 82;

    private static final int VERSION_INIT = 1;
    private static final int VERSION_ADD_PRIMARY = 2;
    private static final int VERSION_FIX_PRIMARY = 3;

    private static final String TAG_VOLUMES = "volumes";
    private static final String ATTR_VERSION = "version";
    private static final String ATTR_PRIMARY_STORAGE_UUID = "primaryStorageUuid";
    private static final String TAG_VOLUME = "volume";
    private static final String ATTR_TYPE = "type";
    private static final String ATTR_FS_UUID = "fsUuid";
    private static final String ATTR_PART_GUID = "partGuid";
    private static final String ATTR_NICKNAME = "nickname";
    private static final String ATTR_USER_FLAGS = "userFlags";
    private static final String ATTR_CREATED_MILLIS = "createdMillis";
    private static final String ATTR_LAST_SEEN_MILLIS = "lastSeenMillis";
    private static final String ATTR_LAST_TRIM_MILLIS = "lastTrimMillis";
    private static final String ATTR_LAST_BENCH_MILLIS = "lastBenchMillis";

    private static final String[] ALL_STORAGE_PERMISSIONS = {
            Manifest.permission.READ_EXTERNAL_STORAGE,
            Manifest.permission.WRITE_EXTERNAL_STORAGE
    };

    @Nullable public static String sMediaStoreAuthorityProcessName;

    private final AtomicFile mSettingsFile;

    /**
     * <em>Never</em> hold the lock while performing downcalls into vold, since
     * unsolicited events can suddenly appear to update data structures.
     */
    private final Object mLock = LockGuard.installNewLock(LockGuard.INDEX_STORAGE);

    /**
     * Similar to {@link #mLock}, never hold this lock while performing downcalls into vold.
     * Also, never hold this while calling into PackageManagerService since it is used in callbacks
     * from PackageManagerService.
     *
     * If both {@link #mLock} and this lock need to be held, {@link #mLock} should be acquired
     * before this.
     *
     * Use -PL suffix for methods that need to called with this lock held.
     */
    private final Object mPackagesLock = new Object();

    /**
     * mLocalUnlockedUsers affects the return value of isUserUnlocked.  If
     * any value in the array changes, then the binder cache for
     * isUserUnlocked must be invalidated.  When adding mutating methods to
     * WatchedLockedUsers, be sure to invalidate the cache in the new
     * methods.
     */
    private class WatchedLockedUsers {
        private int[] users = EmptyArray.INT;
        public WatchedLockedUsers() {
            invalidateIsUserUnlockedCache();
        }
        public void append(int userId) {
            users = ArrayUtils.appendInt(users, userId);
            invalidateIsUserUnlockedCache();
        }
        public void remove(int userId) {
            users = ArrayUtils.removeInt(users, userId);
            invalidateIsUserUnlockedCache();
        }
        public boolean contains(int userId) {
            return ArrayUtils.contains(users, userId);
        }
        public int[] all() {
            return users;
        }
        @Override
        public String toString() {
            return Arrays.toString(users);
        }
        private void invalidateIsUserUnlockedCache() {
            UserManager.invalidateIsUserUnlockedCache();
        }
    }

    /** Set of users that we know are unlocked. */
    @GuardedBy("mLock")
    private WatchedLockedUsers mLocalUnlockedUsers = new WatchedLockedUsers();
    /** Set of users that system knows are unlocked. */
    @GuardedBy("mLock")
    private int[] mSystemUnlockedUsers = EmptyArray.INT;

    /** Map from disk ID to disk */
    @GuardedBy("mLock")
    private ArrayMap<String, DiskInfo> mDisks = new ArrayMap<>();
    /** Map from volume ID to disk */
    @GuardedBy("mLock")
    private final ArrayMap<String, VolumeInfo> mVolumes = new ArrayMap<>();

    /** Map from UUID to record */
    @GuardedBy("mLock")
    private ArrayMap<String, VolumeRecord> mRecords = new ArrayMap<>();
    @GuardedBy("mLock")
    private String mPrimaryStorageUuid;

    /** Map from disk ID to latches */
    @GuardedBy("mLock")
    private ArrayMap<String, CountDownLatch> mDiskScanLatches = new ArrayMap<>();

    @GuardedBy("mLock")
    private IPackageMoveObserver mMoveCallback;
    @GuardedBy("mLock")
    private String mMoveTargetUuid;

    private volatile int mMediaStoreAuthorityAppId = -1;

    private volatile int mDownloadsAuthorityAppId = -1;

    private volatile int mExternalStorageAuthorityAppId = -1;

    private volatile int mCurrentUserId = UserHandle.USER_SYSTEM;

    private final Installer mInstaller;

    /** Holding lock for AppFuse business */
    private final Object mAppFuseLock = new Object();

    @GuardedBy("mAppFuseLock")
    private int mNextAppFuseName = 0;

    @GuardedBy("mAppFuseLock")
    private AppFuseBridge mAppFuseBridge = null;

    /** Matches known application dir paths. The first group contains the generic part of the path,
     * the second group contains the user id (or null if it's a public volume without users), the
     * third group contains the package name, and the fourth group the remainder of the path.
     */
    public static final Pattern KNOWN_APP_DIR_PATHS = Pattern.compile(
            "(?i)(^/storage/[^/]+/(?:([0-9]+)/)?Android/(?:data|media|obb|sandbox)/)([^/]+)(/.*)?");


    /** Automotive device unlockes users before system boot complete and this requires special
     * handling as vold reset can lead into race conditions. When this is set, all users unlocked
     * in {@code UserManager} level are unlocked after vold reset.
     */
    private final boolean mIsAutomotive;

    private VolumeInfo findVolumeByIdOrThrow(String id) {
        synchronized (mLock) {
            final VolumeInfo vol = mVolumes.get(id);
            if (vol != null) {
                return vol;
            }
        }
        throw new IllegalArgumentException("No volume found for ID " + id);
    }

    private String findVolumeIdForPathOrThrow(String path) {
        synchronized (mLock) {
            for (int i = 0; i < mVolumes.size(); i++) {
                final VolumeInfo vol = mVolumes.valueAt(i);
                if (vol.path != null && path.startsWith(vol.path)) {
                    return vol.id;
                }
            }
        }
        throw new IllegalArgumentException("No volume found for path " + path);
    }

    private VolumeRecord findRecordForPath(String path) {
        synchronized (mLock) {
            for (int i = 0; i < mVolumes.size(); i++) {
                final VolumeInfo vol = mVolumes.valueAt(i);
                if (vol.path != null && path.startsWith(vol.path)) {
                    return mRecords.get(vol.fsUuid);
                }
            }
        }
        return null;
    }

    private String scrubPath(String path) {
        if (path.startsWith(Environment.getDataDirectory().getAbsolutePath())) {
            return "internal";
        }
        final VolumeRecord rec = findRecordForPath(path);
        if (rec == null || rec.createdMillis == 0) {
            return "unknown";
        } else {
            return "ext:" + (int) ((System.currentTimeMillis() - rec.createdMillis)
                    / DateUtils.WEEK_IN_MILLIS) + "w";
        }
    }

    private @Nullable VolumeInfo findStorageForUuid(String volumeUuid) {
        final StorageManager storage = mContext.getSystemService(StorageManager.class);
        if (Objects.equals(StorageManager.UUID_PRIVATE_INTERNAL, volumeUuid)) {
            return storage.findVolumeById(VolumeInfo.ID_EMULATED_INTERNAL + ";" + 0);
        } else if (Objects.equals(StorageManager.UUID_PRIMARY_PHYSICAL, volumeUuid)) {
            return storage.getPrimaryPhysicalVolume();
        } else {
            return storage.findEmulatedForPrivate(storage.findVolumeByUuid(volumeUuid));
        }
    }

    private boolean shouldBenchmark() {
        final long benchInterval = Settings.Global.getLong(mContext.getContentResolver(),
                Settings.Global.STORAGE_BENCHMARK_INTERVAL, DateUtils.WEEK_IN_MILLIS);
        if (benchInterval == -1) {
            return false;
        } else if (benchInterval == 0) {
            return true;
        }

        synchronized (mLock) {
            for (int i = 0; i < mVolumes.size(); i++) {
                final VolumeInfo vol = mVolumes.valueAt(i);
                final VolumeRecord rec = mRecords.get(vol.fsUuid);
                if (vol.isMountedWritable() && rec != null) {
                    final long benchAge = System.currentTimeMillis() - rec.lastBenchMillis;
                    if (benchAge >= benchInterval) {
                        return true;
                    }
                }
            }
            return false;
        }
    }

    private CountDownLatch findOrCreateDiskScanLatch(String diskId) {
        synchronized (mLock) {
            CountDownLatch latch = mDiskScanLatches.get(diskId);
            if (latch == null) {
                latch = new CountDownLatch(1);
                mDiskScanLatches.put(diskId, latch);
            }
            return latch;
        }
    }

    /** List of crypto types.
      * These must match CRYPT_TYPE_XXX in cryptfs.h AND their
      * corresponding commands in CommandListener.cpp */
    public static final String[] CRYPTO_TYPES
        = { "password", "default", "pattern", "pin" };

    private final Context mContext;
    private final ContentResolver mResolver;

    private volatile IVold mVold;
    private volatile IStoraged mStoraged;

    private volatile boolean mBootCompleted = false;
    private volatile boolean mDaemonConnected = false;
    private volatile boolean mSecureKeyguardShowing = true;

    private PackageManagerInternal mPmInternal;

    private IPackageManager mIPackageManager;
    private IAppOpsService mIAppOpsService;

    private final Callbacks mCallbacks;
    private final LockPatternUtils mLockPatternUtils;

    /**
     * The size of the crypto algorithm key in bits for OBB files. Currently
     * Twofish is used which takes 128-bit keys.
     */
    private static final int CRYPTO_ALGORITHM_KEY_SIZE = 128;

    /**
     * The number of times to run SHA1 in the PBKDF2 function for OBB files.
     * 1024 is reasonably secure and not too slow.
     */
    private static final int PBKDF2_HASH_ROUNDS = 1024;

    /**
     * Mounted OBB tracking information. Used to track the current state of all
     * OBBs.
     */
    final private Map<IBinder, List<ObbState>> mObbMounts = new HashMap<IBinder, List<ObbState>>();

    /** Map from raw paths to {@link ObbState}. */
    final private Map<String, ObbState> mObbPathToStateMap = new HashMap<String, ObbState>();

    // Not guarded by a lock.
    private final StorageManagerInternalImpl mStorageManagerInternal
            = new StorageManagerInternalImpl();

    // Not guarded by a lock.
    private final StorageSessionController mStorageSessionController;

    private final boolean mIsFuseEnabled;

    private final boolean mVoldAppDataIsolationEnabled;

    @GuardedBy("mLock")
    private final Set<Integer> mUidsWithLegacyExternalStorage = new ArraySet<>();
    // Not guarded by lock, always used on the ActivityManager thread
    private final Map<Integer, PackageMonitor> mPackageMonitorsForUser = new ArrayMap<>();


    class ObbState implements IBinder.DeathRecipient {
        public ObbState(String rawPath, String canonicalPath, int callingUid,
                IObbActionListener token, int nonce, String volId) {
            this.rawPath = rawPath;
            this.canonicalPath = canonicalPath;
            this.ownerGid = UserHandle.getSharedAppGid(callingUid);
            this.token = token;
            this.nonce = nonce;
            this.volId = volId;
        }

        final String rawPath;
        final String canonicalPath;

        final int ownerGid;

        // Token of remote Binder caller
        final IObbActionListener token;

        // Identifier to pass back to the token
        final int nonce;

        String volId;

        public IBinder getBinder() {
            return token.asBinder();
        }

        @Override
        public void binderDied() {
            ObbAction action = new UnmountObbAction(this, true);
            mObbActionHandler.sendMessage(mObbActionHandler.obtainMessage(OBB_RUN_ACTION, action));
        }

        public void link() throws RemoteException {
            getBinder().linkToDeath(this, 0);
        }

        public void unlink() {
            getBinder().unlinkToDeath(this, 0);
        }

        @Override
        public String toString() {
            StringBuilder sb = new StringBuilder("ObbState{");
            sb.append("rawPath=").append(rawPath);
            sb.append(",canonicalPath=").append(canonicalPath);
            sb.append(",ownerGid=").append(ownerGid);
            sb.append(",token=").append(token);
            sb.append(",binder=").append(getBinder());
            sb.append(",volId=").append(volId);
            sb.append('}');
            return sb.toString();
        }
    }

    // OBB Action Handler
    final private ObbActionHandler mObbActionHandler;

    // OBB action handler messages
    private static final int OBB_RUN_ACTION = 1;
    private static final int OBB_FLUSH_MOUNT_STATE = 2;

    // Last fstrim operation tracking
    private static final String LAST_FSTRIM_FILE = "last-fstrim";
    private final File mLastMaintenanceFile;
    private long mLastMaintenance;

    // Handler messages
    private static final int H_SYSTEM_READY = 1;
    private static final int H_DAEMON_CONNECTED = 2;
    private static final int H_SHUTDOWN = 3;
    private static final int H_FSTRIM = 4;
    private static final int H_VOLUME_MOUNT = 5;
    private static final int H_VOLUME_BROADCAST = 6;
    private static final int H_INTERNAL_BROADCAST = 7;
    private static final int H_VOLUME_UNMOUNT = 8;
    private static final int H_PARTITION_FORGET = 9;
    private static final int H_RESET = 10;
    private static final int H_RUN_IDLE_MAINT = 11;
    private static final int H_ABORT_IDLE_MAINT = 12;
    private static final int H_BOOT_COMPLETED = 13;
    private static final int H_COMPLETE_UNLOCK_USER = 14;
    private static final int H_VOLUME_STATE_CHANGED = 15;

    class StorageManagerServiceHandler extends Handler {
        public StorageManagerServiceHandler(Looper looper) {
            super(looper);
        }

        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case H_SYSTEM_READY: {
                    handleSystemReady();
                    break;
                }
                case H_BOOT_COMPLETED: {
                    handleBootCompleted();
                    break;
                }
                case H_DAEMON_CONNECTED: {
                    handleDaemonConnected();
                    break;
                }
                case H_FSTRIM: {
                    Slog.i(TAG, "Running fstrim idle maintenance");

                    // Remember when we kicked it off
                    try {
                        mLastMaintenance = System.currentTimeMillis();
                        mLastMaintenanceFile.setLastModified(mLastMaintenance);
                    } catch (Exception e) {
                        Slog.e(TAG, "Unable to record last fstrim!");
                    }

                    // TODO: Reintroduce shouldBenchmark() test
                    fstrim(0, null);

                    // invoke the completion callback, if any
                    // TODO: fstrim is non-blocking, so remove this useless callback
                    Runnable callback = (Runnable) msg.obj;
                    if (callback != null) {
                        callback.run();
                    }
                    break;
                }
                case H_SHUTDOWN: {
                    final IStorageShutdownObserver obs = (IStorageShutdownObserver) msg.obj;
                    boolean success = false;
                    try {
                        mVold.shutdown();
                        success = true;
                    } catch (Exception e) {
                        Slog.wtf(TAG, e);
                    }
                    if (obs != null) {
                        try {
                            obs.onShutDownComplete(success ? 0 : -1);
                        } catch (Exception ignored) {
                        }
                    }
                    break;
                }
                case H_VOLUME_MOUNT: {
                    final VolumeInfo vol = (VolumeInfo) msg.obj;
                    if (isMountDisallowed(vol)) {
                        Slog.i(TAG, "Ignoring mount " + vol.getId() + " due to policy");
                        break;
                    }

                    mount(vol);
                    break;
                }
                case H_VOLUME_UNMOUNT: {
                    final VolumeInfo vol = (VolumeInfo) msg.obj;
                    unmount(vol);
                    break;
                }
                case H_VOLUME_BROADCAST: {
                    final StorageVolume userVol = (StorageVolume) msg.obj;
                    final String envState = userVol.getState();
                    Slog.d(TAG, "Volume " + userVol.getId() + " broadcasting " + envState + " to "
                            + userVol.getOwner());

                    final String action = VolumeInfo.getBroadcastForEnvironment(envState);
                    if (action != null) {
                        final Intent intent = new Intent(action,
                                Uri.fromFile(userVol.getPathFile()));
                        intent.putExtra(StorageVolume.EXTRA_STORAGE_VOLUME, userVol);
                        intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT
                                | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
                        mContext.sendBroadcastAsUser(intent, userVol.getOwner());
                    }
                    break;
                }
                case H_INTERNAL_BROADCAST: {
                    // Internal broadcasts aimed at system components, not for
                    // third-party apps.
                    final Intent intent = (Intent) msg.obj;
                    mContext.sendBroadcastAsUser(intent, UserHandle.ALL,
                            android.Manifest.permission.WRITE_MEDIA_STORAGE);
                    break;
                }
                case H_PARTITION_FORGET: {
                    final VolumeRecord rec = (VolumeRecord) msg.obj;
                    forgetPartition(rec.partGuid, rec.fsUuid);
                    break;
                }
                case H_RESET: {
                    resetIfBootedAndConnected();
                    break;
                }
                case H_RUN_IDLE_MAINT: {
                    Slog.i(TAG, "Running idle maintenance");
                    runIdleMaint((Runnable)msg.obj);
                    break;
                }
                case H_ABORT_IDLE_MAINT: {
                    Slog.i(TAG, "Aborting idle maintenance");
                    abortIdleMaint((Runnable)msg.obj);
                    break;
                }
                case H_COMPLETE_UNLOCK_USER: {
                    completeUnlockUser((int) msg.obj);
                    break;
                }
                case H_VOLUME_STATE_CHANGED: {
                    final SomeArgs args = (SomeArgs) msg.obj;
                    onVolumeStateChangedAsync((VolumeInfo) args.arg1, (int) args.arg2,
                            (int) args.arg3);
                }
            }
        }
    }

    private final Handler mHandler;

    private BroadcastReceiver mUserReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            final String action = intent.getAction();
            final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
            Preconditions.checkArgument(userId >= 0);

            try {
                if (Intent.ACTION_USER_ADDED.equals(action)) {
                    final UserManager um = mContext.getSystemService(UserManager.class);
                    final int userSerialNumber = um.getUserSerialNumber(userId);
                    mVold.onUserAdded(userId, userSerialNumber);
                } else if (Intent.ACTION_USER_REMOVED.equals(action)) {
                    synchronized (mVolumes) {
                        final int size = mVolumes.size();
                        for (int i = 0; i < size; i++) {
                            final VolumeInfo vol = mVolumes.valueAt(i);
                            if (vol.mountUserId == userId) {
                                vol.mountUserId = UserHandle.USER_NULL;
                                mHandler.obtainMessage(H_VOLUME_UNMOUNT, vol).sendToTarget();
                            }
                        }
                    }
                    mVold.onUserRemoved(userId);
                }
            } catch (Exception e) {
                Slog.wtf(TAG, e);
            }
        }
    };

    private void waitForLatch(CountDownLatch latch, String condition, long timeoutMillis)
            throws TimeoutException {
        final long startMillis = SystemClock.elapsedRealtime();
        while (true) {
            try {
                if (latch.await(5000, TimeUnit.MILLISECONDS)) {
                    return;
                } else {
                    Slog.w(TAG, "Thread " + Thread.currentThread().getName()
                            + " still waiting for " + condition + "...");
                }
            } catch (InterruptedException e) {
                Slog.w(TAG, "Interrupt while waiting for " + condition);
            }
            if (timeoutMillis > 0 && SystemClock.elapsedRealtime() > startMillis + timeoutMillis) {
                throw new TimeoutException("Thread " + Thread.currentThread().getName()
                        + " gave up waiting for " + condition + " after " + timeoutMillis + "ms");
            }
        }
    }

    private void handleSystemReady() {
        // Start scheduling nominally-daily fstrim operations
        MountServiceIdler.scheduleIdlePass(mContext);

        // Toggle zram-enable system property in response to settings
        mContext.getContentResolver().registerContentObserver(
            Settings.Global.getUriFor(Settings.Global.ZRAM_ENABLED),
            false /*notifyForDescendants*/,
            new ContentObserver(null /* current thread */) {
                @Override
                public void onChange(boolean selfChange) {
                    refreshZramSettings();
                }
            });
        refreshZramSettings();

        // Schedule zram writeback unless zram is disabled by persist.sys.zram_enabled
        String zramPropValue = SystemProperties.get(ZRAM_ENABLED_PROPERTY);
        if (!zramPropValue.equals("0")
                && mContext.getResources().getBoolean(
                    com.android.internal.R.bool.config_zramWriteback)) {
            ZramWriteback.scheduleZramWriteback(mContext);
        }
        // Toggle isolated-enable system property in response to settings
        mContext.getContentResolver().registerContentObserver(
            Settings.Global.getUriFor(Settings.Global.ISOLATED_STORAGE_REMOTE),
            false /*notifyForDescendants*/,
            new ContentObserver(null /* current thread */) {
                @Override
                public void onChange(boolean selfChange) {
                    refreshIsolatedStorageSettings();
                }
            });
        // For now, simply clone property when it changes
        DeviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_STORAGE_NATIVE_BOOT,
                mContext.getMainExecutor(), (properties) -> {
                    refreshIsolatedStorageSettings();
                    refreshFuseSettings();
                });
        refreshIsolatedStorageSettings();
    }

    /**
     * Update the zram_enabled system property (which init reads to
     * decide whether to enable zram) to reflect the zram_enabled
     * preference (which we can change for experimentation purposes).
     */
    private void refreshZramSettings() {
        String propertyValue = SystemProperties.get(ZRAM_ENABLED_PROPERTY);
        if ("".equals(propertyValue)) {
            return;  // System doesn't have zram toggling support
        }
        String desiredPropertyValue =
            Settings.Global.getInt(mContext.getContentResolver(),
                                   Settings.Global.ZRAM_ENABLED,
                                   1) != 0
            ? "1" : "0";
        if (!desiredPropertyValue.equals(propertyValue)) {
            // Avoid redundant disk writes by setting only if we're
            // changing the property value. There's no race: we're the
            // sole writer.
            SystemProperties.set(ZRAM_ENABLED_PROPERTY, desiredPropertyValue);
            // Schedule writeback only if zram is being enabled.
            if (desiredPropertyValue.equals("1")
                    && mContext.getResources().getBoolean(
                        com.android.internal.R.bool.config_zramWriteback)) {
                ZramWriteback.scheduleZramWriteback(mContext);
            }
        }
    }

    private void refreshIsolatedStorageSettings() {
        // Always copy value from newer DeviceConfig location
        Settings.Global.putString(mResolver,
                Settings.Global.ISOLATED_STORAGE_REMOTE,
                DeviceConfig.getProperty(DeviceConfig.NAMESPACE_STORAGE_NATIVE_BOOT,
                        ISOLATED_STORAGE_ENABLED));

        final int local = Settings.Global.getInt(mContext.getContentResolver(),
                Settings.Global.ISOLATED_STORAGE_LOCAL, 0);
        final int remote = Settings.Global.getInt(mContext.getContentResolver(),
                Settings.Global.ISOLATED_STORAGE_REMOTE, 0);

        // Walk down precedence chain; we prefer local settings first, then
        // remote settings, before finally falling back to hard-coded default.
        final boolean res;
        if (local == -1) {
            res = false;
        } else if (local == 1) {
            res = true;
        } else if (remote == -1) {
            res = false;
        } else if (remote == 1) {
            res = true;
        } else {
            res = true;
        }

        Slog.d(TAG, "Isolated storage local flag " + local + " and remote flag "
                + remote + " resolved to " + res);
        SystemProperties.set(StorageManager.PROP_ISOLATED_STORAGE, Boolean.toString(res));
    }

    /**
     * The most recent flag change takes precedence. Change fuse Settings flag if Device Config is
     * changed. Settings flag change will in turn change fuse system property (persist.sys.fuse)
     * whenever the user reboots.
     */
    private void refreshFuseSettings() {
        int isFuseEnabled = DeviceConfig.getInt(DeviceConfig.NAMESPACE_STORAGE_NATIVE_BOOT,
                FUSE_ENABLED, 0);
        if (isFuseEnabled == 1) {
            Slog.d(TAG, "Device Config flag for FUSE is enabled, turn Settings fuse flag on");
            SystemProperties.set(FeatureFlagUtils.PERSIST_PREFIX
                    + FeatureFlagUtils.SETTINGS_FUSE_FLAG, "true");
        } else if (isFuseEnabled == -1) {
            Slog.d(TAG, "Device Config flag for FUSE is disabled, turn Settings fuse flag off");
            SystemProperties.set(FeatureFlagUtils.PERSIST_PREFIX
                    + FeatureFlagUtils.SETTINGS_FUSE_FLAG, "false");
        }
        // else, keep the build config.
        // This can be overridden by direct adjustment of persist.sys.fflag.override.settings_fuse
    }

    /**
     * MediaProvider has a ton of code that makes assumptions about storage
     * paths never changing, so we outright kill them to pick up new state.
     */
    @Deprecated
    private void killMediaProvider(List<UserInfo> users) {
        if (users == null) return;

        final long token = Binder.clearCallingIdentity();
        try {
            for (UserInfo user : users) {
                // System user does not have media provider, so skip.
                if (user.isSystemOnly()) continue;

                final ProviderInfo provider = mPmInternal.resolveContentProvider(
                        MediaStore.AUTHORITY, PackageManager.MATCH_DIRECT_BOOT_AWARE
                                | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
                        user.id);
                if (provider != null) {
                    final IActivityManager am = ActivityManager.getService();
                    try {
                        am.killApplication(provider.applicationInfo.packageName,
                                UserHandle.getAppId(provider.applicationInfo.uid),
                                UserHandle.USER_ALL, "vold reset");
                        // We only need to run this once. It will kill all users' media processes.
                        break;
                    } catch (RemoteException e) {
                    }
                }
            }
        } finally {
            Binder.restoreCallingIdentity(token);
        }
    }

    @GuardedBy("mLock")
    private void addInternalVolumeLocked() {
        // Create a stub volume that represents internal storage
        final VolumeInfo internal = new VolumeInfo(VolumeInfo.ID_PRIVATE_INTERNAL,
                VolumeInfo.TYPE_PRIVATE, null, null);
        internal.state = VolumeInfo.STATE_MOUNTED;
        internal.path = Environment.getDataDirectory().getAbsolutePath();
        mVolumes.put(internal.id, internal);
    }

    private void initIfBootedAndConnected() {
        Slog.d(TAG, "Thinking about init, mBootCompleted=" + mBootCompleted
                + ", mDaemonConnected=" + mDaemonConnected);
        if (mBootCompleted && mDaemonConnected
                && !StorageManager.isFileEncryptedNativeOnly()) {
            // When booting a device without native support, make sure that our
            // user directories are locked or unlocked based on the current
            // emulation status.
            final boolean initLocked = StorageManager.isFileEncryptedEmulatedOnly();
            Slog.d(TAG, "Setting up emulation state, initlocked=" + initLocked);
            final List<UserInfo> users = mContext.getSystemService(UserManager.class).getUsers();
            for (UserInfo user : users) {
                try {
                    if (initLocked) {
                        mVold.lockUserKey(user.id);
                    } else {
                        mVold.unlockUserKey(user.id, user.serialNumber, encodeBytes(null),
                                encodeBytes(null));
                    }
                } catch (Exception e) {
                    Slog.wtf(TAG, e);
                }
            }
        }
    }

    private void resetIfBootedAndConnected() {
        Slog.d(TAG, "Thinking about reset, mBootCompleted=" + mBootCompleted
                + ", mDaemonConnected=" + mDaemonConnected);
        if (mBootCompleted && mDaemonConnected) {
            final UserManager userManager = mContext.getSystemService(UserManager.class);
            final List<UserInfo> users = userManager.getUsers();

            if (mIsFuseEnabled) {
                mStorageSessionController.onReset(mVold, () -> {
                    mHandler.removeCallbacksAndMessages(null);
                });
            } else {
                killMediaProvider(users);
            }

            final int[] systemUnlockedUsers;
            synchronized (mLock) {
                // make copy as sorting can change order
                systemUnlockedUsers = Arrays.copyOf(mSystemUnlockedUsers,
                        mSystemUnlockedUsers.length);

                mDisks.clear();
                mVolumes.clear();

                addInternalVolumeLocked();
            }

            try {
                // TODO(b/135341433): Remove paranoid logging when FUSE is stable
                Slog.i(TAG, "Resetting vold...");
                mVold.reset();
                Slog.i(TAG, "Reset vold");

                // Tell vold about all existing and started users
                for (UserInfo user : users) {
                    mVold.onUserAdded(user.id, user.serialNumber);
                }
                for (int userId : systemUnlockedUsers) {
                    mVold.onUserStarted(userId);
                    mStoraged.onUserStarted(userId);
                }
                if (mIsAutomotive) {
                    restoreAllUnlockedUsers(userManager, users, systemUnlockedUsers);
                }
                mVold.onSecureKeyguardStateChanged(mSecureKeyguardShowing);
                mStorageManagerInternal.onReset(mVold);
            } catch (Exception e) {
                Slog.wtf(TAG, e);
            }
        }
    }

    private void restoreAllUnlockedUsers(UserManager userManager, List<UserInfo> allUsers,
            int[] systemUnlockedUsers) throws Exception {
        Arrays.sort(systemUnlockedUsers);
        UserManager.invalidateIsUserUnlockedCache();
        for (UserInfo user : allUsers) {
            int userId = user.id;
            if (!userManager.isUserRunning(userId)) {
                continue;
            }
            if (Arrays.binarySearch(systemUnlockedUsers, userId) >= 0) {
                continue;
            }
            boolean unlockingOrUnlocked = userManager.isUserUnlockingOrUnlocked(userId);
            if (!unlockingOrUnlocked) {
                continue;
            }
            Slog.w(TAG, "UNLOCK_USER lost from vold reset, will retry, user:" + userId);
            mVold.onUserStarted(userId);
            mStoraged.onUserStarted(userId);
            mHandler.obtainMessage(H_COMPLETE_UNLOCK_USER, userId).sendToTarget();
        }
    }

    private void onUnlockUser(int userId) {
        Slog.d(TAG, "onUnlockUser " + userId);

        // We purposefully block here to make sure that user-specific
        // staging area is ready so it's ready for zygote-forked apps to
        // bind mount against.
        try {
            mStorageSessionController.onUnlockUser(userId);
            mVold.onUserStarted(userId);
            mStoraged.onUserStarted(userId);
        } catch (Exception e) {
            Slog.wtf(TAG, e);
        }

        mHandler.obtainMessage(H_COMPLETE_UNLOCK_USER, userId).sendToTarget();
    }

    private void completeUnlockUser(int userId) {
        // If user 0 has completed unlock, perform a one-time migration of legacy obb data
        // to its new location. This may take time depending on the size of the data to be copied
        // so it's done on the StorageManager handler thread.
        if (userId == 0) {
            mPmInternal.migrateLegacyObbData();
        }

        onKeyguardStateChanged(false);

        // Record user as started so newly mounted volumes kick off events
        // correctly, then synthesize events for any already-mounted volumes.
        synchronized (mLock) {
            if (mIsAutomotive) {
                for (int unlockedUser : mSystemUnlockedUsers) {
                    if (unlockedUser == userId) {
                        // This can happen as restoreAllUnlockedUsers can double post the message.
                        Log.i(TAG, "completeUnlockUser called for already unlocked user:" + userId);
                        return;
                    }
                }
            }
            for (int i = 0; i < mVolumes.size(); i++) {
                final VolumeInfo vol = mVolumes.valueAt(i);
                if (vol.isVisibleForRead(userId) && vol.isMountedReadable()) {
                    final StorageVolume userVol = vol.buildStorageVolume(mContext, userId, false);
                    mHandler.obtainMessage(H_VOLUME_BROADCAST, userVol).sendToTarget();

                    final String envState = VolumeInfo.getEnvironmentForState(vol.getState());
                    mCallbacks.notifyStorageStateChanged(userVol.getPath(), envState, envState);
                }
            }
            mSystemUnlockedUsers = ArrayUtils.appendInt(mSystemUnlockedUsers, userId);
        }
    }

    private void onCleanupUser(int userId) {
        Slog.d(TAG, "onCleanupUser " + userId);

        try {
            mVold.onUserStopped(userId);
            mStoraged.onUserStopped(userId);
        } catch (Exception e) {
            Slog.wtf(TAG, e);
        }

        synchronized (mLock) {
            mSystemUnlockedUsers = ArrayUtils.removeInt(mSystemUnlockedUsers, userId);
        }
    }

    private void onStopUser(int userId) {
        Slog.i(TAG, "onStopUser " + userId);
        try {
            mStorageSessionController.onUserStopping(userId);
        } catch (Exception e) {
            Slog.wtf(TAG, e);
        }
        PackageMonitor monitor = mPackageMonitorsForUser.remove(userId);
        if (monitor != null) {
            monitor.unregister();
        }
    }

    private boolean supportsBlockCheckpoint() throws RemoteException {
        enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);
        return mVold.supportsBlockCheckpoint();
    }

    @Override
    public void onAwakeStateChanged(boolean isAwake) {
        // Ignored
    }

    @Override
    public void onKeyguardStateChanged(boolean isShowing) {
        // Push down current secure keyguard status so that we ignore malicious
        // USB devices while locked.
        mSecureKeyguardShowing = isShowing
                && mContext.getSystemService(KeyguardManager.class).isDeviceSecure(mCurrentUserId);
        try {
            mVold.onSecureKeyguardStateChanged(mSecureKeyguardShowing);
        } catch (Exception e) {
            Slog.wtf(TAG, e);
        }
    }

    void runIdleMaintenance(Runnable callback) {
        mHandler.sendMessage(mHandler.obtainMessage(H_FSTRIM, callback));
    }

    // Binder entry point for kicking off an immediate fstrim
    @Override
    public void runMaintenance() {
        enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
        runIdleMaintenance(null);
    }

    @Override
    public long lastMaintenance() {
        return mLastMaintenance;
    }

    public void onDaemonConnected() {
        mDaemonConnected = true;
        mHandler.obtainMessage(H_DAEMON_CONNECTED).sendToTarget();
    }

    private void handleDaemonConnected() {
        initIfBootedAndConnected();
        resetIfBootedAndConnected();

        // On an encrypted device we can't see system properties yet, so pull
        // the system locale out of the mount service.
        if ("".equals(VoldProperties.encrypt_progress().orElse(""))) {
            copyLocaleFromMountService();
        }
    }

    private void copyLocaleFromMountService() {
        String systemLocale;
        try {
            systemLocale = getField(StorageManager.SYSTEM_LOCALE_KEY);
        } catch (RemoteException e) {
            return;
        }
        if (TextUtils.isEmpty(systemLocale)) {
            return;
        }

        Slog.d(TAG, "Got locale " + systemLocale + " from mount service");
        Locale locale = Locale.forLanguageTag(systemLocale);
        Configuration config = new Configuration();
        config.setLocale(locale);
        try {
            ActivityManager.getService().updatePersistentConfiguration(config);
        } catch (RemoteException e) {
            Slog.e(TAG, "Error setting system locale from mount service", e);
        }

        // Temporary workaround for http://b/17945169.
        Slog.d(TAG, "Setting system properties to " + systemLocale + " from mount service");
        SystemProperties.set("persist.sys.locale", locale.toLanguageTag());
    }

    private final IVoldListener mListener = new IVoldListener.Stub() {
        @Override
        public void onDiskCreated(String diskId, int flags) {
            synchronized (mLock) {
                final String value = SystemProperties.get(StorageManager.PROP_ADOPTABLE);
                switch (value) {
                    case "force_on":
                        flags |= DiskInfo.FLAG_ADOPTABLE;
                        break;
                    case "force_off":
                        flags &= ~DiskInfo.FLAG_ADOPTABLE;
                        break;
                }
                mDisks.put(diskId, new DiskInfo(diskId, flags));
            }
        }

        @Override
        public void onDiskScanned(String diskId) {
            synchronized (mLock) {
                final DiskInfo disk = mDisks.get(diskId);
                if (disk != null) {
                    onDiskScannedLocked(disk);
                }
            }
        }

        @Override
        public void onDiskMetadataChanged(String diskId, long sizeBytes, String label,
                String sysPath) {
            synchronized (mLock) {
                final DiskInfo disk = mDisks.get(diskId);
                if (disk != null) {
                    disk.size = sizeBytes;
                    disk.label = label;
                    disk.sysPath = sysPath;
                }
            }
        }

        @Override
        public void onDiskDestroyed(String diskId) {
            synchronized (mLock) {
                final DiskInfo disk = mDisks.remove(diskId);
                if (disk != null) {
                    mCallbacks.notifyDiskDestroyed(disk);
                }
            }
        }

        @Override
        public void onVolumeCreated(String volId, int type, String diskId, String partGuid,
                int userId) {
            synchronized (mLock) {
                final DiskInfo disk = mDisks.get(diskId);
                final VolumeInfo vol = new VolumeInfo(volId, type, disk, partGuid);
                vol.mountUserId = userId;
                mVolumes.put(volId, vol);
                onVolumeCreatedLocked(vol);
            }
        }

        @Override
        public void onVolumeStateChanged(String volId, int state) {
            synchronized (mLock) {
                final VolumeInfo vol = mVolumes.get(volId);
                if (vol != null) {
                    final int oldState = vol.state;
                    final int newState = state;
                    vol.state = newState;
                    final SomeArgs args = SomeArgs.obtain();
                    args.arg1 = vol;
                    args.arg2 = oldState;
                    args.arg3 = newState;
                    mHandler.obtainMessage(H_VOLUME_STATE_CHANGED, args).sendToTarget();
                    onVolumeStateChangedLocked(vol, oldState, newState);
                }
            }
        }

        @Override
        public void onVolumeMetadataChanged(String volId, String fsType, String fsUuid,
                String fsLabel) {
            synchronized (mLock) {
                final VolumeInfo vol = mVolumes.get(volId);
                if (vol != null) {
                    vol.fsType = fsType;
                    vol.fsUuid = fsUuid;
                    vol.fsLabel = fsLabel;
                }
            }
        }

        @Override
        public void onVolumePathChanged(String volId, String path) {
            synchronized (mLock) {
                final VolumeInfo vol = mVolumes.get(volId);
                if (vol != null) {
                    vol.path = path;
                }
            }
        }

        @Override
        public void onVolumeInternalPathChanged(String volId, String internalPath) {
            synchronized (mLock) {
                final VolumeInfo vol = mVolumes.get(volId);
                if (vol != null) {
                    vol.internalPath = internalPath;
                }
            }
        }

        @Override
        public void onVolumeDestroyed(String volId) {
            VolumeInfo vol = null;
            synchronized (mLock) {
                vol = mVolumes.remove(volId);
            }

            if (vol != null) {
                mStorageSessionController.onVolumeRemove(vol);
                try {
                    if (vol.type == VolumeInfo.TYPE_PRIVATE) {
                        mInstaller.onPrivateVolumeRemoved(vol.getFsUuid());
                    }
                } catch (Installer.InstallerException e) {
                    Slog.i(TAG, "Failed when private volume unmounted " + vol, e);
                }
            }
        }
    };

    @GuardedBy("mLock")
    private void onDiskScannedLocked(DiskInfo disk) {
        int volumeCount = 0;
        for (int i = 0; i < mVolumes.size(); i++) {
            final VolumeInfo vol = mVolumes.valueAt(i);
            if (Objects.equals(disk.id, vol.getDiskId())) {
                volumeCount++;
            }
        }

        final Intent intent = new Intent(DiskInfo.ACTION_DISK_SCANNED);
        intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT
                | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
        intent.putExtra(DiskInfo.EXTRA_DISK_ID, disk.id);
        intent.putExtra(DiskInfo.EXTRA_VOLUME_COUNT, volumeCount);
        mHandler.obtainMessage(H_INTERNAL_BROADCAST, intent).sendToTarget();

        final CountDownLatch latch = mDiskScanLatches.remove(disk.id);
        if (latch != null) {
            latch.countDown();
        }

        disk.volumeCount = volumeCount;
        mCallbacks.notifyDiskScanned(disk, volumeCount);
    }

    @GuardedBy("mLock")
    private void onVolumeCreatedLocked(VolumeInfo vol) {
        if (mPmInternal.isOnlyCoreApps()) {
            Slog.d(TAG, "System booted in core-only mode; ignoring volume " + vol.getId());
            return;
        }
        final ActivityManagerInternal amInternal =
                LocalServices.getService(ActivityManagerInternal.class);

        if (mIsFuseEnabled && vol.mountUserId >= 0
                && !amInternal.isUserRunning(vol.mountUserId, 0)) {
            Slog.d(TAG, "Ignoring volume " + vol.getId() + " because user "
                    + Integer.toString(vol.mountUserId) + " is no longer running.");
            return;
        }

        if (vol.type == VolumeInfo.TYPE_EMULATED) {
            final StorageManager storage = mContext.getSystemService(StorageManager.class);
            final VolumeInfo privateVol = storage.findPrivateForEmulated(vol);

            if (Objects.equals(StorageManager.UUID_PRIVATE_INTERNAL, mPrimaryStorageUuid)
                    && VolumeInfo.ID_PRIVATE_INTERNAL.equals(privateVol.id)) {
                Slog.v(TAG, "Found primary storage at " + vol);
                vol.mountFlags |= VolumeInfo.MOUNT_FLAG_PRIMARY;
                vol.mountFlags |= VolumeInfo.MOUNT_FLAG_VISIBLE;
                mHandler.obtainMessage(H_VOLUME_MOUNT, vol).sendToTarget();

            } else if (Objects.equals(privateVol.fsUuid, mPrimaryStorageUuid)) {
                Slog.v(TAG, "Found primary storage at " + vol);
                vol.mountFlags |= VolumeInfo.MOUNT_FLAG_PRIMARY;
                vol.mountFlags |= VolumeInfo.MOUNT_FLAG_VISIBLE;
                mHandler.obtainMessage(H_VOLUME_MOUNT, vol).sendToTarget();
            }

        } else if (vol.type == VolumeInfo.TYPE_PUBLIC) {
            // TODO: only look at first public partition
            if (Objects.equals(StorageManager.UUID_PRIMARY_PHYSICAL, mPrimaryStorageUuid)
                    && vol.disk.isDefaultPrimary()) {
                Slog.v(TAG, "Found primary storage at " + vol);
                vol.mountFlags |= VolumeInfo.MOUNT_FLAG_PRIMARY;
                vol.mountFlags |= VolumeInfo.MOUNT_FLAG_VISIBLE;
            }

            // Adoptable public disks are visible to apps, since they meet
            // public API requirement of being in a stable location.
            if (vol.disk.isAdoptable()) {
                vol.mountFlags |= VolumeInfo.MOUNT_FLAG_VISIBLE;
            }

            vol.mountUserId = mCurrentUserId;
            mHandler.obtainMessage(H_VOLUME_MOUNT, vol).sendToTarget();

        } else if (vol.type == VolumeInfo.TYPE_PRIVATE) {
            mHandler.obtainMessage(H_VOLUME_MOUNT, vol).sendToTarget();

        } else if (vol.type == VolumeInfo.TYPE_STUB) {
            vol.mountUserId = mCurrentUserId;
            mHandler.obtainMessage(H_VOLUME_MOUNT, vol).sendToTarget();
        } else {
            Slog.d(TAG, "Skipping automatic mounting of " + vol);
        }
    }

    private boolean isBroadcastWorthy(VolumeInfo vol) {
        switch (vol.getType()) {
            case VolumeInfo.TYPE_PRIVATE:
            case VolumeInfo.TYPE_PUBLIC:
            case VolumeInfo.TYPE_EMULATED:
            case VolumeInfo.TYPE_STUB:
                break;
            default:
                return false;
        }

        switch (vol.getState()) {
            case VolumeInfo.STATE_MOUNTED:
            case VolumeInfo.STATE_MOUNTED_READ_ONLY:
            case VolumeInfo.STATE_EJECTING:
            case VolumeInfo.STATE_UNMOUNTED:
            case VolumeInfo.STATE_UNMOUNTABLE:
            case VolumeInfo.STATE_BAD_REMOVAL:
                break;
            default:
                return false;
        }

        return true;
    }


    private void onVolumeStateChangedLocked(VolumeInfo vol, int oldState, int newState) {
        if (vol.type == VolumeInfo.TYPE_EMULATED) {
            if (newState != VolumeInfo.STATE_MOUNTED) {
                mFuseMountedUser.remove(vol.getMountUserId());
            } else if (mVoldAppDataIsolationEnabled){
                final int userId = vol.getMountUserId();
                mFuseMountedUser.add(userId);
                // Async remount app storage so it won't block the main thread.
                new Thread(() -> {
                    Map<Integer, String> pidPkgMap = null;
                    // getProcessesWithPendingBindMounts() could fail when a new app process is
                    // starting and it's not planning to mount storage dirs in zygote, but it's
                    // rare, so we retry 5 times and hope we can get the result successfully.
                    for (int i = 0; i < 5; i++) {
                        try {
                            pidPkgMap = LocalServices.getService(ActivityManagerInternal.class)
                                    .getProcessesWithPendingBindMounts(vol.getMountUserId());
                            break;
                        } catch (IllegalStateException e) {
                            Slog.i(TAG, "Some processes are starting, retry");
                            // Wait 100ms and retry so hope the pending process is started.
                            SystemClock.sleep(100);
                        }
                    }
                    if (pidPkgMap != null) {
                        remountAppStorageDirs(pidPkgMap, userId);
                    } else {
                        Slog.wtf(TAG, "Not able to getStorageNotOptimizedProcesses() after"
                                + " 5 retries");
                    }
                }).start();
            }
        }
    }


    private void onVolumeStateChangedAsync(VolumeInfo vol, int oldState, int newState) {
        synchronized (mLock) {
            // Remember that we saw this volume so we're ready to accept user
            // metadata, or so we can annoy them when a private volume is ejected
            if (!TextUtils.isEmpty(vol.fsUuid)) {
                VolumeRecord rec = mRecords.get(vol.fsUuid);
                if (rec == null) {
                    rec = new VolumeRecord(vol.type, vol.fsUuid);
                    rec.partGuid = vol.partGuid;
                    rec.createdMillis = System.currentTimeMillis();
                    if (vol.type == VolumeInfo.TYPE_PRIVATE) {
                        rec.nickname = vol.disk.getDescription();
                    }
                    mRecords.put(rec.fsUuid, rec);
                } else {
                    // Handle upgrade case where we didn't store partition GUID
                    if (TextUtils.isEmpty(rec.partGuid)) {
                        rec.partGuid = vol.partGuid;
                    }
                }

                rec.lastSeenMillis = System.currentTimeMillis();
                writeSettingsLocked();
            }
        }

        if (newState == VolumeInfo.STATE_MOUNTED) {
            // Private volumes can be unmounted and re-mounted even after a user has
            // been unlocked; on devices that support encryption keys tied to the filesystem,
            // this requires setting up the keys again.
            prepareUserStorageIfNeeded(vol);
        }

        // This is a blocking call to Storage Service which needs to process volume state changed
        // before notifying other listeners.
        // Intentionally called without the mLock to avoid deadlocking from the Storage Service.
        try {
            mStorageSessionController.notifyVolumeStateChanged(vol);
        } catch (ExternalStorageServiceException e) {
            Log.e(TAG, "Failed to notify volume state changed to the Storage Service", e);
        }
        synchronized (mLock) {
            mCallbacks.notifyVolumeStateChanged(vol, oldState, newState);

            // Do not broadcast before boot has completed to avoid launching the
            // processes that receive the intent unnecessarily.
            if (mBootCompleted && isBroadcastWorthy(vol)) {
                final Intent intent = new Intent(VolumeInfo.ACTION_VOLUME_STATE_CHANGED);
                intent.putExtra(VolumeInfo.EXTRA_VOLUME_ID, vol.id);
                intent.putExtra(VolumeInfo.EXTRA_VOLUME_STATE, newState);
                intent.putExtra(VolumeRecord.EXTRA_FS_UUID, vol.fsUuid);
                intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT
                        | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
                mHandler.obtainMessage(H_INTERNAL_BROADCAST, intent).sendToTarget();
            }

            final String oldStateEnv = VolumeInfo.getEnvironmentForState(oldState);
            final String newStateEnv = VolumeInfo.getEnvironmentForState(newState);

            if (!Objects.equals(oldStateEnv, newStateEnv)) {
                // Kick state changed event towards all started users. Any users
                // started after this point will trigger additional
                // user-specific broadcasts.
                for (int userId : mSystemUnlockedUsers) {
                    if (vol.isVisibleForRead(userId)) {
                        final StorageVolume userVol = vol.buildStorageVolume(mContext, userId,
                                false);
                        mHandler.obtainMessage(H_VOLUME_BROADCAST, userVol).sendToTarget();

                        mCallbacks.notifyStorageStateChanged(userVol.getPath(), oldStateEnv,
                                newStateEnv);
                    }
                }
            }

            if ((vol.type == VolumeInfo.TYPE_PUBLIC || vol.type == VolumeInfo.TYPE_STUB)
                    && vol.state == VolumeInfo.STATE_EJECTING) {
                // TODO: this should eventually be handled by new ObbVolume state changes
                /*
                 * Some OBBs might have been unmounted when this volume was
                 * unmounted, so send a message to the handler to let it know to
                 * remove those from the list of mounted OBBS.
                 */
                mObbActionHandler.sendMessage(mObbActionHandler.obtainMessage(
                        OBB_FLUSH_MOUNT_STATE, vol.path));
            }
            maybeLogMediaMount(vol, newState);
        }
    }

    private void maybeLogMediaMount(VolumeInfo vol, int newState) {
        if (!SecurityLog.isLoggingEnabled()) {
            return;
        }

        final DiskInfo disk = vol.getDisk();
        if (disk == null || (disk.flags & (DiskInfo.FLAG_SD | DiskInfo.FLAG_USB)) == 0) {
            return;
        }

        // Sometimes there is a newline character.
        final String label = disk.label != null ? disk.label.trim() : "";

        if (newState == VolumeInfo.STATE_MOUNTED
                || newState == VolumeInfo.STATE_MOUNTED_READ_ONLY) {
            SecurityLog.writeEvent(SecurityLog.TAG_MEDIA_MOUNT, vol.path, label);
        } else if (newState == VolumeInfo.STATE_UNMOUNTED
                || newState == VolumeInfo.STATE_BAD_REMOVAL) {
            SecurityLog.writeEvent(SecurityLog.TAG_MEDIA_UNMOUNT, vol.path, label);
        }
    }

    @GuardedBy("mLock")
    private void onMoveStatusLocked(int status) {
        if (mMoveCallback == null) {
            Slog.w(TAG, "Odd, status but no move requested");
            return;
        }

        // TODO: estimate remaining time
        try {
            mMoveCallback.onStatusChanged(-1, status, -1);
        } catch (RemoteException ignored) {
        }

        // We've finished copying and we're about to clean up old data, so
        // remember that move was successful if we get rebooted
        if (status == MOVE_STATUS_COPY_FINISHED) {
            Slog.d(TAG, "Move to " + mMoveTargetUuid + " copy phase finshed; persisting");

            mPrimaryStorageUuid = mMoveTargetUuid;
            writeSettingsLocked();
        }

        if (PackageManager.isMoveStatusFinished(status)) {
            Slog.d(TAG, "Move to " + mMoveTargetUuid + " finished with status " + status);

            mMoveCallback = null;
            mMoveTargetUuid = null;
        }
    }

    private void enforcePermission(String perm) {
        mContext.enforceCallingOrSelfPermission(perm, perm);
    }

    /**
     * Decide if volume is mountable per device policies.
     */
    private boolean isMountDisallowed(VolumeInfo vol) {
        UserManager userManager = mContext.getSystemService(UserManager.class);

        boolean isUsbRestricted = false;
        if (vol.disk != null && vol.disk.isUsb()) {
            isUsbRestricted = userManager.hasUserRestriction(UserManager.DISALLOW_USB_FILE_TRANSFER,
                    Binder.getCallingUserHandle());
        }

        boolean isTypeRestricted = false;
        if (vol.type == VolumeInfo.TYPE_PUBLIC || vol.type == VolumeInfo.TYPE_PRIVATE
                || vol.type == VolumeInfo.TYPE_STUB) {
            isTypeRestricted = userManager
                    .hasUserRestriction(UserManager.DISALLOW_MOUNT_PHYSICAL_MEDIA,
                    Binder.getCallingUserHandle());
        }

        return isUsbRestricted || isTypeRestricted;
    }

    private void enforceAdminUser() {
        UserManager um = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
        final int callingUserId = UserHandle.getCallingUserId();
        boolean isAdmin;
        long token = Binder.clearCallingIdentity();
        try {
            isAdmin = um.getUserInfo(callingUserId).isAdmin();
        } finally {
            Binder.restoreCallingIdentity(token);
        }
        if (!isAdmin) {
            throw new SecurityException("Only admin users can adopt sd cards");
        }
    }

    /**
     * Constructs a new StorageManagerService instance
     *
     * @param context  Binder context for this service
     */
    public StorageManagerService(Context context) {
        sSelf = this;

        // Snapshot feature flag used for this boot
        SystemProperties.set(StorageManager.PROP_ISOLATED_STORAGE_SNAPSHOT, Boolean.toString(
                SystemProperties.getBoolean(StorageManager.PROP_ISOLATED_STORAGE, true)));

        // If there is no value in the property yet (first boot after data wipe), this value may be
        // incorrect until #updateFusePropFromSettings where we set the correct value and reboot if
        // different
        mIsFuseEnabled = SystemProperties.getBoolean(PROP_FUSE, DEFAULT_FUSE_ENABLED);
        mVoldAppDataIsolationEnabled = mIsFuseEnabled && SystemProperties.getBoolean(
                ANDROID_VOLD_APP_DATA_ISOLATION_ENABLED_PROPERTY, false);
        mContext = context;
        mResolver = mContext.getContentResolver();
        mCallbacks = new Callbacks(FgThread.get().getLooper());
        mLockPatternUtils = new LockPatternUtils(mContext);

        HandlerThread hthread = new HandlerThread(TAG);
        hthread.start();
        mHandler = new StorageManagerServiceHandler(hthread.getLooper());

        // Add OBB Action Handler to StorageManagerService thread.
        mObbActionHandler = new ObbActionHandler(IoThread.get().getLooper());

        mStorageSessionController = new StorageSessionController(mContext, mIsFuseEnabled);

        mInstaller = new Installer(mContext);
        mInstaller.onStart();

        // Initialize the last-fstrim tracking if necessary
        File dataDir = Environment.getDataDirectory();
        File systemDir = new File(dataDir, "system");
        mLastMaintenanceFile = new File(systemDir, LAST_FSTRIM_FILE);
        if (!mLastMaintenanceFile.exists()) {
            // Not setting mLastMaintenance here means that we will force an
            // fstrim during reboot following the OTA that installs this code.
            try {
                (new FileOutputStream(mLastMaintenanceFile)).close();
            } catch (IOException e) {
                Slog.e(TAG, "Unable to create fstrim record " + mLastMaintenanceFile.getPath());
            }
        } else {
            mLastMaintenance = mLastMaintenanceFile.lastModified();
        }

        mSettingsFile = new AtomicFile(
                new File(Environment.getDataSystemDirectory(), "storage.xml"), "storage-settings");

        synchronized (mLock) {
            readSettingsLocked();
        }

        LocalServices.addService(StorageManagerInternal.class, mStorageManagerInternal);

        final IntentFilter userFilter = new IntentFilter();
        userFilter.addAction(Intent.ACTION_USER_ADDED);
        userFilter.addAction(Intent.ACTION_USER_REMOVED);
        mContext.registerReceiver(mUserReceiver, userFilter, null, mHandler);

        synchronized (mLock) {
            addInternalVolumeLocked();
        }

        // Add ourself to the Watchdog monitors if enabled.
        if (WATCHDOG_ENABLE) {
            Watchdog.getInstance().addMonitor(this);
        }

        mIsAutomotive = context.getPackageManager().hasSystemFeature(
                PackageManager.FEATURE_AUTOMOTIVE);
    }

    /**
     *  Checks if user changed the persistent settings_fuse flag from Settings UI
     *  and updates PROP_FUSE (reboots if changed).
     */
    private void updateFusePropFromSettings() {
        boolean settingsFuseFlag = SystemProperties.getBoolean(PROP_SETTINGS_FUSE,
                DEFAULT_FUSE_ENABLED);
        Slog.d(TAG, "FUSE flags. Settings: " + settingsFuseFlag
                + ". Default: " + DEFAULT_FUSE_ENABLED);

        if (mIsFuseEnabled != settingsFuseFlag) {
            Slog.i(TAG, "Toggling persist.sys.fuse to " + settingsFuseFlag);
            // Set prop_fuse to match prop_settings_fuse because it is used by native daemons like
            // init, zygote, installd and vold
            SystemProperties.set(PROP_FUSE, Boolean.toString(settingsFuseFlag));
            // Then perform hard reboot to kick policy into place
            mContext.getSystemService(PowerManager.class).reboot("fuse_prop");
        }
    }

    private void start() {
        connectStoraged();
        connectVold();
    }

    private void connectStoraged() {
        IBinder binder = ServiceManager.getService("storaged");
        if (binder != null) {
            try {
                binder.linkToDeath(new DeathRecipient() {
                    @Override
                    public void binderDied() {
                        Slog.w(TAG, "storaged died; reconnecting");
                        mStoraged = null;
                        connectStoraged();
                    }
                }, 0);
            } catch (RemoteException e) {
                binder = null;
            }
        }

        if (binder != null) {
            mStoraged = IStoraged.Stub.asInterface(binder);
        } else {
            Slog.w(TAG, "storaged not found; trying again");
        }

        if (mStoraged == null) {
            BackgroundThread.getHandler().postDelayed(() -> {
                connectStoraged();
            }, DateUtils.SECOND_IN_MILLIS);
        } else {
            onDaemonConnected();
        }
    }

    private void connectVold() {
        IBinder binder = ServiceManager.getService("vold");
        if (binder != null) {
            try {
                binder.linkToDeath(new DeathRecipient() {
                    @Override
                    public void binderDied() {
                        Slog.w(TAG, "vold died; reconnecting");
                        mVold = null;
                        connectVold();
                    }
                }, 0);
            } catch (RemoteException e) {
                binder = null;
            }
        }

        if (binder != null) {
            mVold = IVold.Stub.asInterface(binder);
            try {
                mVold.setListener(mListener);
            } catch (RemoteException e) {
                mVold = null;
                Slog.w(TAG, "vold listener rejected; trying again", e);
            }
        } else {
            Slog.w(TAG, "vold not found; trying again");
        }

        if (mVold == null) {
            BackgroundThread.getHandler().postDelayed(() -> {
                connectVold();
            }, DateUtils.SECOND_IN_MILLIS);
        } else {
            onDaemonConnected();
        }
    }

    private void servicesReady() {
        mPmInternal = LocalServices.getService(PackageManagerInternal.class);

        mIPackageManager = IPackageManager.Stub.asInterface(
                ServiceManager.getService("package"));
        mIAppOpsService = IAppOpsService.Stub.asInterface(
                ServiceManager.getService(Context.APP_OPS_SERVICE));

        ProviderInfo provider = getProviderInfo(MediaStore.AUTHORITY);
        if (provider != null) {
            mMediaStoreAuthorityAppId = UserHandle.getAppId(provider.applicationInfo.uid);
            sMediaStoreAuthorityProcessName = provider.applicationInfo.processName;
        }

        provider = getProviderInfo(Downloads.Impl.AUTHORITY);
        if (provider != null) {
            mDownloadsAuthorityAppId = UserHandle.getAppId(provider.applicationInfo.uid);
        }

        provider = getProviderInfo(DocumentsContract.EXTERNAL_STORAGE_PROVIDER_AUTHORITY);
        if (provider != null) {
            mExternalStorageAuthorityAppId = UserHandle.getAppId(provider.applicationInfo.uid);
        }

        if (!mIsFuseEnabled) {
            try {
                mIAppOpsService.startWatchingMode(OP_REQUEST_INSTALL_PACKAGES, null,
                        mAppOpsCallback);
                mIAppOpsService.startWatchingMode(OP_LEGACY_STORAGE, null, mAppOpsCallback);
            } catch (RemoteException e) {
            }
        }
    }

    private ProviderInfo getProviderInfo(String authority) {
        return mPmInternal.resolveContentProvider(
                authority, PackageManager.MATCH_DIRECT_BOOT_AWARE
                        | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
                UserHandle.getUserId(UserHandle.USER_SYSTEM));
    }

    private void updateLegacyStorageApps(String packageName, int uid, boolean hasLegacy) {
        synchronized (mLock) {
            if (hasLegacy) {
                Slog.v(TAG, "Package " + packageName + " has legacy storage");
                mUidsWithLegacyExternalStorage.add(uid);
            } else {
                // TODO(b/149391976): Handle shared user id. Check if there's any other
                // installed app with legacy external storage before removing
                Slog.v(TAG, "Package " + packageName + " does not have legacy storage");
                mUidsWithLegacyExternalStorage.remove(uid);
            }
        }
    }

    private void snapshotAndMonitorLegacyStorageAppOp(UserHandle user) {
        int userId = user.getIdentifier();

        // TODO(b/149391976): Use mIAppOpsService.getPackagesForOps instead of iterating below
        // It should improve performance but the AppOps method doesn't return any app here :(
        // This operation currently takes about ~20ms on a freshly flashed device
        for (ApplicationInfo ai : mPmInternal.getInstalledApplications(MATCH_DIRECT_BOOT_AWARE
                        | MATCH_DIRECT_BOOT_UNAWARE | MATCH_UNINSTALLED_PACKAGES | MATCH_ANY_USER,
                        userId, Process.myUid())) {
            try {
                boolean hasLegacy = mIAppOpsService.checkOperation(OP_LEGACY_STORAGE, ai.uid,
                        ai.packageName) == MODE_ALLOWED;
                updateLegacyStorageApps(ai.packageName, ai.uid, hasLegacy);
            } catch (RemoteException e) {
                Slog.e(TAG, "Failed to check legacy op for package " + ai.packageName, e);
            }
        }

        PackageMonitor monitor = new PackageMonitor() {
                @Override
                public void onPackageRemoved(String packageName, int uid) {
                    updateLegacyStorageApps(packageName, uid, false);
                }
            };
        // TODO(b/149391976): Use different handler?
        monitor.register(mContext, user, true, mHandler);
        mPackageMonitorsForUser.put(userId, monitor);
    }

    private static long getLastAccessTime(AppOpsManager manager,
            int uid, String packageName, int[] ops) {
        long maxTime = 0;
        final List<AppOpsManager.PackageOps> pkgs = manager.getOpsForPackage(uid, packageName, ops);
        for (AppOpsManager.PackageOps pkg : CollectionUtils.emptyIfNull(pkgs)) {
            for (AppOpsManager.OpEntry op : CollectionUtils.emptyIfNull(pkg.getOps())) {
                maxTime = Math.max(maxTime, op.getLastAccessTime(
                    AppOpsManager.OP_FLAGS_ALL_TRUSTED));
            }
        }
        return maxTime;
    }

    private void systemReady() {
        LocalServices.getService(ActivityTaskManagerInternal.class)
                .registerScreenObserver(this);

        mHandler.obtainMessage(H_SYSTEM_READY).sendToTarget();
    }

    private void bootCompleted() {
        mBootCompleted = true;
        mHandler.obtainMessage(H_BOOT_COMPLETED).sendToTarget();
        updateFusePropFromSettings();
    }

    private void handleBootCompleted() {
        initIfBootedAndConnected();
        resetIfBootedAndConnected();
    }

    private String getDefaultPrimaryStorageUuid() {
        if (SystemProperties.getBoolean(StorageManager.PROP_PRIMARY_PHYSICAL, false)) {
            return StorageManager.UUID_PRIMARY_PHYSICAL;
        } else {
            return StorageManager.UUID_PRIVATE_INTERNAL;
        }
    }

    @GuardedBy("mLock")
    private void readSettingsLocked() {
        mRecords.clear();
        mPrimaryStorageUuid = getDefaultPrimaryStorageUuid();

        FileInputStream fis = null;
        try {
            fis = mSettingsFile.openRead();
            final XmlPullParser in = Xml.newPullParser();
            in.setInput(fis, StandardCharsets.UTF_8.name());

            int type;
            while ((type = in.next()) != END_DOCUMENT) {
                if (type == START_TAG) {
                    final String tag = in.getName();
                    if (TAG_VOLUMES.equals(tag)) {
                        final int version = readIntAttribute(in, ATTR_VERSION, VERSION_INIT);
                        final boolean primaryPhysical = SystemProperties.getBoolean(
                                StorageManager.PROP_PRIMARY_PHYSICAL, false);
                        final boolean validAttr = (version >= VERSION_FIX_PRIMARY)
                                || (version >= VERSION_ADD_PRIMARY && !primaryPhysical);
                        if (validAttr) {
                            mPrimaryStorageUuid = readStringAttribute(in,
                                    ATTR_PRIMARY_STORAGE_UUID);
                        }
                    } else if (TAG_VOLUME.equals(tag)) {
                        final VolumeRecord rec = readVolumeRecord(in);
                        mRecords.put(rec.fsUuid, rec);
                    }
                }
            }
        } catch (FileNotFoundException e) {
            // Missing metadata is okay, probably first boot
        } catch (IOException e) {
            Slog.wtf(TAG, "Failed reading metadata", e);
        } catch (XmlPullParserException e) {
            Slog.wtf(TAG, "Failed reading metadata", e);
        } finally {
            IoUtils.closeQuietly(fis);
        }
    }

    @GuardedBy("mLock")
    private void writeSettingsLocked() {
        FileOutputStream fos = null;
        try {
            fos = mSettingsFile.startWrite();

            XmlSerializer out = new FastXmlSerializer();
            out.setOutput(fos, StandardCharsets.UTF_8.name());
            out.startDocument(null, true);
            out.startTag(null, TAG_VOLUMES);
            writeIntAttribute(out, ATTR_VERSION, VERSION_FIX_PRIMARY);
            writeStringAttribute(out, ATTR_PRIMARY_STORAGE_UUID, mPrimaryStorageUuid);
            final int size = mRecords.size();
            for (int i = 0; i < size; i++) {
                final VolumeRecord rec = mRecords.valueAt(i);
                writeVolumeRecord(out, rec);
            }
            out.endTag(null, TAG_VOLUMES);
            out.endDocument();

            mSettingsFile.finishWrite(fos);
        } catch (IOException e) {
            if (fos != null) {
                mSettingsFile.failWrite(fos);
            }
        }
    }

    public static VolumeRecord readVolumeRecord(XmlPullParser in) throws IOException {
        final int type = readIntAttribute(in, ATTR_TYPE);
        final String fsUuid = readStringAttribute(in, ATTR_FS_UUID);
        final VolumeRecord meta = new VolumeRecord(type, fsUuid);
        meta.partGuid = readStringAttribute(in, ATTR_PART_GUID);
        meta.nickname = readStringAttribute(in, ATTR_NICKNAME);
        meta.userFlags = readIntAttribute(in, ATTR_USER_FLAGS);
        meta.createdMillis = readLongAttribute(in, ATTR_CREATED_MILLIS, 0);
        meta.lastSeenMillis = readLongAttribute(in, ATTR_LAST_SEEN_MILLIS, 0);
        meta.lastTrimMillis = readLongAttribute(in, ATTR_LAST_TRIM_MILLIS, 0);
        meta.lastBenchMillis = readLongAttribute(in, ATTR_LAST_BENCH_MILLIS, 0);
        return meta;
    }

    public static void writeVolumeRecord(XmlSerializer out, VolumeRecord rec) throws IOException {
        out.startTag(null, TAG_VOLUME);
        writeIntAttribute(out, ATTR_TYPE, rec.type);
        writeStringAttribute(out, ATTR_FS_UUID, rec.fsUuid);
        writeStringAttribute(out, ATTR_PART_GUID, rec.partGuid);
        writeStringAttribute(out, ATTR_NICKNAME, rec.nickname);
        writeIntAttribute(out, ATTR_USER_FLAGS, rec.userFlags);
        writeLongAttribute(out, ATTR_CREATED_MILLIS, rec.createdMillis);
        writeLongAttribute(out, ATTR_LAST_SEEN_MILLIS, rec.lastSeenMillis);
        writeLongAttribute(out, ATTR_LAST_TRIM_MILLIS, rec.lastTrimMillis);
        writeLongAttribute(out, ATTR_LAST_BENCH_MILLIS, rec.lastBenchMillis);
        out.endTag(null, TAG_VOLUME);
    }

    /**
     * Exposed API calls below here
     */

    @Override
    public void registerListener(IStorageEventListener listener) {
        mCallbacks.register(listener);
    }

    @Override
    public void unregisterListener(IStorageEventListener listener) {
        mCallbacks.unregister(listener);
    }

    @Override
    public void shutdown(final IStorageShutdownObserver observer) {
        enforcePermission(android.Manifest.permission.SHUTDOWN);

        Slog.i(TAG, "Shutting down");
        mHandler.obtainMessage(H_SHUTDOWN, observer).sendToTarget();
    }

    @Override
    public void mount(String volId) {
        enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);

        final VolumeInfo vol = findVolumeByIdOrThrow(volId);
        if (isMountDisallowed(vol)) {
            throw new SecurityException("Mounting " + volId + " restricted by policy");
        }

        mount(vol);
    }

    private void remountAppStorageDirs(Map<Integer, String> pidPkgMap, int userId) {
        for (Entry<Integer, String> entry : pidPkgMap.entrySet()) {
            final int pid = entry.getKey();
            final String packageName = entry.getValue();
            Slog.i(TAG, "Remounting storage for pid: " + pid);
            final String[] sharedPackages =
                    mPmInternal.getSharedUserPackagesForPackage(packageName, userId);
            final int uid = mPmInternal.getPackageUidInternal(packageName, 0, userId);
            final String[] packages =
                    sharedPackages.length != 0 ? sharedPackages : new String[]{packageName};
            try {
                mVold.remountAppStorageDirs(uid, pid, packages);
            } catch (RemoteException e) {
                throw e.rethrowAsRuntimeException();
            }
        }
    }

    private void mount(VolumeInfo vol) {
        try {
            // TODO(b/135341433): Remove paranoid logging when FUSE is stable
            Slog.i(TAG, "Mounting volume " + vol);
            mVold.mount(vol.id, vol.mountFlags, vol.mountUserId, new IVoldMountCallback.Stub() {
                @Override
                public boolean onVolumeChecking(FileDescriptor fd, String path,
                        String internalPath) {
                    vol.path = path;
                    vol.internalPath = internalPath;
                    ParcelFileDescriptor pfd = new ParcelFileDescriptor(fd);
                    try {
                        mStorageSessionController.onVolumeMount(pfd, vol);
                        return true;
                    } catch (ExternalStorageServiceException e) {
                        Slog.e(TAG, "Failed to mount volume " + vol, e);

                        int nextResetSeconds = FAILED_MOUNT_RESET_TIMEOUT_SECONDS;
                        Slog.i(TAG, "Scheduling reset in " + nextResetSeconds + "s");
                        mHandler.removeMessages(H_RESET);
                        mHandler.sendMessageDelayed(mHandler.obtainMessage(H_RESET),
                                TimeUnit.SECONDS.toMillis(nextResetSeconds));
                        return false;
                    } finally {
                        try {
                            pfd.close();
                        } catch (Exception e) {
                            Slog.e(TAG, "Failed to close FUSE device fd", e);
                        }
                    }
                }
            });
            Slog.i(TAG, "Mounted volume " + vol);
        } catch (Exception e) {
            Slog.wtf(TAG, e);
        }
    }

    @Override
    public void unmount(String volId) {
        enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);

        final VolumeInfo vol = findVolumeByIdOrThrow(volId);
        unmount(vol);
    }

    private void unmount(VolumeInfo vol) {
        try {
            try {
                if (vol.type == VolumeInfo.TYPE_PRIVATE) {
                    mInstaller.onPrivateVolumeRemoved(vol.getFsUuid());
                }
            } catch (Installer.InstallerException e) {
                Slog.e(TAG, "Failed unmount mirror data", e);
            }
            mVold.unmount(vol.id);
            mStorageSessionController.onVolumeUnmount(vol);
        } catch (Exception e) {
            Slog.wtf(TAG, e);
        }
    }

    @Override
    public void format(String volId) {
        enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);

        final VolumeInfo vol = findVolumeByIdOrThrow(volId);
        final String fsUuid = vol.fsUuid;
        try {
            mVold.format(vol.id, "auto");

            // After a successful format above, we should forget about any
            // records for the old partition, since it'll never appear again
            if (!TextUtils.isEmpty(fsUuid)) {
                forgetVolume(fsUuid);
            }
        } catch (Exception e) {
            Slog.wtf(TAG, e);
        }
    }

    @Override
    public void benchmark(String volId, IVoldTaskListener listener) {
        enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);

        try {
            mVold.benchmark(volId, new IVoldTaskListener.Stub() {
                @Override
                public void onStatus(int status, PersistableBundle extras) {
                    dispatchOnStatus(listener, status, extras);
                }

                @Override
                public void onFinished(int status, PersistableBundle extras) {
                    dispatchOnFinished(listener, status, extras);

                    final String path = extras.getString("path");
                    final String ident = extras.getString("ident");
                    final long create = extras.getLong("create");
                    final long run = extras.getLong("run");
                    final long destroy = extras.getLong("destroy");

                    final DropBoxManager dropBox = mContext.getSystemService(DropBoxManager.class);
                    dropBox.addText(TAG_STORAGE_BENCHMARK, scrubPath(path)
                            + " " + ident + " " + create + " " + run + " " + destroy);

                    synchronized (mLock) {
                        final VolumeRecord rec = findRecordForPath(path);
                        if (rec != null) {
                            rec.lastBenchMillis = System.currentTimeMillis();
                            writeSettingsLocked();
                        }
                    }
                }
            });
        } catch (RemoteException e) {
            throw e.rethrowAsRuntimeException();
        }
    }

    @Override
    public void partitionPublic(String diskId) {
        enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);

        final CountDownLatch latch = findOrCreateDiskScanLatch(diskId);
        try {
            mVold.partition(diskId, IVold.PARTITION_TYPE_PUBLIC, -1);
            waitForLatch(latch, "partitionPublic", 3 * DateUtils.MINUTE_IN_MILLIS);
        } catch (Exception e) {
            Slog.wtf(TAG, e);
        }
    }

    @Override
    public void partitionPrivate(String diskId) {
        enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);
        enforceAdminUser();

        final CountDownLatch latch = findOrCreateDiskScanLatch(diskId);
        try {
            mVold.partition(diskId, IVold.PARTITION_TYPE_PRIVATE, -1);
            waitForLatch(latch, "partitionPrivate", 3 * DateUtils.MINUTE_IN_MILLIS);
        } catch (Exception e) {
            Slog.wtf(TAG, e);
        }
    }

    @Override
    public void partitionMixed(String diskId, int ratio) {
        enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);
        enforceAdminUser();

        final CountDownLatch latch = findOrCreateDiskScanLatch(diskId);
        try {
            mVold.partition(diskId, IVold.PARTITION_TYPE_MIXED, ratio);
            waitForLatch(latch, "partitionMixed", 3 * DateUtils.MINUTE_IN_MILLIS);
        } catch (Exception e) {
            Slog.wtf(TAG, e);
        }
    }

    @Override
    public void setVolumeNickname(String fsUuid, String nickname) {
        enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);

        Objects.requireNonNull(fsUuid);
        synchronized (mLock) {
            final VolumeRecord rec = mRecords.get(fsUuid);
            rec.nickname = nickname;
            mCallbacks.notifyVolumeRecordChanged(rec);
            writeSettingsLocked();
        }
    }

    @Override
    public void setVolumeUserFlags(String fsUuid, int flags, int mask) {
        enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);

        Objects.requireNonNull(fsUuid);
        synchronized (mLock) {
            final VolumeRecord rec = mRecords.get(fsUuid);
            rec.userFlags = (rec.userFlags & ~mask) | (flags & mask);
            mCallbacks.notifyVolumeRecordChanged(rec);
            writeSettingsLocked();
        }
    }

    @Override
    public void forgetVolume(String fsUuid) {
        enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);

        Objects.requireNonNull(fsUuid);

        synchronized (mLock) {
            final VolumeRecord rec = mRecords.remove(fsUuid);
            if (rec != null && !TextUtils.isEmpty(rec.partGuid)) {
                mHandler.obtainMessage(H_PARTITION_FORGET, rec).sendToTarget();
            }
            mCallbacks.notifyVolumeForgotten(fsUuid);

            // If this had been primary storage, revert back to internal and
            // reset vold so we bind into new volume into place.
            if (Objects.equals(mPrimaryStorageUuid, fsUuid)) {
                mPrimaryStorageUuid = getDefaultPrimaryStorageUuid();
                mHandler.obtainMessage(H_RESET).sendToTarget();
            }

            writeSettingsLocked();
        }
    }

    @Override
    public void forgetAllVolumes() {
        enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);

        synchronized (mLock) {
            for (int i = 0; i < mRecords.size(); i++) {
                final String fsUuid = mRecords.keyAt(i);
                final VolumeRecord rec = mRecords.valueAt(i);
                if (!TextUtils.isEmpty(rec.partGuid)) {
                    mHandler.obtainMessage(H_PARTITION_FORGET, rec).sendToTarget();
                }
                mCallbacks.notifyVolumeForgotten(fsUuid);
            }
            mRecords.clear();

            if (!Objects.equals(StorageManager.UUID_PRIVATE_INTERNAL, mPrimaryStorageUuid)) {
                mPrimaryStorageUuid = getDefaultPrimaryStorageUuid();
            }

            writeSettingsLocked();
            mHandler.obtainMessage(H_RESET).sendToTarget();
        }
    }

    private void forgetPartition(String partGuid, String fsUuid) {
        try {
            mVold.forgetPartition(partGuid, fsUuid);
        } catch (Exception e) {
            Slog.wtf(TAG, e);
        }
    }

    @Override
    public void fstrim(int flags, IVoldTaskListener listener) {
        enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);

        try {
            // Block based checkpoint process runs fstrim. So, if checkpoint is in progress
            // (first boot after OTA), We skip idle maintenance and make sure the last
            // fstrim time is still updated. If file based checkpoints are used, we run
            // idle maintenance (GC + fstrim) regardless of checkpoint status.
            if (!needsCheckpoint() || !supportsBlockCheckpoint()) {
                mVold.fstrim(flags, new IVoldTaskListener.Stub() {
                    @Override
                    public void onStatus(int status, PersistableBundle extras) {
                        dispatchOnStatus(listener, status, extras);

                        // Ignore trim failures
                        if (status != 0) return;

                        final String path = extras.getString("path");
                        final long bytes = extras.getLong("bytes");
                        final long time = extras.getLong("time");

                        final DropBoxManager dropBox = mContext.getSystemService(DropBoxManager.class);
                        dropBox.addText(TAG_STORAGE_TRIM, scrubPath(path) + " " + bytes + " " + time);

                        synchronized (mLock) {
                            final VolumeRecord rec = findRecordForPath(path);
                            if (rec != null) {
                                rec.lastTrimMillis = System.currentTimeMillis();
                                writeSettingsLocked();
                            }
                        }
                    }

                    @Override
                    public void onFinished(int status, PersistableBundle extras) {
                        dispatchOnFinished(listener, status, extras);

                        // TODO: benchmark when desired
                    }
                });
            } else {
                Slog.i(TAG, "Skipping fstrim - block based checkpoint in progress");
            }
        } catch (RemoteException e) {
            throw e.rethrowAsRuntimeException();
        }
    }

    void runIdleMaint(Runnable callback) {
        enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);

        try {
            // Block based checkpoint process runs fstrim. So, if checkpoint is in progress
            // (first boot after OTA), We skip idle maintenance and make sure the last
            // fstrim time is still updated. If file based checkpoints are used, we run
            // idle maintenance (GC + fstrim) regardless of checkpoint status.
            if (!needsCheckpoint() || !supportsBlockCheckpoint()) {
                mVold.runIdleMaint(new IVoldTaskListener.Stub() {
                    @Override
                    public void onStatus(int status, PersistableBundle extras) {
                        // Not currently used
                    }
                    @Override
                    public void onFinished(int status, PersistableBundle extras) {
                        if (callback != null) {
                            BackgroundThread.getHandler().post(callback);
                        }
                    }
                });
            } else {
                Slog.i(TAG, "Skipping idle maintenance - block based checkpoint in progress");
            }
        } catch (Exception e) {
            Slog.wtf(TAG, e);
        }
    }

    @Override
    public void runIdleMaintenance() {
        runIdleMaint(null);
    }

    void abortIdleMaint(Runnable callback) {
        enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);

        try {
            mVold.abortIdleMaint(new IVoldTaskListener.Stub() {
                @Override
                public void onStatus(int status, PersistableBundle extras) {
                    // Not currently used
                }
                @Override
                public void onFinished(int status, PersistableBundle extras) {
                    if (callback != null) {
                        BackgroundThread.getHandler().post(callback);
                    }
                }
            });
        } catch (Exception e) {
            Slog.wtf(TAG, e);
        }
    }

    @Override
    public void abortIdleMaintenance() {
        abortIdleMaint(null);
    }

    private void remountUidExternalStorage(int uid, int mode) {
        if (uid == Process.SYSTEM_UID) {
            // No need to remount uid for system because it has all access anyways
            return;
        }

        try {
            mVold.remountUid(uid, mode);
        } catch (Exception e) {
            Slog.wtf(TAG, e);
        }
    }

    @Override
    public void setDebugFlags(int flags, int mask) {
        enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);

        if ((mask & StorageManager.DEBUG_EMULATE_FBE) != 0) {
            if (!EMULATE_FBE_SUPPORTED) {
                throw new IllegalStateException(
                        "Emulation not supported on this device");
            }
            if (StorageManager.isFileEncryptedNativeOnly()) {
                throw new IllegalStateException(
                        "Emulation not supported on device with native FBE");
            }
            if (mLockPatternUtils.isCredentialRequiredToDecrypt(false)) {
                throw new IllegalStateException(
                        "Emulation requires disabling 'Secure start-up' in Settings > Security");
            }

            final long token = Binder.clearCallingIdentity();
            try {
                final boolean emulateFbe = (flags & StorageManager.DEBUG_EMULATE_FBE) != 0;
                SystemProperties.set(StorageManager.PROP_EMULATE_FBE, Boolean.toString(emulateFbe));

                // Perform hard reboot to kick policy into place
                mContext.getSystemService(PowerManager.class).reboot(null);
            } finally {
                Binder.restoreCallingIdentity(token);
            }
        }

        if ((mask & (StorageManager.DEBUG_ADOPTABLE_FORCE_ON
                | StorageManager.DEBUG_ADOPTABLE_FORCE_OFF)) != 0) {
            final String value;
            if ((flags & StorageManager.DEBUG_ADOPTABLE_FORCE_ON) != 0) {
                value = "force_on";
            } else if ((flags & StorageManager.DEBUG_ADOPTABLE_FORCE_OFF) != 0) {
                value = "force_off";
            } else {
                value = "";
            }

            final long token = Binder.clearCallingIdentity();
            try {
                SystemProperties.set(StorageManager.PROP_ADOPTABLE, value);

                // Reset storage to kick new setting into place
                mHandler.obtainMessage(H_RESET).sendToTarget();
            } finally {
                Binder.restoreCallingIdentity(token);
            }
        }

        if ((mask & (StorageManager.DEBUG_SDCARDFS_FORCE_ON
                | StorageManager.DEBUG_SDCARDFS_FORCE_OFF)) != 0) {
            final String value;
            if ((flags & StorageManager.DEBUG_SDCARDFS_FORCE_ON) != 0) {
                value = "force_on";
            } else if ((flags & StorageManager.DEBUG_SDCARDFS_FORCE_OFF) != 0) {
                value = "force_off";
            } else {
                value = "";
            }

            final long token = Binder.clearCallingIdentity();
            try {
                SystemProperties.set(StorageManager.PROP_SDCARDFS, value);

                // Reset storage to kick new setting into place
                mHandler.obtainMessage(H_RESET).sendToTarget();
            } finally {
                Binder.restoreCallingIdentity(token);
            }
        }

        if ((mask & StorageManager.DEBUG_VIRTUAL_DISK) != 0) {
            final boolean enabled = (flags & StorageManager.DEBUG_VIRTUAL_DISK) != 0;

            final long token = Binder.clearCallingIdentity();
            try {
                SystemProperties.set(StorageManager.PROP_VIRTUAL_DISK, Boolean.toString(enabled));

                // Reset storage to kick new setting into place
                mHandler.obtainMessage(H_RESET).sendToTarget();
            } finally {
                Binder.restoreCallingIdentity(token);
            }
        }

        if ((mask & (StorageManager.DEBUG_ISOLATED_STORAGE_FORCE_ON
                | StorageManager.DEBUG_ISOLATED_STORAGE_FORCE_OFF)) != 0) {
            final int value;
            if ((flags & StorageManager.DEBUG_ISOLATED_STORAGE_FORCE_ON) != 0) {
                value = 1;
            } else if ((flags & StorageManager.DEBUG_ISOLATED_STORAGE_FORCE_OFF) != 0) {
                value = -1;
            } else {
                value = 0;
            }

            final long token = Binder.clearCallingIdentity();
            try {
                Settings.Global.putInt(mContext.getContentResolver(),
                        Settings.Global.ISOLATED_STORAGE_LOCAL, value);
                refreshIsolatedStorageSettings();

                // Perform hard reboot to kick policy into place
                mHandler.post(() -> {
                    mContext.getSystemService(PowerManager.class).reboot(null);
                });
            } finally {
                Binder.restoreCallingIdentity(token);
            }
        }
    }

    @Override
    public String getPrimaryStorageUuid() {
        synchronized (mLock) {
            return mPrimaryStorageUuid;
        }
    }

    @Override
    public void setPrimaryStorageUuid(String volumeUuid, IPackageMoveObserver callback) {
        enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);

        final VolumeInfo from;
        final VolumeInfo to;

        synchronized (mLock) {
            if (Objects.equals(mPrimaryStorageUuid, volumeUuid)) {
                throw new IllegalArgumentException("Primary storage already at " + volumeUuid);
            }

            if (mMoveCallback != null) {
                throw new IllegalStateException("Move already in progress");
            }
            mMoveCallback = callback;
            mMoveTargetUuid = volumeUuid;

            // We need all the users unlocked to move their primary storage
            final List<UserInfo> users = mContext.getSystemService(UserManager.class).getUsers();
            for (UserInfo user : users) {
                if (StorageManager.isFileEncryptedNativeOrEmulated()
                        && !isUserKeyUnlocked(user.id)) {
                    Slog.w(TAG, "Failing move due to locked user " + user.id);
                    onMoveStatusLocked(PackageManager.MOVE_FAILED_LOCKED_USER);
                    return;
                }
            }

            // When moving to/from primary physical volume, we probably just nuked
            // the current storage location, so we have nothing to move.
            if (Objects.equals(StorageManager.UUID_PRIMARY_PHYSICAL, mPrimaryStorageUuid)
                    || Objects.equals(StorageManager.UUID_PRIMARY_PHYSICAL, volumeUuid)) {
                Slog.d(TAG, "Skipping move to/from primary physical");
                onMoveStatusLocked(MOVE_STATUS_COPY_FINISHED);
                onMoveStatusLocked(PackageManager.MOVE_SUCCEEDED);
                mHandler.obtainMessage(H_RESET).sendToTarget();
                return;

            } else {
                from = findStorageForUuid(mPrimaryStorageUuid);
                to = findStorageForUuid(volumeUuid);

                if (from == null) {
                    Slog.w(TAG, "Failing move due to missing from volume " + mPrimaryStorageUuid);
                    onMoveStatusLocked(PackageManager.MOVE_FAILED_INTERNAL_ERROR);
                    return;
                } else if (to == null) {
                    Slog.w(TAG, "Failing move due to missing to volume " + volumeUuid);
                    onMoveStatusLocked(PackageManager.MOVE_FAILED_INTERNAL_ERROR);
                    return;
                }
            }
        }

        try {
            mVold.moveStorage(from.id, to.id, new IVoldTaskListener.Stub() {
                @Override
                public void onStatus(int status, PersistableBundle extras) {
                    synchronized (mLock) {
                        onMoveStatusLocked(status);
                    }
                }

                @Override
                public void onFinished(int status, PersistableBundle extras) {
                    // Not currently used
                }
            });
        } catch (Exception e) {
            Slog.wtf(TAG, e);
        }
    }

    private void warnOnNotMounted() {
        synchronized (mLock) {
            for (int i = 0; i < mVolumes.size(); i++) {
                final VolumeInfo vol = mVolumes.valueAt(i);
                if (vol.isPrimary() && vol.isMountedWritable()) {
                    // Cool beans, we have a mounted primary volume
                    return;
                }
            }
        }

        Slog.w(TAG, "No primary storage mounted!");
    }

    private boolean isUidOwnerOfPackageOrSystem(String packageName, int callerUid) {
        if (callerUid == android.os.Process.SYSTEM_UID) {
            return true;
        }

        if (packageName == null) {
            return false;
        }

        final int packageUid = mPmInternal.getPackageUid(packageName,
                PackageManager.MATCH_DEBUG_TRIAGED_MISSING, UserHandle.getUserId(callerUid));

        if (DEBUG_OBB) {
            Slog.d(TAG, "packageName = " + packageName + ", packageUid = " +
                    packageUid + ", callerUid = " + callerUid);
        }

        return callerUid == packageUid;
    }

    @Override
    public String getMountedObbPath(String rawPath) {
        Objects.requireNonNull(rawPath, "rawPath cannot be null");

        warnOnNotMounted();

        final ObbState state;
        synchronized (mObbMounts) {
            state = mObbPathToStateMap.get(rawPath);
        }
        if (state == null) {
            Slog.w(TAG, "Failed to find OBB mounted at " + rawPath);
            return null;
        }

        return findVolumeByIdOrThrow(state.volId).getPath().getAbsolutePath();
    }

    @Override
    public boolean isObbMounted(String rawPath) {
        Objects.requireNonNull(rawPath, "rawPath cannot be null");
        synchronized (mObbMounts) {
            return mObbPathToStateMap.containsKey(rawPath);
        }
    }

    @Override
    public void mountObb(String rawPath, String canonicalPath, String key,
            IObbActionListener token, int nonce, ObbInfo obbInfo) {
        Objects.requireNonNull(rawPath, "rawPath cannot be null");
        Objects.requireNonNull(canonicalPath, "canonicalPath cannot be null");
        Objects.requireNonNull(token, "token cannot be null");
        Objects.requireNonNull(obbInfo, "obbIfno cannot be null");

        final int callingUid = Binder.getCallingUid();
        final ObbState obbState = new ObbState(rawPath, canonicalPath,
                callingUid, token, nonce, null);
        final ObbAction action = new MountObbAction(obbState, key, callingUid, obbInfo);
        mObbActionHandler.sendMessage(mObbActionHandler.obtainMessage(OBB_RUN_ACTION, action));

        if (DEBUG_OBB)
            Slog.i(TAG, "Send to OBB handler: " + action.toString());
    }

    @Override
    public void unmountObb(String rawPath, boolean force, IObbActionListener token, int nonce) {
        Objects.requireNonNull(rawPath, "rawPath cannot be null");

        final ObbState existingState;
        synchronized (mObbMounts) {
            existingState = mObbPathToStateMap.get(rawPath);
        }

        if (existingState != null) {
            // TODO: separate state object from request data
            final int callingUid = Binder.getCallingUid();
            final ObbState newState = new ObbState(rawPath, existingState.canonicalPath,
                    callingUid, token, nonce, existingState.volId);
            final ObbAction action = new UnmountObbAction(newState, force);
            mObbActionHandler.sendMessage(mObbActionHandler.obtainMessage(OBB_RUN_ACTION, action));

            if (DEBUG_OBB)
                Slog.i(TAG, "Send to OBB handler: " + action.toString());
        } else {
            Slog.w(TAG, "Unknown OBB mount at " + rawPath);
        }
    }

    @Override
    public int getEncryptionState() {
        mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
                "no permission to access the crypt keeper");

        try {
            return mVold.fdeComplete();
        } catch (Exception e) {
            Slog.wtf(TAG, e);
            return StorageManager.ENCRYPTION_STATE_ERROR_UNKNOWN;
        }
    }

    @Override
    public int decryptStorage(String password) {
        mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
                "no permission to access the crypt keeper");

        if (TextUtils.isEmpty(password)) {
            throw new IllegalArgumentException("password cannot be empty");
        }

        if (DEBUG_EVENTS) {
            Slog.i(TAG, "decrypting storage...");
        }

        try {
            mVold.fdeCheckPassword(password);
            mHandler.postDelayed(() -> {
                try {
                    mVold.fdeRestart();
                } catch (Exception e) {
                    Slog.wtf(TAG, e);
                }
            }, DateUtils.SECOND_IN_MILLIS);
            return 0;
        } catch (ServiceSpecificException e) {
            Slog.e(TAG, "fdeCheckPassword failed", e);
            return e.errorCode;
        } catch (Exception e) {
            Slog.wtf(TAG, e);
            return StorageManager.ENCRYPTION_STATE_ERROR_UNKNOWN;
        }
    }

    @Override
    public int encryptStorage(int type, String password) {
        mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
            "no permission to access the crypt keeper");

        if (type == StorageManager.CRYPT_TYPE_DEFAULT) {
            password = "";
        } else if (TextUtils.isEmpty(password)) {
            throw new IllegalArgumentException("password cannot be empty");
        }

        if (DEBUG_EVENTS) {
            Slog.i(TAG, "encrypting storage...");
        }

        try {
            mVold.fdeEnable(type, password, 0);
        } catch (Exception e) {
            Slog.wtf(TAG, e);
            return -1;
        }

        return 0;
    }

    /** Set the password for encrypting the master key.
     *  @param type One of the CRYPTO_TYPE_XXX consts defined in StorageManager.
     *  @param password The password to set.
     */
    @Override
    public int changeEncryptionPassword(int type, String password) {
        mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
            "no permission to access the crypt keeper");

        if (StorageManager.isFileEncryptedNativeOnly()) {
            // Not supported on FBE devices
            return -1;
        }

        if (type == StorageManager.CRYPT_TYPE_DEFAULT) {
            password = "";
        } else if (TextUtils.isEmpty(password)) {
            throw new IllegalArgumentException("password cannot be empty");
        }

        if (DEBUG_EVENTS) {
            Slog.i(TAG, "changing encryption password...");
        }

        try {
            mVold.fdeChangePassword(type, password);
            return 0;
        } catch (Exception e) {
            Slog.wtf(TAG, e);
            return -1;
        }
    }

    /**
     * Validate a user-supplied password string with cryptfs
     */
    @Override
    public int verifyEncryptionPassword(String password) throws RemoteException {
        // Only the system process is permitted to validate passwords
        if (Binder.getCallingUid() != android.os.Process.SYSTEM_UID) {
            throw new SecurityException("no permission to access the crypt keeper");
        }

        mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
            "no permission to access the crypt keeper");

        if (TextUtils.isEmpty(password)) {
            throw new IllegalArgumentException("password cannot be empty");
        }

        if (DEBUG_EVENTS) {
            Slog.i(TAG, "validating encryption password...");
        }

        try {
            mVold.fdeVerifyPassword(password);
            return 0;
        } catch (Exception e) {
            Slog.wtf(TAG, e);
            return -1;
        }
    }

    /**
     * Get the type of encryption used to encrypt the master key.
     * @return The type, one of the CRYPT_TYPE_XXX consts from StorageManager.
     */
    @Override
    public int getPasswordType() {
        mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
            "no permission to access the crypt keeper");

        try {
            return mVold.fdeGetPasswordType();
        } catch (Exception e) {
            Slog.wtf(TAG, e);
            return -1;
        }
    }

    /**
     * Set a field in the crypto header.
     * @param field field to set
     * @param contents contents to set in field
     */
    @Override
    public void setField(String field, String contents) throws RemoteException {
        mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
            "no permission to access the crypt keeper");

        if (!StorageManager.isBlockEncrypted()) {
            // Only supported on FDE devices
            return;
        }

        try {
            mVold.fdeSetField(field, contents);
            return;
        } catch (Exception e) {
            Slog.wtf(TAG, e);
            return;
        }
    }

    /**
     * Gets a field from the crypto header.
     * @param field field to get
     * @return contents of field
     */
    @Override
    public String getField(String field) throws RemoteException {
        mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
            "no permission to access the crypt keeper");

        if (!StorageManager.isBlockEncrypted()) {
            // Only supported on FDE devices
            return null;
        }

        try {
            return mVold.fdeGetField(field);
        } catch (Exception e) {
            Slog.wtf(TAG, e);
            return null;
        }
    }

    /**
     * Is userdata convertible to file based encryption?
     * @return non zero for convertible
     */
    @Override
    public boolean isConvertibleToFBE() throws RemoteException {
        mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
            "no permission to access the crypt keeper");

        try {
            return mVold.isConvertibleToFbe();
        } catch (Exception e) {
            Slog.wtf(TAG, e);
            return false;
        }
    }

    /**
     * Check whether the device supports filesystem checkpointing.
     *
     * @return true if the device supports filesystem checkpointing, false otherwise.
     */
    @Override
    public boolean supportsCheckpoint() throws RemoteException {
        return mVold.supportsCheckpoint();
    }

    /**
     * Signal that checkpointing partitions should start a checkpoint on the next boot.
     *
     * @param numTries Number of times to try booting in checkpoint mode, before we will boot
     *                 non-checkpoint mode and commit all changes immediately. Callers are
     *                 responsible for ensuring that boot is safe (eg, by rolling back updates).
     */
    @Override
    public void startCheckpoint(int numTries) throws RemoteException {
        // Only the root, system_server and shell processes are permitted to start checkpoints
        final int callingUid = Binder.getCallingUid();
        if (callingUid != Process.SYSTEM_UID && callingUid != Process.ROOT_UID
                && callingUid != Process.SHELL_UID) {
            throw new SecurityException("no permission to start filesystem checkpoint");
        }

        mVold.startCheckpoint(numTries);
    }

    /**
     * Signal that checkpointing partitions should commit changes
     */
    @Override
    public void commitChanges() throws RemoteException {
        // Only the system process is permitted to commit checkpoints
        if (Binder.getCallingUid() != android.os.Process.SYSTEM_UID) {
            throw new SecurityException("no permission to commit checkpoint changes");
        }

        mVold.commitChanges();
    }

    /**
     * Check if we should be mounting with checkpointing or are checkpointing now
     */
    @Override
    public boolean needsCheckpoint() throws RemoteException {
        enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);
        return mVold.needsCheckpoint();
    }

    /**
     * Abort the current set of changes and either try again, or abort entirely
     */
    @Override
    public void abortChanges(String message, boolean retry) throws RemoteException {
        // Only the system process is permitted to abort checkpoints
        if (Binder.getCallingUid() != android.os.Process.SYSTEM_UID) {
            throw new SecurityException("no permission to commit checkpoint changes");
        }

        mVold.abortChanges(message, retry);
    }

    @Override
    public String getPassword() throws RemoteException {
        mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
                "only keyguard can retrieve password");

        try {
            return mVold.fdeGetPassword();
        } catch (Exception e) {
            Slog.wtf(TAG, e);
            return null;
        }
    }

    @Override
    public void clearPassword() throws RemoteException {
        mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
                "only keyguard can clear password");

        try {
            mVold.fdeClearPassword();
            return;
        } catch (Exception e) {
            Slog.wtf(TAG, e);
            return;
        }
    }

    @Override
    public void createUserKey(int userId, int serialNumber, boolean ephemeral) {
        enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);

        try {
            mVold.createUserKey(userId, serialNumber, ephemeral);
        } catch (Exception e) {
            Slog.wtf(TAG, e);
        }
    }

    @Override
    public void destroyUserKey(int userId) {
        enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);

        try {
            mVold.destroyUserKey(userId);
        } catch (Exception e) {
            Slog.wtf(TAG, e);
        }
    }

    private String encodeBytes(byte[] bytes) {
        if (ArrayUtils.isEmpty(bytes)) {
            return "!";
        } else {
            return HexDump.toHexString(bytes);
        }
    }

    /*
     * Add this token/secret pair to the set of ways we can recover a disk encryption key.
     * Changing the token/secret for a disk encryption key is done in two phases: first, adding
     * a new token/secret pair with this call, then delting all other pairs with
     * fixateNewestUserKeyAuth. This allows other places where a credential is used, such as
     * Gatekeeper, to be updated between the two calls.
     */
    @Override
    public void addUserKeyAuth(int userId, int serialNumber, byte[] token, byte[] secret) {
        enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);

        try {
            mVold.addUserKeyAuth(userId, serialNumber, encodeBytes(token), encodeBytes(secret));
        } catch (Exception e) {
            Slog.wtf(TAG, e);
        }
    }

    /*
     * Clear disk encryption key bound to the associated token / secret pair. Removing the user
     * binding of the Disk encryption key is done in two phases: first, this call will retrieve
     * the disk encryption key using the provided token / secret pair and store it by
     * encrypting it with a keymaster key not bound to the user, then fixateNewestUserKeyAuth
     * is called to delete all other bindings of the disk encryption key.
     */
    @Override
    public void clearUserKeyAuth(int userId, int serialNumber, byte[] token, byte[] secret) {
        enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);

        try {
            mVold.clearUserKeyAuth(userId, serialNumber, encodeBytes(token), encodeBytes(secret));
        } catch (Exception e) {
            Slog.wtf(TAG, e);
        }
    }

    /*
     * Delete all disk encryption token/secret pairs except the most recently added one
     */
    @Override
    public void fixateNewestUserKeyAuth(int userId) {
        enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);

        try {
            mVold.fixateNewestUserKeyAuth(userId);
        } catch (Exception e) {
            Slog.wtf(TAG, e);
        }
    }

    @Override
    public void unlockUserKey(int userId, int serialNumber, byte[] token, byte[] secret) {
        boolean isFsEncrypted = StorageManager.isFileEncryptedNativeOrEmulated();
        Slog.d(TAG, "unlockUserKey: " + userId
                + " isFileEncryptedNativeOrEmulated: " + isFsEncrypted
                + " hasToken: " + (token != null)
                + " hasSecret: " + (secret != null));
        enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);

        if (isFsEncrypted) {
            try {
                mVold.unlockUserKey(userId, serialNumber, encodeBytes(token),
                        encodeBytes(secret));
            } catch (Exception e) {
                Slog.wtf(TAG, e);
                return;
            }
        }

        synchronized (mLock) {
            mLocalUnlockedUsers.append(userId);
        }
    }

    @Override
    public void lockUserKey(int userId) {
        enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);

        try {
            mVold.lockUserKey(userId);
        } catch (Exception e) {
            Slog.wtf(TAG, e);
            return;
        }

        synchronized (mLock) {
            mLocalUnlockedUsers.remove(userId);
        }
    }

    @Override
    public boolean isUserKeyUnlocked(int userId) {
        synchronized (mLock) {
            return mLocalUnlockedUsers.contains(userId);
        }
    }

    private boolean isSystemUnlocked(int userId) {
        synchronized (mLock) {
            return ArrayUtils.contains(mSystemUnlockedUsers, userId);
        }
    }

    private void prepareUserStorageIfNeeded(VolumeInfo vol) {
        if (vol.type != VolumeInfo.TYPE_PRIVATE) {
            return;
        }

        final UserManager um = mContext.getSystemService(UserManager.class);
        final UserManagerInternal umInternal =
                LocalServices.getService(UserManagerInternal.class);

        for (UserInfo user : um.getUsers(false /* includeDying */)) {
            final int flags;
            if (umInternal.isUserUnlockingOrUnlocked(user.id)) {
                flags = StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE;
            } else if (umInternal.isUserRunning(user.id)) {
                flags = StorageManager.FLAG_STORAGE_DE;
            } else {
                continue;
            }

            prepareUserStorageInternal(vol.fsUuid, user.id, user.serialNumber, flags);
        }
    }

    @Override
    public void prepareUserStorage(String volumeUuid, int userId, int serialNumber, int flags) {
        enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);

        prepareUserStorageInternal(volumeUuid, userId, serialNumber, flags);
    }

    private void prepareUserStorageInternal(String volumeUuid, int userId, int serialNumber,
            int flags) {
        try {
            mVold.prepareUserStorage(volumeUuid, userId, serialNumber, flags);
            // After preparing user storage, we should check if we should mount data mirror again,
            // and we do it for user 0 only as we only need to do once for all users.
            if (volumeUuid != null) {
                final StorageManager storage = mContext.getSystemService(StorageManager.class);
                VolumeInfo info = storage.findVolumeByUuid(volumeUuid);
                if (info != null && userId == 0 && info.type == VolumeInfo.TYPE_PRIVATE) {
                    mInstaller.tryMountDataMirror(volumeUuid);
                }
            }
        } catch (Exception e) {
            Slog.wtf(TAG, e);
        }
    }

    @Override
    public void destroyUserStorage(String volumeUuid, int userId, int flags) {
        enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);

        try {
            mVold.destroyUserStorage(volumeUuid, userId, flags);
        } catch (Exception e) {
            Slog.wtf(TAG, e);
        }
    }

    @Override
    public void fixupAppDir(String path) {
        final Matcher matcher = KNOWN_APP_DIR_PATHS.matcher(path);
        if (matcher.matches()) {
            if (matcher.group(2) == null) {
                Log.e(TAG, "Asked to fixup an app dir without a userId: " + path);
                return;
            }
            try {
                int userId = Integer.parseInt(matcher.group(2));
                String packageName = matcher.group(3);
                int uid = mContext.getPackageManager().getPackageUidAsUser(packageName, userId);
                try {
                    mVold.fixupAppDir(path + "/", uid);
                } catch (RemoteException | ServiceSpecificException e) {
                    Log.e(TAG, "Failed to fixup app dir for " + packageName, e);
                }
            } catch (NumberFormatException e) {
                Log.e(TAG, "Invalid userId in path: " + path, e);
            } catch (PackageManager.NameNotFoundException e) {
                Log.e(TAG, "Couldn't find package to fixup app dir " + path, e);
            }
        } else {
            Log.e(TAG, "Path " + path + " is not a valid application-specific directory");
        }
    }

    /** Not thread safe */
    class AppFuseMountScope extends AppFuseBridge.MountScope {
        private boolean mMounted = false;

        public AppFuseMountScope(int uid, int mountId) {
            super(uid, mountId);
        }

        @Override
        public ParcelFileDescriptor open() throws NativeDaemonConnectorException {
            try {
                final FileDescriptor fd = mVold.mountAppFuse(uid, mountId);
                mMounted = true;
                return new ParcelFileDescriptor(fd);
            } catch (Exception e) {
                throw new NativeDaemonConnectorException("Failed to mount", e);
            }
        }

        @Override
        public ParcelFileDescriptor openFile(int mountId, int fileId, int flags)
                throws NativeDaemonConnectorException {
            try {
                return new ParcelFileDescriptor(
                        mVold.openAppFuseFile(uid, mountId, fileId, flags));
            } catch (Exception e) {
                throw new NativeDaemonConnectorException("Failed to open", e);
            }
        }

        @Override
        public void close() throws Exception {
            if (mMounted) {
                mVold.unmountAppFuse(uid, mountId);
                mMounted = false;
            }
        }
    }

    @Override
    public @Nullable AppFuseMount mountProxyFileDescriptorBridge() {
        Slog.v(TAG, "mountProxyFileDescriptorBridge");
        final int uid = Binder.getCallingUid();

        while (true) {
            synchronized (mAppFuseLock) {
                boolean newlyCreated = false;
                if (mAppFuseBridge == null) {
                    mAppFuseBridge = new AppFuseBridge();
                    new Thread(mAppFuseBridge, AppFuseBridge.TAG).start();
                    newlyCreated = true;
                }
                try {
                    final int name = mNextAppFuseName++;
                    try {
                        return new AppFuseMount(
                            name, mAppFuseBridge.addBridge(new AppFuseMountScope(uid, name)));
                    } catch (FuseUnavailableMountException e) {
                        if (newlyCreated) {
                            // If newly created bridge fails, it's a real error.
                            Slog.e(TAG, "", e);
                            return null;
                        }
                        // It seems the thread of mAppFuseBridge has already been terminated.
                        mAppFuseBridge = null;
                    }
                } catch (NativeDaemonConnectorException e) {
                    throw e.rethrowAsParcelableException();
                }
            }
        }
    }

    @Override
    public @Nullable ParcelFileDescriptor openProxyFileDescriptor(
            int mountId, int fileId, int mode) {
        Slog.v(TAG, "mountProxyFileDescriptor");

        // We only support a narrow set of incoming mode flags
        mode &= MODE_READ_WRITE;

        try {
            synchronized (mAppFuseLock) {
                if (mAppFuseBridge == null) {
                    Slog.e(TAG, "FuseBridge has not been created");
                    return null;
                }
                return mAppFuseBridge.openFile(mountId, fileId, mode);
            }
        } catch (FuseUnavailableMountException | InterruptedException error) {
            Slog.v(TAG, "The mount point has already been invalid", error);
            return null;
        }
    }

    @Override
    public void mkdirs(String callingPkg, String appPath) {
        final int callingUid = Binder.getCallingUid();
        final int userId = UserHandle.getUserId(callingUid);
        final String propertyName = "sys.user." + userId + ".ce_available";

        // Ignore requests to create directories while storage is locked
        if (!isUserKeyUnlocked(userId)) {
            throw new IllegalStateException("Failed to prepare " + appPath);
        }

        // Ignore requests to create directories if CE storage is not available
        if ((userId == UserHandle.USER_SYSTEM)
                && !SystemProperties.getBoolean(propertyName, false)) {
            throw new IllegalStateException("Failed to prepare " + appPath);
        }

        // Validate that reported package name belongs to caller
        final AppOpsManager appOps = (AppOpsManager) mContext.getSystemService(
                Context.APP_OPS_SERVICE);
        appOps.checkPackage(callingUid, callingPkg);

        File appFile = null;
        try {
            appFile = new File(appPath).getCanonicalFile();
        } catch (IOException e) {
            throw new IllegalStateException("Failed to resolve " + appPath + ": " + e);
        }

        appPath = appFile.getAbsolutePath();
        if (!appPath.endsWith("/")) {
            appPath = appPath + "/";
        }
        // Ensure that the path we're asked to create is a known application directory
        // path.
        final Matcher matcher = KNOWN_APP_DIR_PATHS.matcher(appPath);
        if (matcher.matches()) {
            // And that the package dir matches the calling package
            if (!matcher.group(3).equals(callingPkg)) {
                throw new SecurityException("Invalid mkdirs path: " + appFile
                        + " does not contain calling package " + callingPkg);
            }
            // And that the user id part of the path (if any) matches the calling user id,
            // or if for a public volume (no user id), the user matches the current user
            if ((matcher.group(2) != null && !matcher.group(2).equals(Integer.toString(userId)))
                    || (matcher.group(2) == null && userId != mCurrentUserId)) {
                throw new SecurityException("Invalid mkdirs path: " + appFile
                        + " does not match calling user id " + userId);
            }
            try {
                mVold.setupAppDir(appPath, callingUid);
            } catch (RemoteException e) {
                throw new IllegalStateException("Failed to prepare " + appPath + ": " + e);
            }

            return;
        }
        throw new SecurityException("Invalid mkdirs path: " + appFile
                + " is not a known app path.");
    }

    @Override
    public StorageVolume[] getVolumeList(int uid, String packageName, int flags) {
        final int userId = UserHandle.getUserId(uid);

        final boolean forWrite = (flags & StorageManager.FLAG_FOR_WRITE) != 0;
        final boolean realState = (flags & StorageManager.FLAG_REAL_STATE) != 0;
        final boolean includeInvisible = (flags & StorageManager.FLAG_INCLUDE_INVISIBLE) != 0;
        final boolean includeRecent = (flags & StorageManager.FLAG_INCLUDE_RECENT) != 0;

        // Report all volumes as unmounted until we've recorded that user 0 has unlocked. There
        // are no guarantees that callers will see a consistent view of the volume before that
        // point
        final boolean systemUserUnlocked = isSystemUnlocked(UserHandle.USER_SYSTEM);

        // When the caller is the app actually hosting external storage, we
        // should never attempt to augment the actual storage volume state,
        // otherwise we risk confusing it with race conditions as users go
        // through various unlocked states
        final boolean callerIsMediaStore = UserHandle.isSameApp(Binder.getCallingUid(),
                mMediaStoreAuthorityAppId);

        final boolean userIsDemo;
        final boolean userKeyUnlocked;
        final boolean storagePermission;
        final long token = Binder.clearCallingIdentity();
        try {
            userIsDemo = LocalServices.getService(UserManagerInternal.class)
                    .getUserInfo(userId).isDemo();
            userKeyUnlocked = isUserKeyUnlocked(userId);
            storagePermission = mStorageManagerInternal.hasExternalStorage(uid, packageName);
        } finally {
            Binder.restoreCallingIdentity(token);
        }

        boolean foundPrimary = false;

        final ArrayList<StorageVolume> res = new ArrayList<>();
        final ArraySet<String> resUuids = new ArraySet<>();
        synchronized (mLock) {
            for (int i = 0; i < mVolumes.size(); i++) {
                final String volId = mVolumes.keyAt(i);
                final VolumeInfo vol = mVolumes.valueAt(i);
                switch (vol.getType()) {
                    case VolumeInfo.TYPE_PUBLIC:
                    case VolumeInfo.TYPE_STUB:
                        break;
                    case VolumeInfo.TYPE_EMULATED:
                        if (vol.getMountUserId() == userId) {
                            break;
                        }
                        // Skip if emulated volume not for userId
                    default:
                        continue;
                }

                boolean match = false;
                if (forWrite) {
                    match = vol.isVisibleForWrite(userId);
                } else {
                    match = vol.isVisibleForRead(userId)
                            || (includeInvisible && vol.getPath() != null);
                }
                if (!match) continue;

                boolean reportUnmounted = false;
                if (callerIsMediaStore) {
                    // When the caller is the app actually hosting external storage, we
                    // should never attempt to augment the actual storage volume state,
                    // otherwise we risk confusing it with race conditions as users go
                    // through various unlocked states
                } else if (!systemUserUnlocked) {
                    reportUnmounted = true;
                    Slog.w(TAG, "Reporting " + volId + " unmounted due to system locked");
                } else if ((vol.getType() == VolumeInfo.TYPE_EMULATED) && !userKeyUnlocked) {
                    reportUnmounted = true;
                    Slog.w(TAG, "Reporting " + volId + "unmounted due to " + userId + " locked");
                } else if (!storagePermission && !realState) {
                    Slog.w(TAG, "Reporting " + volId + "unmounted due to missing permissions");
                    reportUnmounted = true;
                }

                final StorageVolume userVol = vol.buildStorageVolume(mContext, userId,
                        reportUnmounted);
                if (vol.isPrimary()) {
                    res.add(0, userVol);
                    foundPrimary = true;
                } else {
                    res.add(userVol);
                }
                resUuids.add(userVol.getUuid());
            }

            if (includeRecent) {
                final long lastWeek = System.currentTimeMillis() - DateUtils.WEEK_IN_MILLIS;
                for (int i = 0; i < mRecords.size(); i++) {
                    final VolumeRecord rec = mRecords.valueAt(i);

                    // Skip if we've already included it above
                    if (resUuids.contains(rec.fsUuid)) continue;

                    // Treat as recent if mounted within the last week
                    if (rec.lastSeenMillis > 0 && rec.lastSeenMillis < lastWeek) {
                        final StorageVolume userVol = rec.buildStorageVolume(mContext);
                        res.add(userVol);
                        resUuids.add(userVol.getUuid());
                    }
                }
            }
        }

        // Synthesize a volume for preloaded media under demo users, so that
        // it's scanned into MediaStore
        if (userIsDemo) {
            final String id = "demo";
            final File path = Environment.getDataPreloadsMediaDirectory();
            final boolean primary = false;
            final boolean removable = false;
            final boolean emulated = true;
            final boolean allowMassStorage = false;
            final long maxFileSize = 0;
            final UserHandle user = new UserHandle(userId);
            final String envState = Environment.MEDIA_MOUNTED_READ_ONLY;
            final String description = mContext.getString(android.R.string.unknownName);

            res.add(new StorageVolume(id, path, path, description, primary, removable,
                    emulated, allowMassStorage, maxFileSize, user, id, envState));
        }

        if (!foundPrimary) {
            Slog.w(TAG, "No primary storage defined yet; hacking together a stub");

            final boolean primaryPhysical = SystemProperties.getBoolean(
                    StorageManager.PROP_PRIMARY_PHYSICAL, false);

            final String id = "stub_primary";
            final File path = Environment.getLegacyExternalStorageDirectory();
            final String description = mContext.getString(android.R.string.unknownName);
            final boolean primary = true;
            final boolean removable = primaryPhysical;
            final boolean emulated = !primaryPhysical;
            final boolean allowMassStorage = false;
            final long maxFileSize = 0L;
            final UserHandle owner = new UserHandle(userId);
            final String uuid = null;
            final String state = Environment.MEDIA_REMOVED;

            res.add(0, new StorageVolume(id, path, path,
                    description, primary, removable, emulated,
                    allowMassStorage, maxFileSize, owner, uuid, state));
        }

        return res.toArray(new StorageVolume[res.size()]);
    }

    @Override
    public DiskInfo[] getDisks() {
        synchronized (mLock) {
            final DiskInfo[] res = new DiskInfo[mDisks.size()];
            for (int i = 0; i < mDisks.size(); i++) {
                res[i] = mDisks.valueAt(i);
            }
            return res;
        }
    }

    @Override
    public VolumeInfo[] getVolumes(int flags) {
        synchronized (mLock) {
            final VolumeInfo[] res = new VolumeInfo[mVolumes.size()];
            for (int i = 0; i < mVolumes.size(); i++) {
                res[i] = mVolumes.valueAt(i);
            }
            return res;
        }
    }

    @Override
    public VolumeRecord[] getVolumeRecords(int flags) {
        synchronized (mLock) {
            final VolumeRecord[] res = new VolumeRecord[mRecords.size()];
            for (int i = 0; i < mRecords.size(); i++) {
                res[i] = mRecords.valueAt(i);
            }
            return res;
        }
    }

    @Override
    public long getCacheQuotaBytes(String volumeUuid, int uid) {
        if (uid != Binder.getCallingUid()) {
            mContext.enforceCallingPermission(android.Manifest.permission.STORAGE_INTERNAL, TAG);
        }
        final long token = Binder.clearCallingIdentity();
        final StorageStatsManager stats = mContext.getSystemService(StorageStatsManager.class);
        try {
            return stats.getCacheQuotaBytes(volumeUuid, uid);
        } finally {
            Binder.restoreCallingIdentity(token);
        }
    }

    @Override
    public long getCacheSizeBytes(String volumeUuid, int uid) {
        if (uid != Binder.getCallingUid()) {
            mContext.enforceCallingPermission(android.Manifest.permission.STORAGE_INTERNAL, TAG);
        }
        final long token = Binder.clearCallingIdentity();
        try {
            return mContext.getSystemService(StorageStatsManager.class)
                    .queryStatsForUid(volumeUuid, uid).getCacheBytes();
        } catch (IOException e) {
            throw new ParcelableException(e);
        } finally {
            Binder.restoreCallingIdentity(token);
        }
    }

    private int adjustAllocateFlags(int flags, int callingUid, String callingPackage) {
        // Require permission to allocate aggressively
        if ((flags & StorageManager.FLAG_ALLOCATE_AGGRESSIVE) != 0) {
            mContext.enforceCallingOrSelfPermission(
                    android.Manifest.permission.ALLOCATE_AGGRESSIVE, TAG);
        }

        // Apps normally can't directly defy reserved space
        flags &= ~StorageManager.FLAG_ALLOCATE_DEFY_ALL_RESERVED;
        flags &= ~StorageManager.FLAG_ALLOCATE_DEFY_HALF_RESERVED;

        // However, if app is actively using the camera, then we're willing to
        // clear up to half of the reserved cache space, since the user might be
        // trying to capture an important memory.
        final AppOpsManager appOps = mContext.getSystemService(AppOpsManager.class);
        final long token = Binder.clearCallingIdentity();
        try {
            if (appOps.isOperationActive(AppOpsManager.OP_CAMERA, callingUid, callingPackage)) {
                Slog.d(TAG, "UID " + callingUid + " is actively using camera;"
                        + " letting them defy reserved cached data");
                flags |= StorageManager.FLAG_ALLOCATE_DEFY_HALF_RESERVED;
            }
        } finally {
            Binder.restoreCallingIdentity(token);
        }

        return flags;
    }

    @Override
    public long getAllocatableBytes(String volumeUuid, int flags, String callingPackage) {
        flags = adjustAllocateFlags(flags, Binder.getCallingUid(), callingPackage);

        final StorageManager storage = mContext.getSystemService(StorageManager.class);
        final StorageStatsManager stats = mContext.getSystemService(StorageStatsManager.class);
        final long token = Binder.clearCallingIdentity();
        try {
            // In general, apps can allocate as much space as they want, except
            // we never let them eat into either the minimum cache space or into
            // the low disk warning space. To avoid user confusion, this logic
            // should be kept in sync with getFreeBytes().
            final File path = storage.findPathForUuid(volumeUuid);

            long usable = 0;
            long lowReserved = 0;
            long fullReserved = 0;
            long cacheClearable = 0;

            if ((flags & StorageManager.FLAG_ALLOCATE_CACHE_ONLY) == 0) {
                usable = path.getUsableSpace();
                lowReserved = storage.getStorageLowBytes(path);
                fullReserved = storage.getStorageFullBytes(path);
            }

            if ((flags & StorageManager.FLAG_ALLOCATE_NON_CACHE_ONLY) == 0
                    && stats.isQuotaSupported(volumeUuid)) {
                final long cacheTotal = stats.getCacheBytes(volumeUuid);
                final long cacheReserved = storage.getStorageCacheBytes(path, flags);
                cacheClearable = Math.max(0, cacheTotal - cacheReserved);
            }

            if ((flags & StorageManager.FLAG_ALLOCATE_AGGRESSIVE) != 0) {
                return Math.max(0, (usable + cacheClearable) - fullReserved);
            } else {
                return Math.max(0, (usable + cacheClearable) - lowReserved);
            }
        } catch (IOException e) {
            throw new ParcelableException(e);
        } finally {
            Binder.restoreCallingIdentity(token);
        }
    }

    @Override
    public void allocateBytes(String volumeUuid, long bytes, int flags, String callingPackage) {
        flags = adjustAllocateFlags(flags, Binder.getCallingUid(), callingPackage);

        final long allocatableBytes = getAllocatableBytes(volumeUuid,
                flags | StorageManager.FLAG_ALLOCATE_NON_CACHE_ONLY, callingPackage);
        if (bytes > allocatableBytes) {
            // If we don't have room without taking cache into account, check to see if we'd have
            // room if we included freeable cache space.
            final long cacheClearable = getAllocatableBytes(volumeUuid,
                    flags | StorageManager.FLAG_ALLOCATE_CACHE_ONLY, callingPackage);
            if (bytes > allocatableBytes + cacheClearable) {
                throw new ParcelableException(new IOException("Failed to allocate " + bytes
                    + " because only " + (allocatableBytes + cacheClearable) + " allocatable"));
            }
        }

        final StorageManager storage = mContext.getSystemService(StorageManager.class);
        final long token = Binder.clearCallingIdentity();
        try {
            // Free up enough disk space to satisfy both the requested allocation
            // and our low disk warning space.
            final File path = storage.findPathForUuid(volumeUuid);
            if ((flags & StorageManager.FLAG_ALLOCATE_AGGRESSIVE) != 0) {
                bytes += storage.getStorageFullBytes(path);
            } else {
                bytes += storage.getStorageLowBytes(path);
            }

            mPmInternal.freeStorage(volumeUuid, bytes, flags);
        } catch (IOException e) {
            throw new ParcelableException(e);
        } finally {
            Binder.restoreCallingIdentity(token);
        }
    }

    private IAppOpsCallback.Stub mAppOpsCallback = new IAppOpsCallback.Stub() {
        @Override
        public void opChanged(int op, int uid, String packageName) throws RemoteException {
            if (!ENABLE_ISOLATED_STORAGE) return;

            int mountMode = getMountMode(uid, packageName);
            boolean isUidActive = LocalServices.getService(ActivityManagerInternal.class)
                    .getUidProcessState(uid) != PROCESS_STATE_NONEXISTENT;

            if (isUidActive) {
                remountUidExternalStorage(uid, mountMode);
            }
        }
    };

    private void addObbStateLocked(ObbState obbState) throws RemoteException {
        final IBinder binder = obbState.getBinder();
        List<ObbState> obbStates = mObbMounts.get(binder);

        if (obbStates == null) {
            obbStates = new ArrayList<ObbState>();
            mObbMounts.put(binder, obbStates);
        } else {
            for (final ObbState o : obbStates) {
                if (o.rawPath.equals(obbState.rawPath)) {
                    throw new IllegalStateException("Attempt to add ObbState twice. "
                            + "This indicates an error in the StorageManagerService logic.");
                }
            }
        }

        obbStates.add(obbState);
        try {
            obbState.link();
        } catch (RemoteException e) {
            /*
             * The binder died before we could link it, so clean up our state
             * and return failure.
             */
            obbStates.remove(obbState);
            if (obbStates.isEmpty()) {
                mObbMounts.remove(binder);
            }

            // Rethrow the error so mountObb can get it
            throw e;
        }

        mObbPathToStateMap.put(obbState.rawPath, obbState);
    }

    private void removeObbStateLocked(ObbState obbState) {
        final IBinder binder = obbState.getBinder();
        final List<ObbState> obbStates = mObbMounts.get(binder);
        if (obbStates != null) {
            if (obbStates.remove(obbState)) {
                obbState.unlink();
            }
            if (obbStates.isEmpty()) {
                mObbMounts.remove(binder);
            }
        }

        mObbPathToStateMap.remove(obbState.rawPath);
    }

    private class ObbActionHandler extends Handler {

        ObbActionHandler(Looper l) {
            super(l);
        }

        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case OBB_RUN_ACTION: {
                    final ObbAction action = (ObbAction) msg.obj;

                    if (DEBUG_OBB)
                        Slog.i(TAG, "OBB_RUN_ACTION: " + action.toString());

                    action.execute(this);
                    break;
                }
                case OBB_FLUSH_MOUNT_STATE: {
                    final String path = (String) msg.obj;

                    if (DEBUG_OBB)
                        Slog.i(TAG, "Flushing all OBB state for path " + path);

                    synchronized (mObbMounts) {
                        final List<ObbState> obbStatesToRemove = new LinkedList<ObbState>();

                        final Iterator<ObbState> i = mObbPathToStateMap.values().iterator();
                        while (i.hasNext()) {
                            final ObbState state = i.next();

                            /*
                             * If this entry's source file is in the volume path
                             * that got unmounted, remove it because it's no
                             * longer valid.
                             */
                            if (state.canonicalPath.startsWith(path)) {
                                obbStatesToRemove.add(state);
                            }
                        }

                        for (final ObbState obbState : obbStatesToRemove) {
                            if (DEBUG_OBB)
                                Slog.i(TAG, "Removing state for " + obbState.rawPath);

                            removeObbStateLocked(obbState);

                            try {
                                obbState.token.onObbResult(obbState.rawPath, obbState.nonce,
                                        OnObbStateChangeListener.UNMOUNTED);
                            } catch (RemoteException e) {
                                Slog.i(TAG, "Couldn't send unmount notification for  OBB: "
                                        + obbState.rawPath);
                            }
                        }
                    }
                    break;
                }
            }
        }
    }

    private static class ObbException extends Exception {
        public final int status;

        public ObbException(int status, String message) {
            super(message);
            this.status = status;
        }

        public ObbException(int status, Throwable cause) {
            super(cause.getMessage(), cause);
            this.status = status;
        }
    }

    abstract class ObbAction {

        ObbState mObbState;

        ObbAction(ObbState obbState) {
            mObbState = obbState;
        }

        public void execute(ObbActionHandler handler) {
            try {
                if (DEBUG_OBB)
                    Slog.i(TAG, "Starting to execute action: " + toString());
                handleExecute();
            } catch (ObbException e) {
                notifyObbStateChange(e);
            }
        }

        abstract void handleExecute() throws ObbException;

        protected void notifyObbStateChange(ObbException e) {
            Slog.w(TAG, e);
            notifyObbStateChange(e.status);
        }

        protected void notifyObbStateChange(int status) {
            if (mObbState == null || mObbState.token == null) {
                return;
            }

            try {
                mObbState.token.onObbResult(mObbState.rawPath, mObbState.nonce, status);
            } catch (RemoteException e) {
                Slog.w(TAG, "StorageEventListener went away while calling onObbStateChanged");
            }
        }
    }

    class MountObbAction extends ObbAction {
        private final String mKey;
        private final int mCallingUid;
        private ObbInfo mObbInfo;

        MountObbAction(ObbState obbState, String key, int callingUid, ObbInfo obbInfo) {
            super(obbState);
            mKey = key;
            mCallingUid = callingUid;
            mObbInfo = obbInfo;
        }

        @Override
        public void handleExecute() throws ObbException {
            warnOnNotMounted();

            if (!isUidOwnerOfPackageOrSystem(mObbInfo.packageName, mCallingUid)) {
                throw new ObbException(ERROR_PERMISSION_DENIED, "Denied attempt to mount OBB "
                        + mObbInfo.filename + " which is owned by " + mObbInfo.packageName);
            }

            final boolean isMounted;
            synchronized (mObbMounts) {
                isMounted = mObbPathToStateMap.containsKey(mObbState.rawPath);
            }
            if (isMounted) {
                throw new ObbException(ERROR_ALREADY_MOUNTED,
                        "Attempt to mount OBB which is already mounted: " + mObbInfo.filename);
            }

            final String hashedKey;
            final String binderKey;
            if (mKey == null) {
                hashedKey = "none";
                binderKey = "";
            } else {
                try {
                    SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");

                    KeySpec ks = new PBEKeySpec(mKey.toCharArray(), mObbInfo.salt,
                            PBKDF2_HASH_ROUNDS, CRYPTO_ALGORITHM_KEY_SIZE);
                    SecretKey key = factory.generateSecret(ks);
                    BigInteger bi = new BigInteger(key.getEncoded());
                    hashedKey = bi.toString(16);
                    binderKey = hashedKey;
                } catch (GeneralSecurityException e) {
                    throw new ObbException(ERROR_INTERNAL, e);
                }
            }

            try {
                mObbState.volId = mVold.createObb(mObbState.canonicalPath, binderKey,
                        mObbState.ownerGid);
                mVold.mount(mObbState.volId, 0, -1, null);

                if (DEBUG_OBB)
                    Slog.d(TAG, "Successfully mounted OBB " + mObbState.canonicalPath);

                synchronized (mObbMounts) {
                    addObbStateLocked(mObbState);
                }

                notifyObbStateChange(MOUNTED);
            } catch (Exception e) {
                throw new ObbException(ERROR_COULD_NOT_MOUNT, e);
            }
        }

        @Override
        public String toString() {
            StringBuilder sb = new StringBuilder();
            sb.append("MountObbAction{");
            sb.append(mObbState);
            sb.append('}');
            return sb.toString();
        }
    }

    class UnmountObbAction extends ObbAction {
        private final boolean mForceUnmount;

        UnmountObbAction(ObbState obbState, boolean force) {
            super(obbState);
            mForceUnmount = force;
        }

        @Override
        public void handleExecute() throws ObbException {
            warnOnNotMounted();

            final ObbState existingState;
            synchronized (mObbMounts) {
                existingState = mObbPathToStateMap.get(mObbState.rawPath);
            }

            if (existingState == null) {
                throw new ObbException(ERROR_NOT_MOUNTED, "Missing existingState");
            }

            if (existingState.ownerGid != mObbState.ownerGid) {
                notifyObbStateChange(new ObbException(ERROR_PERMISSION_DENIED,
                        "Permission denied to unmount OBB " + existingState.rawPath
                                + " (owned by GID " + existingState.ownerGid + ")"));
                return;
            }

            try {
                mVold.unmount(mObbState.volId);
                mVold.destroyObb(mObbState.volId);
                mObbState.volId = null;

                synchronized (mObbMounts) {
                    removeObbStateLocked(existingState);
                }

                notifyObbStateChange(UNMOUNTED);
            } catch (Exception e) {
                throw new ObbException(ERROR_COULD_NOT_UNMOUNT, e);
            }
        }

        @Override
        public String toString() {
            StringBuilder sb = new StringBuilder();
            sb.append("UnmountObbAction{");
            sb.append(mObbState);
            sb.append(",force=");
            sb.append(mForceUnmount);
            sb.append('}');
            return sb.toString();
        }
    }

    private void dispatchOnStatus(IVoldTaskListener listener, int status,
            PersistableBundle extras) {
        if (listener != null) {
            try {
                listener.onStatus(status, extras);
            } catch (RemoteException ignored) {
            }
        }
    }

    private void dispatchOnFinished(IVoldTaskListener listener, int status,
            PersistableBundle extras) {
        if (listener != null) {
            try {
                listener.onFinished(status, extras);
            } catch (RemoteException ignored) {
            }
        }
    }

    private int getMountMode(int uid, String packageName) {
        final int mode = getMountModeInternal(uid, packageName);
        if (LOCAL_LOGV) {
            Slog.v(TAG, "Resolved mode " + mode + " for " + packageName + "/"
                    + UserHandle.formatUid(uid));
        }
        return mode;
    }

    private int getMountModeInternal(int uid, String packageName) {
        try {
            // Get some easy cases out of the way first
            if (Process.isIsolated(uid)) {
                return Zygote.MOUNT_EXTERNAL_NONE;
            }

            final String[] packagesForUid = mIPackageManager.getPackagesForUid(uid);
            if (ArrayUtils.isEmpty(packagesForUid)) {
                // It's possible the package got uninstalled already, so just ignore.
                return Zygote.MOUNT_EXTERNAL_NONE;
            }
            if (packageName == null) {
                packageName = packagesForUid[0];
            }

            if (mPmInternal.isInstantApp(packageName, UserHandle.getUserId(uid))) {
                return Zygote.MOUNT_EXTERNAL_NONE;
            }

            if (mIsFuseEnabled && mStorageManagerInternal.isExternalStorageService(uid)) {
                // Determine if caller requires pass_through mount; note that we do this for
                // all processes that share a UID with MediaProvider; but this is fine, since
                // those processes anyway share the same rights as MediaProvider.
                return Zygote.MOUNT_EXTERNAL_PASS_THROUGH;
            }

            if (mIsFuseEnabled && (mDownloadsAuthorityAppId == UserHandle.getAppId(uid)
                    || mExternalStorageAuthorityAppId == UserHandle.getAppId(uid))) {
                // DownloadManager can write in app-private directories on behalf of apps;
                // give it write access to Android/
                // ExternalStorageProvider can access Android/{data,obb} dirs in managed mode
                return Zygote.MOUNT_EXTERNAL_ANDROID_WRITABLE;
            }

            final boolean hasMtp = mIPackageManager.checkUidPermission(ACCESS_MTP, uid) ==
                    PERMISSION_GRANTED;
            if (mIsFuseEnabled && hasMtp) {
                ApplicationInfo ai = mIPackageManager.getApplicationInfo(packageName,
                        0, UserHandle.getUserId(uid));
                if (ai != null && ai.isSignedWithPlatformKey()) {
                    // Platform processes hosting the MTP server should be able to write in Android/
                    return Zygote.MOUNT_EXTERNAL_ANDROID_WRITABLE;
                }
            }

            // Determine if caller is holding runtime permission
            final boolean hasRead = StorageManager.checkPermissionAndCheckOp(mContext, false, 0,
                    uid, packageName, READ_EXTERNAL_STORAGE, OP_READ_EXTERNAL_STORAGE);
            final boolean hasWrite = StorageManager.checkPermissionAndCheckOp(mContext, false, 0,
                    uid, packageName, WRITE_EXTERNAL_STORAGE, OP_WRITE_EXTERNAL_STORAGE);

            // We're only willing to give out broad access if they also hold
            // runtime permission; this is a firm CDD requirement
            final boolean hasFull = mIPackageManager.checkUidPermission(WRITE_MEDIA_STORAGE,
                    uid) == PERMISSION_GRANTED;
            if (hasFull && hasWrite) {
                return Zygote.MOUNT_EXTERNAL_FULL;
            }

            // We're only willing to give out installer access if they also hold
            // runtime permission; this is a firm CDD requirement
            final boolean hasInstall = mIPackageManager.checkUidPermission(INSTALL_PACKAGES,
                    uid) == PERMISSION_GRANTED;
            boolean hasInstallOp = false;
            // OP_REQUEST_INSTALL_PACKAGES is granted/denied per package but vold can't
            // update mountpoints of a specific package. So, check the appop for all packages
            // sharing the uid and allow same level of storage access for all packages even if
            // one of the packages has the appop granted.
            for (String uidPackageName : packagesForUid) {
                if (mIAppOpsService.checkOperation(
                        OP_REQUEST_INSTALL_PACKAGES, uid, uidPackageName) == MODE_ALLOWED) {
                    hasInstallOp = true;
                    break;
                }
            }
            if ((hasInstall || hasInstallOp) && hasWrite) {
                return Zygote.MOUNT_EXTERNAL_INSTALLER;
            }

            // Otherwise we're willing to give out sandboxed or non-sandboxed if
            // they hold the runtime permission
            boolean hasLegacy = mIAppOpsService.checkOperation(OP_LEGACY_STORAGE,
                    uid, packageName) == MODE_ALLOWED;

            if (hasLegacy && hasWrite) {
                return Zygote.MOUNT_EXTERNAL_WRITE;
            } else if (hasLegacy && hasRead) {
                return Zygote.MOUNT_EXTERNAL_READ;
            } else {
                return Zygote.MOUNT_EXTERNAL_DEFAULT;
            }
        } catch (RemoteException e) {
            // Should not happen
        }
        return Zygote.MOUNT_EXTERNAL_NONE;
    }

    private static class Callbacks extends Handler {
        private static final int MSG_STORAGE_STATE_CHANGED = 1;
        private static final int MSG_VOLUME_STATE_CHANGED = 2;
        private static final int MSG_VOLUME_RECORD_CHANGED = 3;
        private static final int MSG_VOLUME_FORGOTTEN = 4;
        private static final int MSG_DISK_SCANNED = 5;
        private static final int MSG_DISK_DESTROYED = 6;

        private final RemoteCallbackList<IStorageEventListener>
                mCallbacks = new RemoteCallbackList<>();

        public Callbacks(Looper looper) {
            super(looper);
        }

        public void register(IStorageEventListener callback) {
            mCallbacks.register(callback);
        }

        public void unregister(IStorageEventListener callback) {
            mCallbacks.unregister(callback);
        }

        @Override
        public void handleMessage(Message msg) {
            final SomeArgs args = (SomeArgs) msg.obj;
            final int n = mCallbacks.beginBroadcast();
            for (int i = 0; i < n; i++) {
                final IStorageEventListener callback = mCallbacks.getBroadcastItem(i);
                try {
                    invokeCallback(callback, msg.what, args);
                } catch (RemoteException ignored) {
                }
            }
            mCallbacks.finishBroadcast();
            args.recycle();
        }

        private void invokeCallback(IStorageEventListener callback, int what, SomeArgs args)
                throws RemoteException {
            switch (what) {
                case MSG_STORAGE_STATE_CHANGED: {
                    callback.onStorageStateChanged((String) args.arg1, (String) args.arg2,
                            (String) args.arg3);
                    break;
                }
                case MSG_VOLUME_STATE_CHANGED: {
                    callback.onVolumeStateChanged((VolumeInfo) args.arg1, args.argi2, args.argi3);
                    break;
                }
                case MSG_VOLUME_RECORD_CHANGED: {
                    callback.onVolumeRecordChanged((VolumeRecord) args.arg1);
                    break;
                }
                case MSG_VOLUME_FORGOTTEN: {
                    callback.onVolumeForgotten((String) args.arg1);
                    break;
                }
                case MSG_DISK_SCANNED: {
                    callback.onDiskScanned((DiskInfo) args.arg1, args.argi2);
                    break;
                }
                case MSG_DISK_DESTROYED: {
                    callback.onDiskDestroyed((DiskInfo) args.arg1);
                    break;
                }
            }
        }

        private void notifyStorageStateChanged(String path, String oldState, String newState) {
            final SomeArgs args = SomeArgs.obtain();
            args.arg1 = path;
            args.arg2 = oldState;
            args.arg3 = newState;
            obtainMessage(MSG_STORAGE_STATE_CHANGED, args).sendToTarget();
        }

        private void notifyVolumeStateChanged(VolumeInfo vol, int oldState, int newState) {
            final SomeArgs args = SomeArgs.obtain();
            args.arg1 = vol.clone();
            args.argi2 = oldState;
            args.argi3 = newState;
            obtainMessage(MSG_VOLUME_STATE_CHANGED, args).sendToTarget();
        }

        private void notifyVolumeRecordChanged(VolumeRecord rec) {
            final SomeArgs args = SomeArgs.obtain();
            args.arg1 = rec.clone();
            obtainMessage(MSG_VOLUME_RECORD_CHANGED, args).sendToTarget();
        }

        private void notifyVolumeForgotten(String fsUuid) {
            final SomeArgs args = SomeArgs.obtain();
            args.arg1 = fsUuid;
            obtainMessage(MSG_VOLUME_FORGOTTEN, args).sendToTarget();
        }

        private void notifyDiskScanned(DiskInfo disk, int volumeCount) {
            final SomeArgs args = SomeArgs.obtain();
            args.arg1 = disk.clone();
            args.argi2 = volumeCount;
            obtainMessage(MSG_DISK_SCANNED, args).sendToTarget();
        }

        private void notifyDiskDestroyed(DiskInfo disk) {
            final SomeArgs args = SomeArgs.obtain();
            args.arg1 = disk.clone();
            obtainMessage(MSG_DISK_DESTROYED, args).sendToTarget();
        }
    }

    @Override
    protected void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
        if (!DumpUtils.checkDumpPermission(mContext, TAG, writer)) return;

        final IndentingPrintWriter pw = new IndentingPrintWriter(writer, "  ", 160);
        synchronized (mLock) {
            pw.println("Disks:");
            pw.increaseIndent();
            for (int i = 0; i < mDisks.size(); i++) {
                final DiskInfo disk = mDisks.valueAt(i);
                disk.dump(pw);
            }
            pw.decreaseIndent();

            pw.println();
            pw.println("Volumes:");
            pw.increaseIndent();
            for (int i = 0; i < mVolumes.size(); i++) {
                final VolumeInfo vol = mVolumes.valueAt(i);
                if (VolumeInfo.ID_PRIVATE_INTERNAL.equals(vol.id)) continue;
                vol.dump(pw);
            }
            pw.decreaseIndent();

            pw.println();
            pw.println("Records:");
            pw.increaseIndent();
            for (int i = 0; i < mRecords.size(); i++) {
                final VolumeRecord note = mRecords.valueAt(i);
                note.dump(pw);
            }
            pw.decreaseIndent();

            pw.println();
            pw.println("Primary storage UUID: " + mPrimaryStorageUuid);

            pw.println();
            final Pair<String, Long> pair = StorageManager.getPrimaryStoragePathAndSize();
            if (pair == null) {
                pw.println("Internal storage total size: N/A");
            } else {
                pw.print("Internal storage (");
                pw.print(pair.first);
                pw.print(") total size: ");
                pw.print(pair.second);
                pw.print(" (");
                pw.print(DataUnit.MEBIBYTES.toBytes(pair.second));
                pw.println(" MiB)");
            }

            pw.println();
            pw.println("Local unlocked users: " + mLocalUnlockedUsers);
            pw.println("System unlocked users: " + Arrays.toString(mSystemUnlockedUsers));

            final ContentResolver cr = mContext.getContentResolver();
            pw.println();
            pw.println("Isolated storage, local feature flag: "
                    + Settings.Global.getInt(cr, Settings.Global.ISOLATED_STORAGE_LOCAL, 0));
            pw.println("Isolated storage, remote feature flag: "
                    + Settings.Global.getInt(cr, Settings.Global.ISOLATED_STORAGE_REMOTE, 0));
            pw.println("Isolated storage, resolved: " + StorageManager.hasIsolatedStorage());
            pw.println("Forced scoped storage app list: "
                    + DeviceConfig.getProperty(DeviceConfig.NAMESPACE_STORAGE_NATIVE_BOOT,
                    PROP_FORCED_SCOPED_STORAGE_WHITELIST));
            pw.println("isAutomotive:" + mIsAutomotive);
        }

        synchronized (mObbMounts) {
            pw.println();
            pw.println("mObbMounts:");
            pw.increaseIndent();
            final Iterator<Entry<IBinder, List<ObbState>>> binders = mObbMounts.entrySet()
                    .iterator();
            while (binders.hasNext()) {
                Entry<IBinder, List<ObbState>> e = binders.next();
                pw.println(e.getKey() + ":");
                pw.increaseIndent();
                final List<ObbState> obbStates = e.getValue();
                for (final ObbState obbState : obbStates) {
                    pw.println(obbState);
                }
                pw.decreaseIndent();
            }
            pw.decreaseIndent();

            pw.println();
            pw.println("mObbPathToStateMap:");
            pw.increaseIndent();
            final Iterator<Entry<String, ObbState>> maps =
                    mObbPathToStateMap.entrySet().iterator();
            while (maps.hasNext()) {
                final Entry<String, ObbState> e = maps.next();
                pw.print(e.getKey());
                pw.print(" -> ");
                pw.println(e.getValue());
            }
            pw.decreaseIndent();
        }

        pw.println();
        pw.print("Last maintenance: ");
        pw.println(TimeUtils.formatForLogging(mLastMaintenance));
    }

    /** {@inheritDoc} */
    @Override
    public void monitor() {
        try {
            mVold.monitor();
        } catch (Exception e) {
            Slog.wtf(TAG, e);
        }
    }

    private final class StorageManagerInternalImpl extends StorageManagerInternal {
        // Not guarded by a lock.
        private final CopyOnWriteArrayList<ExternalStorageMountPolicy> mPolicies =
                new CopyOnWriteArrayList<>();

        @GuardedBy("mResetListeners")
        private final List<StorageManagerInternal.ResetListener> mResetListeners =
                new ArrayList<>();

        @Override
        public void addExternalStoragePolicy(ExternalStorageMountPolicy policy) {
            // No locking - CopyOnWriteArrayList
            mPolicies.add(policy);
        }

        /**
         * Check if fuse is running in target user, if it's running then setup its storage dirs.
         * Return true if storage dirs are mounted.
         */
        @Override
        public boolean prepareStorageDirs(int userId, Set<String> packageList,
                String processName) {
            synchronized (mLock) {
                if (!mFuseMountedUser.contains(userId)) {
                    Slog.w(TAG, "User " + userId + " is not unlocked yet so skip mounting obb");
                    return false;
                }
            }
            try {
                final IVold vold = IVold.Stub.asInterface(
                        ServiceManager.getServiceOrThrow("vold"));
                for (String pkg : packageList) {
                    final String packageObbDir =
                            String.format("/storage/emulated/%d/Android/obb/%s/", userId, pkg);
                    final String packageDataDir =
                            String.format("/storage/emulated/%d/Android/data/%s/",
                                    userId, pkg);

                    // Create package obb and data dir if it doesn't exist.
                    int appUid = UserHandle.getUid(userId, mPmInternal.getPackage(pkg).getUid());
                    File file = new File(packageObbDir);
                    if (!file.exists()) {
                        vold.setupAppDir(packageObbDir, appUid);
                    }
                    file = new File(packageDataDir);
                    if (!file.exists()) {
                        vold.setupAppDir(packageDataDir, appUid);
                    }
                }
            } catch (ServiceManager.ServiceNotFoundException | RemoteException e) {
                Slog.e(TAG, "Unable to create obb and data directories for " + processName,e);
                return false;
            }
            return true;
        }

        @Override
        public void onExternalStoragePolicyChanged(int uid, String packageName) {
            final int mountMode = getExternalStorageMountMode(uid, packageName);
            remountUidExternalStorage(uid, mountMode);
        }

        @Override
        public int getExternalStorageMountMode(int uid, String packageName) {
            if (ENABLE_ISOLATED_STORAGE) {
                return getMountMode(uid, packageName);
            }
            try {
                if (packageName == null) {
                    final String[] packagesForUid = mIPackageManager.getPackagesForUid(uid);
                    packageName = packagesForUid[0];
                }
            } catch (RemoteException e) {
                // Should not happen - same process
            }
            // No locking - CopyOnWriteArrayList
            int mountMode = Integer.MAX_VALUE;
            for (ExternalStorageMountPolicy policy : mPolicies) {
                final int policyMode = policy.getMountMode(uid, packageName);
                if (policyMode == Zygote.MOUNT_EXTERNAL_NONE) {
                    return Zygote.MOUNT_EXTERNAL_NONE;
                }
                mountMode = Math.min(mountMode, policyMode);
            }
            if (mountMode == Integer.MAX_VALUE) {
                return Zygote.MOUNT_EXTERNAL_NONE;
            }
            return mountMode;
        }

        @Override
        public void addResetListener(StorageManagerInternal.ResetListener listener) {
            synchronized (mResetListeners) {
                mResetListeners.add(listener);
            }
        }

        public void onReset(IVold vold) {
            synchronized (mResetListeners) {
                for (StorageManagerInternal.ResetListener listener : mResetListeners) {
                    listener.onReset(vold);
                }
            }
        }

        @Override
        public void resetUser(int userId) {
            // TODO(b/145931219): ideally, we only reset storage for the user in question,
            // but for now, reset everything.
            mHandler.obtainMessage(H_RESET).sendToTarget();
        }

        @Override
        public boolean hasLegacyExternalStorage(int uid) {
            synchronized (mLock) {
                return mUidsWithLegacyExternalStorage.contains(uid);
            }
        }

        @Override
        public void prepareAppDataAfterInstall(String packageName, int uid) {
            int userId = UserHandle.getUserId(uid);
            final Environment.UserEnvironment userEnv = new Environment.UserEnvironment(userId);

            // The installer may have downloaded OBBs for this newly installed application;
            // make sure the OBB dir for the application is setup correctly, if it exists.
            File[] packageObbDirs = userEnv.buildExternalStorageAppObbDirs(packageName);
            for (File packageObbDir : packageObbDirs) {
                try {
                    mVold.fixupAppDir(packageObbDir.getCanonicalPath() + "/", uid);
                } catch (IOException e) {
                    Log.e(TAG, "Failed to get canonical path for " + packageName);
                } catch (RemoteException | ServiceSpecificException e) {
                    // TODO(b/149975102) there is a known case where this fails, when a new
                    // user is setup and we try to fixup app dirs for some existing apps.
                    // For now catch the exception and don't crash.
                    Log.e(TAG, "Failed to fixup app dir for " + packageName, e);
                }
            }
        }

        @Override
        public boolean isExternalStorageService(int uid) {
            return mMediaStoreAuthorityAppId == UserHandle.getAppId(uid);
        }

        public boolean hasExternalStorage(int uid, String packageName) {
            // No need to check for system uid. This avoids a deadlock between
            // PackageManagerService and AppOpsService.
            if (uid == Process.SYSTEM_UID) {
                return true;
            }
            if (ENABLE_ISOLATED_STORAGE) {
                return getMountMode(uid, packageName) != Zygote.MOUNT_EXTERNAL_NONE;
            }
            // No locking - CopyOnWriteArrayList
            for (ExternalStorageMountPolicy policy : mPolicies) {
                final boolean policyHasStorage = policy.hasExternalStorage(uid, packageName);
                if (!policyHasStorage) {
                    return false;
                }
            }
            return true;
        }

        private void killAppForOpChange(int code, int uid) {
            final IActivityManager am = ActivityManager.getService();
            try {
                am.killUid(UserHandle.getAppId(uid), UserHandle.USER_ALL,
                        AppOpsManager.opToName(code) + " changed.");
            } catch (RemoteException e) {
            }
        }

        public void onAppOpsChanged(int code, int uid, @Nullable String packageName, int mode) {
            final long token = Binder.clearCallingIdentity();
            try {
                if (mIsFuseEnabled) {
                    // When using FUSE, we may need to kill the app if the op changes
                    switch(code) {
                        case OP_REQUEST_INSTALL_PACKAGES:
                            // Always kill regardless of op change, to remount apps /storage
                            killAppForOpChange(code, uid);
                            return;
                        case OP_MANAGE_EXTERNAL_STORAGE:
                            if (mode != MODE_ALLOWED) {
                                // Only kill if op is denied, to lose external_storage gid
                                // Killing when op is granted to pickup the gid automatically,
                                // results in a bad UX, especially since the gid only gives access
                                // to unreliable volumes, USB OTGs that are rarely mounted. The app
                                // will get the external_storage gid on next organic restart.
                                killAppForOpChange(code, uid);
                            }
                            return;
                        case OP_LEGACY_STORAGE:
                            updateLegacyStorageApps(packageName, uid, mode == MODE_ALLOWED);
                            return;
                    }
                }

                if (mode == MODE_ALLOWED && (code == OP_READ_EXTERNAL_STORAGE
                                || code == OP_WRITE_EXTERNAL_STORAGE
                                || code == OP_REQUEST_INSTALL_PACKAGES)) {
                    final UserManagerInternal userManagerInternal =
                            LocalServices.getService(UserManagerInternal.class);
                    if (userManagerInternal.isUserInitialized(UserHandle.getUserId(uid))) {
                        onExternalStoragePolicyChanged(uid, packageName);
                    }
                }
            } finally {
                Binder.restoreCallingIdentity(token);
            }
        }
    }
}
