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