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