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