blob: 396b9772fd12f13600285500366e09a44e7d97d3 [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;
Jeff Sharkey6fd69942019-03-26 17:53:35 -060027import static android.app.AppOpsManager.OP_READ_EXTERNAL_STORAGE;
Sudheer Shanka3a0df3b2018-12-12 12:43:43 -080028import static android.app.AppOpsManager.OP_REQUEST_INSTALL_PACKAGES;
Jeff Sharkey6fd69942019-03-26 17:53:35 -060029import static android.app.AppOpsManager.OP_WRITE_EXTERNAL_STORAGE;
Sudheer Shanka3a0df3b2018-12-12 12:43:43 -080030import static android.content.pm.PackageManager.PERMISSION_GRANTED;
Jeff Sharkey39466322018-12-05 19:19:52 -070031import static android.os.ParcelFileDescriptor.MODE_READ_WRITE;
Jeff Sharkey0095a822018-02-15 13:06:53 -070032import static android.os.storage.OnObbStateChangeListener.ERROR_ALREADY_MOUNTED;
33import static android.os.storage.OnObbStateChangeListener.ERROR_COULD_NOT_MOUNT;
34import static android.os.storage.OnObbStateChangeListener.ERROR_COULD_NOT_UNMOUNT;
35import static android.os.storage.OnObbStateChangeListener.ERROR_INTERNAL;
36import static android.os.storage.OnObbStateChangeListener.ERROR_NOT_MOUNTED;
37import static android.os.storage.OnObbStateChangeListener.ERROR_PERMISSION_DENIED;
38import static android.os.storage.OnObbStateChangeListener.MOUNTED;
39import static android.os.storage.OnObbStateChangeListener.UNMOUNTED;
Jeff Sharkey5790af02018-08-13 17:42:54 -060040
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -070041import static com.android.internal.util.XmlUtils.readIntAttribute;
Jeff Sharkeye8a4b662015-06-27 15:43:45 -070042import static com.android.internal.util.XmlUtils.readLongAttribute;
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -070043import static com.android.internal.util.XmlUtils.readStringAttribute;
44import static com.android.internal.util.XmlUtils.writeIntAttribute;
Jeff Sharkeye8a4b662015-06-27 15:43:45 -070045import static com.android.internal.util.XmlUtils.writeLongAttribute;
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -070046import static com.android.internal.util.XmlUtils.writeStringAttribute;
Jeff Sharkey5790af02018-08-13 17:42:54 -060047
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -070048import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT;
49import static org.xmlpull.v1.XmlPullParser.START_TAG;
50
Jason parks8888c592011-01-20 22:46:41 -060051import android.Manifest;
Jeff Sharkeyef10ee02015-07-05 14:17:27 -070052import android.annotation.Nullable;
Xiaohui Chen621b3fc2015-10-02 14:41:42 -070053import android.app.ActivityManager;
Martijn Coenen7084c6a2019-11-22 16:32:09 +010054import android.app.ActivityManagerInternal;
Jeff Sharkey2d8b4e82013-09-17 17:30:33 -070055import android.app.AppOpsManager;
Jeff Sharkey14cbe522015-07-08 14:06:37 -070056import android.app.IActivityManager;
Jeff Sharkey9765e442017-12-14 22:15:14 -070057import android.app.KeyguardManager;
Pavel Grafovce72ef02018-01-10 17:14:11 +000058import android.app.admin.SecurityLog;
Jeff Sharkey9bed0702017-01-23 20:37:05 -070059import android.app.usage.StorageStatsManager;
Jeff Sharkeybcd262d2015-06-10 09:41:17 -070060import android.content.BroadcastReceiver;
Jeff Sharkeyb0c363b22018-12-15 11:53:03 -070061import android.content.ContentResolver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080062import android.content.Context;
63import android.content.Intent;
Jeff Sharkeybcd262d2015-06-10 09:41:17 -070064import android.content.IntentFilter;
Nandana Duttdc15bb42020-01-03 16:43:46 +000065import android.content.pm.ApplicationInfo;
Sudheer Shanka3a0df3b2018-12-12 12:43:43 -080066import android.content.pm.IPackageManager;
Jeff Sharkey275e3e42015-04-24 16:10:32 -070067import android.content.pm.IPackageMoveObserver;
68import android.content.pm.PackageManager;
Sudheer Shanka0a541a52018-07-31 13:21:11 -070069import android.content.pm.PackageManagerInternal;
Jeff Sharkey14cbe522015-07-08 14:06:37 -070070import android.content.pm.ProviderInfo;
Jeff Sharkeybcd262d2015-06-10 09:41:17 -070071import android.content.pm.UserInfo;
Elliott Hughesf839b4f2014-09-26 12:30:47 -070072import android.content.res.Configuration;
Kenny Root02c87302010-07-01 08:10:18 -070073import android.content.res.ObbInfo;
Daniel Colascione766b6322018-01-08 19:10:36 -080074import android.database.ContentObserver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080075import android.net.Uri;
Kenny Root02c87302010-07-01 08:10:18 -070076import android.os.Binder;
Jeff Sharkey4c099d02015-05-15 13:45:00 -070077import android.os.DropBoxManager;
Kenny Roota02b8b02010-08-05 16:14:17 -070078import android.os.Environment;
Suchi Amalapurapuc42e29e2010-02-22 16:03:53 -080079import android.os.Handler;
Dianne Hackbornefa92b22013-05-03 14:11:43 -070080import android.os.HandlerThread;
Kenny Roota02b8b02010-08-05 16:14:17 -070081import android.os.IBinder;
Jin Qian12690d52017-10-13 18:17:04 -070082import android.os.IStoraged;
Jeff Sharkey1019de92017-09-06 13:47:03 -060083import android.os.IVold;
Jeff Sharkey8058fe62017-09-13 11:50:33 -060084import android.os.IVoldListener;
Zim95eca1d2019-11-15 18:03:00 +000085import android.os.IVoldMountCallback;
Jeff Sharkeyb302c542017-09-15 12:57:59 -060086import android.os.IVoldTaskListener;
Daniel Sandler5f27ef42010-03-16 15:42:02 -040087import android.os.Looper;
Suchi Amalapurapuc42e29e2010-02-22 16:03:53 -080088import android.os.Message;
Daichi Hirono9e8d9e22015-11-13 14:37:00 +090089import android.os.ParcelFileDescriptor;
Jeff Sharkey500ce9e2017-02-12 02:39:24 -070090import android.os.ParcelableException;
Jeff Sharkeyb302c542017-09-15 12:57:59 -060091import android.os.PersistableBundle;
Jeff Sharkeyce14cd02015-12-07 15:35:42 -070092import android.os.PowerManager;
Jeff Sharkey9527b222015-06-24 15:24:48 -070093import android.os.Process;
Jeff Sharkey7151a9a2015-04-04 15:22:37 -070094import android.os.RemoteCallbackList;
San Mehat4270e1e2010-01-29 05:32:19 -080095import android.os.RemoteException;
Suchi Amalapurapufd3530f2010-01-18 00:15:59 -080096import android.os.ServiceManager;
Paul Crowleyfc0b5192018-07-02 13:58:10 -070097import android.os.ServiceSpecificException;
Jeff Sharkeyedcdaf62015-07-09 09:45:36 -070098import android.os.SystemClock;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080099import android.os.SystemProperties;
Dianne Hackbornf02b60a2012-08-16 10:48:27 -0700100import android.os.UserHandle;
Emily Bernier92aa5a22014-07-07 10:11:48 -0400101import android.os.UserManager;
Sudheer Shankab1613982019-05-16 16:55:50 -0700102import android.os.UserManagerInternal;
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -0700103import android.os.storage.DiskInfo;
Kenny Roota02b8b02010-08-05 16:14:17 -0700104import android.os.storage.IObbActionListener;
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -0700105import android.os.storage.IStorageEventListener;
Sudheer Shanka2250d562016-11-07 15:41:02 -0800106import android.os.storage.IStorageManager;
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -0700107import android.os.storage.IStorageShutdownObserver;
Kenny Rootaf9d6672010-10-08 09:21:39 -0700108import android.os.storage.OnObbStateChangeListener;
Paul Lawrence46791e72014-04-03 09:10:26 -0700109import android.os.storage.StorageManager;
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -0700110import android.os.storage.StorageManagerInternal;
Mike Lockwood2f6a3882011-05-09 19:08:06 -0700111import android.os.storage.StorageVolume;
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -0700112import android.os.storage.VolumeInfo;
Jeff Sharkeyb36586a2015-04-27 08:42:28 -0700113import android.os.storage.VolumeRecord;
Jeff Sharkey5d0c55c2019-01-24 14:32:31 -0700114import android.provider.DeviceConfig;
Martijn Coenen496ac002020-01-08 14:55:53 +0100115import android.provider.Downloads;
Jeff Sharkey14cbe522015-07-08 14:06:37 -0700116import android.provider.MediaStore;
Jeff Sharkeye8a4b662015-06-27 15:43:45 -0700117import android.provider.Settings;
Inseob Kimc1246e62018-11-08 13:13:54 +0900118import android.sysprop.VoldProperties;
Jason parksf7b3cd42011-01-27 09:28:25 -0600119import android.text.TextUtils;
Jeff Sharkey1783f142015-04-17 10:52:51 -0700120import android.text.format.DateUtils;
Jeff Sharkey48877892015-03-18 11:27:19 -0700121import android.util.ArrayMap;
Jeff Sharkey04b4ba12019-12-15 22:42:42 -0700122import android.util.ArraySet;
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700123import android.util.AtomicFile;
Jeff Sharkey9f2dc052018-01-07 16:47:31 -0700124import android.util.DataUnit;
Abhijeet Kaurb9847712019-11-19 16:35:47 +0000125import android.util.FeatureFlagUtils;
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -0700126import android.util.Log;
Felipe Leme281389a2016-10-10 17:12:20 -0700127import android.util.Pair;
San Mehata5078592010-03-25 09:36:54 -0700128import android.util.Slog;
Jeff Sharkeye8a4b662015-06-27 15:43:45 -0700129import android.util.TimeUtils;
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700130import android.util.Xml;
Jeff Sharkey48877892015-03-18 11:27:19 -0700131
Jeff Sharkey8b2c3a142012-11-12 11:45:05 -0800132import com.android.internal.annotations.GuardedBy;
Sudheer Shankaff971bc2018-12-13 17:39:59 -0800133import com.android.internal.app.IAppOpsCallback;
Sudheer Shanka3a0df3b2018-12-12 12:43:43 -0800134import com.android.internal.app.IAppOpsService;
Daichi Hirono9fb00182016-11-08 14:12:17 +0900135import com.android.internal.os.AppFuseMount;
Jeff Sharkey1019de92017-09-06 13:47:03 -0600136import com.android.internal.os.BackgroundThread;
Daichi Hirono812c95d2017-02-08 16:20:20 +0900137import com.android.internal.os.FuseUnavailableMountException;
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700138import com.android.internal.os.SomeArgs;
Jeff Sharkey9527b222015-06-24 15:24:48 -0700139import com.android.internal.os.Zygote;
Jeff Sharkey48877892015-03-18 11:27:19 -0700140import com.android.internal.util.ArrayUtils;
Jeff Sharkey11697f52018-12-13 10:14:42 -0700141import com.android.internal.util.CollectionUtils;
Jeff Sharkeyfe9a53b2017-03-31 14:08:23 -0600142import com.android.internal.util.DumpUtils;
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700143import com.android.internal.util.FastXmlSerializer;
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -0800144import com.android.internal.util.HexDump;
Jeff Sharkey5aca2b82013-10-16 16:21:54 -0700145import com.android.internal.util.IndentingPrintWriter;
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700146import com.android.internal.util.Preconditions;
Jeff Sharkeyb9fe5372015-12-03 15:23:08 -0700147import com.android.internal.widget.LockPatternUtils;
Ricky Wai4482ab52019-12-10 19:08:18 +0000148import com.android.server.pm.Installer;
Daichi Hirono9fb00182016-11-08 14:12:17 +0900149import com.android.server.storage.AppFuseBridge;
Zim42f1e9f2019-08-15 17:35:00 +0100150import com.android.server.storage.StorageSessionController;
Zim17be6f92019-09-25 14:37:55 +0100151import com.android.server.storage.StorageSessionController.ExternalStorageServiceException;
Wale Ogunwale9e4f3e02018-05-17 09:35:39 -0700152import com.android.server.wm.ActivityTaskManagerInternal;
153import com.android.server.wm.ActivityTaskManagerInternal.ScreenObserver;
Jeff Sharkey5217cac2015-12-20 15:34:01 -0700154
Jeff Sharkey5790af02018-08-13 17:42:54 -0600155import libcore.io.IoUtils;
156import libcore.util.EmptyArray;
157
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700158import org.xmlpull.v1.XmlPullParser;
159import org.xmlpull.v1.XmlPullParserException;
160import org.xmlpull.v1.XmlSerializer;
161
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700162import java.io.File;
Kenny Root38cf8862010-09-26 14:18:51 -0700163import java.io.FileDescriptor;
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700164import java.io.FileInputStream;
165import java.io.FileNotFoundException;
Christopher Tate7265abe2014-11-21 13:54:45 -0800166import java.io.FileOutputStream;
Kenny Root05105f72010-09-22 17:29:43 -0700167import java.io.IOException;
Kenny Root38cf8862010-09-26 14:18:51 -0700168import java.io.PrintWriter;
Kenny Root3b1abba2010-10-13 15:00:07 -0700169import java.math.BigInteger;
Paul Lawrence8e397362014-01-27 15:22:30 -0800170import java.nio.charset.StandardCharsets;
Jeff Sharkey0095a822018-02-15 13:06:53 -0700171import java.security.GeneralSecurityException;
Kenny Root3b1abba2010-10-13 15:00:07 -0700172import java.security.spec.KeySpec;
San Mehat22dd86e2010-01-12 12:21:18 -0800173import java.util.ArrayList;
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -0800174import java.util.Arrays;
Kenny Roota02b8b02010-08-05 16:14:17 -0700175import java.util.HashMap;
Kenny Root38cf8862010-09-26 14:18:51 -0700176import java.util.Iterator;
Kenny Roota02b8b02010-08-05 16:14:17 -0700177import java.util.LinkedList;
178import java.util.List;
Elliott Hughesf839b4f2014-09-26 12:30:47 -0700179import java.util.Locale;
Kenny Roota02b8b02010-08-05 16:14:17 -0700180import java.util.Map;
Kenny Root38cf8862010-09-26 14:18:51 -0700181import java.util.Map.Entry;
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700182import java.util.Objects;
Svet Ganov6ee871e2015-07-10 14:29:33 -0700183import java.util.concurrent.CopyOnWriteArrayList;
Kenny Root51a573c2012-05-17 13:30:28 -0700184import java.util.concurrent.CountDownLatch;
185import java.util.concurrent.TimeUnit;
Jeff Sharkeyedcdaf62015-07-09 09:45:36 -0700186import java.util.concurrent.TimeoutException;
Martijn Coenen9fd2b642019-12-24 13:04:36 +0100187import java.util.regex.Matcher;
188import java.util.regex.Pattern;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800189
Kenny Root3b1abba2010-10-13 15:00:07 -0700190import javax.crypto.SecretKey;
191import javax.crypto.SecretKeyFactory;
192import javax.crypto.spec.PBEKeySpec;
193
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800194/**
Jeff Sharkey48877892015-03-18 11:27:19 -0700195 * Service responsible for various storage media. Connects to {@code vold} to
196 * watch for and manage dynamically added storage, such as SD cards and USB mass
197 * storage. Also decides how storage should be presented to users on the device.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800198 */
Jeff Sharkey9765e442017-12-14 22:15:14 -0700199class StorageManagerService extends IStorageManager.Stub
200 implements Watchdog.Monitor, ScreenObserver {
Jason parks5af0b912010-11-29 09:05:25 -0600201
Christopher Tated417d622013-08-19 16:14:25 -0700202 // Static direct instance pointer for the tightly-coupled idle service to use
Sudheer Shanka2250d562016-11-07 15:41:02 -0800203 static StorageManagerService sSelf = null;
Christopher Tated417d622013-08-19 16:14:25 -0700204
Daniel Colascione766b6322018-01-08 19:10:36 -0800205 /* Read during boot to decide whether to enable zram when available */
206 private static final String ZRAM_ENABLED_PROPERTY =
Sudheer Shanka0a541a52018-07-31 13:21:11 -0700207 "persist.sys.zram_enabled";
208
Jeff Sharkey10ec9d82018-11-28 14:52:45 -0700209 private static final boolean ENABLE_ISOLATED_STORAGE = StorageManager.hasIsolatedStorage();
Sudheer Shanka0a541a52018-07-31 13:21:11 -0700210
Matt Pape19ea8a62019-03-18 10:38:25 -0700211 /**
212 * If {@code 1}, enables the isolated storage feature. If {@code -1},
213 * disables the isolated storage feature. If {@code 0}, uses the default
214 * value from the build system.
215 */
216 private static final String ISOLATED_STORAGE_ENABLED = "isolated_storage_enabled";
217
shafikb2992b62019-10-01 15:31:02 +0100218 /**
219 * If {@code 1}, enables FuseDaemon to intercept file system ops. If {@code -1},
220 * disables FuseDaemon. If {@code 0}, uses the default value from the build system.
221 */
222 private static final String FUSE_ENABLED = "fuse_enabled";
223
Jeff Sharkey56e62932015-03-21 20:41:00 -0700224 public static class Lifecycle extends SystemService {
Sudheer Shanka2250d562016-11-07 15:41:02 -0800225 private StorageManagerService mStorageManagerService;
Jeff Sharkey56e62932015-03-21 20:41:00 -0700226
227 public Lifecycle(Context context) {
228 super(context);
229 }
230
231 @Override
232 public void onStart() {
Sudheer Shanka2250d562016-11-07 15:41:02 -0800233 mStorageManagerService = new StorageManagerService(getContext());
234 publishBinderService("mount", mStorageManagerService);
235 mStorageManagerService.start();
Jeff Sharkey56e62932015-03-21 20:41:00 -0700236 }
237
238 @Override
239 public void onBootPhase(int phase) {
Jeff Sharkey11697f52018-12-13 10:14:42 -0700240 if (phase == SystemService.PHASE_SYSTEM_SERVICES_READY) {
241 mStorageManagerService.servicesReady();
242 } else if (phase == SystemService.PHASE_ACTIVITY_MANAGER_READY) {
Sudheer Shanka2250d562016-11-07 15:41:02 -0800243 mStorageManagerService.systemReady();
Yasuhiro Matsuda87a38b52015-07-24 22:10:16 +0900244 } else if (phase == SystemService.PHASE_BOOT_COMPLETED) {
Sudheer Shanka2250d562016-11-07 15:41:02 -0800245 mStorageManagerService.bootCompleted();
Jeff Sharkey56e62932015-03-21 20:41:00 -0700246 }
247 }
Jeff Sharkey48877892015-03-18 11:27:19 -0700248
249 @Override
Jeff Sharkeyab15c392016-05-05 11:45:01 -0600250 public void onSwitchUser(int userHandle) {
Sudheer Shanka2250d562016-11-07 15:41:02 -0800251 mStorageManagerService.mCurrentUserId = userHandle;
Jeff Sharkeyab15c392016-05-05 11:45:01 -0600252 }
253
254 @Override
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700255 public void onUnlockUser(int userHandle) {
Sudheer Shanka2250d562016-11-07 15:41:02 -0800256 mStorageManagerService.onUnlockUser(userHandle);
Jeff Sharkey48877892015-03-18 11:27:19 -0700257 }
258
259 @Override
260 public void onCleanupUser(int userHandle) {
Sudheer Shanka2250d562016-11-07 15:41:02 -0800261 mStorageManagerService.onCleanupUser(userHandle);
Jeff Sharkey48877892015-03-18 11:27:19 -0700262 }
Martijn Coenen7084c6a2019-11-22 16:32:09 +0100263
264 @Override
265 public void onStopUser(int userHandle) {
266 mStorageManagerService.onStopUser(userHandle);
267 }
Jeff Sharkey56e62932015-03-21 20:41:00 -0700268 }
269
Dianne Hackborn40e9f292012-11-27 19:12:23 -0800270 private static final boolean DEBUG_EVENTS = false;
Kenny Rootb7db2722011-01-25 16:39:35 -0800271 private static final boolean DEBUG_OBB = false;
Kenny Root02c87302010-07-01 08:10:18 -0700272
Jeff Sharkeyc3c72872018-06-06 15:35:53 -0600273 /**
274 * We now talk to vold over Binder, and it has its own internal lock to
275 * serialize certain calls. All long-running operations have been migrated
276 * to be async with callbacks, so we want watchdog to fire if vold wedges.
277 */
278 private static final boolean WATCHDOG_ENABLE = true;
Kenny Root07714d42011-08-17 17:49:28 -0700279
Jeff Sharkey00455bf2016-11-04 14:45:24 -0600280 /**
281 * Our goal is for all Android devices to be usable as development devices,
282 * which includes the new Direct Boot mode added in N. For devices that
283 * don't have native FBE support, we offer an emulation mode for developer
284 * testing purposes, but if it's prohibitively difficult to support this
285 * mode, it can be disabled for specific products using this flag.
286 */
287 private static final boolean EMULATE_FBE_SUPPORTED = true;
288
Sudheer Shanka2250d562016-11-07 15:41:02 -0800289 private static final String TAG = "StorageManagerService";
Jeff Sharkey6fd69942019-03-26 17:53:35 -0600290 private static final boolean LOCAL_LOGV = Log.isLoggable(TAG, Log.VERBOSE);
Jeff Sharkeye8a4b662015-06-27 15:43:45 -0700291
Jeff Sharkey9756d752015-05-14 21:07:42 -0700292 private static final String TAG_STORAGE_BENCHMARK = "storage_benchmark";
Jeff Sharkeye8a4b662015-06-27 15:43:45 -0700293 private static final String TAG_STORAGE_TRIM = "storage_trim";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800294
Jeff Sharkey275e3e42015-04-24 16:10:32 -0700295 /** Magic value sent by MoveTask.cpp */
296 private static final int MOVE_STATUS_COPY_FINISHED = 82;
297
Jeff Sharkey620b32b2015-04-23 19:36:02 -0700298 private static final int VERSION_INIT = 1;
299 private static final int VERSION_ADD_PRIMARY = 2;
Jeff Sharkeyfced5342015-05-10 14:53:34 -0700300 private static final int VERSION_FIX_PRIMARY = 3;
Jeff Sharkey620b32b2015-04-23 19:36:02 -0700301
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700302 private static final String TAG_VOLUMES = "volumes";
Jeff Sharkey620b32b2015-04-23 19:36:02 -0700303 private static final String ATTR_VERSION = "version";
304 private static final String ATTR_PRIMARY_STORAGE_UUID = "primaryStorageUuid";
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700305 private static final String TAG_VOLUME = "volume";
306 private static final String ATTR_TYPE = "type";
307 private static final String ATTR_FS_UUID = "fsUuid";
Jeff Sharkey5cc0df22015-06-17 19:44:05 -0700308 private static final String ATTR_PART_GUID = "partGuid";
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700309 private static final String ATTR_NICKNAME = "nickname";
310 private static final String ATTR_USER_FLAGS = "userFlags";
Jeff Sharkeye8a4b662015-06-27 15:43:45 -0700311 private static final String ATTR_CREATED_MILLIS = "createdMillis";
Jeff Sharkey3811f352019-05-14 11:54:36 -0600312 private static final String ATTR_LAST_SEEN_MILLIS = "lastSeenMillis";
Jeff Sharkeye8a4b662015-06-27 15:43:45 -0700313 private static final String ATTR_LAST_TRIM_MILLIS = "lastTrimMillis";
314 private static final String ATTR_LAST_BENCH_MILLIS = "lastBenchMillis";
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700315
Philip P. Moltmannc94ba822019-03-04 16:48:22 -0800316 private static final String[] ALL_STORAGE_PERMISSIONS = {
317 Manifest.permission.READ_EXTERNAL_STORAGE,
Philip P. Moltmann129a0b02019-03-27 12:24:45 -0700318 Manifest.permission.WRITE_EXTERNAL_STORAGE
Philip P. Moltmannc94ba822019-03-04 16:48:22 -0800319 };
320
Jeff Sharkeyb36586a2015-04-27 08:42:28 -0700321 private final AtomicFile mSettingsFile;
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700322
Jeff Sharkey48877892015-03-18 11:27:19 -0700323 /**
324 * <em>Never</em> hold the lock while performing downcalls into vold, since
325 * unsolicited events can suddenly appear to update data structures.
326 */
Jeff Sharkey5f3e9342017-03-13 14:53:11 -0600327 private final Object mLock = LockGuard.installNewLock(LockGuard.INDEX_STORAGE);
Jeff Sharkey48877892015-03-18 11:27:19 -0700328
Sudheer Shanka0a541a52018-07-31 13:21:11 -0700329 /**
330 * Similar to {@link #mLock}, never hold this lock while performing downcalls into vold.
331 * Also, never hold this while calling into PackageManagerService since it is used in callbacks
332 * from PackageManagerService.
333 *
334 * If both {@link #mLock} and this lock need to be held, {@link #mLock} should be acquired
335 * before this.
336 *
337 * Use -PL suffix for methods that need to called with this lock held.
338 */
339 private final Object mPackagesLock = new Object();
340
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700341 /** Set of users that we know are unlocked. */
Jeff Sharkey48877892015-03-18 11:27:19 -0700342 @GuardedBy("mLock")
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700343 private int[] mLocalUnlockedUsers = EmptyArray.INT;
344 /** Set of users that system knows are unlocked. */
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -0800345 @GuardedBy("mLock")
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700346 private int[] mSystemUnlockedUsers = EmptyArray.INT;
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700347
348 /** Map from disk ID to disk */
Jeff Sharkey48877892015-03-18 11:27:19 -0700349 @GuardedBy("mLock")
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -0700350 private ArrayMap<String, DiskInfo> mDisks = new ArrayMap<>();
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700351 /** Map from volume ID to disk */
Jeff Sharkey48877892015-03-18 11:27:19 -0700352 @GuardedBy("mLock")
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700353 private final ArrayMap<String, VolumeInfo> mVolumes = new ArrayMap<>();
Jeff Sharkey48877892015-03-18 11:27:19 -0700354
Jeff Sharkeyb36586a2015-04-27 08:42:28 -0700355 /** Map from UUID to record */
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700356 @GuardedBy("mLock")
Jeff Sharkeyb36586a2015-04-27 08:42:28 -0700357 private ArrayMap<String, VolumeRecord> mRecords = new ArrayMap<>();
Jeff Sharkey620b32b2015-04-23 19:36:02 -0700358 @GuardedBy("mLock")
359 private String mPrimaryStorageUuid;
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700360
Jeff Sharkeyeba260d2015-04-19 14:35:16 -0700361 /** Map from disk ID to latches */
362 @GuardedBy("mLock")
363 private ArrayMap<String, CountDownLatch> mDiskScanLatches = new ArrayMap<>();
364
Jeff Sharkey275e3e42015-04-24 16:10:32 -0700365 @GuardedBy("mLock")
366 private IPackageMoveObserver mMoveCallback;
367 @GuardedBy("mLock")
368 private String mMoveTargetUuid;
369
Martijn Coenen44db1ac2019-12-03 16:06:19 +0100370 private volatile int mMediaStoreAuthorityAppId = -1;
Zim74a9bba2019-09-03 20:49:13 +0100371
Martijn Coenen496ac002020-01-08 14:55:53 +0100372 private volatile int mDownloadsAuthorityAppId = -1;
373
Jeff Sharkeyab15c392016-05-05 11:45:01 -0600374 private volatile int mCurrentUserId = UserHandle.USER_SYSTEM;
375
Ricky Wai4482ab52019-12-10 19:08:18 +0000376 private final Installer mInstaller;
377
Daichi Hirono9fb00182016-11-08 14:12:17 +0900378 /** Holding lock for AppFuse business */
379 private final Object mAppFuseLock = new Object();
380
381 @GuardedBy("mAppFuseLock")
382 private int mNextAppFuseName = 0;
383
384 @GuardedBy("mAppFuseLock")
Daichi Hironoe56740d2017-02-02 13:56:45 +0900385 private AppFuseBridge mAppFuseBridge = null;
Daichi Hirono9fb00182016-11-08 14:12:17 +0900386
Martijn Coenen9fd2b642019-12-24 13:04:36 +0100387 /** Matches known application dir paths. The first group contains the generic part of the path,
388 * the second group contains the user id (or null if it's a public volume without users), the
389 * third group contains the package name, and the fourth group the remainder of the path.
390 */
391 public static final Pattern KNOWN_APP_DIR_PATHS = Pattern.compile(
392 "(?i)(^/storage/[^/]+/(?:([0-9]+)/)?Android/(?:data|media|obb|sandbox)/)([^/]+)(/.*)?");
393
394
Jeff Sharkeyef10ee02015-07-05 14:17:27 -0700395 private VolumeInfo findVolumeByIdOrThrow(String id) {
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700396 synchronized (mLock) {
397 final VolumeInfo vol = mVolumes.get(id);
398 if (vol != null) {
399 return vol;
400 }
401 }
402 throw new IllegalArgumentException("No volume found for ID " + id);
403 }
404
Jeff Sharkeyef10ee02015-07-05 14:17:27 -0700405 private String findVolumeIdForPathOrThrow(String path) {
Jeff Sharkey48877892015-03-18 11:27:19 -0700406 synchronized (mLock) {
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -0700407 for (int i = 0; i < mVolumes.size(); i++) {
408 final VolumeInfo vol = mVolumes.valueAt(i);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700409 if (vol.path != null && path.startsWith(vol.path)) {
410 return vol.id;
Jeff Sharkey48877892015-03-18 11:27:19 -0700411 }
412 }
413 }
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700414 throw new IllegalArgumentException("No volume found for path " + path);
Jeff Sharkey48877892015-03-18 11:27:19 -0700415 }
416
Jeff Sharkeye8a4b662015-06-27 15:43:45 -0700417 private VolumeRecord findRecordForPath(String path) {
418 synchronized (mLock) {
419 for (int i = 0; i < mVolumes.size(); i++) {
420 final VolumeInfo vol = mVolumes.valueAt(i);
421 if (vol.path != null && path.startsWith(vol.path)) {
422 return mRecords.get(vol.fsUuid);
423 }
424 }
425 }
426 return null;
427 }
428
429 private String scrubPath(String path) {
430 if (path.startsWith(Environment.getDataDirectory().getAbsolutePath())) {
431 return "internal";
432 }
433 final VolumeRecord rec = findRecordForPath(path);
434 if (rec == null || rec.createdMillis == 0) {
435 return "unknown";
436 } else {
437 return "ext:" + (int) ((System.currentTimeMillis() - rec.createdMillis)
438 / DateUtils.WEEK_IN_MILLIS) + "w";
439 }
440 }
441
Jeff Sharkeyef10ee02015-07-05 14:17:27 -0700442 private @Nullable VolumeInfo findStorageForUuid(String volumeUuid) {
Jeff Sharkey275e3e42015-04-24 16:10:32 -0700443 final StorageManager storage = mContext.getSystemService(StorageManager.class);
444 if (Objects.equals(StorageManager.UUID_PRIVATE_INTERNAL, volumeUuid)) {
Zim17be6f92019-09-25 14:37:55 +0100445 return storage.findVolumeById(VolumeInfo.ID_EMULATED_INTERNAL + ";" + 0);
Jeff Sharkey275e3e42015-04-24 16:10:32 -0700446 } else if (Objects.equals(StorageManager.UUID_PRIMARY_PHYSICAL, volumeUuid)) {
447 return storage.getPrimaryPhysicalVolume();
448 } else {
449 return storage.findEmulatedForPrivate(storage.findVolumeByUuid(volumeUuid));
450 }
451 }
452
Jeff Sharkeye8a4b662015-06-27 15:43:45 -0700453 private boolean shouldBenchmark() {
454 final long benchInterval = Settings.Global.getLong(mContext.getContentResolver(),
455 Settings.Global.STORAGE_BENCHMARK_INTERVAL, DateUtils.WEEK_IN_MILLIS);
Jeff Sharkeye83d8a92015-09-09 14:53:38 -0700456 if (benchInterval == -1) {
457 return false;
458 } else if (benchInterval == 0) {
459 return true;
460 }
461
Jeff Sharkeye8a4b662015-06-27 15:43:45 -0700462 synchronized (mLock) {
463 for (int i = 0; i < mVolumes.size(); i++) {
464 final VolumeInfo vol = mVolumes.valueAt(i);
465 final VolumeRecord rec = mRecords.get(vol.fsUuid);
Jeff Sharkeye83d8a92015-09-09 14:53:38 -0700466 if (vol.isMountedWritable() && rec != null) {
Jeff Sharkeye8a4b662015-06-27 15:43:45 -0700467 final long benchAge = System.currentTimeMillis() - rec.lastBenchMillis;
468 if (benchAge >= benchInterval) {
469 return true;
470 }
471 }
472 }
473 return false;
474 }
475 }
476
Jeff Sharkeyeba260d2015-04-19 14:35:16 -0700477 private CountDownLatch findOrCreateDiskScanLatch(String diskId) {
478 synchronized (mLock) {
479 CountDownLatch latch = mDiskScanLatches.get(diskId);
480 if (latch == null) {
481 latch = new CountDownLatch(1);
482 mDiskScanLatches.put(diskId, latch);
483 }
484 return latch;
485 }
486 }
487
Paul Lawrence8e397362014-01-27 15:22:30 -0800488 /** List of crypto types.
489 * These must match CRYPT_TYPE_XXX in cryptfs.h AND their
490 * corresponding commands in CommandListener.cpp */
491 public static final String[] CRYPTO_TYPES
492 = { "password", "default", "pattern", "pin" };
493
Brian Carlstrom7395a8a2014-04-28 22:11:01 -0700494 private final Context mContext;
Jeff Sharkey5d0c55c2019-01-24 14:32:31 -0700495 private final ContentResolver mResolver;
Jeff Sharkeycd575992016-03-29 14:12:49 -0600496
Jeff Sharkey1019de92017-09-06 13:47:03 -0600497 private volatile IVold mVold;
Jin Qian12690d52017-10-13 18:17:04 -0700498 private volatile IStoraged mStoraged;
Jeff Sharkey1019de92017-09-06 13:47:03 -0600499
Yasuhiro Matsuda87a38b52015-07-24 22:10:16 +0900500 private volatile boolean mBootCompleted = false;
Jeff Sharkey48877892015-03-18 11:27:19 -0700501 private volatile boolean mDaemonConnected = false;
Jeff Sharkey9765e442017-12-14 22:15:14 -0700502 private volatile boolean mSecureKeyguardShowing = true;
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700503
Sudheer Shanka0a541a52018-07-31 13:21:11 -0700504 private PackageManagerInternal mPmInternal;
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700505
Sudheer Shanka3a0df3b2018-12-12 12:43:43 -0800506 private IPackageManager mIPackageManager;
507 private IAppOpsService mIAppOpsService;
508
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700509 private final Callbacks mCallbacks;
Jeff Sharkeyb9fe5372015-12-03 15:23:08 -0700510 private final LockPatternUtils mLockPatternUtils;
Jeff Sharkey48877892015-03-18 11:27:19 -0700511
San Mehat6cdd9c02010-02-09 14:45:20 -0800512 /**
Kenny Root3b1abba2010-10-13 15:00:07 -0700513 * The size of the crypto algorithm key in bits for OBB files. Currently
514 * Twofish is used which takes 128-bit keys.
515 */
516 private static final int CRYPTO_ALGORITHM_KEY_SIZE = 128;
517
518 /**
519 * The number of times to run SHA1 in the PBKDF2 function for OBB files.
520 * 1024 is reasonably secure and not too slow.
521 */
522 private static final int PBKDF2_HASH_ROUNDS = 1024;
523
524 /**
Kenny Roota02b8b02010-08-05 16:14:17 -0700525 * Mounted OBB tracking information. Used to track the current state of all
526 * OBBs.
Kenny Root02c87302010-07-01 08:10:18 -0700527 */
Kenny Root735de3b2010-09-30 14:11:39 -0700528 final private Map<IBinder, List<ObbState>> mObbMounts = new HashMap<IBinder, List<ObbState>>();
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700529
530 /** Map from raw paths to {@link ObbState}. */
Kenny Roota02b8b02010-08-05 16:14:17 -0700531 final private Map<String, ObbState> mObbPathToStateMap = new HashMap<String, ObbState>();
532
Svet Ganov6ee871e2015-07-10 14:29:33 -0700533 // Not guarded by a lock.
Sudheer Shanka2250d562016-11-07 15:41:02 -0800534 private final StorageManagerInternalImpl mStorageManagerInternal
535 = new StorageManagerInternalImpl();
Svet Ganov6ee871e2015-07-10 14:29:33 -0700536
Zim42f1e9f2019-08-15 17:35:00 +0100537 // Not guarded by a lock.
538 private final StorageSessionController mStorageSessionController;
539
Zim17be6f92019-09-25 14:37:55 +0100540 private final boolean mIsFuseEnabled;
541
Kenny Roota02b8b02010-08-05 16:14:17 -0700542 class ObbState implements IBinder.DeathRecipient {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700543 public ObbState(String rawPath, String canonicalPath, int callingUid,
Jeff Sharkey41cd6812017-09-11 10:32:17 -0600544 IObbActionListener token, int nonce, String volId) {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700545 this.rawPath = rawPath;
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700546 this.canonicalPath = canonicalPath;
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700547 this.ownerGid = UserHandle.getSharedAppGid(callingUid);
Kenny Rootaf9d6672010-10-08 09:21:39 -0700548 this.token = token;
549 this.nonce = nonce;
Jeff Sharkey41cd6812017-09-11 10:32:17 -0600550 this.volId = volId;
Kenny Roota02b8b02010-08-05 16:14:17 -0700551 }
552
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700553 final String rawPath;
554 final String canonicalPath;
Kenny Roota02b8b02010-08-05 16:14:17 -0700555
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700556 final int ownerGid;
Kenny Roota02b8b02010-08-05 16:14:17 -0700557
Kenny Rootaf9d6672010-10-08 09:21:39 -0700558 // Token of remote Binder caller
559 final IObbActionListener token;
560
561 // Identifier to pass back to the token
562 final int nonce;
Kenny Roota02b8b02010-08-05 16:14:17 -0700563
Jeff Sharkey41cd6812017-09-11 10:32:17 -0600564 String volId;
565
Kenny Root735de3b2010-09-30 14:11:39 -0700566 public IBinder getBinder() {
567 return token.asBinder();
568 }
569
Kenny Roota02b8b02010-08-05 16:14:17 -0700570 @Override
571 public void binderDied() {
572 ObbAction action = new UnmountObbAction(this, true);
573 mObbActionHandler.sendMessage(mObbActionHandler.obtainMessage(OBB_RUN_ACTION, action));
Kenny Root735de3b2010-09-30 14:11:39 -0700574 }
Kenny Roota02b8b02010-08-05 16:14:17 -0700575
Kenny Root5919ac62010-10-05 09:49:40 -0700576 public void link() throws RemoteException {
577 getBinder().linkToDeath(this, 0);
578 }
579
580 public void unlink() {
Kenny Root735de3b2010-09-30 14:11:39 -0700581 getBinder().unlinkToDeath(this, 0);
Kenny Roota02b8b02010-08-05 16:14:17 -0700582 }
Kenny Root38cf8862010-09-26 14:18:51 -0700583
584 @Override
585 public String toString() {
586 StringBuilder sb = new StringBuilder("ObbState{");
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700587 sb.append("rawPath=").append(rawPath);
588 sb.append(",canonicalPath=").append(canonicalPath);
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700589 sb.append(",ownerGid=").append(ownerGid);
590 sb.append(",token=").append(token);
591 sb.append(",binder=").append(getBinder());
Jeff Sharkey41cd6812017-09-11 10:32:17 -0600592 sb.append(",volId=").append(volId);
Kenny Root38cf8862010-09-26 14:18:51 -0700593 sb.append('}');
594 return sb.toString();
595 }
Kenny Roota02b8b02010-08-05 16:14:17 -0700596 }
597
598 // OBB Action Handler
599 final private ObbActionHandler mObbActionHandler;
600
601 // OBB action handler messages
602 private static final int OBB_RUN_ACTION = 1;
Sudheer Shanka25469aa2018-08-27 15:50:23 -0700603 private static final int OBB_FLUSH_MOUNT_STATE = 2;
Kenny Root02c87302010-07-01 08:10:18 -0700604
Christopher Tate7265abe2014-11-21 13:54:45 -0800605 // Last fstrim operation tracking
606 private static final String LAST_FSTRIM_FILE = "last-fstrim";
607 private final File mLastMaintenanceFile;
608 private long mLastMaintenance;
609
Kenny Root02c87302010-07-01 08:10:18 -0700610 // Handler messages
Jeff Sharkey48877892015-03-18 11:27:19 -0700611 private static final int H_SYSTEM_READY = 1;
612 private static final int H_DAEMON_CONNECTED = 2;
613 private static final int H_SHUTDOWN = 3;
614 private static final int H_FSTRIM = 4;
615 private static final int H_VOLUME_MOUNT = 5;
616 private static final int H_VOLUME_BROADCAST = 6;
Jeff Sharkeyabc3e852015-08-03 14:41:13 -0700617 private static final int H_INTERNAL_BROADCAST = 7;
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700618 private static final int H_VOLUME_UNMOUNT = 8;
Jeff Sharkey5a9bb742015-11-03 10:15:57 -0800619 private static final int H_PARTITION_FORGET = 9;
620 private static final int H_RESET = 10;
Jin Qiana85b9912017-10-17 15:48:18 -0700621 private static final int H_RUN_IDLE_MAINT = 11;
622 private static final int H_ABORT_IDLE_MAINT = 12;
Daniel Rosenberg137aed12019-03-15 18:41:11 -0700623 private static final int H_BOOT_COMPLETED = 13;
Narayan Kamath157dd1d2019-06-12 13:06:30 +0100624 private static final int H_COMPLETE_UNLOCK_USER = 14;
Suchi Amalapurapu6ffce2e2010-03-08 14:48:40 -0800625
Sudheer Shanka2250d562016-11-07 15:41:02 -0800626 class StorageManagerServiceHandler extends Handler {
627 public StorageManagerServiceHandler(Looper looper) {
Jeff Sharkey48877892015-03-18 11:27:19 -0700628 super(looper);
Daniel Sandler5f27ef42010-03-16 15:42:02 -0400629 }
630
Jason parks5af0b912010-11-29 09:05:25 -0600631 @Override
Suchi Amalapurapuc42e29e2010-02-22 16:03:53 -0800632 public void handleMessage(Message msg) {
633 switch (msg.what) {
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700634 case H_SYSTEM_READY: {
Jeff Sharkey48877892015-03-18 11:27:19 -0700635 handleSystemReady();
636 break;
637 }
Daniel Rosenberg137aed12019-03-15 18:41:11 -0700638 case H_BOOT_COMPLETED: {
639 handleBootCompleted();
640 break;
641 }
Jeff Sharkey48877892015-03-18 11:27:19 -0700642 case H_DAEMON_CONNECTED: {
643 handleDaemonConnected();
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700644 break;
645 }
Christopher Tated417d622013-08-19 16:14:25 -0700646 case H_FSTRIM: {
Christopher Tated417d622013-08-19 16:14:25 -0700647 Slog.i(TAG, "Running fstrim idle maintenance");
Christopher Tate7265abe2014-11-21 13:54:45 -0800648
649 // Remember when we kicked it off
650 try {
651 mLastMaintenance = System.currentTimeMillis();
652 mLastMaintenanceFile.setLastModified(mLastMaintenance);
653 } catch (Exception e) {
654 Slog.e(TAG, "Unable to record last fstrim!");
655 }
656
Jeff Sharkeyb302c542017-09-15 12:57:59 -0600657 // TODO: Reintroduce shouldBenchmark() test
Jeff Sharkey7e19f532017-11-06 13:54:11 -0700658 fstrim(0, null);
Christopher Tate7265abe2014-11-21 13:54:45 -0800659
Christopher Tated417d622013-08-19 16:14:25 -0700660 // invoke the completion callback, if any
Jeff Sharkeye8a4b662015-06-27 15:43:45 -0700661 // TODO: fstrim is non-blocking, so remove this useless callback
Christopher Tated417d622013-08-19 16:14:25 -0700662 Runnable callback = (Runnable) msg.obj;
663 if (callback != null) {
664 callback.run();
665 }
666 break;
667 }
Jeff Sharkey48877892015-03-18 11:27:19 -0700668 case H_SHUTDOWN: {
Sudheer Shanka2250d562016-11-07 15:41:02 -0800669 final IStorageShutdownObserver obs = (IStorageShutdownObserver) msg.obj;
Jeff Sharkey48877892015-03-18 11:27:19 -0700670 boolean success = false;
671 try {
Jeff Sharkey54402792017-09-15 16:05:19 -0600672 mVold.shutdown();
673 success = true;
Jeff Sharkeyace874b2017-09-07 15:27:33 -0600674 } catch (Exception e) {
675 Slog.wtf(TAG, e);
Jeff Sharkey48877892015-03-18 11:27:19 -0700676 }
677 if (obs != null) {
678 try {
679 obs.onShutDownComplete(success ? 0 : -1);
Jeff Sharkeyace874b2017-09-07 15:27:33 -0600680 } catch (Exception ignored) {
Jeff Sharkey48877892015-03-18 11:27:19 -0700681 }
682 }
683 break;
684 }
685 case H_VOLUME_MOUNT: {
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -0700686 final VolumeInfo vol = (VolumeInfo) msg.obj;
Jeff Sharkey2e606d72015-07-27 14:19:54 -0700687 if (isMountDisallowed(vol)) {
688 Slog.i(TAG, "Ignoring mount " + vol.getId() + " due to policy");
689 break;
690 }
Zim42f1e9f2019-08-15 17:35:00 +0100691
Zim17be6f92019-09-25 14:37:55 +0100692 mount(vol);
Jeff Sharkey48877892015-03-18 11:27:19 -0700693 break;
694 }
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700695 case H_VOLUME_UNMOUNT: {
696 final VolumeInfo vol = (VolumeInfo) msg.obj;
Sudheer Shanka3f0645b2018-09-18 13:07:59 -0700697 unmount(vol);
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700698 break;
699 }
Jeff Sharkey48877892015-03-18 11:27:19 -0700700 case H_VOLUME_BROADCAST: {
701 final StorageVolume userVol = (StorageVolume) msg.obj;
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700702 final String envState = userVol.getState();
703 Slog.d(TAG, "Volume " + userVol.getId() + " broadcasting " + envState + " to "
Jeff Sharkey48877892015-03-18 11:27:19 -0700704 + userVol.getOwner());
705
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700706 final String action = VolumeInfo.getBroadcastForEnvironment(envState);
Jeff Sharkey48877892015-03-18 11:27:19 -0700707 if (action != null) {
708 final Intent intent = new Intent(action,
709 Uri.fromFile(userVol.getPathFile()));
710 intent.putExtra(StorageVolume.EXTRA_STORAGE_VOLUME, userVol);
Jeff Sharkey082f83b2017-03-26 14:34:47 -0600711 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT
712 | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
Jeff Sharkey48877892015-03-18 11:27:19 -0700713 mContext.sendBroadcastAsUser(intent, userVol.getOwner());
714 }
715 break;
716 }
Jeff Sharkeyabc3e852015-08-03 14:41:13 -0700717 case H_INTERNAL_BROADCAST: {
718 // Internal broadcasts aimed at system components, not for
719 // third-party apps.
720 final Intent intent = (Intent) msg.obj;
721 mContext.sendBroadcastAsUser(intent, UserHandle.ALL,
722 android.Manifest.permission.WRITE_MEDIA_STORAGE);
Jeff Sharkey5a9bb742015-11-03 10:15:57 -0800723 break;
724 }
725 case H_PARTITION_FORGET: {
Jeff Sharkeydb4b6192017-10-24 11:08:50 -0600726 final VolumeRecord rec = (VolumeRecord) msg.obj;
727 forgetPartition(rec.partGuid, rec.fsUuid);
Jeff Sharkey5a9bb742015-11-03 10:15:57 -0800728 break;
729 }
730 case H_RESET: {
Daniel Rosenberg137aed12019-03-15 18:41:11 -0700731 resetIfBootedAndConnected();
Jeff Sharkey5a9bb742015-11-03 10:15:57 -0800732 break;
Jeff Sharkeyabc3e852015-08-03 14:41:13 -0700733 }
Jin Qiana85b9912017-10-17 15:48:18 -0700734 case H_RUN_IDLE_MAINT: {
735 Slog.i(TAG, "Running idle maintenance");
736 runIdleMaint((Runnable)msg.obj);
737 break;
738 }
739 case H_ABORT_IDLE_MAINT: {
740 Slog.i(TAG, "Aborting idle maintenance");
741 abortIdleMaint((Runnable)msg.obj);
742 break;
743 }
Narayan Kamath157dd1d2019-06-12 13:06:30 +0100744 case H_COMPLETE_UNLOCK_USER: {
745 completeUnlockUser((int) msg.obj);
746 break;
747 }
Suchi Amalapurapuc42e29e2010-02-22 16:03:53 -0800748 }
749 }
Jeff Sharkey48877892015-03-18 11:27:19 -0700750 }
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700751
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700752 private final Handler mHandler;
Suchi Amalapurapuc42e29e2010-02-22 16:03:53 -0800753
Jeff Sharkeybcd262d2015-06-10 09:41:17 -0700754 private BroadcastReceiver mUserReceiver = new BroadcastReceiver() {
755 @Override
756 public void onReceive(Context context, Intent intent) {
757 final String action = intent.getAction();
758 final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700759 Preconditions.checkArgument(userId >= 0);
Jeff Sharkeybcd262d2015-06-10 09:41:17 -0700760
761 try {
762 if (Intent.ACTION_USER_ADDED.equals(action)) {
763 final UserManager um = mContext.getSystemService(UserManager.class);
764 final int userSerialNumber = um.getUserSerialNumber(userId);
Jeff Sharkey54402792017-09-15 16:05:19 -0600765 mVold.onUserAdded(userId, userSerialNumber);
Jeff Sharkeybcd262d2015-06-10 09:41:17 -0700766 } else if (Intent.ACTION_USER_REMOVED.equals(action)) {
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700767 synchronized (mVolumes) {
768 final int size = mVolumes.size();
769 for (int i = 0; i < size; i++) {
770 final VolumeInfo vol = mVolumes.valueAt(i);
771 if (vol.mountUserId == userId) {
772 vol.mountUserId = UserHandle.USER_NULL;
773 mHandler.obtainMessage(H_VOLUME_UNMOUNT, vol).sendToTarget();
774 }
775 }
776 }
Jeff Sharkey54402792017-09-15 16:05:19 -0600777 mVold.onUserRemoved(userId);
Jeff Sharkeybcd262d2015-06-10 09:41:17 -0700778 }
Jeff Sharkeyace874b2017-09-07 15:27:33 -0600779 } catch (Exception e) {
780 Slog.wtf(TAG, e);
Jeff Sharkeybcd262d2015-06-10 09:41:17 -0700781 }
782 }
783 };
784
Jeff Sharkeyedcdaf62015-07-09 09:45:36 -0700785 private void waitForLatch(CountDownLatch latch, String condition, long timeoutMillis)
786 throws TimeoutException {
787 final long startMillis = SystemClock.elapsedRealtime();
Jeff Sharkeyeba260d2015-04-19 14:35:16 -0700788 while (true) {
Kenny Root51a573c2012-05-17 13:30:28 -0700789 try {
790 if (latch.await(5000, TimeUnit.MILLISECONDS)) {
San Mehat207e5382010-02-04 20:46:54 -0800791 return;
Kenny Root51a573c2012-05-17 13:30:28 -0700792 } else {
793 Slog.w(TAG, "Thread " + Thread.currentThread().getName()
Jeff Sharkey48877892015-03-18 11:27:19 -0700794 + " still waiting for " + condition + "...");
San Mehat207e5382010-02-04 20:46:54 -0800795 }
Kenny Root51a573c2012-05-17 13:30:28 -0700796 } catch (InterruptedException e) {
Jeff Sharkeyeba260d2015-04-19 14:35:16 -0700797 Slog.w(TAG, "Interrupt while waiting for " + condition);
San Mehat207e5382010-02-04 20:46:54 -0800798 }
Jeff Sharkeyedcdaf62015-07-09 09:45:36 -0700799 if (timeoutMillis > 0 && SystemClock.elapsedRealtime() > startMillis + timeoutMillis) {
800 throw new TimeoutException("Thread " + Thread.currentThread().getName()
801 + " gave up waiting for " + condition + " after " + timeoutMillis + "ms");
802 }
San Mehat207e5382010-02-04 20:46:54 -0800803 }
San Mehat1f6301e2010-01-07 22:40:27 -0800804 }
Kenny Root02c87302010-07-01 08:10:18 -0700805
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700806 private void handleSystemReady() {
Jeff Sharkey48877892015-03-18 11:27:19 -0700807 // Start scheduling nominally-daily fstrim operations
Christopher Tate115afda2014-06-06 19:06:26 -0700808 MountServiceIdler.scheduleIdlePass(mContext);
Daniel Colascione766b6322018-01-08 19:10:36 -0800809
810 // Toggle zram-enable system property in response to settings
811 mContext.getContentResolver().registerContentObserver(
812 Settings.Global.getUriFor(Settings.Global.ZRAM_ENABLED),
813 false /*notifyForDescendants*/,
814 new ContentObserver(null /* current thread */) {
815 @Override
816 public void onChange(boolean selfChange) {
817 refreshZramSettings();
818 }
819 });
820 refreshZramSettings();
Jeff Sharkeyb0c363b22018-12-15 11:53:03 -0700821
Srinivas Paladuguc8261752019-01-09 10:54:52 -0800822 // Schedule zram writeback unless zram is disabled by persist.sys.zram_enabled
823 String zramPropValue = SystemProperties.get(ZRAM_ENABLED_PROPERTY);
824 if (!zramPropValue.equals("0")
825 && mContext.getResources().getBoolean(
826 com.android.internal.R.bool.config_zramWriteback)) {
827 ZramWriteback.scheduleZramWriteback(mContext);
828 }
Jeff Sharkeyb0c363b22018-12-15 11:53:03 -0700829 // Toggle isolated-enable system property in response to settings
830 mContext.getContentResolver().registerContentObserver(
831 Settings.Global.getUriFor(Settings.Global.ISOLATED_STORAGE_REMOTE),
832 false /*notifyForDescendants*/,
833 new ContentObserver(null /* current thread */) {
834 @Override
835 public void onChange(boolean selfChange) {
836 refreshIsolatedStorageSettings();
837 }
838 });
Jeff Sharkey5d0c55c2019-01-24 14:32:31 -0700839 // For now, simply clone property when it changes
shafik91b34612019-09-23 15:41:44 +0100840 DeviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_STORAGE_NATIVE_BOOT,
Matt Pape15769e22019-04-19 12:31:24 -0700841 mContext.getMainExecutor(), (properties) -> {
Jeff Sharkey8b499a02019-01-28 13:31:50 -0700842 refreshIsolatedStorageSettings();
shafikb2992b62019-10-01 15:31:02 +0100843 refreshFuseSettings();
Jeff Sharkey5d0c55c2019-01-24 14:32:31 -0700844 });
Jeff Sharkeyb0c363b22018-12-15 11:53:03 -0700845 refreshIsolatedStorageSettings();
Daniel Colascione766b6322018-01-08 19:10:36 -0800846 }
847
848 /**
849 * Update the zram_enabled system property (which init reads to
850 * decide whether to enable zram) to reflect the zram_enabled
851 * preference (which we can change for experimentation purposes).
852 */
853 private void refreshZramSettings() {
854 String propertyValue = SystemProperties.get(ZRAM_ENABLED_PROPERTY);
855 if ("".equals(propertyValue)) {
856 return; // System doesn't have zram toggling support
857 }
858 String desiredPropertyValue =
859 Settings.Global.getInt(mContext.getContentResolver(),
860 Settings.Global.ZRAM_ENABLED,
861 1) != 0
862 ? "1" : "0";
863 if (!desiredPropertyValue.equals(propertyValue)) {
864 // Avoid redundant disk writes by setting only if we're
865 // changing the property value. There's no race: we're the
866 // sole writer.
867 SystemProperties.set(ZRAM_ENABLED_PROPERTY, desiredPropertyValue);
Srinivas Paladuguc8261752019-01-09 10:54:52 -0800868 // Schedule writeback only if zram is being enabled.
869 if (desiredPropertyValue.equals("1")
870 && mContext.getResources().getBoolean(
871 com.android.internal.R.bool.config_zramWriteback)) {
872 ZramWriteback.scheduleZramWriteback(mContext);
873 }
Daniel Colascione766b6322018-01-08 19:10:36 -0800874 }
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700875 }
876
Jeff Sharkeyb0c363b22018-12-15 11:53:03 -0700877 private void refreshIsolatedStorageSettings() {
Jeff Sharkey8b499a02019-01-28 13:31:50 -0700878 // Always copy value from newer DeviceConfig location
879 Settings.Global.putString(mResolver,
880 Settings.Global.ISOLATED_STORAGE_REMOTE,
shafik91b34612019-09-23 15:41:44 +0100881 DeviceConfig.getProperty(DeviceConfig.NAMESPACE_STORAGE_NATIVE_BOOT,
882 ISOLATED_STORAGE_ENABLED));
Jeff Sharkey8b499a02019-01-28 13:31:50 -0700883
Jeff Sharkeyb0c363b22018-12-15 11:53:03 -0700884 final int local = Settings.Global.getInt(mContext.getContentResolver(),
885 Settings.Global.ISOLATED_STORAGE_LOCAL, 0);
886 final int remote = Settings.Global.getInt(mContext.getContentResolver(),
887 Settings.Global.ISOLATED_STORAGE_REMOTE, 0);
888
889 // Walk down precedence chain; we prefer local settings first, then
890 // remote settings, before finally falling back to hard-coded default.
891 final boolean res;
892 if (local == -1) {
893 res = false;
894 } else if (local == 1) {
895 res = true;
896 } else if (remote == -1) {
897 res = false;
898 } else if (remote == 1) {
899 res = true;
900 } else {
Jeff Sharkey06376802019-02-11 12:20:02 -0700901 res = true;
Jeff Sharkeyb0c363b22018-12-15 11:53:03 -0700902 }
903
904 Slog.d(TAG, "Isolated storage local flag " + local + " and remote flag "
905 + remote + " resolved to " + res);
906 SystemProperties.set(StorageManager.PROP_ISOLATED_STORAGE, Boolean.toString(res));
907 }
908
Abhijeet Kaurb9847712019-11-19 16:35:47 +0000909 /**
910 * The most recent flag change takes precedence. Change fuse Settings flag if Device Config is
911 * changed. Settings flag change will in turn change fuse system property (persist.sys.fuse)
912 * whenever the user reboots.
913 */
shafikb2992b62019-10-01 15:31:02 +0100914 private void refreshFuseSettings() {
915 int isFuseEnabled = DeviceConfig.getInt(DeviceConfig.NAMESPACE_STORAGE_NATIVE_BOOT,
916 FUSE_ENABLED, 0);
917 if (isFuseEnabled == 1) {
Abhijeet Kaurb9847712019-11-19 16:35:47 +0000918 Slog.d(TAG, "Device Config flag for FUSE is enabled, turn Settings fuse flag on");
919 SystemProperties.set(FeatureFlagUtils.PERSIST_PREFIX
920 + FeatureFlagUtils.SETTINGS_FUSE_FLAG, "true");
shafikb2992b62019-10-01 15:31:02 +0100921 } else if (isFuseEnabled == -1) {
Abhijeet Kaurb9847712019-11-19 16:35:47 +0000922 Slog.d(TAG, "Device Config flag for FUSE is disabled, turn Settings fuse flag off");
923 SystemProperties.set(FeatureFlagUtils.PERSIST_PREFIX
924 + FeatureFlagUtils.SETTINGS_FUSE_FLAG, "false");
shafikb2992b62019-10-01 15:31:02 +0100925 }
926 // else, keep the build config.
Abhijeet Kaurb9847712019-11-19 16:35:47 +0000927 // This can be overridden by direct adjustment of persist.sys.fflag.override.settings_fuse
shafikb2992b62019-10-01 15:31:02 +0100928 }
929
Jeff Sharkey14cbe522015-07-08 14:06:37 -0700930 /**
931 * MediaProvider has a ton of code that makes assumptions about storage
932 * paths never changing, so we outright kill them to pick up new state.
933 */
934 @Deprecated
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700935 private void killMediaProvider(List<UserInfo> users) {
936 if (users == null) return;
937
Jeff Sharkeyb3cf9532015-07-17 15:12:39 -0700938 final long token = Binder.clearCallingIdentity();
939 try {
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700940 for (UserInfo user : users) {
941 // System user does not have media provider, so skip.
942 if (user.isSystemOnly()) continue;
943
Jeff Sharkey5790af02018-08-13 17:42:54 -0600944 final ProviderInfo provider = mPmInternal.resolveContentProvider(
945 MediaStore.AUTHORITY, PackageManager.MATCH_DIRECT_BOOT_AWARE
Jeff Sharkey8a372a02016-03-16 16:25:45 -0600946 | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
947 user.id);
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700948 if (provider != null) {
Sudheer Shankadc589ac2016-11-10 15:30:17 -0800949 final IActivityManager am = ActivityManager.getService();
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700950 try {
Jeff Sharkey85f449e2016-06-23 09:26:00 -0600951 am.killApplication(provider.applicationInfo.packageName,
952 UserHandle.getAppId(provider.applicationInfo.uid),
953 UserHandle.USER_ALL, "vold reset");
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700954 // We only need to run this once. It will kill all users' media processes.
955 break;
956 } catch (RemoteException e) {
957 }
Jeff Sharkeyb3cf9532015-07-17 15:12:39 -0700958 }
Jeff Sharkey14cbe522015-07-08 14:06:37 -0700959 }
Jeff Sharkeyb3cf9532015-07-17 15:12:39 -0700960 } finally {
961 Binder.restoreCallingIdentity(token);
Jeff Sharkey14cbe522015-07-08 14:06:37 -0700962 }
963 }
964
Andreas Gampea36dc622018-02-05 17:19:22 -0800965 @GuardedBy("mLock")
Jeff Sharkey5a9bb742015-11-03 10:15:57 -0800966 private void addInternalVolumeLocked() {
Amith Yamasania7892482015-08-07 11:09:05 -0700967 // Create a stub volume that represents internal storage
968 final VolumeInfo internal = new VolumeInfo(VolumeInfo.ID_PRIVATE_INTERNAL,
969 VolumeInfo.TYPE_PRIVATE, null, null);
970 internal.state = VolumeInfo.STATE_MOUNTED;
971 internal.path = Environment.getDataDirectory().getAbsolutePath();
972 mVolumes.put(internal.id, internal);
973 }
974
Daniel Rosenberg137aed12019-03-15 18:41:11 -0700975 private void initIfBootedAndConnected() {
976 Slog.d(TAG, "Thinking about init, mBootCompleted=" + mBootCompleted
Jeff Sharkey8924e872015-11-30 12:52:10 -0700977 + ", mDaemonConnected=" + mDaemonConnected);
Eric Biggers1127d922019-04-05 12:46:35 -0700978 if (mBootCompleted && mDaemonConnected
979 && !StorageManager.isFileEncryptedNativeOnly()) {
980 // When booting a device without native support, make sure that our
981 // user directories are locked or unlocked based on the current
982 // emulation status.
983 final boolean initLocked = StorageManager.isFileEncryptedEmulatedOnly();
984 Slog.d(TAG, "Setting up emulation state, initlocked=" + initLocked);
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700985 final List<UserInfo> users = mContext.getSystemService(UserManager.class).getUsers();
Jeff Sharkey8924e872015-11-30 12:52:10 -0700986 for (UserInfo user : users) {
987 try {
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700988 if (initLocked) {
Jeff Sharkey54402792017-09-15 16:05:19 -0600989 mVold.lockUserKey(user.id);
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700990 } else {
Jeff Sharkey54402792017-09-15 16:05:19 -0600991 mVold.unlockUserKey(user.id, user.serialNumber, encodeBytes(null),
992 encodeBytes(null));
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700993 }
Jeff Sharkey43e12112017-09-12 16:31:45 -0600994 } catch (Exception e) {
995 Slog.wtf(TAG, e);
Jeff Sharkey8924e872015-11-30 12:52:10 -0700996 }
997 }
998 }
999 }
1000
Daniel Rosenberg137aed12019-03-15 18:41:11 -07001001 private void resetIfBootedAndConnected() {
1002 Slog.d(TAG, "Thinking about reset, mBootCompleted=" + mBootCompleted
Jeff Sharkey48877892015-03-18 11:27:19 -07001003 + ", mDaemonConnected=" + mDaemonConnected);
Daniel Rosenberg137aed12019-03-15 18:41:11 -07001004 if (mBootCompleted && mDaemonConnected) {
Jeff Sharkey5a9bb742015-11-03 10:15:57 -08001005 final List<UserInfo> users = mContext.getSystemService(UserManager.class).getUsers();
Zim17be6f92019-09-25 14:37:55 +01001006
1007 if (mIsFuseEnabled) {
1008 mStorageSessionController.onReset(mVold, mHandler);
1009 } else {
1010 killMediaProvider(users);
1011 }
Jeff Sharkey14cbe522015-07-08 14:06:37 -07001012
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07001013 final int[] systemUnlockedUsers;
Jeff Sharkey5a9bb742015-11-03 10:15:57 -08001014 synchronized (mLock) {
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07001015 systemUnlockedUsers = mSystemUnlockedUsers;
Jeff Sharkeyb049e212012-09-07 23:16:01 -07001016
Jeff Sharkey5a9bb742015-11-03 10:15:57 -08001017 mDisks.clear();
1018 mVolumes.clear();
1019
1020 addInternalVolumeLocked();
1021 }
Jeff Sharkey59d577a2015-04-11 21:27:21 -07001022
Jeff Sharkey48877892015-03-18 11:27:19 -07001023 try {
Zim42f1e9f2019-08-15 17:35:00 +01001024 // TODO(b/135341433): Remove paranoid logging when FUSE is stable
Zim17be6f92019-09-25 14:37:55 +01001025 Slog.i(TAG, "Resetting vold...");
Jeff Sharkey54402792017-09-15 16:05:19 -06001026 mVold.reset();
Zim42f1e9f2019-08-15 17:35:00 +01001027 Slog.i(TAG, "Reset vold");
Jeff Sharkeybcd262d2015-06-10 09:41:17 -07001028
1029 // Tell vold about all existing and started users
Jeff Sharkeybcd262d2015-06-10 09:41:17 -07001030 for (UserInfo user : users) {
Jeff Sharkey54402792017-09-15 16:05:19 -06001031 mVold.onUserAdded(user.id, user.serialNumber);
Jeff Sharkeybcd262d2015-06-10 09:41:17 -07001032 }
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07001033 for (int userId : systemUnlockedUsers) {
Sudheer Shanka64501e52019-04-29 10:46:26 -07001034 mVold.onUserStarted(userId);
Jin Qian12690d52017-10-13 18:17:04 -07001035 mStoraged.onUserStarted(userId);
Jeff Sharkey50a05452015-04-29 11:24:52 -07001036 }
Jeff Sharkey9765e442017-12-14 22:15:14 -07001037 mVold.onSecureKeyguardStateChanged(mSecureKeyguardShowing);
Risanaec0ee72018-10-31 10:10:12 +09001038 mStorageManagerInternal.onReset(mVold);
Jeff Sharkeyace874b2017-09-07 15:27:33 -06001039 } catch (Exception e) {
1040 Slog.wtf(TAG, e);
Jeff Sharkeyb049e212012-09-07 23:16:01 -07001041 }
1042 }
Jeff Sharkey48877892015-03-18 11:27:19 -07001043 }
Jeff Sharkeyb049e212012-09-07 23:16:01 -07001044
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07001045 private void onUnlockUser(int userId) {
1046 Slog.d(TAG, "onUnlockUser " + userId);
Jeff Sharkey48877892015-03-18 11:27:19 -07001047
1048 // We purposefully block here to make sure that user-specific
1049 // staging area is ready so it's ready for zygote-forked apps to
1050 // bind mount against.
1051 try {
Zim17be6f92019-09-25 14:37:55 +01001052 mStorageSessionController.onUnlockUser(userId);
Sudheer Shanka64501e52019-04-29 10:46:26 -07001053 mVold.onUserStarted(userId);
Jin Qian12690d52017-10-13 18:17:04 -07001054 mStoraged.onUserStarted(userId);
Jeff Sharkeyace874b2017-09-07 15:27:33 -06001055 } catch (Exception e) {
1056 Slog.wtf(TAG, e);
Jeff Sharkeyb049e212012-09-07 23:16:01 -07001057 }
Jeff Sharkey48877892015-03-18 11:27:19 -07001058
Narayan Kamath157dd1d2019-06-12 13:06:30 +01001059 mHandler.obtainMessage(H_COMPLETE_UNLOCK_USER, userId).sendToTarget();
1060 }
1061
1062 private void completeUnlockUser(int userId) {
1063 // If user 0 has completed unlock, perform a one-time migration of legacy obb data
1064 // to its new location. This may take time depending on the size of the data to be copied
1065 // so it's done on the StorageManager handler thread.
1066 if (userId == 0) {
1067 mPmInternal.migrateLegacyObbData();
1068 }
1069
Jeff Sharkey48877892015-03-18 11:27:19 -07001070 // Record user as started so newly mounted volumes kick off events
1071 // correctly, then synthesize events for any already-mounted volumes.
yuanhuihuiefd1f122016-07-13 21:21:03 +08001072 synchronized (mLock) {
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07001073 for (int i = 0; i < mVolumes.size(); i++) {
1074 final VolumeInfo vol = mVolumes.valueAt(i);
Jeff Sharkey46349872015-07-28 10:49:47 -07001075 if (vol.isVisibleForRead(userId) && vol.isMountedReadable()) {
Svet Ganov6ee871e2015-07-10 14:29:33 -07001076 final StorageVolume userVol = vol.buildStorageVolume(mContext, userId, false);
Jeff Sharkey48877892015-03-18 11:27:19 -07001077 mHandler.obtainMessage(H_VOLUME_BROADCAST, userVol).sendToTarget();
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001078
Jeff Sharkey27de30d2015-04-18 16:20:27 -07001079 final String envState = VolumeInfo.getEnvironmentForState(vol.getState());
1080 mCallbacks.notifyStorageStateChanged(userVol.getPath(), envState, envState);
Jeff Sharkey48877892015-03-18 11:27:19 -07001081 }
1082 }
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07001083 mSystemUnlockedUsers = ArrayUtils.appendInt(mSystemUnlockedUsers, userId);
Jeff Sharkey48877892015-03-18 11:27:19 -07001084 }
1085 }
1086
1087 private void onCleanupUser(int userId) {
1088 Slog.d(TAG, "onCleanupUser " + userId);
1089
1090 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06001091 mVold.onUserStopped(userId);
Jin Qian12690d52017-10-13 18:17:04 -07001092 mStoraged.onUserStopped(userId);
Jeff Sharkeyace874b2017-09-07 15:27:33 -06001093 } catch (Exception e) {
1094 Slog.wtf(TAG, e);
Jeff Sharkey48877892015-03-18 11:27:19 -07001095 }
1096
yuanhuihuiefd1f122016-07-13 21:21:03 +08001097 synchronized (mLock) {
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07001098 mSystemUnlockedUsers = ArrayUtils.removeInt(mSystemUnlockedUsers, userId);
Jeff Sharkey48877892015-03-18 11:27:19 -07001099 }
1100 }
Jeff Sharkeyb049e212012-09-07 23:16:01 -07001101
Martijn Coenen7084c6a2019-11-22 16:32:09 +01001102 private void onStopUser(int userId) {
1103 Slog.i(TAG, "onStopUser " + userId);
1104 try {
1105 mStorageSessionController.onUserStopping(userId);
1106 } catch (Exception e) {
1107 Slog.wtf(TAG, e);
1108 }
1109 }
1110
Sudheer Shanka64501e52019-04-29 10:46:26 -07001111 private boolean supportsBlockCheckpoint() throws RemoteException {
Paul Lawrence15a54462019-04-30 11:14:25 -07001112 enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);
Sandeep Patil7d5c4912019-04-15 09:27:30 -07001113 return mVold.supportsBlockCheckpoint();
1114 }
1115
Jeff Sharkey9765e442017-12-14 22:15:14 -07001116 @Override
1117 public void onAwakeStateChanged(boolean isAwake) {
1118 // Ignored
1119 }
1120
1121 @Override
1122 public void onKeyguardStateChanged(boolean isShowing) {
1123 // Push down current secure keyguard status so that we ignore malicious
1124 // USB devices while locked.
1125 mSecureKeyguardShowing = isShowing
Martijn Coenen7c1df2d2020-01-07 10:21:42 +01001126 && mContext.getSystemService(KeyguardManager.class).isDeviceSecure(mCurrentUserId);
Jeff Sharkey9765e442017-12-14 22:15:14 -07001127 try {
1128 mVold.onSecureKeyguardStateChanged(mSecureKeyguardShowing);
1129 } catch (Exception e) {
1130 Slog.wtf(TAG, e);
1131 }
1132 }
1133
Christopher Tated417d622013-08-19 16:14:25 -07001134 void runIdleMaintenance(Runnable callback) {
1135 mHandler.sendMessage(mHandler.obtainMessage(H_FSTRIM, callback));
1136 }
1137
Christopher Tate7265abe2014-11-21 13:54:45 -08001138 // Binder entry point for kicking off an immediate fstrim
1139 @Override
1140 public void runMaintenance() {
Jeff Sharkey48877892015-03-18 11:27:19 -07001141 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
Christopher Tate7265abe2014-11-21 13:54:45 -08001142 runIdleMaintenance(null);
1143 }
1144
1145 @Override
1146 public long lastMaintenance() {
1147 return mLastMaintenance;
1148 }
1149
San Mehat4270e1e2010-01-29 05:32:19 -08001150 public void onDaemonConnected() {
Jeff Sharkey48877892015-03-18 11:27:19 -07001151 mDaemonConnected = true;
1152 mHandler.obtainMessage(H_DAEMON_CONNECTED).sendToTarget();
1153 }
1154
1155 private void handleDaemonConnected() {
Daniel Rosenberg137aed12019-03-15 18:41:11 -07001156 initIfBootedAndConnected();
1157 resetIfBootedAndConnected();
Jeff Sharkey48877892015-03-18 11:27:19 -07001158
Jeff Sharkey48877892015-03-18 11:27:19 -07001159 // On an encrypted device we can't see system properties yet, so pull
1160 // the system locale out of the mount service.
Inseob Kimc1246e62018-11-08 13:13:54 +09001161 if ("".equals(VoldProperties.encrypt_progress().orElse(""))) {
Jeff Sharkey48877892015-03-18 11:27:19 -07001162 copyLocaleFromMountService();
1163 }
San Mehat4270e1e2010-01-29 05:32:19 -08001164 }
1165
Elliott Hughesf839b4f2014-09-26 12:30:47 -07001166 private void copyLocaleFromMountService() {
1167 String systemLocale;
1168 try {
1169 systemLocale = getField(StorageManager.SYSTEM_LOCALE_KEY);
1170 } catch (RemoteException e) {
1171 return;
1172 }
1173 if (TextUtils.isEmpty(systemLocale)) {
1174 return;
1175 }
1176
1177 Slog.d(TAG, "Got locale " + systemLocale + " from mount service");
1178 Locale locale = Locale.forLanguageTag(systemLocale);
1179 Configuration config = new Configuration();
1180 config.setLocale(locale);
1181 try {
Sudheer Shankadc589ac2016-11-10 15:30:17 -08001182 ActivityManager.getService().updatePersistentConfiguration(config);
Elliott Hughesf839b4f2014-09-26 12:30:47 -07001183 } catch (RemoteException e) {
1184 Slog.e(TAG, "Error setting system locale from mount service", e);
1185 }
Elliott Hughes9c33f282014-10-13 12:39:56 -07001186
1187 // Temporary workaround for http://b/17945169.
1188 Slog.d(TAG, "Setting system properties to " + systemLocale + " from mount service");
Narayan Kamathd30dbb82015-01-15 14:48:15 +00001189 SystemProperties.set("persist.sys.locale", locale.toLanguageTag());
Elliott Hughesf839b4f2014-09-26 12:30:47 -07001190 }
1191
Jeff Sharkey8058fe62017-09-13 11:50:33 -06001192 private final IVoldListener mListener = new IVoldListener.Stub() {
1193 @Override
1194 public void onDiskCreated(String diskId, int flags) {
1195 synchronized (mLock) {
Jeff Sharkey901c0422018-04-20 13:11:20 -06001196 final String value = SystemProperties.get(StorageManager.PROP_ADOPTABLE);
1197 switch (value) {
1198 case "force_on":
1199 flags |= DiskInfo.FLAG_ADOPTABLE;
1200 break;
1201 case "force_off":
1202 flags &= ~DiskInfo.FLAG_ADOPTABLE;
1203 break;
Jeff Sharkey8058fe62017-09-13 11:50:33 -06001204 }
Jeff Sharkey8058fe62017-09-13 11:50:33 -06001205 mDisks.put(diskId, new DiskInfo(diskId, flags));
1206 }
1207 }
1208
1209 @Override
1210 public void onDiskScanned(String diskId) {
1211 synchronized (mLock) {
1212 final DiskInfo disk = mDisks.get(diskId);
1213 if (disk != null) {
1214 onDiskScannedLocked(disk);
1215 }
1216 }
1217 }
1218
1219 @Override
1220 public void onDiskMetadataChanged(String diskId, long sizeBytes, String label,
1221 String sysPath) {
1222 synchronized (mLock) {
1223 final DiskInfo disk = mDisks.get(diskId);
1224 if (disk != null) {
1225 disk.size = sizeBytes;
1226 disk.label = label;
1227 disk.sysPath = sysPath;
1228 }
1229 }
1230 }
1231
1232 @Override
1233 public void onDiskDestroyed(String diskId) {
1234 synchronized (mLock) {
1235 final DiskInfo disk = mDisks.remove(diskId);
1236 if (disk != null) {
1237 mCallbacks.notifyDiskDestroyed(disk);
1238 }
1239 }
1240 }
1241
1242 @Override
Zim17be6f92019-09-25 14:37:55 +01001243 public void onVolumeCreated(String volId, int type, String diskId, String partGuid,
1244 int userId) {
Jeff Sharkey8058fe62017-09-13 11:50:33 -06001245 synchronized (mLock) {
1246 final DiskInfo disk = mDisks.get(diskId);
1247 final VolumeInfo vol = new VolumeInfo(volId, type, disk, partGuid);
Zim17be6f92019-09-25 14:37:55 +01001248 vol.mountUserId = userId;
Jeff Sharkey8058fe62017-09-13 11:50:33 -06001249 mVolumes.put(volId, vol);
1250 onVolumeCreatedLocked(vol);
1251 }
1252 }
1253
1254 @Override
1255 public void onVolumeStateChanged(String volId, int state) {
1256 synchronized (mLock) {
1257 final VolumeInfo vol = mVolumes.get(volId);
1258 if (vol != null) {
1259 final int oldState = vol.state;
1260 final int newState = state;
1261 vol.state = newState;
1262 onVolumeStateChangedLocked(vol, oldState, newState);
1263 }
Ricky Wai4482ab52019-12-10 19:08:18 +00001264 try {
1265 if (vol.type == VolumeInfo.TYPE_PRIVATE && state == VolumeInfo.STATE_MOUNTED) {
1266 mInstaller.onPrivateVolumeMounted(vol.getFsUuid());
1267 }
1268 } catch (Installer.InstallerException e) {
1269 Slog.i(TAG, "Failed when private volume mounted " + vol, e);
1270 }
Jeff Sharkey8058fe62017-09-13 11:50:33 -06001271 }
1272 }
1273
1274 @Override
1275 public void onVolumeMetadataChanged(String volId, String fsType, String fsUuid,
1276 String fsLabel) {
1277 synchronized (mLock) {
1278 final VolumeInfo vol = mVolumes.get(volId);
1279 if (vol != null) {
1280 vol.fsType = fsType;
1281 vol.fsUuid = fsUuid;
1282 vol.fsLabel = fsLabel;
1283 }
1284 }
1285 }
1286
1287 @Override
1288 public void onVolumePathChanged(String volId, String path) {
1289 synchronized (mLock) {
1290 final VolumeInfo vol = mVolumes.get(volId);
1291 if (vol != null) {
1292 vol.path = path;
1293 }
1294 }
1295 }
1296
1297 @Override
1298 public void onVolumeInternalPathChanged(String volId, String internalPath) {
1299 synchronized (mLock) {
1300 final VolumeInfo vol = mVolumes.get(volId);
1301 if (vol != null) {
1302 vol.internalPath = internalPath;
1303 }
1304 }
1305 }
1306
1307 @Override
1308 public void onVolumeDestroyed(String volId) {
Zim17be6f92019-09-25 14:37:55 +01001309 VolumeInfo vol = null;
Jeff Sharkey8058fe62017-09-13 11:50:33 -06001310 synchronized (mLock) {
Zim17be6f92019-09-25 14:37:55 +01001311 vol = mVolumes.remove(volId);
1312 }
1313
1314 if (vol != null) {
1315 mStorageSessionController.onVolumeRemove(vol);
Ricky Wai4482ab52019-12-10 19:08:18 +00001316 try {
1317 if (vol.type == VolumeInfo.TYPE_PRIVATE) {
1318 mInstaller.onPrivateVolumeRemoved(vol.getFsUuid());
1319 }
1320 } catch (Installer.InstallerException e) {
1321 Slog.i(TAG, "Failed when private volume unmounted " + vol, e);
1322 }
Jeff Sharkey8058fe62017-09-13 11:50:33 -06001323 }
1324 }
1325 };
1326
Andreas Gampea36dc622018-02-05 17:19:22 -08001327 @GuardedBy("mLock")
Jeff Sharkeyeba260d2015-04-19 14:35:16 -07001328 private void onDiskScannedLocked(DiskInfo disk) {
Jeff Sharkey620b32b2015-04-23 19:36:02 -07001329 int volumeCount = 0;
Jeff Sharkeyeba260d2015-04-19 14:35:16 -07001330 for (int i = 0; i < mVolumes.size(); i++) {
1331 final VolumeInfo vol = mVolumes.valueAt(i);
1332 if (Objects.equals(disk.id, vol.getDiskId())) {
Jeff Sharkey620b32b2015-04-23 19:36:02 -07001333 volumeCount++;
Jeff Sharkeyeba260d2015-04-19 14:35:16 -07001334 }
1335 }
1336
Jeff Sharkeyc7acac62015-06-12 16:16:56 -07001337 final Intent intent = new Intent(DiskInfo.ACTION_DISK_SCANNED);
Jeff Sharkey7732e1e2016-03-30 17:14:23 -06001338 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT
1339 | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
Jeff Sharkeyc7acac62015-06-12 16:16:56 -07001340 intent.putExtra(DiskInfo.EXTRA_DISK_ID, disk.id);
1341 intent.putExtra(DiskInfo.EXTRA_VOLUME_COUNT, volumeCount);
Jeff Sharkeyabc3e852015-08-03 14:41:13 -07001342 mHandler.obtainMessage(H_INTERNAL_BROADCAST, intent).sendToTarget();
Jeff Sharkeyc7acac62015-06-12 16:16:56 -07001343
1344 final CountDownLatch latch = mDiskScanLatches.remove(disk.id);
1345 if (latch != null) {
1346 latch.countDown();
1347 }
1348
Jeff Sharkeyf5a6bd72015-05-19 14:42:38 -07001349 disk.volumeCount = volumeCount;
Jeff Sharkey620b32b2015-04-23 19:36:02 -07001350 mCallbacks.notifyDiskScanned(disk, volumeCount);
Jeff Sharkeyeba260d2015-04-19 14:35:16 -07001351 }
1352
Andreas Gampea36dc622018-02-05 17:19:22 -08001353 @GuardedBy("mLock")
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07001354 private void onVolumeCreatedLocked(VolumeInfo vol) {
Jeff Sharkey5790af02018-08-13 17:42:54 -06001355 if (mPmInternal.isOnlyCoreApps()) {
Jeff Sharkey6855c482016-03-31 14:34:38 -06001356 Slog.d(TAG, "System booted in core-only mode; ignoring volume " + vol.getId());
1357 return;
1358 }
Martijn Coenen7084c6a2019-11-22 16:32:09 +01001359 final ActivityManagerInternal amInternal =
1360 LocalServices.getService(ActivityManagerInternal.class);
1361
1362 if (mIsFuseEnabled && vol.mountUserId >= 0
1363 && !amInternal.isUserRunning(vol.mountUserId, 0)) {
1364 Slog.d(TAG, "Ignoring volume " + vol.getId() + " because user "
1365 + Integer.toString(vol.mountUserId) + " is no longer running.");
1366 return;
1367 }
Jeff Sharkey6855c482016-03-31 14:34:38 -06001368
Jeff Sharkey275e3e42015-04-24 16:10:32 -07001369 if (vol.type == VolumeInfo.TYPE_EMULATED) {
1370 final StorageManager storage = mContext.getSystemService(StorageManager.class);
1371 final VolumeInfo privateVol = storage.findPrivateForEmulated(vol);
1372
1373 if (Objects.equals(StorageManager.UUID_PRIVATE_INTERNAL, mPrimaryStorageUuid)
1374 && VolumeInfo.ID_PRIVATE_INTERNAL.equals(privateVol.id)) {
1375 Slog.v(TAG, "Found primary storage at " + vol);
1376 vol.mountFlags |= VolumeInfo.MOUNT_FLAG_PRIMARY;
1377 vol.mountFlags |= VolumeInfo.MOUNT_FLAG_VISIBLE;
1378 mHandler.obtainMessage(H_VOLUME_MOUNT, vol).sendToTarget();
1379
1380 } else if (Objects.equals(privateVol.fsUuid, mPrimaryStorageUuid)) {
1381 Slog.v(TAG, "Found primary storage at " + vol);
1382 vol.mountFlags |= VolumeInfo.MOUNT_FLAG_PRIMARY;
1383 vol.mountFlags |= VolumeInfo.MOUNT_FLAG_VISIBLE;
1384 mHandler.obtainMessage(H_VOLUME_MOUNT, vol).sendToTarget();
1385 }
Jeff Sharkeyb049e212012-09-07 23:16:01 -07001386
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07001387 } else if (vol.type == VolumeInfo.TYPE_PUBLIC) {
Jeff Sharkey275e3e42015-04-24 16:10:32 -07001388 // TODO: only look at first public partition
1389 if (Objects.equals(StorageManager.UUID_PRIMARY_PHYSICAL, mPrimaryStorageUuid)
1390 && vol.disk.isDefaultPrimary()) {
1391 Slog.v(TAG, "Found primary storage at " + vol);
Jeff Sharkey7e92ef32015-04-17 17:35:07 -07001392 vol.mountFlags |= VolumeInfo.MOUNT_FLAG_PRIMARY;
1393 vol.mountFlags |= VolumeInfo.MOUNT_FLAG_VISIBLE;
San Mehat4270e1e2010-01-29 05:32:19 -08001394 }
Jeff Sharkey7e92ef32015-04-17 17:35:07 -07001395
1396 // Adoptable public disks are visible to apps, since they meet
1397 // public API requirement of being in a stable location.
Jeff Sharkey275e3e42015-04-24 16:10:32 -07001398 if (vol.disk.isAdoptable()) {
Jeff Sharkey7e92ef32015-04-17 17:35:07 -07001399 vol.mountFlags |= VolumeInfo.MOUNT_FLAG_VISIBLE;
1400 }
1401
Jeff Sharkeyab15c392016-05-05 11:45:01 -06001402 vol.mountUserId = mCurrentUserId;
Jeff Sharkey48877892015-03-18 11:27:19 -07001403 mHandler.obtainMessage(H_VOLUME_MOUNT, vol).sendToTarget();
San Mehat4270e1e2010-01-29 05:32:19 -08001404
Jeff Sharkeyb2b9ab82015-04-05 21:10:42 -07001405 } else if (vol.type == VolumeInfo.TYPE_PRIVATE) {
1406 mHandler.obtainMessage(H_VOLUME_MOUNT, vol).sendToTarget();
1407
Risan05c41e62018-10-29 08:57:43 +09001408 } else if (vol.type == VolumeInfo.TYPE_STUB) {
1409 vol.mountUserId = mCurrentUserId;
1410 mHandler.obtainMessage(H_VOLUME_MOUNT, vol).sendToTarget();
San Mehat4270e1e2010-01-29 05:32:19 -08001411 } else {
Jeff Sharkey48877892015-03-18 11:27:19 -07001412 Slog.d(TAG, "Skipping automatic mounting of " + vol);
San Mehat4270e1e2010-01-29 05:32:19 -08001413 }
1414 }
1415
Jeff Sharkeye6c04f92015-04-18 21:38:05 -07001416 private boolean isBroadcastWorthy(VolumeInfo vol) {
1417 switch (vol.getType()) {
Jeff Sharkeyc7acac62015-06-12 16:16:56 -07001418 case VolumeInfo.TYPE_PRIVATE:
Jeff Sharkeye6c04f92015-04-18 21:38:05 -07001419 case VolumeInfo.TYPE_PUBLIC:
1420 case VolumeInfo.TYPE_EMULATED:
Risan05c41e62018-10-29 08:57:43 +09001421 case VolumeInfo.TYPE_STUB:
Jeff Sharkeye6c04f92015-04-18 21:38:05 -07001422 break;
1423 default:
1424 return false;
1425 }
1426
1427 switch (vol.getState()) {
1428 case VolumeInfo.STATE_MOUNTED:
1429 case VolumeInfo.STATE_MOUNTED_READ_ONLY:
1430 case VolumeInfo.STATE_EJECTING:
1431 case VolumeInfo.STATE_UNMOUNTED:
Jeff Sharkeyc7acac62015-06-12 16:16:56 -07001432 case VolumeInfo.STATE_UNMOUNTABLE:
Tony Mantlerf0d71052015-06-24 11:45:25 -07001433 case VolumeInfo.STATE_BAD_REMOVAL:
Jeff Sharkeye6c04f92015-04-18 21:38:05 -07001434 break;
1435 default:
1436 return false;
1437 }
1438
1439 return true;
1440 }
1441
Andreas Gampea36dc622018-02-05 17:19:22 -08001442 @GuardedBy("mLock")
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07001443 private void onVolumeStateChangedLocked(VolumeInfo vol, int oldState, int newState) {
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001444 // Remember that we saw this volume so we're ready to accept user
1445 // metadata, or so we can annoy them when a private volume is ejected
Jeff Sharkey3811f352019-05-14 11:54:36 -06001446 if (!TextUtils.isEmpty(vol.fsUuid)) {
Jeff Sharkey5cc0df22015-06-17 19:44:05 -07001447 VolumeRecord rec = mRecords.get(vol.fsUuid);
1448 if (rec == null) {
1449 rec = new VolumeRecord(vol.type, vol.fsUuid);
1450 rec.partGuid = vol.partGuid;
Jeff Sharkeye8a4b662015-06-27 15:43:45 -07001451 rec.createdMillis = System.currentTimeMillis();
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001452 if (vol.type == VolumeInfo.TYPE_PRIVATE) {
1453 rec.nickname = vol.disk.getDescription();
1454 }
1455 mRecords.put(rec.fsUuid, rec);
Jeff Sharkey5cc0df22015-06-17 19:44:05 -07001456 } else {
1457 // Handle upgrade case where we didn't store partition GUID
1458 if (TextUtils.isEmpty(rec.partGuid)) {
1459 rec.partGuid = vol.partGuid;
Jeff Sharkey5cc0df22015-06-17 19:44:05 -07001460 }
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001461 }
Jeff Sharkey3811f352019-05-14 11:54:36 -06001462
1463 rec.lastSeenMillis = System.currentTimeMillis();
1464 writeSettingsLocked();
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001465 }
1466
Jeff Sharkeye6c04f92015-04-18 21:38:05 -07001467 mCallbacks.notifyVolumeStateChanged(vol, oldState, newState);
1468
Yasuhiro Matsuda87a38b52015-07-24 22:10:16 +09001469 // Do not broadcast before boot has completed to avoid launching the
1470 // processes that receive the intent unnecessarily.
1471 if (mBootCompleted && isBroadcastWorthy(vol)) {
Jeff Sharkeye6c04f92015-04-18 21:38:05 -07001472 final Intent intent = new Intent(VolumeInfo.ACTION_VOLUME_STATE_CHANGED);
Jeff Sharkeyc7acac62015-06-12 16:16:56 -07001473 intent.putExtra(VolumeInfo.EXTRA_VOLUME_ID, vol.id);
1474 intent.putExtra(VolumeInfo.EXTRA_VOLUME_STATE, newState);
Tony Mantlerf0d71052015-06-24 11:45:25 -07001475 intent.putExtra(VolumeRecord.EXTRA_FS_UUID, vol.fsUuid);
Jeff Sharkey7732e1e2016-03-30 17:14:23 -06001476 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT
1477 | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
Jeff Sharkeyabc3e852015-08-03 14:41:13 -07001478 mHandler.obtainMessage(H_INTERNAL_BROADCAST, intent).sendToTarget();
Jeff Sharkeye6c04f92015-04-18 21:38:05 -07001479 }
Jeff Sharkeyb049e212012-09-07 23:16:01 -07001480
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001481 final String oldStateEnv = VolumeInfo.getEnvironmentForState(oldState);
1482 final String newStateEnv = VolumeInfo.getEnvironmentForState(newState);
Emily Bernier92aa5a22014-07-07 10:11:48 -04001483
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001484 if (!Objects.equals(oldStateEnv, newStateEnv)) {
1485 // Kick state changed event towards all started users. Any users
1486 // started after this point will trigger additional
1487 // user-specific broadcasts.
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07001488 for (int userId : mSystemUnlockedUsers) {
Jeff Sharkey46349872015-07-28 10:49:47 -07001489 if (vol.isVisibleForRead(userId)) {
Svet Ganov6ee871e2015-07-10 14:29:33 -07001490 final StorageVolume userVol = vol.buildStorageVolume(mContext, userId, false);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001491 mHandler.obtainMessage(H_VOLUME_BROADCAST, userVol).sendToTarget();
Jeff Sharkey48877892015-03-18 11:27:19 -07001492
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001493 mCallbacks.notifyStorageStateChanged(userVol.getPath(), oldStateEnv,
1494 newStateEnv);
San Mehat4270e1e2010-01-29 05:32:19 -08001495 }
1496 }
1497 }
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001498
Risan05c41e62018-10-29 08:57:43 +09001499 if ((vol.type == VolumeInfo.TYPE_PUBLIC || vol.type == VolumeInfo.TYPE_STUB)
1500 && vol.state == VolumeInfo.STATE_EJECTING) {
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001501 // TODO: this should eventually be handled by new ObbVolume state changes
1502 /*
1503 * Some OBBs might have been unmounted when this volume was
1504 * unmounted, so send a message to the handler to let it know to
1505 * remove those from the list of mounted OBBS.
1506 */
1507 mObbActionHandler.sendMessage(mObbActionHandler.obtainMessage(
1508 OBB_FLUSH_MOUNT_STATE, vol.path));
1509 }
Pavel Grafovce72ef02018-01-10 17:14:11 +00001510 maybeLogMediaMount(vol, newState);
1511 }
1512
1513 private void maybeLogMediaMount(VolumeInfo vol, int newState) {
1514 if (!SecurityLog.isLoggingEnabled()) {
1515 return;
1516 }
1517
1518 final DiskInfo disk = vol.getDisk();
1519 if (disk == null || (disk.flags & (DiskInfo.FLAG_SD | DiskInfo.FLAG_USB)) == 0) {
1520 return;
1521 }
1522
1523 // Sometimes there is a newline character.
1524 final String label = disk.label != null ? disk.label.trim() : "";
1525
1526 if (newState == VolumeInfo.STATE_MOUNTED
1527 || newState == VolumeInfo.STATE_MOUNTED_READ_ONLY) {
1528 SecurityLog.writeEvent(SecurityLog.TAG_MEDIA_MOUNT, vol.path, label);
1529 } else if (newState == VolumeInfo.STATE_UNMOUNTED
1530 || newState == VolumeInfo.STATE_BAD_REMOVAL) {
1531 SecurityLog.writeEvent(SecurityLog.TAG_MEDIA_UNMOUNT, vol.path, label);
1532 }
San Mehat4270e1e2010-01-29 05:32:19 -08001533 }
1534
Andreas Gampea36dc622018-02-05 17:19:22 -08001535 @GuardedBy("mLock")
Jeff Sharkey275e3e42015-04-24 16:10:32 -07001536 private void onMoveStatusLocked(int status) {
1537 if (mMoveCallback == null) {
1538 Slog.w(TAG, "Odd, status but no move requested");
1539 return;
1540 }
1541
1542 // TODO: estimate remaining time
1543 try {
Jeff Sharkey50a05452015-04-29 11:24:52 -07001544 mMoveCallback.onStatusChanged(-1, status, -1);
Jeff Sharkey275e3e42015-04-24 16:10:32 -07001545 } catch (RemoteException ignored) {
1546 }
1547
1548 // We've finished copying and we're about to clean up old data, so
1549 // remember that move was successful if we get rebooted
1550 if (status == MOVE_STATUS_COPY_FINISHED) {
1551 Slog.d(TAG, "Move to " + mMoveTargetUuid + " copy phase finshed; persisting");
1552
1553 mPrimaryStorageUuid = mMoveTargetUuid;
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001554 writeSettingsLocked();
Jeff Sharkey275e3e42015-04-24 16:10:32 -07001555 }
1556
1557 if (PackageManager.isMoveStatusFinished(status)) {
1558 Slog.d(TAG, "Move to " + mMoveTargetUuid + " finished with status " + status);
1559
1560 mMoveCallback = null;
1561 mMoveTargetUuid = null;
1562 }
1563 }
1564
Jeff Sharkey48877892015-03-18 11:27:19 -07001565 private void enforcePermission(String perm) {
1566 mContext.enforceCallingOrSelfPermission(perm, perm);
Mike Lockwooda5250c92011-05-23 13:44:04 -04001567 }
1568
Jeff Sharkey2e606d72015-07-27 14:19:54 -07001569 /**
1570 * Decide if volume is mountable per device policies.
1571 */
1572 private boolean isMountDisallowed(VolumeInfo vol) {
Philip P. Moltmannec3cbb22016-09-14 13:24:52 -07001573 UserManager userManager = mContext.getSystemService(UserManager.class);
1574
1575 boolean isUsbRestricted = false;
1576 if (vol.disk != null && vol.disk.isUsb()) {
1577 isUsbRestricted = userManager.hasUserRestriction(UserManager.DISALLOW_USB_FILE_TRANSFER,
Jeff Sharkey2e606d72015-07-27 14:19:54 -07001578 Binder.getCallingUserHandle());
Emily Bernier92aa5a22014-07-07 10:11:48 -04001579 }
Philip P. Moltmannec3cbb22016-09-14 13:24:52 -07001580
1581 boolean isTypeRestricted = false;
Risan05c41e62018-10-29 08:57:43 +09001582 if (vol.type == VolumeInfo.TYPE_PUBLIC || vol.type == VolumeInfo.TYPE_PRIVATE
1583 || vol.type == VolumeInfo.TYPE_STUB) {
Philip P. Moltmannec3cbb22016-09-14 13:24:52 -07001584 isTypeRestricted = userManager
1585 .hasUserRestriction(UserManager.DISALLOW_MOUNT_PHYSICAL_MEDIA,
1586 Binder.getCallingUserHandle());
1587 }
1588
1589 return isUsbRestricted || isTypeRestricted;
Emily Bernier92aa5a22014-07-07 10:11:48 -04001590 }
1591
Amith Yamasani462ac3a2015-06-30 14:21:01 -07001592 private void enforceAdminUser() {
1593 UserManager um = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
1594 final int callingUserId = UserHandle.getCallingUserId();
1595 boolean isAdmin;
1596 long token = Binder.clearCallingIdentity();
1597 try {
1598 isAdmin = um.getUserInfo(callingUserId).isAdmin();
1599 } finally {
1600 Binder.restoreCallingIdentity(token);
1601 }
1602 if (!isAdmin) {
1603 throw new SecurityException("Only admin users can adopt sd cards");
1604 }
1605 }
1606
Jeff Sharkeyb049e212012-09-07 23:16:01 -07001607 /**
Sudheer Shanka2250d562016-11-07 15:41:02 -08001608 * Constructs a new StorageManagerService instance
San Mehat207e5382010-02-04 20:46:54 -08001609 *
1610 * @param context Binder context for this service
1611 */
Sudheer Shanka2250d562016-11-07 15:41:02 -08001612 public StorageManagerService(Context context) {
Christopher Tated417d622013-08-19 16:14:25 -07001613 sSelf = this;
1614
Jeff Sharkey342b4bf2018-12-18 11:12:40 -07001615 // Snapshot feature flag used for this boot
1616 SystemProperties.set(StorageManager.PROP_ISOLATED_STORAGE_SNAPSHOT, Boolean.toString(
Jeff Sharkey06376802019-02-11 12:20:02 -07001617 SystemProperties.getBoolean(StorageManager.PROP_ISOLATED_STORAGE, true)));
shafik78fcd502019-09-25 13:50:04 +01001618
Abhijeet Kaura4f40562019-12-09 13:55:42 +00001619 mIsFuseEnabled = SystemProperties.getBoolean(StorageManager.PROP_FUSE, false);
San Mehat207e5382010-02-04 20:46:54 -08001620 mContext = context;
Jeff Sharkey5d0c55c2019-01-24 14:32:31 -07001621 mResolver = mContext.getContentResolver();
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001622 mCallbacks = new Callbacks(FgThread.get().getLooper());
Jeff Sharkeyb9fe5372015-12-03 15:23:08 -07001623 mLockPatternUtils = new LockPatternUtils(mContext);
San Mehat207e5382010-02-04 20:46:54 -08001624
Dianne Hackbornefa92b22013-05-03 14:11:43 -07001625 HandlerThread hthread = new HandlerThread(TAG);
1626 hthread.start();
Sudheer Shanka2250d562016-11-07 15:41:02 -08001627 mHandler = new StorageManagerServiceHandler(hthread.getLooper());
Daniel Sandler5f27ef42010-03-16 15:42:02 -04001628
Sudheer Shanka2250d562016-11-07 15:41:02 -08001629 // Add OBB Action Handler to StorageManagerService thread.
Dianne Hackborn8d044e82013-04-30 17:24:15 -07001630 mObbActionHandler = new ObbActionHandler(IoThread.get().getLooper());
Kenny Roota02b8b02010-08-05 16:14:17 -07001631
Zim17be6f92019-09-25 14:37:55 +01001632 mStorageSessionController = new StorageSessionController(mContext, mIsFuseEnabled);
Zim42f1e9f2019-08-15 17:35:00 +01001633
Ricky Wai4482ab52019-12-10 19:08:18 +00001634 mInstaller = new Installer(mContext);
1635 mInstaller.onStart();
1636
Christopher Tate7265abe2014-11-21 13:54:45 -08001637 // Initialize the last-fstrim tracking if necessary
1638 File dataDir = Environment.getDataDirectory();
1639 File systemDir = new File(dataDir, "system");
1640 mLastMaintenanceFile = new File(systemDir, LAST_FSTRIM_FILE);
1641 if (!mLastMaintenanceFile.exists()) {
1642 // Not setting mLastMaintenance here means that we will force an
1643 // fstrim during reboot following the OTA that installs this code.
1644 try {
1645 (new FileOutputStream(mLastMaintenanceFile)).close();
1646 } catch (IOException e) {
1647 Slog.e(TAG, "Unable to create fstrim record " + mLastMaintenanceFile.getPath());
1648 }
1649 } else {
1650 mLastMaintenance = mLastMaintenanceFile.lastModified();
1651 }
1652
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001653 mSettingsFile = new AtomicFile(
Dianne Hackborne17b4452018-01-10 13:15:40 -08001654 new File(Environment.getDataSystemDirectory(), "storage.xml"), "storage-settings");
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001655
1656 synchronized (mLock) {
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001657 readSettingsLocked();
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001658 }
1659
Sudheer Shanka2250d562016-11-07 15:41:02 -08001660 LocalServices.addService(StorageManagerInternal.class, mStorageManagerInternal);
Svet Ganov6ee871e2015-07-10 14:29:33 -07001661
Jeff Sharkeybcd262d2015-06-10 09:41:17 -07001662 final IntentFilter userFilter = new IntentFilter();
1663 userFilter.addAction(Intent.ACTION_USER_ADDED);
1664 userFilter.addAction(Intent.ACTION_USER_REMOVED);
1665 mContext.registerReceiver(mUserReceiver, userFilter, null, mHandler);
1666
Jeff Sharkey5a9bb742015-11-03 10:15:57 -08001667 synchronized (mLock) {
1668 addInternalVolumeLocked();
1669 }
Amith Yamasania7892482015-08-07 11:09:05 -07001670
Kenny Root07714d42011-08-17 17:49:28 -07001671 // Add ourself to the Watchdog monitors if enabled.
1672 if (WATCHDOG_ENABLE) {
1673 Watchdog.getInstance().addMonitor(this);
1674 }
San Mehat207e5382010-02-04 20:46:54 -08001675 }
1676
Abhijeet Kaurb9847712019-11-19 16:35:47 +00001677 /**
1678 * Checks if user changed the persistent settings_fuse flag from Settings UI
1679 * and updates PROP_FUSE (reboots if changed).
1680 */
1681 private void updateFusePropFromSettings() {
Abhijeet Kaura4f40562019-12-09 13:55:42 +00001682 String settingsFuseFlag = SystemProperties.get(StorageManager.PROP_SETTINGS_FUSE);
1683 Slog.d(TAG, "The value of Settings Fuse Flag is "
1684 + (settingsFuseFlag == null || settingsFuseFlag.isEmpty()
1685 ? "null" : settingsFuseFlag));
1686 // Set default value of PROP_SETTINGS_FUSE and PROP_FUSE if it
1687 // is unset (neither true nor false, this happens only on the first boot
1688 // after wiping data partition).
1689 if (settingsFuseFlag == null || settingsFuseFlag.isEmpty()) {
1690 SystemProperties.set(StorageManager.PROP_SETTINGS_FUSE, "false");
1691 SystemProperties.set(StorageManager.PROP_FUSE, "false");
1692 return;
1693 }
1694
1695 if (!SystemProperties.get(StorageManager.PROP_FUSE).equals(settingsFuseFlag)) {
Abhijeet Kaurb9847712019-11-19 16:35:47 +00001696 Slog.d(TAG, "Set persist.sys.fuse to " + settingsFuseFlag);
Abhijeet Kaura4f40562019-12-09 13:55:42 +00001697 SystemProperties.set(StorageManager.PROP_FUSE, settingsFuseFlag);
Abhijeet Kaurb9847712019-11-19 16:35:47 +00001698 // Perform hard reboot to kick policy into place
1699 mContext.getSystemService(PowerManager.class).reboot("Reboot device for FUSE system"
1700 + "property change to take effect");
1701 }
1702 }
1703
Jeff Sharkeycd575992016-03-29 14:12:49 -06001704 private void start() {
peter.zhangb0d11d12019-06-13 16:39:30 +08001705 connectStoraged();
1706 connectVold();
Jeff Sharkeycd575992016-03-29 14:12:49 -06001707 }
1708
peter.zhangb0d11d12019-06-13 16:39:30 +08001709 private void connectStoraged() {
Jin Qian12690d52017-10-13 18:17:04 -07001710 IBinder binder = ServiceManager.getService("storaged");
1711 if (binder != null) {
1712 try {
1713 binder.linkToDeath(new DeathRecipient() {
1714 @Override
1715 public void binderDied() {
1716 Slog.w(TAG, "storaged died; reconnecting");
1717 mStoraged = null;
peter.zhangb0d11d12019-06-13 16:39:30 +08001718 connectStoraged();
Jin Qian12690d52017-10-13 18:17:04 -07001719 }
1720 }, 0);
1721 } catch (RemoteException e) {
1722 binder = null;
1723 }
1724 }
1725
1726 if (binder != null) {
1727 mStoraged = IStoraged.Stub.asInterface(binder);
1728 } else {
1729 Slog.w(TAG, "storaged not found; trying again");
1730 }
1731
peter.zhangb0d11d12019-06-13 16:39:30 +08001732 if (mStoraged == null) {
1733 BackgroundThread.getHandler().postDelayed(() -> {
1734 connectStoraged();
1735 }, DateUtils.SECOND_IN_MILLIS);
1736 } else {
1737 onDaemonConnected();
1738 }
1739 }
1740
1741 private void connectVold() {
1742 IBinder binder = ServiceManager.getService("vold");
Jeff Sharkey1019de92017-09-06 13:47:03 -06001743 if (binder != null) {
1744 try {
1745 binder.linkToDeath(new DeathRecipient() {
1746 @Override
1747 public void binderDied() {
1748 Slog.w(TAG, "vold died; reconnecting");
Jin Qian12690d52017-10-13 18:17:04 -07001749 mVold = null;
peter.zhangb0d11d12019-06-13 16:39:30 +08001750 connectVold();
Jeff Sharkey1019de92017-09-06 13:47:03 -06001751 }
1752 }, 0);
1753 } catch (RemoteException e) {
1754 binder = null;
1755 }
1756 }
1757
1758 if (binder != null) {
1759 mVold = IVold.Stub.asInterface(binder);
Jeff Sharkey8058fe62017-09-13 11:50:33 -06001760 try {
1761 mVold.setListener(mListener);
Jeff Sharkey8058fe62017-09-13 11:50:33 -06001762 } catch (RemoteException e) {
Jin Qian12690d52017-10-13 18:17:04 -07001763 mVold = null;
Jeff Sharkey8058fe62017-09-13 11:50:33 -06001764 Slog.w(TAG, "vold listener rejected; trying again", e);
1765 }
Jeff Sharkey1019de92017-09-06 13:47:03 -06001766 } else {
1767 Slog.w(TAG, "vold not found; trying again");
Jeff Sharkey1019de92017-09-06 13:47:03 -06001768 }
Jeff Sharkey8058fe62017-09-13 11:50:33 -06001769
peter.zhangb0d11d12019-06-13 16:39:30 +08001770 if (mVold == null) {
Jin Qian12690d52017-10-13 18:17:04 -07001771 BackgroundThread.getHandler().postDelayed(() -> {
peter.zhangb0d11d12019-06-13 16:39:30 +08001772 connectVold();
Jin Qian12690d52017-10-13 18:17:04 -07001773 }, DateUtils.SECOND_IN_MILLIS);
1774 } else {
1775 onDaemonConnected();
1776 }
Jeff Sharkey1019de92017-09-06 13:47:03 -06001777 }
1778
Jeff Sharkey11697f52018-12-13 10:14:42 -07001779 private void servicesReady() {
Sudheer Shankaff585072019-01-29 23:19:45 -08001780 mPmInternal = LocalServices.getService(PackageManagerInternal.class);
Sudheer Shankaff585072019-01-29 23:19:45 -08001781
1782 mIPackageManager = IPackageManager.Stub.asInterface(
1783 ServiceManager.getService("package"));
1784 mIAppOpsService = IAppOpsService.Stub.asInterface(
1785 ServiceManager.getService(Context.APP_OPS_SERVICE));
Zim74a9bba2019-09-03 20:49:13 +01001786
1787 ProviderInfo provider = mPmInternal.resolveContentProvider(
1788 MediaStore.AUTHORITY, PackageManager.MATCH_DIRECT_BOOT_AWARE
1789 | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
1790 UserHandle.getUserId(UserHandle.USER_SYSTEM));
1791 if (provider != null) {
Martijn Coenen44db1ac2019-12-03 16:06:19 +01001792 mMediaStoreAuthorityAppId = UserHandle.getAppId(provider.applicationInfo.uid);
Zim74a9bba2019-09-03 20:49:13 +01001793 }
1794
Martijn Coenen496ac002020-01-08 14:55:53 +01001795 provider = mPmInternal.resolveContentProvider(
1796 Downloads.Impl.AUTHORITY, PackageManager.MATCH_DIRECT_BOOT_AWARE
1797 | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
1798 UserHandle.getUserId(UserHandle.USER_SYSTEM));
1799
1800 if (provider != null) {
1801 mDownloadsAuthorityAppId = UserHandle.getAppId(provider.applicationInfo.uid);
1802 }
1803
Sudheer Shankaff585072019-01-29 23:19:45 -08001804 try {
1805 mIAppOpsService.startWatchingMode(OP_REQUEST_INSTALL_PACKAGES, null, mAppOpsCallback);
Sudheer Shanka783c90e2019-04-12 13:55:20 -07001806 mIAppOpsService.startWatchingMode(OP_LEGACY_STORAGE, null, mAppOpsCallback);
Sudheer Shankaff585072019-01-29 23:19:45 -08001807 } catch (RemoteException e) {
1808 }
Jeff Sharkey11697f52018-12-13 10:14:42 -07001809 }
1810
1811 private static long getLastAccessTime(AppOpsManager manager,
1812 int uid, String packageName, int[] ops) {
1813 long maxTime = 0;
1814 final List<AppOpsManager.PackageOps> pkgs = manager.getOpsForPackage(uid, packageName, ops);
Eugene Susla04d021c2018-12-17 14:49:59 -08001815 for (AppOpsManager.PackageOps pkg : CollectionUtils.emptyIfNull(pkgs)) {
1816 for (AppOpsManager.OpEntry op : CollectionUtils.emptyIfNull(pkg.getOps())) {
Svet Ganovaf189e32019-02-15 18:45:29 -08001817 maxTime = Math.max(maxTime, op.getLastAccessTime(
1818 AppOpsManager.OP_FLAGS_ALL_TRUSTED));
Jeff Sharkey11697f52018-12-13 10:14:42 -07001819 }
1820 }
1821 return maxTime;
1822 }
1823
Jeff Sharkey56e62932015-03-21 20:41:00 -07001824 private void systemReady() {
Wale Ogunwale6767eae2018-05-03 15:52:51 -07001825 LocalServices.getService(ActivityTaskManagerInternal.class)
Jeff Sharkey9765e442017-12-14 22:15:14 -07001826 .registerScreenObserver(this);
1827
Jeff Sharkeyb049e212012-09-07 23:16:01 -07001828 mHandler.obtainMessage(H_SYSTEM_READY).sendToTarget();
1829 }
1830
Yasuhiro Matsuda87a38b52015-07-24 22:10:16 +09001831 private void bootCompleted() {
1832 mBootCompleted = true;
Daniel Rosenberg137aed12019-03-15 18:41:11 -07001833 mHandler.obtainMessage(H_BOOT_COMPLETED).sendToTarget();
Abhijeet Kaur10c56552019-12-04 14:17:40 +00001834 updateFusePropFromSettings();
Daniel Rosenberg137aed12019-03-15 18:41:11 -07001835 }
1836
1837 private void handleBootCompleted() {
1838 initIfBootedAndConnected();
1839 resetIfBootedAndConnected();
Yasuhiro Matsuda87a38b52015-07-24 22:10:16 +09001840 }
1841
Jeff Sharkeyfced5342015-05-10 14:53:34 -07001842 private String getDefaultPrimaryStorageUuid() {
1843 if (SystemProperties.getBoolean(StorageManager.PROP_PRIMARY_PHYSICAL, false)) {
1844 return StorageManager.UUID_PRIMARY_PHYSICAL;
1845 } else {
1846 return StorageManager.UUID_PRIVATE_INTERNAL;
1847 }
1848 }
1849
Andreas Gampea36dc622018-02-05 17:19:22 -08001850 @GuardedBy("mLock")
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001851 private void readSettingsLocked() {
1852 mRecords.clear();
Jeff Sharkeyfced5342015-05-10 14:53:34 -07001853 mPrimaryStorageUuid = getDefaultPrimaryStorageUuid();
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001854
1855 FileInputStream fis = null;
1856 try {
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001857 fis = mSettingsFile.openRead();
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001858 final XmlPullParser in = Xml.newPullParser();
Wojciech Staszkiewicz9e9e2e72015-05-08 14:58:46 +01001859 in.setInput(fis, StandardCharsets.UTF_8.name());
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001860
1861 int type;
1862 while ((type = in.next()) != END_DOCUMENT) {
1863 if (type == START_TAG) {
1864 final String tag = in.getName();
Jeff Sharkey620b32b2015-04-23 19:36:02 -07001865 if (TAG_VOLUMES.equals(tag)) {
1866 final int version = readIntAttribute(in, ATTR_VERSION, VERSION_INIT);
Jeff Sharkeyfced5342015-05-10 14:53:34 -07001867 final boolean primaryPhysical = SystemProperties.getBoolean(
1868 StorageManager.PROP_PRIMARY_PHYSICAL, false);
1869 final boolean validAttr = (version >= VERSION_FIX_PRIMARY)
1870 || (version >= VERSION_ADD_PRIMARY && !primaryPhysical);
1871 if (validAttr) {
Jeff Sharkey620b32b2015-04-23 19:36:02 -07001872 mPrimaryStorageUuid = readStringAttribute(in,
1873 ATTR_PRIMARY_STORAGE_UUID);
Jeff Sharkey620b32b2015-04-23 19:36:02 -07001874 }
Jeff Sharkey620b32b2015-04-23 19:36:02 -07001875 } else if (TAG_VOLUME.equals(tag)) {
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001876 final VolumeRecord rec = readVolumeRecord(in);
1877 mRecords.put(rec.fsUuid, rec);
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001878 }
1879 }
1880 }
1881 } catch (FileNotFoundException e) {
1882 // Missing metadata is okay, probably first boot
1883 } catch (IOException e) {
1884 Slog.wtf(TAG, "Failed reading metadata", e);
1885 } catch (XmlPullParserException e) {
1886 Slog.wtf(TAG, "Failed reading metadata", e);
1887 } finally {
1888 IoUtils.closeQuietly(fis);
1889 }
1890 }
1891
Andreas Gampea36dc622018-02-05 17:19:22 -08001892 @GuardedBy("mLock")
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001893 private void writeSettingsLocked() {
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001894 FileOutputStream fos = null;
1895 try {
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001896 fos = mSettingsFile.startWrite();
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001897
1898 XmlSerializer out = new FastXmlSerializer();
Wojciech Staszkiewicz9e9e2e72015-05-08 14:58:46 +01001899 out.setOutput(fos, StandardCharsets.UTF_8.name());
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001900 out.startDocument(null, true);
1901 out.startTag(null, TAG_VOLUMES);
Jeff Sharkeyfced5342015-05-10 14:53:34 -07001902 writeIntAttribute(out, ATTR_VERSION, VERSION_FIX_PRIMARY);
Jeff Sharkey620b32b2015-04-23 19:36:02 -07001903 writeStringAttribute(out, ATTR_PRIMARY_STORAGE_UUID, mPrimaryStorageUuid);
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001904 final int size = mRecords.size();
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001905 for (int i = 0; i < size; i++) {
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001906 final VolumeRecord rec = mRecords.valueAt(i);
1907 writeVolumeRecord(out, rec);
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001908 }
1909 out.endTag(null, TAG_VOLUMES);
1910 out.endDocument();
1911
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001912 mSettingsFile.finishWrite(fos);
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001913 } catch (IOException e) {
1914 if (fos != null) {
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001915 mSettingsFile.failWrite(fos);
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001916 }
1917 }
1918 }
1919
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001920 public static VolumeRecord readVolumeRecord(XmlPullParser in) throws IOException {
1921 final int type = readIntAttribute(in, ATTR_TYPE);
1922 final String fsUuid = readStringAttribute(in, ATTR_FS_UUID);
1923 final VolumeRecord meta = new VolumeRecord(type, fsUuid);
Jeff Sharkey5cc0df22015-06-17 19:44:05 -07001924 meta.partGuid = readStringAttribute(in, ATTR_PART_GUID);
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001925 meta.nickname = readStringAttribute(in, ATTR_NICKNAME);
1926 meta.userFlags = readIntAttribute(in, ATTR_USER_FLAGS);
Jeff Sharkey3811f352019-05-14 11:54:36 -06001927 meta.createdMillis = readLongAttribute(in, ATTR_CREATED_MILLIS, 0);
1928 meta.lastSeenMillis = readLongAttribute(in, ATTR_LAST_SEEN_MILLIS, 0);
1929 meta.lastTrimMillis = readLongAttribute(in, ATTR_LAST_TRIM_MILLIS, 0);
1930 meta.lastBenchMillis = readLongAttribute(in, ATTR_LAST_BENCH_MILLIS, 0);
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001931 return meta;
1932 }
1933
1934 public static void writeVolumeRecord(XmlSerializer out, VolumeRecord rec) throws IOException {
1935 out.startTag(null, TAG_VOLUME);
1936 writeIntAttribute(out, ATTR_TYPE, rec.type);
1937 writeStringAttribute(out, ATTR_FS_UUID, rec.fsUuid);
Jeff Sharkey5cc0df22015-06-17 19:44:05 -07001938 writeStringAttribute(out, ATTR_PART_GUID, rec.partGuid);
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001939 writeStringAttribute(out, ATTR_NICKNAME, rec.nickname);
1940 writeIntAttribute(out, ATTR_USER_FLAGS, rec.userFlags);
Jeff Sharkeye8a4b662015-06-27 15:43:45 -07001941 writeLongAttribute(out, ATTR_CREATED_MILLIS, rec.createdMillis);
Jeff Sharkey3811f352019-05-14 11:54:36 -06001942 writeLongAttribute(out, ATTR_LAST_SEEN_MILLIS, rec.lastSeenMillis);
Jeff Sharkeye8a4b662015-06-27 15:43:45 -07001943 writeLongAttribute(out, ATTR_LAST_TRIM_MILLIS, rec.lastTrimMillis);
1944 writeLongAttribute(out, ATTR_LAST_BENCH_MILLIS, rec.lastBenchMillis);
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001945 out.endTag(null, TAG_VOLUME);
1946 }
1947
San Mehat207e5382010-02-04 20:46:54 -08001948 /**
San Mehat4270e1e2010-01-29 05:32:19 -08001949 * Exposed API calls below here
1950 */
1951
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001952 @Override
Sudheer Shanka2250d562016-11-07 15:41:02 -08001953 public void registerListener(IStorageEventListener listener) {
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001954 mCallbacks.register(listener);
San Mehat4270e1e2010-01-29 05:32:19 -08001955 }
1956
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001957 @Override
Sudheer Shanka2250d562016-11-07 15:41:02 -08001958 public void unregisterListener(IStorageEventListener listener) {
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001959 mCallbacks.unregister(listener);
San Mehat4270e1e2010-01-29 05:32:19 -08001960 }
1961
Jeff Sharkey48877892015-03-18 11:27:19 -07001962 @Override
Sudheer Shanka2250d562016-11-07 15:41:02 -08001963 public void shutdown(final IStorageShutdownObserver observer) {
Jeff Sharkey48877892015-03-18 11:27:19 -07001964 enforcePermission(android.Manifest.permission.SHUTDOWN);
San Mehat4270e1e2010-01-29 05:32:19 -08001965
San Mehata5078592010-03-25 09:36:54 -07001966 Slog.i(TAG, "Shutting down");
Jeff Sharkey48877892015-03-18 11:27:19 -07001967 mHandler.obtainMessage(H_SHUTDOWN, observer).sendToTarget();
San Mehat4270e1e2010-01-29 05:32:19 -08001968 }
1969
Jeff Sharkey48877892015-03-18 11:27:19 -07001970 @Override
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001971 public void mount(String volId) {
1972 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001973
Jeff Sharkeyef10ee02015-07-05 14:17:27 -07001974 final VolumeInfo vol = findVolumeByIdOrThrow(volId);
Jeff Sharkey2e606d72015-07-27 14:19:54 -07001975 if (isMountDisallowed(vol)) {
1976 throw new SecurityException("Mounting " + volId + " restricted by policy");
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001977 }
Zim17be6f92019-09-25 14:37:55 +01001978
Sudheer Shanka3f0645b2018-09-18 13:07:59 -07001979 mount(vol);
1980 }
1981
Zim17be6f92019-09-25 14:37:55 +01001982 private void mount(VolumeInfo vol) {
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001983 try {
Zim17be6f92019-09-25 14:37:55 +01001984 // TODO(b/135341433): Remove paranoid logging when FUSE is stable
1985 Slog.i(TAG, "Mounting volume " + vol);
Zim95eca1d2019-11-15 18:03:00 +00001986 mVold.mount(vol.id, vol.mountFlags, vol.mountUserId, new IVoldMountCallback.Stub() {
1987 @Override
1988 public boolean onVolumeChecking(FileDescriptor deviceFd, String path,
1989 String internalPath) {
1990 vol.path = path;
1991 vol.internalPath = internalPath;
1992 try {
1993 mStorageSessionController.onVolumeMount(deviceFd, vol);
1994 return true;
1995 } catch (ExternalStorageServiceException e) {
1996 Slog.i(TAG, "Failed to mount volume " + vol, e);
1997 return false;
1998 }
1999 }
2000 });
Zim17be6f92019-09-25 14:37:55 +01002001 Slog.i(TAG, "Mounted volume " + vol);
Jeff Sharkeyace874b2017-09-07 15:27:33 -06002002 } catch (Exception e) {
2003 Slog.wtf(TAG, e);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07002004 }
2005 }
2006
2007 @Override
2008 public void unmount(String volId) {
2009 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07002010
Jeff Sharkeyef10ee02015-07-05 14:17:27 -07002011 final VolumeInfo vol = findVolumeByIdOrThrow(volId);
Sudheer Shanka3f0645b2018-09-18 13:07:59 -07002012 unmount(vol);
2013 }
2014
2015 private void unmount(VolumeInfo vol) {
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07002016 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002017 mVold.unmount(vol.id);
Zim17be6f92019-09-25 14:37:55 +01002018 mStorageSessionController.onVolumeUnmount(vol);
Ricky Wai4482ab52019-12-10 19:08:18 +00002019 try {
2020 if (vol.type == VolumeInfo.TYPE_PRIVATE) {
2021 mInstaller.onPrivateVolumeRemoved(vol.getFsUuid());
2022 }
2023 } catch (Installer.InstallerException e) {
2024 Slog.e(TAG, "Failed unmount mirror data", e);
2025 }
Jeff Sharkeyace874b2017-09-07 15:27:33 -06002026 } catch (Exception e) {
2027 Slog.wtf(TAG, e);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07002028 }
2029 }
2030
2031 @Override
2032 public void format(String volId) {
Jeff Sharkey48877892015-03-18 11:27:19 -07002033 enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);
San Mehat5b77dab2010-01-26 13:28:50 -08002034
Jeff Sharkeyef10ee02015-07-05 14:17:27 -07002035 final VolumeInfo vol = findVolumeByIdOrThrow(volId);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07002036 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002037 mVold.format(vol.id, "auto");
Jeff Sharkeyace874b2017-09-07 15:27:33 -06002038 } catch (Exception e) {
2039 Slog.wtf(TAG, e);
Jeff Sharkey48877892015-03-18 11:27:19 -07002040 }
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07002041 }
2042
2043 @Override
Jeff Sharkey7e19f532017-11-06 13:54:11 -07002044 public void benchmark(String volId, IVoldTaskListener listener) {
Jeff Sharkey9756d752015-05-14 21:07:42 -07002045 enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);
Jeff Sharkey9756d752015-05-14 21:07:42 -07002046
2047 try {
Jeff Sharkeyb302c542017-09-15 12:57:59 -06002048 mVold.benchmark(volId, new IVoldTaskListener.Stub() {
2049 @Override
2050 public void onStatus(int status, PersistableBundle extras) {
Jeff Sharkey7e19f532017-11-06 13:54:11 -07002051 dispatchOnStatus(listener, status, extras);
Jeff Sharkeyb302c542017-09-15 12:57:59 -06002052 }
2053
2054 @Override
2055 public void onFinished(int status, PersistableBundle extras) {
Jeff Sharkey7e19f532017-11-06 13:54:11 -07002056 dispatchOnFinished(listener, status, extras);
Jeff Sharkeyb302c542017-09-15 12:57:59 -06002057
2058 final String path = extras.getString("path");
2059 final String ident = extras.getString("ident");
2060 final long create = extras.getLong("create");
2061 final long run = extras.getLong("run");
2062 final long destroy = extras.getLong("destroy");
2063
2064 final DropBoxManager dropBox = mContext.getSystemService(DropBoxManager.class);
2065 dropBox.addText(TAG_STORAGE_BENCHMARK, scrubPath(path)
2066 + " " + ident + " " + create + " " + run + " " + destroy);
2067
2068 synchronized (mLock) {
2069 final VolumeRecord rec = findRecordForPath(path);
2070 if (rec != null) {
2071 rec.lastBenchMillis = System.currentTimeMillis();
2072 writeSettingsLocked();
2073 }
2074 }
2075 }
2076 });
Jeff Sharkey7e19f532017-11-06 13:54:11 -07002077 } catch (RemoteException e) {
2078 throw e.rethrowAsRuntimeException();
Jeff Sharkey9756d752015-05-14 21:07:42 -07002079 }
2080 }
2081
2082 @Override
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07002083 public void partitionPublic(String diskId) {
2084 enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07002085
Jeff Sharkeyeba260d2015-04-19 14:35:16 -07002086 final CountDownLatch latch = findOrCreateDiskScanLatch(diskId);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07002087 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002088 mVold.partition(diskId, IVold.PARTITION_TYPE_PUBLIC, -1);
Jeff Sharkeyedcdaf62015-07-09 09:45:36 -07002089 waitForLatch(latch, "partitionPublic", 3 * DateUtils.MINUTE_IN_MILLIS);
Jeff Sharkeyace874b2017-09-07 15:27:33 -06002090 } catch (Exception e) {
2091 Slog.wtf(TAG, e);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07002092 }
2093 }
2094
2095 @Override
2096 public void partitionPrivate(String diskId) {
2097 enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);
Amith Yamasani462ac3a2015-06-30 14:21:01 -07002098 enforceAdminUser();
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07002099
Jeff Sharkeyeba260d2015-04-19 14:35:16 -07002100 final CountDownLatch latch = findOrCreateDiskScanLatch(diskId);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07002101 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002102 mVold.partition(diskId, IVold.PARTITION_TYPE_PRIVATE, -1);
Jeff Sharkeyedcdaf62015-07-09 09:45:36 -07002103 waitForLatch(latch, "partitionPrivate", 3 * DateUtils.MINUTE_IN_MILLIS);
Jeff Sharkeyace874b2017-09-07 15:27:33 -06002104 } catch (Exception e) {
2105 Slog.wtf(TAG, e);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07002106 }
2107 }
2108
2109 @Override
2110 public void partitionMixed(String diskId, int ratio) {
2111 enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);
Amith Yamasani462ac3a2015-06-30 14:21:01 -07002112 enforceAdminUser();
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07002113
Jeff Sharkeyeba260d2015-04-19 14:35:16 -07002114 final CountDownLatch latch = findOrCreateDiskScanLatch(diskId);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07002115 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002116 mVold.partition(diskId, IVold.PARTITION_TYPE_MIXED, ratio);
Jeff Sharkeyedcdaf62015-07-09 09:45:36 -07002117 waitForLatch(latch, "partitionMixed", 3 * DateUtils.MINUTE_IN_MILLIS);
Jeff Sharkeyace874b2017-09-07 15:27:33 -06002118 } catch (Exception e) {
2119 Slog.wtf(TAG, e);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07002120 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002121 }
2122
Jeff Sharkey48877892015-03-18 11:27:19 -07002123 @Override
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07002124 public void setVolumeNickname(String fsUuid, String nickname) {
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07002125 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07002126
Daulet Zhanguzinea1a7ca2020-01-03 09:46:50 +00002127 Objects.requireNonNull(fsUuid);
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07002128 synchronized (mLock) {
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07002129 final VolumeRecord rec = mRecords.get(fsUuid);
2130 rec.nickname = nickname;
Jeff Sharkey50a05452015-04-29 11:24:52 -07002131 mCallbacks.notifyVolumeRecordChanged(rec);
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07002132 writeSettingsLocked();
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07002133 }
2134 }
2135
2136 @Override
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07002137 public void setVolumeUserFlags(String fsUuid, int flags, int mask) {
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07002138 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07002139
Daulet Zhanguzinea1a7ca2020-01-03 09:46:50 +00002140 Objects.requireNonNull(fsUuid);
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07002141 synchronized (mLock) {
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07002142 final VolumeRecord rec = mRecords.get(fsUuid);
2143 rec.userFlags = (rec.userFlags & ~mask) | (flags & mask);
Jeff Sharkey50a05452015-04-29 11:24:52 -07002144 mCallbacks.notifyVolumeRecordChanged(rec);
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07002145 writeSettingsLocked();
2146 }
2147 }
2148
2149 @Override
2150 public void forgetVolume(String fsUuid) {
2151 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07002152
Daulet Zhanguzinea1a7ca2020-01-03 09:46:50 +00002153 Objects.requireNonNull(fsUuid);
Jeff Sharkey5a9bb742015-11-03 10:15:57 -08002154
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07002155 synchronized (mLock) {
Jeff Sharkey5cc0df22015-06-17 19:44:05 -07002156 final VolumeRecord rec = mRecords.remove(fsUuid);
2157 if (rec != null && !TextUtils.isEmpty(rec.partGuid)) {
Jeff Sharkeydb4b6192017-10-24 11:08:50 -06002158 mHandler.obtainMessage(H_PARTITION_FORGET, rec).sendToTarget();
Jeff Sharkey5cc0df22015-06-17 19:44:05 -07002159 }
2160 mCallbacks.notifyVolumeForgotten(fsUuid);
Jeff Sharkey50a05452015-04-29 11:24:52 -07002161
2162 // If this had been primary storage, revert back to internal and
2163 // reset vold so we bind into new volume into place.
2164 if (Objects.equals(mPrimaryStorageUuid, fsUuid)) {
Jeff Sharkeyfced5342015-05-10 14:53:34 -07002165 mPrimaryStorageUuid = getDefaultPrimaryStorageUuid();
Jeff Sharkey5a9bb742015-11-03 10:15:57 -08002166 mHandler.obtainMessage(H_RESET).sendToTarget();
Jeff Sharkey50a05452015-04-29 11:24:52 -07002167 }
2168
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07002169 writeSettingsLocked();
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07002170 }
2171 }
2172
Jeff Sharkey7d2af542015-05-12 15:27:15 -07002173 @Override
2174 public void forgetAllVolumes() {
2175 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
Jeff Sharkey7d2af542015-05-12 15:27:15 -07002176
Jeff Sharkey50a05452015-04-29 11:24:52 -07002177 synchronized (mLock) {
2178 for (int i = 0; i < mRecords.size(); i++) {
2179 final String fsUuid = mRecords.keyAt(i);
Jeff Sharkey5cc0df22015-06-17 19:44:05 -07002180 final VolumeRecord rec = mRecords.valueAt(i);
2181 if (!TextUtils.isEmpty(rec.partGuid)) {
Jeff Sharkeydb4b6192017-10-24 11:08:50 -06002182 mHandler.obtainMessage(H_PARTITION_FORGET, rec).sendToTarget();
Jeff Sharkey5cc0df22015-06-17 19:44:05 -07002183 }
Jeff Sharkey50a05452015-04-29 11:24:52 -07002184 mCallbacks.notifyVolumeForgotten(fsUuid);
2185 }
Jeff Sharkey50a05452015-04-29 11:24:52 -07002186 mRecords.clear();
Jeff Sharkey50a05452015-04-29 11:24:52 -07002187
Jeff Sharkeyfced5342015-05-10 14:53:34 -07002188 if (!Objects.equals(StorageManager.UUID_PRIVATE_INTERNAL, mPrimaryStorageUuid)) {
2189 mPrimaryStorageUuid = getDefaultPrimaryStorageUuid();
2190 }
2191
2192 writeSettingsLocked();
Jeff Sharkey5a9bb742015-11-03 10:15:57 -08002193 mHandler.obtainMessage(H_RESET).sendToTarget();
Jeff Sharkey50a05452015-04-29 11:24:52 -07002194 }
2195 }
2196
Jeff Sharkeydb4b6192017-10-24 11:08:50 -06002197 private void forgetPartition(String partGuid, String fsUuid) {
Jeff Sharkey5cc0df22015-06-17 19:44:05 -07002198 try {
Jeff Sharkeydb4b6192017-10-24 11:08:50 -06002199 mVold.forgetPartition(partGuid, fsUuid);
Jeff Sharkeyace874b2017-09-07 15:27:33 -06002200 } catch (Exception e) {
2201 Slog.wtf(TAG, e);
Jeff Sharkey5cc0df22015-06-17 19:44:05 -07002202 }
2203 }
2204
Jeff Sharkey31d0b702016-11-21 14:16:53 -07002205 @Override
Jeff Sharkey7e19f532017-11-06 13:54:11 -07002206 public void fstrim(int flags, IVoldTaskListener listener) {
Jeff Sharkey31d0b702016-11-21 14:16:53 -07002207 enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);
Jeff Sharkey31d0b702016-11-21 14:16:53 -07002208
2209 try {
Sandeep Patil7d5c4912019-04-15 09:27:30 -07002210 // Block based checkpoint process runs fstrim. So, if checkpoint is in progress
2211 // (first boot after OTA), We skip idle maintenance and make sure the last
2212 // fstrim time is still updated. If file based checkpoints are used, we run
2213 // idle maintenance (GC + fstrim) regardless of checkpoint status.
2214 if (!needsCheckpoint() || !supportsBlockCheckpoint()) {
2215 mVold.fstrim(flags, new IVoldTaskListener.Stub() {
2216 @Override
2217 public void onStatus(int status, PersistableBundle extras) {
2218 dispatchOnStatus(listener, status, extras);
Jeff Sharkey7e19f532017-11-06 13:54:11 -07002219
Sandeep Patil7d5c4912019-04-15 09:27:30 -07002220 // Ignore trim failures
2221 if (status != 0) return;
Jeff Sharkeyb302c542017-09-15 12:57:59 -06002222
Sandeep Patil7d5c4912019-04-15 09:27:30 -07002223 final String path = extras.getString("path");
2224 final long bytes = extras.getLong("bytes");
2225 final long time = extras.getLong("time");
Jeff Sharkeyb302c542017-09-15 12:57:59 -06002226
Sandeep Patil7d5c4912019-04-15 09:27:30 -07002227 final DropBoxManager dropBox = mContext.getSystemService(DropBoxManager.class);
2228 dropBox.addText(TAG_STORAGE_TRIM, scrubPath(path) + " " + bytes + " " + time);
Jeff Sharkeyb302c542017-09-15 12:57:59 -06002229
Sandeep Patil7d5c4912019-04-15 09:27:30 -07002230 synchronized (mLock) {
2231 final VolumeRecord rec = findRecordForPath(path);
2232 if (rec != null) {
2233 rec.lastTrimMillis = System.currentTimeMillis();
2234 writeSettingsLocked();
2235 }
Jeff Sharkeyb302c542017-09-15 12:57:59 -06002236 }
2237 }
Jeff Sharkeyb302c542017-09-15 12:57:59 -06002238
Sandeep Patil7d5c4912019-04-15 09:27:30 -07002239 @Override
2240 public void onFinished(int status, PersistableBundle extras) {
2241 dispatchOnFinished(listener, status, extras);
Jeff Sharkey7e19f532017-11-06 13:54:11 -07002242
Sandeep Patil7d5c4912019-04-15 09:27:30 -07002243 // TODO: benchmark when desired
2244 }
2245 });
2246 } else {
2247 Slog.i(TAG, "Skipping fstrim - block based checkpoint in progress");
2248 }
Jeff Sharkey7e19f532017-11-06 13:54:11 -07002249 } catch (RemoteException e) {
2250 throw e.rethrowAsRuntimeException();
Jeff Sharkey31d0b702016-11-21 14:16:53 -07002251 }
2252 }
2253
Jin Qiana85b9912017-10-17 15:48:18 -07002254 void runIdleMaint(Runnable callback) {
2255 enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);
2256
2257 try {
Sandeep Patil7d5c4912019-04-15 09:27:30 -07002258 // Block based checkpoint process runs fstrim. So, if checkpoint is in progress
2259 // (first boot after OTA), We skip idle maintenance and make sure the last
2260 // fstrim time is still updated. If file based checkpoints are used, we run
2261 // idle maintenance (GC + fstrim) regardless of checkpoint status.
2262 if (!needsCheckpoint() || !supportsBlockCheckpoint()) {
2263 mVold.runIdleMaint(new IVoldTaskListener.Stub() {
2264 @Override
2265 public void onStatus(int status, PersistableBundle extras) {
2266 // Not currently used
Jin Qiana85b9912017-10-17 15:48:18 -07002267 }
Sandeep Patil7d5c4912019-04-15 09:27:30 -07002268 @Override
2269 public void onFinished(int status, PersistableBundle extras) {
2270 if (callback != null) {
2271 BackgroundThread.getHandler().post(callback);
2272 }
2273 }
2274 });
2275 } else {
2276 Slog.i(TAG, "Skipping idle maintenance - block based checkpoint in progress");
2277 }
Jin Qiana85b9912017-10-17 15:48:18 -07002278 } catch (Exception e) {
2279 Slog.wtf(TAG, e);
2280 }
2281 }
2282
2283 @Override
2284 public void runIdleMaintenance() {
2285 runIdleMaint(null);
2286 }
2287
2288 void abortIdleMaint(Runnable callback) {
2289 enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);
2290
2291 try {
2292 mVold.abortIdleMaint(new IVoldTaskListener.Stub() {
2293 @Override
2294 public void onStatus(int status, PersistableBundle extras) {
2295 // Not currently used
2296 }
2297 @Override
2298 public void onFinished(int status, PersistableBundle extras) {
2299 if (callback != null) {
2300 BackgroundThread.getHandler().post(callback);
2301 }
2302 }
2303 });
2304 } catch (Exception e) {
2305 Slog.wtf(TAG, e);
2306 }
2307 }
2308
2309 @Override
2310 public void abortIdleMaintenance() {
2311 abortIdleMaint(null);
2312 }
2313
Svet Ganov6ee871e2015-07-10 14:29:33 -07002314 private void remountUidExternalStorage(int uid, int mode) {
Zim4f1a24d2019-11-27 16:35:58 +00002315 if (uid == Process.SYSTEM_UID) {
2316 // No need to remount uid for system because it has all access anyways
2317 return;
2318 }
2319
Jeff Sharkey9527b222015-06-24 15:24:48 -07002320 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002321 mVold.remountUid(uid, mode);
Jeff Sharkeyace874b2017-09-07 15:27:33 -06002322 } catch (Exception e) {
2323 Slog.wtf(TAG, e);
Jeff Sharkey9527b222015-06-24 15:24:48 -07002324 }
2325 }
2326
2327 @Override
Jeff Sharkey4c099d02015-05-15 13:45:00 -07002328 public void setDebugFlags(int flags, int mask) {
2329 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
Jeff Sharkey4c099d02015-05-15 13:45:00 -07002330
Jeff Sharkeyba512352015-11-12 20:17:45 -08002331 if ((mask & StorageManager.DEBUG_EMULATE_FBE) != 0) {
Jeff Sharkey00455bf2016-11-04 14:45:24 -06002332 if (!EMULATE_FBE_SUPPORTED) {
2333 throw new IllegalStateException(
2334 "Emulation not supported on this device");
2335 }
Paul Lawrence20be5d62016-02-26 13:51:17 -08002336 if (StorageManager.isFileEncryptedNativeOnly()) {
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07002337 throw new IllegalStateException(
Jeff Sharkey00455bf2016-11-04 14:45:24 -06002338 "Emulation not supported on device with native FBE");
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07002339 }
Jeff Sharkey5a785162016-03-21 13:02:06 -06002340 if (mLockPatternUtils.isCredentialRequiredToDecrypt(false)) {
2341 throw new IllegalStateException(
2342 "Emulation requires disabling 'Secure start-up' in Settings > Security");
2343 }
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07002344
Jeff Sharkey1176e512016-02-29 17:01:26 -07002345 final long token = Binder.clearCallingIdentity();
2346 try {
2347 final boolean emulateFbe = (flags & StorageManager.DEBUG_EMULATE_FBE) != 0;
2348 SystemProperties.set(StorageManager.PROP_EMULATE_FBE, Boolean.toString(emulateFbe));
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07002349
Jeff Sharkey1176e512016-02-29 17:01:26 -07002350 // Perform hard reboot to kick policy into place
2351 mContext.getSystemService(PowerManager.class).reboot(null);
2352 } finally {
2353 Binder.restoreCallingIdentity(token);
2354 }
Jeff Sharkeyba512352015-11-12 20:17:45 -08002355 }
Jeff Sharkey4c099d02015-05-15 13:45:00 -07002356
Jeff Sharkey901c0422018-04-20 13:11:20 -06002357 if ((mask & (StorageManager.DEBUG_ADOPTABLE_FORCE_ON
2358 | StorageManager.DEBUG_ADOPTABLE_FORCE_OFF)) != 0) {
2359 final String value;
2360 if ((flags & StorageManager.DEBUG_ADOPTABLE_FORCE_ON) != 0) {
2361 value = "force_on";
2362 } else if ((flags & StorageManager.DEBUG_ADOPTABLE_FORCE_OFF) != 0) {
2363 value = "force_off";
2364 } else {
2365 value = "";
2366 }
Jeff Sharkeyba512352015-11-12 20:17:45 -08002367
Jeff Sharkey901c0422018-04-20 13:11:20 -06002368 final long token = Binder.clearCallingIdentity();
2369 try {
2370 SystemProperties.set(StorageManager.PROP_ADOPTABLE, value);
2371
2372 // Reset storage to kick new setting into place
Jeff Sharkeyba512352015-11-12 20:17:45 -08002373 mHandler.obtainMessage(H_RESET).sendToTarget();
Jeff Sharkey901c0422018-04-20 13:11:20 -06002374 } finally {
2375 Binder.restoreCallingIdentity(token);
Jeff Sharkeyba512352015-11-12 20:17:45 -08002376 }
Jeff Sharkey4c099d02015-05-15 13:45:00 -07002377 }
Jeff Sharkey33dd1562016-04-07 11:05:33 -06002378
2379 if ((mask & (StorageManager.DEBUG_SDCARDFS_FORCE_ON
2380 | StorageManager.DEBUG_SDCARDFS_FORCE_OFF)) != 0) {
2381 final String value;
2382 if ((flags & StorageManager.DEBUG_SDCARDFS_FORCE_ON) != 0) {
2383 value = "force_on";
2384 } else if ((flags & StorageManager.DEBUG_SDCARDFS_FORCE_OFF) != 0) {
2385 value = "force_off";
2386 } else {
2387 value = "";
2388 }
2389
2390 final long token = Binder.clearCallingIdentity();
2391 try {
2392 SystemProperties.set(StorageManager.PROP_SDCARDFS, value);
2393
2394 // Reset storage to kick new setting into place
2395 mHandler.obtainMessage(H_RESET).sendToTarget();
2396 } finally {
2397 Binder.restoreCallingIdentity(token);
2398 }
2399 }
Jeff Sharkeye53e2d92017-03-25 23:14:06 -06002400
2401 if ((mask & StorageManager.DEBUG_VIRTUAL_DISK) != 0) {
2402 final boolean enabled = (flags & StorageManager.DEBUG_VIRTUAL_DISK) != 0;
2403
2404 final long token = Binder.clearCallingIdentity();
2405 try {
2406 SystemProperties.set(StorageManager.PROP_VIRTUAL_DISK, Boolean.toString(enabled));
2407
2408 // Reset storage to kick new setting into place
2409 mHandler.obtainMessage(H_RESET).sendToTarget();
2410 } finally {
2411 Binder.restoreCallingIdentity(token);
2412 }
2413 }
Sudheer Shankabe0febe2018-11-07 18:24:37 -08002414
Jeff Sharkeyb0c363b22018-12-15 11:53:03 -07002415 if ((mask & (StorageManager.DEBUG_ISOLATED_STORAGE_FORCE_ON
2416 | StorageManager.DEBUG_ISOLATED_STORAGE_FORCE_OFF)) != 0) {
2417 final int value;
2418 if ((flags & StorageManager.DEBUG_ISOLATED_STORAGE_FORCE_ON) != 0) {
2419 value = 1;
2420 } else if ((flags & StorageManager.DEBUG_ISOLATED_STORAGE_FORCE_OFF) != 0) {
2421 value = -1;
2422 } else {
2423 value = 0;
2424 }
Sudheer Shankabe0febe2018-11-07 18:24:37 -08002425
2426 final long token = Binder.clearCallingIdentity();
2427 try {
Jeff Sharkeyb0c363b22018-12-15 11:53:03 -07002428 Settings.Global.putInt(mContext.getContentResolver(),
2429 Settings.Global.ISOLATED_STORAGE_LOCAL, value);
2430 refreshIsolatedStorageSettings();
Sudheer Shankabe0febe2018-11-07 18:24:37 -08002431
2432 // Perform hard reboot to kick policy into place
Jeff Sharkey36274992019-02-27 12:09:57 -07002433 mHandler.post(() -> {
2434 mContext.getSystemService(PowerManager.class).reboot(null);
2435 });
2436 } finally {
2437 Binder.restoreCallingIdentity(token);
2438 }
2439 }
Jeff Sharkey4c099d02015-05-15 13:45:00 -07002440 }
2441
2442 @Override
Jeff Sharkey275e3e42015-04-24 16:10:32 -07002443 public String getPrimaryStorageUuid() {
Jeff Sharkey620b32b2015-04-23 19:36:02 -07002444 synchronized (mLock) {
2445 return mPrimaryStorageUuid;
2446 }
2447 }
2448
2449 @Override
Jeff Sharkey275e3e42015-04-24 16:10:32 -07002450 public void setPrimaryStorageUuid(String volumeUuid, IPackageMoveObserver callback) {
2451 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
Jeff Sharkey620b32b2015-04-23 19:36:02 -07002452
Jeff Sharkeya31460c2016-06-22 09:04:33 -06002453 final VolumeInfo from;
2454 final VolumeInfo to;
2455
Jeff Sharkey275e3e42015-04-24 16:10:32 -07002456 synchronized (mLock) {
Jeff Sharkeyfced5342015-05-10 14:53:34 -07002457 if (Objects.equals(mPrimaryStorageUuid, volumeUuid)) {
2458 throw new IllegalArgumentException("Primary storage already at " + volumeUuid);
Jeff Sharkey275e3e42015-04-24 16:10:32 -07002459 }
2460
2461 if (mMoveCallback != null) {
2462 throw new IllegalStateException("Move already in progress");
2463 }
2464 mMoveCallback = callback;
2465 mMoveTargetUuid = volumeUuid;
2466
Jeff Sharkeya65e6492017-06-21 13:45:11 -06002467 // We need all the users unlocked to move their primary storage
2468 final List<UserInfo> users = mContext.getSystemService(UserManager.class).getUsers();
2469 for (UserInfo user : users) {
2470 if (StorageManager.isFileEncryptedNativeOrEmulated()
2471 && !isUserKeyUnlocked(user.id)) {
2472 Slog.w(TAG, "Failing move due to locked user " + user.id);
2473 onMoveStatusLocked(PackageManager.MOVE_FAILED_LOCKED_USER);
2474 return;
2475 }
2476 }
2477
Jeff Sharkeyfced5342015-05-10 14:53:34 -07002478 // When moving to/from primary physical volume, we probably just nuked
2479 // the current storage location, so we have nothing to move.
2480 if (Objects.equals(StorageManager.UUID_PRIMARY_PHYSICAL, mPrimaryStorageUuid)
2481 || Objects.equals(StorageManager.UUID_PRIMARY_PHYSICAL, volumeUuid)) {
2482 Slog.d(TAG, "Skipping move to/from primary physical");
2483 onMoveStatusLocked(MOVE_STATUS_COPY_FINISHED);
2484 onMoveStatusLocked(PackageManager.MOVE_SUCCEEDED);
Jeff Sharkey5a9bb742015-11-03 10:15:57 -08002485 mHandler.obtainMessage(H_RESET).sendToTarget();
Jeff Sharkeya31460c2016-06-22 09:04:33 -06002486 return;
Jeff Sharkeyfced5342015-05-10 14:53:34 -07002487
2488 } else {
Jeff Sharkeya31460c2016-06-22 09:04:33 -06002489 from = findStorageForUuid(mPrimaryStorageUuid);
2490 to = findStorageForUuid(volumeUuid);
Jeff Sharkeyef10ee02015-07-05 14:17:27 -07002491
2492 if (from == null) {
2493 Slog.w(TAG, "Failing move due to missing from volume " + mPrimaryStorageUuid);
2494 onMoveStatusLocked(PackageManager.MOVE_FAILED_INTERNAL_ERROR);
2495 return;
2496 } else if (to == null) {
2497 Slog.w(TAG, "Failing move due to missing to volume " + volumeUuid);
2498 onMoveStatusLocked(PackageManager.MOVE_FAILED_INTERNAL_ERROR);
2499 return;
2500 }
Jeff Sharkey275e3e42015-04-24 16:10:32 -07002501 }
Jeff Sharkey620b32b2015-04-23 19:36:02 -07002502 }
Jeff Sharkeya31460c2016-06-22 09:04:33 -06002503
2504 try {
Jeff Sharkeyb302c542017-09-15 12:57:59 -06002505 mVold.moveStorage(from.id, to.id, new IVoldTaskListener.Stub() {
2506 @Override
2507 public void onStatus(int status, PersistableBundle extras) {
2508 synchronized (mLock) {
2509 onMoveStatusLocked(status);
2510 }
2511 }
2512
2513 @Override
2514 public void onFinished(int status, PersistableBundle extras) {
2515 // Not currently used
2516 }
2517 });
Jeff Sharkeyace874b2017-09-07 15:27:33 -06002518 } catch (Exception e) {
2519 Slog.wtf(TAG, e);
Jeff Sharkeya31460c2016-06-22 09:04:33 -06002520 }
Jeff Sharkey620b32b2015-04-23 19:36:02 -07002521 }
2522
San Mehatb1043402010-02-05 08:26:50 -08002523 private void warnOnNotMounted() {
Jeff Sharkey48877892015-03-18 11:27:19 -07002524 synchronized (mLock) {
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07002525 for (int i = 0; i < mVolumes.size(); i++) {
2526 final VolumeInfo vol = mVolumes.valueAt(i);
Jeff Sharkey27de30d2015-04-18 16:20:27 -07002527 if (vol.isPrimary() && vol.isMountedWritable()) {
Jeff Sharkey48877892015-03-18 11:27:19 -07002528 // Cool beans, we have a mounted primary volume
2529 return;
2530 }
Jeff Sharkey32ee8312012-09-30 13:21:31 -07002531 }
San Mehatb1043402010-02-05 08:26:50 -08002532 }
Jeff Sharkey48877892015-03-18 11:27:19 -07002533
2534 Slog.w(TAG, "No primary storage mounted!");
San Mehatb1043402010-02-05 08:26:50 -08002535 }
2536
Kenny Roota02b8b02010-08-05 16:14:17 -07002537 private boolean isUidOwnerOfPackageOrSystem(String packageName, int callerUid) {
2538 if (callerUid == android.os.Process.SYSTEM_UID) {
2539 return true;
2540 }
2541
Kenny Root02c87302010-07-01 08:10:18 -07002542 if (packageName == null) {
2543 return false;
2544 }
2545
Jeff Sharkey5790af02018-08-13 17:42:54 -06002546 final int packageUid = mPmInternal.getPackageUid(packageName,
Jeff Sharkeycd654482016-01-08 17:42:11 -07002547 PackageManager.MATCH_DEBUG_TRIAGED_MISSING, UserHandle.getUserId(callerUid));
Kenny Root02c87302010-07-01 08:10:18 -07002548
2549 if (DEBUG_OBB) {
2550 Slog.d(TAG, "packageName = " + packageName + ", packageUid = " +
2551 packageUid + ", callerUid = " + callerUid);
2552 }
2553
2554 return callerUid == packageUid;
2555 }
2556
Jeff Sharkey54402792017-09-15 16:05:19 -06002557 @Override
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002558 public String getMountedObbPath(String rawPath) {
Daulet Zhanguzinea1a7ca2020-01-03 09:46:50 +00002559 Objects.requireNonNull(rawPath, "rawPath cannot be null");
Kenny Rootaf9d6672010-10-08 09:21:39 -07002560
Kenny Root02c87302010-07-01 08:10:18 -07002561 warnOnNotMounted();
2562
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002563 final ObbState state;
Rubin Xucd7a0142015-04-17 23:45:27 +01002564 synchronized (mObbMounts) {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002565 state = mObbPathToStateMap.get(rawPath);
2566 }
2567 if (state == null) {
2568 Slog.w(TAG, "Failed to find OBB mounted at " + rawPath);
2569 return null;
2570 }
2571
Jeff Sharkey54402792017-09-15 16:05:19 -06002572 return findVolumeByIdOrThrow(state.volId).getPath().getAbsolutePath();
Kenny Root02c87302010-07-01 08:10:18 -07002573 }
2574
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002575 @Override
2576 public boolean isObbMounted(String rawPath) {
Daulet Zhanguzinea1a7ca2020-01-03 09:46:50 +00002577 Objects.requireNonNull(rawPath, "rawPath cannot be null");
Kenny Rootaf9d6672010-10-08 09:21:39 -07002578 synchronized (mObbMounts) {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002579 return mObbPathToStateMap.containsKey(rawPath);
Kenny Rootaf9d6672010-10-08 09:21:39 -07002580 }
Kenny Root02c87302010-07-01 08:10:18 -07002581 }
2582
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002583 @Override
Sudheer Shanka25469aa2018-08-27 15:50:23 -07002584 public void mountObb(String rawPath, String canonicalPath, String key,
2585 IObbActionListener token, int nonce, ObbInfo obbInfo) {
Daulet Zhanguzinea1a7ca2020-01-03 09:46:50 +00002586 Objects.requireNonNull(rawPath, "rawPath cannot be null");
2587 Objects.requireNonNull(canonicalPath, "canonicalPath cannot be null");
2588 Objects.requireNonNull(token, "token cannot be null");
2589 Objects.requireNonNull(obbInfo, "obbIfno cannot be null");
Kenny Rootaf9d6672010-10-08 09:21:39 -07002590
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002591 final int callingUid = Binder.getCallingUid();
Jeff Sharkey41cd6812017-09-11 10:32:17 -06002592 final ObbState obbState = new ObbState(rawPath, canonicalPath,
2593 callingUid, token, nonce, null);
Sudheer Shanka25469aa2018-08-27 15:50:23 -07002594 final ObbAction action = new MountObbAction(obbState, key, callingUid, obbInfo);
Kenny Roota02b8b02010-08-05 16:14:17 -07002595 mObbActionHandler.sendMessage(mObbActionHandler.obtainMessage(OBB_RUN_ACTION, action));
2596
2597 if (DEBUG_OBB)
2598 Slog.i(TAG, "Send to OBB handler: " + action.toString());
Kenny Root02c87302010-07-01 08:10:18 -07002599 }
2600
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002601 @Override
2602 public void unmountObb(String rawPath, boolean force, IObbActionListener token, int nonce) {
Daulet Zhanguzinea1a7ca2020-01-03 09:46:50 +00002603 Objects.requireNonNull(rawPath, "rawPath cannot be null");
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002604
2605 final ObbState existingState;
Rubin Xucd7a0142015-04-17 23:45:27 +01002606 synchronized (mObbMounts) {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002607 existingState = mObbPathToStateMap.get(rawPath);
Kenny Rootf1121dc2010-09-29 07:30:53 -07002608 }
2609
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002610 if (existingState != null) {
2611 // TODO: separate state object from request data
2612 final int callingUid = Binder.getCallingUid();
Jeff Sharkey41cd6812017-09-11 10:32:17 -06002613 final ObbState newState = new ObbState(rawPath, existingState.canonicalPath,
2614 callingUid, token, nonce, existingState.volId);
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002615 final ObbAction action = new UnmountObbAction(newState, force);
2616 mObbActionHandler.sendMessage(mObbActionHandler.obtainMessage(OBB_RUN_ACTION, action));
Kenny Root02c87302010-07-01 08:10:18 -07002617
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002618 if (DEBUG_OBB)
2619 Slog.i(TAG, "Send to OBB handler: " + action.toString());
2620 } else {
2621 Slog.w(TAG, "Unknown OBB mount at " + rawPath);
2622 }
Kenny Roota02b8b02010-08-05 16:14:17 -07002623 }
2624
Ben Komalo444eca22011-09-01 15:17:44 -07002625 @Override
2626 public int getEncryptionState() {
2627 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
2628 "no permission to access the crypt keeper");
2629
Ben Komalo444eca22011-09-01 15:17:44 -07002630 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002631 return mVold.fdeComplete();
2632 } catch (Exception e) {
2633 Slog.wtf(TAG, e);
Sudheer Shankaf7341142016-10-18 17:15:18 -07002634 return StorageManager.ENCRYPTION_STATE_ERROR_UNKNOWN;
Ben Komalo444eca22011-09-01 15:17:44 -07002635 }
2636 }
2637
2638 @Override
Jason parks5af0b912010-11-29 09:05:25 -06002639 public int decryptStorage(String password) {
Jason parks8888c592011-01-20 22:46:41 -06002640 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
2641 "no permission to access the crypt keeper");
Jason parks5af0b912010-11-29 09:05:25 -06002642
Jeff Sharkey8058fe62017-09-13 11:50:33 -06002643 if (TextUtils.isEmpty(password)) {
2644 throw new IllegalArgumentException("password cannot be empty");
2645 }
2646
Jason parks5af0b912010-11-29 09:05:25 -06002647 if (DEBUG_EVENTS) {
2648 Slog.i(TAG, "decrypting storage...");
2649 }
2650
2651 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002652 mVold.fdeCheckPassword(password);
2653 mHandler.postDelayed(() -> {
2654 try {
2655 mVold.fdeRestart();
2656 } catch (Exception e) {
2657 Slog.wtf(TAG, e);
2658 }
2659 }, DateUtils.SECOND_IN_MILLIS);
2660 return 0;
Paul Crowleyfc0b5192018-07-02 13:58:10 -07002661 } catch (ServiceSpecificException e) {
2662 Slog.e(TAG, "fdeCheckPassword failed", e);
2663 return e.errorCode;
Jeff Sharkey54402792017-09-15 16:05:19 -06002664 } catch (Exception e) {
2665 Slog.wtf(TAG, e);
2666 return StorageManager.ENCRYPTION_STATE_ERROR_UNKNOWN;
Jason parks5af0b912010-11-29 09:05:25 -06002667 }
Jason parks5af0b912010-11-29 09:05:25 -06002668 }
2669
Jeff Sharkey54402792017-09-15 16:05:19 -06002670 @Override
Paul Lawrence46791e72014-04-03 09:10:26 -07002671 public int encryptStorage(int type, String password) {
Jason parks8888c592011-01-20 22:46:41 -06002672 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
2673 "no permission to access the crypt keeper");
Jason parks56aa5322011-01-07 09:01:15 -06002674
Jeff Sharkey8058fe62017-09-13 11:50:33 -06002675 if (type == StorageManager.CRYPT_TYPE_DEFAULT) {
2676 password = "";
2677 } else if (TextUtils.isEmpty(password)) {
2678 throw new IllegalArgumentException("password cannot be empty");
2679 }
2680
Jason parks56aa5322011-01-07 09:01:15 -06002681 if (DEBUG_EVENTS) {
Jason parks8888c592011-01-20 22:46:41 -06002682 Slog.i(TAG, "encrypting storage...");
Jason parks56aa5322011-01-07 09:01:15 -06002683 }
2684
2685 try {
Paul Lawrence89a0ae42017-12-22 10:11:10 -08002686 mVold.fdeEnable(type, password, 0);
Jeff Sharkey43e12112017-09-12 16:31:45 -06002687 } catch (Exception e) {
2688 Slog.wtf(TAG, e);
2689 return -1;
Jason parks56aa5322011-01-07 09:01:15 -06002690 }
2691
2692 return 0;
2693 }
2694
Paul Lawrence8e397362014-01-27 15:22:30 -08002695 /** Set the password for encrypting the master key.
2696 * @param type One of the CRYPTO_TYPE_XXX consts defined in StorageManager.
2697 * @param password The password to set.
2698 */
Jeff Sharkey54402792017-09-15 16:05:19 -06002699 @Override
Paul Lawrence8e397362014-01-27 15:22:30 -08002700 public int changeEncryptionPassword(int type, String password) {
Jason parksf7b3cd42011-01-27 09:28:25 -06002701 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
2702 "no permission to access the crypt keeper");
2703
Jeff Sharkeyae266462017-11-27 13:32:24 -07002704 if (StorageManager.isFileEncryptedNativeOnly()) {
2705 // Not supported on FBE devices
2706 return -1;
2707 }
2708
Jeff Sharkey8058fe62017-09-13 11:50:33 -06002709 if (type == StorageManager.CRYPT_TYPE_DEFAULT) {
2710 password = "";
2711 } else if (TextUtils.isEmpty(password)) {
2712 throw new IllegalArgumentException("password cannot be empty");
2713 }
2714
Jason parksf7b3cd42011-01-27 09:28:25 -06002715 if (DEBUG_EVENTS) {
2716 Slog.i(TAG, "changing encryption password...");
2717 }
2718
2719 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002720 mVold.fdeChangePassword(type, password);
2721 return 0;
2722 } catch (Exception e) {
2723 Slog.wtf(TAG, e);
2724 return -1;
Jason parksf7b3cd42011-01-27 09:28:25 -06002725 }
2726 }
2727
Christopher Tate32418be2011-10-10 13:51:12 -07002728 /**
2729 * Validate a user-supplied password string with cryptfs
2730 */
2731 @Override
2732 public int verifyEncryptionPassword(String password) throws RemoteException {
2733 // Only the system process is permitted to validate passwords
2734 if (Binder.getCallingUid() != android.os.Process.SYSTEM_UID) {
2735 throw new SecurityException("no permission to access the crypt keeper");
2736 }
2737
2738 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
2739 "no permission to access the crypt keeper");
2740
2741 if (TextUtils.isEmpty(password)) {
2742 throw new IllegalArgumentException("password cannot be empty");
2743 }
2744
Christopher Tate32418be2011-10-10 13:51:12 -07002745 if (DEBUG_EVENTS) {
2746 Slog.i(TAG, "validating encryption password...");
2747 }
2748
2749 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002750 mVold.fdeVerifyPassword(password);
2751 return 0;
2752 } catch (Exception e) {
2753 Slog.wtf(TAG, e);
2754 return -1;
Christopher Tate32418be2011-10-10 13:51:12 -07002755 }
2756 }
2757
Paul Lawrence8e397362014-01-27 15:22:30 -08002758 /**
2759 * Get the type of encryption used to encrypt the master key.
2760 * @return The type, one of the CRYPT_TYPE_XXX consts from StorageManager.
2761 */
2762 @Override
Svetoslav16e4a1a2014-09-29 18:16:20 -07002763 public int getPasswordType() {
Paul Lawrence76a40572017-03-15 11:08:04 -07002764 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
Paul Lawrence9de713d2016-05-02 22:45:33 +00002765 "no permission to access the crypt keeper");
2766
Paul Lawrence8e397362014-01-27 15:22:30 -08002767 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002768 return mVold.fdeGetPasswordType();
2769 } catch (Exception e) {
2770 Slog.wtf(TAG, e);
2771 return -1;
Paul Lawrence8e397362014-01-27 15:22:30 -08002772 }
2773 }
2774
Paul Lawrencee51dcf92014-03-18 10:56:00 -07002775 /**
2776 * Set a field in the crypto header.
2777 * @param field field to set
2778 * @param contents contents to set in field
2779 */
2780 @Override
2781 public void setField(String field, String contents) throws RemoteException {
Paul Lawrence76a40572017-03-15 11:08:04 -07002782 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
Paul Lawrence0bbd1082016-04-26 15:21:02 -07002783 "no permission to access the crypt keeper");
Paul Lawrencee51dcf92014-03-18 10:56:00 -07002784
yusukes14a8b1f2018-07-23 17:34:42 -07002785 if (!StorageManager.isBlockEncrypted()) {
2786 // Only supported on FDE devices
Jeff Sharkeyae266462017-11-27 13:32:24 -07002787 return;
2788 }
2789
Paul Lawrencee51dcf92014-03-18 10:56:00 -07002790 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002791 mVold.fdeSetField(field, contents);
2792 return;
2793 } catch (Exception e) {
2794 Slog.wtf(TAG, e);
2795 return;
Paul Lawrencee51dcf92014-03-18 10:56:00 -07002796 }
2797 }
2798
2799 /**
2800 * Gets a field from the crypto header.
2801 * @param field field to get
2802 * @return contents of field
2803 */
2804 @Override
2805 public String getField(String field) throws RemoteException {
Paul Lawrence76a40572017-03-15 11:08:04 -07002806 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
Paul Lawrence0bbd1082016-04-26 15:21:02 -07002807 "no permission to access the crypt keeper");
Paul Lawrencee51dcf92014-03-18 10:56:00 -07002808
yusukes14a8b1f2018-07-23 17:34:42 -07002809 if (!StorageManager.isBlockEncrypted()) {
2810 // Only supported on FDE devices
Jeff Sharkeyae266462017-11-27 13:32:24 -07002811 return null;
2812 }
2813
Paul Lawrencee51dcf92014-03-18 10:56:00 -07002814 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002815 return mVold.fdeGetField(field);
2816 } catch (Exception e) {
2817 Slog.wtf(TAG, e);
2818 return null;
Paul Lawrencee51dcf92014-03-18 10:56:00 -07002819 }
2820 }
2821
Paul Lawrence3806d9c2015-10-29 10:30:46 -07002822 /**
2823 * Is userdata convertible to file based encryption?
2824 * @return non zero for convertible
2825 */
2826 @Override
2827 public boolean isConvertibleToFBE() throws RemoteException {
Paul Lawrence76a40572017-03-15 11:08:04 -07002828 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
Paul Lawrence0bbd1082016-04-26 15:21:02 -07002829 "no permission to access the crypt keeper");
Paul Lawrence3806d9c2015-10-29 10:30:46 -07002830
Paul Lawrence3806d9c2015-10-29 10:30:46 -07002831 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002832 return mVold.isConvertibleToFbe();
2833 } catch (Exception e) {
2834 Slog.wtf(TAG, e);
2835 return false;
Paul Lawrence3806d9c2015-10-29 10:30:46 -07002836 }
2837 }
2838
Daniel Rosenberge129e5c2018-11-07 19:25:55 -08002839 /**
Martijn Coenenf04aca42019-03-11 10:35:34 +01002840 * Check whether the device supports filesystem checkpointing.
2841 *
2842 * @return true if the device supports filesystem checkpointing, false otherwise.
2843 */
2844 @Override
2845 public boolean supportsCheckpoint() throws RemoteException {
Martijn Coenenf04aca42019-03-11 10:35:34 +01002846 return mVold.supportsCheckpoint();
2847 }
2848
2849 /**
2850 * Signal that checkpointing partitions should start a checkpoint on the next boot.
2851 *
2852 * @param numTries Number of times to try booting in checkpoint mode, before we will boot
2853 * non-checkpoint mode and commit all changes immediately. Callers are
2854 * responsible for ensuring that boot is safe (eg, by rolling back updates).
2855 */
2856 @Override
2857 public void startCheckpoint(int numTries) throws RemoteException {
Nikita Ioffe6d749422020-01-14 22:19:01 +00002858 // Only the root, system_server and shell processes are permitted to start checkpoints
2859 final int callingUid = Binder.getCallingUid();
2860 if (callingUid != Process.SYSTEM_UID && callingUid != Process.ROOT_UID
2861 && callingUid != Process.SHELL_UID) {
Martijn Coenenf04aca42019-03-11 10:35:34 +01002862 throw new SecurityException("no permission to start filesystem checkpoint");
2863 }
2864
2865 mVold.startCheckpoint(numTries);
2866 }
2867
2868 /**
Daniel Rosenberge129e5c2018-11-07 19:25:55 -08002869 * Signal that checkpointing partitions should commit changes
2870 */
2871 @Override
2872 public void commitChanges() throws RemoteException {
2873 // Only the system process is permitted to commit checkpoints
2874 if (Binder.getCallingUid() != android.os.Process.SYSTEM_UID) {
2875 throw new SecurityException("no permission to commit checkpoint changes");
2876 }
2877
2878 mVold.commitChanges();
2879 }
2880
Daniel Rosenberge3a924d2019-03-19 18:19:08 -07002881 /**
2882 * Check if we should be mounting with checkpointing or are checkpointing now
2883 */
2884 @Override
2885 public boolean needsCheckpoint() throws RemoteException {
Paul Lawrence15a54462019-04-30 11:14:25 -07002886 enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);
Daniel Rosenberge3a924d2019-03-19 18:19:08 -07002887 return mVold.needsCheckpoint();
2888 }
2889
Daniel Rosenberg600799b2019-03-20 17:42:50 -07002890 /**
2891 * Abort the current set of changes and either try again, or abort entirely
2892 */
2893 @Override
2894 public void abortChanges(String message, boolean retry) throws RemoteException {
2895 // Only the system process is permitted to abort checkpoints
2896 if (Binder.getCallingUid() != android.os.Process.SYSTEM_UID) {
2897 throw new SecurityException("no permission to commit checkpoint changes");
2898 }
2899
2900 mVold.abortChanges(message, retry);
2901 }
2902
Jeff Sharkeyb049e212012-09-07 23:16:01 -07002903 @Override
Paul Lawrence945490c2014-03-27 16:37:28 +00002904 public String getPassword() throws RemoteException {
Paul Lawrence76a40572017-03-15 11:08:04 -07002905 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
Rubin Xucd7a0142015-04-17 23:45:27 +01002906 "only keyguard can retrieve password");
Paul Lawrence0bbd1082016-04-26 15:21:02 -07002907
Paul Lawrence945490c2014-03-27 16:37:28 +00002908 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002909 return mVold.fdeGetPassword();
2910 } catch (Exception e) {
2911 Slog.wtf(TAG, e);
Paul Lawrence24063b52015-01-06 13:11:23 -08002912 return null;
Paul Lawrence945490c2014-03-27 16:37:28 +00002913 }
2914 }
2915
2916 @Override
2917 public void clearPassword() throws RemoteException {
Paul Lawrence76a40572017-03-15 11:08:04 -07002918 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
Paul Lawrence0bbd1082016-04-26 15:21:02 -07002919 "only keyguard can clear password");
2920
Paul Lawrence945490c2014-03-27 16:37:28 +00002921 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002922 mVold.fdeClearPassword();
2923 return;
2924 } catch (Exception e) {
2925 Slog.wtf(TAG, e);
2926 return;
Paul Lawrence945490c2014-03-27 16:37:28 +00002927 }
2928 }
2929
2930 @Override
Lenka Trochtovac4dd0212015-11-18 12:22:06 +01002931 public void createUserKey(int userId, int serialNumber, boolean ephemeral) {
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002932 enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
Paul Crowleybcf48ed2015-04-22 13:36:59 +01002933
Paul Crowleybcf48ed2015-04-22 13:36:59 +01002934 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002935 mVold.createUserKey(userId, serialNumber, ephemeral);
Jeff Sharkey43e12112017-09-12 16:31:45 -06002936 } catch (Exception e) {
2937 Slog.wtf(TAG, e);
Paul Crowleybcf48ed2015-04-22 13:36:59 +01002938 }
2939 }
2940
Paul Crowley7ec733f2015-05-19 12:42:00 +01002941 @Override
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002942 public void destroyUserKey(int userId) {
2943 enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
Paul Crowley7ec733f2015-05-19 12:42:00 +01002944
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002945 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002946 mVold.destroyUserKey(userId);
Jeff Sharkey43e12112017-09-12 16:31:45 -06002947 } catch (Exception e) {
2948 Slog.wtf(TAG, e);
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002949 }
2950 }
2951
Jeff Sharkey43e12112017-09-12 16:31:45 -06002952 private String encodeBytes(byte[] bytes) {
Paul Crowleyfaeb3eb2016-02-08 15:58:29 +00002953 if (ArrayUtils.isEmpty(bytes)) {
Jeff Sharkey43e12112017-09-12 16:31:45 -06002954 return "!";
Paul Crowleyfaeb3eb2016-02-08 15:58:29 +00002955 } else {
Jeff Sharkey43e12112017-09-12 16:31:45 -06002956 return HexDump.toHexString(bytes);
Paul Crowleyfaeb3eb2016-02-08 15:58:29 +00002957 }
2958 }
2959
Paul Crowleycc701552016-05-17 14:18:49 -07002960 /*
2961 * Add this token/secret pair to the set of ways we can recover a disk encryption key.
2962 * Changing the token/secret for a disk encryption key is done in two phases: first, adding
2963 * a new token/secret pair with this call, then delting all other pairs with
2964 * fixateNewestUserKeyAuth. This allows other places where a credential is used, such as
2965 * Gatekeeper, to be updated between the two calls.
2966 */
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002967 @Override
Paul Crowleycc701552016-05-17 14:18:49 -07002968 public void addUserKeyAuth(int userId, int serialNumber, byte[] token, byte[] secret) {
Paul Crowleyfaeb3eb2016-02-08 15:58:29 +00002969 enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
Paul Crowleyfaeb3eb2016-02-08 15:58:29 +00002970
2971 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002972 mVold.addUserKeyAuth(userId, serialNumber, encodeBytes(token), encodeBytes(secret));
Jeff Sharkey43e12112017-09-12 16:31:45 -06002973 } catch (Exception e) {
2974 Slog.wtf(TAG, e);
Paul Crowleycc701552016-05-17 14:18:49 -07002975 }
2976 }
2977
2978 /*
2979 * Delete all disk encryption token/secret pairs except the most recently added one
2980 */
2981 @Override
2982 public void fixateNewestUserKeyAuth(int userId) {
2983 enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
Paul Crowleycc701552016-05-17 14:18:49 -07002984
2985 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002986 mVold.fixateNewestUserKeyAuth(userId);
Jeff Sharkey43e12112017-09-12 16:31:45 -06002987 } catch (Exception e) {
2988 Slog.wtf(TAG, e);
Paul Crowleyfaeb3eb2016-02-08 15:58:29 +00002989 }
2990 }
2991
2992 @Override
2993 public void unlockUserKey(int userId, int serialNumber, byte[] token, byte[] secret) {
Sudheer Shanka03b20ec2019-02-21 15:11:00 -08002994 Slog.d(TAG, "unlockUserKey: " + userId);
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002995 enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002996
Jeff Sharkeyce18c812016-04-27 16:00:41 -06002997 if (StorageManager.isFileEncryptedNativeOrEmulated()) {
Jeff Sharkeyce18c812016-04-27 16:00:41 -06002998 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002999 mVold.unlockUserKey(userId, serialNumber, encodeBytes(token),
3000 encodeBytes(secret));
Jeff Sharkey43e12112017-09-12 16:31:45 -06003001 } catch (Exception e) {
3002 Slog.wtf(TAG, e);
3003 return;
Jeff Sharkeyce18c812016-04-27 16:00:41 -06003004 }
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08003005 }
3006
3007 synchronized (mLock) {
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07003008 mLocalUnlockedUsers = ArrayUtils.appendInt(mLocalUnlockedUsers, userId);
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08003009 }
3010 }
3011
3012 @Override
3013 public void lockUserKey(int userId) {
3014 enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08003015
3016 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06003017 mVold.lockUserKey(userId);
Jeff Sharkey43e12112017-09-12 16:31:45 -06003018 } catch (Exception e) {
3019 Slog.wtf(TAG, e);
3020 return;
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08003021 }
3022
3023 synchronized (mLock) {
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07003024 mLocalUnlockedUsers = ArrayUtils.removeInt(mLocalUnlockedUsers, userId);
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08003025 }
3026 }
3027
3028 @Override
3029 public boolean isUserKeyUnlocked(int userId) {
Jeff Sharkeyce18c812016-04-27 16:00:41 -06003030 synchronized (mLock) {
3031 return ArrayUtils.contains(mLocalUnlockedUsers, userId);
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08003032 }
3033 }
3034
Narayan Kamath157dd1d2019-06-12 13:06:30 +01003035 private boolean isSystemUnlocked(int userId) {
3036 synchronized (mLock) {
3037 return ArrayUtils.contains(mSystemUnlockedUsers, userId);
3038 }
3039 }
3040
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08003041 @Override
Jeff Sharkey47f71082016-02-01 17:03:54 -07003042 public void prepareUserStorage(String volumeUuid, int userId, int serialNumber, int flags) {
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08003043 enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08003044
3045 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06003046 mVold.prepareUserStorage(volumeUuid, userId, serialNumber, flags);
Jeff Sharkey43e12112017-09-12 16:31:45 -06003047 } catch (Exception e) {
3048 Slog.wtf(TAG, e);
Paul Crowley7ec733f2015-05-19 12:42:00 +01003049 }
3050 }
3051
Paul Crowleybcf48ed2015-04-22 13:36:59 +01003052 @Override
Jeff Sharkeyfcf1e552016-04-14 20:44:58 -06003053 public void destroyUserStorage(String volumeUuid, int userId, int flags) {
3054 enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
Jeff Sharkeyfcf1e552016-04-14 20:44:58 -06003055
3056 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06003057 mVold.destroyUserStorage(volumeUuid, userId, flags);
Jeff Sharkey43e12112017-09-12 16:31:45 -06003058 } catch (Exception e) {
3059 Slog.wtf(TAG, e);
Jeff Sharkeyfcf1e552016-04-14 20:44:58 -06003060 }
3061 }
3062
Anton Hanssonbe9c9902019-05-28 13:45:26 +01003063 /** Not thread safe */
Daichi Hironoe56740d2017-02-02 13:56:45 +09003064 class AppFuseMountScope extends AppFuseBridge.MountScope {
Anton Hanssonbe9c9902019-05-28 13:45:26 +01003065 private boolean mMounted = false;
Daichi Hirono812c95d2017-02-08 16:20:20 +09003066
Ryo Hashimoto38bcbf02018-05-16 18:20:37 +09003067 public AppFuseMountScope(int uid, int mountId) {
3068 super(uid, mountId);
Daichi Hirono812c95d2017-02-08 16:20:20 +09003069 }
3070
3071 @Override
3072 public ParcelFileDescriptor open() throws NativeDaemonConnectorException {
Jeff Sharkey54402792017-09-15 16:05:19 -06003073 try {
Anton Hanssonbe9c9902019-05-28 13:45:26 +01003074 final FileDescriptor fd = mVold.mountAppFuse(uid, mountId);
3075 mMounted = true;
3076 return new ParcelFileDescriptor(fd);
Jeff Sharkey54402792017-09-15 16:05:19 -06003077 } catch (Exception e) {
3078 throw new NativeDaemonConnectorException("Failed to mount", e);
Daichi Hirono812c95d2017-02-08 16:20:20 +09003079 }
Daichi Hirono9fb00182016-11-08 14:12:17 +09003080 }
3081
3082 @Override
Ryo Hashimoto38bcbf02018-05-16 18:20:37 +09003083 public ParcelFileDescriptor openFile(int mountId, int fileId, int flags)
3084 throws NativeDaemonConnectorException {
3085 try {
3086 return new ParcelFileDescriptor(
3087 mVold.openAppFuseFile(uid, mountId, fileId, flags));
3088 } catch (Exception e) {
3089 throw new NativeDaemonConnectorException("Failed to open", e);
3090 }
3091 }
3092
3093 @Override
Daichi Hironoe56740d2017-02-02 13:56:45 +09003094 public void close() throws Exception {
Anton Hanssonbe9c9902019-05-28 13:45:26 +01003095 if (mMounted) {
Ryo Hashimoto38bcbf02018-05-16 18:20:37 +09003096 mVold.unmountAppFuse(uid, mountId);
Anton Hanssonbe9c9902019-05-28 13:45:26 +01003097 mMounted = false;
Daichi Hirono812c95d2017-02-08 16:20:20 +09003098 }
Daichi Hirono9fb00182016-11-08 14:12:17 +09003099 }
3100 }
3101
3102 @Override
Daichi Hirono812c95d2017-02-08 16:20:20 +09003103 public @Nullable AppFuseMount mountProxyFileDescriptorBridge() {
Daichi Hironoe56740d2017-02-02 13:56:45 +09003104 Slog.v(TAG, "mountProxyFileDescriptorBridge");
Daichi Hirono9fb00182016-11-08 14:12:17 +09003105 final int uid = Binder.getCallingUid();
Daichi Hirono9fb00182016-11-08 14:12:17 +09003106
Daichi Hironoe56740d2017-02-02 13:56:45 +09003107 while (true) {
3108 synchronized (mAppFuseLock) {
3109 boolean newlyCreated = false;
3110 if (mAppFuseBridge == null) {
3111 mAppFuseBridge = new AppFuseBridge();
3112 new Thread(mAppFuseBridge, AppFuseBridge.TAG).start();
3113 newlyCreated = true;
Daichi Hirono9fb00182016-11-08 14:12:17 +09003114 }
Daichi Hironoe56740d2017-02-02 13:56:45 +09003115 try {
3116 final int name = mNextAppFuseName++;
3117 try {
3118 return new AppFuseMount(
Ryo Hashimoto38bcbf02018-05-16 18:20:37 +09003119 name, mAppFuseBridge.addBridge(new AppFuseMountScope(uid, name)));
Daichi Hirono812c95d2017-02-08 16:20:20 +09003120 } catch (FuseUnavailableMountException e) {
Daichi Hironoe56740d2017-02-02 13:56:45 +09003121 if (newlyCreated) {
3122 // If newly created bridge fails, it's a real error.
Daichi Hirono812c95d2017-02-08 16:20:20 +09003123 Slog.e(TAG, "", e);
3124 return null;
Daichi Hironoe56740d2017-02-02 13:56:45 +09003125 }
3126 // It seems the thread of mAppFuseBridge has already been terminated.
3127 mAppFuseBridge = null;
3128 }
3129 } catch (NativeDaemonConnectorException e) {
3130 throw e.rethrowAsParcelableException();
3131 }
Daichi Hirono9fb00182016-11-08 14:12:17 +09003132 }
Daichi Hirono9fb00182016-11-08 14:12:17 +09003133 }
3134 }
3135
3136 @Override
Daichi Hirono812c95d2017-02-08 16:20:20 +09003137 public @Nullable ParcelFileDescriptor openProxyFileDescriptor(
3138 int mountId, int fileId, int mode) {
3139 Slog.v(TAG, "mountProxyFileDescriptor");
Jeff Sharkey39466322018-12-05 19:19:52 -07003140
3141 // We only support a narrow set of incoming mode flags
Jeff Sharkey3b1c2542018-12-13 15:01:38 -07003142 mode &= MODE_READ_WRITE;
Jeff Sharkey39466322018-12-05 19:19:52 -07003143
Daichi Hirono9fb00182016-11-08 14:12:17 +09003144 try {
3145 synchronized (mAppFuseLock) {
Daichi Hironoe56740d2017-02-02 13:56:45 +09003146 if (mAppFuseBridge == null) {
Daichi Hirono812c95d2017-02-08 16:20:20 +09003147 Slog.e(TAG, "FuseBridge has not been created");
3148 return null;
Daichi Hirono9fb00182016-11-08 14:12:17 +09003149 }
Ryo Hashimoto38bcbf02018-05-16 18:20:37 +09003150 return mAppFuseBridge.openFile(mountId, fileId, mode);
Daichi Hirono9fb00182016-11-08 14:12:17 +09003151 }
Daichi Hirono812c95d2017-02-08 16:20:20 +09003152 } catch (FuseUnavailableMountException | InterruptedException error) {
3153 Slog.v(TAG, "The mount point has already been invalid", error);
3154 return null;
Daichi Hirono9fb00182016-11-08 14:12:17 +09003155 }
3156 }
3157
Daichi Hirono9e8d9e22015-11-13 14:37:00 +09003158 @Override
Jeff Sharkeyae266462017-11-27 13:32:24 -07003159 public void mkdirs(String callingPkg, String appPath) {
Sudheer Shankaa63bfb32019-02-28 11:15:58 -08003160 final int callingUid = Binder.getCallingUid();
3161 final int userId = UserHandle.getUserId(callingUid);
Farid Zare Seisanac094512018-04-02 15:06:13 -07003162 final String propertyName = "sys.user." + userId + ".ce_available";
Jeff Sharkey2d8b4e82013-09-17 17:30:33 -07003163
Jeff Sharkey196c7552018-03-26 15:56:50 -06003164 // Ignore requests to create directories while storage is locked
Farid Zare Seisanac094512018-04-02 15:06:13 -07003165 if (!isUserKeyUnlocked(userId)) {
3166 throw new IllegalStateException("Failed to prepare " + appPath);
3167 }
3168
3169 // Ignore requests to create directories if CE storage is not available
Farid Zare Seisan7f6b8122018-03-30 11:19:10 -07003170 if ((userId == UserHandle.USER_SYSTEM)
3171 && !SystemProperties.getBoolean(propertyName, false)) {
Farid Zare Seisanac094512018-04-02 15:06:13 -07003172 throw new IllegalStateException("Failed to prepare " + appPath);
3173 }
Jeff Sharkey196c7552018-03-26 15:56:50 -06003174
Jeff Sharkey2d8b4e82013-09-17 17:30:33 -07003175 // Validate that reported package name belongs to caller
3176 final AppOpsManager appOps = (AppOpsManager) mContext.getSystemService(
3177 Context.APP_OPS_SERVICE);
Sudheer Shankaa63bfb32019-02-28 11:15:58 -08003178 appOps.checkPackage(callingUid, callingPkg);
Jeff Sharkey2d8b4e82013-09-17 17:30:33 -07003179
Jeff Sharkey48877892015-03-18 11:27:19 -07003180 File appFile = null;
Jeff Sharkey2d8b4e82013-09-17 17:30:33 -07003181 try {
Jeff Sharkey48877892015-03-18 11:27:19 -07003182 appFile = new File(appPath).getCanonicalFile();
Jeff Sharkey2d8b4e82013-09-17 17:30:33 -07003183 } catch (IOException e) {
Jeff Sharkeyae266462017-11-27 13:32:24 -07003184 throw new IllegalStateException("Failed to resolve " + appPath + ": " + e);
Jeff Sharkey2d8b4e82013-09-17 17:30:33 -07003185 }
3186
Martijn Coenen9fd2b642019-12-24 13:04:36 +01003187 appPath = appFile.getAbsolutePath();
3188 if (!appPath.endsWith("/")) {
3189 appPath = appPath + "/";
3190 }
3191 // Ensure that the path we're asked to create is a known application directory
3192 // path.
3193 final Matcher matcher = KNOWN_APP_DIR_PATHS.matcher(appPath);
3194 if (matcher.matches()) {
3195 // And that the package dir matches the calling package
3196 if (!matcher.group(3).equals(callingPkg)) {
3197 throw new SecurityException("Invalid mkdirs path: " + appFile
3198 + " does not contain calling package " + callingPkg);
Jeff Sharkey48877892015-03-18 11:27:19 -07003199 }
Martijn Coenen9fd2b642019-12-24 13:04:36 +01003200 // And that the user id part of the path (if any) matches the calling user id,
3201 // or if for a public volume (no user id), the user matches the current user
3202 if ((matcher.group(2) != null && !matcher.group(2).equals(Integer.toString(userId)))
3203 || (matcher.group(2) == null && userId != mCurrentUserId)) {
3204 throw new SecurityException("Invalid mkdirs path: " + appFile
3205 + " does not match calling user id " + userId);
3206 }
Jeff Sharkey2d8b4e82013-09-17 17:30:33 -07003207 try {
Martijn Coenen9fd2b642019-12-24 13:04:36 +01003208 mVold.setupAppDir(appPath, matcher.group(1), callingUid);
3209 } catch (RemoteException e) {
Sudheer Shanka64501e52019-04-29 10:46:26 -07003210 throw new IllegalStateException("Failed to prepare " + appPath + ": " + e);
Jeff Sharkey2d8b4e82013-09-17 17:30:33 -07003211 }
Jeff Sharkey2d8b4e82013-09-17 17:30:33 -07003212
Martijn Coenen9fd2b642019-12-24 13:04:36 +01003213 return;
3214 }
3215 throw new SecurityException("Invalid mkdirs path: " + appFile
3216 + " is not a known app path.");
Jeff Sharkey2d8b4e82013-09-17 17:30:33 -07003217 }
3218
3219 @Override
Jeff Sharkey46349872015-07-28 10:49:47 -07003220 public StorageVolume[] getVolumeList(int uid, String packageName, int flags) {
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07003221 final int userId = UserHandle.getUserId(uid);
Jeff Sharkeyc02bfae2016-03-27 15:06:53 -06003222
Jeff Sharkey46349872015-07-28 10:49:47 -07003223 final boolean forWrite = (flags & StorageManager.FLAG_FOR_WRITE) != 0;
Jeff Sharkeyc02bfae2016-03-27 15:06:53 -06003224 final boolean realState = (flags & StorageManager.FLAG_REAL_STATE) != 0;
3225 final boolean includeInvisible = (flags & StorageManager.FLAG_INCLUDE_INVISIBLE) != 0;
Jeff Sharkey04b4ba12019-12-15 22:42:42 -07003226 final boolean includeRecent = (flags & StorageManager.FLAG_INCLUDE_RECENT) != 0;
Jeff Sharkey46349872015-07-28 10:49:47 -07003227
Narayan Kamath157dd1d2019-06-12 13:06:30 +01003228 // Report all volumes as unmounted until we've recorded that user 0 has unlocked. There
3229 // are no guarantees that callers will see a consistent view of the volume before that
3230 // point
3231 final boolean systemUserUnlocked = isSystemUnlocked(UserHandle.USER_SYSTEM);
3232
Jeff Sharkey04b4ba12019-12-15 22:42:42 -07003233 final boolean userIsDemo;
Jeff Sharkeyc02bfae2016-03-27 15:06:53 -06003234 final boolean userKeyUnlocked;
3235 final boolean storagePermission;
3236 final long token = Binder.clearCallingIdentity();
Svetoslav38c3dbb2015-07-14 11:27:06 -07003237 try {
Jeff Sharkey04b4ba12019-12-15 22:42:42 -07003238 userIsDemo = LocalServices.getService(UserManagerInternal.class)
3239 .getUserInfo(userId).isDemo();
Jeff Sharkeyc02bfae2016-03-27 15:06:53 -06003240 userKeyUnlocked = isUserKeyUnlocked(userId);
Sudheer Shanka2250d562016-11-07 15:41:02 -08003241 storagePermission = mStorageManagerInternal.hasExternalStorage(uid, packageName);
Svetoslav38c3dbb2015-07-14 11:27:06 -07003242 } finally {
Jeff Sharkeyc02bfae2016-03-27 15:06:53 -06003243 Binder.restoreCallingIdentity(token);
Svetoslav38c3dbb2015-07-14 11:27:06 -07003244 }
Svet Ganov6ee871e2015-07-10 14:29:33 -07003245
Jeff Sharkeyc02bfae2016-03-27 15:06:53 -06003246 boolean foundPrimary = false;
3247
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07003248 final ArrayList<StorageVolume> res = new ArrayList<>();
Jeff Sharkey04b4ba12019-12-15 22:42:42 -07003249 final ArraySet<String> resUuids = new ArraySet<>();
Jeff Sharkey48877892015-03-18 11:27:19 -07003250 synchronized (mLock) {
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07003251 for (int i = 0; i < mVolumes.size(); i++) {
3252 final VolumeInfo vol = mVolumes.valueAt(i);
Jeff Sharkeyc02bfae2016-03-27 15:06:53 -06003253 switch (vol.getType()) {
3254 case VolumeInfo.TYPE_PUBLIC:
Risan05c41e62018-10-29 08:57:43 +09003255 case VolumeInfo.TYPE_STUB:
Jeff Sharkeyc02bfae2016-03-27 15:06:53 -06003256 break;
Zim17be6f92019-09-25 14:37:55 +01003257 case VolumeInfo.TYPE_EMULATED:
3258 if (vol.getMountUserId() == userId) {
3259 break;
3260 }
3261 // Skip if emulated volume not for userId
Jeff Sharkeyc02bfae2016-03-27 15:06:53 -06003262 default:
3263 continue;
3264 }
3265
3266 boolean match = false;
3267 if (forWrite) {
3268 match = vol.isVisibleForWrite(userId);
3269 } else {
Felipe Leme123a0e72016-06-10 11:09:11 -07003270 match = vol.isVisibleForRead(userId)
3271 || (includeInvisible && vol.getPath() != null);
Jeff Sharkeyc02bfae2016-03-27 15:06:53 -06003272 }
3273 if (!match) continue;
3274
3275 boolean reportUnmounted = false;
Narayan Kamath157dd1d2019-06-12 13:06:30 +01003276 if (!systemUserUnlocked) {
3277 reportUnmounted = true;
3278 } else if ((vol.getType() == VolumeInfo.TYPE_EMULATED) && !userKeyUnlocked) {
Jeff Sharkeyc02bfae2016-03-27 15:06:53 -06003279 reportUnmounted = true;
3280 } else if (!storagePermission && !realState) {
3281 reportUnmounted = true;
3282 }
3283
3284 final StorageVolume userVol = vol.buildStorageVolume(mContext, userId,
3285 reportUnmounted);
3286 if (vol.isPrimary()) {
3287 res.add(0, userVol);
3288 foundPrimary = true;
3289 } else {
3290 res.add(userVol);
Jeff Sharkeyb049e212012-09-07 23:16:01 -07003291 }
Jeff Sharkey04b4ba12019-12-15 22:42:42 -07003292 resUuids.add(userVol.getUuid());
Mike Lockwood8fa5f802011-03-24 08:12:30 -07003293 }
Jeff Sharkey04b4ba12019-12-15 22:42:42 -07003294
3295 if (includeRecent) {
3296 final long lastWeek = System.currentTimeMillis() - DateUtils.WEEK_IN_MILLIS;
3297 for (int i = 0; i < mRecords.size(); i++) {
3298 final VolumeRecord rec = mRecords.valueAt(i);
3299
3300 // Skip if we've already included it above
3301 if (resUuids.contains(rec.fsUuid)) continue;
3302
3303 // Treat as recent if mounted within the last week
3304 if (rec.lastSeenMillis > 0 && rec.lastSeenMillis < lastWeek) {
3305 final StorageVolume userVol = rec.buildStorageVolume(mContext);
3306 res.add(userVol);
3307 resUuids.add(userVol.getUuid());
3308 }
3309 }
3310 }
3311 }
3312
3313 // Synthesize a volume for preloaded media under demo users, so that
3314 // it's scanned into MediaStore
3315 if (userIsDemo) {
3316 final String id = "demo";
3317 final File path = Environment.getDataPreloadsMediaDirectory();
3318 final boolean primary = false;
3319 final boolean removable = false;
3320 final boolean emulated = true;
3321 final boolean allowMassStorage = false;
3322 final long maxFileSize = 0;
3323 final UserHandle user = new UserHandle(userId);
3324 final String envState = Environment.MEDIA_MOUNTED_READ_ONLY;
3325 final String description = mContext.getString(android.R.string.unknownName);
3326
3327 res.add(new StorageVolume(id, path, path, description, primary, removable,
3328 emulated, allowMassStorage, maxFileSize, user, id, envState));
Mike Lockwood8fa5f802011-03-24 08:12:30 -07003329 }
Jeff Sharkey48877892015-03-18 11:27:19 -07003330
3331 if (!foundPrimary) {
Jeff Sharkey11697f52018-12-13 10:14:42 -07003332 Slog.w(TAG, "No primary storage defined yet; hacking together a stub");
Jeff Sharkey48877892015-03-18 11:27:19 -07003333
3334 final boolean primaryPhysical = SystemProperties.getBoolean(
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07003335 StorageManager.PROP_PRIMARY_PHYSICAL, false);
Jeff Sharkey48877892015-03-18 11:27:19 -07003336
3337 final String id = "stub_primary";
3338 final File path = Environment.getLegacyExternalStorageDirectory();
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07003339 final String description = mContext.getString(android.R.string.unknownName);
Jeff Sharkey48877892015-03-18 11:27:19 -07003340 final boolean primary = true;
3341 final boolean removable = primaryPhysical;
3342 final boolean emulated = !primaryPhysical;
Jeff Sharkey48877892015-03-18 11:27:19 -07003343 final boolean allowMassStorage = false;
3344 final long maxFileSize = 0L;
3345 final UserHandle owner = new UserHandle(userId);
3346 final String uuid = null;
Jeff Sharkey48877892015-03-18 11:27:19 -07003347 final String state = Environment.MEDIA_REMOVED;
3348
Jerry Zhang71938e12018-05-10 18:28:29 -07003349 res.add(0, new StorageVolume(id, path, path,
Jerry Zhangf9c5c252017-08-16 18:07:51 -07003350 description, primary, removable, emulated,
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07003351 allowMassStorage, maxFileSize, owner, uuid, state));
Jeff Sharkey48877892015-03-18 11:27:19 -07003352 }
3353
3354 return res.toArray(new StorageVolume[res.size()]);
Mike Lockwood8fa5f802011-03-24 08:12:30 -07003355 }
3356
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07003357 @Override
3358 public DiskInfo[] getDisks() {
3359 synchronized (mLock) {
3360 final DiskInfo[] res = new DiskInfo[mDisks.size()];
3361 for (int i = 0; i < mDisks.size(); i++) {
3362 res[i] = mDisks.valueAt(i);
3363 }
3364 return res;
3365 }
3366 }
3367
3368 @Override
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07003369 public VolumeInfo[] getVolumes(int flags) {
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07003370 synchronized (mLock) {
3371 final VolumeInfo[] res = new VolumeInfo[mVolumes.size()];
3372 for (int i = 0; i < mVolumes.size(); i++) {
3373 res[i] = mVolumes.valueAt(i);
3374 }
3375 return res;
3376 }
3377 }
3378
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07003379 @Override
3380 public VolumeRecord[] getVolumeRecords(int flags) {
3381 synchronized (mLock) {
3382 final VolumeRecord[] res = new VolumeRecord[mRecords.size()];
3383 for (int i = 0; i < mRecords.size(); i++) {
3384 res[i] = mRecords.valueAt(i);
3385 }
3386 return res;
3387 }
3388 }
3389
Jeff Sharkey9bed0702017-01-23 20:37:05 -07003390 @Override
3391 public long getCacheQuotaBytes(String volumeUuid, int uid) {
3392 if (uid != Binder.getCallingUid()) {
3393 mContext.enforceCallingPermission(android.Manifest.permission.STORAGE_INTERNAL, TAG);
3394 }
Daniel Nishi80fdb012017-03-09 14:30:07 -08003395 final long token = Binder.clearCallingIdentity();
3396 final StorageStatsManager stats = mContext.getSystemService(StorageStatsManager.class);
3397 try {
3398 return stats.getCacheQuotaBytes(volumeUuid, uid);
3399 } finally {
3400 Binder.restoreCallingIdentity(token);
3401 }
Jeff Sharkey9bed0702017-01-23 20:37:05 -07003402 }
3403
3404 @Override
3405 public long getCacheSizeBytes(String volumeUuid, int uid) {
3406 if (uid != Binder.getCallingUid()) {
3407 mContext.enforceCallingPermission(android.Manifest.permission.STORAGE_INTERNAL, TAG);
3408 }
3409 final long token = Binder.clearCallingIdentity();
3410 try {
3411 return mContext.getSystemService(StorageStatsManager.class)
3412 .queryStatsForUid(volumeUuid, uid).getCacheBytes();
Jeff Sharkey789a8fc2017-04-16 13:18:35 -06003413 } catch (IOException e) {
3414 throw new ParcelableException(e);
Jeff Sharkey9bed0702017-01-23 20:37:05 -07003415 } finally {
3416 Binder.restoreCallingIdentity(token);
3417 }
3418 }
3419
Jeff Sharkey35e46d22017-06-09 10:01:20 -06003420 private int adjustAllocateFlags(int flags, int callingUid, String callingPackage) {
3421 // Require permission to allocate aggressively
3422 if ((flags & StorageManager.FLAG_ALLOCATE_AGGRESSIVE) != 0) {
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07003423 mContext.enforceCallingOrSelfPermission(
3424 android.Manifest.permission.ALLOCATE_AGGRESSIVE, TAG);
3425 }
3426
Jeff Sharkey35e46d22017-06-09 10:01:20 -06003427 // Apps normally can't directly defy reserved space
3428 flags &= ~StorageManager.FLAG_ALLOCATE_DEFY_ALL_RESERVED;
3429 flags &= ~StorageManager.FLAG_ALLOCATE_DEFY_HALF_RESERVED;
3430
3431 // However, if app is actively using the camera, then we're willing to
3432 // clear up to half of the reserved cache space, since the user might be
3433 // trying to capture an important memory.
3434 final AppOpsManager appOps = mContext.getSystemService(AppOpsManager.class);
3435 final long token = Binder.clearCallingIdentity();
3436 try {
3437 if (appOps.isOperationActive(AppOpsManager.OP_CAMERA, callingUid, callingPackage)) {
3438 Slog.d(TAG, "UID " + callingUid + " is actively using camera;"
3439 + " letting them defy reserved cached data");
3440 flags |= StorageManager.FLAG_ALLOCATE_DEFY_HALF_RESERVED;
3441 }
3442 } finally {
3443 Binder.restoreCallingIdentity(token);
3444 }
3445
3446 return flags;
3447 }
3448
3449 @Override
3450 public long getAllocatableBytes(String volumeUuid, int flags, String callingPackage) {
3451 flags = adjustAllocateFlags(flags, Binder.getCallingUid(), callingPackage);
3452
3453 final StorageManager storage = mContext.getSystemService(StorageManager.class);
3454 final StorageStatsManager stats = mContext.getSystemService(StorageStatsManager.class);
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07003455 final long token = Binder.clearCallingIdentity();
3456 try {
3457 // In general, apps can allocate as much space as they want, except
3458 // we never let them eat into either the minimum cache space or into
Jeff Sharkeyddff8072017-05-26 13:10:46 -06003459 // the low disk warning space. To avoid user confusion, this logic
3460 // should be kept in sync with getFreeBytes().
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07003461 final File path = storage.findPathForUuid(volumeUuid);
Jeff Sharkeyddff8072017-05-26 13:10:46 -06003462
Noah Zimmtb2558072019-07-25 16:15:06 -07003463 long usable = 0;
3464 long lowReserved = 0;
3465 long fullReserved = 0;
3466 long cacheClearable = 0;
Jeff Sharkeyddff8072017-05-26 13:10:46 -06003467
Noah Zimmtb2558072019-07-25 16:15:06 -07003468 if ((flags & StorageManager.FLAG_ALLOCATE_CACHE_ONLY) == 0) {
3469 usable = path.getUsableSpace();
3470 lowReserved = storage.getStorageLowBytes(path);
3471 fullReserved = storage.getStorageFullBytes(path);
3472 }
3473
3474 if ((flags & StorageManager.FLAG_ALLOCATE_NON_CACHE_ONLY) == 0
3475 && stats.isQuotaSupported(volumeUuid)) {
Jeff Sharkeyddff8072017-05-26 13:10:46 -06003476 final long cacheTotal = stats.getCacheBytes(volumeUuid);
Jeff Sharkey35e46d22017-06-09 10:01:20 -06003477 final long cacheReserved = storage.getStorageCacheBytes(path, flags);
Noah Zimmtb2558072019-07-25 16:15:06 -07003478 cacheClearable = Math.max(0, cacheTotal - cacheReserved);
3479 }
Jeff Sharkeyddff8072017-05-26 13:10:46 -06003480
Noah Zimmtb2558072019-07-25 16:15:06 -07003481 if ((flags & StorageManager.FLAG_ALLOCATE_AGGRESSIVE) != 0) {
3482 return Math.max(0, (usable + cacheClearable) - fullReserved);
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07003483 } else {
Noah Zimmtb2558072019-07-25 16:15:06 -07003484 return Math.max(0, (usable + cacheClearable) - lowReserved);
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07003485 }
Jeff Sharkey789a8fc2017-04-16 13:18:35 -06003486 } catch (IOException e) {
3487 throw new ParcelableException(e);
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07003488 } finally {
3489 Binder.restoreCallingIdentity(token);
3490 }
Jeff Sharkey500ce9e2017-02-12 02:39:24 -07003491 }
3492
3493 @Override
Jeff Sharkey35e46d22017-06-09 10:01:20 -06003494 public void allocateBytes(String volumeUuid, long bytes, int flags, String callingPackage) {
3495 flags = adjustAllocateFlags(flags, Binder.getCallingUid(), callingPackage);
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07003496
Noah Zimmtb2558072019-07-25 16:15:06 -07003497 final long allocatableBytes = getAllocatableBytes(volumeUuid,
3498 flags | StorageManager.FLAG_ALLOCATE_NON_CACHE_ONLY, callingPackage);
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07003499 if (bytes > allocatableBytes) {
Noah Zimmtb2558072019-07-25 16:15:06 -07003500 // If we don't have room without taking cache into account, check to see if we'd have
3501 // room if we included freeable cache space.
3502 final long cacheClearable = getAllocatableBytes(volumeUuid,
3503 flags | StorageManager.FLAG_ALLOCATE_CACHE_ONLY, callingPackage);
3504 if (bytes > allocatableBytes + cacheClearable) {
3505 throw new ParcelableException(new IOException("Failed to allocate " + bytes
3506 + " because only " + (allocatableBytes + cacheClearable) + " allocatable"));
3507 }
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07003508 }
3509
Jeff Sharkey35e46d22017-06-09 10:01:20 -06003510 final StorageManager storage = mContext.getSystemService(StorageManager.class);
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07003511 final long token = Binder.clearCallingIdentity();
3512 try {
Jeff Sharkey789a8fc2017-04-16 13:18:35 -06003513 // Free up enough disk space to satisfy both the requested allocation
3514 // and our low disk warning space.
3515 final File path = storage.findPathForUuid(volumeUuid);
Jeff Sharkeyddff8072017-05-26 13:10:46 -06003516 if ((flags & StorageManager.FLAG_ALLOCATE_AGGRESSIVE) != 0) {
3517 bytes += storage.getStorageFullBytes(path);
3518 } else {
3519 bytes += storage.getStorageLowBytes(path);
3520 }
Jeff Sharkey789a8fc2017-04-16 13:18:35 -06003521
Jeff Sharkey5790af02018-08-13 17:42:54 -06003522 mPmInternal.freeStorage(volumeUuid, bytes, flags);
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07003523 } catch (IOException e) {
3524 throw new ParcelableException(e);
3525 } finally {
3526 Binder.restoreCallingIdentity(token);
Jeff Sharkey500ce9e2017-02-12 02:39:24 -07003527 }
3528 }
3529
Sudheer Shankaff971bc2018-12-13 17:39:59 -08003530 private IAppOpsCallback.Stub mAppOpsCallback = new IAppOpsCallback.Stub() {
3531 @Override
3532 public void opChanged(int op, int uid, String packageName) throws RemoteException {
3533 if (!ENABLE_ISOLATED_STORAGE) return;
3534
Zim64726cb2019-11-27 13:06:34 +00003535 int mountMode = getMountMode(uid, packageName);
3536 boolean isUidActive = LocalServices.getService(ActivityManagerInternal.class)
3537 .getUidProcessState(uid) != PROCESS_STATE_NONEXISTENT;
3538
3539 if (isUidActive) {
3540 remountUidExternalStorage(uid, mountMode);
3541 }
Sudheer Shankaff971bc2018-12-13 17:39:59 -08003542 }
3543 };
3544
Kenny Rootaf9d6672010-10-08 09:21:39 -07003545 private void addObbStateLocked(ObbState obbState) throws RemoteException {
3546 final IBinder binder = obbState.getBinder();
3547 List<ObbState> obbStates = mObbMounts.get(binder);
Kenny Root5919ac62010-10-05 09:49:40 -07003548
Kenny Rootaf9d6672010-10-08 09:21:39 -07003549 if (obbStates == null) {
3550 obbStates = new ArrayList<ObbState>();
3551 mObbMounts.put(binder, obbStates);
3552 } else {
3553 for (final ObbState o : obbStates) {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003554 if (o.rawPath.equals(obbState.rawPath)) {
Kenny Rootaf9d6672010-10-08 09:21:39 -07003555 throw new IllegalStateException("Attempt to add ObbState twice. "
Sudheer Shanka2250d562016-11-07 15:41:02 -08003556 + "This indicates an error in the StorageManagerService logic.");
Kenny Root5919ac62010-10-05 09:49:40 -07003557 }
3558 }
Kenny Roota02b8b02010-08-05 16:14:17 -07003559 }
Kenny Rootaf9d6672010-10-08 09:21:39 -07003560
3561 obbStates.add(obbState);
3562 try {
3563 obbState.link();
3564 } catch (RemoteException e) {
3565 /*
3566 * The binder died before we could link it, so clean up our state
3567 * and return failure.
3568 */
3569 obbStates.remove(obbState);
3570 if (obbStates.isEmpty()) {
3571 mObbMounts.remove(binder);
3572 }
3573
3574 // Rethrow the error so mountObb can get it
3575 throw e;
3576 }
3577
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003578 mObbPathToStateMap.put(obbState.rawPath, obbState);
Kenny Roota02b8b02010-08-05 16:14:17 -07003579 }
3580
Kenny Rootaf9d6672010-10-08 09:21:39 -07003581 private void removeObbStateLocked(ObbState obbState) {
3582 final IBinder binder = obbState.getBinder();
3583 final List<ObbState> obbStates = mObbMounts.get(binder);
3584 if (obbStates != null) {
3585 if (obbStates.remove(obbState)) {
3586 obbState.unlink();
Kenny Root05105f72010-09-22 17:29:43 -07003587 }
Kenny Rootaf9d6672010-10-08 09:21:39 -07003588 if (obbStates.isEmpty()) {
3589 mObbMounts.remove(binder);
3590 }
Kenny Roota02b8b02010-08-05 16:14:17 -07003591 }
Kenny Roota02b8b02010-08-05 16:14:17 -07003592
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003593 mObbPathToStateMap.remove(obbState.rawPath);
Kenny Root38cf8862010-09-26 14:18:51 -07003594 }
3595
Kenny Roota02b8b02010-08-05 16:14:17 -07003596 private class ObbActionHandler extends Handler {
Kenny Roota02b8b02010-08-05 16:14:17 -07003597
3598 ObbActionHandler(Looper l) {
3599 super(l);
3600 }
3601
3602 @Override
3603 public void handleMessage(Message msg) {
3604 switch (msg.what) {
3605 case OBB_RUN_ACTION: {
Kenny Root480afe72010-10-07 10:17:50 -07003606 final ObbAction action = (ObbAction) msg.obj;
Kenny Roota02b8b02010-08-05 16:14:17 -07003607
3608 if (DEBUG_OBB)
3609 Slog.i(TAG, "OBB_RUN_ACTION: " + action.toString());
3610
Sudheer Shanka25469aa2018-08-27 15:50:23 -07003611 action.execute(this);
Kenny Roota02b8b02010-08-05 16:14:17 -07003612 break;
3613 }
Kenny Rootaf9d6672010-10-08 09:21:39 -07003614 case OBB_FLUSH_MOUNT_STATE: {
3615 final String path = (String) msg.obj;
3616
3617 if (DEBUG_OBB)
3618 Slog.i(TAG, "Flushing all OBB state for path " + path);
3619
3620 synchronized (mObbMounts) {
3621 final List<ObbState> obbStatesToRemove = new LinkedList<ObbState>();
3622
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003623 final Iterator<ObbState> i = mObbPathToStateMap.values().iterator();
Kenny Rootaf9d6672010-10-08 09:21:39 -07003624 while (i.hasNext()) {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003625 final ObbState state = i.next();
Kenny Rootaf9d6672010-10-08 09:21:39 -07003626
3627 /*
3628 * If this entry's source file is in the volume path
3629 * that got unmounted, remove it because it's no
3630 * longer valid.
3631 */
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003632 if (state.canonicalPath.startsWith(path)) {
3633 obbStatesToRemove.add(state);
Kenny Rootaf9d6672010-10-08 09:21:39 -07003634 }
3635 }
3636
3637 for (final ObbState obbState : obbStatesToRemove) {
3638 if (DEBUG_OBB)
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003639 Slog.i(TAG, "Removing state for " + obbState.rawPath);
Kenny Rootaf9d6672010-10-08 09:21:39 -07003640
3641 removeObbStateLocked(obbState);
3642
3643 try {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003644 obbState.token.onObbResult(obbState.rawPath, obbState.nonce,
Kenny Rootaf9d6672010-10-08 09:21:39 -07003645 OnObbStateChangeListener.UNMOUNTED);
3646 } catch (RemoteException e) {
3647 Slog.i(TAG, "Couldn't send unmount notification for OBB: "
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003648 + obbState.rawPath);
Kenny Rootaf9d6672010-10-08 09:21:39 -07003649 }
3650 }
3651 }
3652 break;
3653 }
Kenny Roota02b8b02010-08-05 16:14:17 -07003654 }
3655 }
Kenny Roota02b8b02010-08-05 16:14:17 -07003656 }
3657
Jeff Sharkey0095a822018-02-15 13:06:53 -07003658 private static class ObbException extends Exception {
3659 public final int status;
3660
3661 public ObbException(int status, String message) {
3662 super(message);
3663 this.status = status;
3664 }
3665
3666 public ObbException(int status, Throwable cause) {
3667 super(cause.getMessage(), cause);
3668 this.status = status;
3669 }
3670 }
3671
Kenny Roota02b8b02010-08-05 16:14:17 -07003672 abstract class ObbAction {
Kenny Roota02b8b02010-08-05 16:14:17 -07003673
3674 ObbState mObbState;
3675
3676 ObbAction(ObbState obbState) {
3677 mObbState = obbState;
3678 }
3679
3680 public void execute(ObbActionHandler handler) {
3681 try {
3682 if (DEBUG_OBB)
Ben Komalo444eca22011-09-01 15:17:44 -07003683 Slog.i(TAG, "Starting to execute action: " + toString());
Sudheer Shanka25469aa2018-08-27 15:50:23 -07003684 handleExecute();
Jeff Sharkey0095a822018-02-15 13:06:53 -07003685 } catch (ObbException e) {
3686 notifyObbStateChange(e);
Kenny Roota02b8b02010-08-05 16:14:17 -07003687 }
3688 }
3689
Jeff Sharkey0095a822018-02-15 13:06:53 -07003690 abstract void handleExecute() throws ObbException;
Kenny Root38cf8862010-09-26 14:18:51 -07003691
Jeff Sharkey0095a822018-02-15 13:06:53 -07003692 protected void notifyObbStateChange(ObbException e) {
3693 Slog.w(TAG, e);
3694 notifyObbStateChange(e.status);
3695 }
3696
3697 protected void notifyObbStateChange(int status) {
Kenny Rootaf9d6672010-10-08 09:21:39 -07003698 if (mObbState == null || mObbState.token == null) {
3699 return;
3700 }
3701
Kenny Root38cf8862010-09-26 14:18:51 -07003702 try {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003703 mObbState.token.onObbResult(mObbState.rawPath, mObbState.nonce, status);
Kenny Root38cf8862010-09-26 14:18:51 -07003704 } catch (RemoteException e) {
Sudheer Shanka2250d562016-11-07 15:41:02 -08003705 Slog.w(TAG, "StorageEventListener went away while calling onObbStateChanged");
Kenny Root38cf8862010-09-26 14:18:51 -07003706 }
3707 }
Kenny Roota02b8b02010-08-05 16:14:17 -07003708 }
3709
3710 class MountObbAction extends ObbAction {
Ben Komalo444eca22011-09-01 15:17:44 -07003711 private final String mKey;
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003712 private final int mCallingUid;
Sudheer Shanka25469aa2018-08-27 15:50:23 -07003713 private ObbInfo mObbInfo;
Kenny Roota02b8b02010-08-05 16:14:17 -07003714
Sudheer Shanka25469aa2018-08-27 15:50:23 -07003715 MountObbAction(ObbState obbState, String key, int callingUid, ObbInfo obbInfo) {
Kenny Roota02b8b02010-08-05 16:14:17 -07003716 super(obbState);
3717 mKey = key;
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003718 mCallingUid = callingUid;
Sudheer Shanka25469aa2018-08-27 15:50:23 -07003719 mObbInfo = obbInfo;
Kenny Roota02b8b02010-08-05 16:14:17 -07003720 }
3721
Jason parks5af0b912010-11-29 09:05:25 -06003722 @Override
Jeff Sharkey0095a822018-02-15 13:06:53 -07003723 public void handleExecute() throws ObbException {
Kenny Rootaf9d6672010-10-08 09:21:39 -07003724 warnOnNotMounted();
3725
Sudheer Shanka25469aa2018-08-27 15:50:23 -07003726 if (!isUidOwnerOfPackageOrSystem(mObbInfo.packageName, mCallingUid)) {
Jeff Sharkey0095a822018-02-15 13:06:53 -07003727 throw new ObbException(ERROR_PERMISSION_DENIED, "Denied attempt to mount OBB "
Sudheer Shanka25469aa2018-08-27 15:50:23 -07003728 + mObbInfo.filename + " which is owned by " + mObbInfo.packageName);
Kenny Roota02b8b02010-08-05 16:14:17 -07003729 }
3730
Kenny Rootaf9d6672010-10-08 09:21:39 -07003731 final boolean isMounted;
3732 synchronized (mObbMounts) {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003733 isMounted = mObbPathToStateMap.containsKey(mObbState.rawPath);
Kenny Rootaf9d6672010-10-08 09:21:39 -07003734 }
3735 if (isMounted) {
Jeff Sharkey0095a822018-02-15 13:06:53 -07003736 throw new ObbException(ERROR_ALREADY_MOUNTED,
Sudheer Shanka25469aa2018-08-27 15:50:23 -07003737 "Attempt to mount OBB which is already mounted: " + mObbInfo.filename);
Kenny Rootaf9d6672010-10-08 09:21:39 -07003738 }
3739
Kenny Rootaf9d6672010-10-08 09:21:39 -07003740 final String hashedKey;
Jeff Sharkey41cd6812017-09-11 10:32:17 -06003741 final String binderKey;
Kenny Rootaf9d6672010-10-08 09:21:39 -07003742 if (mKey == null) {
3743 hashedKey = "none";
Jeff Sharkey41cd6812017-09-11 10:32:17 -06003744 binderKey = "";
Kenny Rootaf9d6672010-10-08 09:21:39 -07003745 } else {
Kenny Rootaf9d6672010-10-08 09:21:39 -07003746 try {
Kenny Root3b1abba2010-10-13 15:00:07 -07003747 SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
3748
Sudheer Shanka25469aa2018-08-27 15:50:23 -07003749 KeySpec ks = new PBEKeySpec(mKey.toCharArray(), mObbInfo.salt,
Kenny Root3b1abba2010-10-13 15:00:07 -07003750 PBKDF2_HASH_ROUNDS, CRYPTO_ALGORITHM_KEY_SIZE);
3751 SecretKey key = factory.generateSecret(ks);
3752 BigInteger bi = new BigInteger(key.getEncoded());
3753 hashedKey = bi.toString(16);
Jeff Sharkey41cd6812017-09-11 10:32:17 -06003754 binderKey = hashedKey;
Jeff Sharkey0095a822018-02-15 13:06:53 -07003755 } catch (GeneralSecurityException e) {
3756 throw new ObbException(ERROR_INTERNAL, e);
Kenny Root38cf8862010-09-26 14:18:51 -07003757 }
Kenny Rootaf9d6672010-10-08 09:21:39 -07003758 }
Kenny Root38cf8862010-09-26 14:18:51 -07003759
Kenny Rootaf9d6672010-10-08 09:21:39 -07003760 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06003761 mObbState.volId = mVold.createObb(mObbState.canonicalPath, binderKey,
3762 mObbState.ownerGid);
Zim95eca1d2019-11-15 18:03:00 +00003763 mVold.mount(mObbState.volId, 0, -1, null);
Kenny Roota02b8b02010-08-05 16:14:17 -07003764
Kenny Rootaf9d6672010-10-08 09:21:39 -07003765 if (DEBUG_OBB)
Xiaohui Chen621b3fc2015-10-02 14:41:42 -07003766 Slog.d(TAG, "Successfully mounted OBB " + mObbState.canonicalPath);
Kenny Rootaf9d6672010-10-08 09:21:39 -07003767
3768 synchronized (mObbMounts) {
3769 addObbStateLocked(mObbState);
3770 }
3771
Jeff Sharkey0095a822018-02-15 13:06:53 -07003772 notifyObbStateChange(MOUNTED);
3773 } catch (Exception e) {
3774 throw new ObbException(ERROR_COULD_NOT_MOUNT, e);
Kenny Root02c87302010-07-01 08:10:18 -07003775 }
3776 }
3777
Jason parks5af0b912010-11-29 09:05:25 -06003778 @Override
Kenny Roota02b8b02010-08-05 16:14:17 -07003779 public String toString() {
3780 StringBuilder sb = new StringBuilder();
3781 sb.append("MountObbAction{");
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003782 sb.append(mObbState);
Kenny Roota02b8b02010-08-05 16:14:17 -07003783 sb.append('}');
3784 return sb.toString();
3785 }
3786 }
3787
3788 class UnmountObbAction extends ObbAction {
Ben Komalo444eca22011-09-01 15:17:44 -07003789 private final boolean mForceUnmount;
Kenny Roota02b8b02010-08-05 16:14:17 -07003790
3791 UnmountObbAction(ObbState obbState, boolean force) {
3792 super(obbState);
3793 mForceUnmount = force;
3794 }
3795
Jason parks5af0b912010-11-29 09:05:25 -06003796 @Override
Jeff Sharkey0095a822018-02-15 13:06:53 -07003797 public void handleExecute() throws ObbException {
Kenny Rootaf9d6672010-10-08 09:21:39 -07003798 warnOnNotMounted();
3799
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003800 final ObbState existingState;
Kenny Root38cf8862010-09-26 14:18:51 -07003801 synchronized (mObbMounts) {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003802 existingState = mObbPathToStateMap.get(mObbState.rawPath);
Kenny Rootaf9d6672010-10-08 09:21:39 -07003803 }
Kenny Root38cf8862010-09-26 14:18:51 -07003804
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003805 if (existingState == null) {
Jeff Sharkey0095a822018-02-15 13:06:53 -07003806 throw new ObbException(ERROR_NOT_MOUNTED, "Missing existingState");
Kenny Rootaf9d6672010-10-08 09:21:39 -07003807 }
3808
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003809 if (existingState.ownerGid != mObbState.ownerGid) {
Jeff Sharkey0095a822018-02-15 13:06:53 -07003810 notifyObbStateChange(new ObbException(ERROR_PERMISSION_DENIED,
3811 "Permission denied to unmount OBB " + existingState.rawPath
3812 + " (owned by GID " + existingState.ownerGid + ")"));
Kenny Rootaf9d6672010-10-08 09:21:39 -07003813 return;
3814 }
3815
Kenny Rootaf9d6672010-10-08 09:21:39 -07003816 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06003817 mVold.unmount(mObbState.volId);
3818 mVold.destroyObb(mObbState.volId);
3819 mObbState.volId = null;
Kenny Roota02b8b02010-08-05 16:14:17 -07003820
Kenny Rootaf9d6672010-10-08 09:21:39 -07003821 synchronized (mObbMounts) {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003822 removeObbStateLocked(existingState);
Kenny Root38cf8862010-09-26 14:18:51 -07003823 }
3824
Jeff Sharkey0095a822018-02-15 13:06:53 -07003825 notifyObbStateChange(UNMOUNTED);
3826 } catch (Exception e) {
3827 throw new ObbException(ERROR_COULD_NOT_UNMOUNT, e);
Kenny Roota02b8b02010-08-05 16:14:17 -07003828 }
3829 }
3830
Jason parks5af0b912010-11-29 09:05:25 -06003831 @Override
Kenny Roota02b8b02010-08-05 16:14:17 -07003832 public String toString() {
3833 StringBuilder sb = new StringBuilder();
3834 sb.append("UnmountObbAction{");
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003835 sb.append(mObbState);
Kenny Roota02b8b02010-08-05 16:14:17 -07003836 sb.append(",force=");
3837 sb.append(mForceUnmount);
Kenny Roota02b8b02010-08-05 16:14:17 -07003838 sb.append('}');
3839 return sb.toString();
3840 }
Kenny Root02c87302010-07-01 08:10:18 -07003841 }
Kenny Root38cf8862010-09-26 14:18:51 -07003842
Jeff Sharkey7e19f532017-11-06 13:54:11 -07003843 private void dispatchOnStatus(IVoldTaskListener listener, int status,
3844 PersistableBundle extras) {
3845 if (listener != null) {
3846 try {
3847 listener.onStatus(status, extras);
3848 } catch (RemoteException ignored) {
3849 }
3850 }
3851 }
3852
3853 private void dispatchOnFinished(IVoldTaskListener listener, int status,
3854 PersistableBundle extras) {
3855 if (listener != null) {
3856 try {
3857 listener.onFinished(status, extras);
3858 } catch (RemoteException ignored) {
3859 }
3860 }
3861 }
3862
Sudheer Shanka3a0df3b2018-12-12 12:43:43 -08003863 private int getMountMode(int uid, String packageName) {
Jeff Sharkey6fd69942019-03-26 17:53:35 -06003864 final int mode = getMountModeInternal(uid, packageName);
3865 if (LOCAL_LOGV) {
3866 Slog.v(TAG, "Resolved mode " + mode + " for " + packageName + "/"
3867 + UserHandle.formatUid(uid));
3868 }
3869 return mode;
3870 }
3871
3872 private int getMountModeInternal(int uid, String packageName) {
Sudheer Shanka3a0df3b2018-12-12 12:43:43 -08003873 try {
Jeff Sharkey6fd69942019-03-26 17:53:35 -06003874 // Get some easy cases out of the way first
Sudheer Shanka3a0df3b2018-12-12 12:43:43 -08003875 if (Process.isIsolated(uid)) {
3876 return Zygote.MOUNT_EXTERNAL_NONE;
3877 }
Sudheer Shankab1613982019-05-16 16:55:50 -07003878
3879 final String[] packagesForUid = mIPackageManager.getPackagesForUid(uid);
Sudheer Shanka1df72db2019-05-24 10:59:52 -07003880 if (ArrayUtils.isEmpty(packagesForUid)) {
3881 // It's possible the package got uninstalled already, so just ignore.
3882 return Zygote.MOUNT_EXTERNAL_NONE;
3883 }
Sudheer Shankab1613982019-05-16 16:55:50 -07003884 if (packageName == null) {
3885 packageName = packagesForUid[0];
3886 }
3887
Jeff Sharkey6fd69942019-03-26 17:53:35 -06003888 if (mPmInternal.isInstantApp(packageName, UserHandle.getUserId(uid))) {
Winson Chiu5118d492019-05-15 18:24:06 +00003889 return Zygote.MOUNT_EXTERNAL_NONE;
Jeff Sharkey6fd69942019-03-26 17:53:35 -06003890 }
3891
Martijn Coenen44db1ac2019-12-03 16:06:19 +01003892 if (mIsFuseEnabled && mMediaStoreAuthorityAppId == UserHandle.getAppId(uid)) {
3893 // Determine if caller requires pass_through mount; note that we do this for
3894 // all processes that share a UID with MediaProvider; but this is fine, since
3895 // those processes anyway share the same rights as MediaProvider.
Zim74a9bba2019-09-03 20:49:13 +01003896 return Zygote.MOUNT_EXTERNAL_PASS_THROUGH;
3897 }
3898
Martijn Coenen496ac002020-01-08 14:55:53 +01003899 if (mIsFuseEnabled && mDownloadsAuthorityAppId == UserHandle.getAppId(uid)) {
3900 // DownloadManager can write in app-private directories on behalf of apps;
3901 // give it write access to Android/
3902 return Zygote.MOUNT_EXTERNAL_ANDROID_WRITABLE;
3903 }
3904
3905 final boolean hasMtp = mIPackageManager.checkUidPermission(ACCESS_MTP, uid) ==
3906 PERMISSION_GRANTED;
3907 if (mIsFuseEnabled && hasMtp) {
3908 // The process hosting the MTP server should be able to write in Android/
3909 return Zygote.MOUNT_EXTERNAL_ANDROID_WRITABLE;
3910 }
3911
Jeff Sharkey6fd69942019-03-26 17:53:35 -06003912 // Determine if caller is holding runtime permission
Chad Brubaker45810af2019-04-08 19:19:48 -07003913 final boolean hasRead = StorageManager.checkPermissionAndCheckOp(mContext, false, 0,
Jeff Sharkey6fd69942019-03-26 17:53:35 -06003914 uid, packageName, READ_EXTERNAL_STORAGE, OP_READ_EXTERNAL_STORAGE);
Chad Brubaker45810af2019-04-08 19:19:48 -07003915 final boolean hasWrite = StorageManager.checkPermissionAndCheckOp(mContext, false, 0,
Jeff Sharkey6fd69942019-03-26 17:53:35 -06003916 uid, packageName, WRITE_EXTERNAL_STORAGE, OP_WRITE_EXTERNAL_STORAGE);
Jeff Sharkey6fd69942019-03-26 17:53:35 -06003917
3918 // We're only willing to give out broad access if they also hold
3919 // runtime permission; this is a firm CDD requirement
3920 final boolean hasFull = mIPackageManager.checkUidPermission(WRITE_MEDIA_STORAGE,
3921 uid) == PERMISSION_GRANTED;
Jeff Sharkey26874a22019-04-17 21:30:47 -06003922 if (hasFull && hasWrite) {
Jeff Sharkey6fd69942019-03-26 17:53:35 -06003923 return Zygote.MOUNT_EXTERNAL_FULL;
3924 }
3925
3926 // We're only willing to give out installer access if they also hold
3927 // runtime permission; this is a firm CDD requirement
3928 final boolean hasInstall = mIPackageManager.checkUidPermission(INSTALL_PACKAGES,
3929 uid) == PERMISSION_GRANTED;
Sudheer Shankab1613982019-05-16 16:55:50 -07003930 boolean hasInstallOp = false;
3931 // OP_REQUEST_INSTALL_PACKAGES is granted/denied per package but vold can't
3932 // update mountpoints of a specific package. So, check the appop for all packages
3933 // sharing the uid and allow same level of storage access for all packages even if
3934 // one of the packages has the appop granted.
3935 for (String uidPackageName : packagesForUid) {
3936 if (mIAppOpsService.checkOperation(
3937 OP_REQUEST_INSTALL_PACKAGES, uid, uidPackageName) == MODE_ALLOWED) {
3938 hasInstallOp = true;
3939 break;
3940 }
3941 }
Jeff Sharkey26874a22019-04-17 21:30:47 -06003942 if ((hasInstall || hasInstallOp) && hasWrite) {
Martijn Coenenfc9c3b62019-12-13 16:36:27 +01003943 return Zygote.MOUNT_EXTERNAL_INSTALLER;
Jeff Sharkey6fd69942019-03-26 17:53:35 -06003944 }
3945
3946 // Otherwise we're willing to give out sandboxed or non-sandboxed if
3947 // they hold the runtime permission
Nandana Duttdc15bb42020-01-03 16:43:46 +00003948 boolean hasLegacy = mIAppOpsService.checkOperation(OP_LEGACY_STORAGE,
Jeff Sharkey6fd69942019-03-26 17:53:35 -06003949 uid, packageName) == MODE_ALLOWED;
Nandana Duttdc15bb42020-01-03 16:43:46 +00003950
3951 // Hack(b/147137425): we have to honor hasRequestedLegacyExternalStorage for a short
3952 // while to enable 2 cases.
3953 // 1) Apps that want to be in scoped storage in R, but want to opt out in Q devices,
3954 // because they want to use raw file paths, would fail until fuse is enabled by default.
3955 // 2) Test apps that target current sdk will fail. They would fail even after fuse is
3956 // enabled, but we are fixing it with b/142395442. We are not planning to enable
3957 // fuse by default until b/142395442 is fixed.
3958 if (!hasLegacy && !mIsFuseEnabled) {
3959 ApplicationInfo ai = mIPackageManager.getApplicationInfo(packageName,
3960 0, UserHandle.getUserId(uid));
3961 hasLegacy = ai.hasRequestedLegacyExternalStorage();
3962 }
3963
Jeff Sharkey26874a22019-04-17 21:30:47 -06003964 if (hasLegacy && hasWrite) {
3965 return Zygote.MOUNT_EXTERNAL_WRITE;
3966 } else if (hasLegacy && hasRead) {
3967 return Zygote.MOUNT_EXTERNAL_READ;
Sudheer Shanka3a0df3b2018-12-12 12:43:43 -08003968 } else {
Sudheer Shanka783c90e2019-04-12 13:55:20 -07003969 return Zygote.MOUNT_EXTERNAL_DEFAULT;
Sudheer Shanka3a0df3b2018-12-12 12:43:43 -08003970 }
3971 } catch (RemoteException e) {
3972 // Should not happen
3973 }
3974 return Zygote.MOUNT_EXTERNAL_NONE;
3975 }
3976
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07003977 private static class Callbacks extends Handler {
3978 private static final int MSG_STORAGE_STATE_CHANGED = 1;
3979 private static final int MSG_VOLUME_STATE_CHANGED = 2;
Jeff Sharkey50a05452015-04-29 11:24:52 -07003980 private static final int MSG_VOLUME_RECORD_CHANGED = 3;
3981 private static final int MSG_VOLUME_FORGOTTEN = 4;
3982 private static final int MSG_DISK_SCANNED = 5;
Makoto Onuki9dc575d2015-06-12 16:10:25 -07003983 private static final int MSG_DISK_DESTROYED = 6;
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07003984
Sudheer Shanka2250d562016-11-07 15:41:02 -08003985 private final RemoteCallbackList<IStorageEventListener>
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07003986 mCallbacks = new RemoteCallbackList<>();
3987
3988 public Callbacks(Looper looper) {
3989 super(looper);
3990 }
3991
Sudheer Shanka2250d562016-11-07 15:41:02 -08003992 public void register(IStorageEventListener callback) {
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07003993 mCallbacks.register(callback);
3994 }
3995
Sudheer Shanka2250d562016-11-07 15:41:02 -08003996 public void unregister(IStorageEventListener callback) {
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07003997 mCallbacks.unregister(callback);
3998 }
3999
4000 @Override
4001 public void handleMessage(Message msg) {
4002 final SomeArgs args = (SomeArgs) msg.obj;
4003 final int n = mCallbacks.beginBroadcast();
4004 for (int i = 0; i < n; i++) {
Sudheer Shanka2250d562016-11-07 15:41:02 -08004005 final IStorageEventListener callback = mCallbacks.getBroadcastItem(i);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07004006 try {
4007 invokeCallback(callback, msg.what, args);
4008 } catch (RemoteException ignored) {
4009 }
4010 }
4011 mCallbacks.finishBroadcast();
4012 args.recycle();
4013 }
4014
Sudheer Shanka2250d562016-11-07 15:41:02 -08004015 private void invokeCallback(IStorageEventListener callback, int what, SomeArgs args)
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07004016 throws RemoteException {
4017 switch (what) {
4018 case MSG_STORAGE_STATE_CHANGED: {
4019 callback.onStorageStateChanged((String) args.arg1, (String) args.arg2,
4020 (String) args.arg3);
4021 break;
4022 }
4023 case MSG_VOLUME_STATE_CHANGED: {
4024 callback.onVolumeStateChanged((VolumeInfo) args.arg1, args.argi2, args.argi3);
4025 break;
4026 }
Jeff Sharkey50a05452015-04-29 11:24:52 -07004027 case MSG_VOLUME_RECORD_CHANGED: {
4028 callback.onVolumeRecordChanged((VolumeRecord) args.arg1);
4029 break;
4030 }
4031 case MSG_VOLUME_FORGOTTEN: {
4032 callback.onVolumeForgotten((String) args.arg1);
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07004033 break;
4034 }
Jeff Sharkey620b32b2015-04-23 19:36:02 -07004035 case MSG_DISK_SCANNED: {
4036 callback.onDiskScanned((DiskInfo) args.arg1, args.argi2);
Jeff Sharkey7e92ef32015-04-17 17:35:07 -07004037 break;
4038 }
Makoto Onuki9dc575d2015-06-12 16:10:25 -07004039 case MSG_DISK_DESTROYED: {
4040 callback.onDiskDestroyed((DiskInfo) args.arg1);
4041 break;
4042 }
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07004043 }
4044 }
4045
4046 private void notifyStorageStateChanged(String path, String oldState, String newState) {
4047 final SomeArgs args = SomeArgs.obtain();
4048 args.arg1 = path;
4049 args.arg2 = oldState;
4050 args.arg3 = newState;
4051 obtainMessage(MSG_STORAGE_STATE_CHANGED, args).sendToTarget();
4052 }
4053
4054 private void notifyVolumeStateChanged(VolumeInfo vol, int oldState, int newState) {
4055 final SomeArgs args = SomeArgs.obtain();
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07004056 args.arg1 = vol.clone();
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07004057 args.argi2 = oldState;
4058 args.argi3 = newState;
4059 obtainMessage(MSG_VOLUME_STATE_CHANGED, args).sendToTarget();
4060 }
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07004061
Jeff Sharkey50a05452015-04-29 11:24:52 -07004062 private void notifyVolumeRecordChanged(VolumeRecord rec) {
4063 final SomeArgs args = SomeArgs.obtain();
4064 args.arg1 = rec.clone();
4065 obtainMessage(MSG_VOLUME_RECORD_CHANGED, args).sendToTarget();
4066 }
4067
4068 private void notifyVolumeForgotten(String fsUuid) {
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07004069 final SomeArgs args = SomeArgs.obtain();
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07004070 args.arg1 = fsUuid;
Jeff Sharkey50a05452015-04-29 11:24:52 -07004071 obtainMessage(MSG_VOLUME_FORGOTTEN, args).sendToTarget();
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07004072 }
Jeff Sharkey7e92ef32015-04-17 17:35:07 -07004073
Jeff Sharkey620b32b2015-04-23 19:36:02 -07004074 private void notifyDiskScanned(DiskInfo disk, int volumeCount) {
Jeff Sharkey7e92ef32015-04-17 17:35:07 -07004075 final SomeArgs args = SomeArgs.obtain();
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07004076 args.arg1 = disk.clone();
Jeff Sharkey620b32b2015-04-23 19:36:02 -07004077 args.argi2 = volumeCount;
4078 obtainMessage(MSG_DISK_SCANNED, args).sendToTarget();
Jeff Sharkey7e92ef32015-04-17 17:35:07 -07004079 }
Makoto Onuki9dc575d2015-06-12 16:10:25 -07004080
4081 private void notifyDiskDestroyed(DiskInfo disk) {
4082 final SomeArgs args = SomeArgs.obtain();
4083 args.arg1 = disk.clone();
4084 obtainMessage(MSG_DISK_DESTROYED, args).sendToTarget();
4085 }
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07004086 }
4087
Kenny Root38cf8862010-09-26 14:18:51 -07004088 @Override
Jeff Sharkey5aca2b82013-10-16 16:21:54 -07004089 protected void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
Jeff Sharkeyfe9a53b2017-03-31 14:08:23 -06004090 if (!DumpUtils.checkDumpPermission(mContext, TAG, writer)) return;
Jeff Sharkey5aca2b82013-10-16 16:21:54 -07004091
4092 final IndentingPrintWriter pw = new IndentingPrintWriter(writer, " ", 160);
Jeff Sharkey27de30d2015-04-18 16:20:27 -07004093 synchronized (mLock) {
4094 pw.println("Disks:");
4095 pw.increaseIndent();
4096 for (int i = 0; i < mDisks.size(); i++) {
4097 final DiskInfo disk = mDisks.valueAt(i);
4098 disk.dump(pw);
4099 }
4100 pw.decreaseIndent();
4101
4102 pw.println();
4103 pw.println("Volumes:");
4104 pw.increaseIndent();
4105 for (int i = 0; i < mVolumes.size(); i++) {
4106 final VolumeInfo vol = mVolumes.valueAt(i);
4107 if (VolumeInfo.ID_PRIVATE_INTERNAL.equals(vol.id)) continue;
4108 vol.dump(pw);
4109 }
4110 pw.decreaseIndent();
4111
4112 pw.println();
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07004113 pw.println("Records:");
Jeff Sharkey27de30d2015-04-18 16:20:27 -07004114 pw.increaseIndent();
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07004115 for (int i = 0; i < mRecords.size(); i++) {
4116 final VolumeRecord note = mRecords.valueAt(i);
4117 note.dump(pw);
Jeff Sharkey27de30d2015-04-18 16:20:27 -07004118 }
4119 pw.decreaseIndent();
Jeff Sharkey275e3e42015-04-24 16:10:32 -07004120
4121 pw.println();
4122 pw.println("Primary storage UUID: " + mPrimaryStorageUuid);
Jeff Sharkeyb0c363b22018-12-15 11:53:03 -07004123
4124 pw.println();
Felipe Leme281389a2016-10-10 17:12:20 -07004125 final Pair<String, Long> pair = StorageManager.getPrimaryStoragePathAndSize();
4126 if (pair == null) {
4127 pw.println("Internal storage total size: N/A");
4128 } else {
4129 pw.print("Internal storage (");
4130 pw.print(pair.first);
4131 pw.print(") total size: ");
4132 pw.print(pair.second);
4133 pw.print(" (");
Jeff Sharkey9f2dc052018-01-07 16:47:31 -07004134 pw.print(DataUnit.MEBIBYTES.toBytes(pair.second));
4135 pw.println(" MiB)");
Felipe Leme281389a2016-10-10 17:12:20 -07004136 }
Jeff Sharkeyb0c363b22018-12-15 11:53:03 -07004137
4138 pw.println();
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07004139 pw.println("Local unlocked users: " + Arrays.toString(mLocalUnlockedUsers));
4140 pw.println("System unlocked users: " + Arrays.toString(mSystemUnlockedUsers));
Jeff Sharkeyb0c363b22018-12-15 11:53:03 -07004141
4142 final ContentResolver cr = mContext.getContentResolver();
4143 pw.println();
4144 pw.println("Isolated storage, local feature flag: "
4145 + Settings.Global.getInt(cr, Settings.Global.ISOLATED_STORAGE_LOCAL, 0));
4146 pw.println("Isolated storage, remote feature flag: "
4147 + Settings.Global.getInt(cr, Settings.Global.ISOLATED_STORAGE_REMOTE, 0));
4148 pw.println("Isolated storage, resolved: " + StorageManager.hasIsolatedStorage());
Jeff Sharkey27de30d2015-04-18 16:20:27 -07004149 }
Kenny Root38cf8862010-09-26 14:18:51 -07004150
Kenny Root38cf8862010-09-26 14:18:51 -07004151 synchronized (mObbMounts) {
Jeff Sharkey27de30d2015-04-18 16:20:27 -07004152 pw.println();
Jeff Sharkey5aca2b82013-10-16 16:21:54 -07004153 pw.println("mObbMounts:");
4154 pw.increaseIndent();
4155 final Iterator<Entry<IBinder, List<ObbState>>> binders = mObbMounts.entrySet()
4156 .iterator();
Kenny Rootaf9d6672010-10-08 09:21:39 -07004157 while (binders.hasNext()) {
4158 Entry<IBinder, List<ObbState>> e = binders.next();
Jeff Sharkey5aca2b82013-10-16 16:21:54 -07004159 pw.println(e.getKey() + ":");
4160 pw.increaseIndent();
Kenny Rootaf9d6672010-10-08 09:21:39 -07004161 final List<ObbState> obbStates = e.getValue();
Kenny Root38cf8862010-09-26 14:18:51 -07004162 for (final ObbState obbState : obbStates) {
Jeff Sharkey5aca2b82013-10-16 16:21:54 -07004163 pw.println(obbState);
Kenny Root38cf8862010-09-26 14:18:51 -07004164 }
Jeff Sharkey5aca2b82013-10-16 16:21:54 -07004165 pw.decreaseIndent();
Kenny Root38cf8862010-09-26 14:18:51 -07004166 }
Jeff Sharkey5aca2b82013-10-16 16:21:54 -07004167 pw.decreaseIndent();
Kenny Rootaf9d6672010-10-08 09:21:39 -07004168
Jeff Sharkey5aca2b82013-10-16 16:21:54 -07004169 pw.println();
4170 pw.println("mObbPathToStateMap:");
4171 pw.increaseIndent();
Kenny Rootaf9d6672010-10-08 09:21:39 -07004172 final Iterator<Entry<String, ObbState>> maps = mObbPathToStateMap.entrySet().iterator();
4173 while (maps.hasNext()) {
4174 final Entry<String, ObbState> e = maps.next();
Jeff Sharkey5aca2b82013-10-16 16:21:54 -07004175 pw.print(e.getKey());
4176 pw.print(" -> ");
4177 pw.println(e.getValue());
Kenny Rootaf9d6672010-10-08 09:21:39 -07004178 }
Jeff Sharkey5aca2b82013-10-16 16:21:54 -07004179 pw.decreaseIndent();
Kenny Root38cf8862010-09-26 14:18:51 -07004180 }
Kenny Root4161f9b2011-07-13 09:48:33 -07004181
Robert Greenwalt470fd722012-01-18 12:51:15 -08004182 pw.println();
Christopher Tate7265abe2014-11-21 13:54:45 -08004183 pw.print("Last maintenance: ");
Jeff Sharkeye8a4b662015-06-27 15:43:45 -07004184 pw.println(TimeUtils.formatForLogging(mLastMaintenance));
Kenny Root38cf8862010-09-26 14:18:51 -07004185 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004186
Jeff Sharkeyfa23c5a2011-08-09 21:44:24 -07004187 /** {@inheritDoc} */
Jeff Sharkey48877892015-03-18 11:27:19 -07004188 @Override
Jeff Sharkeyfa23c5a2011-08-09 21:44:24 -07004189 public void monitor() {
Jeff Sharkey54402792017-09-15 16:05:19 -06004190 try {
4191 mVold.monitor();
4192 } catch (Exception e) {
4193 Slog.wtf(TAG, e);
Paul Lawrence1c62cbb2015-06-03 14:14:52 -07004194 }
Jeff Sharkeyfa23c5a2011-08-09 21:44:24 -07004195 }
Svet Ganov6ee871e2015-07-10 14:29:33 -07004196
Sudheer Shanka2250d562016-11-07 15:41:02 -08004197 private final class StorageManagerInternalImpl extends StorageManagerInternal {
Svet Ganov6ee871e2015-07-10 14:29:33 -07004198 // Not guarded by a lock.
4199 private final CopyOnWriteArrayList<ExternalStorageMountPolicy> mPolicies =
4200 new CopyOnWriteArrayList<>();
4201
Risanaec0ee72018-10-31 10:10:12 +09004202 @GuardedBy("mResetListeners")
4203 private final List<StorageManagerInternal.ResetListener> mResetListeners =
4204 new ArrayList<>();
4205
Svet Ganov6ee871e2015-07-10 14:29:33 -07004206 @Override
4207 public void addExternalStoragePolicy(ExternalStorageMountPolicy policy) {
4208 // No locking - CopyOnWriteArrayList
4209 mPolicies.add(policy);
4210 }
4211
4212 @Override
4213 public void onExternalStoragePolicyChanged(int uid, String packageName) {
4214 final int mountMode = getExternalStorageMountMode(uid, packageName);
4215 remountUidExternalStorage(uid, mountMode);
4216 }
4217
4218 @Override
4219 public int getExternalStorageMountMode(int uid, String packageName) {
Sudheer Shanka3a0df3b2018-12-12 12:43:43 -08004220 if (ENABLE_ISOLATED_STORAGE) {
4221 return getMountMode(uid, packageName);
4222 }
Sudheer Shankab1613982019-05-16 16:55:50 -07004223 try {
4224 if (packageName == null) {
4225 final String[] packagesForUid = mIPackageManager.getPackagesForUid(uid);
4226 packageName = packagesForUid[0];
4227 }
4228 } catch (RemoteException e) {
4229 // Should not happen - same process
4230 }
Svet Ganov6ee871e2015-07-10 14:29:33 -07004231 // No locking - CopyOnWriteArrayList
4232 int mountMode = Integer.MAX_VALUE;
4233 for (ExternalStorageMountPolicy policy : mPolicies) {
4234 final int policyMode = policy.getMountMode(uid, packageName);
4235 if (policyMode == Zygote.MOUNT_EXTERNAL_NONE) {
4236 return Zygote.MOUNT_EXTERNAL_NONE;
4237 }
4238 mountMode = Math.min(mountMode, policyMode);
4239 }
4240 if (mountMode == Integer.MAX_VALUE) {
4241 return Zygote.MOUNT_EXTERNAL_NONE;
4242 }
4243 return mountMode;
4244 }
4245
Risanaec0ee72018-10-31 10:10:12 +09004246 @Override
4247 public void addResetListener(StorageManagerInternal.ResetListener listener) {
4248 synchronized (mResetListeners) {
4249 mResetListeners.add(listener);
4250 }
4251 }
4252
4253 public void onReset(IVold vold) {
4254 synchronized (mResetListeners) {
4255 for (StorageManagerInternal.ResetListener listener : mResetListeners) {
4256 listener.onReset(vold);
4257 }
4258 }
4259 }
4260
Martijn Coenen73918202019-12-09 17:02:44 +01004261 @Override
4262 public void resetUser(int userId) {
4263 // TODO(b/145931219): ideally, we only reset storage for the user in question,
4264 // but for now, reset everything.
4265 mHandler.obtainMessage(H_RESET).sendToTarget();
4266 }
4267
Svet Ganov6ee871e2015-07-10 14:29:33 -07004268 public boolean hasExternalStorage(int uid, String packageName) {
Amith Yamasani2bd5cff2015-07-22 14:42:31 -07004269 // No need to check for system uid. This avoids a deadlock between
4270 // PackageManagerService and AppOpsService.
4271 if (uid == Process.SYSTEM_UID) {
4272 return true;
4273 }
Sudheer Shanka3a0df3b2018-12-12 12:43:43 -08004274 if (ENABLE_ISOLATED_STORAGE) {
4275 return getMountMode(uid, packageName) != Zygote.MOUNT_EXTERNAL_NONE;
4276 }
Svet Ganov6ee871e2015-07-10 14:29:33 -07004277 // No locking - CopyOnWriteArrayList
4278 for (ExternalStorageMountPolicy policy : mPolicies) {
4279 final boolean policyHasStorage = policy.hasExternalStorage(uid, packageName);
4280 if (!policyHasStorage) {
4281 return false;
4282 }
4283 }
4284 return true;
4285 }
Sudheer Shankab1613982019-05-16 16:55:50 -07004286
4287 public void onAppOpsChanged(int code, int uid,
4288 @Nullable String packageName, int mode) {
4289 if (mode == MODE_ALLOWED && (code == OP_READ_EXTERNAL_STORAGE
4290 || code == OP_WRITE_EXTERNAL_STORAGE
4291 || code == OP_REQUEST_INSTALL_PACKAGES)) {
4292 final long token = Binder.clearCallingIdentity();
4293 try {
4294 final UserManagerInternal userManagerInternal =
4295 LocalServices.getService(UserManagerInternal.class);
4296 if (userManagerInternal.isUserInitialized(UserHandle.getUserId(uid))) {
4297 onExternalStoragePolicyChanged(uid, packageName);
4298 }
4299 } finally {
4300 Binder.restoreCallingIdentity(token);
4301 }
4302 }
4303 }
Svet Ganov6ee871e2015-07-10 14:29:33 -07004304 }
Jeff Sharkeyfa23c5a2011-08-09 21:44:24 -07004305}