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