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