blob: 6e8eca3f46cf1b1284b8eb75976ef9cafa664e43 [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
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
17package com.android.server;
18
Martijn Coenen496ac002020-01-08 14:55:53 +010019import static android.Manifest.permission.ACCESS_MTP;
Sudheer Shanka3a0df3b2018-12-12 12:43:43 -080020import static android.Manifest.permission.INSTALL_PACKAGES;
Jeff Sharkey6fd69942019-03-26 17:53:35 -060021import static android.Manifest.permission.READ_EXTERNAL_STORAGE;
22import static android.Manifest.permission.WRITE_EXTERNAL_STORAGE;
Sudheer Shanka3a0df3b2018-12-12 12:43:43 -080023import static android.Manifest.permission.WRITE_MEDIA_STORAGE;
Zim64726cb2019-11-27 13:06:34 +000024import static android.app.ActivityManager.PROCESS_STATE_NONEXISTENT;
Sudheer Shanka3a0df3b2018-12-12 12:43:43 -080025import static android.app.AppOpsManager.MODE_ALLOWED;
Jeff Sharkey11697f52018-12-13 10:14:42 -070026import static android.app.AppOpsManager.OP_LEGACY_STORAGE;
Zimb0dffde2020-01-29 18:45:52 +000027import static android.app.AppOpsManager.OP_MANAGE_EXTERNAL_STORAGE;
Jeff Sharkey6fd69942019-03-26 17:53:35 -060028import static android.app.AppOpsManager.OP_READ_EXTERNAL_STORAGE;
Sudheer Shanka3a0df3b2018-12-12 12:43:43 -080029import static android.app.AppOpsManager.OP_REQUEST_INSTALL_PACKAGES;
Jeff Sharkey6fd69942019-03-26 17:53:35 -060030import static android.app.AppOpsManager.OP_WRITE_EXTERNAL_STORAGE;
Zim3ce38492020-02-07 15:14:58 +000031import static android.content.pm.PackageManager.MATCH_ANY_USER;
32import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_AWARE;
33import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_UNAWARE;
34import static android.content.pm.PackageManager.MATCH_UNINSTALLED_PACKAGES;
Sudheer Shanka3a0df3b2018-12-12 12:43:43 -080035import static android.content.pm.PackageManager.PERMISSION_GRANTED;
Jeff Sharkey39466322018-12-05 19:19:52 -070036import static android.os.ParcelFileDescriptor.MODE_READ_WRITE;
Jeff Sharkey0095a822018-02-15 13:06:53 -070037import static android.os.storage.OnObbStateChangeListener.ERROR_ALREADY_MOUNTED;
38import static android.os.storage.OnObbStateChangeListener.ERROR_COULD_NOT_MOUNT;
39import static android.os.storage.OnObbStateChangeListener.ERROR_COULD_NOT_UNMOUNT;
40import static android.os.storage.OnObbStateChangeListener.ERROR_INTERNAL;
41import static android.os.storage.OnObbStateChangeListener.ERROR_NOT_MOUNTED;
42import static android.os.storage.OnObbStateChangeListener.ERROR_PERMISSION_DENIED;
43import static android.os.storage.OnObbStateChangeListener.MOUNTED;
44import static android.os.storage.OnObbStateChangeListener.UNMOUNTED;
shafik3acc77c2020-05-18 17:04:53 +010045import static android.os.storage.StorageManager.PROP_FORCED_SCOPED_STORAGE_WHITELIST;
Zim69e9c092020-01-21 13:32:32 +000046import static android.os.storage.StorageManager.PROP_FUSE;
47import static android.os.storage.StorageManager.PROP_SETTINGS_FUSE;
Jeff Sharkey5790af02018-08-13 17:42:54 -060048
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -070049import static com.android.internal.util.XmlUtils.readIntAttribute;
Jeff Sharkeye8a4b662015-06-27 15:43:45 -070050import static com.android.internal.util.XmlUtils.readLongAttribute;
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -070051import static com.android.internal.util.XmlUtils.readStringAttribute;
52import static com.android.internal.util.XmlUtils.writeIntAttribute;
Jeff Sharkeye8a4b662015-06-27 15:43:45 -070053import static com.android.internal.util.XmlUtils.writeLongAttribute;
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -070054import static com.android.internal.util.XmlUtils.writeStringAttribute;
Jeff Sharkey5790af02018-08-13 17:42:54 -060055
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -070056import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT;
57import static org.xmlpull.v1.XmlPullParser.START_TAG;
58
Jason parks8888c592011-01-20 22:46:41 -060059import android.Manifest;
Jeff Sharkeyef10ee02015-07-05 14:17:27 -070060import android.annotation.Nullable;
Xiaohui Chen621b3fc2015-10-02 14:41:42 -070061import android.app.ActivityManager;
Martijn Coenen7084c6a2019-11-22 16:32:09 +010062import android.app.ActivityManagerInternal;
Jeff Sharkey2d8b4e82013-09-17 17:30:33 -070063import android.app.AppOpsManager;
Jeff Sharkey14cbe522015-07-08 14:06:37 -070064import android.app.IActivityManager;
Jeff Sharkey9765e442017-12-14 22:15:14 -070065import android.app.KeyguardManager;
Pavel Grafovce72ef02018-01-10 17:14:11 +000066import android.app.admin.SecurityLog;
Jeff Sharkey9bed0702017-01-23 20:37:05 -070067import android.app.usage.StorageStatsManager;
Jeff Sharkeybcd262d2015-06-10 09:41:17 -070068import android.content.BroadcastReceiver;
Jeff Sharkeyb0c363b22018-12-15 11:53:03 -070069import android.content.ContentResolver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080070import android.content.Context;
71import android.content.Intent;
Jeff Sharkeybcd262d2015-06-10 09:41:17 -070072import android.content.IntentFilter;
Nandana Duttdc15bb42020-01-03 16:43:46 +000073import android.content.pm.ApplicationInfo;
Sudheer Shanka3a0df3b2018-12-12 12:43:43 -080074import android.content.pm.IPackageManager;
Jeff Sharkey275e3e42015-04-24 16:10:32 -070075import android.content.pm.IPackageMoveObserver;
76import android.content.pm.PackageManager;
Sudheer Shanka0a541a52018-07-31 13:21:11 -070077import android.content.pm.PackageManagerInternal;
Jeff Sharkey14cbe522015-07-08 14:06:37 -070078import android.content.pm.ProviderInfo;
Jeff Sharkeybcd262d2015-06-10 09:41:17 -070079import android.content.pm.UserInfo;
Elliott Hughesf839b4f2014-09-26 12:30:47 -070080import android.content.res.Configuration;
Kenny Root02c87302010-07-01 08:10:18 -070081import android.content.res.ObbInfo;
Daniel Colascione766b6322018-01-08 19:10:36 -080082import android.database.ContentObserver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080083import android.net.Uri;
Kenny Root02c87302010-07-01 08:10:18 -070084import android.os.Binder;
Jeff Sharkey4c099d02015-05-15 13:45:00 -070085import android.os.DropBoxManager;
Kenny Roota02b8b02010-08-05 16:14:17 -070086import android.os.Environment;
Suchi Amalapurapuc42e29e2010-02-22 16:03:53 -080087import android.os.Handler;
Dianne Hackbornefa92b22013-05-03 14:11:43 -070088import android.os.HandlerThread;
Kenny Roota02b8b02010-08-05 16:14:17 -070089import android.os.IBinder;
Jin Qian12690d52017-10-13 18:17:04 -070090import android.os.IStoraged;
Jeff Sharkey1019de92017-09-06 13:47:03 -060091import android.os.IVold;
Jeff Sharkey8058fe62017-09-13 11:50:33 -060092import android.os.IVoldListener;
Zim95eca1d2019-11-15 18:03:00 +000093import android.os.IVoldMountCallback;
Jeff Sharkeyb302c542017-09-15 12:57:59 -060094import android.os.IVoldTaskListener;
Daniel Sandler5f27ef42010-03-16 15:42:02 -040095import android.os.Looper;
Suchi Amalapurapuc42e29e2010-02-22 16:03:53 -080096import android.os.Message;
Daichi Hirono9e8d9e22015-11-13 14:37:00 +090097import android.os.ParcelFileDescriptor;
Jeff Sharkey500ce9e2017-02-12 02:39:24 -070098import android.os.ParcelableException;
Jeff Sharkeyb302c542017-09-15 12:57:59 -060099import android.os.PersistableBundle;
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700100import android.os.PowerManager;
Jeff Sharkey9527b222015-06-24 15:24:48 -0700101import android.os.Process;
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700102import android.os.RemoteCallbackList;
San Mehat4270e1e2010-01-29 05:32:19 -0800103import android.os.RemoteException;
Suchi Amalapurapufd3530f2010-01-18 00:15:59 -0800104import android.os.ServiceManager;
Paul Crowleyfc0b5192018-07-02 13:58:10 -0700105import android.os.ServiceSpecificException;
Jeff Sharkeyedcdaf62015-07-09 09:45:36 -0700106import android.os.SystemClock;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800107import android.os.SystemProperties;
Dianne Hackbornf02b60a2012-08-16 10:48:27 -0700108import android.os.UserHandle;
Emily Bernier92aa5a22014-07-07 10:11:48 -0400109import android.os.UserManager;
Sudheer Shankab1613982019-05-16 16:55:50 -0700110import android.os.UserManagerInternal;
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -0700111import android.os.storage.DiskInfo;
Kenny Roota02b8b02010-08-05 16:14:17 -0700112import android.os.storage.IObbActionListener;
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -0700113import android.os.storage.IStorageEventListener;
Sudheer Shanka2250d562016-11-07 15:41:02 -0800114import android.os.storage.IStorageManager;
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -0700115import android.os.storage.IStorageShutdownObserver;
Kenny Rootaf9d6672010-10-08 09:21:39 -0700116import android.os.storage.OnObbStateChangeListener;
Paul Lawrence46791e72014-04-03 09:10:26 -0700117import android.os.storage.StorageManager;
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -0700118import android.os.storage.StorageManagerInternal;
Mike Lockwood2f6a3882011-05-09 19:08:06 -0700119import android.os.storage.StorageVolume;
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -0700120import android.os.storage.VolumeInfo;
Jeff Sharkeyb36586a2015-04-27 08:42:28 -0700121import android.os.storage.VolumeRecord;
Jeff Sharkey5d0c55c2019-01-24 14:32:31 -0700122import android.provider.DeviceConfig;
Abhijeet Kaurde4e90a2020-05-14 11:44:15 +0100123import android.provider.DocumentsContract;
Martijn Coenen496ac002020-01-08 14:55:53 +0100124import android.provider.Downloads;
Jeff Sharkey14cbe522015-07-08 14:06:37 -0700125import android.provider.MediaStore;
Jeff Sharkeye8a4b662015-06-27 15:43:45 -0700126import android.provider.Settings;
Inseob Kimc1246e62018-11-08 13:13:54 +0900127import android.sysprop.VoldProperties;
Jason parksf7b3cd42011-01-27 09:28:25 -0600128import android.text.TextUtils;
Jeff Sharkey1783f142015-04-17 10:52:51 -0700129import android.text.format.DateUtils;
Jeff Sharkey48877892015-03-18 11:27:19 -0700130import android.util.ArrayMap;
Jeff Sharkey04b4ba12019-12-15 22:42:42 -0700131import android.util.ArraySet;
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700132import android.util.AtomicFile;
Jeff Sharkey9f2dc052018-01-07 16:47:31 -0700133import android.util.DataUnit;
Abhijeet Kaurb9847712019-11-19 16:35:47 +0000134import android.util.FeatureFlagUtils;
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -0700135import android.util.Log;
Felipe Leme281389a2016-10-10 17:12:20 -0700136import android.util.Pair;
San Mehata5078592010-03-25 09:36:54 -0700137import android.util.Slog;
Jeff Sharkeye8a4b662015-06-27 15:43:45 -0700138import android.util.TimeUtils;
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700139import android.util.Xml;
Jeff Sharkey48877892015-03-18 11:27:19 -0700140
Jeff Sharkey8b2c3a142012-11-12 11:45:05 -0800141import com.android.internal.annotations.GuardedBy;
Sudheer Shankaff971bc2018-12-13 17:39:59 -0800142import com.android.internal.app.IAppOpsCallback;
Sudheer Shanka3a0df3b2018-12-12 12:43:43 -0800143import com.android.internal.app.IAppOpsService;
Zim3ce38492020-02-07 15:14:58 +0000144import com.android.internal.content.PackageMonitor;
Daichi Hirono9fb00182016-11-08 14:12:17 +0900145import com.android.internal.os.AppFuseMount;
Jeff Sharkey1019de92017-09-06 13:47:03 -0600146import com.android.internal.os.BackgroundThread;
Daichi Hirono812c95d2017-02-08 16:20:20 +0900147import com.android.internal.os.FuseUnavailableMountException;
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700148import com.android.internal.os.SomeArgs;
Jeff Sharkey9527b222015-06-24 15:24:48 -0700149import com.android.internal.os.Zygote;
Jeff Sharkey48877892015-03-18 11:27:19 -0700150import com.android.internal.util.ArrayUtils;
Jeff Sharkey11697f52018-12-13 10:14:42 -0700151import com.android.internal.util.CollectionUtils;
Jeff Sharkeyfe9a53b2017-03-31 14:08:23 -0600152import com.android.internal.util.DumpUtils;
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700153import com.android.internal.util.FastXmlSerializer;
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -0800154import com.android.internal.util.HexDump;
Jeff Sharkey5aca2b82013-10-16 16:21:54 -0700155import com.android.internal.util.IndentingPrintWriter;
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700156import com.android.internal.util.Preconditions;
Jeff Sharkeyb9fe5372015-12-03 15:23:08 -0700157import com.android.internal.widget.LockPatternUtils;
Ricky Wai4482ab52019-12-10 19:08:18 +0000158import com.android.server.pm.Installer;
Daichi Hirono9fb00182016-11-08 14:12:17 +0900159import com.android.server.storage.AppFuseBridge;
Zim42f1e9f2019-08-15 17:35:00 +0100160import com.android.server.storage.StorageSessionController;
Zim17be6f92019-09-25 14:37:55 +0100161import com.android.server.storage.StorageSessionController.ExternalStorageServiceException;
Wale Ogunwale9e4f3e02018-05-17 09:35:39 -0700162import com.android.server.wm.ActivityTaskManagerInternal;
163import com.android.server.wm.ActivityTaskManagerInternal.ScreenObserver;
Jeff Sharkey5217cac2015-12-20 15:34:01 -0700164
Jeff Sharkey5790af02018-08-13 17:42:54 -0600165import libcore.io.IoUtils;
166import libcore.util.EmptyArray;
167
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700168import org.xmlpull.v1.XmlPullParser;
169import org.xmlpull.v1.XmlPullParserException;
170import org.xmlpull.v1.XmlSerializer;
171
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700172import java.io.File;
Kenny Root38cf8862010-09-26 14:18:51 -0700173import java.io.FileDescriptor;
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700174import java.io.FileInputStream;
175import java.io.FileNotFoundException;
Christopher Tate7265abe2014-11-21 13:54:45 -0800176import java.io.FileOutputStream;
Kenny Root05105f72010-09-22 17:29:43 -0700177import java.io.IOException;
Kenny Root38cf8862010-09-26 14:18:51 -0700178import java.io.PrintWriter;
Kenny Root3b1abba2010-10-13 15:00:07 -0700179import java.math.BigInteger;
Paul Lawrence8e397362014-01-27 15:22:30 -0800180import java.nio.charset.StandardCharsets;
Jeff Sharkey0095a822018-02-15 13:06:53 -0700181import java.security.GeneralSecurityException;
Kenny Root3b1abba2010-10-13 15:00:07 -0700182import java.security.spec.KeySpec;
San Mehat22dd86e2010-01-12 12:21:18 -0800183import java.util.ArrayList;
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -0800184import java.util.Arrays;
Kenny Roota02b8b02010-08-05 16:14:17 -0700185import java.util.HashMap;
Kenny Root38cf8862010-09-26 14:18:51 -0700186import java.util.Iterator;
Kenny Roota02b8b02010-08-05 16:14:17 -0700187import java.util.LinkedList;
188import java.util.List;
Elliott Hughesf839b4f2014-09-26 12:30:47 -0700189import java.util.Locale;
Kenny Roota02b8b02010-08-05 16:14:17 -0700190import java.util.Map;
Kenny Root38cf8862010-09-26 14:18:51 -0700191import java.util.Map.Entry;
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700192import java.util.Objects;
Zim3ce38492020-02-07 15:14:58 +0000193import java.util.Set;
Svet Ganov6ee871e2015-07-10 14:29:33 -0700194import java.util.concurrent.CopyOnWriteArrayList;
Kenny Root51a573c2012-05-17 13:30:28 -0700195import java.util.concurrent.CountDownLatch;
196import java.util.concurrent.TimeUnit;
Jeff Sharkeyedcdaf62015-07-09 09:45:36 -0700197import java.util.concurrent.TimeoutException;
Martijn Coenen9fd2b642019-12-24 13:04:36 +0100198import java.util.regex.Matcher;
199import java.util.regex.Pattern;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800200
Kenny Root3b1abba2010-10-13 15:00:07 -0700201import javax.crypto.SecretKey;
202import javax.crypto.SecretKeyFactory;
203import javax.crypto.spec.PBEKeySpec;
204
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800205/**
Jeff Sharkey48877892015-03-18 11:27:19 -0700206 * Service responsible for various storage media. Connects to {@code vold} to
207 * watch for and manage dynamically added storage, such as SD cards and USB mass
208 * storage. Also decides how storage should be presented to users on the device.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800209 */
Jeff Sharkey9765e442017-12-14 22:15:14 -0700210class StorageManagerService extends IStorageManager.Stub
211 implements Watchdog.Monitor, ScreenObserver {
Jason parks5af0b912010-11-29 09:05:25 -0600212
Christopher Tated417d622013-08-19 16:14:25 -0700213 // Static direct instance pointer for the tightly-coupled idle service to use
Sudheer Shanka2250d562016-11-07 15:41:02 -0800214 static StorageManagerService sSelf = null;
Christopher Tated417d622013-08-19 16:14:25 -0700215
Daniel Colascione766b6322018-01-08 19:10:36 -0800216 /* Read during boot to decide whether to enable zram when available */
217 private static final String ZRAM_ENABLED_PROPERTY =
Sudheer Shanka0a541a52018-07-31 13:21:11 -0700218 "persist.sys.zram_enabled";
219
Jeff Sharkey10ec9d82018-11-28 14:52:45 -0700220 private static final boolean ENABLE_ISOLATED_STORAGE = StorageManager.hasIsolatedStorage();
Sudheer Shanka0a541a52018-07-31 13:21:11 -0700221
Ricky Wai64167472020-04-08 16:14:37 +0100222 // A system property to control if obb app data isolation is enabled in vold.
223 private static final String ANDROID_VOLD_APP_DATA_ISOLATION_ENABLED_PROPERTY =
224 "persist.sys.vold_app_data_isolation_enabled";
225
Martijn Coenenab0c7402020-06-17 14:42:13 +0200226 // How long we wait to reset storage, if we failed to call onMount on the
227 // external storage service.
228 public static final int FAILED_MOUNT_RESET_TIMEOUT_SECONDS = 10;
Matt Pape19ea8a62019-03-18 10:38:25 -0700229 /**
230 * If {@code 1}, enables the isolated storage feature. If {@code -1},
231 * disables the isolated storage feature. If {@code 0}, uses the default
232 * value from the build system.
233 */
234 private static final String ISOLATED_STORAGE_ENABLED = "isolated_storage_enabled";
235
shafikb2992b62019-10-01 15:31:02 +0100236 /**
237 * If {@code 1}, enables FuseDaemon to intercept file system ops. If {@code -1},
238 * disables FuseDaemon. If {@code 0}, uses the default value from the build system.
239 */
240 private static final String FUSE_ENABLED = "fuse_enabled";
Zime074df22020-01-21 13:48:09 +0000241 private static final boolean DEFAULT_FUSE_ENABLED = true;
shafikb2992b62019-10-01 15:31:02 +0100242
Linus Tufvesson4e0ff022020-03-27 14:53:30 +0000243 @GuardedBy("mLock")
Ricky Wai486d7602020-02-28 16:37:07 +0000244 private final Set<Integer> mFuseMountedUser = new ArraySet<>();
245
Jeff Sharkey56e62932015-03-21 20:41:00 -0700246 public static class Lifecycle extends SystemService {
Sudheer Shanka2250d562016-11-07 15:41:02 -0800247 private StorageManagerService mStorageManagerService;
Jeff Sharkey56e62932015-03-21 20:41:00 -0700248
249 public Lifecycle(Context context) {
250 super(context);
251 }
252
253 @Override
254 public void onStart() {
Sudheer Shanka2250d562016-11-07 15:41:02 -0800255 mStorageManagerService = new StorageManagerService(getContext());
256 publishBinderService("mount", mStorageManagerService);
257 mStorageManagerService.start();
Jeff Sharkey56e62932015-03-21 20:41:00 -0700258 }
259
260 @Override
261 public void onBootPhase(int phase) {
Jeff Sharkey11697f52018-12-13 10:14:42 -0700262 if (phase == SystemService.PHASE_SYSTEM_SERVICES_READY) {
263 mStorageManagerService.servicesReady();
264 } else if (phase == SystemService.PHASE_ACTIVITY_MANAGER_READY) {
Sudheer Shanka2250d562016-11-07 15:41:02 -0800265 mStorageManagerService.systemReady();
Yasuhiro Matsuda87a38b52015-07-24 22:10:16 +0900266 } else if (phase == SystemService.PHASE_BOOT_COMPLETED) {
Sudheer Shanka2250d562016-11-07 15:41:02 -0800267 mStorageManagerService.bootCompleted();
Jeff Sharkey56e62932015-03-21 20:41:00 -0700268 }
269 }
Jeff Sharkey48877892015-03-18 11:27:19 -0700270
271 @Override
Jeff Sharkeyab15c392016-05-05 11:45:01 -0600272 public void onSwitchUser(int userHandle) {
Sudheer Shanka2250d562016-11-07 15:41:02 -0800273 mStorageManagerService.mCurrentUserId = userHandle;
Jeff Sharkeyab15c392016-05-05 11:45:01 -0600274 }
275
276 @Override
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700277 public void onUnlockUser(int userHandle) {
Sudheer Shanka2250d562016-11-07 15:41:02 -0800278 mStorageManagerService.onUnlockUser(userHandle);
Jeff Sharkey48877892015-03-18 11:27:19 -0700279 }
280
281 @Override
282 public void onCleanupUser(int userHandle) {
Sudheer Shanka2250d562016-11-07 15:41:02 -0800283 mStorageManagerService.onCleanupUser(userHandle);
Jeff Sharkey48877892015-03-18 11:27:19 -0700284 }
Martijn Coenen7084c6a2019-11-22 16:32:09 +0100285
286 @Override
287 public void onStopUser(int userHandle) {
288 mStorageManagerService.onStopUser(userHandle);
289 }
Zim3ce38492020-02-07 15:14:58 +0000290
291 @Override
Felipe Leme339b7142020-02-21 11:05:49 -0800292 public void onUserStarting(TargetUser user) {
Zim3ce38492020-02-07 15:14:58 +0000293 mStorageManagerService.snapshotAndMonitorLegacyStorageAppOp(user.getUserHandle());
294 }
Jeff Sharkey56e62932015-03-21 20:41:00 -0700295 }
296
Dianne Hackborn40e9f292012-11-27 19:12:23 -0800297 private static final boolean DEBUG_EVENTS = false;
Kenny Rootb7db2722011-01-25 16:39:35 -0800298 private static final boolean DEBUG_OBB = false;
Kenny Root02c87302010-07-01 08:10:18 -0700299
Jeff Sharkeyc3c72872018-06-06 15:35:53 -0600300 /**
301 * We now talk to vold over Binder, and it has its own internal lock to
302 * serialize certain calls. All long-running operations have been migrated
303 * to be async with callbacks, so we want watchdog to fire if vold wedges.
304 */
305 private static final boolean WATCHDOG_ENABLE = true;
Kenny Root07714d42011-08-17 17:49:28 -0700306
Jeff Sharkey00455bf2016-11-04 14:45:24 -0600307 /**
308 * Our goal is for all Android devices to be usable as development devices,
309 * which includes the new Direct Boot mode added in N. For devices that
310 * don't have native FBE support, we offer an emulation mode for developer
311 * testing purposes, but if it's prohibitively difficult to support this
312 * mode, it can be disabled for specific products using this flag.
313 */
314 private static final boolean EMULATE_FBE_SUPPORTED = true;
315
Sudheer Shanka2250d562016-11-07 15:41:02 -0800316 private static final String TAG = "StorageManagerService";
Jeff Sharkey6fd69942019-03-26 17:53:35 -0600317 private static final boolean LOCAL_LOGV = Log.isLoggable(TAG, Log.VERBOSE);
Jeff Sharkeye8a4b662015-06-27 15:43:45 -0700318
Jeff Sharkey9756d752015-05-14 21:07:42 -0700319 private static final String TAG_STORAGE_BENCHMARK = "storage_benchmark";
Jeff Sharkeye8a4b662015-06-27 15:43:45 -0700320 private static final String TAG_STORAGE_TRIM = "storage_trim";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800321
Jeff Sharkey275e3e42015-04-24 16:10:32 -0700322 /** Magic value sent by MoveTask.cpp */
323 private static final int MOVE_STATUS_COPY_FINISHED = 82;
324
Jeff Sharkey620b32b2015-04-23 19:36:02 -0700325 private static final int VERSION_INIT = 1;
326 private static final int VERSION_ADD_PRIMARY = 2;
Jeff Sharkeyfced5342015-05-10 14:53:34 -0700327 private static final int VERSION_FIX_PRIMARY = 3;
Jeff Sharkey620b32b2015-04-23 19:36:02 -0700328
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700329 private static final String TAG_VOLUMES = "volumes";
Jeff Sharkey620b32b2015-04-23 19:36:02 -0700330 private static final String ATTR_VERSION = "version";
331 private static final String ATTR_PRIMARY_STORAGE_UUID = "primaryStorageUuid";
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700332 private static final String TAG_VOLUME = "volume";
333 private static final String ATTR_TYPE = "type";
334 private static final String ATTR_FS_UUID = "fsUuid";
Jeff Sharkey5cc0df22015-06-17 19:44:05 -0700335 private static final String ATTR_PART_GUID = "partGuid";
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700336 private static final String ATTR_NICKNAME = "nickname";
337 private static final String ATTR_USER_FLAGS = "userFlags";
Jeff Sharkeye8a4b662015-06-27 15:43:45 -0700338 private static final String ATTR_CREATED_MILLIS = "createdMillis";
Jeff Sharkey3811f352019-05-14 11:54:36 -0600339 private static final String ATTR_LAST_SEEN_MILLIS = "lastSeenMillis";
Jeff Sharkeye8a4b662015-06-27 15:43:45 -0700340 private static final String ATTR_LAST_TRIM_MILLIS = "lastTrimMillis";
341 private static final String ATTR_LAST_BENCH_MILLIS = "lastBenchMillis";
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700342
Philip P. Moltmannc94ba822019-03-04 16:48:22 -0800343 private static final String[] ALL_STORAGE_PERMISSIONS = {
344 Manifest.permission.READ_EXTERNAL_STORAGE,
Philip P. Moltmann129a0b02019-03-27 12:24:45 -0700345 Manifest.permission.WRITE_EXTERNAL_STORAGE
Philip P. Moltmannc94ba822019-03-04 16:48:22 -0800346 };
347
Zim9ce0a7c2020-03-04 07:34:27 +0000348 @Nullable public static String sMediaStoreAuthorityProcessName;
349
Jeff Sharkeyb36586a2015-04-27 08:42:28 -0700350 private final AtomicFile mSettingsFile;
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700351
Jeff Sharkey48877892015-03-18 11:27:19 -0700352 /**
353 * <em>Never</em> hold the lock while performing downcalls into vold, since
354 * unsolicited events can suddenly appear to update data structures.
355 */
Jeff Sharkey5f3e9342017-03-13 14:53:11 -0600356 private final Object mLock = LockGuard.installNewLock(LockGuard.INDEX_STORAGE);
Jeff Sharkey48877892015-03-18 11:27:19 -0700357
Sudheer Shanka0a541a52018-07-31 13:21:11 -0700358 /**
359 * Similar to {@link #mLock}, never hold this lock while performing downcalls into vold.
360 * Also, never hold this while calling into PackageManagerService since it is used in callbacks
361 * from PackageManagerService.
362 *
363 * If both {@link #mLock} and this lock need to be held, {@link #mLock} should be acquired
364 * before this.
365 *
366 * Use -PL suffix for methods that need to called with this lock held.
367 */
368 private final Object mPackagesLock = new Object();
369
Lee Shombertebe2a0b2020-01-23 10:02:15 -0800370 /**
371 * mLocalUnlockedUsers affects the return value of isUserUnlocked. If
372 * any value in the array changes, then the binder cache for
373 * isUserUnlocked must be invalidated. When adding mutating methods to
374 * WatchedLockedUsers, be sure to invalidate the cache in the new
375 * methods.
376 */
377 private class WatchedLockedUsers {
378 private int[] users = EmptyArray.INT;
379 public WatchedLockedUsers() {
Lee Shombert5473e172020-05-27 13:46:46 -0700380 invalidateIsUserUnlockedCache();
Lee Shombertebe2a0b2020-01-23 10:02:15 -0800381 }
382 public void append(int userId) {
383 users = ArrayUtils.appendInt(users, userId);
384 invalidateIsUserUnlockedCache();
385 }
386 public void remove(int userId) {
387 users = ArrayUtils.removeInt(users, userId);
388 invalidateIsUserUnlockedCache();
389 }
390 public boolean contains(int userId) {
391 return ArrayUtils.contains(users, userId);
392 }
393 public int[] all() {
394 return users;
395 }
396 @Override
397 public String toString() {
398 return Arrays.toString(users);
399 }
400 private void invalidateIsUserUnlockedCache() {
401 UserManager.invalidateIsUserUnlockedCache();
402 }
403 }
404
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700405 /** Set of users that we know are unlocked. */
Jeff Sharkey48877892015-03-18 11:27:19 -0700406 @GuardedBy("mLock")
Lee Shombertebe2a0b2020-01-23 10:02:15 -0800407 private WatchedLockedUsers mLocalUnlockedUsers = new WatchedLockedUsers();
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700408 /** Set of users that system knows are unlocked. */
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -0800409 @GuardedBy("mLock")
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700410 private int[] mSystemUnlockedUsers = EmptyArray.INT;
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700411
412 /** Map from disk ID to disk */
Jeff Sharkey48877892015-03-18 11:27:19 -0700413 @GuardedBy("mLock")
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -0700414 private ArrayMap<String, DiskInfo> mDisks = new ArrayMap<>();
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700415 /** Map from volume ID to disk */
Jeff Sharkey48877892015-03-18 11:27:19 -0700416 @GuardedBy("mLock")
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700417 private final ArrayMap<String, VolumeInfo> mVolumes = new ArrayMap<>();
Jeff Sharkey48877892015-03-18 11:27:19 -0700418
Jeff Sharkeyb36586a2015-04-27 08:42:28 -0700419 /** Map from UUID to record */
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700420 @GuardedBy("mLock")
Jeff Sharkeyb36586a2015-04-27 08:42:28 -0700421 private ArrayMap<String, VolumeRecord> mRecords = new ArrayMap<>();
Jeff Sharkey620b32b2015-04-23 19:36:02 -0700422 @GuardedBy("mLock")
423 private String mPrimaryStorageUuid;
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700424
Jeff Sharkeyeba260d2015-04-19 14:35:16 -0700425 /** Map from disk ID to latches */
426 @GuardedBy("mLock")
427 private ArrayMap<String, CountDownLatch> mDiskScanLatches = new ArrayMap<>();
428
Jeff Sharkey275e3e42015-04-24 16:10:32 -0700429 @GuardedBy("mLock")
430 private IPackageMoveObserver mMoveCallback;
431 @GuardedBy("mLock")
432 private String mMoveTargetUuid;
433
Martijn Coenen44db1ac2019-12-03 16:06:19 +0100434 private volatile int mMediaStoreAuthorityAppId = -1;
Zim74a9bba2019-09-03 20:49:13 +0100435
Martijn Coenen496ac002020-01-08 14:55:53 +0100436 private volatile int mDownloadsAuthorityAppId = -1;
437
Abhijeet Kaurde4e90a2020-05-14 11:44:15 +0100438 private volatile int mExternalStorageAuthorityAppId = -1;
439
Jeff Sharkeyab15c392016-05-05 11:45:01 -0600440 private volatile int mCurrentUserId = UserHandle.USER_SYSTEM;
441
Ricky Wai4482ab52019-12-10 19:08:18 +0000442 private final Installer mInstaller;
443
Daichi Hirono9fb00182016-11-08 14:12:17 +0900444 /** Holding lock for AppFuse business */
445 private final Object mAppFuseLock = new Object();
446
447 @GuardedBy("mAppFuseLock")
448 private int mNextAppFuseName = 0;
449
450 @GuardedBy("mAppFuseLock")
Daichi Hironoe56740d2017-02-02 13:56:45 +0900451 private AppFuseBridge mAppFuseBridge = null;
Daichi Hirono9fb00182016-11-08 14:12:17 +0900452
Martijn Coenen9fd2b642019-12-24 13:04:36 +0100453 /** Matches known application dir paths. The first group contains the generic part of the path,
454 * the second group contains the user id (or null if it's a public volume without users), the
455 * third group contains the package name, and the fourth group the remainder of the path.
456 */
457 public static final Pattern KNOWN_APP_DIR_PATHS = Pattern.compile(
458 "(?i)(^/storage/[^/]+/(?:([0-9]+)/)?Android/(?:data|media|obb|sandbox)/)([^/]+)(/.*)?");
459
460
Keun young Park37a49da2020-06-18 16:01:05 -0700461 /** Automotive device unlockes users before system boot complete and this requires special
462 * handling as vold reset can lead into race conditions. When this is set, all users unlocked
463 * in {@code UserManager} level are unlocked after vold reset.
464 */
465 private final boolean mIsAutomotive;
466
Jeff Sharkeyef10ee02015-07-05 14:17:27 -0700467 private VolumeInfo findVolumeByIdOrThrow(String id) {
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700468 synchronized (mLock) {
469 final VolumeInfo vol = mVolumes.get(id);
470 if (vol != null) {
471 return vol;
472 }
473 }
474 throw new IllegalArgumentException("No volume found for ID " + id);
475 }
476
Jeff Sharkeyef10ee02015-07-05 14:17:27 -0700477 private String findVolumeIdForPathOrThrow(String path) {
Jeff Sharkey48877892015-03-18 11:27:19 -0700478 synchronized (mLock) {
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -0700479 for (int i = 0; i < mVolumes.size(); i++) {
480 final VolumeInfo vol = mVolumes.valueAt(i);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700481 if (vol.path != null && path.startsWith(vol.path)) {
482 return vol.id;
Jeff Sharkey48877892015-03-18 11:27:19 -0700483 }
484 }
485 }
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700486 throw new IllegalArgumentException("No volume found for path " + path);
Jeff Sharkey48877892015-03-18 11:27:19 -0700487 }
488
Jeff Sharkeye8a4b662015-06-27 15:43:45 -0700489 private VolumeRecord findRecordForPath(String path) {
490 synchronized (mLock) {
491 for (int i = 0; i < mVolumes.size(); i++) {
492 final VolumeInfo vol = mVolumes.valueAt(i);
493 if (vol.path != null && path.startsWith(vol.path)) {
494 return mRecords.get(vol.fsUuid);
495 }
496 }
497 }
498 return null;
499 }
500
501 private String scrubPath(String path) {
502 if (path.startsWith(Environment.getDataDirectory().getAbsolutePath())) {
503 return "internal";
504 }
505 final VolumeRecord rec = findRecordForPath(path);
506 if (rec == null || rec.createdMillis == 0) {
507 return "unknown";
508 } else {
509 return "ext:" + (int) ((System.currentTimeMillis() - rec.createdMillis)
510 / DateUtils.WEEK_IN_MILLIS) + "w";
511 }
512 }
513
Jeff Sharkeyef10ee02015-07-05 14:17:27 -0700514 private @Nullable VolumeInfo findStorageForUuid(String volumeUuid) {
Jeff Sharkey275e3e42015-04-24 16:10:32 -0700515 final StorageManager storage = mContext.getSystemService(StorageManager.class);
516 if (Objects.equals(StorageManager.UUID_PRIVATE_INTERNAL, volumeUuid)) {
Zim17be6f92019-09-25 14:37:55 +0100517 return storage.findVolumeById(VolumeInfo.ID_EMULATED_INTERNAL + ";" + 0);
Jeff Sharkey275e3e42015-04-24 16:10:32 -0700518 } else if (Objects.equals(StorageManager.UUID_PRIMARY_PHYSICAL, volumeUuid)) {
519 return storage.getPrimaryPhysicalVolume();
520 } else {
521 return storage.findEmulatedForPrivate(storage.findVolumeByUuid(volumeUuid));
522 }
523 }
524
Jeff Sharkeye8a4b662015-06-27 15:43:45 -0700525 private boolean shouldBenchmark() {
526 final long benchInterval = Settings.Global.getLong(mContext.getContentResolver(),
527 Settings.Global.STORAGE_BENCHMARK_INTERVAL, DateUtils.WEEK_IN_MILLIS);
Jeff Sharkeye83d8a92015-09-09 14:53:38 -0700528 if (benchInterval == -1) {
529 return false;
530 } else if (benchInterval == 0) {
531 return true;
532 }
533
Jeff Sharkeye8a4b662015-06-27 15:43:45 -0700534 synchronized (mLock) {
535 for (int i = 0; i < mVolumes.size(); i++) {
536 final VolumeInfo vol = mVolumes.valueAt(i);
537 final VolumeRecord rec = mRecords.get(vol.fsUuid);
Jeff Sharkeye83d8a92015-09-09 14:53:38 -0700538 if (vol.isMountedWritable() && rec != null) {
Jeff Sharkeye8a4b662015-06-27 15:43:45 -0700539 final long benchAge = System.currentTimeMillis() - rec.lastBenchMillis;
540 if (benchAge >= benchInterval) {
541 return true;
542 }
543 }
544 }
545 return false;
546 }
547 }
548
Jeff Sharkeyeba260d2015-04-19 14:35:16 -0700549 private CountDownLatch findOrCreateDiskScanLatch(String diskId) {
550 synchronized (mLock) {
551 CountDownLatch latch = mDiskScanLatches.get(diskId);
552 if (latch == null) {
553 latch = new CountDownLatch(1);
554 mDiskScanLatches.put(diskId, latch);
555 }
556 return latch;
557 }
558 }
559
Paul Lawrence8e397362014-01-27 15:22:30 -0800560 /** List of crypto types.
561 * These must match CRYPT_TYPE_XXX in cryptfs.h AND their
562 * corresponding commands in CommandListener.cpp */
563 public static final String[] CRYPTO_TYPES
564 = { "password", "default", "pattern", "pin" };
565
Brian Carlstrom7395a8a2014-04-28 22:11:01 -0700566 private final Context mContext;
Jeff Sharkey5d0c55c2019-01-24 14:32:31 -0700567 private final ContentResolver mResolver;
Jeff Sharkeycd575992016-03-29 14:12:49 -0600568
Jeff Sharkey1019de92017-09-06 13:47:03 -0600569 private volatile IVold mVold;
Jin Qian12690d52017-10-13 18:17:04 -0700570 private volatile IStoraged mStoraged;
Jeff Sharkey1019de92017-09-06 13:47:03 -0600571
Yasuhiro Matsuda87a38b52015-07-24 22:10:16 +0900572 private volatile boolean mBootCompleted = false;
Jeff Sharkey48877892015-03-18 11:27:19 -0700573 private volatile boolean mDaemonConnected = false;
Jeff Sharkey9765e442017-12-14 22:15:14 -0700574 private volatile boolean mSecureKeyguardShowing = true;
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700575
Sudheer Shanka0a541a52018-07-31 13:21:11 -0700576 private PackageManagerInternal mPmInternal;
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700577
Sudheer Shanka3a0df3b2018-12-12 12:43:43 -0800578 private IPackageManager mIPackageManager;
579 private IAppOpsService mIAppOpsService;
580
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700581 private final Callbacks mCallbacks;
Jeff Sharkeyb9fe5372015-12-03 15:23:08 -0700582 private final LockPatternUtils mLockPatternUtils;
Jeff Sharkey48877892015-03-18 11:27:19 -0700583
San Mehat6cdd9c02010-02-09 14:45:20 -0800584 /**
Kenny Root3b1abba2010-10-13 15:00:07 -0700585 * The size of the crypto algorithm key in bits for OBB files. Currently
586 * Twofish is used which takes 128-bit keys.
587 */
588 private static final int CRYPTO_ALGORITHM_KEY_SIZE = 128;
589
590 /**
591 * The number of times to run SHA1 in the PBKDF2 function for OBB files.
592 * 1024 is reasonably secure and not too slow.
593 */
594 private static final int PBKDF2_HASH_ROUNDS = 1024;
595
596 /**
Kenny Roota02b8b02010-08-05 16:14:17 -0700597 * Mounted OBB tracking information. Used to track the current state of all
598 * OBBs.
Kenny Root02c87302010-07-01 08:10:18 -0700599 */
Kenny Root735de3b2010-09-30 14:11:39 -0700600 final private Map<IBinder, List<ObbState>> mObbMounts = new HashMap<IBinder, List<ObbState>>();
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700601
602 /** Map from raw paths to {@link ObbState}. */
Kenny Roota02b8b02010-08-05 16:14:17 -0700603 final private Map<String, ObbState> mObbPathToStateMap = new HashMap<String, ObbState>();
604
Svet Ganov6ee871e2015-07-10 14:29:33 -0700605 // Not guarded by a lock.
Sudheer Shanka2250d562016-11-07 15:41:02 -0800606 private final StorageManagerInternalImpl mStorageManagerInternal
607 = new StorageManagerInternalImpl();
Svet Ganov6ee871e2015-07-10 14:29:33 -0700608
Zim42f1e9f2019-08-15 17:35:00 +0100609 // Not guarded by a lock.
610 private final StorageSessionController mStorageSessionController;
611
Zim17be6f92019-09-25 14:37:55 +0100612 private final boolean mIsFuseEnabled;
613
Ricky Wai64167472020-04-08 16:14:37 +0100614 private final boolean mVoldAppDataIsolationEnabled;
615
Zim3ce38492020-02-07 15:14:58 +0000616 @GuardedBy("mLock")
617 private final Set<Integer> mUidsWithLegacyExternalStorage = new ArraySet<>();
618 // Not guarded by lock, always used on the ActivityManager thread
619 private final Map<Integer, PackageMonitor> mPackageMonitorsForUser = new ArrayMap<>();
620
621
Kenny Roota02b8b02010-08-05 16:14:17 -0700622 class ObbState implements IBinder.DeathRecipient {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700623 public ObbState(String rawPath, String canonicalPath, int callingUid,
Jeff Sharkey41cd6812017-09-11 10:32:17 -0600624 IObbActionListener token, int nonce, String volId) {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700625 this.rawPath = rawPath;
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700626 this.canonicalPath = canonicalPath;
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700627 this.ownerGid = UserHandle.getSharedAppGid(callingUid);
Kenny Rootaf9d6672010-10-08 09:21:39 -0700628 this.token = token;
629 this.nonce = nonce;
Jeff Sharkey41cd6812017-09-11 10:32:17 -0600630 this.volId = volId;
Kenny Roota02b8b02010-08-05 16:14:17 -0700631 }
632
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700633 final String rawPath;
634 final String canonicalPath;
Kenny Roota02b8b02010-08-05 16:14:17 -0700635
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700636 final int ownerGid;
Kenny Roota02b8b02010-08-05 16:14:17 -0700637
Kenny Rootaf9d6672010-10-08 09:21:39 -0700638 // Token of remote Binder caller
639 final IObbActionListener token;
640
641 // Identifier to pass back to the token
642 final int nonce;
Kenny Roota02b8b02010-08-05 16:14:17 -0700643
Jeff Sharkey41cd6812017-09-11 10:32:17 -0600644 String volId;
645
Kenny Root735de3b2010-09-30 14:11:39 -0700646 public IBinder getBinder() {
647 return token.asBinder();
648 }
649
Kenny Roota02b8b02010-08-05 16:14:17 -0700650 @Override
651 public void binderDied() {
652 ObbAction action = new UnmountObbAction(this, true);
653 mObbActionHandler.sendMessage(mObbActionHandler.obtainMessage(OBB_RUN_ACTION, action));
Kenny Root735de3b2010-09-30 14:11:39 -0700654 }
Kenny Roota02b8b02010-08-05 16:14:17 -0700655
Kenny Root5919ac62010-10-05 09:49:40 -0700656 public void link() throws RemoteException {
657 getBinder().linkToDeath(this, 0);
658 }
659
660 public void unlink() {
Kenny Root735de3b2010-09-30 14:11:39 -0700661 getBinder().unlinkToDeath(this, 0);
Kenny Roota02b8b02010-08-05 16:14:17 -0700662 }
Kenny Root38cf8862010-09-26 14:18:51 -0700663
664 @Override
665 public String toString() {
666 StringBuilder sb = new StringBuilder("ObbState{");
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700667 sb.append("rawPath=").append(rawPath);
668 sb.append(",canonicalPath=").append(canonicalPath);
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700669 sb.append(",ownerGid=").append(ownerGid);
670 sb.append(",token=").append(token);
671 sb.append(",binder=").append(getBinder());
Jeff Sharkey41cd6812017-09-11 10:32:17 -0600672 sb.append(",volId=").append(volId);
Kenny Root38cf8862010-09-26 14:18:51 -0700673 sb.append('}');
674 return sb.toString();
675 }
Kenny Roota02b8b02010-08-05 16:14:17 -0700676 }
677
678 // OBB Action Handler
679 final private ObbActionHandler mObbActionHandler;
680
681 // OBB action handler messages
682 private static final int OBB_RUN_ACTION = 1;
Sudheer Shanka25469aa2018-08-27 15:50:23 -0700683 private static final int OBB_FLUSH_MOUNT_STATE = 2;
Kenny Root02c87302010-07-01 08:10:18 -0700684
Christopher Tate7265abe2014-11-21 13:54:45 -0800685 // Last fstrim operation tracking
686 private static final String LAST_FSTRIM_FILE = "last-fstrim";
687 private final File mLastMaintenanceFile;
688 private long mLastMaintenance;
689
Kenny Root02c87302010-07-01 08:10:18 -0700690 // Handler messages
Jeff Sharkey48877892015-03-18 11:27:19 -0700691 private static final int H_SYSTEM_READY = 1;
692 private static final int H_DAEMON_CONNECTED = 2;
693 private static final int H_SHUTDOWN = 3;
694 private static final int H_FSTRIM = 4;
695 private static final int H_VOLUME_MOUNT = 5;
696 private static final int H_VOLUME_BROADCAST = 6;
Jeff Sharkeyabc3e852015-08-03 14:41:13 -0700697 private static final int H_INTERNAL_BROADCAST = 7;
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700698 private static final int H_VOLUME_UNMOUNT = 8;
Jeff Sharkey5a9bb742015-11-03 10:15:57 -0800699 private static final int H_PARTITION_FORGET = 9;
700 private static final int H_RESET = 10;
Jin Qiana85b9912017-10-17 15:48:18 -0700701 private static final int H_RUN_IDLE_MAINT = 11;
702 private static final int H_ABORT_IDLE_MAINT = 12;
Daniel Rosenberg137aed12019-03-15 18:41:11 -0700703 private static final int H_BOOT_COMPLETED = 13;
Narayan Kamath157dd1d2019-06-12 13:06:30 +0100704 private static final int H_COMPLETE_UNLOCK_USER = 14;
Abhijeet Kaur29dc0892020-03-12 18:14:24 +0000705 private static final int H_VOLUME_STATE_CHANGED = 15;
Suchi Amalapurapu6ffce2e2010-03-08 14:48:40 -0800706
Sudheer Shanka2250d562016-11-07 15:41:02 -0800707 class StorageManagerServiceHandler extends Handler {
708 public StorageManagerServiceHandler(Looper looper) {
Jeff Sharkey48877892015-03-18 11:27:19 -0700709 super(looper);
Daniel Sandler5f27ef42010-03-16 15:42:02 -0400710 }
711
Jason parks5af0b912010-11-29 09:05:25 -0600712 @Override
Suchi Amalapurapuc42e29e2010-02-22 16:03:53 -0800713 public void handleMessage(Message msg) {
714 switch (msg.what) {
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700715 case H_SYSTEM_READY: {
Jeff Sharkey48877892015-03-18 11:27:19 -0700716 handleSystemReady();
717 break;
718 }
Daniel Rosenberg137aed12019-03-15 18:41:11 -0700719 case H_BOOT_COMPLETED: {
720 handleBootCompleted();
721 break;
722 }
Jeff Sharkey48877892015-03-18 11:27:19 -0700723 case H_DAEMON_CONNECTED: {
724 handleDaemonConnected();
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700725 break;
726 }
Christopher Tated417d622013-08-19 16:14:25 -0700727 case H_FSTRIM: {
Christopher Tated417d622013-08-19 16:14:25 -0700728 Slog.i(TAG, "Running fstrim idle maintenance");
Christopher Tate7265abe2014-11-21 13:54:45 -0800729
730 // Remember when we kicked it off
731 try {
732 mLastMaintenance = System.currentTimeMillis();
733 mLastMaintenanceFile.setLastModified(mLastMaintenance);
734 } catch (Exception e) {
735 Slog.e(TAG, "Unable to record last fstrim!");
736 }
737
Jeff Sharkeyb302c542017-09-15 12:57:59 -0600738 // TODO: Reintroduce shouldBenchmark() test
Jeff Sharkey7e19f532017-11-06 13:54:11 -0700739 fstrim(0, null);
Christopher Tate7265abe2014-11-21 13:54:45 -0800740
Christopher Tated417d622013-08-19 16:14:25 -0700741 // invoke the completion callback, if any
Jeff Sharkeye8a4b662015-06-27 15:43:45 -0700742 // TODO: fstrim is non-blocking, so remove this useless callback
Christopher Tated417d622013-08-19 16:14:25 -0700743 Runnable callback = (Runnable) msg.obj;
744 if (callback != null) {
745 callback.run();
746 }
747 break;
748 }
Jeff Sharkey48877892015-03-18 11:27:19 -0700749 case H_SHUTDOWN: {
Sudheer Shanka2250d562016-11-07 15:41:02 -0800750 final IStorageShutdownObserver obs = (IStorageShutdownObserver) msg.obj;
Jeff Sharkey48877892015-03-18 11:27:19 -0700751 boolean success = false;
752 try {
Jeff Sharkey54402792017-09-15 16:05:19 -0600753 mVold.shutdown();
754 success = true;
Jeff Sharkeyace874b2017-09-07 15:27:33 -0600755 } catch (Exception e) {
756 Slog.wtf(TAG, e);
Jeff Sharkey48877892015-03-18 11:27:19 -0700757 }
758 if (obs != null) {
759 try {
760 obs.onShutDownComplete(success ? 0 : -1);
Jeff Sharkeyace874b2017-09-07 15:27:33 -0600761 } catch (Exception ignored) {
Jeff Sharkey48877892015-03-18 11:27:19 -0700762 }
763 }
764 break;
765 }
766 case H_VOLUME_MOUNT: {
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -0700767 final VolumeInfo vol = (VolumeInfo) msg.obj;
Jeff Sharkey2e606d72015-07-27 14:19:54 -0700768 if (isMountDisallowed(vol)) {
769 Slog.i(TAG, "Ignoring mount " + vol.getId() + " due to policy");
770 break;
771 }
Zim42f1e9f2019-08-15 17:35:00 +0100772
Zim17be6f92019-09-25 14:37:55 +0100773 mount(vol);
Jeff Sharkey48877892015-03-18 11:27:19 -0700774 break;
775 }
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700776 case H_VOLUME_UNMOUNT: {
777 final VolumeInfo vol = (VolumeInfo) msg.obj;
Sudheer Shanka3f0645b2018-09-18 13:07:59 -0700778 unmount(vol);
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700779 break;
780 }
Jeff Sharkey48877892015-03-18 11:27:19 -0700781 case H_VOLUME_BROADCAST: {
782 final StorageVolume userVol = (StorageVolume) msg.obj;
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700783 final String envState = userVol.getState();
784 Slog.d(TAG, "Volume " + userVol.getId() + " broadcasting " + envState + " to "
Jeff Sharkey48877892015-03-18 11:27:19 -0700785 + userVol.getOwner());
786
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700787 final String action = VolumeInfo.getBroadcastForEnvironment(envState);
Jeff Sharkey48877892015-03-18 11:27:19 -0700788 if (action != null) {
789 final Intent intent = new Intent(action,
790 Uri.fromFile(userVol.getPathFile()));
791 intent.putExtra(StorageVolume.EXTRA_STORAGE_VOLUME, userVol);
Jeff Sharkey082f83b2017-03-26 14:34:47 -0600792 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT
793 | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
Jeff Sharkey48877892015-03-18 11:27:19 -0700794 mContext.sendBroadcastAsUser(intent, userVol.getOwner());
795 }
796 break;
797 }
Jeff Sharkeyabc3e852015-08-03 14:41:13 -0700798 case H_INTERNAL_BROADCAST: {
799 // Internal broadcasts aimed at system components, not for
800 // third-party apps.
801 final Intent intent = (Intent) msg.obj;
802 mContext.sendBroadcastAsUser(intent, UserHandle.ALL,
803 android.Manifest.permission.WRITE_MEDIA_STORAGE);
Jeff Sharkey5a9bb742015-11-03 10:15:57 -0800804 break;
805 }
806 case H_PARTITION_FORGET: {
Jeff Sharkeydb4b6192017-10-24 11:08:50 -0600807 final VolumeRecord rec = (VolumeRecord) msg.obj;
808 forgetPartition(rec.partGuid, rec.fsUuid);
Jeff Sharkey5a9bb742015-11-03 10:15:57 -0800809 break;
810 }
811 case H_RESET: {
Daniel Rosenberg137aed12019-03-15 18:41:11 -0700812 resetIfBootedAndConnected();
Jeff Sharkey5a9bb742015-11-03 10:15:57 -0800813 break;
Jeff Sharkeyabc3e852015-08-03 14:41:13 -0700814 }
Jin Qiana85b9912017-10-17 15:48:18 -0700815 case H_RUN_IDLE_MAINT: {
816 Slog.i(TAG, "Running idle maintenance");
817 runIdleMaint((Runnable)msg.obj);
818 break;
819 }
820 case H_ABORT_IDLE_MAINT: {
821 Slog.i(TAG, "Aborting idle maintenance");
822 abortIdleMaint((Runnable)msg.obj);
823 break;
824 }
Narayan Kamath157dd1d2019-06-12 13:06:30 +0100825 case H_COMPLETE_UNLOCK_USER: {
826 completeUnlockUser((int) msg.obj);
827 break;
828 }
Abhijeet Kaur29dc0892020-03-12 18:14:24 +0000829 case H_VOLUME_STATE_CHANGED: {
830 final SomeArgs args = (SomeArgs) msg.obj;
Linus Tufvesson4e0ff022020-03-27 14:53:30 +0000831 onVolumeStateChangedAsync((VolumeInfo) args.arg1, (int) args.arg2,
Abhijeet Kaur29dc0892020-03-12 18:14:24 +0000832 (int) args.arg3);
833 }
Suchi Amalapurapuc42e29e2010-02-22 16:03:53 -0800834 }
835 }
Jeff Sharkey48877892015-03-18 11:27:19 -0700836 }
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700837
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700838 private final Handler mHandler;
Suchi Amalapurapuc42e29e2010-02-22 16:03:53 -0800839
Jeff Sharkeybcd262d2015-06-10 09:41:17 -0700840 private BroadcastReceiver mUserReceiver = new BroadcastReceiver() {
841 @Override
842 public void onReceive(Context context, Intent intent) {
843 final String action = intent.getAction();
844 final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700845 Preconditions.checkArgument(userId >= 0);
Jeff Sharkeybcd262d2015-06-10 09:41:17 -0700846
847 try {
848 if (Intent.ACTION_USER_ADDED.equals(action)) {
849 final UserManager um = mContext.getSystemService(UserManager.class);
850 final int userSerialNumber = um.getUserSerialNumber(userId);
Jeff Sharkey54402792017-09-15 16:05:19 -0600851 mVold.onUserAdded(userId, userSerialNumber);
Jeff Sharkeybcd262d2015-06-10 09:41:17 -0700852 } else if (Intent.ACTION_USER_REMOVED.equals(action)) {
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700853 synchronized (mVolumes) {
854 final int size = mVolumes.size();
855 for (int i = 0; i < size; i++) {
856 final VolumeInfo vol = mVolumes.valueAt(i);
857 if (vol.mountUserId == userId) {
858 vol.mountUserId = UserHandle.USER_NULL;
859 mHandler.obtainMessage(H_VOLUME_UNMOUNT, vol).sendToTarget();
860 }
861 }
862 }
Jeff Sharkey54402792017-09-15 16:05:19 -0600863 mVold.onUserRemoved(userId);
Jeff Sharkeybcd262d2015-06-10 09:41:17 -0700864 }
Jeff Sharkeyace874b2017-09-07 15:27:33 -0600865 } catch (Exception e) {
866 Slog.wtf(TAG, e);
Jeff Sharkeybcd262d2015-06-10 09:41:17 -0700867 }
868 }
869 };
870
Jeff Sharkeyedcdaf62015-07-09 09:45:36 -0700871 private void waitForLatch(CountDownLatch latch, String condition, long timeoutMillis)
872 throws TimeoutException {
873 final long startMillis = SystemClock.elapsedRealtime();
Jeff Sharkeyeba260d2015-04-19 14:35:16 -0700874 while (true) {
Kenny Root51a573c2012-05-17 13:30:28 -0700875 try {
876 if (latch.await(5000, TimeUnit.MILLISECONDS)) {
San Mehat207e5382010-02-04 20:46:54 -0800877 return;
Kenny Root51a573c2012-05-17 13:30:28 -0700878 } else {
879 Slog.w(TAG, "Thread " + Thread.currentThread().getName()
Jeff Sharkey48877892015-03-18 11:27:19 -0700880 + " still waiting for " + condition + "...");
San Mehat207e5382010-02-04 20:46:54 -0800881 }
Kenny Root51a573c2012-05-17 13:30:28 -0700882 } catch (InterruptedException e) {
Jeff Sharkeyeba260d2015-04-19 14:35:16 -0700883 Slog.w(TAG, "Interrupt while waiting for " + condition);
San Mehat207e5382010-02-04 20:46:54 -0800884 }
Jeff Sharkeyedcdaf62015-07-09 09:45:36 -0700885 if (timeoutMillis > 0 && SystemClock.elapsedRealtime() > startMillis + timeoutMillis) {
886 throw new TimeoutException("Thread " + Thread.currentThread().getName()
887 + " gave up waiting for " + condition + " after " + timeoutMillis + "ms");
888 }
San Mehat207e5382010-02-04 20:46:54 -0800889 }
San Mehat1f6301e2010-01-07 22:40:27 -0800890 }
Kenny Root02c87302010-07-01 08:10:18 -0700891
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700892 private void handleSystemReady() {
Jeff Sharkey48877892015-03-18 11:27:19 -0700893 // Start scheduling nominally-daily fstrim operations
Christopher Tate115afda2014-06-06 19:06:26 -0700894 MountServiceIdler.scheduleIdlePass(mContext);
Daniel Colascione766b6322018-01-08 19:10:36 -0800895
896 // Toggle zram-enable system property in response to settings
897 mContext.getContentResolver().registerContentObserver(
898 Settings.Global.getUriFor(Settings.Global.ZRAM_ENABLED),
899 false /*notifyForDescendants*/,
900 new ContentObserver(null /* current thread */) {
901 @Override
902 public void onChange(boolean selfChange) {
903 refreshZramSettings();
904 }
905 });
906 refreshZramSettings();
Jeff Sharkeyb0c363b22018-12-15 11:53:03 -0700907
Srinivas Paladuguc8261752019-01-09 10:54:52 -0800908 // Schedule zram writeback unless zram is disabled by persist.sys.zram_enabled
909 String zramPropValue = SystemProperties.get(ZRAM_ENABLED_PROPERTY);
910 if (!zramPropValue.equals("0")
911 && mContext.getResources().getBoolean(
912 com.android.internal.R.bool.config_zramWriteback)) {
913 ZramWriteback.scheduleZramWriteback(mContext);
914 }
Jeff Sharkeyb0c363b22018-12-15 11:53:03 -0700915 // Toggle isolated-enable system property in response to settings
916 mContext.getContentResolver().registerContentObserver(
917 Settings.Global.getUriFor(Settings.Global.ISOLATED_STORAGE_REMOTE),
918 false /*notifyForDescendants*/,
919 new ContentObserver(null /* current thread */) {
920 @Override
921 public void onChange(boolean selfChange) {
922 refreshIsolatedStorageSettings();
923 }
924 });
Jeff Sharkey5d0c55c2019-01-24 14:32:31 -0700925 // For now, simply clone property when it changes
shafik91b34612019-09-23 15:41:44 +0100926 DeviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_STORAGE_NATIVE_BOOT,
Matt Pape15769e22019-04-19 12:31:24 -0700927 mContext.getMainExecutor(), (properties) -> {
Jeff Sharkey8b499a02019-01-28 13:31:50 -0700928 refreshIsolatedStorageSettings();
shafikb2992b62019-10-01 15:31:02 +0100929 refreshFuseSettings();
Jeff Sharkey5d0c55c2019-01-24 14:32:31 -0700930 });
Jeff Sharkeyb0c363b22018-12-15 11:53:03 -0700931 refreshIsolatedStorageSettings();
Daniel Colascione766b6322018-01-08 19:10:36 -0800932 }
933
934 /**
935 * Update the zram_enabled system property (which init reads to
936 * decide whether to enable zram) to reflect the zram_enabled
937 * preference (which we can change for experimentation purposes).
938 */
939 private void refreshZramSettings() {
940 String propertyValue = SystemProperties.get(ZRAM_ENABLED_PROPERTY);
941 if ("".equals(propertyValue)) {
942 return; // System doesn't have zram toggling support
943 }
944 String desiredPropertyValue =
945 Settings.Global.getInt(mContext.getContentResolver(),
946 Settings.Global.ZRAM_ENABLED,
947 1) != 0
948 ? "1" : "0";
949 if (!desiredPropertyValue.equals(propertyValue)) {
950 // Avoid redundant disk writes by setting only if we're
951 // changing the property value. There's no race: we're the
952 // sole writer.
953 SystemProperties.set(ZRAM_ENABLED_PROPERTY, desiredPropertyValue);
Srinivas Paladuguc8261752019-01-09 10:54:52 -0800954 // Schedule writeback only if zram is being enabled.
955 if (desiredPropertyValue.equals("1")
956 && mContext.getResources().getBoolean(
957 com.android.internal.R.bool.config_zramWriteback)) {
958 ZramWriteback.scheduleZramWriteback(mContext);
959 }
Daniel Colascione766b6322018-01-08 19:10:36 -0800960 }
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700961 }
962
Jeff Sharkeyb0c363b22018-12-15 11:53:03 -0700963 private void refreshIsolatedStorageSettings() {
Jeff Sharkey8b499a02019-01-28 13:31:50 -0700964 // Always copy value from newer DeviceConfig location
965 Settings.Global.putString(mResolver,
966 Settings.Global.ISOLATED_STORAGE_REMOTE,
shafik91b34612019-09-23 15:41:44 +0100967 DeviceConfig.getProperty(DeviceConfig.NAMESPACE_STORAGE_NATIVE_BOOT,
968 ISOLATED_STORAGE_ENABLED));
Jeff Sharkey8b499a02019-01-28 13:31:50 -0700969
Jeff Sharkeyb0c363b22018-12-15 11:53:03 -0700970 final int local = Settings.Global.getInt(mContext.getContentResolver(),
971 Settings.Global.ISOLATED_STORAGE_LOCAL, 0);
972 final int remote = Settings.Global.getInt(mContext.getContentResolver(),
973 Settings.Global.ISOLATED_STORAGE_REMOTE, 0);
974
975 // Walk down precedence chain; we prefer local settings first, then
976 // remote settings, before finally falling back to hard-coded default.
977 final boolean res;
978 if (local == -1) {
979 res = false;
980 } else if (local == 1) {
981 res = true;
982 } else if (remote == -1) {
983 res = false;
984 } else if (remote == 1) {
985 res = true;
986 } else {
Jeff Sharkey06376802019-02-11 12:20:02 -0700987 res = true;
Jeff Sharkeyb0c363b22018-12-15 11:53:03 -0700988 }
989
990 Slog.d(TAG, "Isolated storage local flag " + local + " and remote flag "
991 + remote + " resolved to " + res);
992 SystemProperties.set(StorageManager.PROP_ISOLATED_STORAGE, Boolean.toString(res));
993 }
994
Abhijeet Kaurb9847712019-11-19 16:35:47 +0000995 /**
996 * The most recent flag change takes precedence. Change fuse Settings flag if Device Config is
997 * changed. Settings flag change will in turn change fuse system property (persist.sys.fuse)
998 * whenever the user reboots.
999 */
shafikb2992b62019-10-01 15:31:02 +01001000 private void refreshFuseSettings() {
1001 int isFuseEnabled = DeviceConfig.getInt(DeviceConfig.NAMESPACE_STORAGE_NATIVE_BOOT,
1002 FUSE_ENABLED, 0);
1003 if (isFuseEnabled == 1) {
Abhijeet Kaurb9847712019-11-19 16:35:47 +00001004 Slog.d(TAG, "Device Config flag for FUSE is enabled, turn Settings fuse flag on");
1005 SystemProperties.set(FeatureFlagUtils.PERSIST_PREFIX
1006 + FeatureFlagUtils.SETTINGS_FUSE_FLAG, "true");
shafikb2992b62019-10-01 15:31:02 +01001007 } else if (isFuseEnabled == -1) {
Abhijeet Kaurb9847712019-11-19 16:35:47 +00001008 Slog.d(TAG, "Device Config flag for FUSE is disabled, turn Settings fuse flag off");
1009 SystemProperties.set(FeatureFlagUtils.PERSIST_PREFIX
1010 + FeatureFlagUtils.SETTINGS_FUSE_FLAG, "false");
shafikb2992b62019-10-01 15:31:02 +01001011 }
1012 // else, keep the build config.
Abhijeet Kaurb9847712019-11-19 16:35:47 +00001013 // This can be overridden by direct adjustment of persist.sys.fflag.override.settings_fuse
shafikb2992b62019-10-01 15:31:02 +01001014 }
1015
Jeff Sharkey14cbe522015-07-08 14:06:37 -07001016 /**
1017 * MediaProvider has a ton of code that makes assumptions about storage
1018 * paths never changing, so we outright kill them to pick up new state.
1019 */
1020 @Deprecated
Xiaohui Chen621b3fc2015-10-02 14:41:42 -07001021 private void killMediaProvider(List<UserInfo> users) {
1022 if (users == null) return;
1023
Jeff Sharkeyb3cf9532015-07-17 15:12:39 -07001024 final long token = Binder.clearCallingIdentity();
1025 try {
Xiaohui Chen621b3fc2015-10-02 14:41:42 -07001026 for (UserInfo user : users) {
1027 // System user does not have media provider, so skip.
1028 if (user.isSystemOnly()) continue;
1029
Jeff Sharkey5790af02018-08-13 17:42:54 -06001030 final ProviderInfo provider = mPmInternal.resolveContentProvider(
1031 MediaStore.AUTHORITY, PackageManager.MATCH_DIRECT_BOOT_AWARE
Jeff Sharkey8a372a02016-03-16 16:25:45 -06001032 | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
1033 user.id);
Xiaohui Chen621b3fc2015-10-02 14:41:42 -07001034 if (provider != null) {
Sudheer Shankadc589ac2016-11-10 15:30:17 -08001035 final IActivityManager am = ActivityManager.getService();
Xiaohui Chen621b3fc2015-10-02 14:41:42 -07001036 try {
Jeff Sharkey85f449e2016-06-23 09:26:00 -06001037 am.killApplication(provider.applicationInfo.packageName,
1038 UserHandle.getAppId(provider.applicationInfo.uid),
1039 UserHandle.USER_ALL, "vold reset");
Xiaohui Chen621b3fc2015-10-02 14:41:42 -07001040 // We only need to run this once. It will kill all users' media processes.
1041 break;
1042 } catch (RemoteException e) {
1043 }
Jeff Sharkeyb3cf9532015-07-17 15:12:39 -07001044 }
Jeff Sharkey14cbe522015-07-08 14:06:37 -07001045 }
Jeff Sharkeyb3cf9532015-07-17 15:12:39 -07001046 } finally {
1047 Binder.restoreCallingIdentity(token);
Jeff Sharkey14cbe522015-07-08 14:06:37 -07001048 }
1049 }
1050
Andreas Gampea36dc622018-02-05 17:19:22 -08001051 @GuardedBy("mLock")
Jeff Sharkey5a9bb742015-11-03 10:15:57 -08001052 private void addInternalVolumeLocked() {
Amith Yamasania7892482015-08-07 11:09:05 -07001053 // Create a stub volume that represents internal storage
1054 final VolumeInfo internal = new VolumeInfo(VolumeInfo.ID_PRIVATE_INTERNAL,
1055 VolumeInfo.TYPE_PRIVATE, null, null);
1056 internal.state = VolumeInfo.STATE_MOUNTED;
1057 internal.path = Environment.getDataDirectory().getAbsolutePath();
1058 mVolumes.put(internal.id, internal);
1059 }
1060
Daniel Rosenberg137aed12019-03-15 18:41:11 -07001061 private void initIfBootedAndConnected() {
1062 Slog.d(TAG, "Thinking about init, mBootCompleted=" + mBootCompleted
Jeff Sharkey8924e872015-11-30 12:52:10 -07001063 + ", mDaemonConnected=" + mDaemonConnected);
Eric Biggers1127d922019-04-05 12:46:35 -07001064 if (mBootCompleted && mDaemonConnected
1065 && !StorageManager.isFileEncryptedNativeOnly()) {
1066 // When booting a device without native support, make sure that our
1067 // user directories are locked or unlocked based on the current
1068 // emulation status.
1069 final boolean initLocked = StorageManager.isFileEncryptedEmulatedOnly();
1070 Slog.d(TAG, "Setting up emulation state, initlocked=" + initLocked);
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07001071 final List<UserInfo> users = mContext.getSystemService(UserManager.class).getUsers();
Jeff Sharkey8924e872015-11-30 12:52:10 -07001072 for (UserInfo user : users) {
1073 try {
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07001074 if (initLocked) {
Jeff Sharkey54402792017-09-15 16:05:19 -06001075 mVold.lockUserKey(user.id);
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07001076 } else {
Jeff Sharkey54402792017-09-15 16:05:19 -06001077 mVold.unlockUserKey(user.id, user.serialNumber, encodeBytes(null),
1078 encodeBytes(null));
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07001079 }
Jeff Sharkey43e12112017-09-12 16:31:45 -06001080 } catch (Exception e) {
1081 Slog.wtf(TAG, e);
Jeff Sharkey8924e872015-11-30 12:52:10 -07001082 }
1083 }
1084 }
1085 }
1086
Daniel Rosenberg137aed12019-03-15 18:41:11 -07001087 private void resetIfBootedAndConnected() {
1088 Slog.d(TAG, "Thinking about reset, mBootCompleted=" + mBootCompleted
Jeff Sharkey48877892015-03-18 11:27:19 -07001089 + ", mDaemonConnected=" + mDaemonConnected);
Daniel Rosenberg137aed12019-03-15 18:41:11 -07001090 if (mBootCompleted && mDaemonConnected) {
Keun young Park37a49da2020-06-18 16:01:05 -07001091 final UserManager userManager = mContext.getSystemService(UserManager.class);
1092 final List<UserInfo> users = userManager.getUsers();
Zim17be6f92019-09-25 14:37:55 +01001093
1094 if (mIsFuseEnabled) {
Keun young Park0c00e522020-06-17 14:27:37 -07001095 mStorageSessionController.onReset(mVold, () -> {
Keun young Park37a49da2020-06-18 16:01:05 -07001096 mHandler.removeCallbacksAndMessages(null);
Keun young Park0c00e522020-06-17 14:27:37 -07001097 });
Zim17be6f92019-09-25 14:37:55 +01001098 } else {
1099 killMediaProvider(users);
1100 }
Jeff Sharkey14cbe522015-07-08 14:06:37 -07001101
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07001102 final int[] systemUnlockedUsers;
Jeff Sharkey5a9bb742015-11-03 10:15:57 -08001103 synchronized (mLock) {
Keun young Park37a49da2020-06-18 16:01:05 -07001104 // make copy as sorting can change order
1105 systemUnlockedUsers = Arrays.copyOf(mSystemUnlockedUsers,
1106 mSystemUnlockedUsers.length);
Jeff Sharkeyb049e212012-09-07 23:16:01 -07001107
Jeff Sharkey5a9bb742015-11-03 10:15:57 -08001108 mDisks.clear();
1109 mVolumes.clear();
1110
1111 addInternalVolumeLocked();
1112 }
Jeff Sharkey59d577a2015-04-11 21:27:21 -07001113
Jeff Sharkey48877892015-03-18 11:27:19 -07001114 try {
Zim42f1e9f2019-08-15 17:35:00 +01001115 // TODO(b/135341433): Remove paranoid logging when FUSE is stable
Zim17be6f92019-09-25 14:37:55 +01001116 Slog.i(TAG, "Resetting vold...");
Jeff Sharkey54402792017-09-15 16:05:19 -06001117 mVold.reset();
Zim42f1e9f2019-08-15 17:35:00 +01001118 Slog.i(TAG, "Reset vold");
Jeff Sharkeybcd262d2015-06-10 09:41:17 -07001119
1120 // Tell vold about all existing and started users
Jeff Sharkeybcd262d2015-06-10 09:41:17 -07001121 for (UserInfo user : users) {
Jeff Sharkey54402792017-09-15 16:05:19 -06001122 mVold.onUserAdded(user.id, user.serialNumber);
Jeff Sharkeybcd262d2015-06-10 09:41:17 -07001123 }
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07001124 for (int userId : systemUnlockedUsers) {
Sudheer Shanka64501e52019-04-29 10:46:26 -07001125 mVold.onUserStarted(userId);
Jin Qian12690d52017-10-13 18:17:04 -07001126 mStoraged.onUserStarted(userId);
Jeff Sharkey50a05452015-04-29 11:24:52 -07001127 }
Keun young Park37a49da2020-06-18 16:01:05 -07001128 if (mIsAutomotive) {
1129 restoreAllUnlockedUsers(userManager, users, systemUnlockedUsers);
1130 }
Jeff Sharkey9765e442017-12-14 22:15:14 -07001131 mVold.onSecureKeyguardStateChanged(mSecureKeyguardShowing);
Risanaec0ee72018-10-31 10:10:12 +09001132 mStorageManagerInternal.onReset(mVold);
Jeff Sharkeyace874b2017-09-07 15:27:33 -06001133 } catch (Exception e) {
1134 Slog.wtf(TAG, e);
Jeff Sharkeyb049e212012-09-07 23:16:01 -07001135 }
1136 }
Jeff Sharkey48877892015-03-18 11:27:19 -07001137 }
Jeff Sharkeyb049e212012-09-07 23:16:01 -07001138
Keun young Park37a49da2020-06-18 16:01:05 -07001139 private void restoreAllUnlockedUsers(UserManager userManager, List<UserInfo> allUsers,
1140 int[] systemUnlockedUsers) throws Exception {
1141 Arrays.sort(systemUnlockedUsers);
1142 UserManager.invalidateIsUserUnlockedCache();
1143 for (UserInfo user : allUsers) {
1144 int userId = user.id;
1145 if (!userManager.isUserRunning(userId)) {
1146 continue;
1147 }
1148 if (Arrays.binarySearch(systemUnlockedUsers, userId) >= 0) {
1149 continue;
1150 }
1151 boolean unlockingOrUnlocked = userManager.isUserUnlockingOrUnlocked(userId);
1152 if (!unlockingOrUnlocked) {
1153 continue;
1154 }
1155 Slog.w(TAG, "UNLOCK_USER lost from vold reset, will retry, user:" + userId);
1156 mVold.onUserStarted(userId);
1157 mStoraged.onUserStarted(userId);
1158 mHandler.obtainMessage(H_COMPLETE_UNLOCK_USER, userId).sendToTarget();
1159 }
1160 }
1161
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07001162 private void onUnlockUser(int userId) {
1163 Slog.d(TAG, "onUnlockUser " + userId);
Jeff Sharkey48877892015-03-18 11:27:19 -07001164
1165 // We purposefully block here to make sure that user-specific
1166 // staging area is ready so it's ready for zygote-forked apps to
1167 // bind mount against.
1168 try {
Zim17be6f92019-09-25 14:37:55 +01001169 mStorageSessionController.onUnlockUser(userId);
Sudheer Shanka64501e52019-04-29 10:46:26 -07001170 mVold.onUserStarted(userId);
Jin Qian12690d52017-10-13 18:17:04 -07001171 mStoraged.onUserStarted(userId);
Jeff Sharkeyace874b2017-09-07 15:27:33 -06001172 } catch (Exception e) {
1173 Slog.wtf(TAG, e);
Jeff Sharkeyb049e212012-09-07 23:16:01 -07001174 }
Jeff Sharkey48877892015-03-18 11:27:19 -07001175
Narayan Kamath157dd1d2019-06-12 13:06:30 +01001176 mHandler.obtainMessage(H_COMPLETE_UNLOCK_USER, userId).sendToTarget();
1177 }
1178
1179 private void completeUnlockUser(int userId) {
1180 // If user 0 has completed unlock, perform a one-time migration of legacy obb data
1181 // to its new location. This may take time depending on the size of the data to be copied
1182 // so it's done on the StorageManager handler thread.
1183 if (userId == 0) {
1184 mPmInternal.migrateLegacyObbData();
1185 }
1186
Sergey Nikolaienkov64a3cca2020-06-10 07:28:13 +02001187 onKeyguardStateChanged(false);
1188
Jeff Sharkey48877892015-03-18 11:27:19 -07001189 // Record user as started so newly mounted volumes kick off events
1190 // correctly, then synthesize events for any already-mounted volumes.
yuanhuihuiefd1f122016-07-13 21:21:03 +08001191 synchronized (mLock) {
Keun young Park37a49da2020-06-18 16:01:05 -07001192 if (mIsAutomotive) {
1193 for (int unlockedUser : mSystemUnlockedUsers) {
1194 if (unlockedUser == userId) {
1195 // This can happen as restoreAllUnlockedUsers can double post the message.
1196 Log.i(TAG, "completeUnlockUser called for already unlocked user:" + userId);
1197 return;
1198 }
1199 }
1200 }
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07001201 for (int i = 0; i < mVolumes.size(); i++) {
1202 final VolumeInfo vol = mVolumes.valueAt(i);
Jeff Sharkey46349872015-07-28 10:49:47 -07001203 if (vol.isVisibleForRead(userId) && vol.isMountedReadable()) {
Svet Ganov6ee871e2015-07-10 14:29:33 -07001204 final StorageVolume userVol = vol.buildStorageVolume(mContext, userId, false);
Jeff Sharkey48877892015-03-18 11:27:19 -07001205 mHandler.obtainMessage(H_VOLUME_BROADCAST, userVol).sendToTarget();
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001206
Jeff Sharkey27de30d2015-04-18 16:20:27 -07001207 final String envState = VolumeInfo.getEnvironmentForState(vol.getState());
1208 mCallbacks.notifyStorageStateChanged(userVol.getPath(), envState, envState);
Jeff Sharkey48877892015-03-18 11:27:19 -07001209 }
1210 }
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07001211 mSystemUnlockedUsers = ArrayUtils.appendInt(mSystemUnlockedUsers, userId);
Jeff Sharkey48877892015-03-18 11:27:19 -07001212 }
1213 }
1214
1215 private void onCleanupUser(int userId) {
1216 Slog.d(TAG, "onCleanupUser " + userId);
1217
1218 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06001219 mVold.onUserStopped(userId);
Jin Qian12690d52017-10-13 18:17:04 -07001220 mStoraged.onUserStopped(userId);
Jeff Sharkeyace874b2017-09-07 15:27:33 -06001221 } catch (Exception e) {
1222 Slog.wtf(TAG, e);
Jeff Sharkey48877892015-03-18 11:27:19 -07001223 }
1224
yuanhuihuiefd1f122016-07-13 21:21:03 +08001225 synchronized (mLock) {
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07001226 mSystemUnlockedUsers = ArrayUtils.removeInt(mSystemUnlockedUsers, userId);
Jeff Sharkey48877892015-03-18 11:27:19 -07001227 }
1228 }
Jeff Sharkeyb049e212012-09-07 23:16:01 -07001229
Martijn Coenen7084c6a2019-11-22 16:32:09 +01001230 private void onStopUser(int userId) {
1231 Slog.i(TAG, "onStopUser " + userId);
1232 try {
1233 mStorageSessionController.onUserStopping(userId);
1234 } catch (Exception e) {
1235 Slog.wtf(TAG, e);
1236 }
Zim3ce38492020-02-07 15:14:58 +00001237 PackageMonitor monitor = mPackageMonitorsForUser.remove(userId);
1238 if (monitor != null) {
1239 monitor.unregister();
1240 }
Martijn Coenen7084c6a2019-11-22 16:32:09 +01001241 }
1242
Sudheer Shanka64501e52019-04-29 10:46:26 -07001243 private boolean supportsBlockCheckpoint() throws RemoteException {
Paul Lawrence15a54462019-04-30 11:14:25 -07001244 enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);
Sandeep Patil7d5c4912019-04-15 09:27:30 -07001245 return mVold.supportsBlockCheckpoint();
1246 }
1247
Jeff Sharkey9765e442017-12-14 22:15:14 -07001248 @Override
1249 public void onAwakeStateChanged(boolean isAwake) {
1250 // Ignored
1251 }
1252
1253 @Override
1254 public void onKeyguardStateChanged(boolean isShowing) {
1255 // Push down current secure keyguard status so that we ignore malicious
1256 // USB devices while locked.
1257 mSecureKeyguardShowing = isShowing
Martijn Coenen7c1df2d2020-01-07 10:21:42 +01001258 && mContext.getSystemService(KeyguardManager.class).isDeviceSecure(mCurrentUserId);
Jeff Sharkey9765e442017-12-14 22:15:14 -07001259 try {
1260 mVold.onSecureKeyguardStateChanged(mSecureKeyguardShowing);
1261 } catch (Exception e) {
1262 Slog.wtf(TAG, e);
1263 }
1264 }
1265
Christopher Tated417d622013-08-19 16:14:25 -07001266 void runIdleMaintenance(Runnable callback) {
1267 mHandler.sendMessage(mHandler.obtainMessage(H_FSTRIM, callback));
1268 }
1269
Christopher Tate7265abe2014-11-21 13:54:45 -08001270 // Binder entry point for kicking off an immediate fstrim
1271 @Override
1272 public void runMaintenance() {
Jeff Sharkey48877892015-03-18 11:27:19 -07001273 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
Christopher Tate7265abe2014-11-21 13:54:45 -08001274 runIdleMaintenance(null);
1275 }
1276
1277 @Override
1278 public long lastMaintenance() {
1279 return mLastMaintenance;
1280 }
1281
San Mehat4270e1e2010-01-29 05:32:19 -08001282 public void onDaemonConnected() {
Jeff Sharkey48877892015-03-18 11:27:19 -07001283 mDaemonConnected = true;
1284 mHandler.obtainMessage(H_DAEMON_CONNECTED).sendToTarget();
1285 }
1286
1287 private void handleDaemonConnected() {
Daniel Rosenberg137aed12019-03-15 18:41:11 -07001288 initIfBootedAndConnected();
1289 resetIfBootedAndConnected();
Jeff Sharkey48877892015-03-18 11:27:19 -07001290
Jeff Sharkey48877892015-03-18 11:27:19 -07001291 // On an encrypted device we can't see system properties yet, so pull
1292 // the system locale out of the mount service.
Inseob Kimc1246e62018-11-08 13:13:54 +09001293 if ("".equals(VoldProperties.encrypt_progress().orElse(""))) {
Jeff Sharkey48877892015-03-18 11:27:19 -07001294 copyLocaleFromMountService();
1295 }
San Mehat4270e1e2010-01-29 05:32:19 -08001296 }
1297
Elliott Hughesf839b4f2014-09-26 12:30:47 -07001298 private void copyLocaleFromMountService() {
1299 String systemLocale;
1300 try {
1301 systemLocale = getField(StorageManager.SYSTEM_LOCALE_KEY);
1302 } catch (RemoteException e) {
1303 return;
1304 }
1305 if (TextUtils.isEmpty(systemLocale)) {
1306 return;
1307 }
1308
1309 Slog.d(TAG, "Got locale " + systemLocale + " from mount service");
1310 Locale locale = Locale.forLanguageTag(systemLocale);
1311 Configuration config = new Configuration();
1312 config.setLocale(locale);
1313 try {
Sudheer Shankadc589ac2016-11-10 15:30:17 -08001314 ActivityManager.getService().updatePersistentConfiguration(config);
Elliott Hughesf839b4f2014-09-26 12:30:47 -07001315 } catch (RemoteException e) {
1316 Slog.e(TAG, "Error setting system locale from mount service", e);
1317 }
Elliott Hughes9c33f282014-10-13 12:39:56 -07001318
1319 // Temporary workaround for http://b/17945169.
1320 Slog.d(TAG, "Setting system properties to " + systemLocale + " from mount service");
Narayan Kamathd30dbb82015-01-15 14:48:15 +00001321 SystemProperties.set("persist.sys.locale", locale.toLanguageTag());
Elliott Hughesf839b4f2014-09-26 12:30:47 -07001322 }
1323
Jeff Sharkey8058fe62017-09-13 11:50:33 -06001324 private final IVoldListener mListener = new IVoldListener.Stub() {
1325 @Override
1326 public void onDiskCreated(String diskId, int flags) {
1327 synchronized (mLock) {
Jeff Sharkey901c0422018-04-20 13:11:20 -06001328 final String value = SystemProperties.get(StorageManager.PROP_ADOPTABLE);
1329 switch (value) {
1330 case "force_on":
1331 flags |= DiskInfo.FLAG_ADOPTABLE;
1332 break;
1333 case "force_off":
1334 flags &= ~DiskInfo.FLAG_ADOPTABLE;
1335 break;
Jeff Sharkey8058fe62017-09-13 11:50:33 -06001336 }
Jeff Sharkey8058fe62017-09-13 11:50:33 -06001337 mDisks.put(diskId, new DiskInfo(diskId, flags));
1338 }
1339 }
1340
1341 @Override
1342 public void onDiskScanned(String diskId) {
1343 synchronized (mLock) {
1344 final DiskInfo disk = mDisks.get(diskId);
1345 if (disk != null) {
1346 onDiskScannedLocked(disk);
1347 }
1348 }
1349 }
1350
1351 @Override
1352 public void onDiskMetadataChanged(String diskId, long sizeBytes, String label,
1353 String sysPath) {
1354 synchronized (mLock) {
1355 final DiskInfo disk = mDisks.get(diskId);
1356 if (disk != null) {
1357 disk.size = sizeBytes;
1358 disk.label = label;
1359 disk.sysPath = sysPath;
1360 }
1361 }
1362 }
1363
1364 @Override
1365 public void onDiskDestroyed(String diskId) {
1366 synchronized (mLock) {
1367 final DiskInfo disk = mDisks.remove(diskId);
1368 if (disk != null) {
1369 mCallbacks.notifyDiskDestroyed(disk);
1370 }
1371 }
1372 }
1373
1374 @Override
Zim17be6f92019-09-25 14:37:55 +01001375 public void onVolumeCreated(String volId, int type, String diskId, String partGuid,
1376 int userId) {
Jeff Sharkey8058fe62017-09-13 11:50:33 -06001377 synchronized (mLock) {
1378 final DiskInfo disk = mDisks.get(diskId);
1379 final VolumeInfo vol = new VolumeInfo(volId, type, disk, partGuid);
Zim17be6f92019-09-25 14:37:55 +01001380 vol.mountUserId = userId;
Jeff Sharkey8058fe62017-09-13 11:50:33 -06001381 mVolumes.put(volId, vol);
1382 onVolumeCreatedLocked(vol);
1383 }
1384 }
1385
1386 @Override
1387 public void onVolumeStateChanged(String volId, int state) {
1388 synchronized (mLock) {
1389 final VolumeInfo vol = mVolumes.get(volId);
1390 if (vol != null) {
1391 final int oldState = vol.state;
1392 final int newState = state;
1393 vol.state = newState;
Abhijeet Kaur29dc0892020-03-12 18:14:24 +00001394 final SomeArgs args = SomeArgs.obtain();
1395 args.arg1 = vol;
1396 args.arg2 = oldState;
1397 args.arg3 = newState;
1398 mHandler.obtainMessage(H_VOLUME_STATE_CHANGED, args).sendToTarget();
Linus Tufvesson4e0ff022020-03-27 14:53:30 +00001399 onVolumeStateChangedLocked(vol, oldState, newState);
Jeff Sharkey8058fe62017-09-13 11:50:33 -06001400 }
1401 }
1402 }
1403
1404 @Override
1405 public void onVolumeMetadataChanged(String volId, String fsType, String fsUuid,
1406 String fsLabel) {
1407 synchronized (mLock) {
1408 final VolumeInfo vol = mVolumes.get(volId);
1409 if (vol != null) {
1410 vol.fsType = fsType;
1411 vol.fsUuid = fsUuid;
1412 vol.fsLabel = fsLabel;
1413 }
1414 }
1415 }
1416
1417 @Override
1418 public void onVolumePathChanged(String volId, String path) {
1419 synchronized (mLock) {
1420 final VolumeInfo vol = mVolumes.get(volId);
1421 if (vol != null) {
1422 vol.path = path;
1423 }
1424 }
1425 }
1426
1427 @Override
1428 public void onVolumeInternalPathChanged(String volId, String internalPath) {
1429 synchronized (mLock) {
1430 final VolumeInfo vol = mVolumes.get(volId);
1431 if (vol != null) {
1432 vol.internalPath = internalPath;
1433 }
1434 }
1435 }
1436
1437 @Override
1438 public void onVolumeDestroyed(String volId) {
Zim17be6f92019-09-25 14:37:55 +01001439 VolumeInfo vol = null;
Jeff Sharkey8058fe62017-09-13 11:50:33 -06001440 synchronized (mLock) {
Zim17be6f92019-09-25 14:37:55 +01001441 vol = mVolumes.remove(volId);
1442 }
1443
1444 if (vol != null) {
1445 mStorageSessionController.onVolumeRemove(vol);
Ricky Wai4482ab52019-12-10 19:08:18 +00001446 try {
1447 if (vol.type == VolumeInfo.TYPE_PRIVATE) {
1448 mInstaller.onPrivateVolumeRemoved(vol.getFsUuid());
1449 }
1450 } catch (Installer.InstallerException e) {
1451 Slog.i(TAG, "Failed when private volume unmounted " + vol, e);
1452 }
Jeff Sharkey8058fe62017-09-13 11:50:33 -06001453 }
1454 }
1455 };
1456
Andreas Gampea36dc622018-02-05 17:19:22 -08001457 @GuardedBy("mLock")
Jeff Sharkeyeba260d2015-04-19 14:35:16 -07001458 private void onDiskScannedLocked(DiskInfo disk) {
Jeff Sharkey620b32b2015-04-23 19:36:02 -07001459 int volumeCount = 0;
Jeff Sharkeyeba260d2015-04-19 14:35:16 -07001460 for (int i = 0; i < mVolumes.size(); i++) {
1461 final VolumeInfo vol = mVolumes.valueAt(i);
1462 if (Objects.equals(disk.id, vol.getDiskId())) {
Jeff Sharkey620b32b2015-04-23 19:36:02 -07001463 volumeCount++;
Jeff Sharkeyeba260d2015-04-19 14:35:16 -07001464 }
1465 }
1466
Jeff Sharkeyc7acac62015-06-12 16:16:56 -07001467 final Intent intent = new Intent(DiskInfo.ACTION_DISK_SCANNED);
Jeff Sharkey7732e1e2016-03-30 17:14:23 -06001468 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT
1469 | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
Jeff Sharkeyc7acac62015-06-12 16:16:56 -07001470 intent.putExtra(DiskInfo.EXTRA_DISK_ID, disk.id);
1471 intent.putExtra(DiskInfo.EXTRA_VOLUME_COUNT, volumeCount);
Jeff Sharkeyabc3e852015-08-03 14:41:13 -07001472 mHandler.obtainMessage(H_INTERNAL_BROADCAST, intent).sendToTarget();
Jeff Sharkeyc7acac62015-06-12 16:16:56 -07001473
1474 final CountDownLatch latch = mDiskScanLatches.remove(disk.id);
1475 if (latch != null) {
1476 latch.countDown();
1477 }
1478
Jeff Sharkeyf5a6bd72015-05-19 14:42:38 -07001479 disk.volumeCount = volumeCount;
Jeff Sharkey620b32b2015-04-23 19:36:02 -07001480 mCallbacks.notifyDiskScanned(disk, volumeCount);
Jeff Sharkeyeba260d2015-04-19 14:35:16 -07001481 }
1482
Andreas Gampea36dc622018-02-05 17:19:22 -08001483 @GuardedBy("mLock")
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07001484 private void onVolumeCreatedLocked(VolumeInfo vol) {
Jeff Sharkey5790af02018-08-13 17:42:54 -06001485 if (mPmInternal.isOnlyCoreApps()) {
Jeff Sharkey6855c482016-03-31 14:34:38 -06001486 Slog.d(TAG, "System booted in core-only mode; ignoring volume " + vol.getId());
1487 return;
1488 }
Martijn Coenen7084c6a2019-11-22 16:32:09 +01001489 final ActivityManagerInternal amInternal =
1490 LocalServices.getService(ActivityManagerInternal.class);
1491
1492 if (mIsFuseEnabled && vol.mountUserId >= 0
1493 && !amInternal.isUserRunning(vol.mountUserId, 0)) {
1494 Slog.d(TAG, "Ignoring volume " + vol.getId() + " because user "
1495 + Integer.toString(vol.mountUserId) + " is no longer running.");
1496 return;
1497 }
Jeff Sharkey6855c482016-03-31 14:34:38 -06001498
Jeff Sharkey275e3e42015-04-24 16:10:32 -07001499 if (vol.type == VolumeInfo.TYPE_EMULATED) {
1500 final StorageManager storage = mContext.getSystemService(StorageManager.class);
1501 final VolumeInfo privateVol = storage.findPrivateForEmulated(vol);
1502
1503 if (Objects.equals(StorageManager.UUID_PRIVATE_INTERNAL, mPrimaryStorageUuid)
1504 && VolumeInfo.ID_PRIVATE_INTERNAL.equals(privateVol.id)) {
1505 Slog.v(TAG, "Found primary storage at " + vol);
1506 vol.mountFlags |= VolumeInfo.MOUNT_FLAG_PRIMARY;
1507 vol.mountFlags |= VolumeInfo.MOUNT_FLAG_VISIBLE;
1508 mHandler.obtainMessage(H_VOLUME_MOUNT, vol).sendToTarget();
1509
1510 } else if (Objects.equals(privateVol.fsUuid, mPrimaryStorageUuid)) {
1511 Slog.v(TAG, "Found primary storage at " + vol);
1512 vol.mountFlags |= VolumeInfo.MOUNT_FLAG_PRIMARY;
1513 vol.mountFlags |= VolumeInfo.MOUNT_FLAG_VISIBLE;
1514 mHandler.obtainMessage(H_VOLUME_MOUNT, vol).sendToTarget();
1515 }
Jeff Sharkeyb049e212012-09-07 23:16:01 -07001516
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07001517 } else if (vol.type == VolumeInfo.TYPE_PUBLIC) {
Jeff Sharkey275e3e42015-04-24 16:10:32 -07001518 // TODO: only look at first public partition
1519 if (Objects.equals(StorageManager.UUID_PRIMARY_PHYSICAL, mPrimaryStorageUuid)
1520 && vol.disk.isDefaultPrimary()) {
1521 Slog.v(TAG, "Found primary storage at " + vol);
Jeff Sharkey7e92ef32015-04-17 17:35:07 -07001522 vol.mountFlags |= VolumeInfo.MOUNT_FLAG_PRIMARY;
1523 vol.mountFlags |= VolumeInfo.MOUNT_FLAG_VISIBLE;
San Mehat4270e1e2010-01-29 05:32:19 -08001524 }
Jeff Sharkey7e92ef32015-04-17 17:35:07 -07001525
1526 // Adoptable public disks are visible to apps, since they meet
1527 // public API requirement of being in a stable location.
Jeff Sharkey275e3e42015-04-24 16:10:32 -07001528 if (vol.disk.isAdoptable()) {
Jeff Sharkey7e92ef32015-04-17 17:35:07 -07001529 vol.mountFlags |= VolumeInfo.MOUNT_FLAG_VISIBLE;
1530 }
1531
Jeff Sharkeyab15c392016-05-05 11:45:01 -06001532 vol.mountUserId = mCurrentUserId;
Jeff Sharkey48877892015-03-18 11:27:19 -07001533 mHandler.obtainMessage(H_VOLUME_MOUNT, vol).sendToTarget();
San Mehat4270e1e2010-01-29 05:32:19 -08001534
Jeff Sharkeyb2b9ab82015-04-05 21:10:42 -07001535 } else if (vol.type == VolumeInfo.TYPE_PRIVATE) {
1536 mHandler.obtainMessage(H_VOLUME_MOUNT, vol).sendToTarget();
1537
Risan05c41e62018-10-29 08:57:43 +09001538 } else if (vol.type == VolumeInfo.TYPE_STUB) {
1539 vol.mountUserId = mCurrentUserId;
1540 mHandler.obtainMessage(H_VOLUME_MOUNT, vol).sendToTarget();
San Mehat4270e1e2010-01-29 05:32:19 -08001541 } else {
Jeff Sharkey48877892015-03-18 11:27:19 -07001542 Slog.d(TAG, "Skipping automatic mounting of " + vol);
San Mehat4270e1e2010-01-29 05:32:19 -08001543 }
1544 }
1545
Jeff Sharkeye6c04f92015-04-18 21:38:05 -07001546 private boolean isBroadcastWorthy(VolumeInfo vol) {
1547 switch (vol.getType()) {
Jeff Sharkeyc7acac62015-06-12 16:16:56 -07001548 case VolumeInfo.TYPE_PRIVATE:
Jeff Sharkeye6c04f92015-04-18 21:38:05 -07001549 case VolumeInfo.TYPE_PUBLIC:
1550 case VolumeInfo.TYPE_EMULATED:
Risan05c41e62018-10-29 08:57:43 +09001551 case VolumeInfo.TYPE_STUB:
Jeff Sharkeye6c04f92015-04-18 21:38:05 -07001552 break;
1553 default:
1554 return false;
1555 }
1556
1557 switch (vol.getState()) {
1558 case VolumeInfo.STATE_MOUNTED:
1559 case VolumeInfo.STATE_MOUNTED_READ_ONLY:
1560 case VolumeInfo.STATE_EJECTING:
1561 case VolumeInfo.STATE_UNMOUNTED:
Jeff Sharkeyc7acac62015-06-12 16:16:56 -07001562 case VolumeInfo.STATE_UNMOUNTABLE:
Tony Mantlerf0d71052015-06-24 11:45:25 -07001563 case VolumeInfo.STATE_BAD_REMOVAL:
Jeff Sharkeye6c04f92015-04-18 21:38:05 -07001564 break;
1565 default:
1566 return false;
1567 }
1568
1569 return true;
1570 }
1571
Linus Tufvesson4e0ff022020-03-27 14:53:30 +00001572
1573 private void onVolumeStateChangedLocked(VolumeInfo vol, int oldState, int newState) {
1574 if (vol.type == VolumeInfo.TYPE_EMULATED) {
1575 if (newState != VolumeInfo.STATE_MOUNTED) {
Abhijeet Kaur29dc0892020-03-12 18:14:24 +00001576 mFuseMountedUser.remove(vol.getMountUserId());
Ricky Wai64167472020-04-08 16:14:37 +01001577 } else if (mVoldAppDataIsolationEnabled){
Linus Tufvesson4e0ff022020-03-27 14:53:30 +00001578 final int userId = vol.getMountUserId();
1579 mFuseMountedUser.add(userId);
1580 // Async remount app storage so it won't block the main thread.
1581 new Thread(() -> {
1582 Map<Integer, String> pidPkgMap = null;
1583 // getProcessesWithPendingBindMounts() could fail when a new app process is
1584 // starting and it's not planning to mount storage dirs in zygote, but it's
1585 // rare, so we retry 5 times and hope we can get the result successfully.
1586 for (int i = 0; i < 5; i++) {
1587 try {
1588 pidPkgMap = LocalServices.getService(ActivityManagerInternal.class)
1589 .getProcessesWithPendingBindMounts(vol.getMountUserId());
1590 break;
1591 } catch (IllegalStateException e) {
1592 Slog.i(TAG, "Some processes are starting, retry");
1593 // Wait 100ms and retry so hope the pending process is started.
1594 SystemClock.sleep(100);
1595 }
1596 }
1597 if (pidPkgMap != null) {
1598 remountAppStorageDirs(pidPkgMap, userId);
1599 } else {
1600 Slog.wtf(TAG, "Not able to getStorageNotOptimizedProcesses() after"
1601 + " 5 retries");
1602 }
1603 }).start();
Abhijeet Kaur29dc0892020-03-12 18:14:24 +00001604 }
Linus Tufvesson4e0ff022020-03-27 14:53:30 +00001605 }
1606 }
1607
1608
1609 private void onVolumeStateChangedAsync(VolumeInfo vol, int oldState, int newState) {
1610 synchronized (mLock) {
Abhijeet Kaur29dc0892020-03-12 18:14:24 +00001611 // Remember that we saw this volume so we're ready to accept user
1612 // metadata, or so we can annoy them when a private volume is ejected
1613 if (!TextUtils.isEmpty(vol.fsUuid)) {
1614 VolumeRecord rec = mRecords.get(vol.fsUuid);
1615 if (rec == null) {
1616 rec = new VolumeRecord(vol.type, vol.fsUuid);
Jeff Sharkey5cc0df22015-06-17 19:44:05 -07001617 rec.partGuid = vol.partGuid;
Abhijeet Kaur29dc0892020-03-12 18:14:24 +00001618 rec.createdMillis = System.currentTimeMillis();
1619 if (vol.type == VolumeInfo.TYPE_PRIVATE) {
1620 rec.nickname = vol.disk.getDescription();
1621 }
1622 mRecords.put(rec.fsUuid, rec);
1623 } else {
1624 // Handle upgrade case where we didn't store partition GUID
1625 if (TextUtils.isEmpty(rec.partGuid)) {
1626 rec.partGuid = vol.partGuid;
1627 }
1628 }
1629
1630 rec.lastSeenMillis = System.currentTimeMillis();
1631 writeSettingsLocked();
1632 }
1633 }
Martijn Coenencecf90c2020-05-04 15:16:48 +02001634
1635 if (newState == VolumeInfo.STATE_MOUNTED) {
1636 // Private volumes can be unmounted and re-mounted even after a user has
1637 // been unlocked; on devices that support encryption keys tied to the filesystem,
1638 // this requires setting up the keys again.
1639 prepareUserStorageIfNeeded(vol);
1640 }
1641
Abhijeet Kaur29dc0892020-03-12 18:14:24 +00001642 // This is a blocking call to Storage Service which needs to process volume state changed
1643 // before notifying other listeners.
1644 // Intentionally called without the mLock to avoid deadlocking from the Storage Service.
1645 try {
1646 mStorageSessionController.notifyVolumeStateChanged(vol);
1647 } catch (ExternalStorageServiceException e) {
1648 Log.e(TAG, "Failed to notify volume state changed to the Storage Service", e);
1649 }
1650 synchronized (mLock) {
1651 mCallbacks.notifyVolumeStateChanged(vol, oldState, newState);
1652
1653 // Do not broadcast before boot has completed to avoid launching the
1654 // processes that receive the intent unnecessarily.
1655 if (mBootCompleted && isBroadcastWorthy(vol)) {
1656 final Intent intent = new Intent(VolumeInfo.ACTION_VOLUME_STATE_CHANGED);
1657 intent.putExtra(VolumeInfo.EXTRA_VOLUME_ID, vol.id);
1658 intent.putExtra(VolumeInfo.EXTRA_VOLUME_STATE, newState);
1659 intent.putExtra(VolumeRecord.EXTRA_FS_UUID, vol.fsUuid);
1660 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT
1661 | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
1662 mHandler.obtainMessage(H_INTERNAL_BROADCAST, intent).sendToTarget();
1663 }
1664
1665 final String oldStateEnv = VolumeInfo.getEnvironmentForState(oldState);
1666 final String newStateEnv = VolumeInfo.getEnvironmentForState(newState);
1667
1668 if (!Objects.equals(oldStateEnv, newStateEnv)) {
1669 // Kick state changed event towards all started users. Any users
1670 // started after this point will trigger additional
1671 // user-specific broadcasts.
1672 for (int userId : mSystemUnlockedUsers) {
1673 if (vol.isVisibleForRead(userId)) {
1674 final StorageVolume userVol = vol.buildStorageVolume(mContext, userId,
1675 false);
1676 mHandler.obtainMessage(H_VOLUME_BROADCAST, userVol).sendToTarget();
1677
1678 mCallbacks.notifyStorageStateChanged(userVol.getPath(), oldStateEnv,
1679 newStateEnv);
1680 }
Jeff Sharkey5cc0df22015-06-17 19:44:05 -07001681 }
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001682 }
Jeff Sharkey3811f352019-05-14 11:54:36 -06001683
Abhijeet Kaur29dc0892020-03-12 18:14:24 +00001684 if ((vol.type == VolumeInfo.TYPE_PUBLIC || vol.type == VolumeInfo.TYPE_STUB)
Risan05c41e62018-10-29 08:57:43 +09001685 && vol.state == VolumeInfo.STATE_EJECTING) {
Abhijeet Kaur29dc0892020-03-12 18:14:24 +00001686 // TODO: this should eventually be handled by new ObbVolume state changes
1687 /*
1688 * Some OBBs might have been unmounted when this volume was
1689 * unmounted, so send a message to the handler to let it know to
1690 * remove those from the list of mounted OBBS.
1691 */
1692 mObbActionHandler.sendMessage(mObbActionHandler.obtainMessage(
1693 OBB_FLUSH_MOUNT_STATE, vol.path));
1694 }
1695 maybeLogMediaMount(vol, newState);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001696 }
Pavel Grafovce72ef02018-01-10 17:14:11 +00001697 }
1698
1699 private void maybeLogMediaMount(VolumeInfo vol, int newState) {
1700 if (!SecurityLog.isLoggingEnabled()) {
1701 return;
1702 }
1703
1704 final DiskInfo disk = vol.getDisk();
1705 if (disk == null || (disk.flags & (DiskInfo.FLAG_SD | DiskInfo.FLAG_USB)) == 0) {
1706 return;
1707 }
1708
1709 // Sometimes there is a newline character.
1710 final String label = disk.label != null ? disk.label.trim() : "";
1711
1712 if (newState == VolumeInfo.STATE_MOUNTED
1713 || newState == VolumeInfo.STATE_MOUNTED_READ_ONLY) {
1714 SecurityLog.writeEvent(SecurityLog.TAG_MEDIA_MOUNT, vol.path, label);
1715 } else if (newState == VolumeInfo.STATE_UNMOUNTED
1716 || newState == VolumeInfo.STATE_BAD_REMOVAL) {
1717 SecurityLog.writeEvent(SecurityLog.TAG_MEDIA_UNMOUNT, vol.path, label);
1718 }
San Mehat4270e1e2010-01-29 05:32:19 -08001719 }
1720
Andreas Gampea36dc622018-02-05 17:19:22 -08001721 @GuardedBy("mLock")
Jeff Sharkey275e3e42015-04-24 16:10:32 -07001722 private void onMoveStatusLocked(int status) {
1723 if (mMoveCallback == null) {
1724 Slog.w(TAG, "Odd, status but no move requested");
1725 return;
1726 }
1727
1728 // TODO: estimate remaining time
1729 try {
Jeff Sharkey50a05452015-04-29 11:24:52 -07001730 mMoveCallback.onStatusChanged(-1, status, -1);
Jeff Sharkey275e3e42015-04-24 16:10:32 -07001731 } catch (RemoteException ignored) {
1732 }
1733
1734 // We've finished copying and we're about to clean up old data, so
1735 // remember that move was successful if we get rebooted
1736 if (status == MOVE_STATUS_COPY_FINISHED) {
1737 Slog.d(TAG, "Move to " + mMoveTargetUuid + " copy phase finshed; persisting");
1738
1739 mPrimaryStorageUuid = mMoveTargetUuid;
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001740 writeSettingsLocked();
Jeff Sharkey275e3e42015-04-24 16:10:32 -07001741 }
1742
1743 if (PackageManager.isMoveStatusFinished(status)) {
1744 Slog.d(TAG, "Move to " + mMoveTargetUuid + " finished with status " + status);
1745
1746 mMoveCallback = null;
1747 mMoveTargetUuid = null;
1748 }
1749 }
1750
Jeff Sharkey48877892015-03-18 11:27:19 -07001751 private void enforcePermission(String perm) {
1752 mContext.enforceCallingOrSelfPermission(perm, perm);
Mike Lockwooda5250c92011-05-23 13:44:04 -04001753 }
1754
Jeff Sharkey2e606d72015-07-27 14:19:54 -07001755 /**
1756 * Decide if volume is mountable per device policies.
1757 */
1758 private boolean isMountDisallowed(VolumeInfo vol) {
Philip P. Moltmannec3cbb22016-09-14 13:24:52 -07001759 UserManager userManager = mContext.getSystemService(UserManager.class);
1760
1761 boolean isUsbRestricted = false;
1762 if (vol.disk != null && vol.disk.isUsb()) {
1763 isUsbRestricted = userManager.hasUserRestriction(UserManager.DISALLOW_USB_FILE_TRANSFER,
Jeff Sharkey2e606d72015-07-27 14:19:54 -07001764 Binder.getCallingUserHandle());
Emily Bernier92aa5a22014-07-07 10:11:48 -04001765 }
Philip P. Moltmannec3cbb22016-09-14 13:24:52 -07001766
1767 boolean isTypeRestricted = false;
Risan05c41e62018-10-29 08:57:43 +09001768 if (vol.type == VolumeInfo.TYPE_PUBLIC || vol.type == VolumeInfo.TYPE_PRIVATE
1769 || vol.type == VolumeInfo.TYPE_STUB) {
Philip P. Moltmannec3cbb22016-09-14 13:24:52 -07001770 isTypeRestricted = userManager
1771 .hasUserRestriction(UserManager.DISALLOW_MOUNT_PHYSICAL_MEDIA,
1772 Binder.getCallingUserHandle());
1773 }
1774
1775 return isUsbRestricted || isTypeRestricted;
Emily Bernier92aa5a22014-07-07 10:11:48 -04001776 }
1777
Amith Yamasani462ac3a2015-06-30 14:21:01 -07001778 private void enforceAdminUser() {
1779 UserManager um = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
1780 final int callingUserId = UserHandle.getCallingUserId();
1781 boolean isAdmin;
1782 long token = Binder.clearCallingIdentity();
1783 try {
1784 isAdmin = um.getUserInfo(callingUserId).isAdmin();
1785 } finally {
1786 Binder.restoreCallingIdentity(token);
1787 }
1788 if (!isAdmin) {
1789 throw new SecurityException("Only admin users can adopt sd cards");
1790 }
1791 }
1792
Jeff Sharkeyb049e212012-09-07 23:16:01 -07001793 /**
Sudheer Shanka2250d562016-11-07 15:41:02 -08001794 * Constructs a new StorageManagerService instance
San Mehat207e5382010-02-04 20:46:54 -08001795 *
1796 * @param context Binder context for this service
1797 */
Sudheer Shanka2250d562016-11-07 15:41:02 -08001798 public StorageManagerService(Context context) {
Christopher Tated417d622013-08-19 16:14:25 -07001799 sSelf = this;
1800
Jeff Sharkey342b4bf2018-12-18 11:12:40 -07001801 // Snapshot feature flag used for this boot
1802 SystemProperties.set(StorageManager.PROP_ISOLATED_STORAGE_SNAPSHOT, Boolean.toString(
Jeff Sharkey06376802019-02-11 12:20:02 -07001803 SystemProperties.getBoolean(StorageManager.PROP_ISOLATED_STORAGE, true)));
shafik78fcd502019-09-25 13:50:04 +01001804
Zim69e9c092020-01-21 13:32:32 +00001805 // If there is no value in the property yet (first boot after data wipe), this value may be
1806 // incorrect until #updateFusePropFromSettings where we set the correct value and reboot if
1807 // different
Zim238aa332020-02-11 16:59:09 +00001808 mIsFuseEnabled = SystemProperties.getBoolean(PROP_FUSE, DEFAULT_FUSE_ENABLED);
Ricky Wai64167472020-04-08 16:14:37 +01001809 mVoldAppDataIsolationEnabled = mIsFuseEnabled && SystemProperties.getBoolean(
1810 ANDROID_VOLD_APP_DATA_ISOLATION_ENABLED_PROPERTY, false);
San Mehat207e5382010-02-04 20:46:54 -08001811 mContext = context;
Jeff Sharkey5d0c55c2019-01-24 14:32:31 -07001812 mResolver = mContext.getContentResolver();
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001813 mCallbacks = new Callbacks(FgThread.get().getLooper());
Jeff Sharkeyb9fe5372015-12-03 15:23:08 -07001814 mLockPatternUtils = new LockPatternUtils(mContext);
San Mehat207e5382010-02-04 20:46:54 -08001815
Dianne Hackbornefa92b22013-05-03 14:11:43 -07001816 HandlerThread hthread = new HandlerThread(TAG);
1817 hthread.start();
Sudheer Shanka2250d562016-11-07 15:41:02 -08001818 mHandler = new StorageManagerServiceHandler(hthread.getLooper());
Daniel Sandler5f27ef42010-03-16 15:42:02 -04001819
Sudheer Shanka2250d562016-11-07 15:41:02 -08001820 // Add OBB Action Handler to StorageManagerService thread.
Dianne Hackborn8d044e82013-04-30 17:24:15 -07001821 mObbActionHandler = new ObbActionHandler(IoThread.get().getLooper());
Kenny Roota02b8b02010-08-05 16:14:17 -07001822
Zim17be6f92019-09-25 14:37:55 +01001823 mStorageSessionController = new StorageSessionController(mContext, mIsFuseEnabled);
Zim42f1e9f2019-08-15 17:35:00 +01001824
Ricky Wai4482ab52019-12-10 19:08:18 +00001825 mInstaller = new Installer(mContext);
1826 mInstaller.onStart();
1827
Christopher Tate7265abe2014-11-21 13:54:45 -08001828 // Initialize the last-fstrim tracking if necessary
1829 File dataDir = Environment.getDataDirectory();
1830 File systemDir = new File(dataDir, "system");
1831 mLastMaintenanceFile = new File(systemDir, LAST_FSTRIM_FILE);
1832 if (!mLastMaintenanceFile.exists()) {
1833 // Not setting mLastMaintenance here means that we will force an
1834 // fstrim during reboot following the OTA that installs this code.
1835 try {
1836 (new FileOutputStream(mLastMaintenanceFile)).close();
1837 } catch (IOException e) {
1838 Slog.e(TAG, "Unable to create fstrim record " + mLastMaintenanceFile.getPath());
1839 }
1840 } else {
1841 mLastMaintenance = mLastMaintenanceFile.lastModified();
1842 }
1843
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001844 mSettingsFile = new AtomicFile(
Dianne Hackborne17b4452018-01-10 13:15:40 -08001845 new File(Environment.getDataSystemDirectory(), "storage.xml"), "storage-settings");
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001846
1847 synchronized (mLock) {
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001848 readSettingsLocked();
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001849 }
1850
Sudheer Shanka2250d562016-11-07 15:41:02 -08001851 LocalServices.addService(StorageManagerInternal.class, mStorageManagerInternal);
Svet Ganov6ee871e2015-07-10 14:29:33 -07001852
Jeff Sharkeybcd262d2015-06-10 09:41:17 -07001853 final IntentFilter userFilter = new IntentFilter();
1854 userFilter.addAction(Intent.ACTION_USER_ADDED);
1855 userFilter.addAction(Intent.ACTION_USER_REMOVED);
1856 mContext.registerReceiver(mUserReceiver, userFilter, null, mHandler);
1857
Jeff Sharkey5a9bb742015-11-03 10:15:57 -08001858 synchronized (mLock) {
1859 addInternalVolumeLocked();
1860 }
Amith Yamasania7892482015-08-07 11:09:05 -07001861
Kenny Root07714d42011-08-17 17:49:28 -07001862 // Add ourself to the Watchdog monitors if enabled.
1863 if (WATCHDOG_ENABLE) {
1864 Watchdog.getInstance().addMonitor(this);
1865 }
Keun young Park37a49da2020-06-18 16:01:05 -07001866
1867 mIsAutomotive = context.getPackageManager().hasSystemFeature(
1868 PackageManager.FEATURE_AUTOMOTIVE);
San Mehat207e5382010-02-04 20:46:54 -08001869 }
1870
Abhijeet Kaurb9847712019-11-19 16:35:47 +00001871 /**
1872 * Checks if user changed the persistent settings_fuse flag from Settings UI
1873 * and updates PROP_FUSE (reboots if changed).
1874 */
1875 private void updateFusePropFromSettings() {
Zim238aa332020-02-11 16:59:09 +00001876 boolean settingsFuseFlag = SystemProperties.getBoolean(PROP_SETTINGS_FUSE,
1877 DEFAULT_FUSE_ENABLED);
1878 Slog.d(TAG, "FUSE flags. Settings: " + settingsFuseFlag
1879 + ". Default: " + DEFAULT_FUSE_ENABLED);
Abhijeet Kaura4f40562019-12-09 13:55:42 +00001880
Zim69e9c092020-01-21 13:32:32 +00001881 if (mIsFuseEnabled != settingsFuseFlag) {
1882 Slog.i(TAG, "Toggling persist.sys.fuse to " + settingsFuseFlag);
Zim238aa332020-02-11 16:59:09 +00001883 // Set prop_fuse to match prop_settings_fuse because it is used by native daemons like
1884 // init, zygote, installd and vold
Zim69e9c092020-01-21 13:32:32 +00001885 SystemProperties.set(PROP_FUSE, Boolean.toString(settingsFuseFlag));
Zim238aa332020-02-11 16:59:09 +00001886 // Then perform hard reboot to kick policy into place
Shafik Nassar07dcbbc2020-01-28 18:35:25 +00001887 mContext.getSystemService(PowerManager.class).reboot("fuse_prop");
Abhijeet Kaurb9847712019-11-19 16:35:47 +00001888 }
1889 }
1890
Jeff Sharkeycd575992016-03-29 14:12:49 -06001891 private void start() {
peter.zhangb0d11d12019-06-13 16:39:30 +08001892 connectStoraged();
1893 connectVold();
Jeff Sharkeycd575992016-03-29 14:12:49 -06001894 }
1895
peter.zhangb0d11d12019-06-13 16:39:30 +08001896 private void connectStoraged() {
Jin Qian12690d52017-10-13 18:17:04 -07001897 IBinder binder = ServiceManager.getService("storaged");
1898 if (binder != null) {
1899 try {
1900 binder.linkToDeath(new DeathRecipient() {
1901 @Override
1902 public void binderDied() {
1903 Slog.w(TAG, "storaged died; reconnecting");
1904 mStoraged = null;
peter.zhangb0d11d12019-06-13 16:39:30 +08001905 connectStoraged();
Jin Qian12690d52017-10-13 18:17:04 -07001906 }
1907 }, 0);
1908 } catch (RemoteException e) {
1909 binder = null;
1910 }
1911 }
1912
1913 if (binder != null) {
1914 mStoraged = IStoraged.Stub.asInterface(binder);
1915 } else {
1916 Slog.w(TAG, "storaged not found; trying again");
1917 }
1918
peter.zhangb0d11d12019-06-13 16:39:30 +08001919 if (mStoraged == null) {
1920 BackgroundThread.getHandler().postDelayed(() -> {
1921 connectStoraged();
1922 }, DateUtils.SECOND_IN_MILLIS);
1923 } else {
1924 onDaemonConnected();
1925 }
1926 }
1927
1928 private void connectVold() {
1929 IBinder binder = ServiceManager.getService("vold");
Jeff Sharkey1019de92017-09-06 13:47:03 -06001930 if (binder != null) {
1931 try {
1932 binder.linkToDeath(new DeathRecipient() {
1933 @Override
1934 public void binderDied() {
1935 Slog.w(TAG, "vold died; reconnecting");
Jin Qian12690d52017-10-13 18:17:04 -07001936 mVold = null;
peter.zhangb0d11d12019-06-13 16:39:30 +08001937 connectVold();
Jeff Sharkey1019de92017-09-06 13:47:03 -06001938 }
1939 }, 0);
1940 } catch (RemoteException e) {
1941 binder = null;
1942 }
1943 }
1944
1945 if (binder != null) {
1946 mVold = IVold.Stub.asInterface(binder);
Jeff Sharkey8058fe62017-09-13 11:50:33 -06001947 try {
1948 mVold.setListener(mListener);
Jeff Sharkey8058fe62017-09-13 11:50:33 -06001949 } catch (RemoteException e) {
Jin Qian12690d52017-10-13 18:17:04 -07001950 mVold = null;
Jeff Sharkey8058fe62017-09-13 11:50:33 -06001951 Slog.w(TAG, "vold listener rejected; trying again", e);
1952 }
Jeff Sharkey1019de92017-09-06 13:47:03 -06001953 } else {
1954 Slog.w(TAG, "vold not found; trying again");
Jeff Sharkey1019de92017-09-06 13:47:03 -06001955 }
Jeff Sharkey8058fe62017-09-13 11:50:33 -06001956
peter.zhangb0d11d12019-06-13 16:39:30 +08001957 if (mVold == null) {
Jin Qian12690d52017-10-13 18:17:04 -07001958 BackgroundThread.getHandler().postDelayed(() -> {
peter.zhangb0d11d12019-06-13 16:39:30 +08001959 connectVold();
Jin Qian12690d52017-10-13 18:17:04 -07001960 }, DateUtils.SECOND_IN_MILLIS);
1961 } else {
1962 onDaemonConnected();
1963 }
Jeff Sharkey1019de92017-09-06 13:47:03 -06001964 }
1965
Jeff Sharkey11697f52018-12-13 10:14:42 -07001966 private void servicesReady() {
Sudheer Shankaff585072019-01-29 23:19:45 -08001967 mPmInternal = LocalServices.getService(PackageManagerInternal.class);
Sudheer Shankaff585072019-01-29 23:19:45 -08001968
1969 mIPackageManager = IPackageManager.Stub.asInterface(
1970 ServiceManager.getService("package"));
1971 mIAppOpsService = IAppOpsService.Stub.asInterface(
1972 ServiceManager.getService(Context.APP_OPS_SERVICE));
Zim74a9bba2019-09-03 20:49:13 +01001973
Abhijeet Kaurde4e90a2020-05-14 11:44:15 +01001974 ProviderInfo provider = getProviderInfo(MediaStore.AUTHORITY);
Zim74a9bba2019-09-03 20:49:13 +01001975 if (provider != null) {
Martijn Coenen44db1ac2019-12-03 16:06:19 +01001976 mMediaStoreAuthorityAppId = UserHandle.getAppId(provider.applicationInfo.uid);
Zim9ce0a7c2020-03-04 07:34:27 +00001977 sMediaStoreAuthorityProcessName = provider.applicationInfo.processName;
Zim74a9bba2019-09-03 20:49:13 +01001978 }
1979
Abhijeet Kaurde4e90a2020-05-14 11:44:15 +01001980 provider = getProviderInfo(Downloads.Impl.AUTHORITY);
Martijn Coenen496ac002020-01-08 14:55:53 +01001981 if (provider != null) {
1982 mDownloadsAuthorityAppId = UserHandle.getAppId(provider.applicationInfo.uid);
1983 }
1984
Abhijeet Kaurde4e90a2020-05-14 11:44:15 +01001985 provider = getProviderInfo(DocumentsContract.EXTERNAL_STORAGE_PROVIDER_AUTHORITY);
1986 if (provider != null) {
1987 mExternalStorageAuthorityAppId = UserHandle.getAppId(provider.applicationInfo.uid);
1988 }
1989
Sudheer Shanka3567f2b2020-05-07 03:37:17 -07001990 if (!mIsFuseEnabled) {
1991 try {
1992 mIAppOpsService.startWatchingMode(OP_REQUEST_INSTALL_PACKAGES, null,
1993 mAppOpsCallback);
1994 mIAppOpsService.startWatchingMode(OP_LEGACY_STORAGE, null, mAppOpsCallback);
1995 } catch (RemoteException e) {
1996 }
Sudheer Shankaff585072019-01-29 23:19:45 -08001997 }
Jeff Sharkey11697f52018-12-13 10:14:42 -07001998 }
1999
Abhijeet Kaurde4e90a2020-05-14 11:44:15 +01002000 private ProviderInfo getProviderInfo(String authority) {
2001 return mPmInternal.resolveContentProvider(
2002 authority, PackageManager.MATCH_DIRECT_BOOT_AWARE
2003 | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
2004 UserHandle.getUserId(UserHandle.USER_SYSTEM));
2005 }
2006
Zim3ce38492020-02-07 15:14:58 +00002007 private void updateLegacyStorageApps(String packageName, int uid, boolean hasLegacy) {
2008 synchronized (mLock) {
2009 if (hasLegacy) {
2010 Slog.v(TAG, "Package " + packageName + " has legacy storage");
2011 mUidsWithLegacyExternalStorage.add(uid);
2012 } else {
2013 // TODO(b/149391976): Handle shared user id. Check if there's any other
2014 // installed app with legacy external storage before removing
2015 Slog.v(TAG, "Package " + packageName + " does not have legacy storage");
2016 mUidsWithLegacyExternalStorage.remove(uid);
2017 }
2018 }
2019 }
2020
2021 private void snapshotAndMonitorLegacyStorageAppOp(UserHandle user) {
2022 int userId = user.getIdentifier();
2023
2024 // TODO(b/149391976): Use mIAppOpsService.getPackagesForOps instead of iterating below
2025 // It should improve performance but the AppOps method doesn't return any app here :(
2026 // This operation currently takes about ~20ms on a freshly flashed device
2027 for (ApplicationInfo ai : mPmInternal.getInstalledApplications(MATCH_DIRECT_BOOT_AWARE
2028 | MATCH_DIRECT_BOOT_UNAWARE | MATCH_UNINSTALLED_PACKAGES | MATCH_ANY_USER,
2029 userId, Process.myUid())) {
2030 try {
2031 boolean hasLegacy = mIAppOpsService.checkOperation(OP_LEGACY_STORAGE, ai.uid,
2032 ai.packageName) == MODE_ALLOWED;
2033 updateLegacyStorageApps(ai.packageName, ai.uid, hasLegacy);
2034 } catch (RemoteException e) {
2035 Slog.e(TAG, "Failed to check legacy op for package " + ai.packageName, e);
2036 }
2037 }
2038
2039 PackageMonitor monitor = new PackageMonitor() {
2040 @Override
2041 public void onPackageRemoved(String packageName, int uid) {
2042 updateLegacyStorageApps(packageName, uid, false);
2043 }
2044 };
2045 // TODO(b/149391976): Use different handler?
2046 monitor.register(mContext, user, true, mHandler);
2047 mPackageMonitorsForUser.put(userId, monitor);
2048 }
2049
Jeff Sharkey11697f52018-12-13 10:14:42 -07002050 private static long getLastAccessTime(AppOpsManager manager,
2051 int uid, String packageName, int[] ops) {
2052 long maxTime = 0;
2053 final List<AppOpsManager.PackageOps> pkgs = manager.getOpsForPackage(uid, packageName, ops);
Eugene Susla04d021c2018-12-17 14:49:59 -08002054 for (AppOpsManager.PackageOps pkg : CollectionUtils.emptyIfNull(pkgs)) {
2055 for (AppOpsManager.OpEntry op : CollectionUtils.emptyIfNull(pkg.getOps())) {
Svet Ganovaf189e32019-02-15 18:45:29 -08002056 maxTime = Math.max(maxTime, op.getLastAccessTime(
2057 AppOpsManager.OP_FLAGS_ALL_TRUSTED));
Jeff Sharkey11697f52018-12-13 10:14:42 -07002058 }
2059 }
2060 return maxTime;
2061 }
2062
Jeff Sharkey56e62932015-03-21 20:41:00 -07002063 private void systemReady() {
Wale Ogunwale6767eae2018-05-03 15:52:51 -07002064 LocalServices.getService(ActivityTaskManagerInternal.class)
Jeff Sharkey9765e442017-12-14 22:15:14 -07002065 .registerScreenObserver(this);
2066
Jeff Sharkeyb049e212012-09-07 23:16:01 -07002067 mHandler.obtainMessage(H_SYSTEM_READY).sendToTarget();
2068 }
2069
Yasuhiro Matsuda87a38b52015-07-24 22:10:16 +09002070 private void bootCompleted() {
2071 mBootCompleted = true;
Daniel Rosenberg137aed12019-03-15 18:41:11 -07002072 mHandler.obtainMessage(H_BOOT_COMPLETED).sendToTarget();
Abhijeet Kaur10c56552019-12-04 14:17:40 +00002073 updateFusePropFromSettings();
Daniel Rosenberg137aed12019-03-15 18:41:11 -07002074 }
2075
2076 private void handleBootCompleted() {
2077 initIfBootedAndConnected();
2078 resetIfBootedAndConnected();
Yasuhiro Matsuda87a38b52015-07-24 22:10:16 +09002079 }
2080
Jeff Sharkeyfced5342015-05-10 14:53:34 -07002081 private String getDefaultPrimaryStorageUuid() {
2082 if (SystemProperties.getBoolean(StorageManager.PROP_PRIMARY_PHYSICAL, false)) {
2083 return StorageManager.UUID_PRIMARY_PHYSICAL;
2084 } else {
2085 return StorageManager.UUID_PRIVATE_INTERNAL;
2086 }
2087 }
2088
Andreas Gampea36dc622018-02-05 17:19:22 -08002089 @GuardedBy("mLock")
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07002090 private void readSettingsLocked() {
2091 mRecords.clear();
Jeff Sharkeyfced5342015-05-10 14:53:34 -07002092 mPrimaryStorageUuid = getDefaultPrimaryStorageUuid();
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07002093
2094 FileInputStream fis = null;
2095 try {
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07002096 fis = mSettingsFile.openRead();
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07002097 final XmlPullParser in = Xml.newPullParser();
Wojciech Staszkiewicz9e9e2e72015-05-08 14:58:46 +01002098 in.setInput(fis, StandardCharsets.UTF_8.name());
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07002099
2100 int type;
2101 while ((type = in.next()) != END_DOCUMENT) {
2102 if (type == START_TAG) {
2103 final String tag = in.getName();
Jeff Sharkey620b32b2015-04-23 19:36:02 -07002104 if (TAG_VOLUMES.equals(tag)) {
2105 final int version = readIntAttribute(in, ATTR_VERSION, VERSION_INIT);
Jeff Sharkeyfced5342015-05-10 14:53:34 -07002106 final boolean primaryPhysical = SystemProperties.getBoolean(
2107 StorageManager.PROP_PRIMARY_PHYSICAL, false);
2108 final boolean validAttr = (version >= VERSION_FIX_PRIMARY)
2109 || (version >= VERSION_ADD_PRIMARY && !primaryPhysical);
2110 if (validAttr) {
Jeff Sharkey620b32b2015-04-23 19:36:02 -07002111 mPrimaryStorageUuid = readStringAttribute(in,
2112 ATTR_PRIMARY_STORAGE_UUID);
Jeff Sharkey620b32b2015-04-23 19:36:02 -07002113 }
Jeff Sharkey620b32b2015-04-23 19:36:02 -07002114 } else if (TAG_VOLUME.equals(tag)) {
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07002115 final VolumeRecord rec = readVolumeRecord(in);
2116 mRecords.put(rec.fsUuid, rec);
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07002117 }
2118 }
2119 }
2120 } catch (FileNotFoundException e) {
2121 // Missing metadata is okay, probably first boot
2122 } catch (IOException e) {
2123 Slog.wtf(TAG, "Failed reading metadata", e);
2124 } catch (XmlPullParserException e) {
2125 Slog.wtf(TAG, "Failed reading metadata", e);
2126 } finally {
2127 IoUtils.closeQuietly(fis);
2128 }
2129 }
2130
Andreas Gampea36dc622018-02-05 17:19:22 -08002131 @GuardedBy("mLock")
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07002132 private void writeSettingsLocked() {
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07002133 FileOutputStream fos = null;
2134 try {
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07002135 fos = mSettingsFile.startWrite();
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07002136
2137 XmlSerializer out = new FastXmlSerializer();
Wojciech Staszkiewicz9e9e2e72015-05-08 14:58:46 +01002138 out.setOutput(fos, StandardCharsets.UTF_8.name());
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07002139 out.startDocument(null, true);
2140 out.startTag(null, TAG_VOLUMES);
Jeff Sharkeyfced5342015-05-10 14:53:34 -07002141 writeIntAttribute(out, ATTR_VERSION, VERSION_FIX_PRIMARY);
Jeff Sharkey620b32b2015-04-23 19:36:02 -07002142 writeStringAttribute(out, ATTR_PRIMARY_STORAGE_UUID, mPrimaryStorageUuid);
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07002143 final int size = mRecords.size();
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07002144 for (int i = 0; i < size; i++) {
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07002145 final VolumeRecord rec = mRecords.valueAt(i);
2146 writeVolumeRecord(out, rec);
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07002147 }
2148 out.endTag(null, TAG_VOLUMES);
2149 out.endDocument();
2150
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07002151 mSettingsFile.finishWrite(fos);
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07002152 } catch (IOException e) {
2153 if (fos != null) {
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07002154 mSettingsFile.failWrite(fos);
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07002155 }
2156 }
2157 }
2158
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07002159 public static VolumeRecord readVolumeRecord(XmlPullParser in) throws IOException {
2160 final int type = readIntAttribute(in, ATTR_TYPE);
2161 final String fsUuid = readStringAttribute(in, ATTR_FS_UUID);
2162 final VolumeRecord meta = new VolumeRecord(type, fsUuid);
Jeff Sharkey5cc0df22015-06-17 19:44:05 -07002163 meta.partGuid = readStringAttribute(in, ATTR_PART_GUID);
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07002164 meta.nickname = readStringAttribute(in, ATTR_NICKNAME);
2165 meta.userFlags = readIntAttribute(in, ATTR_USER_FLAGS);
Jeff Sharkey3811f352019-05-14 11:54:36 -06002166 meta.createdMillis = readLongAttribute(in, ATTR_CREATED_MILLIS, 0);
2167 meta.lastSeenMillis = readLongAttribute(in, ATTR_LAST_SEEN_MILLIS, 0);
2168 meta.lastTrimMillis = readLongAttribute(in, ATTR_LAST_TRIM_MILLIS, 0);
2169 meta.lastBenchMillis = readLongAttribute(in, ATTR_LAST_BENCH_MILLIS, 0);
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07002170 return meta;
2171 }
2172
2173 public static void writeVolumeRecord(XmlSerializer out, VolumeRecord rec) throws IOException {
2174 out.startTag(null, TAG_VOLUME);
2175 writeIntAttribute(out, ATTR_TYPE, rec.type);
2176 writeStringAttribute(out, ATTR_FS_UUID, rec.fsUuid);
Jeff Sharkey5cc0df22015-06-17 19:44:05 -07002177 writeStringAttribute(out, ATTR_PART_GUID, rec.partGuid);
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07002178 writeStringAttribute(out, ATTR_NICKNAME, rec.nickname);
2179 writeIntAttribute(out, ATTR_USER_FLAGS, rec.userFlags);
Jeff Sharkeye8a4b662015-06-27 15:43:45 -07002180 writeLongAttribute(out, ATTR_CREATED_MILLIS, rec.createdMillis);
Jeff Sharkey3811f352019-05-14 11:54:36 -06002181 writeLongAttribute(out, ATTR_LAST_SEEN_MILLIS, rec.lastSeenMillis);
Jeff Sharkeye8a4b662015-06-27 15:43:45 -07002182 writeLongAttribute(out, ATTR_LAST_TRIM_MILLIS, rec.lastTrimMillis);
2183 writeLongAttribute(out, ATTR_LAST_BENCH_MILLIS, rec.lastBenchMillis);
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07002184 out.endTag(null, TAG_VOLUME);
2185 }
2186
San Mehat207e5382010-02-04 20:46:54 -08002187 /**
San Mehat4270e1e2010-01-29 05:32:19 -08002188 * Exposed API calls below here
2189 */
2190
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07002191 @Override
Sudheer Shanka2250d562016-11-07 15:41:02 -08002192 public void registerListener(IStorageEventListener listener) {
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07002193 mCallbacks.register(listener);
San Mehat4270e1e2010-01-29 05:32:19 -08002194 }
2195
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07002196 @Override
Sudheer Shanka2250d562016-11-07 15:41:02 -08002197 public void unregisterListener(IStorageEventListener listener) {
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07002198 mCallbacks.unregister(listener);
San Mehat4270e1e2010-01-29 05:32:19 -08002199 }
2200
Jeff Sharkey48877892015-03-18 11:27:19 -07002201 @Override
Sudheer Shanka2250d562016-11-07 15:41:02 -08002202 public void shutdown(final IStorageShutdownObserver observer) {
Jeff Sharkey48877892015-03-18 11:27:19 -07002203 enforcePermission(android.Manifest.permission.SHUTDOWN);
San Mehat4270e1e2010-01-29 05:32:19 -08002204
San Mehata5078592010-03-25 09:36:54 -07002205 Slog.i(TAG, "Shutting down");
Jeff Sharkey48877892015-03-18 11:27:19 -07002206 mHandler.obtainMessage(H_SHUTDOWN, observer).sendToTarget();
San Mehat4270e1e2010-01-29 05:32:19 -08002207 }
2208
Jeff Sharkey48877892015-03-18 11:27:19 -07002209 @Override
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07002210 public void mount(String volId) {
2211 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07002212
Jeff Sharkeyef10ee02015-07-05 14:17:27 -07002213 final VolumeInfo vol = findVolumeByIdOrThrow(volId);
Jeff Sharkey2e606d72015-07-27 14:19:54 -07002214 if (isMountDisallowed(vol)) {
2215 throw new SecurityException("Mounting " + volId + " restricted by policy");
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07002216 }
Zim17be6f92019-09-25 14:37:55 +01002217
Sudheer Shanka3f0645b2018-09-18 13:07:59 -07002218 mount(vol);
2219 }
2220
Ricky Wai486d7602020-02-28 16:37:07 +00002221 private void remountAppStorageDirs(Map<Integer, String> pidPkgMap, int userId) {
2222 for (Entry<Integer, String> entry : pidPkgMap.entrySet()) {
2223 final int pid = entry.getKey();
2224 final String packageName = entry.getValue();
2225 Slog.i(TAG, "Remounting storage for pid: " + pid);
2226 final String[] sharedPackages =
2227 mPmInternal.getSharedUserPackagesForPackage(packageName, userId);
2228 final int uid = mPmInternal.getPackageUidInternal(packageName, 0, userId);
2229 final String[] packages =
2230 sharedPackages.length != 0 ? sharedPackages : new String[]{packageName};
2231 try {
2232 mVold.remountAppStorageDirs(uid, pid, packages);
2233 } catch (RemoteException e) {
2234 throw e.rethrowAsRuntimeException();
2235 }
2236 }
2237 }
2238
Zim17be6f92019-09-25 14:37:55 +01002239 private void mount(VolumeInfo vol) {
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07002240 try {
Zim17be6f92019-09-25 14:37:55 +01002241 // TODO(b/135341433): Remove paranoid logging when FUSE is stable
2242 Slog.i(TAG, "Mounting volume " + vol);
Zim95eca1d2019-11-15 18:03:00 +00002243 mVold.mount(vol.id, vol.mountFlags, vol.mountUserId, new IVoldMountCallback.Stub() {
Ricky Wai486d7602020-02-28 16:37:07 +00002244 @Override
2245 public boolean onVolumeChecking(FileDescriptor fd, String path,
2246 String internalPath) {
2247 vol.path = path;
2248 vol.internalPath = internalPath;
2249 ParcelFileDescriptor pfd = new ParcelFileDescriptor(fd);
2250 try {
2251 mStorageSessionController.onVolumeMount(pfd, vol);
2252 return true;
2253 } catch (ExternalStorageServiceException e) {
2254 Slog.e(TAG, "Failed to mount volume " + vol, e);
Zim7924a512020-01-15 15:23:54 +00002255
Martijn Coenenab0c7402020-06-17 14:42:13 +02002256 int nextResetSeconds = FAILED_MOUNT_RESET_TIMEOUT_SECONDS;
Ricky Wai486d7602020-02-28 16:37:07 +00002257 Slog.i(TAG, "Scheduling reset in " + nextResetSeconds + "s");
2258 mHandler.removeMessages(H_RESET);
2259 mHandler.sendMessageDelayed(mHandler.obtainMessage(H_RESET),
2260 TimeUnit.SECONDS.toMillis(nextResetSeconds));
2261 return false;
2262 } finally {
2263 try {
2264 pfd.close();
2265 } catch (Exception e) {
2266 Slog.e(TAG, "Failed to close FUSE device fd", e);
Zim95eca1d2019-11-15 18:03:00 +00002267 }
2268 }
Ricky Wai486d7602020-02-28 16:37:07 +00002269 }
2270 });
Zim17be6f92019-09-25 14:37:55 +01002271 Slog.i(TAG, "Mounted volume " + vol);
Jeff Sharkeyace874b2017-09-07 15:27:33 -06002272 } catch (Exception e) {
2273 Slog.wtf(TAG, e);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07002274 }
2275 }
2276
2277 @Override
2278 public void unmount(String volId) {
2279 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07002280
Jeff Sharkeyef10ee02015-07-05 14:17:27 -07002281 final VolumeInfo vol = findVolumeByIdOrThrow(volId);
Sudheer Shanka3f0645b2018-09-18 13:07:59 -07002282 unmount(vol);
2283 }
2284
2285 private void unmount(VolumeInfo vol) {
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07002286 try {
Ricky Wai4482ab52019-12-10 19:08:18 +00002287 try {
2288 if (vol.type == VolumeInfo.TYPE_PRIVATE) {
2289 mInstaller.onPrivateVolumeRemoved(vol.getFsUuid());
2290 }
2291 } catch (Installer.InstallerException e) {
2292 Slog.e(TAG, "Failed unmount mirror data", e);
2293 }
Ricky Waie5088d92020-01-22 17:52:52 +00002294 mVold.unmount(vol.id);
2295 mStorageSessionController.onVolumeUnmount(vol);
Jeff Sharkeyace874b2017-09-07 15:27:33 -06002296 } catch (Exception e) {
2297 Slog.wtf(TAG, e);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07002298 }
2299 }
2300
2301 @Override
2302 public void format(String volId) {
Jeff Sharkey48877892015-03-18 11:27:19 -07002303 enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);
San Mehat5b77dab2010-01-26 13:28:50 -08002304
Jeff Sharkeyef10ee02015-07-05 14:17:27 -07002305 final VolumeInfo vol = findVolumeByIdOrThrow(volId);
Jeff Sharkeye56dab22020-06-16 10:12:54 -06002306 final String fsUuid = vol.fsUuid;
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07002307 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002308 mVold.format(vol.id, "auto");
Jeff Sharkeye56dab22020-06-16 10:12:54 -06002309
2310 // After a successful format above, we should forget about any
2311 // records for the old partition, since it'll never appear again
2312 if (!TextUtils.isEmpty(fsUuid)) {
2313 forgetVolume(fsUuid);
2314 }
Jeff Sharkeyace874b2017-09-07 15:27:33 -06002315 } catch (Exception e) {
2316 Slog.wtf(TAG, e);
Jeff Sharkey48877892015-03-18 11:27:19 -07002317 }
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07002318 }
2319
2320 @Override
Jeff Sharkey7e19f532017-11-06 13:54:11 -07002321 public void benchmark(String volId, IVoldTaskListener listener) {
Jeff Sharkey9756d752015-05-14 21:07:42 -07002322 enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);
Jeff Sharkey9756d752015-05-14 21:07:42 -07002323
2324 try {
Jeff Sharkeyb302c542017-09-15 12:57:59 -06002325 mVold.benchmark(volId, new IVoldTaskListener.Stub() {
2326 @Override
2327 public void onStatus(int status, PersistableBundle extras) {
Jeff Sharkey7e19f532017-11-06 13:54:11 -07002328 dispatchOnStatus(listener, status, extras);
Jeff Sharkeyb302c542017-09-15 12:57:59 -06002329 }
2330
2331 @Override
2332 public void onFinished(int status, PersistableBundle extras) {
Jeff Sharkey7e19f532017-11-06 13:54:11 -07002333 dispatchOnFinished(listener, status, extras);
Jeff Sharkeyb302c542017-09-15 12:57:59 -06002334
2335 final String path = extras.getString("path");
2336 final String ident = extras.getString("ident");
2337 final long create = extras.getLong("create");
2338 final long run = extras.getLong("run");
2339 final long destroy = extras.getLong("destroy");
2340
2341 final DropBoxManager dropBox = mContext.getSystemService(DropBoxManager.class);
2342 dropBox.addText(TAG_STORAGE_BENCHMARK, scrubPath(path)
2343 + " " + ident + " " + create + " " + run + " " + destroy);
2344
2345 synchronized (mLock) {
2346 final VolumeRecord rec = findRecordForPath(path);
2347 if (rec != null) {
2348 rec.lastBenchMillis = System.currentTimeMillis();
2349 writeSettingsLocked();
2350 }
2351 }
2352 }
2353 });
Jeff Sharkey7e19f532017-11-06 13:54:11 -07002354 } catch (RemoteException e) {
2355 throw e.rethrowAsRuntimeException();
Jeff Sharkey9756d752015-05-14 21:07:42 -07002356 }
2357 }
2358
2359 @Override
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07002360 public void partitionPublic(String diskId) {
2361 enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07002362
Jeff Sharkeyeba260d2015-04-19 14:35:16 -07002363 final CountDownLatch latch = findOrCreateDiskScanLatch(diskId);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07002364 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002365 mVold.partition(diskId, IVold.PARTITION_TYPE_PUBLIC, -1);
Jeff Sharkeyedcdaf62015-07-09 09:45:36 -07002366 waitForLatch(latch, "partitionPublic", 3 * DateUtils.MINUTE_IN_MILLIS);
Jeff Sharkeyace874b2017-09-07 15:27:33 -06002367 } catch (Exception e) {
2368 Slog.wtf(TAG, e);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07002369 }
2370 }
2371
2372 @Override
2373 public void partitionPrivate(String diskId) {
2374 enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);
Amith Yamasani462ac3a2015-06-30 14:21:01 -07002375 enforceAdminUser();
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07002376
Jeff Sharkeyeba260d2015-04-19 14:35:16 -07002377 final CountDownLatch latch = findOrCreateDiskScanLatch(diskId);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07002378 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002379 mVold.partition(diskId, IVold.PARTITION_TYPE_PRIVATE, -1);
Jeff Sharkeyedcdaf62015-07-09 09:45:36 -07002380 waitForLatch(latch, "partitionPrivate", 3 * DateUtils.MINUTE_IN_MILLIS);
Jeff Sharkeyace874b2017-09-07 15:27:33 -06002381 } catch (Exception e) {
2382 Slog.wtf(TAG, e);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07002383 }
2384 }
2385
2386 @Override
2387 public void partitionMixed(String diskId, int ratio) {
2388 enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);
Amith Yamasani462ac3a2015-06-30 14:21:01 -07002389 enforceAdminUser();
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07002390
Jeff Sharkeyeba260d2015-04-19 14:35:16 -07002391 final CountDownLatch latch = findOrCreateDiskScanLatch(diskId);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07002392 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002393 mVold.partition(diskId, IVold.PARTITION_TYPE_MIXED, ratio);
Jeff Sharkeyedcdaf62015-07-09 09:45:36 -07002394 waitForLatch(latch, "partitionMixed", 3 * DateUtils.MINUTE_IN_MILLIS);
Jeff Sharkeyace874b2017-09-07 15:27:33 -06002395 } catch (Exception e) {
2396 Slog.wtf(TAG, e);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07002397 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002398 }
2399
Jeff Sharkey48877892015-03-18 11:27:19 -07002400 @Override
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07002401 public void setVolumeNickname(String fsUuid, String nickname) {
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07002402 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07002403
Daulet Zhanguzinea1a7ca2020-01-03 09:46:50 +00002404 Objects.requireNonNull(fsUuid);
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07002405 synchronized (mLock) {
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07002406 final VolumeRecord rec = mRecords.get(fsUuid);
2407 rec.nickname = nickname;
Jeff Sharkey50a05452015-04-29 11:24:52 -07002408 mCallbacks.notifyVolumeRecordChanged(rec);
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07002409 writeSettingsLocked();
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07002410 }
2411 }
2412
2413 @Override
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07002414 public void setVolumeUserFlags(String fsUuid, int flags, int mask) {
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07002415 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07002416
Daulet Zhanguzinea1a7ca2020-01-03 09:46:50 +00002417 Objects.requireNonNull(fsUuid);
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07002418 synchronized (mLock) {
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07002419 final VolumeRecord rec = mRecords.get(fsUuid);
2420 rec.userFlags = (rec.userFlags & ~mask) | (flags & mask);
Jeff Sharkey50a05452015-04-29 11:24:52 -07002421 mCallbacks.notifyVolumeRecordChanged(rec);
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07002422 writeSettingsLocked();
2423 }
2424 }
2425
2426 @Override
2427 public void forgetVolume(String fsUuid) {
2428 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07002429
Daulet Zhanguzinea1a7ca2020-01-03 09:46:50 +00002430 Objects.requireNonNull(fsUuid);
Jeff Sharkey5a9bb742015-11-03 10:15:57 -08002431
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07002432 synchronized (mLock) {
Jeff Sharkey5cc0df22015-06-17 19:44:05 -07002433 final VolumeRecord rec = mRecords.remove(fsUuid);
2434 if (rec != null && !TextUtils.isEmpty(rec.partGuid)) {
Jeff Sharkeydb4b6192017-10-24 11:08:50 -06002435 mHandler.obtainMessage(H_PARTITION_FORGET, rec).sendToTarget();
Jeff Sharkey5cc0df22015-06-17 19:44:05 -07002436 }
2437 mCallbacks.notifyVolumeForgotten(fsUuid);
Jeff Sharkey50a05452015-04-29 11:24:52 -07002438
2439 // If this had been primary storage, revert back to internal and
2440 // reset vold so we bind into new volume into place.
2441 if (Objects.equals(mPrimaryStorageUuid, fsUuid)) {
Jeff Sharkeyfced5342015-05-10 14:53:34 -07002442 mPrimaryStorageUuid = getDefaultPrimaryStorageUuid();
Jeff Sharkey5a9bb742015-11-03 10:15:57 -08002443 mHandler.obtainMessage(H_RESET).sendToTarget();
Jeff Sharkey50a05452015-04-29 11:24:52 -07002444 }
2445
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07002446 writeSettingsLocked();
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07002447 }
2448 }
2449
Jeff Sharkey7d2af542015-05-12 15:27:15 -07002450 @Override
2451 public void forgetAllVolumes() {
2452 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
Jeff Sharkey7d2af542015-05-12 15:27:15 -07002453
Jeff Sharkey50a05452015-04-29 11:24:52 -07002454 synchronized (mLock) {
2455 for (int i = 0; i < mRecords.size(); i++) {
2456 final String fsUuid = mRecords.keyAt(i);
Jeff Sharkey5cc0df22015-06-17 19:44:05 -07002457 final VolumeRecord rec = mRecords.valueAt(i);
2458 if (!TextUtils.isEmpty(rec.partGuid)) {
Jeff Sharkeydb4b6192017-10-24 11:08:50 -06002459 mHandler.obtainMessage(H_PARTITION_FORGET, rec).sendToTarget();
Jeff Sharkey5cc0df22015-06-17 19:44:05 -07002460 }
Jeff Sharkey50a05452015-04-29 11:24:52 -07002461 mCallbacks.notifyVolumeForgotten(fsUuid);
2462 }
Jeff Sharkey50a05452015-04-29 11:24:52 -07002463 mRecords.clear();
Jeff Sharkey50a05452015-04-29 11:24:52 -07002464
Jeff Sharkeyfced5342015-05-10 14:53:34 -07002465 if (!Objects.equals(StorageManager.UUID_PRIVATE_INTERNAL, mPrimaryStorageUuid)) {
2466 mPrimaryStorageUuid = getDefaultPrimaryStorageUuid();
2467 }
2468
2469 writeSettingsLocked();
Jeff Sharkey5a9bb742015-11-03 10:15:57 -08002470 mHandler.obtainMessage(H_RESET).sendToTarget();
Jeff Sharkey50a05452015-04-29 11:24:52 -07002471 }
2472 }
2473
Jeff Sharkeydb4b6192017-10-24 11:08:50 -06002474 private void forgetPartition(String partGuid, String fsUuid) {
Jeff Sharkey5cc0df22015-06-17 19:44:05 -07002475 try {
Jeff Sharkeydb4b6192017-10-24 11:08:50 -06002476 mVold.forgetPartition(partGuid, fsUuid);
Jeff Sharkeyace874b2017-09-07 15:27:33 -06002477 } catch (Exception e) {
2478 Slog.wtf(TAG, e);
Jeff Sharkey5cc0df22015-06-17 19:44:05 -07002479 }
2480 }
2481
Jeff Sharkey31d0b702016-11-21 14:16:53 -07002482 @Override
Jeff Sharkey7e19f532017-11-06 13:54:11 -07002483 public void fstrim(int flags, IVoldTaskListener listener) {
Jeff Sharkey31d0b702016-11-21 14:16:53 -07002484 enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);
Jeff Sharkey31d0b702016-11-21 14:16:53 -07002485
2486 try {
Sandeep Patil7d5c4912019-04-15 09:27:30 -07002487 // Block based checkpoint process runs fstrim. So, if checkpoint is in progress
2488 // (first boot after OTA), We skip idle maintenance and make sure the last
2489 // fstrim time is still updated. If file based checkpoints are used, we run
2490 // idle maintenance (GC + fstrim) regardless of checkpoint status.
2491 if (!needsCheckpoint() || !supportsBlockCheckpoint()) {
2492 mVold.fstrim(flags, new IVoldTaskListener.Stub() {
2493 @Override
2494 public void onStatus(int status, PersistableBundle extras) {
2495 dispatchOnStatus(listener, status, extras);
Jeff Sharkey7e19f532017-11-06 13:54:11 -07002496
Sandeep Patil7d5c4912019-04-15 09:27:30 -07002497 // Ignore trim failures
2498 if (status != 0) return;
Jeff Sharkeyb302c542017-09-15 12:57:59 -06002499
Sandeep Patil7d5c4912019-04-15 09:27:30 -07002500 final String path = extras.getString("path");
2501 final long bytes = extras.getLong("bytes");
2502 final long time = extras.getLong("time");
Jeff Sharkeyb302c542017-09-15 12:57:59 -06002503
Sandeep Patil7d5c4912019-04-15 09:27:30 -07002504 final DropBoxManager dropBox = mContext.getSystemService(DropBoxManager.class);
2505 dropBox.addText(TAG_STORAGE_TRIM, scrubPath(path) + " " + bytes + " " + time);
Jeff Sharkeyb302c542017-09-15 12:57:59 -06002506
Sandeep Patil7d5c4912019-04-15 09:27:30 -07002507 synchronized (mLock) {
2508 final VolumeRecord rec = findRecordForPath(path);
2509 if (rec != null) {
2510 rec.lastTrimMillis = System.currentTimeMillis();
2511 writeSettingsLocked();
2512 }
Jeff Sharkeyb302c542017-09-15 12:57:59 -06002513 }
2514 }
Jeff Sharkeyb302c542017-09-15 12:57:59 -06002515
Sandeep Patil7d5c4912019-04-15 09:27:30 -07002516 @Override
2517 public void onFinished(int status, PersistableBundle extras) {
2518 dispatchOnFinished(listener, status, extras);
Jeff Sharkey7e19f532017-11-06 13:54:11 -07002519
Sandeep Patil7d5c4912019-04-15 09:27:30 -07002520 // TODO: benchmark when desired
2521 }
2522 });
2523 } else {
2524 Slog.i(TAG, "Skipping fstrim - block based checkpoint in progress");
2525 }
Jeff Sharkey7e19f532017-11-06 13:54:11 -07002526 } catch (RemoteException e) {
2527 throw e.rethrowAsRuntimeException();
Jeff Sharkey31d0b702016-11-21 14:16:53 -07002528 }
2529 }
2530
Jin Qiana85b9912017-10-17 15:48:18 -07002531 void runIdleMaint(Runnable callback) {
2532 enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);
2533
2534 try {
Sandeep Patil7d5c4912019-04-15 09:27:30 -07002535 // Block based checkpoint process runs fstrim. So, if checkpoint is in progress
2536 // (first boot after OTA), We skip idle maintenance and make sure the last
2537 // fstrim time is still updated. If file based checkpoints are used, we run
2538 // idle maintenance (GC + fstrim) regardless of checkpoint status.
2539 if (!needsCheckpoint() || !supportsBlockCheckpoint()) {
2540 mVold.runIdleMaint(new IVoldTaskListener.Stub() {
2541 @Override
2542 public void onStatus(int status, PersistableBundle extras) {
2543 // Not currently used
Jin Qiana85b9912017-10-17 15:48:18 -07002544 }
Sandeep Patil7d5c4912019-04-15 09:27:30 -07002545 @Override
2546 public void onFinished(int status, PersistableBundle extras) {
2547 if (callback != null) {
2548 BackgroundThread.getHandler().post(callback);
2549 }
2550 }
2551 });
2552 } else {
2553 Slog.i(TAG, "Skipping idle maintenance - block based checkpoint in progress");
2554 }
Jin Qiana85b9912017-10-17 15:48:18 -07002555 } catch (Exception e) {
2556 Slog.wtf(TAG, e);
2557 }
2558 }
2559
2560 @Override
2561 public void runIdleMaintenance() {
2562 runIdleMaint(null);
2563 }
2564
2565 void abortIdleMaint(Runnable callback) {
2566 enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);
2567
2568 try {
2569 mVold.abortIdleMaint(new IVoldTaskListener.Stub() {
2570 @Override
2571 public void onStatus(int status, PersistableBundle extras) {
2572 // Not currently used
2573 }
2574 @Override
2575 public void onFinished(int status, PersistableBundle extras) {
2576 if (callback != null) {
2577 BackgroundThread.getHandler().post(callback);
2578 }
2579 }
2580 });
2581 } catch (Exception e) {
2582 Slog.wtf(TAG, e);
2583 }
2584 }
2585
2586 @Override
2587 public void abortIdleMaintenance() {
2588 abortIdleMaint(null);
2589 }
2590
Svet Ganov6ee871e2015-07-10 14:29:33 -07002591 private void remountUidExternalStorage(int uid, int mode) {
Zim4f1a24d2019-11-27 16:35:58 +00002592 if (uid == Process.SYSTEM_UID) {
2593 // No need to remount uid for system because it has all access anyways
2594 return;
2595 }
2596
Jeff Sharkey9527b222015-06-24 15:24:48 -07002597 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002598 mVold.remountUid(uid, mode);
Jeff Sharkeyace874b2017-09-07 15:27:33 -06002599 } catch (Exception e) {
2600 Slog.wtf(TAG, e);
Jeff Sharkey9527b222015-06-24 15:24:48 -07002601 }
2602 }
2603
2604 @Override
Jeff Sharkey4c099d02015-05-15 13:45:00 -07002605 public void setDebugFlags(int flags, int mask) {
2606 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
Jeff Sharkey4c099d02015-05-15 13:45:00 -07002607
Jeff Sharkeyba512352015-11-12 20:17:45 -08002608 if ((mask & StorageManager.DEBUG_EMULATE_FBE) != 0) {
Jeff Sharkey00455bf2016-11-04 14:45:24 -06002609 if (!EMULATE_FBE_SUPPORTED) {
2610 throw new IllegalStateException(
2611 "Emulation not supported on this device");
2612 }
Paul Lawrence20be5d62016-02-26 13:51:17 -08002613 if (StorageManager.isFileEncryptedNativeOnly()) {
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07002614 throw new IllegalStateException(
Jeff Sharkey00455bf2016-11-04 14:45:24 -06002615 "Emulation not supported on device with native FBE");
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07002616 }
Jeff Sharkey5a785162016-03-21 13:02:06 -06002617 if (mLockPatternUtils.isCredentialRequiredToDecrypt(false)) {
2618 throw new IllegalStateException(
2619 "Emulation requires disabling 'Secure start-up' in Settings > Security");
2620 }
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07002621
Jeff Sharkey1176e512016-02-29 17:01:26 -07002622 final long token = Binder.clearCallingIdentity();
2623 try {
2624 final boolean emulateFbe = (flags & StorageManager.DEBUG_EMULATE_FBE) != 0;
2625 SystemProperties.set(StorageManager.PROP_EMULATE_FBE, Boolean.toString(emulateFbe));
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07002626
Jeff Sharkey1176e512016-02-29 17:01:26 -07002627 // Perform hard reboot to kick policy into place
2628 mContext.getSystemService(PowerManager.class).reboot(null);
2629 } finally {
2630 Binder.restoreCallingIdentity(token);
2631 }
Jeff Sharkeyba512352015-11-12 20:17:45 -08002632 }
Jeff Sharkey4c099d02015-05-15 13:45:00 -07002633
Jeff Sharkey901c0422018-04-20 13:11:20 -06002634 if ((mask & (StorageManager.DEBUG_ADOPTABLE_FORCE_ON
2635 | StorageManager.DEBUG_ADOPTABLE_FORCE_OFF)) != 0) {
2636 final String value;
2637 if ((flags & StorageManager.DEBUG_ADOPTABLE_FORCE_ON) != 0) {
2638 value = "force_on";
2639 } else if ((flags & StorageManager.DEBUG_ADOPTABLE_FORCE_OFF) != 0) {
2640 value = "force_off";
2641 } else {
2642 value = "";
2643 }
Jeff Sharkeyba512352015-11-12 20:17:45 -08002644
Jeff Sharkey901c0422018-04-20 13:11:20 -06002645 final long token = Binder.clearCallingIdentity();
2646 try {
2647 SystemProperties.set(StorageManager.PROP_ADOPTABLE, value);
2648
2649 // Reset storage to kick new setting into place
Jeff Sharkeyba512352015-11-12 20:17:45 -08002650 mHandler.obtainMessage(H_RESET).sendToTarget();
Jeff Sharkey901c0422018-04-20 13:11:20 -06002651 } finally {
2652 Binder.restoreCallingIdentity(token);
Jeff Sharkeyba512352015-11-12 20:17:45 -08002653 }
Jeff Sharkey4c099d02015-05-15 13:45:00 -07002654 }
Jeff Sharkey33dd1562016-04-07 11:05:33 -06002655
2656 if ((mask & (StorageManager.DEBUG_SDCARDFS_FORCE_ON
2657 | StorageManager.DEBUG_SDCARDFS_FORCE_OFF)) != 0) {
2658 final String value;
2659 if ((flags & StorageManager.DEBUG_SDCARDFS_FORCE_ON) != 0) {
2660 value = "force_on";
2661 } else if ((flags & StorageManager.DEBUG_SDCARDFS_FORCE_OFF) != 0) {
2662 value = "force_off";
2663 } else {
2664 value = "";
2665 }
2666
2667 final long token = Binder.clearCallingIdentity();
2668 try {
2669 SystemProperties.set(StorageManager.PROP_SDCARDFS, value);
2670
2671 // Reset storage to kick new setting into place
2672 mHandler.obtainMessage(H_RESET).sendToTarget();
2673 } finally {
2674 Binder.restoreCallingIdentity(token);
2675 }
2676 }
Jeff Sharkeye53e2d92017-03-25 23:14:06 -06002677
2678 if ((mask & StorageManager.DEBUG_VIRTUAL_DISK) != 0) {
2679 final boolean enabled = (flags & StorageManager.DEBUG_VIRTUAL_DISK) != 0;
2680
2681 final long token = Binder.clearCallingIdentity();
2682 try {
2683 SystemProperties.set(StorageManager.PROP_VIRTUAL_DISK, Boolean.toString(enabled));
2684
2685 // Reset storage to kick new setting into place
2686 mHandler.obtainMessage(H_RESET).sendToTarget();
2687 } finally {
2688 Binder.restoreCallingIdentity(token);
2689 }
2690 }
Sudheer Shankabe0febe2018-11-07 18:24:37 -08002691
Jeff Sharkeyb0c363b22018-12-15 11:53:03 -07002692 if ((mask & (StorageManager.DEBUG_ISOLATED_STORAGE_FORCE_ON
2693 | StorageManager.DEBUG_ISOLATED_STORAGE_FORCE_OFF)) != 0) {
2694 final int value;
2695 if ((flags & StorageManager.DEBUG_ISOLATED_STORAGE_FORCE_ON) != 0) {
2696 value = 1;
2697 } else if ((flags & StorageManager.DEBUG_ISOLATED_STORAGE_FORCE_OFF) != 0) {
2698 value = -1;
2699 } else {
2700 value = 0;
2701 }
Sudheer Shankabe0febe2018-11-07 18:24:37 -08002702
2703 final long token = Binder.clearCallingIdentity();
2704 try {
Jeff Sharkeyb0c363b22018-12-15 11:53:03 -07002705 Settings.Global.putInt(mContext.getContentResolver(),
2706 Settings.Global.ISOLATED_STORAGE_LOCAL, value);
2707 refreshIsolatedStorageSettings();
Sudheer Shankabe0febe2018-11-07 18:24:37 -08002708
2709 // Perform hard reboot to kick policy into place
Jeff Sharkey36274992019-02-27 12:09:57 -07002710 mHandler.post(() -> {
2711 mContext.getSystemService(PowerManager.class).reboot(null);
2712 });
2713 } finally {
2714 Binder.restoreCallingIdentity(token);
2715 }
2716 }
Jeff Sharkey4c099d02015-05-15 13:45:00 -07002717 }
2718
2719 @Override
Jeff Sharkey275e3e42015-04-24 16:10:32 -07002720 public String getPrimaryStorageUuid() {
Jeff Sharkey620b32b2015-04-23 19:36:02 -07002721 synchronized (mLock) {
2722 return mPrimaryStorageUuid;
2723 }
2724 }
2725
2726 @Override
Jeff Sharkey275e3e42015-04-24 16:10:32 -07002727 public void setPrimaryStorageUuid(String volumeUuid, IPackageMoveObserver callback) {
2728 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
Jeff Sharkey620b32b2015-04-23 19:36:02 -07002729
Jeff Sharkeya31460c2016-06-22 09:04:33 -06002730 final VolumeInfo from;
2731 final VolumeInfo to;
2732
Jeff Sharkey275e3e42015-04-24 16:10:32 -07002733 synchronized (mLock) {
Jeff Sharkeyfced5342015-05-10 14:53:34 -07002734 if (Objects.equals(mPrimaryStorageUuid, volumeUuid)) {
2735 throw new IllegalArgumentException("Primary storage already at " + volumeUuid);
Jeff Sharkey275e3e42015-04-24 16:10:32 -07002736 }
2737
2738 if (mMoveCallback != null) {
2739 throw new IllegalStateException("Move already in progress");
2740 }
2741 mMoveCallback = callback;
2742 mMoveTargetUuid = volumeUuid;
2743
Jeff Sharkeya65e6492017-06-21 13:45:11 -06002744 // We need all the users unlocked to move their primary storage
2745 final List<UserInfo> users = mContext.getSystemService(UserManager.class).getUsers();
2746 for (UserInfo user : users) {
2747 if (StorageManager.isFileEncryptedNativeOrEmulated()
2748 && !isUserKeyUnlocked(user.id)) {
2749 Slog.w(TAG, "Failing move due to locked user " + user.id);
2750 onMoveStatusLocked(PackageManager.MOVE_FAILED_LOCKED_USER);
2751 return;
2752 }
2753 }
2754
Jeff Sharkeyfced5342015-05-10 14:53:34 -07002755 // When moving to/from primary physical volume, we probably just nuked
2756 // the current storage location, so we have nothing to move.
2757 if (Objects.equals(StorageManager.UUID_PRIMARY_PHYSICAL, mPrimaryStorageUuid)
2758 || Objects.equals(StorageManager.UUID_PRIMARY_PHYSICAL, volumeUuid)) {
2759 Slog.d(TAG, "Skipping move to/from primary physical");
2760 onMoveStatusLocked(MOVE_STATUS_COPY_FINISHED);
2761 onMoveStatusLocked(PackageManager.MOVE_SUCCEEDED);
Jeff Sharkey5a9bb742015-11-03 10:15:57 -08002762 mHandler.obtainMessage(H_RESET).sendToTarget();
Jeff Sharkeya31460c2016-06-22 09:04:33 -06002763 return;
Jeff Sharkeyfced5342015-05-10 14:53:34 -07002764
2765 } else {
Jeff Sharkeya31460c2016-06-22 09:04:33 -06002766 from = findStorageForUuid(mPrimaryStorageUuid);
2767 to = findStorageForUuid(volumeUuid);
Jeff Sharkeyef10ee02015-07-05 14:17:27 -07002768
2769 if (from == null) {
2770 Slog.w(TAG, "Failing move due to missing from volume " + mPrimaryStorageUuid);
2771 onMoveStatusLocked(PackageManager.MOVE_FAILED_INTERNAL_ERROR);
2772 return;
2773 } else if (to == null) {
2774 Slog.w(TAG, "Failing move due to missing to volume " + volumeUuid);
2775 onMoveStatusLocked(PackageManager.MOVE_FAILED_INTERNAL_ERROR);
2776 return;
2777 }
Jeff Sharkey275e3e42015-04-24 16:10:32 -07002778 }
Jeff Sharkey620b32b2015-04-23 19:36:02 -07002779 }
Jeff Sharkeya31460c2016-06-22 09:04:33 -06002780
2781 try {
Jeff Sharkeyb302c542017-09-15 12:57:59 -06002782 mVold.moveStorage(from.id, to.id, new IVoldTaskListener.Stub() {
2783 @Override
2784 public void onStatus(int status, PersistableBundle extras) {
2785 synchronized (mLock) {
2786 onMoveStatusLocked(status);
2787 }
2788 }
2789
2790 @Override
2791 public void onFinished(int status, PersistableBundle extras) {
2792 // Not currently used
2793 }
2794 });
Jeff Sharkeyace874b2017-09-07 15:27:33 -06002795 } catch (Exception e) {
2796 Slog.wtf(TAG, e);
Jeff Sharkeya31460c2016-06-22 09:04:33 -06002797 }
Jeff Sharkey620b32b2015-04-23 19:36:02 -07002798 }
2799
San Mehatb1043402010-02-05 08:26:50 -08002800 private void warnOnNotMounted() {
Jeff Sharkey48877892015-03-18 11:27:19 -07002801 synchronized (mLock) {
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07002802 for (int i = 0; i < mVolumes.size(); i++) {
2803 final VolumeInfo vol = mVolumes.valueAt(i);
Jeff Sharkey27de30d2015-04-18 16:20:27 -07002804 if (vol.isPrimary() && vol.isMountedWritable()) {
Jeff Sharkey48877892015-03-18 11:27:19 -07002805 // Cool beans, we have a mounted primary volume
2806 return;
2807 }
Jeff Sharkey32ee8312012-09-30 13:21:31 -07002808 }
San Mehatb1043402010-02-05 08:26:50 -08002809 }
Jeff Sharkey48877892015-03-18 11:27:19 -07002810
2811 Slog.w(TAG, "No primary storage mounted!");
San Mehatb1043402010-02-05 08:26:50 -08002812 }
2813
Kenny Roota02b8b02010-08-05 16:14:17 -07002814 private boolean isUidOwnerOfPackageOrSystem(String packageName, int callerUid) {
2815 if (callerUid == android.os.Process.SYSTEM_UID) {
2816 return true;
2817 }
2818
Kenny Root02c87302010-07-01 08:10:18 -07002819 if (packageName == null) {
2820 return false;
2821 }
2822
Jeff Sharkey5790af02018-08-13 17:42:54 -06002823 final int packageUid = mPmInternal.getPackageUid(packageName,
Jeff Sharkeycd654482016-01-08 17:42:11 -07002824 PackageManager.MATCH_DEBUG_TRIAGED_MISSING, UserHandle.getUserId(callerUid));
Kenny Root02c87302010-07-01 08:10:18 -07002825
2826 if (DEBUG_OBB) {
2827 Slog.d(TAG, "packageName = " + packageName + ", packageUid = " +
2828 packageUid + ", callerUid = " + callerUid);
2829 }
2830
2831 return callerUid == packageUid;
2832 }
2833
Jeff Sharkey54402792017-09-15 16:05:19 -06002834 @Override
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002835 public String getMountedObbPath(String rawPath) {
Daulet Zhanguzinea1a7ca2020-01-03 09:46:50 +00002836 Objects.requireNonNull(rawPath, "rawPath cannot be null");
Kenny Rootaf9d6672010-10-08 09:21:39 -07002837
Kenny Root02c87302010-07-01 08:10:18 -07002838 warnOnNotMounted();
2839
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002840 final ObbState state;
Rubin Xucd7a0142015-04-17 23:45:27 +01002841 synchronized (mObbMounts) {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002842 state = mObbPathToStateMap.get(rawPath);
2843 }
2844 if (state == null) {
2845 Slog.w(TAG, "Failed to find OBB mounted at " + rawPath);
2846 return null;
2847 }
2848
Jeff Sharkey54402792017-09-15 16:05:19 -06002849 return findVolumeByIdOrThrow(state.volId).getPath().getAbsolutePath();
Kenny Root02c87302010-07-01 08:10:18 -07002850 }
2851
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002852 @Override
2853 public boolean isObbMounted(String rawPath) {
Daulet Zhanguzinea1a7ca2020-01-03 09:46:50 +00002854 Objects.requireNonNull(rawPath, "rawPath cannot be null");
Kenny Rootaf9d6672010-10-08 09:21:39 -07002855 synchronized (mObbMounts) {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002856 return mObbPathToStateMap.containsKey(rawPath);
Kenny Rootaf9d6672010-10-08 09:21:39 -07002857 }
Kenny Root02c87302010-07-01 08:10:18 -07002858 }
2859
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002860 @Override
Sudheer Shanka25469aa2018-08-27 15:50:23 -07002861 public void mountObb(String rawPath, String canonicalPath, String key,
2862 IObbActionListener token, int nonce, ObbInfo obbInfo) {
Daulet Zhanguzinea1a7ca2020-01-03 09:46:50 +00002863 Objects.requireNonNull(rawPath, "rawPath cannot be null");
2864 Objects.requireNonNull(canonicalPath, "canonicalPath cannot be null");
2865 Objects.requireNonNull(token, "token cannot be null");
2866 Objects.requireNonNull(obbInfo, "obbIfno cannot be null");
Kenny Rootaf9d6672010-10-08 09:21:39 -07002867
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002868 final int callingUid = Binder.getCallingUid();
Jeff Sharkey41cd6812017-09-11 10:32:17 -06002869 final ObbState obbState = new ObbState(rawPath, canonicalPath,
2870 callingUid, token, nonce, null);
Sudheer Shanka25469aa2018-08-27 15:50:23 -07002871 final ObbAction action = new MountObbAction(obbState, key, callingUid, obbInfo);
Kenny Roota02b8b02010-08-05 16:14:17 -07002872 mObbActionHandler.sendMessage(mObbActionHandler.obtainMessage(OBB_RUN_ACTION, action));
2873
2874 if (DEBUG_OBB)
2875 Slog.i(TAG, "Send to OBB handler: " + action.toString());
Kenny Root02c87302010-07-01 08:10:18 -07002876 }
2877
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002878 @Override
2879 public void unmountObb(String rawPath, boolean force, IObbActionListener token, int nonce) {
Daulet Zhanguzinea1a7ca2020-01-03 09:46:50 +00002880 Objects.requireNonNull(rawPath, "rawPath cannot be null");
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002881
2882 final ObbState existingState;
Rubin Xucd7a0142015-04-17 23:45:27 +01002883 synchronized (mObbMounts) {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002884 existingState = mObbPathToStateMap.get(rawPath);
Kenny Rootf1121dc2010-09-29 07:30:53 -07002885 }
2886
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002887 if (existingState != null) {
2888 // TODO: separate state object from request data
2889 final int callingUid = Binder.getCallingUid();
Jeff Sharkey41cd6812017-09-11 10:32:17 -06002890 final ObbState newState = new ObbState(rawPath, existingState.canonicalPath,
2891 callingUid, token, nonce, existingState.volId);
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002892 final ObbAction action = new UnmountObbAction(newState, force);
2893 mObbActionHandler.sendMessage(mObbActionHandler.obtainMessage(OBB_RUN_ACTION, action));
Kenny Root02c87302010-07-01 08:10:18 -07002894
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002895 if (DEBUG_OBB)
2896 Slog.i(TAG, "Send to OBB handler: " + action.toString());
2897 } else {
2898 Slog.w(TAG, "Unknown OBB mount at " + rawPath);
2899 }
Kenny Roota02b8b02010-08-05 16:14:17 -07002900 }
2901
Ben Komalo444eca22011-09-01 15:17:44 -07002902 @Override
2903 public int getEncryptionState() {
2904 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
2905 "no permission to access the crypt keeper");
2906
Ben Komalo444eca22011-09-01 15:17:44 -07002907 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002908 return mVold.fdeComplete();
2909 } catch (Exception e) {
2910 Slog.wtf(TAG, e);
Sudheer Shankaf7341142016-10-18 17:15:18 -07002911 return StorageManager.ENCRYPTION_STATE_ERROR_UNKNOWN;
Ben Komalo444eca22011-09-01 15:17:44 -07002912 }
2913 }
2914
2915 @Override
Jason parks5af0b912010-11-29 09:05:25 -06002916 public int decryptStorage(String password) {
Jason parks8888c592011-01-20 22:46:41 -06002917 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
2918 "no permission to access the crypt keeper");
Jason parks5af0b912010-11-29 09:05:25 -06002919
Jeff Sharkey8058fe62017-09-13 11:50:33 -06002920 if (TextUtils.isEmpty(password)) {
2921 throw new IllegalArgumentException("password cannot be empty");
2922 }
2923
Jason parks5af0b912010-11-29 09:05:25 -06002924 if (DEBUG_EVENTS) {
2925 Slog.i(TAG, "decrypting storage...");
2926 }
2927
2928 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002929 mVold.fdeCheckPassword(password);
2930 mHandler.postDelayed(() -> {
2931 try {
2932 mVold.fdeRestart();
2933 } catch (Exception e) {
2934 Slog.wtf(TAG, e);
2935 }
2936 }, DateUtils.SECOND_IN_MILLIS);
2937 return 0;
Paul Crowleyfc0b5192018-07-02 13:58:10 -07002938 } catch (ServiceSpecificException e) {
2939 Slog.e(TAG, "fdeCheckPassword failed", e);
2940 return e.errorCode;
Jeff Sharkey54402792017-09-15 16:05:19 -06002941 } catch (Exception e) {
2942 Slog.wtf(TAG, e);
2943 return StorageManager.ENCRYPTION_STATE_ERROR_UNKNOWN;
Jason parks5af0b912010-11-29 09:05:25 -06002944 }
Jason parks5af0b912010-11-29 09:05:25 -06002945 }
2946
Jeff Sharkey54402792017-09-15 16:05:19 -06002947 @Override
Paul Lawrence46791e72014-04-03 09:10:26 -07002948 public int encryptStorage(int type, String password) {
Jason parks8888c592011-01-20 22:46:41 -06002949 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
2950 "no permission to access the crypt keeper");
Jason parks56aa5322011-01-07 09:01:15 -06002951
Jeff Sharkey8058fe62017-09-13 11:50:33 -06002952 if (type == StorageManager.CRYPT_TYPE_DEFAULT) {
2953 password = "";
2954 } else if (TextUtils.isEmpty(password)) {
2955 throw new IllegalArgumentException("password cannot be empty");
2956 }
2957
Jason parks56aa5322011-01-07 09:01:15 -06002958 if (DEBUG_EVENTS) {
Jason parks8888c592011-01-20 22:46:41 -06002959 Slog.i(TAG, "encrypting storage...");
Jason parks56aa5322011-01-07 09:01:15 -06002960 }
2961
2962 try {
Paul Lawrence89a0ae42017-12-22 10:11:10 -08002963 mVold.fdeEnable(type, password, 0);
Jeff Sharkey43e12112017-09-12 16:31:45 -06002964 } catch (Exception e) {
2965 Slog.wtf(TAG, e);
2966 return -1;
Jason parks56aa5322011-01-07 09:01:15 -06002967 }
2968
2969 return 0;
2970 }
2971
Paul Lawrence8e397362014-01-27 15:22:30 -08002972 /** Set the password for encrypting the master key.
2973 * @param type One of the CRYPTO_TYPE_XXX consts defined in StorageManager.
2974 * @param password The password to set.
2975 */
Jeff Sharkey54402792017-09-15 16:05:19 -06002976 @Override
Paul Lawrence8e397362014-01-27 15:22:30 -08002977 public int changeEncryptionPassword(int type, String password) {
Jason parksf7b3cd42011-01-27 09:28:25 -06002978 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
2979 "no permission to access the crypt keeper");
2980
Jeff Sharkeyae266462017-11-27 13:32:24 -07002981 if (StorageManager.isFileEncryptedNativeOnly()) {
2982 // Not supported on FBE devices
2983 return -1;
2984 }
2985
Jeff Sharkey8058fe62017-09-13 11:50:33 -06002986 if (type == StorageManager.CRYPT_TYPE_DEFAULT) {
2987 password = "";
2988 } else if (TextUtils.isEmpty(password)) {
2989 throw new IllegalArgumentException("password cannot be empty");
2990 }
2991
Jason parksf7b3cd42011-01-27 09:28:25 -06002992 if (DEBUG_EVENTS) {
2993 Slog.i(TAG, "changing encryption password...");
2994 }
2995
2996 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002997 mVold.fdeChangePassword(type, password);
2998 return 0;
2999 } catch (Exception e) {
3000 Slog.wtf(TAG, e);
3001 return -1;
Jason parksf7b3cd42011-01-27 09:28:25 -06003002 }
3003 }
3004
Christopher Tate32418be2011-10-10 13:51:12 -07003005 /**
3006 * Validate a user-supplied password string with cryptfs
3007 */
3008 @Override
3009 public int verifyEncryptionPassword(String password) throws RemoteException {
3010 // Only the system process is permitted to validate passwords
3011 if (Binder.getCallingUid() != android.os.Process.SYSTEM_UID) {
3012 throw new SecurityException("no permission to access the crypt keeper");
3013 }
3014
3015 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
3016 "no permission to access the crypt keeper");
3017
3018 if (TextUtils.isEmpty(password)) {
3019 throw new IllegalArgumentException("password cannot be empty");
3020 }
3021
Christopher Tate32418be2011-10-10 13:51:12 -07003022 if (DEBUG_EVENTS) {
3023 Slog.i(TAG, "validating encryption password...");
3024 }
3025
3026 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06003027 mVold.fdeVerifyPassword(password);
3028 return 0;
3029 } catch (Exception e) {
3030 Slog.wtf(TAG, e);
3031 return -1;
Christopher Tate32418be2011-10-10 13:51:12 -07003032 }
3033 }
3034
Paul Lawrence8e397362014-01-27 15:22:30 -08003035 /**
3036 * Get the type of encryption used to encrypt the master key.
3037 * @return The type, one of the CRYPT_TYPE_XXX consts from StorageManager.
3038 */
3039 @Override
Svetoslav16e4a1a2014-09-29 18:16:20 -07003040 public int getPasswordType() {
Paul Lawrence76a40572017-03-15 11:08:04 -07003041 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
Paul Lawrence9de713d2016-05-02 22:45:33 +00003042 "no permission to access the crypt keeper");
3043
Paul Lawrence8e397362014-01-27 15:22:30 -08003044 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06003045 return mVold.fdeGetPasswordType();
3046 } catch (Exception e) {
3047 Slog.wtf(TAG, e);
3048 return -1;
Paul Lawrence8e397362014-01-27 15:22:30 -08003049 }
3050 }
3051
Paul Lawrencee51dcf92014-03-18 10:56:00 -07003052 /**
3053 * Set a field in the crypto header.
3054 * @param field field to set
3055 * @param contents contents to set in field
3056 */
3057 @Override
3058 public void setField(String field, String contents) throws RemoteException {
Paul Lawrence76a40572017-03-15 11:08:04 -07003059 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
Paul Lawrence0bbd1082016-04-26 15:21:02 -07003060 "no permission to access the crypt keeper");
Paul Lawrencee51dcf92014-03-18 10:56:00 -07003061
yusukes14a8b1f2018-07-23 17:34:42 -07003062 if (!StorageManager.isBlockEncrypted()) {
3063 // Only supported on FDE devices
Jeff Sharkeyae266462017-11-27 13:32:24 -07003064 return;
3065 }
3066
Paul Lawrencee51dcf92014-03-18 10:56:00 -07003067 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06003068 mVold.fdeSetField(field, contents);
3069 return;
3070 } catch (Exception e) {
3071 Slog.wtf(TAG, e);
3072 return;
Paul Lawrencee51dcf92014-03-18 10:56:00 -07003073 }
3074 }
3075
3076 /**
3077 * Gets a field from the crypto header.
3078 * @param field field to get
3079 * @return contents of field
3080 */
3081 @Override
3082 public String getField(String field) throws RemoteException {
Paul Lawrence76a40572017-03-15 11:08:04 -07003083 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
Paul Lawrence0bbd1082016-04-26 15:21:02 -07003084 "no permission to access the crypt keeper");
Paul Lawrencee51dcf92014-03-18 10:56:00 -07003085
yusukes14a8b1f2018-07-23 17:34:42 -07003086 if (!StorageManager.isBlockEncrypted()) {
3087 // Only supported on FDE devices
Jeff Sharkeyae266462017-11-27 13:32:24 -07003088 return null;
3089 }
3090
Paul Lawrencee51dcf92014-03-18 10:56:00 -07003091 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06003092 return mVold.fdeGetField(field);
3093 } catch (Exception e) {
3094 Slog.wtf(TAG, e);
3095 return null;
Paul Lawrencee51dcf92014-03-18 10:56:00 -07003096 }
3097 }
3098
Paul Lawrence3806d9c2015-10-29 10:30:46 -07003099 /**
3100 * Is userdata convertible to file based encryption?
3101 * @return non zero for convertible
3102 */
3103 @Override
3104 public boolean isConvertibleToFBE() throws RemoteException {
Paul Lawrence76a40572017-03-15 11:08:04 -07003105 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
Paul Lawrence0bbd1082016-04-26 15:21:02 -07003106 "no permission to access the crypt keeper");
Paul Lawrence3806d9c2015-10-29 10:30:46 -07003107
Paul Lawrence3806d9c2015-10-29 10:30:46 -07003108 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06003109 return mVold.isConvertibleToFbe();
3110 } catch (Exception e) {
3111 Slog.wtf(TAG, e);
3112 return false;
Paul Lawrence3806d9c2015-10-29 10:30:46 -07003113 }
3114 }
3115
Daniel Rosenberge129e5c2018-11-07 19:25:55 -08003116 /**
Martijn Coenenf04aca42019-03-11 10:35:34 +01003117 * Check whether the device supports filesystem checkpointing.
3118 *
3119 * @return true if the device supports filesystem checkpointing, false otherwise.
3120 */
3121 @Override
3122 public boolean supportsCheckpoint() throws RemoteException {
Martijn Coenenf04aca42019-03-11 10:35:34 +01003123 return mVold.supportsCheckpoint();
3124 }
3125
3126 /**
3127 * Signal that checkpointing partitions should start a checkpoint on the next boot.
3128 *
3129 * @param numTries Number of times to try booting in checkpoint mode, before we will boot
3130 * non-checkpoint mode and commit all changes immediately. Callers are
3131 * responsible for ensuring that boot is safe (eg, by rolling back updates).
3132 */
3133 @Override
3134 public void startCheckpoint(int numTries) throws RemoteException {
Nikita Ioffe6d749422020-01-14 22:19:01 +00003135 // Only the root, system_server and shell processes are permitted to start checkpoints
3136 final int callingUid = Binder.getCallingUid();
3137 if (callingUid != Process.SYSTEM_UID && callingUid != Process.ROOT_UID
3138 && callingUid != Process.SHELL_UID) {
Martijn Coenenf04aca42019-03-11 10:35:34 +01003139 throw new SecurityException("no permission to start filesystem checkpoint");
3140 }
3141
3142 mVold.startCheckpoint(numTries);
3143 }
3144
3145 /**
Daniel Rosenberge129e5c2018-11-07 19:25:55 -08003146 * Signal that checkpointing partitions should commit changes
3147 */
3148 @Override
3149 public void commitChanges() throws RemoteException {
3150 // Only the system process is permitted to commit checkpoints
3151 if (Binder.getCallingUid() != android.os.Process.SYSTEM_UID) {
3152 throw new SecurityException("no permission to commit checkpoint changes");
3153 }
3154
3155 mVold.commitChanges();
3156 }
3157
Daniel Rosenberge3a924d2019-03-19 18:19:08 -07003158 /**
3159 * Check if we should be mounting with checkpointing or are checkpointing now
3160 */
3161 @Override
3162 public boolean needsCheckpoint() throws RemoteException {
Paul Lawrence15a54462019-04-30 11:14:25 -07003163 enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);
Daniel Rosenberge3a924d2019-03-19 18:19:08 -07003164 return mVold.needsCheckpoint();
3165 }
3166
Daniel Rosenberg600799b2019-03-20 17:42:50 -07003167 /**
3168 * Abort the current set of changes and either try again, or abort entirely
3169 */
3170 @Override
3171 public void abortChanges(String message, boolean retry) throws RemoteException {
3172 // Only the system process is permitted to abort checkpoints
3173 if (Binder.getCallingUid() != android.os.Process.SYSTEM_UID) {
3174 throw new SecurityException("no permission to commit checkpoint changes");
3175 }
3176
3177 mVold.abortChanges(message, retry);
3178 }
3179
Jeff Sharkeyb049e212012-09-07 23:16:01 -07003180 @Override
Paul Lawrence945490c2014-03-27 16:37:28 +00003181 public String getPassword() throws RemoteException {
Paul Lawrence76a40572017-03-15 11:08:04 -07003182 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
Rubin Xucd7a0142015-04-17 23:45:27 +01003183 "only keyguard can retrieve password");
Paul Lawrence0bbd1082016-04-26 15:21:02 -07003184
Paul Lawrence945490c2014-03-27 16:37:28 +00003185 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06003186 return mVold.fdeGetPassword();
3187 } catch (Exception e) {
3188 Slog.wtf(TAG, e);
Paul Lawrence24063b52015-01-06 13:11:23 -08003189 return null;
Paul Lawrence945490c2014-03-27 16:37:28 +00003190 }
3191 }
3192
3193 @Override
3194 public void clearPassword() throws RemoteException {
Paul Lawrence76a40572017-03-15 11:08:04 -07003195 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
Paul Lawrence0bbd1082016-04-26 15:21:02 -07003196 "only keyguard can clear password");
3197
Paul Lawrence945490c2014-03-27 16:37:28 +00003198 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06003199 mVold.fdeClearPassword();
3200 return;
3201 } catch (Exception e) {
3202 Slog.wtf(TAG, e);
3203 return;
Paul Lawrence945490c2014-03-27 16:37:28 +00003204 }
3205 }
3206
3207 @Override
Lenka Trochtovac4dd0212015-11-18 12:22:06 +01003208 public void createUserKey(int userId, int serialNumber, boolean ephemeral) {
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08003209 enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
Paul Crowleybcf48ed2015-04-22 13:36:59 +01003210
Paul Crowleybcf48ed2015-04-22 13:36:59 +01003211 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06003212 mVold.createUserKey(userId, serialNumber, ephemeral);
Jeff Sharkey43e12112017-09-12 16:31:45 -06003213 } catch (Exception e) {
3214 Slog.wtf(TAG, e);
Paul Crowleybcf48ed2015-04-22 13:36:59 +01003215 }
3216 }
3217
Paul Crowley7ec733f2015-05-19 12:42:00 +01003218 @Override
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08003219 public void destroyUserKey(int userId) {
3220 enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
Paul Crowley7ec733f2015-05-19 12:42:00 +01003221
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08003222 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06003223 mVold.destroyUserKey(userId);
Jeff Sharkey43e12112017-09-12 16:31:45 -06003224 } catch (Exception e) {
3225 Slog.wtf(TAG, e);
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08003226 }
3227 }
3228
Jeff Sharkey43e12112017-09-12 16:31:45 -06003229 private String encodeBytes(byte[] bytes) {
Paul Crowleyfaeb3eb2016-02-08 15:58:29 +00003230 if (ArrayUtils.isEmpty(bytes)) {
Jeff Sharkey43e12112017-09-12 16:31:45 -06003231 return "!";
Paul Crowleyfaeb3eb2016-02-08 15:58:29 +00003232 } else {
Jeff Sharkey43e12112017-09-12 16:31:45 -06003233 return HexDump.toHexString(bytes);
Paul Crowleyfaeb3eb2016-02-08 15:58:29 +00003234 }
3235 }
3236
Paul Crowleycc701552016-05-17 14:18:49 -07003237 /*
3238 * Add this token/secret pair to the set of ways we can recover a disk encryption key.
3239 * Changing the token/secret for a disk encryption key is done in two phases: first, adding
3240 * a new token/secret pair with this call, then delting all other pairs with
3241 * fixateNewestUserKeyAuth. This allows other places where a credential is used, such as
3242 * Gatekeeper, to be updated between the two calls.
3243 */
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08003244 @Override
Paul Crowleycc701552016-05-17 14:18:49 -07003245 public void addUserKeyAuth(int userId, int serialNumber, byte[] token, byte[] secret) {
Paul Crowleyfaeb3eb2016-02-08 15:58:29 +00003246 enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
Paul Crowleyfaeb3eb2016-02-08 15:58:29 +00003247
3248 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06003249 mVold.addUserKeyAuth(userId, serialNumber, encodeBytes(token), encodeBytes(secret));
Jeff Sharkey43e12112017-09-12 16:31:45 -06003250 } catch (Exception e) {
3251 Slog.wtf(TAG, e);
Paul Crowleycc701552016-05-17 14:18:49 -07003252 }
3253 }
3254
3255 /*
Barani Muthukumaran9ba99ed2019-12-18 00:36:06 -08003256 * Clear disk encryption key bound to the associated token / secret pair. Removing the user
3257 * binding of the Disk encryption key is done in two phases: first, this call will retrieve
3258 * the disk encryption key using the provided token / secret pair and store it by
3259 * encrypting it with a keymaster key not bound to the user, then fixateNewestUserKeyAuth
3260 * is called to delete all other bindings of the disk encryption key.
3261 */
3262 @Override
3263 public void clearUserKeyAuth(int userId, int serialNumber, byte[] token, byte[] secret) {
3264 enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
3265
3266 try {
3267 mVold.clearUserKeyAuth(userId, serialNumber, encodeBytes(token), encodeBytes(secret));
3268 } catch (Exception e) {
3269 Slog.wtf(TAG, e);
3270 }
3271 }
3272
3273 /*
Paul Crowleycc701552016-05-17 14:18:49 -07003274 * Delete all disk encryption token/secret pairs except the most recently added one
3275 */
3276 @Override
3277 public void fixateNewestUserKeyAuth(int userId) {
3278 enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
Paul Crowleycc701552016-05-17 14:18:49 -07003279
3280 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06003281 mVold.fixateNewestUserKeyAuth(userId);
Jeff Sharkey43e12112017-09-12 16:31:45 -06003282 } catch (Exception e) {
3283 Slog.wtf(TAG, e);
Paul Crowleyfaeb3eb2016-02-08 15:58:29 +00003284 }
3285 }
3286
3287 @Override
3288 public void unlockUserKey(int userId, int serialNumber, byte[] token, byte[] secret) {
felipeal4efe9a82020-04-13 10:36:37 -07003289 boolean isFsEncrypted = StorageManager.isFileEncryptedNativeOrEmulated();
3290 Slog.d(TAG, "unlockUserKey: " + userId
3291 + " isFileEncryptedNativeOrEmulated: " + isFsEncrypted
3292 + " hasToken: " + (token != null)
3293 + " hasSecret: " + (secret != null));
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08003294 enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08003295
felipeal4efe9a82020-04-13 10:36:37 -07003296 if (isFsEncrypted) {
Jeff Sharkeyce18c812016-04-27 16:00:41 -06003297 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06003298 mVold.unlockUserKey(userId, serialNumber, encodeBytes(token),
3299 encodeBytes(secret));
Jeff Sharkey43e12112017-09-12 16:31:45 -06003300 } catch (Exception e) {
3301 Slog.wtf(TAG, e);
3302 return;
Jeff Sharkeyce18c812016-04-27 16:00:41 -06003303 }
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08003304 }
3305
3306 synchronized (mLock) {
Lee Shombertebe2a0b2020-01-23 10:02:15 -08003307 mLocalUnlockedUsers.append(userId);
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08003308 }
3309 }
3310
3311 @Override
3312 public void lockUserKey(int userId) {
3313 enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08003314
3315 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06003316 mVold.lockUserKey(userId);
Jeff Sharkey43e12112017-09-12 16:31:45 -06003317 } catch (Exception e) {
3318 Slog.wtf(TAG, e);
3319 return;
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08003320 }
3321
3322 synchronized (mLock) {
Lee Shombertebe2a0b2020-01-23 10:02:15 -08003323 mLocalUnlockedUsers.remove(userId);
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08003324 }
3325 }
3326
3327 @Override
3328 public boolean isUserKeyUnlocked(int userId) {
Jeff Sharkeyce18c812016-04-27 16:00:41 -06003329 synchronized (mLock) {
Lee Shombertebe2a0b2020-01-23 10:02:15 -08003330 return mLocalUnlockedUsers.contains(userId);
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08003331 }
3332 }
3333
Narayan Kamath157dd1d2019-06-12 13:06:30 +01003334 private boolean isSystemUnlocked(int userId) {
3335 synchronized (mLock) {
3336 return ArrayUtils.contains(mSystemUnlockedUsers, userId);
3337 }
3338 }
3339
Martijn Coenencecf90c2020-05-04 15:16:48 +02003340 private void prepareUserStorageIfNeeded(VolumeInfo vol) {
3341 if (vol.type != VolumeInfo.TYPE_PRIVATE) {
3342 return;
3343 }
3344
3345 final UserManager um = mContext.getSystemService(UserManager.class);
3346 final UserManagerInternal umInternal =
3347 LocalServices.getService(UserManagerInternal.class);
3348
3349 for (UserInfo user : um.getUsers(false /* includeDying */)) {
3350 final int flags;
3351 if (umInternal.isUserUnlockingOrUnlocked(user.id)) {
3352 flags = StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE;
3353 } else if (umInternal.isUserRunning(user.id)) {
3354 flags = StorageManager.FLAG_STORAGE_DE;
3355 } else {
3356 continue;
3357 }
3358
3359 prepareUserStorageInternal(vol.fsUuid, user.id, user.serialNumber, flags);
3360 }
3361 }
3362
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08003363 @Override
Jeff Sharkey47f71082016-02-01 17:03:54 -07003364 public void prepareUserStorage(String volumeUuid, int userId, int serialNumber, int flags) {
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08003365 enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08003366
Martijn Coenencecf90c2020-05-04 15:16:48 +02003367 prepareUserStorageInternal(volumeUuid, userId, serialNumber, flags);
3368 }
3369
3370 private void prepareUserStorageInternal(String volumeUuid, int userId, int serialNumber,
3371 int flags) {
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08003372 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06003373 mVold.prepareUserStorage(volumeUuid, userId, serialNumber, flags);
Ricky Wai88b369a2020-02-07 16:26:29 +00003374 // After preparing user storage, we should check if we should mount data mirror again,
3375 // and we do it for user 0 only as we only need to do once for all users.
3376 if (volumeUuid != null) {
3377 final StorageManager storage = mContext.getSystemService(StorageManager.class);
3378 VolumeInfo info = storage.findVolumeByUuid(volumeUuid);
3379 if (info != null && userId == 0 && info.type == VolumeInfo.TYPE_PRIVATE) {
3380 mInstaller.tryMountDataMirror(volumeUuid);
3381 }
3382 }
Jeff Sharkey43e12112017-09-12 16:31:45 -06003383 } catch (Exception e) {
3384 Slog.wtf(TAG, e);
Paul Crowley7ec733f2015-05-19 12:42:00 +01003385 }
3386 }
3387
Paul Crowleybcf48ed2015-04-22 13:36:59 +01003388 @Override
Jeff Sharkeyfcf1e552016-04-14 20:44:58 -06003389 public void destroyUserStorage(String volumeUuid, int userId, int flags) {
3390 enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
Jeff Sharkeyfcf1e552016-04-14 20:44:58 -06003391
3392 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06003393 mVold.destroyUserStorage(volumeUuid, userId, flags);
Jeff Sharkey43e12112017-09-12 16:31:45 -06003394 } catch (Exception e) {
3395 Slog.wtf(TAG, e);
Jeff Sharkeyfcf1e552016-04-14 20:44:58 -06003396 }
3397 }
3398
Martijn Coenen0f522bf2020-03-23 15:47:33 +01003399 @Override
3400 public void fixupAppDir(String path) {
3401 final Matcher matcher = KNOWN_APP_DIR_PATHS.matcher(path);
3402 if (matcher.matches()) {
Martijn Coenen7b977f32020-06-04 15:38:53 +02003403 if (matcher.group(2) == null) {
3404 Log.e(TAG, "Asked to fixup an app dir without a userId: " + path);
3405 return;
3406 }
3407 try {
3408 int userId = Integer.parseInt(matcher.group(2));
3409 String packageName = matcher.group(3);
3410 int uid = mContext.getPackageManager().getPackageUidAsUser(packageName, userId);
Martijn Coenen0f522bf2020-03-23 15:47:33 +01003411 try {
Martijn Coenen7b977f32020-06-04 15:38:53 +02003412 mVold.fixupAppDir(path + "/", uid);
Martijn Coenen0f522bf2020-03-23 15:47:33 +01003413 } catch (RemoteException | ServiceSpecificException e) {
Martijn Coenen7b977f32020-06-04 15:38:53 +02003414 Log.e(TAG, "Failed to fixup app dir for " + packageName, e);
Martijn Coenen0f522bf2020-03-23 15:47:33 +01003415 }
Martijn Coenen7b977f32020-06-04 15:38:53 +02003416 } catch (NumberFormatException e) {
3417 Log.e(TAG, "Invalid userId in path: " + path, e);
3418 } catch (PackageManager.NameNotFoundException e) {
3419 Log.e(TAG, "Couldn't find package to fixup app dir " + path, e);
Martijn Coenen0f522bf2020-03-23 15:47:33 +01003420 }
3421 } else {
3422 Log.e(TAG, "Path " + path + " is not a valid application-specific directory");
3423 }
3424 }
3425
Anton Hanssonbe9c9902019-05-28 13:45:26 +01003426 /** Not thread safe */
Daichi Hironoe56740d2017-02-02 13:56:45 +09003427 class AppFuseMountScope extends AppFuseBridge.MountScope {
Anton Hanssonbe9c9902019-05-28 13:45:26 +01003428 private boolean mMounted = false;
Daichi Hirono812c95d2017-02-08 16:20:20 +09003429
Ryo Hashimoto38bcbf02018-05-16 18:20:37 +09003430 public AppFuseMountScope(int uid, int mountId) {
3431 super(uid, mountId);
Daichi Hirono812c95d2017-02-08 16:20:20 +09003432 }
3433
3434 @Override
3435 public ParcelFileDescriptor open() throws NativeDaemonConnectorException {
Jeff Sharkey54402792017-09-15 16:05:19 -06003436 try {
Anton Hanssonbe9c9902019-05-28 13:45:26 +01003437 final FileDescriptor fd = mVold.mountAppFuse(uid, mountId);
3438 mMounted = true;
3439 return new ParcelFileDescriptor(fd);
Jeff Sharkey54402792017-09-15 16:05:19 -06003440 } catch (Exception e) {
3441 throw new NativeDaemonConnectorException("Failed to mount", e);
Daichi Hirono812c95d2017-02-08 16:20:20 +09003442 }
Daichi Hirono9fb00182016-11-08 14:12:17 +09003443 }
3444
3445 @Override
Ryo Hashimoto38bcbf02018-05-16 18:20:37 +09003446 public ParcelFileDescriptor openFile(int mountId, int fileId, int flags)
3447 throws NativeDaemonConnectorException {
3448 try {
3449 return new ParcelFileDescriptor(
3450 mVold.openAppFuseFile(uid, mountId, fileId, flags));
3451 } catch (Exception e) {
3452 throw new NativeDaemonConnectorException("Failed to open", e);
3453 }
3454 }
3455
3456 @Override
Daichi Hironoe56740d2017-02-02 13:56:45 +09003457 public void close() throws Exception {
Anton Hanssonbe9c9902019-05-28 13:45:26 +01003458 if (mMounted) {
Ryo Hashimoto38bcbf02018-05-16 18:20:37 +09003459 mVold.unmountAppFuse(uid, mountId);
Anton Hanssonbe9c9902019-05-28 13:45:26 +01003460 mMounted = false;
Daichi Hirono812c95d2017-02-08 16:20:20 +09003461 }
Daichi Hirono9fb00182016-11-08 14:12:17 +09003462 }
3463 }
3464
3465 @Override
Daichi Hirono812c95d2017-02-08 16:20:20 +09003466 public @Nullable AppFuseMount mountProxyFileDescriptorBridge() {
Daichi Hironoe56740d2017-02-02 13:56:45 +09003467 Slog.v(TAG, "mountProxyFileDescriptorBridge");
Daichi Hirono9fb00182016-11-08 14:12:17 +09003468 final int uid = Binder.getCallingUid();
Daichi Hirono9fb00182016-11-08 14:12:17 +09003469
Daichi Hironoe56740d2017-02-02 13:56:45 +09003470 while (true) {
3471 synchronized (mAppFuseLock) {
3472 boolean newlyCreated = false;
3473 if (mAppFuseBridge == null) {
3474 mAppFuseBridge = new AppFuseBridge();
3475 new Thread(mAppFuseBridge, AppFuseBridge.TAG).start();
3476 newlyCreated = true;
Daichi Hirono9fb00182016-11-08 14:12:17 +09003477 }
Daichi Hironoe56740d2017-02-02 13:56:45 +09003478 try {
3479 final int name = mNextAppFuseName++;
3480 try {
3481 return new AppFuseMount(
Ryo Hashimoto38bcbf02018-05-16 18:20:37 +09003482 name, mAppFuseBridge.addBridge(new AppFuseMountScope(uid, name)));
Daichi Hirono812c95d2017-02-08 16:20:20 +09003483 } catch (FuseUnavailableMountException e) {
Daichi Hironoe56740d2017-02-02 13:56:45 +09003484 if (newlyCreated) {
3485 // If newly created bridge fails, it's a real error.
Daichi Hirono812c95d2017-02-08 16:20:20 +09003486 Slog.e(TAG, "", e);
3487 return null;
Daichi Hironoe56740d2017-02-02 13:56:45 +09003488 }
3489 // It seems the thread of mAppFuseBridge has already been terminated.
3490 mAppFuseBridge = null;
3491 }
3492 } catch (NativeDaemonConnectorException e) {
3493 throw e.rethrowAsParcelableException();
3494 }
Daichi Hirono9fb00182016-11-08 14:12:17 +09003495 }
Daichi Hirono9fb00182016-11-08 14:12:17 +09003496 }
3497 }
3498
3499 @Override
Daichi Hirono812c95d2017-02-08 16:20:20 +09003500 public @Nullable ParcelFileDescriptor openProxyFileDescriptor(
3501 int mountId, int fileId, int mode) {
3502 Slog.v(TAG, "mountProxyFileDescriptor");
Jeff Sharkey39466322018-12-05 19:19:52 -07003503
3504 // We only support a narrow set of incoming mode flags
Jeff Sharkey3b1c2542018-12-13 15:01:38 -07003505 mode &= MODE_READ_WRITE;
Jeff Sharkey39466322018-12-05 19:19:52 -07003506
Daichi Hirono9fb00182016-11-08 14:12:17 +09003507 try {
3508 synchronized (mAppFuseLock) {
Daichi Hironoe56740d2017-02-02 13:56:45 +09003509 if (mAppFuseBridge == null) {
Daichi Hirono812c95d2017-02-08 16:20:20 +09003510 Slog.e(TAG, "FuseBridge has not been created");
3511 return null;
Daichi Hirono9fb00182016-11-08 14:12:17 +09003512 }
Ryo Hashimoto38bcbf02018-05-16 18:20:37 +09003513 return mAppFuseBridge.openFile(mountId, fileId, mode);
Daichi Hirono9fb00182016-11-08 14:12:17 +09003514 }
Daichi Hirono812c95d2017-02-08 16:20:20 +09003515 } catch (FuseUnavailableMountException | InterruptedException error) {
3516 Slog.v(TAG, "The mount point has already been invalid", error);
3517 return null;
Daichi Hirono9fb00182016-11-08 14:12:17 +09003518 }
3519 }
3520
Daichi Hirono9e8d9e22015-11-13 14:37:00 +09003521 @Override
Jeff Sharkeyae266462017-11-27 13:32:24 -07003522 public void mkdirs(String callingPkg, String appPath) {
Sudheer Shankaa63bfb32019-02-28 11:15:58 -08003523 final int callingUid = Binder.getCallingUid();
3524 final int userId = UserHandle.getUserId(callingUid);
Farid Zare Seisanac094512018-04-02 15:06:13 -07003525 final String propertyName = "sys.user." + userId + ".ce_available";
Jeff Sharkey2d8b4e82013-09-17 17:30:33 -07003526
Jeff Sharkey196c7552018-03-26 15:56:50 -06003527 // Ignore requests to create directories while storage is locked
Farid Zare Seisanac094512018-04-02 15:06:13 -07003528 if (!isUserKeyUnlocked(userId)) {
3529 throw new IllegalStateException("Failed to prepare " + appPath);
3530 }
3531
3532 // Ignore requests to create directories if CE storage is not available
Farid Zare Seisan7f6b8122018-03-30 11:19:10 -07003533 if ((userId == UserHandle.USER_SYSTEM)
3534 && !SystemProperties.getBoolean(propertyName, false)) {
Farid Zare Seisanac094512018-04-02 15:06:13 -07003535 throw new IllegalStateException("Failed to prepare " + appPath);
3536 }
Jeff Sharkey196c7552018-03-26 15:56:50 -06003537
Jeff Sharkey2d8b4e82013-09-17 17:30:33 -07003538 // Validate that reported package name belongs to caller
3539 final AppOpsManager appOps = (AppOpsManager) mContext.getSystemService(
3540 Context.APP_OPS_SERVICE);
Sudheer Shankaa63bfb32019-02-28 11:15:58 -08003541 appOps.checkPackage(callingUid, callingPkg);
Jeff Sharkey2d8b4e82013-09-17 17:30:33 -07003542
Jeff Sharkey48877892015-03-18 11:27:19 -07003543 File appFile = null;
Jeff Sharkey2d8b4e82013-09-17 17:30:33 -07003544 try {
Jeff Sharkey48877892015-03-18 11:27:19 -07003545 appFile = new File(appPath).getCanonicalFile();
Jeff Sharkey2d8b4e82013-09-17 17:30:33 -07003546 } catch (IOException e) {
Jeff Sharkeyae266462017-11-27 13:32:24 -07003547 throw new IllegalStateException("Failed to resolve " + appPath + ": " + e);
Jeff Sharkey2d8b4e82013-09-17 17:30:33 -07003548 }
3549
Martijn Coenen9fd2b642019-12-24 13:04:36 +01003550 appPath = appFile.getAbsolutePath();
3551 if (!appPath.endsWith("/")) {
3552 appPath = appPath + "/";
3553 }
3554 // Ensure that the path we're asked to create is a known application directory
3555 // path.
3556 final Matcher matcher = KNOWN_APP_DIR_PATHS.matcher(appPath);
3557 if (matcher.matches()) {
3558 // And that the package dir matches the calling package
3559 if (!matcher.group(3).equals(callingPkg)) {
3560 throw new SecurityException("Invalid mkdirs path: " + appFile
3561 + " does not contain calling package " + callingPkg);
Jeff Sharkey48877892015-03-18 11:27:19 -07003562 }
Martijn Coenen9fd2b642019-12-24 13:04:36 +01003563 // And that the user id part of the path (if any) matches the calling user id,
3564 // or if for a public volume (no user id), the user matches the current user
3565 if ((matcher.group(2) != null && !matcher.group(2).equals(Integer.toString(userId)))
3566 || (matcher.group(2) == null && userId != mCurrentUserId)) {
3567 throw new SecurityException("Invalid mkdirs path: " + appFile
3568 + " does not match calling user id " + userId);
3569 }
Jeff Sharkey2d8b4e82013-09-17 17:30:33 -07003570 try {
Martijn Coenen714eda22020-02-12 15:29:53 +01003571 mVold.setupAppDir(appPath, callingUid);
Martijn Coenen9fd2b642019-12-24 13:04:36 +01003572 } catch (RemoteException e) {
Sudheer Shanka64501e52019-04-29 10:46:26 -07003573 throw new IllegalStateException("Failed to prepare " + appPath + ": " + e);
Jeff Sharkey2d8b4e82013-09-17 17:30:33 -07003574 }
Jeff Sharkey2d8b4e82013-09-17 17:30:33 -07003575
Martijn Coenen9fd2b642019-12-24 13:04:36 +01003576 return;
3577 }
3578 throw new SecurityException("Invalid mkdirs path: " + appFile
3579 + " is not a known app path.");
Jeff Sharkey2d8b4e82013-09-17 17:30:33 -07003580 }
3581
3582 @Override
Jeff Sharkey46349872015-07-28 10:49:47 -07003583 public StorageVolume[] getVolumeList(int uid, String packageName, int flags) {
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07003584 final int userId = UserHandle.getUserId(uid);
Jeff Sharkeyc02bfae2016-03-27 15:06:53 -06003585
Jeff Sharkey46349872015-07-28 10:49:47 -07003586 final boolean forWrite = (flags & StorageManager.FLAG_FOR_WRITE) != 0;
Jeff Sharkeyc02bfae2016-03-27 15:06:53 -06003587 final boolean realState = (flags & StorageManager.FLAG_REAL_STATE) != 0;
3588 final boolean includeInvisible = (flags & StorageManager.FLAG_INCLUDE_INVISIBLE) != 0;
Jeff Sharkey04b4ba12019-12-15 22:42:42 -07003589 final boolean includeRecent = (flags & StorageManager.FLAG_INCLUDE_RECENT) != 0;
Jeff Sharkey46349872015-07-28 10:49:47 -07003590
Narayan Kamath157dd1d2019-06-12 13:06:30 +01003591 // Report all volumes as unmounted until we've recorded that user 0 has unlocked. There
3592 // are no guarantees that callers will see a consistent view of the volume before that
3593 // point
3594 final boolean systemUserUnlocked = isSystemUnlocked(UserHandle.USER_SYSTEM);
3595
Jeff Sharkeye915a7e2020-06-17 14:47:35 -06003596 // When the caller is the app actually hosting external storage, we
3597 // should never attempt to augment the actual storage volume state,
3598 // otherwise we risk confusing it with race conditions as users go
3599 // through various unlocked states
3600 final boolean callerIsMediaStore = UserHandle.isSameApp(Binder.getCallingUid(),
3601 mMediaStoreAuthorityAppId);
3602
Jeff Sharkey04b4ba12019-12-15 22:42:42 -07003603 final boolean userIsDemo;
Jeff Sharkeyc02bfae2016-03-27 15:06:53 -06003604 final boolean userKeyUnlocked;
3605 final boolean storagePermission;
3606 final long token = Binder.clearCallingIdentity();
Svetoslav38c3dbb2015-07-14 11:27:06 -07003607 try {
Jeff Sharkey04b4ba12019-12-15 22:42:42 -07003608 userIsDemo = LocalServices.getService(UserManagerInternal.class)
3609 .getUserInfo(userId).isDemo();
Jeff Sharkeyc02bfae2016-03-27 15:06:53 -06003610 userKeyUnlocked = isUserKeyUnlocked(userId);
Sudheer Shanka2250d562016-11-07 15:41:02 -08003611 storagePermission = mStorageManagerInternal.hasExternalStorage(uid, packageName);
Svetoslav38c3dbb2015-07-14 11:27:06 -07003612 } finally {
Jeff Sharkeyc02bfae2016-03-27 15:06:53 -06003613 Binder.restoreCallingIdentity(token);
Svetoslav38c3dbb2015-07-14 11:27:06 -07003614 }
Svet Ganov6ee871e2015-07-10 14:29:33 -07003615
Jeff Sharkeyc02bfae2016-03-27 15:06:53 -06003616 boolean foundPrimary = false;
3617
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07003618 final ArrayList<StorageVolume> res = new ArrayList<>();
Jeff Sharkey04b4ba12019-12-15 22:42:42 -07003619 final ArraySet<String> resUuids = new ArraySet<>();
Jeff Sharkey48877892015-03-18 11:27:19 -07003620 synchronized (mLock) {
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07003621 for (int i = 0; i < mVolumes.size(); i++) {
Jeff Sharkeye915a7e2020-06-17 14:47:35 -06003622 final String volId = mVolumes.keyAt(i);
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07003623 final VolumeInfo vol = mVolumes.valueAt(i);
Jeff Sharkeyc02bfae2016-03-27 15:06:53 -06003624 switch (vol.getType()) {
3625 case VolumeInfo.TYPE_PUBLIC:
Risan05c41e62018-10-29 08:57:43 +09003626 case VolumeInfo.TYPE_STUB:
Jeff Sharkeyc02bfae2016-03-27 15:06:53 -06003627 break;
Zim17be6f92019-09-25 14:37:55 +01003628 case VolumeInfo.TYPE_EMULATED:
3629 if (vol.getMountUserId() == userId) {
3630 break;
3631 }
3632 // Skip if emulated volume not for userId
Jeff Sharkeyc02bfae2016-03-27 15:06:53 -06003633 default:
3634 continue;
3635 }
3636
3637 boolean match = false;
3638 if (forWrite) {
3639 match = vol.isVisibleForWrite(userId);
3640 } else {
Felipe Leme123a0e72016-06-10 11:09:11 -07003641 match = vol.isVisibleForRead(userId)
3642 || (includeInvisible && vol.getPath() != null);
Jeff Sharkeyc02bfae2016-03-27 15:06:53 -06003643 }
3644 if (!match) continue;
3645
3646 boolean reportUnmounted = false;
Jeff Sharkeye915a7e2020-06-17 14:47:35 -06003647 if (callerIsMediaStore) {
3648 // When the caller is the app actually hosting external storage, we
3649 // should never attempt to augment the actual storage volume state,
3650 // otherwise we risk confusing it with race conditions as users go
3651 // through various unlocked states
3652 } else if (!systemUserUnlocked) {
Narayan Kamath157dd1d2019-06-12 13:06:30 +01003653 reportUnmounted = true;
Jeff Sharkeye915a7e2020-06-17 14:47:35 -06003654 Slog.w(TAG, "Reporting " + volId + " unmounted due to system locked");
Narayan Kamath157dd1d2019-06-12 13:06:30 +01003655 } else if ((vol.getType() == VolumeInfo.TYPE_EMULATED) && !userKeyUnlocked) {
Jeff Sharkeyc02bfae2016-03-27 15:06:53 -06003656 reportUnmounted = true;
Jeff Sharkeye915a7e2020-06-17 14:47:35 -06003657 Slog.w(TAG, "Reporting " + volId + "unmounted due to " + userId + " locked");
Jeff Sharkeyc02bfae2016-03-27 15:06:53 -06003658 } else if (!storagePermission && !realState) {
Jeff Sharkeye915a7e2020-06-17 14:47:35 -06003659 Slog.w(TAG, "Reporting " + volId + "unmounted due to missing permissions");
Jeff Sharkeyc02bfae2016-03-27 15:06:53 -06003660 reportUnmounted = true;
3661 }
3662
3663 final StorageVolume userVol = vol.buildStorageVolume(mContext, userId,
3664 reportUnmounted);
3665 if (vol.isPrimary()) {
3666 res.add(0, userVol);
3667 foundPrimary = true;
3668 } else {
3669 res.add(userVol);
Jeff Sharkeyb049e212012-09-07 23:16:01 -07003670 }
Jeff Sharkey04b4ba12019-12-15 22:42:42 -07003671 resUuids.add(userVol.getUuid());
Mike Lockwood8fa5f802011-03-24 08:12:30 -07003672 }
Jeff Sharkey04b4ba12019-12-15 22:42:42 -07003673
3674 if (includeRecent) {
3675 final long lastWeek = System.currentTimeMillis() - DateUtils.WEEK_IN_MILLIS;
3676 for (int i = 0; i < mRecords.size(); i++) {
3677 final VolumeRecord rec = mRecords.valueAt(i);
3678
3679 // Skip if we've already included it above
3680 if (resUuids.contains(rec.fsUuid)) continue;
3681
3682 // Treat as recent if mounted within the last week
3683 if (rec.lastSeenMillis > 0 && rec.lastSeenMillis < lastWeek) {
3684 final StorageVolume userVol = rec.buildStorageVolume(mContext);
3685 res.add(userVol);
3686 resUuids.add(userVol.getUuid());
3687 }
3688 }
3689 }
3690 }
3691
3692 // Synthesize a volume for preloaded media under demo users, so that
3693 // it's scanned into MediaStore
3694 if (userIsDemo) {
3695 final String id = "demo";
3696 final File path = Environment.getDataPreloadsMediaDirectory();
3697 final boolean primary = false;
3698 final boolean removable = false;
3699 final boolean emulated = true;
3700 final boolean allowMassStorage = false;
3701 final long maxFileSize = 0;
3702 final UserHandle user = new UserHandle(userId);
3703 final String envState = Environment.MEDIA_MOUNTED_READ_ONLY;
3704 final String description = mContext.getString(android.R.string.unknownName);
3705
3706 res.add(new StorageVolume(id, path, path, description, primary, removable,
3707 emulated, allowMassStorage, maxFileSize, user, id, envState));
Mike Lockwood8fa5f802011-03-24 08:12:30 -07003708 }
Jeff Sharkey48877892015-03-18 11:27:19 -07003709
3710 if (!foundPrimary) {
Jeff Sharkey11697f52018-12-13 10:14:42 -07003711 Slog.w(TAG, "No primary storage defined yet; hacking together a stub");
Jeff Sharkey48877892015-03-18 11:27:19 -07003712
3713 final boolean primaryPhysical = SystemProperties.getBoolean(
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07003714 StorageManager.PROP_PRIMARY_PHYSICAL, false);
Jeff Sharkey48877892015-03-18 11:27:19 -07003715
3716 final String id = "stub_primary";
3717 final File path = Environment.getLegacyExternalStorageDirectory();
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07003718 final String description = mContext.getString(android.R.string.unknownName);
Jeff Sharkey48877892015-03-18 11:27:19 -07003719 final boolean primary = true;
3720 final boolean removable = primaryPhysical;
3721 final boolean emulated = !primaryPhysical;
Jeff Sharkey48877892015-03-18 11:27:19 -07003722 final boolean allowMassStorage = false;
3723 final long maxFileSize = 0L;
3724 final UserHandle owner = new UserHandle(userId);
3725 final String uuid = null;
Jeff Sharkey48877892015-03-18 11:27:19 -07003726 final String state = Environment.MEDIA_REMOVED;
3727
Jerry Zhang71938e12018-05-10 18:28:29 -07003728 res.add(0, new StorageVolume(id, path, path,
Jerry Zhangf9c5c252017-08-16 18:07:51 -07003729 description, primary, removable, emulated,
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07003730 allowMassStorage, maxFileSize, owner, uuid, state));
Jeff Sharkey48877892015-03-18 11:27:19 -07003731 }
3732
3733 return res.toArray(new StorageVolume[res.size()]);
Mike Lockwood8fa5f802011-03-24 08:12:30 -07003734 }
3735
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07003736 @Override
3737 public DiskInfo[] getDisks() {
3738 synchronized (mLock) {
3739 final DiskInfo[] res = new DiskInfo[mDisks.size()];
3740 for (int i = 0; i < mDisks.size(); i++) {
3741 res[i] = mDisks.valueAt(i);
3742 }
3743 return res;
3744 }
3745 }
3746
3747 @Override
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07003748 public VolumeInfo[] getVolumes(int flags) {
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07003749 synchronized (mLock) {
3750 final VolumeInfo[] res = new VolumeInfo[mVolumes.size()];
3751 for (int i = 0; i < mVolumes.size(); i++) {
3752 res[i] = mVolumes.valueAt(i);
3753 }
3754 return res;
3755 }
3756 }
3757
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07003758 @Override
3759 public VolumeRecord[] getVolumeRecords(int flags) {
3760 synchronized (mLock) {
3761 final VolumeRecord[] res = new VolumeRecord[mRecords.size()];
3762 for (int i = 0; i < mRecords.size(); i++) {
3763 res[i] = mRecords.valueAt(i);
3764 }
3765 return res;
3766 }
3767 }
3768
Jeff Sharkey9bed0702017-01-23 20:37:05 -07003769 @Override
3770 public long getCacheQuotaBytes(String volumeUuid, int uid) {
3771 if (uid != Binder.getCallingUid()) {
3772 mContext.enforceCallingPermission(android.Manifest.permission.STORAGE_INTERNAL, TAG);
3773 }
Daniel Nishi80fdb012017-03-09 14:30:07 -08003774 final long token = Binder.clearCallingIdentity();
3775 final StorageStatsManager stats = mContext.getSystemService(StorageStatsManager.class);
3776 try {
3777 return stats.getCacheQuotaBytes(volumeUuid, uid);
3778 } finally {
3779 Binder.restoreCallingIdentity(token);
3780 }
Jeff Sharkey9bed0702017-01-23 20:37:05 -07003781 }
3782
3783 @Override
3784 public long getCacheSizeBytes(String volumeUuid, int uid) {
3785 if (uid != Binder.getCallingUid()) {
3786 mContext.enforceCallingPermission(android.Manifest.permission.STORAGE_INTERNAL, TAG);
3787 }
3788 final long token = Binder.clearCallingIdentity();
3789 try {
3790 return mContext.getSystemService(StorageStatsManager.class)
3791 .queryStatsForUid(volumeUuid, uid).getCacheBytes();
Jeff Sharkey789a8fc2017-04-16 13:18:35 -06003792 } catch (IOException e) {
3793 throw new ParcelableException(e);
Jeff Sharkey9bed0702017-01-23 20:37:05 -07003794 } finally {
3795 Binder.restoreCallingIdentity(token);
3796 }
3797 }
3798
Jeff Sharkey35e46d22017-06-09 10:01:20 -06003799 private int adjustAllocateFlags(int flags, int callingUid, String callingPackage) {
3800 // Require permission to allocate aggressively
3801 if ((flags & StorageManager.FLAG_ALLOCATE_AGGRESSIVE) != 0) {
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07003802 mContext.enforceCallingOrSelfPermission(
3803 android.Manifest.permission.ALLOCATE_AGGRESSIVE, TAG);
3804 }
3805
Jeff Sharkey35e46d22017-06-09 10:01:20 -06003806 // Apps normally can't directly defy reserved space
3807 flags &= ~StorageManager.FLAG_ALLOCATE_DEFY_ALL_RESERVED;
3808 flags &= ~StorageManager.FLAG_ALLOCATE_DEFY_HALF_RESERVED;
3809
3810 // However, if app is actively using the camera, then we're willing to
3811 // clear up to half of the reserved cache space, since the user might be
3812 // trying to capture an important memory.
3813 final AppOpsManager appOps = mContext.getSystemService(AppOpsManager.class);
3814 final long token = Binder.clearCallingIdentity();
3815 try {
3816 if (appOps.isOperationActive(AppOpsManager.OP_CAMERA, callingUid, callingPackage)) {
3817 Slog.d(TAG, "UID " + callingUid + " is actively using camera;"
3818 + " letting them defy reserved cached data");
3819 flags |= StorageManager.FLAG_ALLOCATE_DEFY_HALF_RESERVED;
3820 }
3821 } finally {
3822 Binder.restoreCallingIdentity(token);
3823 }
3824
3825 return flags;
3826 }
3827
3828 @Override
3829 public long getAllocatableBytes(String volumeUuid, int flags, String callingPackage) {
3830 flags = adjustAllocateFlags(flags, Binder.getCallingUid(), callingPackage);
3831
3832 final StorageManager storage = mContext.getSystemService(StorageManager.class);
3833 final StorageStatsManager stats = mContext.getSystemService(StorageStatsManager.class);
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07003834 final long token = Binder.clearCallingIdentity();
3835 try {
3836 // In general, apps can allocate as much space as they want, except
3837 // we never let them eat into either the minimum cache space or into
Jeff Sharkeyddff8072017-05-26 13:10:46 -06003838 // the low disk warning space. To avoid user confusion, this logic
3839 // should be kept in sync with getFreeBytes().
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07003840 final File path = storage.findPathForUuid(volumeUuid);
Jeff Sharkeyddff8072017-05-26 13:10:46 -06003841
Noah Zimmtb2558072019-07-25 16:15:06 -07003842 long usable = 0;
3843 long lowReserved = 0;
3844 long fullReserved = 0;
3845 long cacheClearable = 0;
Jeff Sharkeyddff8072017-05-26 13:10:46 -06003846
Noah Zimmtb2558072019-07-25 16:15:06 -07003847 if ((flags & StorageManager.FLAG_ALLOCATE_CACHE_ONLY) == 0) {
3848 usable = path.getUsableSpace();
3849 lowReserved = storage.getStorageLowBytes(path);
3850 fullReserved = storage.getStorageFullBytes(path);
3851 }
3852
3853 if ((flags & StorageManager.FLAG_ALLOCATE_NON_CACHE_ONLY) == 0
3854 && stats.isQuotaSupported(volumeUuid)) {
Jeff Sharkeyddff8072017-05-26 13:10:46 -06003855 final long cacheTotal = stats.getCacheBytes(volumeUuid);
Jeff Sharkey35e46d22017-06-09 10:01:20 -06003856 final long cacheReserved = storage.getStorageCacheBytes(path, flags);
Noah Zimmtb2558072019-07-25 16:15:06 -07003857 cacheClearable = Math.max(0, cacheTotal - cacheReserved);
3858 }
Jeff Sharkeyddff8072017-05-26 13:10:46 -06003859
Noah Zimmtb2558072019-07-25 16:15:06 -07003860 if ((flags & StorageManager.FLAG_ALLOCATE_AGGRESSIVE) != 0) {
3861 return Math.max(0, (usable + cacheClearable) - fullReserved);
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07003862 } else {
Noah Zimmtb2558072019-07-25 16:15:06 -07003863 return Math.max(0, (usable + cacheClearable) - lowReserved);
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07003864 }
Jeff Sharkey789a8fc2017-04-16 13:18:35 -06003865 } catch (IOException e) {
3866 throw new ParcelableException(e);
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07003867 } finally {
3868 Binder.restoreCallingIdentity(token);
3869 }
Jeff Sharkey500ce9e2017-02-12 02:39:24 -07003870 }
3871
3872 @Override
Jeff Sharkey35e46d22017-06-09 10:01:20 -06003873 public void allocateBytes(String volumeUuid, long bytes, int flags, String callingPackage) {
3874 flags = adjustAllocateFlags(flags, Binder.getCallingUid(), callingPackage);
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07003875
Noah Zimmtb2558072019-07-25 16:15:06 -07003876 final long allocatableBytes = getAllocatableBytes(volumeUuid,
3877 flags | StorageManager.FLAG_ALLOCATE_NON_CACHE_ONLY, callingPackage);
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07003878 if (bytes > allocatableBytes) {
Noah Zimmtb2558072019-07-25 16:15:06 -07003879 // If we don't have room without taking cache into account, check to see if we'd have
3880 // room if we included freeable cache space.
3881 final long cacheClearable = getAllocatableBytes(volumeUuid,
3882 flags | StorageManager.FLAG_ALLOCATE_CACHE_ONLY, callingPackage);
3883 if (bytes > allocatableBytes + cacheClearable) {
3884 throw new ParcelableException(new IOException("Failed to allocate " + bytes
3885 + " because only " + (allocatableBytes + cacheClearable) + " allocatable"));
3886 }
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07003887 }
3888
Jeff Sharkey35e46d22017-06-09 10:01:20 -06003889 final StorageManager storage = mContext.getSystemService(StorageManager.class);
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07003890 final long token = Binder.clearCallingIdentity();
3891 try {
Jeff Sharkey789a8fc2017-04-16 13:18:35 -06003892 // Free up enough disk space to satisfy both the requested allocation
3893 // and our low disk warning space.
3894 final File path = storage.findPathForUuid(volumeUuid);
Jeff Sharkeyddff8072017-05-26 13:10:46 -06003895 if ((flags & StorageManager.FLAG_ALLOCATE_AGGRESSIVE) != 0) {
3896 bytes += storage.getStorageFullBytes(path);
3897 } else {
3898 bytes += storage.getStorageLowBytes(path);
3899 }
Jeff Sharkey789a8fc2017-04-16 13:18:35 -06003900
Jeff Sharkey5790af02018-08-13 17:42:54 -06003901 mPmInternal.freeStorage(volumeUuid, bytes, flags);
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07003902 } catch (IOException e) {
3903 throw new ParcelableException(e);
3904 } finally {
3905 Binder.restoreCallingIdentity(token);
Jeff Sharkey500ce9e2017-02-12 02:39:24 -07003906 }
3907 }
3908
Sudheer Shankaff971bc2018-12-13 17:39:59 -08003909 private IAppOpsCallback.Stub mAppOpsCallback = new IAppOpsCallback.Stub() {
3910 @Override
3911 public void opChanged(int op, int uid, String packageName) throws RemoteException {
3912 if (!ENABLE_ISOLATED_STORAGE) return;
3913
Zim64726cb2019-11-27 13:06:34 +00003914 int mountMode = getMountMode(uid, packageName);
3915 boolean isUidActive = LocalServices.getService(ActivityManagerInternal.class)
3916 .getUidProcessState(uid) != PROCESS_STATE_NONEXISTENT;
3917
3918 if (isUidActive) {
3919 remountUidExternalStorage(uid, mountMode);
3920 }
Sudheer Shankaff971bc2018-12-13 17:39:59 -08003921 }
3922 };
3923
Kenny Rootaf9d6672010-10-08 09:21:39 -07003924 private void addObbStateLocked(ObbState obbState) throws RemoteException {
3925 final IBinder binder = obbState.getBinder();
3926 List<ObbState> obbStates = mObbMounts.get(binder);
Kenny Root5919ac62010-10-05 09:49:40 -07003927
Kenny Rootaf9d6672010-10-08 09:21:39 -07003928 if (obbStates == null) {
3929 obbStates = new ArrayList<ObbState>();
3930 mObbMounts.put(binder, obbStates);
3931 } else {
3932 for (final ObbState o : obbStates) {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003933 if (o.rawPath.equals(obbState.rawPath)) {
Kenny Rootaf9d6672010-10-08 09:21:39 -07003934 throw new IllegalStateException("Attempt to add ObbState twice. "
Sudheer Shanka2250d562016-11-07 15:41:02 -08003935 + "This indicates an error in the StorageManagerService logic.");
Kenny Root5919ac62010-10-05 09:49:40 -07003936 }
3937 }
Kenny Roota02b8b02010-08-05 16:14:17 -07003938 }
Kenny Rootaf9d6672010-10-08 09:21:39 -07003939
3940 obbStates.add(obbState);
3941 try {
3942 obbState.link();
3943 } catch (RemoteException e) {
3944 /*
3945 * The binder died before we could link it, so clean up our state
3946 * and return failure.
3947 */
3948 obbStates.remove(obbState);
3949 if (obbStates.isEmpty()) {
3950 mObbMounts.remove(binder);
3951 }
3952
3953 // Rethrow the error so mountObb can get it
3954 throw e;
3955 }
3956
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003957 mObbPathToStateMap.put(obbState.rawPath, obbState);
Kenny Roota02b8b02010-08-05 16:14:17 -07003958 }
3959
Kenny Rootaf9d6672010-10-08 09:21:39 -07003960 private void removeObbStateLocked(ObbState obbState) {
3961 final IBinder binder = obbState.getBinder();
3962 final List<ObbState> obbStates = mObbMounts.get(binder);
3963 if (obbStates != null) {
3964 if (obbStates.remove(obbState)) {
3965 obbState.unlink();
Kenny Root05105f72010-09-22 17:29:43 -07003966 }
Kenny Rootaf9d6672010-10-08 09:21:39 -07003967 if (obbStates.isEmpty()) {
3968 mObbMounts.remove(binder);
3969 }
Kenny Roota02b8b02010-08-05 16:14:17 -07003970 }
Kenny Roota02b8b02010-08-05 16:14:17 -07003971
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003972 mObbPathToStateMap.remove(obbState.rawPath);
Kenny Root38cf8862010-09-26 14:18:51 -07003973 }
3974
Kenny Roota02b8b02010-08-05 16:14:17 -07003975 private class ObbActionHandler extends Handler {
Kenny Roota02b8b02010-08-05 16:14:17 -07003976
3977 ObbActionHandler(Looper l) {
3978 super(l);
3979 }
3980
3981 @Override
3982 public void handleMessage(Message msg) {
3983 switch (msg.what) {
3984 case OBB_RUN_ACTION: {
Kenny Root480afe72010-10-07 10:17:50 -07003985 final ObbAction action = (ObbAction) msg.obj;
Kenny Roota02b8b02010-08-05 16:14:17 -07003986
3987 if (DEBUG_OBB)
3988 Slog.i(TAG, "OBB_RUN_ACTION: " + action.toString());
3989
Sudheer Shanka25469aa2018-08-27 15:50:23 -07003990 action.execute(this);
Kenny Roota02b8b02010-08-05 16:14:17 -07003991 break;
3992 }
Kenny Rootaf9d6672010-10-08 09:21:39 -07003993 case OBB_FLUSH_MOUNT_STATE: {
3994 final String path = (String) msg.obj;
3995
3996 if (DEBUG_OBB)
3997 Slog.i(TAG, "Flushing all OBB state for path " + path);
3998
3999 synchronized (mObbMounts) {
4000 final List<ObbState> obbStatesToRemove = new LinkedList<ObbState>();
4001
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07004002 final Iterator<ObbState> i = mObbPathToStateMap.values().iterator();
Kenny Rootaf9d6672010-10-08 09:21:39 -07004003 while (i.hasNext()) {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07004004 final ObbState state = i.next();
Kenny Rootaf9d6672010-10-08 09:21:39 -07004005
4006 /*
4007 * If this entry's source file is in the volume path
4008 * that got unmounted, remove it because it's no
4009 * longer valid.
4010 */
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07004011 if (state.canonicalPath.startsWith(path)) {
4012 obbStatesToRemove.add(state);
Kenny Rootaf9d6672010-10-08 09:21:39 -07004013 }
4014 }
4015
4016 for (final ObbState obbState : obbStatesToRemove) {
4017 if (DEBUG_OBB)
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07004018 Slog.i(TAG, "Removing state for " + obbState.rawPath);
Kenny Rootaf9d6672010-10-08 09:21:39 -07004019
4020 removeObbStateLocked(obbState);
4021
4022 try {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07004023 obbState.token.onObbResult(obbState.rawPath, obbState.nonce,
Kenny Rootaf9d6672010-10-08 09:21:39 -07004024 OnObbStateChangeListener.UNMOUNTED);
4025 } catch (RemoteException e) {
4026 Slog.i(TAG, "Couldn't send unmount notification for OBB: "
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07004027 + obbState.rawPath);
Kenny Rootaf9d6672010-10-08 09:21:39 -07004028 }
4029 }
4030 }
4031 break;
4032 }
Kenny Roota02b8b02010-08-05 16:14:17 -07004033 }
4034 }
Kenny Roota02b8b02010-08-05 16:14:17 -07004035 }
4036
Jeff Sharkey0095a822018-02-15 13:06:53 -07004037 private static class ObbException extends Exception {
4038 public final int status;
4039
4040 public ObbException(int status, String message) {
4041 super(message);
4042 this.status = status;
4043 }
4044
4045 public ObbException(int status, Throwable cause) {
4046 super(cause.getMessage(), cause);
4047 this.status = status;
4048 }
4049 }
4050
Kenny Roota02b8b02010-08-05 16:14:17 -07004051 abstract class ObbAction {
Kenny Roota02b8b02010-08-05 16:14:17 -07004052
4053 ObbState mObbState;
4054
4055 ObbAction(ObbState obbState) {
4056 mObbState = obbState;
4057 }
4058
4059 public void execute(ObbActionHandler handler) {
4060 try {
4061 if (DEBUG_OBB)
Ben Komalo444eca22011-09-01 15:17:44 -07004062 Slog.i(TAG, "Starting to execute action: " + toString());
Sudheer Shanka25469aa2018-08-27 15:50:23 -07004063 handleExecute();
Jeff Sharkey0095a822018-02-15 13:06:53 -07004064 } catch (ObbException e) {
4065 notifyObbStateChange(e);
Kenny Roota02b8b02010-08-05 16:14:17 -07004066 }
4067 }
4068
Jeff Sharkey0095a822018-02-15 13:06:53 -07004069 abstract void handleExecute() throws ObbException;
Kenny Root38cf8862010-09-26 14:18:51 -07004070
Jeff Sharkey0095a822018-02-15 13:06:53 -07004071 protected void notifyObbStateChange(ObbException e) {
4072 Slog.w(TAG, e);
4073 notifyObbStateChange(e.status);
4074 }
4075
4076 protected void notifyObbStateChange(int status) {
Kenny Rootaf9d6672010-10-08 09:21:39 -07004077 if (mObbState == null || mObbState.token == null) {
4078 return;
4079 }
4080
Kenny Root38cf8862010-09-26 14:18:51 -07004081 try {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07004082 mObbState.token.onObbResult(mObbState.rawPath, mObbState.nonce, status);
Kenny Root38cf8862010-09-26 14:18:51 -07004083 } catch (RemoteException e) {
Sudheer Shanka2250d562016-11-07 15:41:02 -08004084 Slog.w(TAG, "StorageEventListener went away while calling onObbStateChanged");
Kenny Root38cf8862010-09-26 14:18:51 -07004085 }
4086 }
Kenny Roota02b8b02010-08-05 16:14:17 -07004087 }
4088
4089 class MountObbAction extends ObbAction {
Ben Komalo444eca22011-09-01 15:17:44 -07004090 private final String mKey;
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07004091 private final int mCallingUid;
Sudheer Shanka25469aa2018-08-27 15:50:23 -07004092 private ObbInfo mObbInfo;
Kenny Roota02b8b02010-08-05 16:14:17 -07004093
Sudheer Shanka25469aa2018-08-27 15:50:23 -07004094 MountObbAction(ObbState obbState, String key, int callingUid, ObbInfo obbInfo) {
Kenny Roota02b8b02010-08-05 16:14:17 -07004095 super(obbState);
4096 mKey = key;
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07004097 mCallingUid = callingUid;
Sudheer Shanka25469aa2018-08-27 15:50:23 -07004098 mObbInfo = obbInfo;
Kenny Roota02b8b02010-08-05 16:14:17 -07004099 }
4100
Jason parks5af0b912010-11-29 09:05:25 -06004101 @Override
Jeff Sharkey0095a822018-02-15 13:06:53 -07004102 public void handleExecute() throws ObbException {
Kenny Rootaf9d6672010-10-08 09:21:39 -07004103 warnOnNotMounted();
4104
Sudheer Shanka25469aa2018-08-27 15:50:23 -07004105 if (!isUidOwnerOfPackageOrSystem(mObbInfo.packageName, mCallingUid)) {
Jeff Sharkey0095a822018-02-15 13:06:53 -07004106 throw new ObbException(ERROR_PERMISSION_DENIED, "Denied attempt to mount OBB "
Sudheer Shanka25469aa2018-08-27 15:50:23 -07004107 + mObbInfo.filename + " which is owned by " + mObbInfo.packageName);
Kenny Roota02b8b02010-08-05 16:14:17 -07004108 }
4109
Kenny Rootaf9d6672010-10-08 09:21:39 -07004110 final boolean isMounted;
4111 synchronized (mObbMounts) {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07004112 isMounted = mObbPathToStateMap.containsKey(mObbState.rawPath);
Kenny Rootaf9d6672010-10-08 09:21:39 -07004113 }
4114 if (isMounted) {
Jeff Sharkey0095a822018-02-15 13:06:53 -07004115 throw new ObbException(ERROR_ALREADY_MOUNTED,
Sudheer Shanka25469aa2018-08-27 15:50:23 -07004116 "Attempt to mount OBB which is already mounted: " + mObbInfo.filename);
Kenny Rootaf9d6672010-10-08 09:21:39 -07004117 }
4118
Kenny Rootaf9d6672010-10-08 09:21:39 -07004119 final String hashedKey;
Jeff Sharkey41cd6812017-09-11 10:32:17 -06004120 final String binderKey;
Kenny Rootaf9d6672010-10-08 09:21:39 -07004121 if (mKey == null) {
4122 hashedKey = "none";
Jeff Sharkey41cd6812017-09-11 10:32:17 -06004123 binderKey = "";
Kenny Rootaf9d6672010-10-08 09:21:39 -07004124 } else {
Kenny Rootaf9d6672010-10-08 09:21:39 -07004125 try {
Kenny Root3b1abba2010-10-13 15:00:07 -07004126 SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
4127
Sudheer Shanka25469aa2018-08-27 15:50:23 -07004128 KeySpec ks = new PBEKeySpec(mKey.toCharArray(), mObbInfo.salt,
Kenny Root3b1abba2010-10-13 15:00:07 -07004129 PBKDF2_HASH_ROUNDS, CRYPTO_ALGORITHM_KEY_SIZE);
4130 SecretKey key = factory.generateSecret(ks);
4131 BigInteger bi = new BigInteger(key.getEncoded());
4132 hashedKey = bi.toString(16);
Jeff Sharkey41cd6812017-09-11 10:32:17 -06004133 binderKey = hashedKey;
Jeff Sharkey0095a822018-02-15 13:06:53 -07004134 } catch (GeneralSecurityException e) {
4135 throw new ObbException(ERROR_INTERNAL, e);
Kenny Root38cf8862010-09-26 14:18:51 -07004136 }
Kenny Rootaf9d6672010-10-08 09:21:39 -07004137 }
Kenny Root38cf8862010-09-26 14:18:51 -07004138
Kenny Rootaf9d6672010-10-08 09:21:39 -07004139 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06004140 mObbState.volId = mVold.createObb(mObbState.canonicalPath, binderKey,
4141 mObbState.ownerGid);
Zim95eca1d2019-11-15 18:03:00 +00004142 mVold.mount(mObbState.volId, 0, -1, null);
Kenny Roota02b8b02010-08-05 16:14:17 -07004143
Kenny Rootaf9d6672010-10-08 09:21:39 -07004144 if (DEBUG_OBB)
Xiaohui Chen621b3fc2015-10-02 14:41:42 -07004145 Slog.d(TAG, "Successfully mounted OBB " + mObbState.canonicalPath);
Kenny Rootaf9d6672010-10-08 09:21:39 -07004146
4147 synchronized (mObbMounts) {
4148 addObbStateLocked(mObbState);
4149 }
4150
Jeff Sharkey0095a822018-02-15 13:06:53 -07004151 notifyObbStateChange(MOUNTED);
4152 } catch (Exception e) {
4153 throw new ObbException(ERROR_COULD_NOT_MOUNT, e);
Kenny Root02c87302010-07-01 08:10:18 -07004154 }
4155 }
4156
Jason parks5af0b912010-11-29 09:05:25 -06004157 @Override
Kenny Roota02b8b02010-08-05 16:14:17 -07004158 public String toString() {
4159 StringBuilder sb = new StringBuilder();
4160 sb.append("MountObbAction{");
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07004161 sb.append(mObbState);
Kenny Roota02b8b02010-08-05 16:14:17 -07004162 sb.append('}');
4163 return sb.toString();
4164 }
4165 }
4166
4167 class UnmountObbAction extends ObbAction {
Ben Komalo444eca22011-09-01 15:17:44 -07004168 private final boolean mForceUnmount;
Kenny Roota02b8b02010-08-05 16:14:17 -07004169
4170 UnmountObbAction(ObbState obbState, boolean force) {
4171 super(obbState);
4172 mForceUnmount = force;
4173 }
4174
Jason parks5af0b912010-11-29 09:05:25 -06004175 @Override
Jeff Sharkey0095a822018-02-15 13:06:53 -07004176 public void handleExecute() throws ObbException {
Kenny Rootaf9d6672010-10-08 09:21:39 -07004177 warnOnNotMounted();
4178
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07004179 final ObbState existingState;
Kenny Root38cf8862010-09-26 14:18:51 -07004180 synchronized (mObbMounts) {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07004181 existingState = mObbPathToStateMap.get(mObbState.rawPath);
Kenny Rootaf9d6672010-10-08 09:21:39 -07004182 }
Kenny Root38cf8862010-09-26 14:18:51 -07004183
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07004184 if (existingState == null) {
Jeff Sharkey0095a822018-02-15 13:06:53 -07004185 throw new ObbException(ERROR_NOT_MOUNTED, "Missing existingState");
Kenny Rootaf9d6672010-10-08 09:21:39 -07004186 }
4187
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07004188 if (existingState.ownerGid != mObbState.ownerGid) {
Jeff Sharkey0095a822018-02-15 13:06:53 -07004189 notifyObbStateChange(new ObbException(ERROR_PERMISSION_DENIED,
4190 "Permission denied to unmount OBB " + existingState.rawPath
4191 + " (owned by GID " + existingState.ownerGid + ")"));
Kenny Rootaf9d6672010-10-08 09:21:39 -07004192 return;
4193 }
4194
Kenny Rootaf9d6672010-10-08 09:21:39 -07004195 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06004196 mVold.unmount(mObbState.volId);
4197 mVold.destroyObb(mObbState.volId);
4198 mObbState.volId = null;
Kenny Roota02b8b02010-08-05 16:14:17 -07004199
Kenny Rootaf9d6672010-10-08 09:21:39 -07004200 synchronized (mObbMounts) {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07004201 removeObbStateLocked(existingState);
Kenny Root38cf8862010-09-26 14:18:51 -07004202 }
4203
Jeff Sharkey0095a822018-02-15 13:06:53 -07004204 notifyObbStateChange(UNMOUNTED);
4205 } catch (Exception e) {
4206 throw new ObbException(ERROR_COULD_NOT_UNMOUNT, e);
Kenny Roota02b8b02010-08-05 16:14:17 -07004207 }
4208 }
4209
Jason parks5af0b912010-11-29 09:05:25 -06004210 @Override
Kenny Roota02b8b02010-08-05 16:14:17 -07004211 public String toString() {
4212 StringBuilder sb = new StringBuilder();
4213 sb.append("UnmountObbAction{");
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07004214 sb.append(mObbState);
Kenny Roota02b8b02010-08-05 16:14:17 -07004215 sb.append(",force=");
4216 sb.append(mForceUnmount);
Kenny Roota02b8b02010-08-05 16:14:17 -07004217 sb.append('}');
4218 return sb.toString();
4219 }
Kenny Root02c87302010-07-01 08:10:18 -07004220 }
Kenny Root38cf8862010-09-26 14:18:51 -07004221
Jeff Sharkey7e19f532017-11-06 13:54:11 -07004222 private void dispatchOnStatus(IVoldTaskListener listener, int status,
4223 PersistableBundle extras) {
4224 if (listener != null) {
4225 try {
4226 listener.onStatus(status, extras);
4227 } catch (RemoteException ignored) {
4228 }
4229 }
4230 }
4231
4232 private void dispatchOnFinished(IVoldTaskListener listener, int status,
4233 PersistableBundle extras) {
4234 if (listener != null) {
4235 try {
4236 listener.onFinished(status, extras);
4237 } catch (RemoteException ignored) {
4238 }
4239 }
4240 }
4241
Sudheer Shanka3a0df3b2018-12-12 12:43:43 -08004242 private int getMountMode(int uid, String packageName) {
Jeff Sharkey6fd69942019-03-26 17:53:35 -06004243 final int mode = getMountModeInternal(uid, packageName);
4244 if (LOCAL_LOGV) {
4245 Slog.v(TAG, "Resolved mode " + mode + " for " + packageName + "/"
4246 + UserHandle.formatUid(uid));
4247 }
4248 return mode;
4249 }
4250
4251 private int getMountModeInternal(int uid, String packageName) {
Sudheer Shanka3a0df3b2018-12-12 12:43:43 -08004252 try {
Jeff Sharkey6fd69942019-03-26 17:53:35 -06004253 // Get some easy cases out of the way first
Sudheer Shanka3a0df3b2018-12-12 12:43:43 -08004254 if (Process.isIsolated(uid)) {
4255 return Zygote.MOUNT_EXTERNAL_NONE;
4256 }
Sudheer Shankab1613982019-05-16 16:55:50 -07004257
4258 final String[] packagesForUid = mIPackageManager.getPackagesForUid(uid);
Sudheer Shanka1df72db2019-05-24 10:59:52 -07004259 if (ArrayUtils.isEmpty(packagesForUid)) {
4260 // It's possible the package got uninstalled already, so just ignore.
4261 return Zygote.MOUNT_EXTERNAL_NONE;
4262 }
Sudheer Shankab1613982019-05-16 16:55:50 -07004263 if (packageName == null) {
4264 packageName = packagesForUid[0];
4265 }
4266
Jeff Sharkey6fd69942019-03-26 17:53:35 -06004267 if (mPmInternal.isInstantApp(packageName, UserHandle.getUserId(uid))) {
Winson Chiu5118d492019-05-15 18:24:06 +00004268 return Zygote.MOUNT_EXTERNAL_NONE;
Jeff Sharkey6fd69942019-03-26 17:53:35 -06004269 }
4270
Ricky Waie25c92d2020-03-16 15:55:06 +00004271 if (mIsFuseEnabled && mStorageManagerInternal.isExternalStorageService(uid)) {
Martijn Coenen44db1ac2019-12-03 16:06:19 +01004272 // Determine if caller requires pass_through mount; note that we do this for
4273 // all processes that share a UID with MediaProvider; but this is fine, since
4274 // those processes anyway share the same rights as MediaProvider.
Zim74a9bba2019-09-03 20:49:13 +01004275 return Zygote.MOUNT_EXTERNAL_PASS_THROUGH;
4276 }
4277
Abhijeet Kaurde4e90a2020-05-14 11:44:15 +01004278 if (mIsFuseEnabled && (mDownloadsAuthorityAppId == UserHandle.getAppId(uid)
4279 || mExternalStorageAuthorityAppId == UserHandle.getAppId(uid))) {
Martijn Coenen496ac002020-01-08 14:55:53 +01004280 // DownloadManager can write in app-private directories on behalf of apps;
4281 // give it write access to Android/
Abhijeet Kaurde4e90a2020-05-14 11:44:15 +01004282 // ExternalStorageProvider can access Android/{data,obb} dirs in managed mode
Martijn Coenen496ac002020-01-08 14:55:53 +01004283 return Zygote.MOUNT_EXTERNAL_ANDROID_WRITABLE;
4284 }
4285
4286 final boolean hasMtp = mIPackageManager.checkUidPermission(ACCESS_MTP, uid) ==
4287 PERMISSION_GRANTED;
4288 if (mIsFuseEnabled && hasMtp) {
Zim36e16b22020-01-31 13:28:13 +00004289 ApplicationInfo ai = mIPackageManager.getApplicationInfo(packageName,
4290 0, UserHandle.getUserId(uid));
Martijn Coenen0fc9f5e2020-02-14 19:46:40 +01004291 if (ai != null && ai.isSignedWithPlatformKey()) {
Zim36e16b22020-01-31 13:28:13 +00004292 // Platform processes hosting the MTP server should be able to write in Android/
4293 return Zygote.MOUNT_EXTERNAL_ANDROID_WRITABLE;
4294 }
Martijn Coenen496ac002020-01-08 14:55:53 +01004295 }
4296
Jeff Sharkey6fd69942019-03-26 17:53:35 -06004297 // Determine if caller is holding runtime permission
Chad Brubaker45810af2019-04-08 19:19:48 -07004298 final boolean hasRead = StorageManager.checkPermissionAndCheckOp(mContext, false, 0,
Jeff Sharkey6fd69942019-03-26 17:53:35 -06004299 uid, packageName, READ_EXTERNAL_STORAGE, OP_READ_EXTERNAL_STORAGE);
Chad Brubaker45810af2019-04-08 19:19:48 -07004300 final boolean hasWrite = StorageManager.checkPermissionAndCheckOp(mContext, false, 0,
Jeff Sharkey6fd69942019-03-26 17:53:35 -06004301 uid, packageName, WRITE_EXTERNAL_STORAGE, OP_WRITE_EXTERNAL_STORAGE);
Jeff Sharkey6fd69942019-03-26 17:53:35 -06004302
4303 // We're only willing to give out broad access if they also hold
4304 // runtime permission; this is a firm CDD requirement
4305 final boolean hasFull = mIPackageManager.checkUidPermission(WRITE_MEDIA_STORAGE,
4306 uid) == PERMISSION_GRANTED;
Jeff Sharkey26874a22019-04-17 21:30:47 -06004307 if (hasFull && hasWrite) {
Jeff Sharkey6fd69942019-03-26 17:53:35 -06004308 return Zygote.MOUNT_EXTERNAL_FULL;
4309 }
4310
4311 // We're only willing to give out installer access if they also hold
4312 // runtime permission; this is a firm CDD requirement
4313 final boolean hasInstall = mIPackageManager.checkUidPermission(INSTALL_PACKAGES,
4314 uid) == PERMISSION_GRANTED;
Sudheer Shankab1613982019-05-16 16:55:50 -07004315 boolean hasInstallOp = false;
4316 // OP_REQUEST_INSTALL_PACKAGES is granted/denied per package but vold can't
4317 // update mountpoints of a specific package. So, check the appop for all packages
4318 // sharing the uid and allow same level of storage access for all packages even if
4319 // one of the packages has the appop granted.
4320 for (String uidPackageName : packagesForUid) {
4321 if (mIAppOpsService.checkOperation(
4322 OP_REQUEST_INSTALL_PACKAGES, uid, uidPackageName) == MODE_ALLOWED) {
4323 hasInstallOp = true;
4324 break;
4325 }
4326 }
Jeff Sharkey26874a22019-04-17 21:30:47 -06004327 if ((hasInstall || hasInstallOp) && hasWrite) {
Martijn Coenenfc9c3b62019-12-13 16:36:27 +01004328 return Zygote.MOUNT_EXTERNAL_INSTALLER;
Jeff Sharkey6fd69942019-03-26 17:53:35 -06004329 }
4330
4331 // Otherwise we're willing to give out sandboxed or non-sandboxed if
4332 // they hold the runtime permission
Nandana Duttdc15bb42020-01-03 16:43:46 +00004333 boolean hasLegacy = mIAppOpsService.checkOperation(OP_LEGACY_STORAGE,
Jeff Sharkey6fd69942019-03-26 17:53:35 -06004334 uid, packageName) == MODE_ALLOWED;
Nandana Duttdc15bb42020-01-03 16:43:46 +00004335
Jeff Sharkey26874a22019-04-17 21:30:47 -06004336 if (hasLegacy && hasWrite) {
4337 return Zygote.MOUNT_EXTERNAL_WRITE;
4338 } else if (hasLegacy && hasRead) {
4339 return Zygote.MOUNT_EXTERNAL_READ;
Sudheer Shanka3a0df3b2018-12-12 12:43:43 -08004340 } else {
Sudheer Shanka783c90e2019-04-12 13:55:20 -07004341 return Zygote.MOUNT_EXTERNAL_DEFAULT;
Sudheer Shanka3a0df3b2018-12-12 12:43:43 -08004342 }
4343 } catch (RemoteException e) {
4344 // Should not happen
4345 }
4346 return Zygote.MOUNT_EXTERNAL_NONE;
4347 }
4348
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07004349 private static class Callbacks extends Handler {
4350 private static final int MSG_STORAGE_STATE_CHANGED = 1;
4351 private static final int MSG_VOLUME_STATE_CHANGED = 2;
Jeff Sharkey50a05452015-04-29 11:24:52 -07004352 private static final int MSG_VOLUME_RECORD_CHANGED = 3;
4353 private static final int MSG_VOLUME_FORGOTTEN = 4;
4354 private static final int MSG_DISK_SCANNED = 5;
Makoto Onuki9dc575d2015-06-12 16:10:25 -07004355 private static final int MSG_DISK_DESTROYED = 6;
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07004356
Sudheer Shanka2250d562016-11-07 15:41:02 -08004357 private final RemoteCallbackList<IStorageEventListener>
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07004358 mCallbacks = new RemoteCallbackList<>();
4359
4360 public Callbacks(Looper looper) {
4361 super(looper);
4362 }
4363
Sudheer Shanka2250d562016-11-07 15:41:02 -08004364 public void register(IStorageEventListener callback) {
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07004365 mCallbacks.register(callback);
4366 }
4367
Sudheer Shanka2250d562016-11-07 15:41:02 -08004368 public void unregister(IStorageEventListener callback) {
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07004369 mCallbacks.unregister(callback);
4370 }
4371
4372 @Override
4373 public void handleMessage(Message msg) {
4374 final SomeArgs args = (SomeArgs) msg.obj;
4375 final int n = mCallbacks.beginBroadcast();
4376 for (int i = 0; i < n; i++) {
Sudheer Shanka2250d562016-11-07 15:41:02 -08004377 final IStorageEventListener callback = mCallbacks.getBroadcastItem(i);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07004378 try {
4379 invokeCallback(callback, msg.what, args);
4380 } catch (RemoteException ignored) {
4381 }
4382 }
4383 mCallbacks.finishBroadcast();
4384 args.recycle();
4385 }
4386
Sudheer Shanka2250d562016-11-07 15:41:02 -08004387 private void invokeCallback(IStorageEventListener callback, int what, SomeArgs args)
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07004388 throws RemoteException {
4389 switch (what) {
4390 case MSG_STORAGE_STATE_CHANGED: {
4391 callback.onStorageStateChanged((String) args.arg1, (String) args.arg2,
4392 (String) args.arg3);
4393 break;
4394 }
4395 case MSG_VOLUME_STATE_CHANGED: {
4396 callback.onVolumeStateChanged((VolumeInfo) args.arg1, args.argi2, args.argi3);
4397 break;
4398 }
Jeff Sharkey50a05452015-04-29 11:24:52 -07004399 case MSG_VOLUME_RECORD_CHANGED: {
4400 callback.onVolumeRecordChanged((VolumeRecord) args.arg1);
4401 break;
4402 }
4403 case MSG_VOLUME_FORGOTTEN: {
4404 callback.onVolumeForgotten((String) args.arg1);
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07004405 break;
4406 }
Jeff Sharkey620b32b2015-04-23 19:36:02 -07004407 case MSG_DISK_SCANNED: {
4408 callback.onDiskScanned((DiskInfo) args.arg1, args.argi2);
Jeff Sharkey7e92ef32015-04-17 17:35:07 -07004409 break;
4410 }
Makoto Onuki9dc575d2015-06-12 16:10:25 -07004411 case MSG_DISK_DESTROYED: {
4412 callback.onDiskDestroyed((DiskInfo) args.arg1);
4413 break;
4414 }
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07004415 }
4416 }
4417
4418 private void notifyStorageStateChanged(String path, String oldState, String newState) {
4419 final SomeArgs args = SomeArgs.obtain();
4420 args.arg1 = path;
4421 args.arg2 = oldState;
4422 args.arg3 = newState;
4423 obtainMessage(MSG_STORAGE_STATE_CHANGED, args).sendToTarget();
4424 }
4425
4426 private void notifyVolumeStateChanged(VolumeInfo vol, int oldState, int newState) {
4427 final SomeArgs args = SomeArgs.obtain();
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07004428 args.arg1 = vol.clone();
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07004429 args.argi2 = oldState;
4430 args.argi3 = newState;
4431 obtainMessage(MSG_VOLUME_STATE_CHANGED, args).sendToTarget();
4432 }
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07004433
Jeff Sharkey50a05452015-04-29 11:24:52 -07004434 private void notifyVolumeRecordChanged(VolumeRecord rec) {
4435 final SomeArgs args = SomeArgs.obtain();
4436 args.arg1 = rec.clone();
4437 obtainMessage(MSG_VOLUME_RECORD_CHANGED, args).sendToTarget();
4438 }
4439
4440 private void notifyVolumeForgotten(String fsUuid) {
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07004441 final SomeArgs args = SomeArgs.obtain();
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07004442 args.arg1 = fsUuid;
Jeff Sharkey50a05452015-04-29 11:24:52 -07004443 obtainMessage(MSG_VOLUME_FORGOTTEN, args).sendToTarget();
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07004444 }
Jeff Sharkey7e92ef32015-04-17 17:35:07 -07004445
Jeff Sharkey620b32b2015-04-23 19:36:02 -07004446 private void notifyDiskScanned(DiskInfo disk, int volumeCount) {
Jeff Sharkey7e92ef32015-04-17 17:35:07 -07004447 final SomeArgs args = SomeArgs.obtain();
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07004448 args.arg1 = disk.clone();
Jeff Sharkey620b32b2015-04-23 19:36:02 -07004449 args.argi2 = volumeCount;
4450 obtainMessage(MSG_DISK_SCANNED, args).sendToTarget();
Jeff Sharkey7e92ef32015-04-17 17:35:07 -07004451 }
Makoto Onuki9dc575d2015-06-12 16:10:25 -07004452
4453 private void notifyDiskDestroyed(DiskInfo disk) {
4454 final SomeArgs args = SomeArgs.obtain();
4455 args.arg1 = disk.clone();
4456 obtainMessage(MSG_DISK_DESTROYED, args).sendToTarget();
4457 }
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07004458 }
4459
Kenny Root38cf8862010-09-26 14:18:51 -07004460 @Override
Jeff Sharkey5aca2b82013-10-16 16:21:54 -07004461 protected void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
Jeff Sharkeyfe9a53b2017-03-31 14:08:23 -06004462 if (!DumpUtils.checkDumpPermission(mContext, TAG, writer)) return;
Jeff Sharkey5aca2b82013-10-16 16:21:54 -07004463
4464 final IndentingPrintWriter pw = new IndentingPrintWriter(writer, " ", 160);
Jeff Sharkey27de30d2015-04-18 16:20:27 -07004465 synchronized (mLock) {
4466 pw.println("Disks:");
4467 pw.increaseIndent();
4468 for (int i = 0; i < mDisks.size(); i++) {
4469 final DiskInfo disk = mDisks.valueAt(i);
4470 disk.dump(pw);
4471 }
4472 pw.decreaseIndent();
4473
4474 pw.println();
4475 pw.println("Volumes:");
4476 pw.increaseIndent();
4477 for (int i = 0; i < mVolumes.size(); i++) {
4478 final VolumeInfo vol = mVolumes.valueAt(i);
4479 if (VolumeInfo.ID_PRIVATE_INTERNAL.equals(vol.id)) continue;
4480 vol.dump(pw);
4481 }
4482 pw.decreaseIndent();
4483
4484 pw.println();
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07004485 pw.println("Records:");
Jeff Sharkey27de30d2015-04-18 16:20:27 -07004486 pw.increaseIndent();
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07004487 for (int i = 0; i < mRecords.size(); i++) {
4488 final VolumeRecord note = mRecords.valueAt(i);
4489 note.dump(pw);
Jeff Sharkey27de30d2015-04-18 16:20:27 -07004490 }
4491 pw.decreaseIndent();
Jeff Sharkey275e3e42015-04-24 16:10:32 -07004492
4493 pw.println();
4494 pw.println("Primary storage UUID: " + mPrimaryStorageUuid);
Jeff Sharkeyb0c363b22018-12-15 11:53:03 -07004495
4496 pw.println();
Felipe Leme281389a2016-10-10 17:12:20 -07004497 final Pair<String, Long> pair = StorageManager.getPrimaryStoragePathAndSize();
4498 if (pair == null) {
4499 pw.println("Internal storage total size: N/A");
4500 } else {
4501 pw.print("Internal storage (");
4502 pw.print(pair.first);
4503 pw.print(") total size: ");
4504 pw.print(pair.second);
4505 pw.print(" (");
Jeff Sharkey9f2dc052018-01-07 16:47:31 -07004506 pw.print(DataUnit.MEBIBYTES.toBytes(pair.second));
4507 pw.println(" MiB)");
Felipe Leme281389a2016-10-10 17:12:20 -07004508 }
Jeff Sharkeyb0c363b22018-12-15 11:53:03 -07004509
4510 pw.println();
Lee Shombertebe2a0b2020-01-23 10:02:15 -08004511 pw.println("Local unlocked users: " + mLocalUnlockedUsers);
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07004512 pw.println("System unlocked users: " + Arrays.toString(mSystemUnlockedUsers));
Jeff Sharkeyb0c363b22018-12-15 11:53:03 -07004513
4514 final ContentResolver cr = mContext.getContentResolver();
4515 pw.println();
4516 pw.println("Isolated storage, local feature flag: "
4517 + Settings.Global.getInt(cr, Settings.Global.ISOLATED_STORAGE_LOCAL, 0));
4518 pw.println("Isolated storage, remote feature flag: "
4519 + Settings.Global.getInt(cr, Settings.Global.ISOLATED_STORAGE_REMOTE, 0));
4520 pw.println("Isolated storage, resolved: " + StorageManager.hasIsolatedStorage());
shafik3acc77c2020-05-18 17:04:53 +01004521 pw.println("Forced scoped storage app list: "
4522 + DeviceConfig.getProperty(DeviceConfig.NAMESPACE_STORAGE_NATIVE_BOOT,
4523 PROP_FORCED_SCOPED_STORAGE_WHITELIST));
Keun young Park37a49da2020-06-18 16:01:05 -07004524 pw.println("isAutomotive:" + mIsAutomotive);
Jeff Sharkey27de30d2015-04-18 16:20:27 -07004525 }
Kenny Root38cf8862010-09-26 14:18:51 -07004526
Kenny Root38cf8862010-09-26 14:18:51 -07004527 synchronized (mObbMounts) {
Jeff Sharkey27de30d2015-04-18 16:20:27 -07004528 pw.println();
Jeff Sharkey5aca2b82013-10-16 16:21:54 -07004529 pw.println("mObbMounts:");
4530 pw.increaseIndent();
4531 final Iterator<Entry<IBinder, List<ObbState>>> binders = mObbMounts.entrySet()
4532 .iterator();
Kenny Rootaf9d6672010-10-08 09:21:39 -07004533 while (binders.hasNext()) {
4534 Entry<IBinder, List<ObbState>> e = binders.next();
Jeff Sharkey5aca2b82013-10-16 16:21:54 -07004535 pw.println(e.getKey() + ":");
4536 pw.increaseIndent();
Kenny Rootaf9d6672010-10-08 09:21:39 -07004537 final List<ObbState> obbStates = e.getValue();
Kenny Root38cf8862010-09-26 14:18:51 -07004538 for (final ObbState obbState : obbStates) {
Jeff Sharkey5aca2b82013-10-16 16:21:54 -07004539 pw.println(obbState);
Kenny Root38cf8862010-09-26 14:18:51 -07004540 }
Jeff Sharkey5aca2b82013-10-16 16:21:54 -07004541 pw.decreaseIndent();
Kenny Root38cf8862010-09-26 14:18:51 -07004542 }
Jeff Sharkey5aca2b82013-10-16 16:21:54 -07004543 pw.decreaseIndent();
Kenny Rootaf9d6672010-10-08 09:21:39 -07004544
Jeff Sharkey5aca2b82013-10-16 16:21:54 -07004545 pw.println();
4546 pw.println("mObbPathToStateMap:");
4547 pw.increaseIndent();
Ricky Wai486d7602020-02-28 16:37:07 +00004548 final Iterator<Entry<String, ObbState>> maps =
4549 mObbPathToStateMap.entrySet().iterator();
Kenny Rootaf9d6672010-10-08 09:21:39 -07004550 while (maps.hasNext()) {
4551 final Entry<String, ObbState> e = maps.next();
Jeff Sharkey5aca2b82013-10-16 16:21:54 -07004552 pw.print(e.getKey());
4553 pw.print(" -> ");
4554 pw.println(e.getValue());
Kenny Rootaf9d6672010-10-08 09:21:39 -07004555 }
Jeff Sharkey5aca2b82013-10-16 16:21:54 -07004556 pw.decreaseIndent();
Kenny Root38cf8862010-09-26 14:18:51 -07004557 }
Kenny Root4161f9b2011-07-13 09:48:33 -07004558
Robert Greenwalt470fd722012-01-18 12:51:15 -08004559 pw.println();
Christopher Tate7265abe2014-11-21 13:54:45 -08004560 pw.print("Last maintenance: ");
Jeff Sharkeye8a4b662015-06-27 15:43:45 -07004561 pw.println(TimeUtils.formatForLogging(mLastMaintenance));
Kenny Root38cf8862010-09-26 14:18:51 -07004562 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004563
Jeff Sharkeyfa23c5a2011-08-09 21:44:24 -07004564 /** {@inheritDoc} */
Jeff Sharkey48877892015-03-18 11:27:19 -07004565 @Override
Jeff Sharkeyfa23c5a2011-08-09 21:44:24 -07004566 public void monitor() {
Jeff Sharkey54402792017-09-15 16:05:19 -06004567 try {
4568 mVold.monitor();
4569 } catch (Exception e) {
4570 Slog.wtf(TAG, e);
Paul Lawrence1c62cbb2015-06-03 14:14:52 -07004571 }
Jeff Sharkeyfa23c5a2011-08-09 21:44:24 -07004572 }
Svet Ganov6ee871e2015-07-10 14:29:33 -07004573
Sudheer Shanka2250d562016-11-07 15:41:02 -08004574 private final class StorageManagerInternalImpl extends StorageManagerInternal {
Svet Ganov6ee871e2015-07-10 14:29:33 -07004575 // Not guarded by a lock.
4576 private final CopyOnWriteArrayList<ExternalStorageMountPolicy> mPolicies =
4577 new CopyOnWriteArrayList<>();
4578
Risanaec0ee72018-10-31 10:10:12 +09004579 @GuardedBy("mResetListeners")
4580 private final List<StorageManagerInternal.ResetListener> mResetListeners =
4581 new ArrayList<>();
4582
Svet Ganov6ee871e2015-07-10 14:29:33 -07004583 @Override
4584 public void addExternalStoragePolicy(ExternalStorageMountPolicy policy) {
4585 // No locking - CopyOnWriteArrayList
4586 mPolicies.add(policy);
4587 }
4588
Ricky Waie5088d92020-01-22 17:52:52 +00004589 /**
Ricky Wai486d7602020-02-28 16:37:07 +00004590 * Check if fuse is running in target user, if it's running then setup its storage dirs.
4591 * Return true if storage dirs are mounted.
Ricky Waie5088d92020-01-22 17:52:52 +00004592 */
4593 @Override
Ricky Wai486d7602020-02-28 16:37:07 +00004594 public boolean prepareStorageDirs(int userId, Set<String> packageList,
4595 String processName) {
Linus Tufvesson4e0ff022020-03-27 14:53:30 +00004596 synchronized (mLock) {
4597 if (!mFuseMountedUser.contains(userId)) {
4598 Slog.w(TAG, "User " + userId + " is not unlocked yet so skip mounting obb");
4599 return false;
4600 }
Ricky Waie5088d92020-01-22 17:52:52 +00004601 }
Ricky Wai486d7602020-02-28 16:37:07 +00004602 try {
4603 final IVold vold = IVold.Stub.asInterface(
4604 ServiceManager.getServiceOrThrow("vold"));
4605 for (String pkg : packageList) {
4606 final String packageObbDir =
4607 String.format("/storage/emulated/%d/Android/obb/%s/", userId, pkg);
4608 final String packageDataDir =
4609 String.format("/storage/emulated/%d/Android/data/%s/",
4610 userId, pkg);
Ricky Waie5088d92020-01-22 17:52:52 +00004611
Ricky Wai486d7602020-02-28 16:37:07 +00004612 // Create package obb and data dir if it doesn't exist.
Ricky Waiaf8bcbd2020-03-30 19:07:06 +01004613 int appUid = UserHandle.getUid(userId, mPmInternal.getPackage(pkg).getUid());
Ricky Wai486d7602020-02-28 16:37:07 +00004614 File file = new File(packageObbDir);
4615 if (!file.exists()) {
Ricky Waie25c92d2020-03-16 15:55:06 +00004616 vold.setupAppDir(packageObbDir, appUid);
Ricky Waie5088d92020-01-22 17:52:52 +00004617 }
Ricky Wai486d7602020-02-28 16:37:07 +00004618 file = new File(packageDataDir);
4619 if (!file.exists()) {
Ricky Waie25c92d2020-03-16 15:55:06 +00004620 vold.setupAppDir(packageDataDir, appUid);
Ricky Wai486d7602020-02-28 16:37:07 +00004621 }
Ricky Waie5088d92020-01-22 17:52:52 +00004622 }
Ricky Wai486d7602020-02-28 16:37:07 +00004623 } catch (ServiceManager.ServiceNotFoundException | RemoteException e) {
4624 Slog.e(TAG, "Unable to create obb and data directories for " + processName,e);
4625 return false;
Ricky Waie5088d92020-01-22 17:52:52 +00004626 }
Ricky Wai486d7602020-02-28 16:37:07 +00004627 return true;
Ricky Waie5088d92020-01-22 17:52:52 +00004628 }
4629
Svet Ganov6ee871e2015-07-10 14:29:33 -07004630 @Override
4631 public void onExternalStoragePolicyChanged(int uid, String packageName) {
4632 final int mountMode = getExternalStorageMountMode(uid, packageName);
4633 remountUidExternalStorage(uid, mountMode);
4634 }
4635
4636 @Override
4637 public int getExternalStorageMountMode(int uid, String packageName) {
Sudheer Shanka3a0df3b2018-12-12 12:43:43 -08004638 if (ENABLE_ISOLATED_STORAGE) {
4639 return getMountMode(uid, packageName);
4640 }
Sudheer Shankab1613982019-05-16 16:55:50 -07004641 try {
4642 if (packageName == null) {
4643 final String[] packagesForUid = mIPackageManager.getPackagesForUid(uid);
4644 packageName = packagesForUid[0];
4645 }
4646 } catch (RemoteException e) {
4647 // Should not happen - same process
4648 }
Svet Ganov6ee871e2015-07-10 14:29:33 -07004649 // No locking - CopyOnWriteArrayList
4650 int mountMode = Integer.MAX_VALUE;
4651 for (ExternalStorageMountPolicy policy : mPolicies) {
4652 final int policyMode = policy.getMountMode(uid, packageName);
4653 if (policyMode == Zygote.MOUNT_EXTERNAL_NONE) {
4654 return Zygote.MOUNT_EXTERNAL_NONE;
4655 }
4656 mountMode = Math.min(mountMode, policyMode);
4657 }
4658 if (mountMode == Integer.MAX_VALUE) {
4659 return Zygote.MOUNT_EXTERNAL_NONE;
4660 }
4661 return mountMode;
4662 }
4663
Risanaec0ee72018-10-31 10:10:12 +09004664 @Override
4665 public void addResetListener(StorageManagerInternal.ResetListener listener) {
4666 synchronized (mResetListeners) {
4667 mResetListeners.add(listener);
4668 }
4669 }
4670
4671 public void onReset(IVold vold) {
4672 synchronized (mResetListeners) {
4673 for (StorageManagerInternal.ResetListener listener : mResetListeners) {
4674 listener.onReset(vold);
4675 }
4676 }
4677 }
4678
Martijn Coenen73918202019-12-09 17:02:44 +01004679 @Override
4680 public void resetUser(int userId) {
4681 // TODO(b/145931219): ideally, we only reset storage for the user in question,
4682 // but for now, reset everything.
4683 mHandler.obtainMessage(H_RESET).sendToTarget();
4684 }
4685
Zim3ce38492020-02-07 15:14:58 +00004686 @Override
4687 public boolean hasLegacyExternalStorage(int uid) {
4688 synchronized (mLock) {
4689 return mUidsWithLegacyExternalStorage.contains(uid);
4690 }
4691 }
4692
Martijn Coenenb3562f42020-02-12 15:11:56 +01004693 @Override
4694 public void prepareAppDataAfterInstall(String packageName, int uid) {
4695 int userId = UserHandle.getUserId(uid);
4696 final Environment.UserEnvironment userEnv = new Environment.UserEnvironment(userId);
4697
4698 // The installer may have downloaded OBBs for this newly installed application;
4699 // make sure the OBB dir for the application is setup correctly, if it exists.
4700 File[] packageObbDirs = userEnv.buildExternalStorageAppObbDirs(packageName);
4701 for (File packageObbDir : packageObbDirs) {
4702 try {
4703 mVold.fixupAppDir(packageObbDir.getCanonicalPath() + "/", uid);
4704 } catch (IOException e) {
4705 Log.e(TAG, "Failed to get canonical path for " + packageName);
Martijn Coenen1ebebfd2020-02-21 09:04:30 +01004706 } catch (RemoteException | ServiceSpecificException e) {
4707 // TODO(b/149975102) there is a known case where this fails, when a new
4708 // user is setup and we try to fixup app dirs for some existing apps.
4709 // For now catch the exception and don't crash.
4710 Log.e(TAG, "Failed to fixup app dir for " + packageName, e);
Martijn Coenenb3562f42020-02-12 15:11:56 +01004711 }
4712 }
4713 }
4714
Ricky Waie25c92d2020-03-16 15:55:06 +00004715 @Override
4716 public boolean isExternalStorageService(int uid) {
4717 return mMediaStoreAuthorityAppId == UserHandle.getAppId(uid);
4718 }
4719
Svet Ganov6ee871e2015-07-10 14:29:33 -07004720 public boolean hasExternalStorage(int uid, String packageName) {
Amith Yamasani2bd5cff2015-07-22 14:42:31 -07004721 // No need to check for system uid. This avoids a deadlock between
4722 // PackageManagerService and AppOpsService.
4723 if (uid == Process.SYSTEM_UID) {
4724 return true;
4725 }
Sudheer Shanka3a0df3b2018-12-12 12:43:43 -08004726 if (ENABLE_ISOLATED_STORAGE) {
4727 return getMountMode(uid, packageName) != Zygote.MOUNT_EXTERNAL_NONE;
4728 }
Svet Ganov6ee871e2015-07-10 14:29:33 -07004729 // No locking - CopyOnWriteArrayList
4730 for (ExternalStorageMountPolicy policy : mPolicies) {
4731 final boolean policyHasStorage = policy.hasExternalStorage(uid, packageName);
4732 if (!policyHasStorage) {
4733 return false;
4734 }
4735 }
4736 return true;
4737 }
Sudheer Shankab1613982019-05-16 16:55:50 -07004738
Zimb0dffde2020-01-29 18:45:52 +00004739 private void killAppForOpChange(int code, int uid, String packageName) {
4740 final IActivityManager am = ActivityManager.getService();
4741 try {
Martijn Coenen6bb801e2020-06-04 06:15:43 +02004742 am.killUid(UserHandle.getAppId(uid), UserHandle.USER_ALL,
4743 AppOpsManager.opToName(code) + " changed.");
Zimb0dffde2020-01-29 18:45:52 +00004744 } catch (RemoteException e) {
Martijn Coenen28ec85a2020-01-28 17:02:23 +01004745 }
Zimb0dffde2020-01-29 18:45:52 +00004746 }
4747
4748 public void onAppOpsChanged(int code, int uid, @Nullable String packageName, int mode) {
Zimc93da802020-02-28 19:01:49 +00004749 final long token = Binder.clearCallingIdentity();
4750 try {
4751 if (mIsFuseEnabled) {
4752 // When using FUSE, we may need to kill the app if the op changes
4753 switch(code) {
4754 case OP_REQUEST_INSTALL_PACKAGES:
4755 // Always kill regardless of op change, to remount apps /storage
Zimb0dffde2020-01-29 18:45:52 +00004756 killAppForOpChange(code, uid, packageName);
Zimc93da802020-02-28 19:01:49 +00004757 return;
4758 case OP_MANAGE_EXTERNAL_STORAGE:
4759 if (mode != MODE_ALLOWED) {
4760 // Only kill if op is denied, to lose external_storage gid
4761 // Killing when op is granted to pickup the gid automatically,
4762 // results in a bad UX, especially since the gid only gives access
4763 // to unreliable volumes, USB OTGs that are rarely mounted. The app
4764 // will get the external_storage gid on next organic restart.
Martijn Coenen6bb801e2020-06-04 06:15:43 +02004765 if (packageName != null) {
4766 killAppForOpChange(code, uid, packageName);
4767 } else {
4768 // TODO(b/158283222) this can happen, figure out if we need
4769 // to kill in this case as well.
4770 }
Zimc93da802020-02-28 19:01:49 +00004771 }
4772 return;
4773 case OP_LEGACY_STORAGE:
4774 updateLegacyStorageApps(packageName, uid, mode == MODE_ALLOWED);
4775 return;
4776 }
Zimb0dffde2020-01-29 18:45:52 +00004777 }
Zimb0dffde2020-01-29 18:45:52 +00004778
Zimc93da802020-02-28 19:01:49 +00004779 if (mode == MODE_ALLOWED && (code == OP_READ_EXTERNAL_STORAGE
4780 || code == OP_WRITE_EXTERNAL_STORAGE
4781 || code == OP_REQUEST_INSTALL_PACKAGES)) {
Sudheer Shankab1613982019-05-16 16:55:50 -07004782 final UserManagerInternal userManagerInternal =
4783 LocalServices.getService(UserManagerInternal.class);
4784 if (userManagerInternal.isUserInitialized(UserHandle.getUserId(uid))) {
4785 onExternalStoragePolicyChanged(uid, packageName);
4786 }
Sudheer Shankab1613982019-05-16 16:55:50 -07004787 }
Zimc93da802020-02-28 19:01:49 +00004788 } finally {
4789 Binder.restoreCallingIdentity(token);
Sudheer Shankab1613982019-05-16 16:55:50 -07004790 }
4791 }
Svet Ganov6ee871e2015-07-10 14:29:33 -07004792 }
Jeff Sharkeyfa23c5a2011-08-09 21:44:24 -07004793}