• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2007 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.server;
18 
19 import static android.Manifest.permission.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         connect();
1561     }
1562 
connect()1563     private void connect() {
1564         IBinder binder = ServiceManager.getService("storaged");
1565         if (binder != null) {
1566             try {
1567                 binder.linkToDeath(new DeathRecipient() {
1568                     @Override
1569                     public void binderDied() {
1570                         Slog.w(TAG, "storaged died; reconnecting");
1571                         mStoraged = null;
1572                         connect();
1573                     }
1574                 }, 0);
1575             } catch (RemoteException e) {
1576                 binder = null;
1577             }
1578         }
1579 
1580         if (binder != null) {
1581             mStoraged = IStoraged.Stub.asInterface(binder);
1582         } else {
1583             Slog.w(TAG, "storaged not found; trying again");
1584         }
1585 
1586         binder = ServiceManager.getService("vold");
1587         if (binder != null) {
1588             try {
1589                 binder.linkToDeath(new DeathRecipient() {
1590                     @Override
1591                     public void binderDied() {
1592                         Slog.w(TAG, "vold died; reconnecting");
1593                         mVold = null;
1594                         connect();
1595                     }
1596                 }, 0);
1597             } catch (RemoteException e) {
1598                 binder = null;
1599             }
1600         }
1601 
1602         if (binder != null) {
1603             mVold = IVold.Stub.asInterface(binder);
1604             try {
1605                 mVold.setListener(mListener);
1606             } catch (RemoteException e) {
1607                 mVold = null;
1608                 Slog.w(TAG, "vold listener rejected; trying again", e);
1609             }
1610         } else {
1611             Slog.w(TAG, "vold not found; trying again");
1612         }
1613 
1614         if (mStoraged == null || mVold == null) {
1615             BackgroundThread.getHandler().postDelayed(() -> {
1616                 connect();
1617             }, DateUtils.SECOND_IN_MILLIS);
1618         } else {
1619             onDaemonConnected();
1620         }
1621     }
1622 
servicesReady()1623     private void servicesReady() {
1624         mPmInternal = LocalServices.getService(PackageManagerInternal.class);
1625 
1626         mIPackageManager = IPackageManager.Stub.asInterface(
1627                 ServiceManager.getService("package"));
1628         mIAppOpsService = IAppOpsService.Stub.asInterface(
1629                 ServiceManager.getService(Context.APP_OPS_SERVICE));
1630         try {
1631             mIAppOpsService.startWatchingMode(OP_REQUEST_INSTALL_PACKAGES, null, mAppOpsCallback);
1632             mIAppOpsService.startWatchingMode(OP_LEGACY_STORAGE, null, mAppOpsCallback);
1633         } catch (RemoteException e) {
1634         }
1635     }
1636 
getLastAccessTime(AppOpsManager manager, int uid, String packageName, int[] ops)1637     private static long getLastAccessTime(AppOpsManager manager,
1638             int uid, String packageName, int[] ops) {
1639         long maxTime = 0;
1640         final List<AppOpsManager.PackageOps> pkgs = manager.getOpsForPackage(uid, packageName, ops);
1641         for (AppOpsManager.PackageOps pkg : CollectionUtils.emptyIfNull(pkgs)) {
1642             for (AppOpsManager.OpEntry op : CollectionUtils.emptyIfNull(pkg.getOps())) {
1643                 maxTime = Math.max(maxTime, op.getLastAccessTime(
1644                     AppOpsManager.OP_FLAGS_ALL_TRUSTED));
1645             }
1646         }
1647         return maxTime;
1648     }
1649 
systemReady()1650     private void systemReady() {
1651         LocalServices.getService(ActivityTaskManagerInternal.class)
1652                 .registerScreenObserver(this);
1653 
1654         mHandler.obtainMessage(H_SYSTEM_READY).sendToTarget();
1655     }
1656 
bootCompleted()1657     private void bootCompleted() {
1658         mBootCompleted = true;
1659         mHandler.obtainMessage(H_BOOT_COMPLETED).sendToTarget();
1660     }
1661 
handleBootCompleted()1662     private void handleBootCompleted() {
1663         initIfBootedAndConnected();
1664         resetIfBootedAndConnected();
1665     }
1666 
getDefaultPrimaryStorageUuid()1667     private String getDefaultPrimaryStorageUuid() {
1668         if (SystemProperties.getBoolean(StorageManager.PROP_PRIMARY_PHYSICAL, false)) {
1669             return StorageManager.UUID_PRIMARY_PHYSICAL;
1670         } else {
1671             return StorageManager.UUID_PRIVATE_INTERNAL;
1672         }
1673     }
1674 
1675     @GuardedBy("mLock")
readSettingsLocked()1676     private void readSettingsLocked() {
1677         mRecords.clear();
1678         mPrimaryStorageUuid = getDefaultPrimaryStorageUuid();
1679 
1680         FileInputStream fis = null;
1681         try {
1682             fis = mSettingsFile.openRead();
1683             final XmlPullParser in = Xml.newPullParser();
1684             in.setInput(fis, StandardCharsets.UTF_8.name());
1685 
1686             int type;
1687             while ((type = in.next()) != END_DOCUMENT) {
1688                 if (type == START_TAG) {
1689                     final String tag = in.getName();
1690                     if (TAG_VOLUMES.equals(tag)) {
1691                         final int version = readIntAttribute(in, ATTR_VERSION, VERSION_INIT);
1692                         final boolean primaryPhysical = SystemProperties.getBoolean(
1693                                 StorageManager.PROP_PRIMARY_PHYSICAL, false);
1694                         final boolean validAttr = (version >= VERSION_FIX_PRIMARY)
1695                                 || (version >= VERSION_ADD_PRIMARY && !primaryPhysical);
1696                         if (validAttr) {
1697                             mPrimaryStorageUuid = readStringAttribute(in,
1698                                     ATTR_PRIMARY_STORAGE_UUID);
1699                         }
1700                     } else if (TAG_VOLUME.equals(tag)) {
1701                         final VolumeRecord rec = readVolumeRecord(in);
1702                         mRecords.put(rec.fsUuid, rec);
1703                     }
1704                 }
1705             }
1706         } catch (FileNotFoundException e) {
1707             // Missing metadata is okay, probably first boot
1708         } catch (IOException e) {
1709             Slog.wtf(TAG, "Failed reading metadata", e);
1710         } catch (XmlPullParserException e) {
1711             Slog.wtf(TAG, "Failed reading metadata", e);
1712         } finally {
1713             IoUtils.closeQuietly(fis);
1714         }
1715     }
1716 
1717     @GuardedBy("mLock")
writeSettingsLocked()1718     private void writeSettingsLocked() {
1719         FileOutputStream fos = null;
1720         try {
1721             fos = mSettingsFile.startWrite();
1722 
1723             XmlSerializer out = new FastXmlSerializer();
1724             out.setOutput(fos, StandardCharsets.UTF_8.name());
1725             out.startDocument(null, true);
1726             out.startTag(null, TAG_VOLUMES);
1727             writeIntAttribute(out, ATTR_VERSION, VERSION_FIX_PRIMARY);
1728             writeStringAttribute(out, ATTR_PRIMARY_STORAGE_UUID, mPrimaryStorageUuid);
1729             final int size = mRecords.size();
1730             for (int i = 0; i < size; i++) {
1731                 final VolumeRecord rec = mRecords.valueAt(i);
1732                 writeVolumeRecord(out, rec);
1733             }
1734             out.endTag(null, TAG_VOLUMES);
1735             out.endDocument();
1736 
1737             mSettingsFile.finishWrite(fos);
1738         } catch (IOException e) {
1739             if (fos != null) {
1740                 mSettingsFile.failWrite(fos);
1741             }
1742         }
1743     }
1744 
readVolumeRecord(XmlPullParser in)1745     public static VolumeRecord readVolumeRecord(XmlPullParser in) throws IOException {
1746         final int type = readIntAttribute(in, ATTR_TYPE);
1747         final String fsUuid = readStringAttribute(in, ATTR_FS_UUID);
1748         final VolumeRecord meta = new VolumeRecord(type, fsUuid);
1749         meta.partGuid = readStringAttribute(in, ATTR_PART_GUID);
1750         meta.nickname = readStringAttribute(in, ATTR_NICKNAME);
1751         meta.userFlags = readIntAttribute(in, ATTR_USER_FLAGS);
1752         meta.createdMillis = readLongAttribute(in, ATTR_CREATED_MILLIS, 0);
1753         meta.lastSeenMillis = readLongAttribute(in, ATTR_LAST_SEEN_MILLIS, 0);
1754         meta.lastTrimMillis = readLongAttribute(in, ATTR_LAST_TRIM_MILLIS, 0);
1755         meta.lastBenchMillis = readLongAttribute(in, ATTR_LAST_BENCH_MILLIS, 0);
1756         return meta;
1757     }
1758 
writeVolumeRecord(XmlSerializer out, VolumeRecord rec)1759     public static void writeVolumeRecord(XmlSerializer out, VolumeRecord rec) throws IOException {
1760         out.startTag(null, TAG_VOLUME);
1761         writeIntAttribute(out, ATTR_TYPE, rec.type);
1762         writeStringAttribute(out, ATTR_FS_UUID, rec.fsUuid);
1763         writeStringAttribute(out, ATTR_PART_GUID, rec.partGuid);
1764         writeStringAttribute(out, ATTR_NICKNAME, rec.nickname);
1765         writeIntAttribute(out, ATTR_USER_FLAGS, rec.userFlags);
1766         writeLongAttribute(out, ATTR_CREATED_MILLIS, rec.createdMillis);
1767         writeLongAttribute(out, ATTR_LAST_SEEN_MILLIS, rec.lastSeenMillis);
1768         writeLongAttribute(out, ATTR_LAST_TRIM_MILLIS, rec.lastTrimMillis);
1769         writeLongAttribute(out, ATTR_LAST_BENCH_MILLIS, rec.lastBenchMillis);
1770         out.endTag(null, TAG_VOLUME);
1771     }
1772 
1773     /**
1774      * Exposed API calls below here
1775      */
1776 
1777     @Override
registerListener(IStorageEventListener listener)1778     public void registerListener(IStorageEventListener listener) {
1779         mCallbacks.register(listener);
1780     }
1781 
1782     @Override
unregisterListener(IStorageEventListener listener)1783     public void unregisterListener(IStorageEventListener listener) {
1784         mCallbacks.unregister(listener);
1785     }
1786 
1787     @Override
shutdown(final IStorageShutdownObserver observer)1788     public void shutdown(final IStorageShutdownObserver observer) {
1789         enforcePermission(android.Manifest.permission.SHUTDOWN);
1790 
1791         Slog.i(TAG, "Shutting down");
1792         mHandler.obtainMessage(H_SHUTDOWN, observer).sendToTarget();
1793     }
1794 
1795     @Override
mount(String volId)1796     public void mount(String volId) {
1797         enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
1798 
1799         final VolumeInfo vol = findVolumeByIdOrThrow(volId);
1800         if (isMountDisallowed(vol)) {
1801             throw new SecurityException("Mounting " + volId + " restricted by policy");
1802         }
1803         mount(vol);
1804     }
1805 
mount(VolumeInfo vol)1806     private void mount(VolumeInfo vol) {
1807         try {
1808             mVold.mount(vol.id, vol.mountFlags, vol.mountUserId);
1809         } catch (Exception e) {
1810             Slog.wtf(TAG, e);
1811         }
1812     }
1813 
1814     @Override
unmount(String volId)1815     public void unmount(String volId) {
1816         enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
1817 
1818         final VolumeInfo vol = findVolumeByIdOrThrow(volId);
1819         unmount(vol);
1820     }
1821 
unmount(VolumeInfo vol)1822     private void unmount(VolumeInfo vol) {
1823         try {
1824             mVold.unmount(vol.id);
1825         } catch (Exception e) {
1826             Slog.wtf(TAG, e);
1827         }
1828     }
1829 
1830     @Override
format(String volId)1831     public void format(String volId) {
1832         enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);
1833 
1834         final VolumeInfo vol = findVolumeByIdOrThrow(volId);
1835         try {
1836             mVold.format(vol.id, "auto");
1837         } catch (Exception e) {
1838             Slog.wtf(TAG, e);
1839         }
1840     }
1841 
1842     @Override
benchmark(String volId, IVoldTaskListener listener)1843     public void benchmark(String volId, IVoldTaskListener listener) {
1844         enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);
1845 
1846         try {
1847             mVold.benchmark(volId, new IVoldTaskListener.Stub() {
1848                 @Override
1849                 public void onStatus(int status, PersistableBundle extras) {
1850                     dispatchOnStatus(listener, status, extras);
1851                 }
1852 
1853                 @Override
1854                 public void onFinished(int status, PersistableBundle extras) {
1855                     dispatchOnFinished(listener, status, extras);
1856 
1857                     final String path = extras.getString("path");
1858                     final String ident = extras.getString("ident");
1859                     final long create = extras.getLong("create");
1860                     final long run = extras.getLong("run");
1861                     final long destroy = extras.getLong("destroy");
1862 
1863                     final DropBoxManager dropBox = mContext.getSystemService(DropBoxManager.class);
1864                     dropBox.addText(TAG_STORAGE_BENCHMARK, scrubPath(path)
1865                             + " " + ident + " " + create + " " + run + " " + destroy);
1866 
1867                     synchronized (mLock) {
1868                         final VolumeRecord rec = findRecordForPath(path);
1869                         if (rec != null) {
1870                             rec.lastBenchMillis = System.currentTimeMillis();
1871                             writeSettingsLocked();
1872                         }
1873                     }
1874                 }
1875             });
1876         } catch (RemoteException e) {
1877             throw e.rethrowAsRuntimeException();
1878         }
1879     }
1880 
1881     @Override
partitionPublic(String diskId)1882     public void partitionPublic(String diskId) {
1883         enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);
1884 
1885         final CountDownLatch latch = findOrCreateDiskScanLatch(diskId);
1886         try {
1887             mVold.partition(diskId, IVold.PARTITION_TYPE_PUBLIC, -1);
1888             waitForLatch(latch, "partitionPublic", 3 * DateUtils.MINUTE_IN_MILLIS);
1889         } catch (Exception e) {
1890             Slog.wtf(TAG, e);
1891         }
1892     }
1893 
1894     @Override
partitionPrivate(String diskId)1895     public void partitionPrivate(String diskId) {
1896         enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);
1897         enforceAdminUser();
1898 
1899         final CountDownLatch latch = findOrCreateDiskScanLatch(diskId);
1900         try {
1901             mVold.partition(diskId, IVold.PARTITION_TYPE_PRIVATE, -1);
1902             waitForLatch(latch, "partitionPrivate", 3 * DateUtils.MINUTE_IN_MILLIS);
1903         } catch (Exception e) {
1904             Slog.wtf(TAG, e);
1905         }
1906     }
1907 
1908     @Override
partitionMixed(String diskId, int ratio)1909     public void partitionMixed(String diskId, int ratio) {
1910         enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);
1911         enforceAdminUser();
1912 
1913         final CountDownLatch latch = findOrCreateDiskScanLatch(diskId);
1914         try {
1915             mVold.partition(diskId, IVold.PARTITION_TYPE_MIXED, ratio);
1916             waitForLatch(latch, "partitionMixed", 3 * DateUtils.MINUTE_IN_MILLIS);
1917         } catch (Exception e) {
1918             Slog.wtf(TAG, e);
1919         }
1920     }
1921 
1922     @Override
setVolumeNickname(String fsUuid, String nickname)1923     public void setVolumeNickname(String fsUuid, String nickname) {
1924         enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
1925 
1926         Preconditions.checkNotNull(fsUuid);
1927         synchronized (mLock) {
1928             final VolumeRecord rec = mRecords.get(fsUuid);
1929             rec.nickname = nickname;
1930             mCallbacks.notifyVolumeRecordChanged(rec);
1931             writeSettingsLocked();
1932         }
1933     }
1934 
1935     @Override
setVolumeUserFlags(String fsUuid, int flags, int mask)1936     public void setVolumeUserFlags(String fsUuid, int flags, int mask) {
1937         enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
1938 
1939         Preconditions.checkNotNull(fsUuid);
1940         synchronized (mLock) {
1941             final VolumeRecord rec = mRecords.get(fsUuid);
1942             rec.userFlags = (rec.userFlags & ~mask) | (flags & mask);
1943             mCallbacks.notifyVolumeRecordChanged(rec);
1944             writeSettingsLocked();
1945         }
1946     }
1947 
1948     @Override
forgetVolume(String fsUuid)1949     public void forgetVolume(String fsUuid) {
1950         enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
1951 
1952         Preconditions.checkNotNull(fsUuid);
1953 
1954         synchronized (mLock) {
1955             final VolumeRecord rec = mRecords.remove(fsUuid);
1956             if (rec != null && !TextUtils.isEmpty(rec.partGuid)) {
1957                 mHandler.obtainMessage(H_PARTITION_FORGET, rec).sendToTarget();
1958             }
1959             mCallbacks.notifyVolumeForgotten(fsUuid);
1960 
1961             // If this had been primary storage, revert back to internal and
1962             // reset vold so we bind into new volume into place.
1963             if (Objects.equals(mPrimaryStorageUuid, fsUuid)) {
1964                 mPrimaryStorageUuid = getDefaultPrimaryStorageUuid();
1965                 mHandler.obtainMessage(H_RESET).sendToTarget();
1966             }
1967 
1968             writeSettingsLocked();
1969         }
1970     }
1971 
1972     @Override
forgetAllVolumes()1973     public void forgetAllVolumes() {
1974         enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
1975 
1976         synchronized (mLock) {
1977             for (int i = 0; i < mRecords.size(); i++) {
1978                 final String fsUuid = mRecords.keyAt(i);
1979                 final VolumeRecord rec = mRecords.valueAt(i);
1980                 if (!TextUtils.isEmpty(rec.partGuid)) {
1981                     mHandler.obtainMessage(H_PARTITION_FORGET, rec).sendToTarget();
1982                 }
1983                 mCallbacks.notifyVolumeForgotten(fsUuid);
1984             }
1985             mRecords.clear();
1986 
1987             if (!Objects.equals(StorageManager.UUID_PRIVATE_INTERNAL, mPrimaryStorageUuid)) {
1988                 mPrimaryStorageUuid = getDefaultPrimaryStorageUuid();
1989             }
1990 
1991             writeSettingsLocked();
1992             mHandler.obtainMessage(H_RESET).sendToTarget();
1993         }
1994     }
1995 
forgetPartition(String partGuid, String fsUuid)1996     private void forgetPartition(String partGuid, String fsUuid) {
1997         try {
1998             mVold.forgetPartition(partGuid, fsUuid);
1999         } catch (Exception e) {
2000             Slog.wtf(TAG, e);
2001         }
2002     }
2003 
2004     @Override
fstrim(int flags, IVoldTaskListener listener)2005     public void fstrim(int flags, IVoldTaskListener listener) {
2006         enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);
2007 
2008         try {
2009             // Block based checkpoint process runs fstrim. So, if checkpoint is in progress
2010             // (first boot after OTA), We skip idle maintenance and make sure the last
2011             // fstrim time is still updated. If file based checkpoints are used, we run
2012             // idle maintenance (GC + fstrim) regardless of checkpoint status.
2013             if (!needsCheckpoint() || !supportsBlockCheckpoint()) {
2014                 mVold.fstrim(flags, new IVoldTaskListener.Stub() {
2015                     @Override
2016                     public void onStatus(int status, PersistableBundle extras) {
2017                         dispatchOnStatus(listener, status, extras);
2018 
2019                         // Ignore trim failures
2020                         if (status != 0) return;
2021 
2022                         final String path = extras.getString("path");
2023                         final long bytes = extras.getLong("bytes");
2024                         final long time = extras.getLong("time");
2025 
2026                         final DropBoxManager dropBox = mContext.getSystemService(DropBoxManager.class);
2027                         dropBox.addText(TAG_STORAGE_TRIM, scrubPath(path) + " " + bytes + " " + time);
2028 
2029                         synchronized (mLock) {
2030                             final VolumeRecord rec = findRecordForPath(path);
2031                             if (rec != null) {
2032                                 rec.lastTrimMillis = System.currentTimeMillis();
2033                                 writeSettingsLocked();
2034                             }
2035                         }
2036                     }
2037 
2038                     @Override
2039                     public void onFinished(int status, PersistableBundle extras) {
2040                         dispatchOnFinished(listener, status, extras);
2041 
2042                         // TODO: benchmark when desired
2043                     }
2044                 });
2045             } else {
2046                 Slog.i(TAG, "Skipping fstrim - block based checkpoint in progress");
2047             }
2048         } catch (RemoteException e) {
2049             throw e.rethrowAsRuntimeException();
2050         }
2051     }
2052 
runIdleMaint(Runnable callback)2053     void runIdleMaint(Runnable callback) {
2054         enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);
2055 
2056         try {
2057             // Block based checkpoint process runs fstrim. So, if checkpoint is in progress
2058             // (first boot after OTA), We skip idle maintenance and make sure the last
2059             // fstrim time is still updated. If file based checkpoints are used, we run
2060             // idle maintenance (GC + fstrim) regardless of checkpoint status.
2061             if (!needsCheckpoint() || !supportsBlockCheckpoint()) {
2062                 mVold.runIdleMaint(new IVoldTaskListener.Stub() {
2063                     @Override
2064                     public void onStatus(int status, PersistableBundle extras) {
2065                         // Not currently used
2066                     }
2067                     @Override
2068                     public void onFinished(int status, PersistableBundle extras) {
2069                         if (callback != null) {
2070                             BackgroundThread.getHandler().post(callback);
2071                         }
2072                     }
2073                 });
2074             } else {
2075                 Slog.i(TAG, "Skipping idle maintenance - block based checkpoint in progress");
2076             }
2077         } catch (Exception e) {
2078             Slog.wtf(TAG, e);
2079         }
2080     }
2081 
2082     @Override
runIdleMaintenance()2083     public void runIdleMaintenance() {
2084         runIdleMaint(null);
2085     }
2086 
abortIdleMaint(Runnable callback)2087     void abortIdleMaint(Runnable callback) {
2088         enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);
2089 
2090         try {
2091             mVold.abortIdleMaint(new IVoldTaskListener.Stub() {
2092                 @Override
2093                 public void onStatus(int status, PersistableBundle extras) {
2094                     // Not currently used
2095                 }
2096                 @Override
2097                 public void onFinished(int status, PersistableBundle extras) {
2098                     if (callback != null) {
2099                         BackgroundThread.getHandler().post(callback);
2100                     }
2101                 }
2102             });
2103         } catch (Exception e) {
2104             Slog.wtf(TAG, e);
2105         }
2106     }
2107 
2108     @Override
abortIdleMaintenance()2109     public void abortIdleMaintenance() {
2110         abortIdleMaint(null);
2111     }
2112 
remountUidExternalStorage(int uid, int mode)2113     private void remountUidExternalStorage(int uid, int mode) {
2114         try {
2115             mVold.remountUid(uid, mode);
2116         } catch (Exception e) {
2117             Slog.wtf(TAG, e);
2118         }
2119     }
2120 
2121     @Override
setDebugFlags(int flags, int mask)2122     public void setDebugFlags(int flags, int mask) {
2123         enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
2124 
2125         if ((mask & StorageManager.DEBUG_EMULATE_FBE) != 0) {
2126             if (!EMULATE_FBE_SUPPORTED) {
2127                 throw new IllegalStateException(
2128                         "Emulation not supported on this device");
2129             }
2130             if (StorageManager.isFileEncryptedNativeOnly()) {
2131                 throw new IllegalStateException(
2132                         "Emulation not supported on device with native FBE");
2133             }
2134             if (mLockPatternUtils.isCredentialRequiredToDecrypt(false)) {
2135                 throw new IllegalStateException(
2136                         "Emulation requires disabling 'Secure start-up' in Settings > Security");
2137             }
2138 
2139             final long token = Binder.clearCallingIdentity();
2140             try {
2141                 final boolean emulateFbe = (flags & StorageManager.DEBUG_EMULATE_FBE) != 0;
2142                 SystemProperties.set(StorageManager.PROP_EMULATE_FBE, Boolean.toString(emulateFbe));
2143 
2144                 // Perform hard reboot to kick policy into place
2145                 mContext.getSystemService(PowerManager.class).reboot(null);
2146             } finally {
2147                 Binder.restoreCallingIdentity(token);
2148             }
2149         }
2150 
2151         if ((mask & (StorageManager.DEBUG_ADOPTABLE_FORCE_ON
2152                 | StorageManager.DEBUG_ADOPTABLE_FORCE_OFF)) != 0) {
2153             final String value;
2154             if ((flags & StorageManager.DEBUG_ADOPTABLE_FORCE_ON) != 0) {
2155                 value = "force_on";
2156             } else if ((flags & StorageManager.DEBUG_ADOPTABLE_FORCE_OFF) != 0) {
2157                 value = "force_off";
2158             } else {
2159                 value = "";
2160             }
2161 
2162             final long token = Binder.clearCallingIdentity();
2163             try {
2164                 SystemProperties.set(StorageManager.PROP_ADOPTABLE, value);
2165 
2166                 // Reset storage to kick new setting into place
2167                 mHandler.obtainMessage(H_RESET).sendToTarget();
2168             } finally {
2169                 Binder.restoreCallingIdentity(token);
2170             }
2171         }
2172 
2173         if ((mask & (StorageManager.DEBUG_SDCARDFS_FORCE_ON
2174                 | StorageManager.DEBUG_SDCARDFS_FORCE_OFF)) != 0) {
2175             final String value;
2176             if ((flags & StorageManager.DEBUG_SDCARDFS_FORCE_ON) != 0) {
2177                 value = "force_on";
2178             } else if ((flags & StorageManager.DEBUG_SDCARDFS_FORCE_OFF) != 0) {
2179                 value = "force_off";
2180             } else {
2181                 value = "";
2182             }
2183 
2184             final long token = Binder.clearCallingIdentity();
2185             try {
2186                 SystemProperties.set(StorageManager.PROP_SDCARDFS, value);
2187 
2188                 // Reset storage to kick new setting into place
2189                 mHandler.obtainMessage(H_RESET).sendToTarget();
2190             } finally {
2191                 Binder.restoreCallingIdentity(token);
2192             }
2193         }
2194 
2195         if ((mask & StorageManager.DEBUG_VIRTUAL_DISK) != 0) {
2196             final boolean enabled = (flags & StorageManager.DEBUG_VIRTUAL_DISK) != 0;
2197 
2198             final long token = Binder.clearCallingIdentity();
2199             try {
2200                 SystemProperties.set(StorageManager.PROP_VIRTUAL_DISK, Boolean.toString(enabled));
2201 
2202                 // Reset storage to kick new setting into place
2203                 mHandler.obtainMessage(H_RESET).sendToTarget();
2204             } finally {
2205                 Binder.restoreCallingIdentity(token);
2206             }
2207         }
2208 
2209         if ((mask & (StorageManager.DEBUG_ISOLATED_STORAGE_FORCE_ON
2210                 | StorageManager.DEBUG_ISOLATED_STORAGE_FORCE_OFF)) != 0) {
2211             final int value;
2212             if ((flags & StorageManager.DEBUG_ISOLATED_STORAGE_FORCE_ON) != 0) {
2213                 value = 1;
2214             } else if ((flags & StorageManager.DEBUG_ISOLATED_STORAGE_FORCE_OFF) != 0) {
2215                 value = -1;
2216             } else {
2217                 value = 0;
2218             }
2219 
2220             final long token = Binder.clearCallingIdentity();
2221             try {
2222                 Settings.Global.putInt(mContext.getContentResolver(),
2223                         Settings.Global.ISOLATED_STORAGE_LOCAL, value);
2224                 refreshIsolatedStorageSettings();
2225 
2226                 // Perform hard reboot to kick policy into place
2227                 mHandler.post(() -> {
2228                     mContext.getSystemService(PowerManager.class).reboot(null);
2229                 });
2230             } finally {
2231                 Binder.restoreCallingIdentity(token);
2232             }
2233         }
2234     }
2235 
2236     @Override
getPrimaryStorageUuid()2237     public String getPrimaryStorageUuid() {
2238         synchronized (mLock) {
2239             return mPrimaryStorageUuid;
2240         }
2241     }
2242 
2243     @Override
setPrimaryStorageUuid(String volumeUuid, IPackageMoveObserver callback)2244     public void setPrimaryStorageUuid(String volumeUuid, IPackageMoveObserver callback) {
2245         enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
2246 
2247         final VolumeInfo from;
2248         final VolumeInfo to;
2249 
2250         synchronized (mLock) {
2251             if (Objects.equals(mPrimaryStorageUuid, volumeUuid)) {
2252                 throw new IllegalArgumentException("Primary storage already at " + volumeUuid);
2253             }
2254 
2255             if (mMoveCallback != null) {
2256                 throw new IllegalStateException("Move already in progress");
2257             }
2258             mMoveCallback = callback;
2259             mMoveTargetUuid = volumeUuid;
2260 
2261             // We need all the users unlocked to move their primary storage
2262             final List<UserInfo> users = mContext.getSystemService(UserManager.class).getUsers();
2263             for (UserInfo user : users) {
2264                 if (StorageManager.isFileEncryptedNativeOrEmulated()
2265                         && !isUserKeyUnlocked(user.id)) {
2266                     Slog.w(TAG, "Failing move due to locked user " + user.id);
2267                     onMoveStatusLocked(PackageManager.MOVE_FAILED_LOCKED_USER);
2268                     return;
2269                 }
2270             }
2271 
2272             // When moving to/from primary physical volume, we probably just nuked
2273             // the current storage location, so we have nothing to move.
2274             if (Objects.equals(StorageManager.UUID_PRIMARY_PHYSICAL, mPrimaryStorageUuid)
2275                     || Objects.equals(StorageManager.UUID_PRIMARY_PHYSICAL, volumeUuid)) {
2276                 Slog.d(TAG, "Skipping move to/from primary physical");
2277                 onMoveStatusLocked(MOVE_STATUS_COPY_FINISHED);
2278                 onMoveStatusLocked(PackageManager.MOVE_SUCCEEDED);
2279                 mHandler.obtainMessage(H_RESET).sendToTarget();
2280                 return;
2281 
2282             } else {
2283                 from = findStorageForUuid(mPrimaryStorageUuid);
2284                 to = findStorageForUuid(volumeUuid);
2285 
2286                 if (from == null) {
2287                     Slog.w(TAG, "Failing move due to missing from volume " + mPrimaryStorageUuid);
2288                     onMoveStatusLocked(PackageManager.MOVE_FAILED_INTERNAL_ERROR);
2289                     return;
2290                 } else if (to == null) {
2291                     Slog.w(TAG, "Failing move due to missing to volume " + volumeUuid);
2292                     onMoveStatusLocked(PackageManager.MOVE_FAILED_INTERNAL_ERROR);
2293                     return;
2294                 }
2295             }
2296         }
2297 
2298         try {
2299             mVold.moveStorage(from.id, to.id, new IVoldTaskListener.Stub() {
2300                 @Override
2301                 public void onStatus(int status, PersistableBundle extras) {
2302                     synchronized (mLock) {
2303                         onMoveStatusLocked(status);
2304                     }
2305                 }
2306 
2307                 @Override
2308                 public void onFinished(int status, PersistableBundle extras) {
2309                     // Not currently used
2310                 }
2311             });
2312         } catch (Exception e) {
2313             Slog.wtf(TAG, e);
2314         }
2315     }
2316 
warnOnNotMounted()2317     private void warnOnNotMounted() {
2318         synchronized (mLock) {
2319             for (int i = 0; i < mVolumes.size(); i++) {
2320                 final VolumeInfo vol = mVolumes.valueAt(i);
2321                 if (vol.isPrimary() && vol.isMountedWritable()) {
2322                     // Cool beans, we have a mounted primary volume
2323                     return;
2324                 }
2325             }
2326         }
2327 
2328         Slog.w(TAG, "No primary storage mounted!");
2329     }
2330 
isUidOwnerOfPackageOrSystem(String packageName, int callerUid)2331     private boolean isUidOwnerOfPackageOrSystem(String packageName, int callerUid) {
2332         if (callerUid == android.os.Process.SYSTEM_UID) {
2333             return true;
2334         }
2335 
2336         if (packageName == null) {
2337             return false;
2338         }
2339 
2340         final int packageUid = mPmInternal.getPackageUid(packageName,
2341                 PackageManager.MATCH_DEBUG_TRIAGED_MISSING, UserHandle.getUserId(callerUid));
2342 
2343         if (DEBUG_OBB) {
2344             Slog.d(TAG, "packageName = " + packageName + ", packageUid = " +
2345                     packageUid + ", callerUid = " + callerUid);
2346         }
2347 
2348         return callerUid == packageUid;
2349     }
2350 
2351     @Override
getMountedObbPath(String rawPath)2352     public String getMountedObbPath(String rawPath) {
2353         Preconditions.checkNotNull(rawPath, "rawPath cannot be null");
2354 
2355         warnOnNotMounted();
2356 
2357         final ObbState state;
2358         synchronized (mObbMounts) {
2359             state = mObbPathToStateMap.get(rawPath);
2360         }
2361         if (state == null) {
2362             Slog.w(TAG, "Failed to find OBB mounted at " + rawPath);
2363             return null;
2364         }
2365 
2366         return findVolumeByIdOrThrow(state.volId).getPath().getAbsolutePath();
2367     }
2368 
2369     @Override
isObbMounted(String rawPath)2370     public boolean isObbMounted(String rawPath) {
2371         Preconditions.checkNotNull(rawPath, "rawPath cannot be null");
2372         synchronized (mObbMounts) {
2373             return mObbPathToStateMap.containsKey(rawPath);
2374         }
2375     }
2376 
2377     @Override
mountObb(String rawPath, String canonicalPath, String key, IObbActionListener token, int nonce, ObbInfo obbInfo)2378     public void mountObb(String rawPath, String canonicalPath, String key,
2379             IObbActionListener token, int nonce, ObbInfo obbInfo) {
2380         Preconditions.checkNotNull(rawPath, "rawPath cannot be null");
2381         Preconditions.checkNotNull(canonicalPath, "canonicalPath cannot be null");
2382         Preconditions.checkNotNull(token, "token cannot be null");
2383         Preconditions.checkNotNull(obbInfo, "obbIfno cannot be null");
2384 
2385         final int callingUid = Binder.getCallingUid();
2386         final ObbState obbState = new ObbState(rawPath, canonicalPath,
2387                 callingUid, token, nonce, null);
2388         final ObbAction action = new MountObbAction(obbState, key, callingUid, obbInfo);
2389         mObbActionHandler.sendMessage(mObbActionHandler.obtainMessage(OBB_RUN_ACTION, action));
2390 
2391         if (DEBUG_OBB)
2392             Slog.i(TAG, "Send to OBB handler: " + action.toString());
2393     }
2394 
2395     @Override
unmountObb(String rawPath, boolean force, IObbActionListener token, int nonce)2396     public void unmountObb(String rawPath, boolean force, IObbActionListener token, int nonce) {
2397         Preconditions.checkNotNull(rawPath, "rawPath cannot be null");
2398 
2399         final ObbState existingState;
2400         synchronized (mObbMounts) {
2401             existingState = mObbPathToStateMap.get(rawPath);
2402         }
2403 
2404         if (existingState != null) {
2405             // TODO: separate state object from request data
2406             final int callingUid = Binder.getCallingUid();
2407             final ObbState newState = new ObbState(rawPath, existingState.canonicalPath,
2408                     callingUid, token, nonce, existingState.volId);
2409             final ObbAction action = new UnmountObbAction(newState, force);
2410             mObbActionHandler.sendMessage(mObbActionHandler.obtainMessage(OBB_RUN_ACTION, action));
2411 
2412             if (DEBUG_OBB)
2413                 Slog.i(TAG, "Send to OBB handler: " + action.toString());
2414         } else {
2415             Slog.w(TAG, "Unknown OBB mount at " + rawPath);
2416         }
2417     }
2418 
2419     @Override
getEncryptionState()2420     public int getEncryptionState() {
2421         mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
2422                 "no permission to access the crypt keeper");
2423 
2424         try {
2425             return mVold.fdeComplete();
2426         } catch (Exception e) {
2427             Slog.wtf(TAG, e);
2428             return StorageManager.ENCRYPTION_STATE_ERROR_UNKNOWN;
2429         }
2430     }
2431 
2432     @Override
decryptStorage(String password)2433     public int decryptStorage(String password) {
2434         mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
2435                 "no permission to access the crypt keeper");
2436 
2437         if (TextUtils.isEmpty(password)) {
2438             throw new IllegalArgumentException("password cannot be empty");
2439         }
2440 
2441         if (DEBUG_EVENTS) {
2442             Slog.i(TAG, "decrypting storage...");
2443         }
2444 
2445         try {
2446             mVold.fdeCheckPassword(password);
2447             mHandler.postDelayed(() -> {
2448                 try {
2449                     mVold.fdeRestart();
2450                 } catch (Exception e) {
2451                     Slog.wtf(TAG, e);
2452                 }
2453             }, DateUtils.SECOND_IN_MILLIS);
2454             return 0;
2455         } catch (ServiceSpecificException e) {
2456             Slog.e(TAG, "fdeCheckPassword failed", e);
2457             return e.errorCode;
2458         } catch (Exception e) {
2459             Slog.wtf(TAG, e);
2460             return StorageManager.ENCRYPTION_STATE_ERROR_UNKNOWN;
2461         }
2462     }
2463 
2464     @Override
encryptStorage(int type, String password)2465     public int encryptStorage(int type, String password) {
2466         mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
2467             "no permission to access the crypt keeper");
2468 
2469         if (type == StorageManager.CRYPT_TYPE_DEFAULT) {
2470             password = "";
2471         } else if (TextUtils.isEmpty(password)) {
2472             throw new IllegalArgumentException("password cannot be empty");
2473         }
2474 
2475         if (DEBUG_EVENTS) {
2476             Slog.i(TAG, "encrypting storage...");
2477         }
2478 
2479         try {
2480             mVold.fdeEnable(type, password, 0);
2481         } catch (Exception e) {
2482             Slog.wtf(TAG, e);
2483             return -1;
2484         }
2485 
2486         return 0;
2487     }
2488 
2489     /** Set the password for encrypting the master key.
2490      *  @param type One of the CRYPTO_TYPE_XXX consts defined in StorageManager.
2491      *  @param password The password to set.
2492      */
2493     @Override
changeEncryptionPassword(int type, String password)2494     public int changeEncryptionPassword(int type, String password) {
2495         mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
2496             "no permission to access the crypt keeper");
2497 
2498         if (StorageManager.isFileEncryptedNativeOnly()) {
2499             // Not supported on FBE devices
2500             return -1;
2501         }
2502 
2503         if (type == StorageManager.CRYPT_TYPE_DEFAULT) {
2504             password = "";
2505         } else if (TextUtils.isEmpty(password)) {
2506             throw new IllegalArgumentException("password cannot be empty");
2507         }
2508 
2509         if (DEBUG_EVENTS) {
2510             Slog.i(TAG, "changing encryption password...");
2511         }
2512 
2513         try {
2514             mVold.fdeChangePassword(type, password);
2515             return 0;
2516         } catch (Exception e) {
2517             Slog.wtf(TAG, e);
2518             return -1;
2519         }
2520     }
2521 
2522     /**
2523      * Validate a user-supplied password string with cryptfs
2524      */
2525     @Override
verifyEncryptionPassword(String password)2526     public int verifyEncryptionPassword(String password) throws RemoteException {
2527         // Only the system process is permitted to validate passwords
2528         if (Binder.getCallingUid() != android.os.Process.SYSTEM_UID) {
2529             throw new SecurityException("no permission to access the crypt keeper");
2530         }
2531 
2532         mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
2533             "no permission to access the crypt keeper");
2534 
2535         if (TextUtils.isEmpty(password)) {
2536             throw new IllegalArgumentException("password cannot be empty");
2537         }
2538 
2539         if (DEBUG_EVENTS) {
2540             Slog.i(TAG, "validating encryption password...");
2541         }
2542 
2543         try {
2544             mVold.fdeVerifyPassword(password);
2545             return 0;
2546         } catch (Exception e) {
2547             Slog.wtf(TAG, e);
2548             return -1;
2549         }
2550     }
2551 
2552     /**
2553      * Get the type of encryption used to encrypt the master key.
2554      * @return The type, one of the CRYPT_TYPE_XXX consts from StorageManager.
2555      */
2556     @Override
getPasswordType()2557     public int getPasswordType() {
2558         mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
2559             "no permission to access the crypt keeper");
2560 
2561         try {
2562             return mVold.fdeGetPasswordType();
2563         } catch (Exception e) {
2564             Slog.wtf(TAG, e);
2565             return -1;
2566         }
2567     }
2568 
2569     /**
2570      * Set a field in the crypto header.
2571      * @param field field to set
2572      * @param contents contents to set in field
2573      */
2574     @Override
setField(String field, String contents)2575     public void setField(String field, String contents) throws RemoteException {
2576         mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
2577             "no permission to access the crypt keeper");
2578 
2579         if (!StorageManager.isBlockEncrypted()) {
2580             // Only supported on FDE devices
2581             return;
2582         }
2583 
2584         try {
2585             mVold.fdeSetField(field, contents);
2586             return;
2587         } catch (Exception e) {
2588             Slog.wtf(TAG, e);
2589             return;
2590         }
2591     }
2592 
2593     /**
2594      * Gets a field from the crypto header.
2595      * @param field field to get
2596      * @return contents of field
2597      */
2598     @Override
getField(String field)2599     public String getField(String field) throws RemoteException {
2600         mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
2601             "no permission to access the crypt keeper");
2602 
2603         if (!StorageManager.isBlockEncrypted()) {
2604             // Only supported on FDE devices
2605             return null;
2606         }
2607 
2608         try {
2609             return mVold.fdeGetField(field);
2610         } catch (Exception e) {
2611             Slog.wtf(TAG, e);
2612             return null;
2613         }
2614     }
2615 
2616     /**
2617      * Is userdata convertible to file based encryption?
2618      * @return non zero for convertible
2619      */
2620     @Override
isConvertibleToFBE()2621     public boolean isConvertibleToFBE() throws RemoteException {
2622         mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
2623             "no permission to access the crypt keeper");
2624 
2625         try {
2626             return mVold.isConvertibleToFbe();
2627         } catch (Exception e) {
2628             Slog.wtf(TAG, e);
2629             return false;
2630         }
2631     }
2632 
2633     /**
2634      * Check whether the device supports filesystem checkpointing.
2635      *
2636      * @return true if the device supports filesystem checkpointing, false otherwise.
2637      */
2638     @Override
supportsCheckpoint()2639     public boolean supportsCheckpoint() throws RemoteException {
2640         // Only the system process is permitted to start checkpoints
2641         if (Binder.getCallingUid() != android.os.Process.SYSTEM_UID) {
2642             throw new SecurityException("no permission to check filesystem checkpoint support");
2643         }
2644 
2645         return mVold.supportsCheckpoint();
2646     }
2647 
2648     /**
2649      * Signal that checkpointing partitions should start a checkpoint on the next boot.
2650      *
2651      * @param numTries Number of times to try booting in checkpoint mode, before we will boot
2652      *                 non-checkpoint mode and commit all changes immediately. Callers are
2653      *                 responsible for ensuring that boot is safe (eg, by rolling back updates).
2654      */
2655     @Override
startCheckpoint(int numTries)2656     public void startCheckpoint(int numTries) throws RemoteException {
2657         // Only the system process is permitted to start checkpoints
2658         if (Binder.getCallingUid() != android.os.Process.SYSTEM_UID) {
2659             throw new SecurityException("no permission to start filesystem checkpoint");
2660         }
2661 
2662         mVold.startCheckpoint(numTries);
2663     }
2664 
2665     /**
2666      * Signal that checkpointing partitions should commit changes
2667      */
2668     @Override
commitChanges()2669     public void commitChanges() throws RemoteException {
2670         // Only the system process is permitted to commit checkpoints
2671         if (Binder.getCallingUid() != android.os.Process.SYSTEM_UID) {
2672             throw new SecurityException("no permission to commit checkpoint changes");
2673         }
2674 
2675         mVold.commitChanges();
2676     }
2677 
2678     /**
2679      * Check if we should be mounting with checkpointing or are checkpointing now
2680      */
2681     @Override
needsCheckpoint()2682     public boolean needsCheckpoint() throws RemoteException {
2683         enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);
2684         return mVold.needsCheckpoint();
2685     }
2686 
2687     /**
2688      * Abort the current set of changes and either try again, or abort entirely
2689      */
2690     @Override
abortChanges(String message, boolean retry)2691     public void abortChanges(String message, boolean retry) throws RemoteException {
2692         // Only the system process is permitted to abort checkpoints
2693         if (Binder.getCallingUid() != android.os.Process.SYSTEM_UID) {
2694             throw new SecurityException("no permission to commit checkpoint changes");
2695         }
2696 
2697         mVold.abortChanges(message, retry);
2698     }
2699 
2700     @Override
getPassword()2701     public String getPassword() throws RemoteException {
2702         mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
2703                 "only keyguard can retrieve password");
2704 
2705         try {
2706             return mVold.fdeGetPassword();
2707         } catch (Exception e) {
2708             Slog.wtf(TAG, e);
2709             return null;
2710         }
2711     }
2712 
2713     @Override
clearPassword()2714     public void clearPassword() throws RemoteException {
2715         mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
2716                 "only keyguard can clear password");
2717 
2718         try {
2719             mVold.fdeClearPassword();
2720             return;
2721         } catch (Exception e) {
2722             Slog.wtf(TAG, e);
2723             return;
2724         }
2725     }
2726 
2727     @Override
createUserKey(int userId, int serialNumber, boolean ephemeral)2728     public void createUserKey(int userId, int serialNumber, boolean ephemeral) {
2729         enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
2730 
2731         try {
2732             mVold.createUserKey(userId, serialNumber, ephemeral);
2733         } catch (Exception e) {
2734             Slog.wtf(TAG, e);
2735         }
2736     }
2737 
2738     @Override
destroyUserKey(int userId)2739     public void destroyUserKey(int userId) {
2740         enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
2741 
2742         try {
2743             mVold.destroyUserKey(userId);
2744         } catch (Exception e) {
2745             Slog.wtf(TAG, e);
2746         }
2747     }
2748 
encodeBytes(byte[] bytes)2749     private String encodeBytes(byte[] bytes) {
2750         if (ArrayUtils.isEmpty(bytes)) {
2751             return "!";
2752         } else {
2753             return HexDump.toHexString(bytes);
2754         }
2755     }
2756 
2757     /*
2758      * Add this token/secret pair to the set of ways we can recover a disk encryption key.
2759      * Changing the token/secret for a disk encryption key is done in two phases: first, adding
2760      * a new token/secret pair with this call, then delting all other pairs with
2761      * fixateNewestUserKeyAuth. This allows other places where a credential is used, such as
2762      * Gatekeeper, to be updated between the two calls.
2763      */
2764     @Override
addUserKeyAuth(int userId, int serialNumber, byte[] token, byte[] secret)2765     public void addUserKeyAuth(int userId, int serialNumber, byte[] token, byte[] secret) {
2766         enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
2767 
2768         try {
2769             mVold.addUserKeyAuth(userId, serialNumber, encodeBytes(token), encodeBytes(secret));
2770         } catch (Exception e) {
2771             Slog.wtf(TAG, e);
2772         }
2773     }
2774 
2775     /*
2776      * Delete all disk encryption token/secret pairs except the most recently added one
2777      */
2778     @Override
fixateNewestUserKeyAuth(int userId)2779     public void fixateNewestUserKeyAuth(int userId) {
2780         enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
2781 
2782         try {
2783             mVold.fixateNewestUserKeyAuth(userId);
2784         } catch (Exception e) {
2785             Slog.wtf(TAG, e);
2786         }
2787     }
2788 
2789     @Override
unlockUserKey(int userId, int serialNumber, byte[] token, byte[] secret)2790     public void unlockUserKey(int userId, int serialNumber, byte[] token, byte[] secret) {
2791         Slog.d(TAG, "unlockUserKey: " + userId);
2792         enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
2793 
2794         if (StorageManager.isFileEncryptedNativeOrEmulated()) {
2795             // When a user has secure lock screen, require secret to actually unlock.
2796             // This check is mostly in place for emulation mode.
2797             if (mLockPatternUtils.isSecure(userId) && ArrayUtils.isEmpty(secret)) {
2798                 throw new IllegalStateException("Secret required to unlock secure user " + userId);
2799             }
2800 
2801             try {
2802                 mVold.unlockUserKey(userId, serialNumber, encodeBytes(token),
2803                         encodeBytes(secret));
2804             } catch (Exception e) {
2805                 Slog.wtf(TAG, e);
2806                 return;
2807             }
2808         }
2809 
2810         synchronized (mLock) {
2811             mLocalUnlockedUsers = ArrayUtils.appendInt(mLocalUnlockedUsers, userId);
2812         }
2813     }
2814 
2815     @Override
lockUserKey(int userId)2816     public void lockUserKey(int userId) {
2817         enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
2818 
2819         try {
2820             mVold.lockUserKey(userId);
2821         } catch (Exception e) {
2822             Slog.wtf(TAG, e);
2823             return;
2824         }
2825 
2826         synchronized (mLock) {
2827             mLocalUnlockedUsers = ArrayUtils.removeInt(mLocalUnlockedUsers, userId);
2828         }
2829     }
2830 
2831     @Override
isUserKeyUnlocked(int userId)2832     public boolean isUserKeyUnlocked(int userId) {
2833         synchronized (mLock) {
2834             return ArrayUtils.contains(mLocalUnlockedUsers, userId);
2835         }
2836     }
2837 
isSystemUnlocked(int userId)2838     private boolean isSystemUnlocked(int userId) {
2839         synchronized (mLock) {
2840             return ArrayUtils.contains(mSystemUnlockedUsers, userId);
2841         }
2842     }
2843 
2844     @Override
prepareUserStorage(String volumeUuid, int userId, int serialNumber, int flags)2845     public void prepareUserStorage(String volumeUuid, int userId, int serialNumber, int flags) {
2846         enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
2847 
2848         try {
2849             mVold.prepareUserStorage(volumeUuid, userId, serialNumber, flags);
2850         } catch (Exception e) {
2851             Slog.wtf(TAG, e);
2852         }
2853     }
2854 
2855     @Override
destroyUserStorage(String volumeUuid, int userId, int flags)2856     public void destroyUserStorage(String volumeUuid, int userId, int flags) {
2857         enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
2858 
2859         try {
2860             mVold.destroyUserStorage(volumeUuid, userId, flags);
2861         } catch (Exception e) {
2862             Slog.wtf(TAG, e);
2863         }
2864     }
2865 
2866     /** Not thread safe */
2867     class AppFuseMountScope extends AppFuseBridge.MountScope {
2868         private boolean mMounted = false;
2869 
AppFuseMountScope(int uid, int mountId)2870         public AppFuseMountScope(int uid, int mountId) {
2871             super(uid, mountId);
2872         }
2873 
2874         @Override
open()2875         public ParcelFileDescriptor open() throws NativeDaemonConnectorException {
2876             try {
2877                 final FileDescriptor fd = mVold.mountAppFuse(uid, mountId);
2878                 mMounted = true;
2879                 return new ParcelFileDescriptor(fd);
2880             } catch (Exception e) {
2881                 throw new NativeDaemonConnectorException("Failed to mount", e);
2882             }
2883         }
2884 
2885         @Override
openFile(int mountId, int fileId, int flags)2886         public ParcelFileDescriptor openFile(int mountId, int fileId, int flags)
2887                 throws NativeDaemonConnectorException {
2888             try {
2889                 return new ParcelFileDescriptor(
2890                         mVold.openAppFuseFile(uid, mountId, fileId, flags));
2891             } catch (Exception e) {
2892                 throw new NativeDaemonConnectorException("Failed to open", e);
2893             }
2894         }
2895 
2896         @Override
close()2897         public void close() throws Exception {
2898             if (mMounted) {
2899                 mVold.unmountAppFuse(uid, mountId);
2900                 mMounted = false;
2901             }
2902         }
2903     }
2904 
2905     @Override
mountProxyFileDescriptorBridge()2906     public @Nullable AppFuseMount mountProxyFileDescriptorBridge() {
2907         Slog.v(TAG, "mountProxyFileDescriptorBridge");
2908         final int uid = Binder.getCallingUid();
2909 
2910         while (true) {
2911             synchronized (mAppFuseLock) {
2912                 boolean newlyCreated = false;
2913                 if (mAppFuseBridge == null) {
2914                     mAppFuseBridge = new AppFuseBridge();
2915                     new Thread(mAppFuseBridge, AppFuseBridge.TAG).start();
2916                     newlyCreated = true;
2917                 }
2918                 try {
2919                     final int name = mNextAppFuseName++;
2920                     try {
2921                         return new AppFuseMount(
2922                             name, mAppFuseBridge.addBridge(new AppFuseMountScope(uid, name)));
2923                     } catch (FuseUnavailableMountException e) {
2924                         if (newlyCreated) {
2925                             // If newly created bridge fails, it's a real error.
2926                             Slog.e(TAG, "", e);
2927                             return null;
2928                         }
2929                         // It seems the thread of mAppFuseBridge has already been terminated.
2930                         mAppFuseBridge = null;
2931                     }
2932                 } catch (NativeDaemonConnectorException e) {
2933                     throw e.rethrowAsParcelableException();
2934                 }
2935             }
2936         }
2937     }
2938 
2939     @Override
openProxyFileDescriptor( int mountId, int fileId, int mode)2940     public @Nullable ParcelFileDescriptor openProxyFileDescriptor(
2941             int mountId, int fileId, int mode) {
2942         Slog.v(TAG, "mountProxyFileDescriptor");
2943 
2944         // We only support a narrow set of incoming mode flags
2945         mode &= MODE_READ_WRITE;
2946 
2947         try {
2948             synchronized (mAppFuseLock) {
2949                 if (mAppFuseBridge == null) {
2950                     Slog.e(TAG, "FuseBridge has not been created");
2951                     return null;
2952                 }
2953                 return mAppFuseBridge.openFile(mountId, fileId, mode);
2954             }
2955         } catch (FuseUnavailableMountException | InterruptedException error) {
2956             Slog.v(TAG, "The mount point has already been invalid", error);
2957             return null;
2958         }
2959     }
2960 
2961     @Override
mkdirs(String callingPkg, String appPath)2962     public void mkdirs(String callingPkg, String appPath) {
2963         final int callingUid = Binder.getCallingUid();
2964         final int userId = UserHandle.getUserId(callingUid);
2965         final UserEnvironment userEnv = new UserEnvironment(userId);
2966         final String propertyName = "sys.user." + userId + ".ce_available";
2967 
2968         // Ignore requests to create directories while storage is locked
2969         if (!isUserKeyUnlocked(userId)) {
2970             throw new IllegalStateException("Failed to prepare " + appPath);
2971         }
2972 
2973         // Ignore requests to create directories if CE storage is not available
2974         if ((userId == UserHandle.USER_SYSTEM)
2975                 && !SystemProperties.getBoolean(propertyName, false)) {
2976             throw new IllegalStateException("Failed to prepare " + appPath);
2977         }
2978 
2979         // Validate that reported package name belongs to caller
2980         final AppOpsManager appOps = (AppOpsManager) mContext.getSystemService(
2981                 Context.APP_OPS_SERVICE);
2982         appOps.checkPackage(callingUid, callingPkg);
2983 
2984         File appFile = null;
2985         try {
2986             appFile = new File(appPath).getCanonicalFile();
2987         } catch (IOException e) {
2988             throw new IllegalStateException("Failed to resolve " + appPath + ": " + e);
2989         }
2990 
2991         // Try translating the app path into a vold path, but require that it
2992         // belong to the calling package.
2993         if (FileUtils.contains(userEnv.buildExternalStorageAppDataDirs(callingPkg), appFile) ||
2994                 FileUtils.contains(userEnv.buildExternalStorageAppObbDirs(callingPkg), appFile) ||
2995                 FileUtils.contains(userEnv.buildExternalStorageAppMediaDirs(callingPkg), appFile)) {
2996             appPath = appFile.getAbsolutePath();
2997             if (!appPath.endsWith("/")) {
2998                 appPath = appPath + "/";
2999             }
3000 
3001             try {
3002                 mVold.mkdirs(appPath);
3003                 return;
3004             } catch (Exception e) {
3005                 throw new IllegalStateException("Failed to prepare " + appPath + ": " + e);
3006             }
3007         }
3008 
3009         throw new SecurityException("Invalid mkdirs path: " + appFile);
3010     }
3011 
3012     @Override
getVolumeList(int uid, String packageName, int flags)3013     public StorageVolume[] getVolumeList(int uid, String packageName, int flags) {
3014         final int userId = UserHandle.getUserId(uid);
3015 
3016         final boolean forWrite = (flags & StorageManager.FLAG_FOR_WRITE) != 0;
3017         final boolean realState = (flags & StorageManager.FLAG_REAL_STATE) != 0;
3018         final boolean includeInvisible = (flags & StorageManager.FLAG_INCLUDE_INVISIBLE) != 0;
3019 
3020         // Report all volumes as unmounted until we've recorded that user 0 has unlocked. There
3021         // are no guarantees that callers will see a consistent view of the volume before that
3022         // point
3023         final boolean systemUserUnlocked = isSystemUnlocked(UserHandle.USER_SYSTEM);
3024 
3025         final boolean userKeyUnlocked;
3026         final boolean storagePermission;
3027         final long token = Binder.clearCallingIdentity();
3028         try {
3029             userKeyUnlocked = isUserKeyUnlocked(userId);
3030             storagePermission = mStorageManagerInternal.hasExternalStorage(uid, packageName);
3031         } finally {
3032             Binder.restoreCallingIdentity(token);
3033         }
3034 
3035         boolean foundPrimary = false;
3036 
3037         final ArrayList<StorageVolume> res = new ArrayList<>();
3038         synchronized (mLock) {
3039             for (int i = 0; i < mVolumes.size(); i++) {
3040                 final VolumeInfo vol = mVolumes.valueAt(i);
3041                 switch (vol.getType()) {
3042                     case VolumeInfo.TYPE_PUBLIC:
3043                     case VolumeInfo.TYPE_STUB:
3044                     case VolumeInfo.TYPE_EMULATED:
3045                         break;
3046                     default:
3047                         continue;
3048                 }
3049 
3050                 boolean match = false;
3051                 if (forWrite) {
3052                     match = vol.isVisibleForWrite(userId);
3053                 } else {
3054                     match = vol.isVisibleForRead(userId)
3055                             || (includeInvisible && vol.getPath() != null);
3056                 }
3057                 if (!match) continue;
3058 
3059                 boolean reportUnmounted = false;
3060                 if (!systemUserUnlocked) {
3061                     reportUnmounted = true;
3062                 } else if ((vol.getType() == VolumeInfo.TYPE_EMULATED) && !userKeyUnlocked) {
3063                     reportUnmounted = true;
3064                 } else if (!storagePermission && !realState) {
3065                     reportUnmounted = true;
3066                 }
3067 
3068                 final StorageVolume userVol = vol.buildStorageVolume(mContext, userId,
3069                         reportUnmounted);
3070                 if (vol.isPrimary()) {
3071                     res.add(0, userVol);
3072                     foundPrimary = true;
3073                 } else {
3074                     res.add(userVol);
3075                 }
3076             }
3077         }
3078 
3079         if (!foundPrimary) {
3080             Slog.w(TAG, "No primary storage defined yet; hacking together a stub");
3081 
3082             final boolean primaryPhysical = SystemProperties.getBoolean(
3083                     StorageManager.PROP_PRIMARY_PHYSICAL, false);
3084 
3085             final String id = "stub_primary";
3086             final File path = Environment.getLegacyExternalStorageDirectory();
3087             final String description = mContext.getString(android.R.string.unknownName);
3088             final boolean primary = true;
3089             final boolean removable = primaryPhysical;
3090             final boolean emulated = !primaryPhysical;
3091             final boolean allowMassStorage = false;
3092             final long maxFileSize = 0L;
3093             final UserHandle owner = new UserHandle(userId);
3094             final String uuid = null;
3095             final String state = Environment.MEDIA_REMOVED;
3096 
3097             res.add(0, new StorageVolume(id, path, path,
3098                     description, primary, removable, emulated,
3099                     allowMassStorage, maxFileSize, owner, uuid, state));
3100         }
3101 
3102         return res.toArray(new StorageVolume[res.size()]);
3103     }
3104 
3105     @Override
getDisks()3106     public DiskInfo[] getDisks() {
3107         synchronized (mLock) {
3108             final DiskInfo[] res = new DiskInfo[mDisks.size()];
3109             for (int i = 0; i < mDisks.size(); i++) {
3110                 res[i] = mDisks.valueAt(i);
3111             }
3112             return res;
3113         }
3114     }
3115 
3116     @Override
getVolumes(int flags)3117     public VolumeInfo[] getVolumes(int flags) {
3118         synchronized (mLock) {
3119             final VolumeInfo[] res = new VolumeInfo[mVolumes.size()];
3120             for (int i = 0; i < mVolumes.size(); i++) {
3121                 res[i] = mVolumes.valueAt(i);
3122             }
3123             return res;
3124         }
3125     }
3126 
3127     @Override
getVolumeRecords(int flags)3128     public VolumeRecord[] getVolumeRecords(int flags) {
3129         synchronized (mLock) {
3130             final VolumeRecord[] res = new VolumeRecord[mRecords.size()];
3131             for (int i = 0; i < mRecords.size(); i++) {
3132                 res[i] = mRecords.valueAt(i);
3133             }
3134             return res;
3135         }
3136     }
3137 
3138     @Override
getCacheQuotaBytes(String volumeUuid, int uid)3139     public long getCacheQuotaBytes(String volumeUuid, int uid) {
3140         if (uid != Binder.getCallingUid()) {
3141             mContext.enforceCallingPermission(android.Manifest.permission.STORAGE_INTERNAL, TAG);
3142         }
3143         final long token = Binder.clearCallingIdentity();
3144         final StorageStatsManager stats = mContext.getSystemService(StorageStatsManager.class);
3145         try {
3146             return stats.getCacheQuotaBytes(volumeUuid, uid);
3147         } finally {
3148             Binder.restoreCallingIdentity(token);
3149         }
3150     }
3151 
3152     @Override
getCacheSizeBytes(String volumeUuid, int uid)3153     public long getCacheSizeBytes(String volumeUuid, int uid) {
3154         if (uid != Binder.getCallingUid()) {
3155             mContext.enforceCallingPermission(android.Manifest.permission.STORAGE_INTERNAL, TAG);
3156         }
3157         final long token = Binder.clearCallingIdentity();
3158         try {
3159             return mContext.getSystemService(StorageStatsManager.class)
3160                     .queryStatsForUid(volumeUuid, uid).getCacheBytes();
3161         } catch (IOException e) {
3162             throw new ParcelableException(e);
3163         } finally {
3164             Binder.restoreCallingIdentity(token);
3165         }
3166     }
3167 
adjustAllocateFlags(int flags, int callingUid, String callingPackage)3168     private int adjustAllocateFlags(int flags, int callingUid, String callingPackage) {
3169         // Require permission to allocate aggressively
3170         if ((flags & StorageManager.FLAG_ALLOCATE_AGGRESSIVE) != 0) {
3171             mContext.enforceCallingOrSelfPermission(
3172                     android.Manifest.permission.ALLOCATE_AGGRESSIVE, TAG);
3173         }
3174 
3175         // Apps normally can't directly defy reserved space
3176         flags &= ~StorageManager.FLAG_ALLOCATE_DEFY_ALL_RESERVED;
3177         flags &= ~StorageManager.FLAG_ALLOCATE_DEFY_HALF_RESERVED;
3178 
3179         // However, if app is actively using the camera, then we're willing to
3180         // clear up to half of the reserved cache space, since the user might be
3181         // trying to capture an important memory.
3182         final AppOpsManager appOps = mContext.getSystemService(AppOpsManager.class);
3183         final long token = Binder.clearCallingIdentity();
3184         try {
3185             if (appOps.isOperationActive(AppOpsManager.OP_CAMERA, callingUid, callingPackage)) {
3186                 Slog.d(TAG, "UID " + callingUid + " is actively using camera;"
3187                         + " letting them defy reserved cached data");
3188                 flags |= StorageManager.FLAG_ALLOCATE_DEFY_HALF_RESERVED;
3189             }
3190         } finally {
3191             Binder.restoreCallingIdentity(token);
3192         }
3193 
3194         return flags;
3195     }
3196 
3197     @Override
getAllocatableBytes(String volumeUuid, int flags, String callingPackage)3198     public long getAllocatableBytes(String volumeUuid, int flags, String callingPackage) {
3199         flags = adjustAllocateFlags(flags, Binder.getCallingUid(), callingPackage);
3200 
3201         final StorageManager storage = mContext.getSystemService(StorageManager.class);
3202         final StorageStatsManager stats = mContext.getSystemService(StorageStatsManager.class);
3203         final long token = Binder.clearCallingIdentity();
3204         try {
3205             // In general, apps can allocate as much space as they want, except
3206             // we never let them eat into either the minimum cache space or into
3207             // the low disk warning space. To avoid user confusion, this logic
3208             // should be kept in sync with getFreeBytes().
3209             final File path = storage.findPathForUuid(volumeUuid);
3210 
3211             final long usable = path.getUsableSpace();
3212             final long lowReserved = storage.getStorageLowBytes(path);
3213             final long fullReserved = storage.getStorageFullBytes(path);
3214 
3215             if (stats.isQuotaSupported(volumeUuid)) {
3216                 final long cacheTotal = stats.getCacheBytes(volumeUuid);
3217                 final long cacheReserved = storage.getStorageCacheBytes(path, flags);
3218                 final long cacheClearable = Math.max(0, cacheTotal - cacheReserved);
3219 
3220                 if ((flags & StorageManager.FLAG_ALLOCATE_AGGRESSIVE) != 0) {
3221                     return Math.max(0, (usable + cacheClearable) - fullReserved);
3222                 } else {
3223                     return Math.max(0, (usable + cacheClearable) - lowReserved);
3224                 }
3225             } else {
3226                 // When we don't have fast quota information, we ignore cached
3227                 // data and only consider unused bytes.
3228                 if ((flags & StorageManager.FLAG_ALLOCATE_AGGRESSIVE) != 0) {
3229                     return Math.max(0, usable - fullReserved);
3230                 } else {
3231                     return Math.max(0, usable - lowReserved);
3232                 }
3233             }
3234         } catch (IOException e) {
3235             throw new ParcelableException(e);
3236         } finally {
3237             Binder.restoreCallingIdentity(token);
3238         }
3239     }
3240 
3241     @Override
allocateBytes(String volumeUuid, long bytes, int flags, String callingPackage)3242     public void allocateBytes(String volumeUuid, long bytes, int flags, String callingPackage) {
3243         flags = adjustAllocateFlags(flags, Binder.getCallingUid(), callingPackage);
3244 
3245         final long allocatableBytes = getAllocatableBytes(volumeUuid, flags, callingPackage);
3246         if (bytes > allocatableBytes) {
3247             throw new ParcelableException(new IOException("Failed to allocate " + bytes
3248                     + " because only " + allocatableBytes + " allocatable"));
3249         }
3250 
3251         final StorageManager storage = mContext.getSystemService(StorageManager.class);
3252         final long token = Binder.clearCallingIdentity();
3253         try {
3254             // Free up enough disk space to satisfy both the requested allocation
3255             // and our low disk warning space.
3256             final File path = storage.findPathForUuid(volumeUuid);
3257             if ((flags & StorageManager.FLAG_ALLOCATE_AGGRESSIVE) != 0) {
3258                 bytes += storage.getStorageFullBytes(path);
3259             } else {
3260                 bytes += storage.getStorageLowBytes(path);
3261             }
3262 
3263             mPmInternal.freeStorage(volumeUuid, bytes, flags);
3264         } catch (IOException e) {
3265             throw new ParcelableException(e);
3266         } finally {
3267             Binder.restoreCallingIdentity(token);
3268         }
3269     }
3270 
3271     private IAppOpsCallback.Stub mAppOpsCallback = new IAppOpsCallback.Stub() {
3272         @Override
3273         public void opChanged(int op, int uid, String packageName) throws RemoteException {
3274             if (!ENABLE_ISOLATED_STORAGE) return;
3275 
3276             remountUidExternalStorage(uid, getMountMode(uid, packageName));
3277         }
3278     };
3279 
addObbStateLocked(ObbState obbState)3280     private void addObbStateLocked(ObbState obbState) throws RemoteException {
3281         final IBinder binder = obbState.getBinder();
3282         List<ObbState> obbStates = mObbMounts.get(binder);
3283 
3284         if (obbStates == null) {
3285             obbStates = new ArrayList<ObbState>();
3286             mObbMounts.put(binder, obbStates);
3287         } else {
3288             for (final ObbState o : obbStates) {
3289                 if (o.rawPath.equals(obbState.rawPath)) {
3290                     throw new IllegalStateException("Attempt to add ObbState twice. "
3291                             + "This indicates an error in the StorageManagerService logic.");
3292                 }
3293             }
3294         }
3295 
3296         obbStates.add(obbState);
3297         try {
3298             obbState.link();
3299         } catch (RemoteException e) {
3300             /*
3301              * The binder died before we could link it, so clean up our state
3302              * and return failure.
3303              */
3304             obbStates.remove(obbState);
3305             if (obbStates.isEmpty()) {
3306                 mObbMounts.remove(binder);
3307             }
3308 
3309             // Rethrow the error so mountObb can get it
3310             throw e;
3311         }
3312 
3313         mObbPathToStateMap.put(obbState.rawPath, obbState);
3314     }
3315 
removeObbStateLocked(ObbState obbState)3316     private void removeObbStateLocked(ObbState obbState) {
3317         final IBinder binder = obbState.getBinder();
3318         final List<ObbState> obbStates = mObbMounts.get(binder);
3319         if (obbStates != null) {
3320             if (obbStates.remove(obbState)) {
3321                 obbState.unlink();
3322             }
3323             if (obbStates.isEmpty()) {
3324                 mObbMounts.remove(binder);
3325             }
3326         }
3327 
3328         mObbPathToStateMap.remove(obbState.rawPath);
3329     }
3330 
3331     private class ObbActionHandler extends Handler {
3332 
ObbActionHandler(Looper l)3333         ObbActionHandler(Looper l) {
3334             super(l);
3335         }
3336 
3337         @Override
handleMessage(Message msg)3338         public void handleMessage(Message msg) {
3339             switch (msg.what) {
3340                 case OBB_RUN_ACTION: {
3341                     final ObbAction action = (ObbAction) msg.obj;
3342 
3343                     if (DEBUG_OBB)
3344                         Slog.i(TAG, "OBB_RUN_ACTION: " + action.toString());
3345 
3346                     action.execute(this);
3347                     break;
3348                 }
3349                 case OBB_FLUSH_MOUNT_STATE: {
3350                     final String path = (String) msg.obj;
3351 
3352                     if (DEBUG_OBB)
3353                         Slog.i(TAG, "Flushing all OBB state for path " + path);
3354 
3355                     synchronized (mObbMounts) {
3356                         final List<ObbState> obbStatesToRemove = new LinkedList<ObbState>();
3357 
3358                         final Iterator<ObbState> i = mObbPathToStateMap.values().iterator();
3359                         while (i.hasNext()) {
3360                             final ObbState state = i.next();
3361 
3362                             /*
3363                              * If this entry's source file is in the volume path
3364                              * that got unmounted, remove it because it's no
3365                              * longer valid.
3366                              */
3367                             if (state.canonicalPath.startsWith(path)) {
3368                                 obbStatesToRemove.add(state);
3369                             }
3370                         }
3371 
3372                         for (final ObbState obbState : obbStatesToRemove) {
3373                             if (DEBUG_OBB)
3374                                 Slog.i(TAG, "Removing state for " + obbState.rawPath);
3375 
3376                             removeObbStateLocked(obbState);
3377 
3378                             try {
3379                                 obbState.token.onObbResult(obbState.rawPath, obbState.nonce,
3380                                         OnObbStateChangeListener.UNMOUNTED);
3381                             } catch (RemoteException e) {
3382                                 Slog.i(TAG, "Couldn't send unmount notification for  OBB: "
3383                                         + obbState.rawPath);
3384                             }
3385                         }
3386                     }
3387                     break;
3388                 }
3389             }
3390         }
3391     }
3392 
3393     private static class ObbException extends Exception {
3394         public final int status;
3395 
ObbException(int status, String message)3396         public ObbException(int status, String message) {
3397             super(message);
3398             this.status = status;
3399         }
3400 
ObbException(int status, Throwable cause)3401         public ObbException(int status, Throwable cause) {
3402             super(cause.getMessage(), cause);
3403             this.status = status;
3404         }
3405     }
3406 
3407     abstract class ObbAction {
3408 
3409         ObbState mObbState;
3410 
ObbAction(ObbState obbState)3411         ObbAction(ObbState obbState) {
3412             mObbState = obbState;
3413         }
3414 
execute(ObbActionHandler handler)3415         public void execute(ObbActionHandler handler) {
3416             try {
3417                 if (DEBUG_OBB)
3418                     Slog.i(TAG, "Starting to execute action: " + toString());
3419                 handleExecute();
3420             } catch (ObbException e) {
3421                 notifyObbStateChange(e);
3422             }
3423         }
3424 
handleExecute()3425         abstract void handleExecute() throws ObbException;
3426 
notifyObbStateChange(ObbException e)3427         protected void notifyObbStateChange(ObbException e) {
3428             Slog.w(TAG, e);
3429             notifyObbStateChange(e.status);
3430         }
3431 
notifyObbStateChange(int status)3432         protected void notifyObbStateChange(int status) {
3433             if (mObbState == null || mObbState.token == null) {
3434                 return;
3435             }
3436 
3437             try {
3438                 mObbState.token.onObbResult(mObbState.rawPath, mObbState.nonce, status);
3439             } catch (RemoteException e) {
3440                 Slog.w(TAG, "StorageEventListener went away while calling onObbStateChanged");
3441             }
3442         }
3443     }
3444 
3445     class MountObbAction extends ObbAction {
3446         private final String mKey;
3447         private final int mCallingUid;
3448         private ObbInfo mObbInfo;
3449 
MountObbAction(ObbState obbState, String key, int callingUid, ObbInfo obbInfo)3450         MountObbAction(ObbState obbState, String key, int callingUid, ObbInfo obbInfo) {
3451             super(obbState);
3452             mKey = key;
3453             mCallingUid = callingUid;
3454             mObbInfo = obbInfo;
3455         }
3456 
3457         @Override
handleExecute()3458         public void handleExecute() throws ObbException {
3459             warnOnNotMounted();
3460 
3461             if (!isUidOwnerOfPackageOrSystem(mObbInfo.packageName, mCallingUid)) {
3462                 throw new ObbException(ERROR_PERMISSION_DENIED, "Denied attempt to mount OBB "
3463                         + mObbInfo.filename + " which is owned by " + mObbInfo.packageName);
3464             }
3465 
3466             final boolean isMounted;
3467             synchronized (mObbMounts) {
3468                 isMounted = mObbPathToStateMap.containsKey(mObbState.rawPath);
3469             }
3470             if (isMounted) {
3471                 throw new ObbException(ERROR_ALREADY_MOUNTED,
3472                         "Attempt to mount OBB which is already mounted: " + mObbInfo.filename);
3473             }
3474 
3475             final String hashedKey;
3476             final String binderKey;
3477             if (mKey == null) {
3478                 hashedKey = "none";
3479                 binderKey = "";
3480             } else {
3481                 try {
3482                     SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
3483 
3484                     KeySpec ks = new PBEKeySpec(mKey.toCharArray(), mObbInfo.salt,
3485                             PBKDF2_HASH_ROUNDS, CRYPTO_ALGORITHM_KEY_SIZE);
3486                     SecretKey key = factory.generateSecret(ks);
3487                     BigInteger bi = new BigInteger(key.getEncoded());
3488                     hashedKey = bi.toString(16);
3489                     binderKey = hashedKey;
3490                 } catch (GeneralSecurityException e) {
3491                     throw new ObbException(ERROR_INTERNAL, e);
3492                 }
3493             }
3494 
3495             try {
3496                 mObbState.volId = mVold.createObb(mObbState.canonicalPath, binderKey,
3497                         mObbState.ownerGid);
3498                 mVold.mount(mObbState.volId, 0, -1);
3499 
3500                 if (DEBUG_OBB)
3501                     Slog.d(TAG, "Successfully mounted OBB " + mObbState.canonicalPath);
3502 
3503                 synchronized (mObbMounts) {
3504                     addObbStateLocked(mObbState);
3505                 }
3506 
3507                 notifyObbStateChange(MOUNTED);
3508             } catch (Exception e) {
3509                 throw new ObbException(ERROR_COULD_NOT_MOUNT, e);
3510             }
3511         }
3512 
3513         @Override
toString()3514         public String toString() {
3515             StringBuilder sb = new StringBuilder();
3516             sb.append("MountObbAction{");
3517             sb.append(mObbState);
3518             sb.append('}');
3519             return sb.toString();
3520         }
3521     }
3522 
3523     class UnmountObbAction extends ObbAction {
3524         private final boolean mForceUnmount;
3525 
UnmountObbAction(ObbState obbState, boolean force)3526         UnmountObbAction(ObbState obbState, boolean force) {
3527             super(obbState);
3528             mForceUnmount = force;
3529         }
3530 
3531         @Override
handleExecute()3532         public void handleExecute() throws ObbException {
3533             warnOnNotMounted();
3534 
3535             final ObbState existingState;
3536             synchronized (mObbMounts) {
3537                 existingState = mObbPathToStateMap.get(mObbState.rawPath);
3538             }
3539 
3540             if (existingState == null) {
3541                 throw new ObbException(ERROR_NOT_MOUNTED, "Missing existingState");
3542             }
3543 
3544             if (existingState.ownerGid != mObbState.ownerGid) {
3545                 notifyObbStateChange(new ObbException(ERROR_PERMISSION_DENIED,
3546                         "Permission denied to unmount OBB " + existingState.rawPath
3547                                 + " (owned by GID " + existingState.ownerGid + ")"));
3548                 return;
3549             }
3550 
3551             try {
3552                 mVold.unmount(mObbState.volId);
3553                 mVold.destroyObb(mObbState.volId);
3554                 mObbState.volId = null;
3555 
3556                 synchronized (mObbMounts) {
3557                     removeObbStateLocked(existingState);
3558                 }
3559 
3560                 notifyObbStateChange(UNMOUNTED);
3561             } catch (Exception e) {
3562                 throw new ObbException(ERROR_COULD_NOT_UNMOUNT, e);
3563             }
3564         }
3565 
3566         @Override
toString()3567         public String toString() {
3568             StringBuilder sb = new StringBuilder();
3569             sb.append("UnmountObbAction{");
3570             sb.append(mObbState);
3571             sb.append(",force=");
3572             sb.append(mForceUnmount);
3573             sb.append('}');
3574             return sb.toString();
3575         }
3576     }
3577 
dispatchOnStatus(IVoldTaskListener listener, int status, PersistableBundle extras)3578     private void dispatchOnStatus(IVoldTaskListener listener, int status,
3579             PersistableBundle extras) {
3580         if (listener != null) {
3581             try {
3582                 listener.onStatus(status, extras);
3583             } catch (RemoteException ignored) {
3584             }
3585         }
3586     }
3587 
dispatchOnFinished(IVoldTaskListener listener, int status, PersistableBundle extras)3588     private void dispatchOnFinished(IVoldTaskListener listener, int status,
3589             PersistableBundle extras) {
3590         if (listener != null) {
3591             try {
3592                 listener.onFinished(status, extras);
3593             } catch (RemoteException ignored) {
3594             }
3595         }
3596     }
3597 
getMountMode(int uid, String packageName)3598     private int getMountMode(int uid, String packageName) {
3599         final int mode = getMountModeInternal(uid, packageName);
3600         if (LOCAL_LOGV) {
3601             Slog.v(TAG, "Resolved mode " + mode + " for " + packageName + "/"
3602                     + UserHandle.formatUid(uid));
3603         }
3604         return mode;
3605     }
3606 
getMountModeInternal(int uid, String packageName)3607     private int getMountModeInternal(int uid, String packageName) {
3608         try {
3609             // Get some easy cases out of the way first
3610             if (Process.isIsolated(uid)) {
3611                 return Zygote.MOUNT_EXTERNAL_NONE;
3612             }
3613 
3614             final String[] packagesForUid = mIPackageManager.getPackagesForUid(uid);
3615             if (ArrayUtils.isEmpty(packagesForUid)) {
3616                 // It's possible the package got uninstalled already, so just ignore.
3617                 return Zygote.MOUNT_EXTERNAL_NONE;
3618             }
3619             if (packageName == null) {
3620                 packageName = packagesForUid[0];
3621             }
3622 
3623             if (mPmInternal.isInstantApp(packageName, UserHandle.getUserId(uid))) {
3624                 return Zygote.MOUNT_EXTERNAL_NONE;
3625             }
3626 
3627             // Determine if caller is holding runtime permission
3628             final boolean hasRead = StorageManager.checkPermissionAndCheckOp(mContext, false, 0,
3629                     uid, packageName, READ_EXTERNAL_STORAGE, OP_READ_EXTERNAL_STORAGE);
3630             final boolean hasWrite = StorageManager.checkPermissionAndCheckOp(mContext, false, 0,
3631                     uid, packageName, WRITE_EXTERNAL_STORAGE, OP_WRITE_EXTERNAL_STORAGE);
3632 
3633             // We're only willing to give out broad access if they also hold
3634             // runtime permission; this is a firm CDD requirement
3635             final boolean hasFull = mIPackageManager.checkUidPermission(WRITE_MEDIA_STORAGE,
3636                     uid) == PERMISSION_GRANTED;
3637             if (hasFull && hasWrite) {
3638                 return Zygote.MOUNT_EXTERNAL_FULL;
3639             }
3640 
3641             // We're only willing to give out installer access if they also hold
3642             // runtime permission; this is a firm CDD requirement
3643             final boolean hasInstall = mIPackageManager.checkUidPermission(INSTALL_PACKAGES,
3644                     uid) == PERMISSION_GRANTED;
3645             boolean hasInstallOp = false;
3646             // OP_REQUEST_INSTALL_PACKAGES is granted/denied per package but vold can't
3647             // update mountpoints of a specific package. So, check the appop for all packages
3648             // sharing the uid and allow same level of storage access for all packages even if
3649             // one of the packages has the appop granted.
3650             for (String uidPackageName : packagesForUid) {
3651                 if (mIAppOpsService.checkOperation(
3652                         OP_REQUEST_INSTALL_PACKAGES, uid, uidPackageName) == MODE_ALLOWED) {
3653                     hasInstallOp = true;
3654                     break;
3655                 }
3656             }
3657             if ((hasInstall || hasInstallOp) && hasWrite) {
3658                 return Zygote.MOUNT_EXTERNAL_WRITE;
3659             }
3660 
3661             // Otherwise we're willing to give out sandboxed or non-sandboxed if
3662             // they hold the runtime permission
3663             final boolean hasLegacy = mIAppOpsService.checkOperation(OP_LEGACY_STORAGE,
3664                     uid, packageName) == MODE_ALLOWED;
3665             if (hasLegacy && hasWrite) {
3666                 return Zygote.MOUNT_EXTERNAL_WRITE;
3667             } else if (hasLegacy && hasRead) {
3668                 return Zygote.MOUNT_EXTERNAL_READ;
3669             } else {
3670                 return Zygote.MOUNT_EXTERNAL_DEFAULT;
3671             }
3672         } catch (RemoteException e) {
3673             // Should not happen
3674         }
3675         return Zygote.MOUNT_EXTERNAL_NONE;
3676     }
3677 
3678     private static class Callbacks extends Handler {
3679         private static final int MSG_STORAGE_STATE_CHANGED = 1;
3680         private static final int MSG_VOLUME_STATE_CHANGED = 2;
3681         private static final int MSG_VOLUME_RECORD_CHANGED = 3;
3682         private static final int MSG_VOLUME_FORGOTTEN = 4;
3683         private static final int MSG_DISK_SCANNED = 5;
3684         private static final int MSG_DISK_DESTROYED = 6;
3685 
3686         private final RemoteCallbackList<IStorageEventListener>
3687                 mCallbacks = new RemoteCallbackList<>();
3688 
Callbacks(Looper looper)3689         public Callbacks(Looper looper) {
3690             super(looper);
3691         }
3692 
register(IStorageEventListener callback)3693         public void register(IStorageEventListener callback) {
3694             mCallbacks.register(callback);
3695         }
3696 
unregister(IStorageEventListener callback)3697         public void unregister(IStorageEventListener callback) {
3698             mCallbacks.unregister(callback);
3699         }
3700 
3701         @Override
handleMessage(Message msg)3702         public void handleMessage(Message msg) {
3703             final SomeArgs args = (SomeArgs) msg.obj;
3704             final int n = mCallbacks.beginBroadcast();
3705             for (int i = 0; i < n; i++) {
3706                 final IStorageEventListener callback = mCallbacks.getBroadcastItem(i);
3707                 try {
3708                     invokeCallback(callback, msg.what, args);
3709                 } catch (RemoteException ignored) {
3710                 }
3711             }
3712             mCallbacks.finishBroadcast();
3713             args.recycle();
3714         }
3715 
invokeCallback(IStorageEventListener callback, int what, SomeArgs args)3716         private void invokeCallback(IStorageEventListener callback, int what, SomeArgs args)
3717                 throws RemoteException {
3718             switch (what) {
3719                 case MSG_STORAGE_STATE_CHANGED: {
3720                     callback.onStorageStateChanged((String) args.arg1, (String) args.arg2,
3721                             (String) args.arg3);
3722                     break;
3723                 }
3724                 case MSG_VOLUME_STATE_CHANGED: {
3725                     callback.onVolumeStateChanged((VolumeInfo) args.arg1, args.argi2, args.argi3);
3726                     break;
3727                 }
3728                 case MSG_VOLUME_RECORD_CHANGED: {
3729                     callback.onVolumeRecordChanged((VolumeRecord) args.arg1);
3730                     break;
3731                 }
3732                 case MSG_VOLUME_FORGOTTEN: {
3733                     callback.onVolumeForgotten((String) args.arg1);
3734                     break;
3735                 }
3736                 case MSG_DISK_SCANNED: {
3737                     callback.onDiskScanned((DiskInfo) args.arg1, args.argi2);
3738                     break;
3739                 }
3740                 case MSG_DISK_DESTROYED: {
3741                     callback.onDiskDestroyed((DiskInfo) args.arg1);
3742                     break;
3743                 }
3744             }
3745         }
3746 
notifyStorageStateChanged(String path, String oldState, String newState)3747         private void notifyStorageStateChanged(String path, String oldState, String newState) {
3748             final SomeArgs args = SomeArgs.obtain();
3749             args.arg1 = path;
3750             args.arg2 = oldState;
3751             args.arg3 = newState;
3752             obtainMessage(MSG_STORAGE_STATE_CHANGED, args).sendToTarget();
3753         }
3754 
notifyVolumeStateChanged(VolumeInfo vol, int oldState, int newState)3755         private void notifyVolumeStateChanged(VolumeInfo vol, int oldState, int newState) {
3756             final SomeArgs args = SomeArgs.obtain();
3757             args.arg1 = vol.clone();
3758             args.argi2 = oldState;
3759             args.argi3 = newState;
3760             obtainMessage(MSG_VOLUME_STATE_CHANGED, args).sendToTarget();
3761         }
3762 
notifyVolumeRecordChanged(VolumeRecord rec)3763         private void notifyVolumeRecordChanged(VolumeRecord rec) {
3764             final SomeArgs args = SomeArgs.obtain();
3765             args.arg1 = rec.clone();
3766             obtainMessage(MSG_VOLUME_RECORD_CHANGED, args).sendToTarget();
3767         }
3768 
notifyVolumeForgotten(String fsUuid)3769         private void notifyVolumeForgotten(String fsUuid) {
3770             final SomeArgs args = SomeArgs.obtain();
3771             args.arg1 = fsUuid;
3772             obtainMessage(MSG_VOLUME_FORGOTTEN, args).sendToTarget();
3773         }
3774 
notifyDiskScanned(DiskInfo disk, int volumeCount)3775         private void notifyDiskScanned(DiskInfo disk, int volumeCount) {
3776             final SomeArgs args = SomeArgs.obtain();
3777             args.arg1 = disk.clone();
3778             args.argi2 = volumeCount;
3779             obtainMessage(MSG_DISK_SCANNED, args).sendToTarget();
3780         }
3781 
notifyDiskDestroyed(DiskInfo disk)3782         private void notifyDiskDestroyed(DiskInfo disk) {
3783             final SomeArgs args = SomeArgs.obtain();
3784             args.arg1 = disk.clone();
3785             obtainMessage(MSG_DISK_DESTROYED, args).sendToTarget();
3786         }
3787     }
3788 
3789     @Override
dump(FileDescriptor fd, PrintWriter writer, String[] args)3790     protected void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
3791         if (!DumpUtils.checkDumpPermission(mContext, TAG, writer)) return;
3792 
3793         final IndentingPrintWriter pw = new IndentingPrintWriter(writer, "  ", 160);
3794         synchronized (mLock) {
3795             pw.println("Disks:");
3796             pw.increaseIndent();
3797             for (int i = 0; i < mDisks.size(); i++) {
3798                 final DiskInfo disk = mDisks.valueAt(i);
3799                 disk.dump(pw);
3800             }
3801             pw.decreaseIndent();
3802 
3803             pw.println();
3804             pw.println("Volumes:");
3805             pw.increaseIndent();
3806             for (int i = 0; i < mVolumes.size(); i++) {
3807                 final VolumeInfo vol = mVolumes.valueAt(i);
3808                 if (VolumeInfo.ID_PRIVATE_INTERNAL.equals(vol.id)) continue;
3809                 vol.dump(pw);
3810             }
3811             pw.decreaseIndent();
3812 
3813             pw.println();
3814             pw.println("Records:");
3815             pw.increaseIndent();
3816             for (int i = 0; i < mRecords.size(); i++) {
3817                 final VolumeRecord note = mRecords.valueAt(i);
3818                 note.dump(pw);
3819             }
3820             pw.decreaseIndent();
3821 
3822             pw.println();
3823             pw.println("Primary storage UUID: " + mPrimaryStorageUuid);
3824 
3825             pw.println();
3826             final Pair<String, Long> pair = StorageManager.getPrimaryStoragePathAndSize();
3827             if (pair == null) {
3828                 pw.println("Internal storage total size: N/A");
3829             } else {
3830                 pw.print("Internal storage (");
3831                 pw.print(pair.first);
3832                 pw.print(") total size: ");
3833                 pw.print(pair.second);
3834                 pw.print(" (");
3835                 pw.print(DataUnit.MEBIBYTES.toBytes(pair.second));
3836                 pw.println(" MiB)");
3837             }
3838 
3839             pw.println();
3840             pw.println("Local unlocked users: " + Arrays.toString(mLocalUnlockedUsers));
3841             pw.println("System unlocked users: " + Arrays.toString(mSystemUnlockedUsers));
3842 
3843             final ContentResolver cr = mContext.getContentResolver();
3844             pw.println();
3845             pw.println("Isolated storage, local feature flag: "
3846                     + Settings.Global.getInt(cr, Settings.Global.ISOLATED_STORAGE_LOCAL, 0));
3847             pw.println("Isolated storage, remote feature flag: "
3848                     + Settings.Global.getInt(cr, Settings.Global.ISOLATED_STORAGE_REMOTE, 0));
3849             pw.println("Isolated storage, resolved: " + StorageManager.hasIsolatedStorage());
3850         }
3851 
3852         synchronized (mObbMounts) {
3853             pw.println();
3854             pw.println("mObbMounts:");
3855             pw.increaseIndent();
3856             final Iterator<Entry<IBinder, List<ObbState>>> binders = mObbMounts.entrySet()
3857                     .iterator();
3858             while (binders.hasNext()) {
3859                 Entry<IBinder, List<ObbState>> e = binders.next();
3860                 pw.println(e.getKey() + ":");
3861                 pw.increaseIndent();
3862                 final List<ObbState> obbStates = e.getValue();
3863                 for (final ObbState obbState : obbStates) {
3864                     pw.println(obbState);
3865                 }
3866                 pw.decreaseIndent();
3867             }
3868             pw.decreaseIndent();
3869 
3870             pw.println();
3871             pw.println("mObbPathToStateMap:");
3872             pw.increaseIndent();
3873             final Iterator<Entry<String, ObbState>> maps = mObbPathToStateMap.entrySet().iterator();
3874             while (maps.hasNext()) {
3875                 final Entry<String, ObbState> e = maps.next();
3876                 pw.print(e.getKey());
3877                 pw.print(" -> ");
3878                 pw.println(e.getValue());
3879             }
3880             pw.decreaseIndent();
3881         }
3882 
3883         pw.println();
3884         pw.print("Last maintenance: ");
3885         pw.println(TimeUtils.formatForLogging(mLastMaintenance));
3886     }
3887 
3888     /** {@inheritDoc} */
3889     @Override
monitor()3890     public void monitor() {
3891         try {
3892             mVold.monitor();
3893         } catch (Exception e) {
3894             Slog.wtf(TAG, e);
3895         }
3896     }
3897 
3898     private final class StorageManagerInternalImpl extends StorageManagerInternal {
3899         // Not guarded by a lock.
3900         private final CopyOnWriteArrayList<ExternalStorageMountPolicy> mPolicies =
3901                 new CopyOnWriteArrayList<>();
3902 
3903         @GuardedBy("mResetListeners")
3904         private final List<StorageManagerInternal.ResetListener> mResetListeners =
3905                 new ArrayList<>();
3906 
3907         @Override
addExternalStoragePolicy(ExternalStorageMountPolicy policy)3908         public void addExternalStoragePolicy(ExternalStorageMountPolicy policy) {
3909             // No locking - CopyOnWriteArrayList
3910             mPolicies.add(policy);
3911         }
3912 
3913         @Override
onExternalStoragePolicyChanged(int uid, String packageName)3914         public void onExternalStoragePolicyChanged(int uid, String packageName) {
3915             final int mountMode = getExternalStorageMountMode(uid, packageName);
3916             remountUidExternalStorage(uid, mountMode);
3917         }
3918 
3919         @Override
getExternalStorageMountMode(int uid, String packageName)3920         public int getExternalStorageMountMode(int uid, String packageName) {
3921             if (ENABLE_ISOLATED_STORAGE) {
3922                 return getMountMode(uid, packageName);
3923             }
3924             try {
3925                 if (packageName == null) {
3926                     final String[] packagesForUid = mIPackageManager.getPackagesForUid(uid);
3927                     packageName = packagesForUid[0];
3928                 }
3929             } catch (RemoteException e) {
3930                 // Should not happen - same process
3931             }
3932             // No locking - CopyOnWriteArrayList
3933             int mountMode = Integer.MAX_VALUE;
3934             for (ExternalStorageMountPolicy policy : mPolicies) {
3935                 final int policyMode = policy.getMountMode(uid, packageName);
3936                 if (policyMode == Zygote.MOUNT_EXTERNAL_NONE) {
3937                     return Zygote.MOUNT_EXTERNAL_NONE;
3938                 }
3939                 mountMode = Math.min(mountMode, policyMode);
3940             }
3941             if (mountMode == Integer.MAX_VALUE) {
3942                 return Zygote.MOUNT_EXTERNAL_NONE;
3943             }
3944             return mountMode;
3945         }
3946 
3947         @Override
addResetListener(StorageManagerInternal.ResetListener listener)3948         public void addResetListener(StorageManagerInternal.ResetListener listener) {
3949             synchronized (mResetListeners) {
3950                 mResetListeners.add(listener);
3951             }
3952         }
3953 
onReset(IVold vold)3954         public void onReset(IVold vold) {
3955             synchronized (mResetListeners) {
3956                 for (StorageManagerInternal.ResetListener listener : mResetListeners) {
3957                     listener.onReset(vold);
3958                 }
3959             }
3960         }
3961 
hasExternalStorage(int uid, String packageName)3962         public boolean hasExternalStorage(int uid, String packageName) {
3963             // No need to check for system uid. This avoids a deadlock between
3964             // PackageManagerService and AppOpsService.
3965             if (uid == Process.SYSTEM_UID) {
3966                 return true;
3967             }
3968             if (ENABLE_ISOLATED_STORAGE) {
3969                 return getMountMode(uid, packageName) != Zygote.MOUNT_EXTERNAL_NONE;
3970             }
3971             // No locking - CopyOnWriteArrayList
3972             for (ExternalStorageMountPolicy policy : mPolicies) {
3973                 final boolean policyHasStorage = policy.hasExternalStorage(uid, packageName);
3974                 if (!policyHasStorage) {
3975                     return false;
3976                 }
3977             }
3978             return true;
3979         }
3980 
onAppOpsChanged(int code, int uid, @Nullable String packageName, int mode)3981         public void onAppOpsChanged(int code, int uid,
3982                 @Nullable String packageName, int mode) {
3983             if (mode == MODE_ALLOWED && (code == OP_READ_EXTERNAL_STORAGE
3984                     || code == OP_WRITE_EXTERNAL_STORAGE
3985                     || code == OP_REQUEST_INSTALL_PACKAGES)) {
3986                 final long token = Binder.clearCallingIdentity();
3987                 try {
3988                     final UserManagerInternal userManagerInternal =
3989                             LocalServices.getService(UserManagerInternal.class);
3990                     if (userManagerInternal.isUserInitialized(UserHandle.getUserId(uid))) {
3991                         onExternalStoragePolicyChanged(uid, packageName);
3992                     }
3993                 } finally {
3994                     Binder.restoreCallingIdentity(token);
3995                 }
3996             }
3997         }
3998     }
3999 }
4000