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