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