blob: a04f25b0d20c653e3ed82a362933153d8fe52ec5 [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;
Zim69e9c092020-01-21 13:32:32 +000040import static android.os.storage.StorageManager.PROP_FUSE;
41import static android.os.storage.StorageManager.PROP_SETTINGS_FUSE;
Jeff Sharkey5790af02018-08-13 17:42:54 -060042
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -070043import static com.android.internal.util.XmlUtils.readIntAttribute;
Jeff Sharkeye8a4b662015-06-27 15:43:45 -070044import static com.android.internal.util.XmlUtils.readLongAttribute;
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -070045import static com.android.internal.util.XmlUtils.readStringAttribute;
46import static com.android.internal.util.XmlUtils.writeIntAttribute;
Jeff Sharkeye8a4b662015-06-27 15:43:45 -070047import static com.android.internal.util.XmlUtils.writeLongAttribute;
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -070048import static com.android.internal.util.XmlUtils.writeStringAttribute;
Zim7924a512020-01-15 15:23:54 +000049import static com.android.server.storage.StorageUserConnection.REMOTE_TIMEOUT_SECONDS;
Jeff Sharkey5790af02018-08-13 17:42:54 -060050
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -070051import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT;
52import static org.xmlpull.v1.XmlPullParser.START_TAG;
53
Jason parks8888c592011-01-20 22:46:41 -060054import android.Manifest;
Jeff Sharkeyef10ee02015-07-05 14:17:27 -070055import android.annotation.Nullable;
Xiaohui Chen621b3fc2015-10-02 14:41:42 -070056import android.app.ActivityManager;
Martijn Coenen7084c6a2019-11-22 16:32:09 +010057import android.app.ActivityManagerInternal;
Jeff Sharkey2d8b4e82013-09-17 17:30:33 -070058import android.app.AppOpsManager;
Jeff Sharkey14cbe522015-07-08 14:06:37 -070059import android.app.IActivityManager;
Jeff Sharkey9765e442017-12-14 22:15:14 -070060import android.app.KeyguardManager;
Pavel Grafovce72ef02018-01-10 17:14:11 +000061import android.app.admin.SecurityLog;
Jeff Sharkey9bed0702017-01-23 20:37:05 -070062import android.app.usage.StorageStatsManager;
Jeff Sharkeybcd262d2015-06-10 09:41:17 -070063import android.content.BroadcastReceiver;
Jeff Sharkeyb0c363b22018-12-15 11:53:03 -070064import android.content.ContentResolver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080065import android.content.Context;
66import android.content.Intent;
Jeff Sharkeybcd262d2015-06-10 09:41:17 -070067import android.content.IntentFilter;
Nandana Duttdc15bb42020-01-03 16:43:46 +000068import android.content.pm.ApplicationInfo;
Sudheer Shanka3a0df3b2018-12-12 12:43:43 -080069import android.content.pm.IPackageManager;
Jeff Sharkey275e3e42015-04-24 16:10:32 -070070import android.content.pm.IPackageMoveObserver;
71import android.content.pm.PackageManager;
Sudheer Shanka0a541a52018-07-31 13:21:11 -070072import android.content.pm.PackageManagerInternal;
Jeff Sharkey14cbe522015-07-08 14:06:37 -070073import android.content.pm.ProviderInfo;
Jeff Sharkeybcd262d2015-06-10 09:41:17 -070074import android.content.pm.UserInfo;
Elliott Hughesf839b4f2014-09-26 12:30:47 -070075import android.content.res.Configuration;
Kenny Root02c87302010-07-01 08:10:18 -070076import android.content.res.ObbInfo;
Daniel Colascione766b6322018-01-08 19:10:36 -080077import android.database.ContentObserver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080078import android.net.Uri;
Kenny Root02c87302010-07-01 08:10:18 -070079import android.os.Binder;
Jeff Sharkey4c099d02015-05-15 13:45:00 -070080import android.os.DropBoxManager;
Kenny Roota02b8b02010-08-05 16:14:17 -070081import android.os.Environment;
Suchi Amalapurapuc42e29e2010-02-22 16:03:53 -080082import android.os.Handler;
Dianne Hackbornefa92b22013-05-03 14:11:43 -070083import android.os.HandlerThread;
Kenny Roota02b8b02010-08-05 16:14:17 -070084import android.os.IBinder;
Jin Qian12690d52017-10-13 18:17:04 -070085import android.os.IStoraged;
Jeff Sharkey1019de92017-09-06 13:47:03 -060086import android.os.IVold;
Jeff Sharkey8058fe62017-09-13 11:50:33 -060087import android.os.IVoldListener;
Zim95eca1d2019-11-15 18:03:00 +000088import android.os.IVoldMountCallback;
Jeff Sharkeyb302c542017-09-15 12:57:59 -060089import android.os.IVoldTaskListener;
Daniel Sandler5f27ef42010-03-16 15:42:02 -040090import android.os.Looper;
Suchi Amalapurapuc42e29e2010-02-22 16:03:53 -080091import android.os.Message;
Daichi Hirono9e8d9e22015-11-13 14:37:00 +090092import android.os.ParcelFileDescriptor;
Jeff Sharkey500ce9e2017-02-12 02:39:24 -070093import android.os.ParcelableException;
Jeff Sharkeyb302c542017-09-15 12:57:59 -060094import android.os.PersistableBundle;
Jeff Sharkeyce14cd02015-12-07 15:35:42 -070095import android.os.PowerManager;
Jeff Sharkey9527b222015-06-24 15:24:48 -070096import android.os.Process;
Jeff Sharkey7151a9a2015-04-04 15:22:37 -070097import android.os.RemoteCallbackList;
San Mehat4270e1e2010-01-29 05:32:19 -080098import android.os.RemoteException;
Suchi Amalapurapufd3530f2010-01-18 00:15:59 -080099import android.os.ServiceManager;
Paul Crowleyfc0b5192018-07-02 13:58:10 -0700100import android.os.ServiceSpecificException;
Jeff Sharkeyedcdaf62015-07-09 09:45:36 -0700101import android.os.SystemClock;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800102import android.os.SystemProperties;
Dianne Hackbornf02b60a2012-08-16 10:48:27 -0700103import android.os.UserHandle;
Emily Bernier92aa5a22014-07-07 10:11:48 -0400104import android.os.UserManager;
Sudheer Shankab1613982019-05-16 16:55:50 -0700105import android.os.UserManagerInternal;
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -0700106import android.os.storage.DiskInfo;
Kenny Roota02b8b02010-08-05 16:14:17 -0700107import android.os.storage.IObbActionListener;
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -0700108import android.os.storage.IStorageEventListener;
Sudheer Shanka2250d562016-11-07 15:41:02 -0800109import android.os.storage.IStorageManager;
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -0700110import android.os.storage.IStorageShutdownObserver;
Kenny Rootaf9d6672010-10-08 09:21:39 -0700111import android.os.storage.OnObbStateChangeListener;
Paul Lawrence46791e72014-04-03 09:10:26 -0700112import android.os.storage.StorageManager;
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -0700113import android.os.storage.StorageManagerInternal;
Mike Lockwood2f6a3882011-05-09 19:08:06 -0700114import android.os.storage.StorageVolume;
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -0700115import android.os.storage.VolumeInfo;
Jeff Sharkeyb36586a2015-04-27 08:42:28 -0700116import android.os.storage.VolumeRecord;
Jeff Sharkey5d0c55c2019-01-24 14:32:31 -0700117import android.provider.DeviceConfig;
Martijn Coenen496ac002020-01-08 14:55:53 +0100118import android.provider.Downloads;
Jeff Sharkey14cbe522015-07-08 14:06:37 -0700119import android.provider.MediaStore;
Jeff Sharkeye8a4b662015-06-27 15:43:45 -0700120import android.provider.Settings;
Inseob Kimc1246e62018-11-08 13:13:54 +0900121import android.sysprop.VoldProperties;
Jason parksf7b3cd42011-01-27 09:28:25 -0600122import android.text.TextUtils;
Jeff Sharkey1783f142015-04-17 10:52:51 -0700123import android.text.format.DateUtils;
Jeff Sharkey48877892015-03-18 11:27:19 -0700124import android.util.ArrayMap;
Jeff Sharkey04b4ba12019-12-15 22:42:42 -0700125import android.util.ArraySet;
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700126import android.util.AtomicFile;
Jeff Sharkey9f2dc052018-01-07 16:47:31 -0700127import android.util.DataUnit;
Abhijeet Kaurb9847712019-11-19 16:35:47 +0000128import android.util.FeatureFlagUtils;
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -0700129import android.util.Log;
Felipe Leme281389a2016-10-10 17:12:20 -0700130import android.util.Pair;
San Mehata5078592010-03-25 09:36:54 -0700131import android.util.Slog;
Jeff Sharkeye8a4b662015-06-27 15:43:45 -0700132import android.util.TimeUtils;
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700133import android.util.Xml;
Jeff Sharkey48877892015-03-18 11:27:19 -0700134
Jeff Sharkey8b2c3a142012-11-12 11:45:05 -0800135import com.android.internal.annotations.GuardedBy;
Sudheer Shankaff971bc2018-12-13 17:39:59 -0800136import com.android.internal.app.IAppOpsCallback;
Sudheer Shanka3a0df3b2018-12-12 12:43:43 -0800137import com.android.internal.app.IAppOpsService;
Daichi Hirono9fb00182016-11-08 14:12:17 +0900138import com.android.internal.os.AppFuseMount;
Jeff Sharkey1019de92017-09-06 13:47:03 -0600139import com.android.internal.os.BackgroundThread;
Daichi Hirono812c95d2017-02-08 16:20:20 +0900140import com.android.internal.os.FuseUnavailableMountException;
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700141import com.android.internal.os.SomeArgs;
Jeff Sharkey9527b222015-06-24 15:24:48 -0700142import com.android.internal.os.Zygote;
Jeff Sharkey48877892015-03-18 11:27:19 -0700143import com.android.internal.util.ArrayUtils;
Jeff Sharkey11697f52018-12-13 10:14:42 -0700144import com.android.internal.util.CollectionUtils;
Jeff Sharkeyfe9a53b2017-03-31 14:08:23 -0600145import com.android.internal.util.DumpUtils;
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700146import com.android.internal.util.FastXmlSerializer;
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -0800147import com.android.internal.util.HexDump;
Jeff Sharkey5aca2b82013-10-16 16:21:54 -0700148import com.android.internal.util.IndentingPrintWriter;
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700149import com.android.internal.util.Preconditions;
Jeff Sharkeyb9fe5372015-12-03 15:23:08 -0700150import com.android.internal.widget.LockPatternUtils;
Ricky Wai4482ab52019-12-10 19:08:18 +0000151import com.android.server.pm.Installer;
Daichi Hirono9fb00182016-11-08 14:12:17 +0900152import com.android.server.storage.AppFuseBridge;
Zim42f1e9f2019-08-15 17:35:00 +0100153import com.android.server.storage.StorageSessionController;
Zim17be6f92019-09-25 14:37:55 +0100154import com.android.server.storage.StorageSessionController.ExternalStorageServiceException;
Wale Ogunwale9e4f3e02018-05-17 09:35:39 -0700155import com.android.server.wm.ActivityTaskManagerInternal;
156import com.android.server.wm.ActivityTaskManagerInternal.ScreenObserver;
Jeff Sharkey5217cac2015-12-20 15:34:01 -0700157
Jeff Sharkey5790af02018-08-13 17:42:54 -0600158import libcore.io.IoUtils;
159import libcore.util.EmptyArray;
160
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700161import org.xmlpull.v1.XmlPullParser;
162import org.xmlpull.v1.XmlPullParserException;
163import org.xmlpull.v1.XmlSerializer;
164
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700165import java.io.File;
Kenny Root38cf8862010-09-26 14:18:51 -0700166import java.io.FileDescriptor;
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700167import java.io.FileInputStream;
168import java.io.FileNotFoundException;
Christopher Tate7265abe2014-11-21 13:54:45 -0800169import java.io.FileOutputStream;
Kenny Root05105f72010-09-22 17:29:43 -0700170import java.io.IOException;
Kenny Root38cf8862010-09-26 14:18:51 -0700171import java.io.PrintWriter;
Kenny Root3b1abba2010-10-13 15:00:07 -0700172import java.math.BigInteger;
Paul Lawrence8e397362014-01-27 15:22:30 -0800173import java.nio.charset.StandardCharsets;
Jeff Sharkey0095a822018-02-15 13:06:53 -0700174import java.security.GeneralSecurityException;
Kenny Root3b1abba2010-10-13 15:00:07 -0700175import java.security.spec.KeySpec;
San Mehat22dd86e2010-01-12 12:21:18 -0800176import java.util.ArrayList;
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -0800177import java.util.Arrays;
Kenny Roota02b8b02010-08-05 16:14:17 -0700178import java.util.HashMap;
Kenny Root38cf8862010-09-26 14:18:51 -0700179import java.util.Iterator;
Kenny Roota02b8b02010-08-05 16:14:17 -0700180import java.util.LinkedList;
181import java.util.List;
Elliott Hughesf839b4f2014-09-26 12:30:47 -0700182import java.util.Locale;
Kenny Roota02b8b02010-08-05 16:14:17 -0700183import java.util.Map;
Kenny Root38cf8862010-09-26 14:18:51 -0700184import java.util.Map.Entry;
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700185import java.util.Objects;
Svet Ganov6ee871e2015-07-10 14:29:33 -0700186import java.util.concurrent.CopyOnWriteArrayList;
Kenny Root51a573c2012-05-17 13:30:28 -0700187import java.util.concurrent.CountDownLatch;
188import java.util.concurrent.TimeUnit;
Jeff Sharkeyedcdaf62015-07-09 09:45:36 -0700189import java.util.concurrent.TimeoutException;
Martijn Coenen9fd2b642019-12-24 13:04:36 +0100190import java.util.regex.Matcher;
191import java.util.regex.Pattern;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800192
Kenny Root3b1abba2010-10-13 15:00:07 -0700193import javax.crypto.SecretKey;
194import javax.crypto.SecretKeyFactory;
195import javax.crypto.spec.PBEKeySpec;
196
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800197/**
Jeff Sharkey48877892015-03-18 11:27:19 -0700198 * Service responsible for various storage media. Connects to {@code vold} to
199 * watch for and manage dynamically added storage, such as SD cards and USB mass
200 * storage. Also decides how storage should be presented to users on the device.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800201 */
Jeff Sharkey9765e442017-12-14 22:15:14 -0700202class StorageManagerService extends IStorageManager.Stub
203 implements Watchdog.Monitor, ScreenObserver {
Jason parks5af0b912010-11-29 09:05:25 -0600204
Christopher Tated417d622013-08-19 16:14:25 -0700205 // Static direct instance pointer for the tightly-coupled idle service to use
Sudheer Shanka2250d562016-11-07 15:41:02 -0800206 static StorageManagerService sSelf = null;
Christopher Tated417d622013-08-19 16:14:25 -0700207
Daniel Colascione766b6322018-01-08 19:10:36 -0800208 /* Read during boot to decide whether to enable zram when available */
209 private static final String ZRAM_ENABLED_PROPERTY =
Sudheer Shanka0a541a52018-07-31 13:21:11 -0700210 "persist.sys.zram_enabled";
211
Jeff Sharkey10ec9d82018-11-28 14:52:45 -0700212 private static final boolean ENABLE_ISOLATED_STORAGE = StorageManager.hasIsolatedStorage();
Sudheer Shanka0a541a52018-07-31 13:21:11 -0700213
Matt Pape19ea8a62019-03-18 10:38:25 -0700214 /**
215 * If {@code 1}, enables the isolated storage feature. If {@code -1},
216 * disables the isolated storage feature. If {@code 0}, uses the default
217 * value from the build system.
218 */
219 private static final String ISOLATED_STORAGE_ENABLED = "isolated_storage_enabled";
220
shafikb2992b62019-10-01 15:31:02 +0100221 /**
222 * If {@code 1}, enables FuseDaemon to intercept file system ops. If {@code -1},
223 * disables FuseDaemon. If {@code 0}, uses the default value from the build system.
224 */
225 private static final String FUSE_ENABLED = "fuse_enabled";
226
Jeff Sharkey56e62932015-03-21 20:41:00 -0700227 public static class Lifecycle extends SystemService {
Sudheer Shanka2250d562016-11-07 15:41:02 -0800228 private StorageManagerService mStorageManagerService;
Jeff Sharkey56e62932015-03-21 20:41:00 -0700229
230 public Lifecycle(Context context) {
231 super(context);
232 }
233
234 @Override
235 public void onStart() {
Sudheer Shanka2250d562016-11-07 15:41:02 -0800236 mStorageManagerService = new StorageManagerService(getContext());
237 publishBinderService("mount", mStorageManagerService);
238 mStorageManagerService.start();
Jeff Sharkey56e62932015-03-21 20:41:00 -0700239 }
240
241 @Override
242 public void onBootPhase(int phase) {
Jeff Sharkey11697f52018-12-13 10:14:42 -0700243 if (phase == SystemService.PHASE_SYSTEM_SERVICES_READY) {
244 mStorageManagerService.servicesReady();
245 } else if (phase == SystemService.PHASE_ACTIVITY_MANAGER_READY) {
Sudheer Shanka2250d562016-11-07 15:41:02 -0800246 mStorageManagerService.systemReady();
Yasuhiro Matsuda87a38b52015-07-24 22:10:16 +0900247 } else if (phase == SystemService.PHASE_BOOT_COMPLETED) {
Sudheer Shanka2250d562016-11-07 15:41:02 -0800248 mStorageManagerService.bootCompleted();
Jeff Sharkey56e62932015-03-21 20:41:00 -0700249 }
250 }
Jeff Sharkey48877892015-03-18 11:27:19 -0700251
252 @Override
Jeff Sharkeyab15c392016-05-05 11:45:01 -0600253 public void onSwitchUser(int userHandle) {
Sudheer Shanka2250d562016-11-07 15:41:02 -0800254 mStorageManagerService.mCurrentUserId = userHandle;
Jeff Sharkeyab15c392016-05-05 11:45:01 -0600255 }
256
257 @Override
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700258 public void onUnlockUser(int userHandle) {
Sudheer Shanka2250d562016-11-07 15:41:02 -0800259 mStorageManagerService.onUnlockUser(userHandle);
Jeff Sharkey48877892015-03-18 11:27:19 -0700260 }
261
262 @Override
263 public void onCleanupUser(int userHandle) {
Sudheer Shanka2250d562016-11-07 15:41:02 -0800264 mStorageManagerService.onCleanupUser(userHandle);
Jeff Sharkey48877892015-03-18 11:27:19 -0700265 }
Martijn Coenen7084c6a2019-11-22 16:32:09 +0100266
267 @Override
268 public void onStopUser(int userHandle) {
269 mStorageManagerService.onStopUser(userHandle);
270 }
Jeff Sharkey56e62932015-03-21 20:41:00 -0700271 }
272
Dianne Hackborn40e9f292012-11-27 19:12:23 -0800273 private static final boolean DEBUG_EVENTS = false;
Kenny Rootb7db2722011-01-25 16:39:35 -0800274 private static final boolean DEBUG_OBB = false;
Kenny Root02c87302010-07-01 08:10:18 -0700275
Jeff Sharkeyc3c72872018-06-06 15:35:53 -0600276 /**
277 * We now talk to vold over Binder, and it has its own internal lock to
278 * serialize certain calls. All long-running operations have been migrated
279 * to be async with callbacks, so we want watchdog to fire if vold wedges.
280 */
281 private static final boolean WATCHDOG_ENABLE = true;
Kenny Root07714d42011-08-17 17:49:28 -0700282
Jeff Sharkey00455bf2016-11-04 14:45:24 -0600283 /**
284 * Our goal is for all Android devices to be usable as development devices,
285 * which includes the new Direct Boot mode added in N. For devices that
286 * don't have native FBE support, we offer an emulation mode for developer
287 * testing purposes, but if it's prohibitively difficult to support this
288 * mode, it can be disabled for specific products using this flag.
289 */
290 private static final boolean EMULATE_FBE_SUPPORTED = true;
291
Sudheer Shanka2250d562016-11-07 15:41:02 -0800292 private static final String TAG = "StorageManagerService";
Jeff Sharkey6fd69942019-03-26 17:53:35 -0600293 private static final boolean LOCAL_LOGV = Log.isLoggable(TAG, Log.VERBOSE);
Jeff Sharkeye8a4b662015-06-27 15:43:45 -0700294
Jeff Sharkey9756d752015-05-14 21:07:42 -0700295 private static final String TAG_STORAGE_BENCHMARK = "storage_benchmark";
Jeff Sharkeye8a4b662015-06-27 15:43:45 -0700296 private static final String TAG_STORAGE_TRIM = "storage_trim";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800297
Jeff Sharkey275e3e42015-04-24 16:10:32 -0700298 /** Magic value sent by MoveTask.cpp */
299 private static final int MOVE_STATUS_COPY_FINISHED = 82;
300
Jeff Sharkey620b32b2015-04-23 19:36:02 -0700301 private static final int VERSION_INIT = 1;
302 private static final int VERSION_ADD_PRIMARY = 2;
Jeff Sharkeyfced5342015-05-10 14:53:34 -0700303 private static final int VERSION_FIX_PRIMARY = 3;
Jeff Sharkey620b32b2015-04-23 19:36:02 -0700304
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700305 private static final String TAG_VOLUMES = "volumes";
Jeff Sharkey620b32b2015-04-23 19:36:02 -0700306 private static final String ATTR_VERSION = "version";
307 private static final String ATTR_PRIMARY_STORAGE_UUID = "primaryStorageUuid";
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700308 private static final String TAG_VOLUME = "volume";
309 private static final String ATTR_TYPE = "type";
310 private static final String ATTR_FS_UUID = "fsUuid";
Jeff Sharkey5cc0df22015-06-17 19:44:05 -0700311 private static final String ATTR_PART_GUID = "partGuid";
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700312 private static final String ATTR_NICKNAME = "nickname";
313 private static final String ATTR_USER_FLAGS = "userFlags";
Jeff Sharkeye8a4b662015-06-27 15:43:45 -0700314 private static final String ATTR_CREATED_MILLIS = "createdMillis";
Jeff Sharkey3811f352019-05-14 11:54:36 -0600315 private static final String ATTR_LAST_SEEN_MILLIS = "lastSeenMillis";
Jeff Sharkeye8a4b662015-06-27 15:43:45 -0700316 private static final String ATTR_LAST_TRIM_MILLIS = "lastTrimMillis";
317 private static final String ATTR_LAST_BENCH_MILLIS = "lastBenchMillis";
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700318
Philip P. Moltmannc94ba822019-03-04 16:48:22 -0800319 private static final String[] ALL_STORAGE_PERMISSIONS = {
320 Manifest.permission.READ_EXTERNAL_STORAGE,
Philip P. Moltmann129a0b02019-03-27 12:24:45 -0700321 Manifest.permission.WRITE_EXTERNAL_STORAGE
Philip P. Moltmannc94ba822019-03-04 16:48:22 -0800322 };
323
Jeff Sharkeyb36586a2015-04-27 08:42:28 -0700324 private final AtomicFile mSettingsFile;
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700325
Jeff Sharkey48877892015-03-18 11:27:19 -0700326 /**
327 * <em>Never</em> hold the lock while performing downcalls into vold, since
328 * unsolicited events can suddenly appear to update data structures.
329 */
Jeff Sharkey5f3e9342017-03-13 14:53:11 -0600330 private final Object mLock = LockGuard.installNewLock(LockGuard.INDEX_STORAGE);
Jeff Sharkey48877892015-03-18 11:27:19 -0700331
Sudheer Shanka0a541a52018-07-31 13:21:11 -0700332 /**
333 * Similar to {@link #mLock}, never hold this lock while performing downcalls into vold.
334 * Also, never hold this while calling into PackageManagerService since it is used in callbacks
335 * from PackageManagerService.
336 *
337 * If both {@link #mLock} and this lock need to be held, {@link #mLock} should be acquired
338 * before this.
339 *
340 * Use -PL suffix for methods that need to called with this lock held.
341 */
342 private final Object mPackagesLock = new Object();
343
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700344 /** Set of users that we know are unlocked. */
Jeff Sharkey48877892015-03-18 11:27:19 -0700345 @GuardedBy("mLock")
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700346 private int[] mLocalUnlockedUsers = EmptyArray.INT;
347 /** Set of users that system knows are unlocked. */
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -0800348 @GuardedBy("mLock")
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700349 private int[] mSystemUnlockedUsers = EmptyArray.INT;
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700350
351 /** Map from disk ID to disk */
Jeff Sharkey48877892015-03-18 11:27:19 -0700352 @GuardedBy("mLock")
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -0700353 private ArrayMap<String, DiskInfo> mDisks = new ArrayMap<>();
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700354 /** Map from volume ID to disk */
Jeff Sharkey48877892015-03-18 11:27:19 -0700355 @GuardedBy("mLock")
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700356 private final ArrayMap<String, VolumeInfo> mVolumes = new ArrayMap<>();
Jeff Sharkey48877892015-03-18 11:27:19 -0700357
Jeff Sharkeyb36586a2015-04-27 08:42:28 -0700358 /** Map from UUID to record */
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700359 @GuardedBy("mLock")
Jeff Sharkeyb36586a2015-04-27 08:42:28 -0700360 private ArrayMap<String, VolumeRecord> mRecords = new ArrayMap<>();
Jeff Sharkey620b32b2015-04-23 19:36:02 -0700361 @GuardedBy("mLock")
362 private String mPrimaryStorageUuid;
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700363
Jeff Sharkeyeba260d2015-04-19 14:35:16 -0700364 /** Map from disk ID to latches */
365 @GuardedBy("mLock")
366 private ArrayMap<String, CountDownLatch> mDiskScanLatches = new ArrayMap<>();
367
Jeff Sharkey275e3e42015-04-24 16:10:32 -0700368 @GuardedBy("mLock")
369 private IPackageMoveObserver mMoveCallback;
370 @GuardedBy("mLock")
371 private String mMoveTargetUuid;
372
Martijn Coenen44db1ac2019-12-03 16:06:19 +0100373 private volatile int mMediaStoreAuthorityAppId = -1;
Zim74a9bba2019-09-03 20:49:13 +0100374
Martijn Coenen496ac002020-01-08 14:55:53 +0100375 private volatile int mDownloadsAuthorityAppId = -1;
376
Jeff Sharkeyab15c392016-05-05 11:45:01 -0600377 private volatile int mCurrentUserId = UserHandle.USER_SYSTEM;
378
Ricky Wai4482ab52019-12-10 19:08:18 +0000379 private final Installer mInstaller;
380
Daichi Hirono9fb00182016-11-08 14:12:17 +0900381 /** Holding lock for AppFuse business */
382 private final Object mAppFuseLock = new Object();
383
384 @GuardedBy("mAppFuseLock")
385 private int mNextAppFuseName = 0;
386
387 @GuardedBy("mAppFuseLock")
Daichi Hironoe56740d2017-02-02 13:56:45 +0900388 private AppFuseBridge mAppFuseBridge = null;
Daichi Hirono9fb00182016-11-08 14:12:17 +0900389
Martijn Coenen9fd2b642019-12-24 13:04:36 +0100390 /** Matches known application dir paths. The first group contains the generic part of the path,
391 * the second group contains the user id (or null if it's a public volume without users), the
392 * third group contains the package name, and the fourth group the remainder of the path.
393 */
394 public static final Pattern KNOWN_APP_DIR_PATHS = Pattern.compile(
395 "(?i)(^/storage/[^/]+/(?:([0-9]+)/)?Android/(?:data|media|obb|sandbox)/)([^/]+)(/.*)?");
396
397
Jeff Sharkeyef10ee02015-07-05 14:17:27 -0700398 private VolumeInfo findVolumeByIdOrThrow(String id) {
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700399 synchronized (mLock) {
400 final VolumeInfo vol = mVolumes.get(id);
401 if (vol != null) {
402 return vol;
403 }
404 }
405 throw new IllegalArgumentException("No volume found for ID " + id);
406 }
407
Jeff Sharkeyef10ee02015-07-05 14:17:27 -0700408 private String findVolumeIdForPathOrThrow(String path) {
Jeff Sharkey48877892015-03-18 11:27:19 -0700409 synchronized (mLock) {
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -0700410 for (int i = 0; i < mVolumes.size(); i++) {
411 final VolumeInfo vol = mVolumes.valueAt(i);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700412 if (vol.path != null && path.startsWith(vol.path)) {
413 return vol.id;
Jeff Sharkey48877892015-03-18 11:27:19 -0700414 }
415 }
416 }
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700417 throw new IllegalArgumentException("No volume found for path " + path);
Jeff Sharkey48877892015-03-18 11:27:19 -0700418 }
419
Jeff Sharkeye8a4b662015-06-27 15:43:45 -0700420 private VolumeRecord findRecordForPath(String path) {
421 synchronized (mLock) {
422 for (int i = 0; i < mVolumes.size(); i++) {
423 final VolumeInfo vol = mVolumes.valueAt(i);
424 if (vol.path != null && path.startsWith(vol.path)) {
425 return mRecords.get(vol.fsUuid);
426 }
427 }
428 }
429 return null;
430 }
431
432 private String scrubPath(String path) {
433 if (path.startsWith(Environment.getDataDirectory().getAbsolutePath())) {
434 return "internal";
435 }
436 final VolumeRecord rec = findRecordForPath(path);
437 if (rec == null || rec.createdMillis == 0) {
438 return "unknown";
439 } else {
440 return "ext:" + (int) ((System.currentTimeMillis() - rec.createdMillis)
441 / DateUtils.WEEK_IN_MILLIS) + "w";
442 }
443 }
444
Jeff Sharkeyef10ee02015-07-05 14:17:27 -0700445 private @Nullable VolumeInfo findStorageForUuid(String volumeUuid) {
Jeff Sharkey275e3e42015-04-24 16:10:32 -0700446 final StorageManager storage = mContext.getSystemService(StorageManager.class);
447 if (Objects.equals(StorageManager.UUID_PRIVATE_INTERNAL, volumeUuid)) {
Zim17be6f92019-09-25 14:37:55 +0100448 return storage.findVolumeById(VolumeInfo.ID_EMULATED_INTERNAL + ";" + 0);
Jeff Sharkey275e3e42015-04-24 16:10:32 -0700449 } else if (Objects.equals(StorageManager.UUID_PRIMARY_PHYSICAL, volumeUuid)) {
450 return storage.getPrimaryPhysicalVolume();
451 } else {
452 return storage.findEmulatedForPrivate(storage.findVolumeByUuid(volumeUuid));
453 }
454 }
455
Jeff Sharkeye8a4b662015-06-27 15:43:45 -0700456 private boolean shouldBenchmark() {
457 final long benchInterval = Settings.Global.getLong(mContext.getContentResolver(),
458 Settings.Global.STORAGE_BENCHMARK_INTERVAL, DateUtils.WEEK_IN_MILLIS);
Jeff Sharkeye83d8a92015-09-09 14:53:38 -0700459 if (benchInterval == -1) {
460 return false;
461 } else if (benchInterval == 0) {
462 return true;
463 }
464
Jeff Sharkeye8a4b662015-06-27 15:43:45 -0700465 synchronized (mLock) {
466 for (int i = 0; i < mVolumes.size(); i++) {
467 final VolumeInfo vol = mVolumes.valueAt(i);
468 final VolumeRecord rec = mRecords.get(vol.fsUuid);
Jeff Sharkeye83d8a92015-09-09 14:53:38 -0700469 if (vol.isMountedWritable() && rec != null) {
Jeff Sharkeye8a4b662015-06-27 15:43:45 -0700470 final long benchAge = System.currentTimeMillis() - rec.lastBenchMillis;
471 if (benchAge >= benchInterval) {
472 return true;
473 }
474 }
475 }
476 return false;
477 }
478 }
479
Jeff Sharkeyeba260d2015-04-19 14:35:16 -0700480 private CountDownLatch findOrCreateDiskScanLatch(String diskId) {
481 synchronized (mLock) {
482 CountDownLatch latch = mDiskScanLatches.get(diskId);
483 if (latch == null) {
484 latch = new CountDownLatch(1);
485 mDiskScanLatches.put(diskId, latch);
486 }
487 return latch;
488 }
489 }
490
Paul Lawrence8e397362014-01-27 15:22:30 -0800491 /** List of crypto types.
492 * These must match CRYPT_TYPE_XXX in cryptfs.h AND their
493 * corresponding commands in CommandListener.cpp */
494 public static final String[] CRYPTO_TYPES
495 = { "password", "default", "pattern", "pin" };
496
Brian Carlstrom7395a8a2014-04-28 22:11:01 -0700497 private final Context mContext;
Jeff Sharkey5d0c55c2019-01-24 14:32:31 -0700498 private final ContentResolver mResolver;
Jeff Sharkeycd575992016-03-29 14:12:49 -0600499
Jeff Sharkey1019de92017-09-06 13:47:03 -0600500 private volatile IVold mVold;
Jin Qian12690d52017-10-13 18:17:04 -0700501 private volatile IStoraged mStoraged;
Jeff Sharkey1019de92017-09-06 13:47:03 -0600502
Yasuhiro Matsuda87a38b52015-07-24 22:10:16 +0900503 private volatile boolean mBootCompleted = false;
Jeff Sharkey48877892015-03-18 11:27:19 -0700504 private volatile boolean mDaemonConnected = false;
Jeff Sharkey9765e442017-12-14 22:15:14 -0700505 private volatile boolean mSecureKeyguardShowing = true;
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700506
Sudheer Shanka0a541a52018-07-31 13:21:11 -0700507 private PackageManagerInternal mPmInternal;
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700508
Sudheer Shanka3a0df3b2018-12-12 12:43:43 -0800509 private IPackageManager mIPackageManager;
510 private IAppOpsService mIAppOpsService;
511
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700512 private final Callbacks mCallbacks;
Jeff Sharkeyb9fe5372015-12-03 15:23:08 -0700513 private final LockPatternUtils mLockPatternUtils;
Jeff Sharkey48877892015-03-18 11:27:19 -0700514
San Mehat6cdd9c02010-02-09 14:45:20 -0800515 /**
Kenny Root3b1abba2010-10-13 15:00:07 -0700516 * The size of the crypto algorithm key in bits for OBB files. Currently
517 * Twofish is used which takes 128-bit keys.
518 */
519 private static final int CRYPTO_ALGORITHM_KEY_SIZE = 128;
520
521 /**
522 * The number of times to run SHA1 in the PBKDF2 function for OBB files.
523 * 1024 is reasonably secure and not too slow.
524 */
525 private static final int PBKDF2_HASH_ROUNDS = 1024;
526
527 /**
Kenny Roota02b8b02010-08-05 16:14:17 -0700528 * Mounted OBB tracking information. Used to track the current state of all
529 * OBBs.
Kenny Root02c87302010-07-01 08:10:18 -0700530 */
Kenny Root735de3b2010-09-30 14:11:39 -0700531 final private Map<IBinder, List<ObbState>> mObbMounts = new HashMap<IBinder, List<ObbState>>();
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700532
533 /** Map from raw paths to {@link ObbState}. */
Kenny Roota02b8b02010-08-05 16:14:17 -0700534 final private Map<String, ObbState> mObbPathToStateMap = new HashMap<String, ObbState>();
535
Svet Ganov6ee871e2015-07-10 14:29:33 -0700536 // Not guarded by a lock.
Sudheer Shanka2250d562016-11-07 15:41:02 -0800537 private final StorageManagerInternalImpl mStorageManagerInternal
538 = new StorageManagerInternalImpl();
Svet Ganov6ee871e2015-07-10 14:29:33 -0700539
Zim42f1e9f2019-08-15 17:35:00 +0100540 // Not guarded by a lock.
541 private final StorageSessionController mStorageSessionController;
542
Zim17be6f92019-09-25 14:37:55 +0100543 private final boolean mIsFuseEnabled;
544
Kenny Roota02b8b02010-08-05 16:14:17 -0700545 class ObbState implements IBinder.DeathRecipient {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700546 public ObbState(String rawPath, String canonicalPath, int callingUid,
Jeff Sharkey41cd6812017-09-11 10:32:17 -0600547 IObbActionListener token, int nonce, String volId) {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700548 this.rawPath = rawPath;
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700549 this.canonicalPath = canonicalPath;
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700550 this.ownerGid = UserHandle.getSharedAppGid(callingUid);
Kenny Rootaf9d6672010-10-08 09:21:39 -0700551 this.token = token;
552 this.nonce = nonce;
Jeff Sharkey41cd6812017-09-11 10:32:17 -0600553 this.volId = volId;
Kenny Roota02b8b02010-08-05 16:14:17 -0700554 }
555
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700556 final String rawPath;
557 final String canonicalPath;
Kenny Roota02b8b02010-08-05 16:14:17 -0700558
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700559 final int ownerGid;
Kenny Roota02b8b02010-08-05 16:14:17 -0700560
Kenny Rootaf9d6672010-10-08 09:21:39 -0700561 // Token of remote Binder caller
562 final IObbActionListener token;
563
564 // Identifier to pass back to the token
565 final int nonce;
Kenny Roota02b8b02010-08-05 16:14:17 -0700566
Jeff Sharkey41cd6812017-09-11 10:32:17 -0600567 String volId;
568
Kenny Root735de3b2010-09-30 14:11:39 -0700569 public IBinder getBinder() {
570 return token.asBinder();
571 }
572
Kenny Roota02b8b02010-08-05 16:14:17 -0700573 @Override
574 public void binderDied() {
575 ObbAction action = new UnmountObbAction(this, true);
576 mObbActionHandler.sendMessage(mObbActionHandler.obtainMessage(OBB_RUN_ACTION, action));
Kenny Root735de3b2010-09-30 14:11:39 -0700577 }
Kenny Roota02b8b02010-08-05 16:14:17 -0700578
Kenny Root5919ac62010-10-05 09:49:40 -0700579 public void link() throws RemoteException {
580 getBinder().linkToDeath(this, 0);
581 }
582
583 public void unlink() {
Kenny Root735de3b2010-09-30 14:11:39 -0700584 getBinder().unlinkToDeath(this, 0);
Kenny Roota02b8b02010-08-05 16:14:17 -0700585 }
Kenny Root38cf8862010-09-26 14:18:51 -0700586
587 @Override
588 public String toString() {
589 StringBuilder sb = new StringBuilder("ObbState{");
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700590 sb.append("rawPath=").append(rawPath);
591 sb.append(",canonicalPath=").append(canonicalPath);
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700592 sb.append(",ownerGid=").append(ownerGid);
593 sb.append(",token=").append(token);
594 sb.append(",binder=").append(getBinder());
Jeff Sharkey41cd6812017-09-11 10:32:17 -0600595 sb.append(",volId=").append(volId);
Kenny Root38cf8862010-09-26 14:18:51 -0700596 sb.append('}');
597 return sb.toString();
598 }
Kenny Roota02b8b02010-08-05 16:14:17 -0700599 }
600
601 // OBB Action Handler
602 final private ObbActionHandler mObbActionHandler;
603
604 // OBB action handler messages
605 private static final int OBB_RUN_ACTION = 1;
Sudheer Shanka25469aa2018-08-27 15:50:23 -0700606 private static final int OBB_FLUSH_MOUNT_STATE = 2;
Kenny Root02c87302010-07-01 08:10:18 -0700607
Christopher Tate7265abe2014-11-21 13:54:45 -0800608 // Last fstrim operation tracking
609 private static final String LAST_FSTRIM_FILE = "last-fstrim";
610 private final File mLastMaintenanceFile;
611 private long mLastMaintenance;
612
Kenny Root02c87302010-07-01 08:10:18 -0700613 // Handler messages
Jeff Sharkey48877892015-03-18 11:27:19 -0700614 private static final int H_SYSTEM_READY = 1;
615 private static final int H_DAEMON_CONNECTED = 2;
616 private static final int H_SHUTDOWN = 3;
617 private static final int H_FSTRIM = 4;
618 private static final int H_VOLUME_MOUNT = 5;
619 private static final int H_VOLUME_BROADCAST = 6;
Jeff Sharkeyabc3e852015-08-03 14:41:13 -0700620 private static final int H_INTERNAL_BROADCAST = 7;
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700621 private static final int H_VOLUME_UNMOUNT = 8;
Jeff Sharkey5a9bb742015-11-03 10:15:57 -0800622 private static final int H_PARTITION_FORGET = 9;
623 private static final int H_RESET = 10;
Jin Qiana85b9912017-10-17 15:48:18 -0700624 private static final int H_RUN_IDLE_MAINT = 11;
625 private static final int H_ABORT_IDLE_MAINT = 12;
Daniel Rosenberg137aed12019-03-15 18:41:11 -0700626 private static final int H_BOOT_COMPLETED = 13;
Narayan Kamath157dd1d2019-06-12 13:06:30 +0100627 private static final int H_COMPLETE_UNLOCK_USER = 14;
Suchi Amalapurapu6ffce2e2010-03-08 14:48:40 -0800628
Sudheer Shanka2250d562016-11-07 15:41:02 -0800629 class StorageManagerServiceHandler extends Handler {
630 public StorageManagerServiceHandler(Looper looper) {
Jeff Sharkey48877892015-03-18 11:27:19 -0700631 super(looper);
Daniel Sandler5f27ef42010-03-16 15:42:02 -0400632 }
633
Jason parks5af0b912010-11-29 09:05:25 -0600634 @Override
Suchi Amalapurapuc42e29e2010-02-22 16:03:53 -0800635 public void handleMessage(Message msg) {
636 switch (msg.what) {
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700637 case H_SYSTEM_READY: {
Jeff Sharkey48877892015-03-18 11:27:19 -0700638 handleSystemReady();
639 break;
640 }
Daniel Rosenberg137aed12019-03-15 18:41:11 -0700641 case H_BOOT_COMPLETED: {
642 handleBootCompleted();
643 break;
644 }
Jeff Sharkey48877892015-03-18 11:27:19 -0700645 case H_DAEMON_CONNECTED: {
646 handleDaemonConnected();
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700647 break;
648 }
Christopher Tated417d622013-08-19 16:14:25 -0700649 case H_FSTRIM: {
Christopher Tated417d622013-08-19 16:14:25 -0700650 Slog.i(TAG, "Running fstrim idle maintenance");
Christopher Tate7265abe2014-11-21 13:54:45 -0800651
652 // Remember when we kicked it off
653 try {
654 mLastMaintenance = System.currentTimeMillis();
655 mLastMaintenanceFile.setLastModified(mLastMaintenance);
656 } catch (Exception e) {
657 Slog.e(TAG, "Unable to record last fstrim!");
658 }
659
Jeff Sharkeyb302c542017-09-15 12:57:59 -0600660 // TODO: Reintroduce shouldBenchmark() test
Jeff Sharkey7e19f532017-11-06 13:54:11 -0700661 fstrim(0, null);
Christopher Tate7265abe2014-11-21 13:54:45 -0800662
Christopher Tated417d622013-08-19 16:14:25 -0700663 // invoke the completion callback, if any
Jeff Sharkeye8a4b662015-06-27 15:43:45 -0700664 // TODO: fstrim is non-blocking, so remove this useless callback
Christopher Tated417d622013-08-19 16:14:25 -0700665 Runnable callback = (Runnable) msg.obj;
666 if (callback != null) {
667 callback.run();
668 }
669 break;
670 }
Jeff Sharkey48877892015-03-18 11:27:19 -0700671 case H_SHUTDOWN: {
Sudheer Shanka2250d562016-11-07 15:41:02 -0800672 final IStorageShutdownObserver obs = (IStorageShutdownObserver) msg.obj;
Jeff Sharkey48877892015-03-18 11:27:19 -0700673 boolean success = false;
674 try {
Jeff Sharkey54402792017-09-15 16:05:19 -0600675 mVold.shutdown();
676 success = true;
Jeff Sharkeyace874b2017-09-07 15:27:33 -0600677 } catch (Exception e) {
678 Slog.wtf(TAG, e);
Jeff Sharkey48877892015-03-18 11:27:19 -0700679 }
680 if (obs != null) {
681 try {
682 obs.onShutDownComplete(success ? 0 : -1);
Jeff Sharkeyace874b2017-09-07 15:27:33 -0600683 } catch (Exception ignored) {
Jeff Sharkey48877892015-03-18 11:27:19 -0700684 }
685 }
686 break;
687 }
688 case H_VOLUME_MOUNT: {
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -0700689 final VolumeInfo vol = (VolumeInfo) msg.obj;
Jeff Sharkey2e606d72015-07-27 14:19:54 -0700690 if (isMountDisallowed(vol)) {
691 Slog.i(TAG, "Ignoring mount " + vol.getId() + " due to policy");
692 break;
693 }
Zim42f1e9f2019-08-15 17:35:00 +0100694
Zim17be6f92019-09-25 14:37:55 +0100695 mount(vol);
Jeff Sharkey48877892015-03-18 11:27:19 -0700696 break;
697 }
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700698 case H_VOLUME_UNMOUNT: {
699 final VolumeInfo vol = (VolumeInfo) msg.obj;
Sudheer Shanka3f0645b2018-09-18 13:07:59 -0700700 unmount(vol);
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700701 break;
702 }
Jeff Sharkey48877892015-03-18 11:27:19 -0700703 case H_VOLUME_BROADCAST: {
704 final StorageVolume userVol = (StorageVolume) msg.obj;
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700705 final String envState = userVol.getState();
706 Slog.d(TAG, "Volume " + userVol.getId() + " broadcasting " + envState + " to "
Jeff Sharkey48877892015-03-18 11:27:19 -0700707 + userVol.getOwner());
708
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700709 final String action = VolumeInfo.getBroadcastForEnvironment(envState);
Jeff Sharkey48877892015-03-18 11:27:19 -0700710 if (action != null) {
711 final Intent intent = new Intent(action,
712 Uri.fromFile(userVol.getPathFile()));
713 intent.putExtra(StorageVolume.EXTRA_STORAGE_VOLUME, userVol);
Jeff Sharkey082f83b2017-03-26 14:34:47 -0600714 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT
715 | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
Jeff Sharkey48877892015-03-18 11:27:19 -0700716 mContext.sendBroadcastAsUser(intent, userVol.getOwner());
717 }
718 break;
719 }
Jeff Sharkeyabc3e852015-08-03 14:41:13 -0700720 case H_INTERNAL_BROADCAST: {
721 // Internal broadcasts aimed at system components, not for
722 // third-party apps.
723 final Intent intent = (Intent) msg.obj;
724 mContext.sendBroadcastAsUser(intent, UserHandle.ALL,
725 android.Manifest.permission.WRITE_MEDIA_STORAGE);
Jeff Sharkey5a9bb742015-11-03 10:15:57 -0800726 break;
727 }
728 case H_PARTITION_FORGET: {
Jeff Sharkeydb4b6192017-10-24 11:08:50 -0600729 final VolumeRecord rec = (VolumeRecord) msg.obj;
730 forgetPartition(rec.partGuid, rec.fsUuid);
Jeff Sharkey5a9bb742015-11-03 10:15:57 -0800731 break;
732 }
733 case H_RESET: {
Daniel Rosenberg137aed12019-03-15 18:41:11 -0700734 resetIfBootedAndConnected();
Jeff Sharkey5a9bb742015-11-03 10:15:57 -0800735 break;
Jeff Sharkeyabc3e852015-08-03 14:41:13 -0700736 }
Jin Qiana85b9912017-10-17 15:48:18 -0700737 case H_RUN_IDLE_MAINT: {
738 Slog.i(TAG, "Running idle maintenance");
739 runIdleMaint((Runnable)msg.obj);
740 break;
741 }
742 case H_ABORT_IDLE_MAINT: {
743 Slog.i(TAG, "Aborting idle maintenance");
744 abortIdleMaint((Runnable)msg.obj);
745 break;
746 }
Narayan Kamath157dd1d2019-06-12 13:06:30 +0100747 case H_COMPLETE_UNLOCK_USER: {
748 completeUnlockUser((int) msg.obj);
749 break;
750 }
Suchi Amalapurapuc42e29e2010-02-22 16:03:53 -0800751 }
752 }
Jeff Sharkey48877892015-03-18 11:27:19 -0700753 }
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700754
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700755 private final Handler mHandler;
Suchi Amalapurapuc42e29e2010-02-22 16:03:53 -0800756
Jeff Sharkeybcd262d2015-06-10 09:41:17 -0700757 private BroadcastReceiver mUserReceiver = new BroadcastReceiver() {
758 @Override
759 public void onReceive(Context context, Intent intent) {
760 final String action = intent.getAction();
761 final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700762 Preconditions.checkArgument(userId >= 0);
Jeff Sharkeybcd262d2015-06-10 09:41:17 -0700763
764 try {
765 if (Intent.ACTION_USER_ADDED.equals(action)) {
766 final UserManager um = mContext.getSystemService(UserManager.class);
767 final int userSerialNumber = um.getUserSerialNumber(userId);
Jeff Sharkey54402792017-09-15 16:05:19 -0600768 mVold.onUserAdded(userId, userSerialNumber);
Jeff Sharkeybcd262d2015-06-10 09:41:17 -0700769 } else if (Intent.ACTION_USER_REMOVED.equals(action)) {
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700770 synchronized (mVolumes) {
771 final int size = mVolumes.size();
772 for (int i = 0; i < size; i++) {
773 final VolumeInfo vol = mVolumes.valueAt(i);
774 if (vol.mountUserId == userId) {
775 vol.mountUserId = UserHandle.USER_NULL;
776 mHandler.obtainMessage(H_VOLUME_UNMOUNT, vol).sendToTarget();
777 }
778 }
779 }
Jeff Sharkey54402792017-09-15 16:05:19 -0600780 mVold.onUserRemoved(userId);
Jeff Sharkeybcd262d2015-06-10 09:41:17 -0700781 }
Jeff Sharkeyace874b2017-09-07 15:27:33 -0600782 } catch (Exception e) {
783 Slog.wtf(TAG, e);
Jeff Sharkeybcd262d2015-06-10 09:41:17 -0700784 }
785 }
786 };
787
Jeff Sharkeyedcdaf62015-07-09 09:45:36 -0700788 private void waitForLatch(CountDownLatch latch, String condition, long timeoutMillis)
789 throws TimeoutException {
790 final long startMillis = SystemClock.elapsedRealtime();
Jeff Sharkeyeba260d2015-04-19 14:35:16 -0700791 while (true) {
Kenny Root51a573c2012-05-17 13:30:28 -0700792 try {
793 if (latch.await(5000, TimeUnit.MILLISECONDS)) {
San Mehat207e5382010-02-04 20:46:54 -0800794 return;
Kenny Root51a573c2012-05-17 13:30:28 -0700795 } else {
796 Slog.w(TAG, "Thread " + Thread.currentThread().getName()
Jeff Sharkey48877892015-03-18 11:27:19 -0700797 + " still waiting for " + condition + "...");
San Mehat207e5382010-02-04 20:46:54 -0800798 }
Kenny Root51a573c2012-05-17 13:30:28 -0700799 } catch (InterruptedException e) {
Jeff Sharkeyeba260d2015-04-19 14:35:16 -0700800 Slog.w(TAG, "Interrupt while waiting for " + condition);
San Mehat207e5382010-02-04 20:46:54 -0800801 }
Jeff Sharkeyedcdaf62015-07-09 09:45:36 -0700802 if (timeoutMillis > 0 && SystemClock.elapsedRealtime() > startMillis + timeoutMillis) {
803 throw new TimeoutException("Thread " + Thread.currentThread().getName()
804 + " gave up waiting for " + condition + " after " + timeoutMillis + "ms");
805 }
San Mehat207e5382010-02-04 20:46:54 -0800806 }
San Mehat1f6301e2010-01-07 22:40:27 -0800807 }
Kenny Root02c87302010-07-01 08:10:18 -0700808
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700809 private void handleSystemReady() {
Jeff Sharkey48877892015-03-18 11:27:19 -0700810 // Start scheduling nominally-daily fstrim operations
Christopher Tate115afda2014-06-06 19:06:26 -0700811 MountServiceIdler.scheduleIdlePass(mContext);
Daniel Colascione766b6322018-01-08 19:10:36 -0800812
813 // Toggle zram-enable system property in response to settings
814 mContext.getContentResolver().registerContentObserver(
815 Settings.Global.getUriFor(Settings.Global.ZRAM_ENABLED),
816 false /*notifyForDescendants*/,
817 new ContentObserver(null /* current thread */) {
818 @Override
819 public void onChange(boolean selfChange) {
820 refreshZramSettings();
821 }
822 });
823 refreshZramSettings();
Jeff Sharkeyb0c363b22018-12-15 11:53:03 -0700824
Srinivas Paladuguc8261752019-01-09 10:54:52 -0800825 // Schedule zram writeback unless zram is disabled by persist.sys.zram_enabled
826 String zramPropValue = SystemProperties.get(ZRAM_ENABLED_PROPERTY);
827 if (!zramPropValue.equals("0")
828 && mContext.getResources().getBoolean(
829 com.android.internal.R.bool.config_zramWriteback)) {
830 ZramWriteback.scheduleZramWriteback(mContext);
831 }
Jeff Sharkeyb0c363b22018-12-15 11:53:03 -0700832 // Toggle isolated-enable system property in response to settings
833 mContext.getContentResolver().registerContentObserver(
834 Settings.Global.getUriFor(Settings.Global.ISOLATED_STORAGE_REMOTE),
835 false /*notifyForDescendants*/,
836 new ContentObserver(null /* current thread */) {
837 @Override
838 public void onChange(boolean selfChange) {
839 refreshIsolatedStorageSettings();
840 }
841 });
Jeff Sharkey5d0c55c2019-01-24 14:32:31 -0700842 // For now, simply clone property when it changes
shafik91b34612019-09-23 15:41:44 +0100843 DeviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_STORAGE_NATIVE_BOOT,
Matt Pape15769e22019-04-19 12:31:24 -0700844 mContext.getMainExecutor(), (properties) -> {
Jeff Sharkey8b499a02019-01-28 13:31:50 -0700845 refreshIsolatedStorageSettings();
shafikb2992b62019-10-01 15:31:02 +0100846 refreshFuseSettings();
Jeff Sharkey5d0c55c2019-01-24 14:32:31 -0700847 });
Jeff Sharkeyb0c363b22018-12-15 11:53:03 -0700848 refreshIsolatedStorageSettings();
Daniel Colascione766b6322018-01-08 19:10:36 -0800849 }
850
851 /**
852 * Update the zram_enabled system property (which init reads to
853 * decide whether to enable zram) to reflect the zram_enabled
854 * preference (which we can change for experimentation purposes).
855 */
856 private void refreshZramSettings() {
857 String propertyValue = SystemProperties.get(ZRAM_ENABLED_PROPERTY);
858 if ("".equals(propertyValue)) {
859 return; // System doesn't have zram toggling support
860 }
861 String desiredPropertyValue =
862 Settings.Global.getInt(mContext.getContentResolver(),
863 Settings.Global.ZRAM_ENABLED,
864 1) != 0
865 ? "1" : "0";
866 if (!desiredPropertyValue.equals(propertyValue)) {
867 // Avoid redundant disk writes by setting only if we're
868 // changing the property value. There's no race: we're the
869 // sole writer.
870 SystemProperties.set(ZRAM_ENABLED_PROPERTY, desiredPropertyValue);
Srinivas Paladuguc8261752019-01-09 10:54:52 -0800871 // Schedule writeback only if zram is being enabled.
872 if (desiredPropertyValue.equals("1")
873 && mContext.getResources().getBoolean(
874 com.android.internal.R.bool.config_zramWriteback)) {
875 ZramWriteback.scheduleZramWriteback(mContext);
876 }
Daniel Colascione766b6322018-01-08 19:10:36 -0800877 }
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700878 }
879
Jeff Sharkeyb0c363b22018-12-15 11:53:03 -0700880 private void refreshIsolatedStorageSettings() {
Jeff Sharkey8b499a02019-01-28 13:31:50 -0700881 // Always copy value from newer DeviceConfig location
882 Settings.Global.putString(mResolver,
883 Settings.Global.ISOLATED_STORAGE_REMOTE,
shafik91b34612019-09-23 15:41:44 +0100884 DeviceConfig.getProperty(DeviceConfig.NAMESPACE_STORAGE_NATIVE_BOOT,
885 ISOLATED_STORAGE_ENABLED));
Jeff Sharkey8b499a02019-01-28 13:31:50 -0700886
Jeff Sharkeyb0c363b22018-12-15 11:53:03 -0700887 final int local = Settings.Global.getInt(mContext.getContentResolver(),
888 Settings.Global.ISOLATED_STORAGE_LOCAL, 0);
889 final int remote = Settings.Global.getInt(mContext.getContentResolver(),
890 Settings.Global.ISOLATED_STORAGE_REMOTE, 0);
891
892 // Walk down precedence chain; we prefer local settings first, then
893 // remote settings, before finally falling back to hard-coded default.
894 final boolean res;
895 if (local == -1) {
896 res = false;
897 } else if (local == 1) {
898 res = true;
899 } else if (remote == -1) {
900 res = false;
901 } else if (remote == 1) {
902 res = true;
903 } else {
Jeff Sharkey06376802019-02-11 12:20:02 -0700904 res = true;
Jeff Sharkeyb0c363b22018-12-15 11:53:03 -0700905 }
906
907 Slog.d(TAG, "Isolated storage local flag " + local + " and remote flag "
908 + remote + " resolved to " + res);
909 SystemProperties.set(StorageManager.PROP_ISOLATED_STORAGE, Boolean.toString(res));
910 }
911
Abhijeet Kaurb9847712019-11-19 16:35:47 +0000912 /**
913 * The most recent flag change takes precedence. Change fuse Settings flag if Device Config is
914 * changed. Settings flag change will in turn change fuse system property (persist.sys.fuse)
915 * whenever the user reboots.
916 */
shafikb2992b62019-10-01 15:31:02 +0100917 private void refreshFuseSettings() {
918 int isFuseEnabled = DeviceConfig.getInt(DeviceConfig.NAMESPACE_STORAGE_NATIVE_BOOT,
919 FUSE_ENABLED, 0);
920 if (isFuseEnabled == 1) {
Abhijeet Kaurb9847712019-11-19 16:35:47 +0000921 Slog.d(TAG, "Device Config flag for FUSE is enabled, turn Settings fuse flag on");
922 SystemProperties.set(FeatureFlagUtils.PERSIST_PREFIX
923 + FeatureFlagUtils.SETTINGS_FUSE_FLAG, "true");
shafikb2992b62019-10-01 15:31:02 +0100924 } else if (isFuseEnabled == -1) {
Abhijeet Kaurb9847712019-11-19 16:35:47 +0000925 Slog.d(TAG, "Device Config flag for FUSE is disabled, turn Settings fuse flag off");
926 SystemProperties.set(FeatureFlagUtils.PERSIST_PREFIX
927 + FeatureFlagUtils.SETTINGS_FUSE_FLAG, "false");
shafikb2992b62019-10-01 15:31:02 +0100928 }
929 // else, keep the build config.
Abhijeet Kaurb9847712019-11-19 16:35:47 +0000930 // This can be overridden by direct adjustment of persist.sys.fflag.override.settings_fuse
shafikb2992b62019-10-01 15:31:02 +0100931 }
932
Jeff Sharkey14cbe522015-07-08 14:06:37 -0700933 /**
934 * MediaProvider has a ton of code that makes assumptions about storage
935 * paths never changing, so we outright kill them to pick up new state.
936 */
937 @Deprecated
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700938 private void killMediaProvider(List<UserInfo> users) {
939 if (users == null) return;
940
Jeff Sharkeyb3cf9532015-07-17 15:12:39 -0700941 final long token = Binder.clearCallingIdentity();
942 try {
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700943 for (UserInfo user : users) {
944 // System user does not have media provider, so skip.
945 if (user.isSystemOnly()) continue;
946
Jeff Sharkey5790af02018-08-13 17:42:54 -0600947 final ProviderInfo provider = mPmInternal.resolveContentProvider(
948 MediaStore.AUTHORITY, PackageManager.MATCH_DIRECT_BOOT_AWARE
Jeff Sharkey8a372a02016-03-16 16:25:45 -0600949 | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
950 user.id);
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700951 if (provider != null) {
Sudheer Shankadc589ac2016-11-10 15:30:17 -0800952 final IActivityManager am = ActivityManager.getService();
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700953 try {
Jeff Sharkey85f449e2016-06-23 09:26:00 -0600954 am.killApplication(provider.applicationInfo.packageName,
955 UserHandle.getAppId(provider.applicationInfo.uid),
956 UserHandle.USER_ALL, "vold reset");
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700957 // We only need to run this once. It will kill all users' media processes.
958 break;
959 } catch (RemoteException e) {
960 }
Jeff Sharkeyb3cf9532015-07-17 15:12:39 -0700961 }
Jeff Sharkey14cbe522015-07-08 14:06:37 -0700962 }
Jeff Sharkeyb3cf9532015-07-17 15:12:39 -0700963 } finally {
964 Binder.restoreCallingIdentity(token);
Jeff Sharkey14cbe522015-07-08 14:06:37 -0700965 }
966 }
967
Andreas Gampea36dc622018-02-05 17:19:22 -0800968 @GuardedBy("mLock")
Jeff Sharkey5a9bb742015-11-03 10:15:57 -0800969 private void addInternalVolumeLocked() {
Amith Yamasania7892482015-08-07 11:09:05 -0700970 // Create a stub volume that represents internal storage
971 final VolumeInfo internal = new VolumeInfo(VolumeInfo.ID_PRIVATE_INTERNAL,
972 VolumeInfo.TYPE_PRIVATE, null, null);
973 internal.state = VolumeInfo.STATE_MOUNTED;
974 internal.path = Environment.getDataDirectory().getAbsolutePath();
975 mVolumes.put(internal.id, internal);
976 }
977
Daniel Rosenberg137aed12019-03-15 18:41:11 -0700978 private void initIfBootedAndConnected() {
979 Slog.d(TAG, "Thinking about init, mBootCompleted=" + mBootCompleted
Jeff Sharkey8924e872015-11-30 12:52:10 -0700980 + ", mDaemonConnected=" + mDaemonConnected);
Eric Biggers1127d922019-04-05 12:46:35 -0700981 if (mBootCompleted && mDaemonConnected
982 && !StorageManager.isFileEncryptedNativeOnly()) {
983 // When booting a device without native support, make sure that our
984 // user directories are locked or unlocked based on the current
985 // emulation status.
986 final boolean initLocked = StorageManager.isFileEncryptedEmulatedOnly();
987 Slog.d(TAG, "Setting up emulation state, initlocked=" + initLocked);
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700988 final List<UserInfo> users = mContext.getSystemService(UserManager.class).getUsers();
Jeff Sharkey8924e872015-11-30 12:52:10 -0700989 for (UserInfo user : users) {
990 try {
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700991 if (initLocked) {
Jeff Sharkey54402792017-09-15 16:05:19 -0600992 mVold.lockUserKey(user.id);
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700993 } else {
Jeff Sharkey54402792017-09-15 16:05:19 -0600994 mVold.unlockUserKey(user.id, user.serialNumber, encodeBytes(null),
995 encodeBytes(null));
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700996 }
Jeff Sharkey43e12112017-09-12 16:31:45 -0600997 } catch (Exception e) {
998 Slog.wtf(TAG, e);
Jeff Sharkey8924e872015-11-30 12:52:10 -0700999 }
1000 }
1001 }
1002 }
1003
Daniel Rosenberg137aed12019-03-15 18:41:11 -07001004 private void resetIfBootedAndConnected() {
1005 Slog.d(TAG, "Thinking about reset, mBootCompleted=" + mBootCompleted
Jeff Sharkey48877892015-03-18 11:27:19 -07001006 + ", mDaemonConnected=" + mDaemonConnected);
Daniel Rosenberg137aed12019-03-15 18:41:11 -07001007 if (mBootCompleted && mDaemonConnected) {
Jeff Sharkey5a9bb742015-11-03 10:15:57 -08001008 final List<UserInfo> users = mContext.getSystemService(UserManager.class).getUsers();
Zim17be6f92019-09-25 14:37:55 +01001009
1010 if (mIsFuseEnabled) {
1011 mStorageSessionController.onReset(mVold, mHandler);
1012 } else {
1013 killMediaProvider(users);
1014 }
Jeff Sharkey14cbe522015-07-08 14:06:37 -07001015
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07001016 final int[] systemUnlockedUsers;
Jeff Sharkey5a9bb742015-11-03 10:15:57 -08001017 synchronized (mLock) {
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07001018 systemUnlockedUsers = mSystemUnlockedUsers;
Jeff Sharkeyb049e212012-09-07 23:16:01 -07001019
Jeff Sharkey5a9bb742015-11-03 10:15:57 -08001020 mDisks.clear();
1021 mVolumes.clear();
1022
1023 addInternalVolumeLocked();
1024 }
Jeff Sharkey59d577a2015-04-11 21:27:21 -07001025
Jeff Sharkey48877892015-03-18 11:27:19 -07001026 try {
Zim42f1e9f2019-08-15 17:35:00 +01001027 // TODO(b/135341433): Remove paranoid logging when FUSE is stable
Zim17be6f92019-09-25 14:37:55 +01001028 Slog.i(TAG, "Resetting vold...");
Jeff Sharkey54402792017-09-15 16:05:19 -06001029 mVold.reset();
Zim42f1e9f2019-08-15 17:35:00 +01001030 Slog.i(TAG, "Reset vold");
Jeff Sharkeybcd262d2015-06-10 09:41:17 -07001031
1032 // Tell vold about all existing and started users
Jeff Sharkeybcd262d2015-06-10 09:41:17 -07001033 for (UserInfo user : users) {
Jeff Sharkey54402792017-09-15 16:05:19 -06001034 mVold.onUserAdded(user.id, user.serialNumber);
Jeff Sharkeybcd262d2015-06-10 09:41:17 -07001035 }
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07001036 for (int userId : systemUnlockedUsers) {
Sudheer Shanka64501e52019-04-29 10:46:26 -07001037 mVold.onUserStarted(userId);
Jin Qian12690d52017-10-13 18:17:04 -07001038 mStoraged.onUserStarted(userId);
Jeff Sharkey50a05452015-04-29 11:24:52 -07001039 }
Jeff Sharkey9765e442017-12-14 22:15:14 -07001040 mVold.onSecureKeyguardStateChanged(mSecureKeyguardShowing);
Risanaec0ee72018-10-31 10:10:12 +09001041 mStorageManagerInternal.onReset(mVold);
Jeff Sharkeyace874b2017-09-07 15:27:33 -06001042 } catch (Exception e) {
1043 Slog.wtf(TAG, e);
Jeff Sharkeyb049e212012-09-07 23:16:01 -07001044 }
1045 }
Jeff Sharkey48877892015-03-18 11:27:19 -07001046 }
Jeff Sharkeyb049e212012-09-07 23:16:01 -07001047
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07001048 private void onUnlockUser(int userId) {
1049 Slog.d(TAG, "onUnlockUser " + userId);
Jeff Sharkey48877892015-03-18 11:27:19 -07001050
1051 // We purposefully block here to make sure that user-specific
1052 // staging area is ready so it's ready for zygote-forked apps to
1053 // bind mount against.
1054 try {
Zim17be6f92019-09-25 14:37:55 +01001055 mStorageSessionController.onUnlockUser(userId);
Sudheer Shanka64501e52019-04-29 10:46:26 -07001056 mVold.onUserStarted(userId);
Jin Qian12690d52017-10-13 18:17:04 -07001057 mStoraged.onUserStarted(userId);
Jeff Sharkeyace874b2017-09-07 15:27:33 -06001058 } catch (Exception e) {
1059 Slog.wtf(TAG, e);
Jeff Sharkeyb049e212012-09-07 23:16:01 -07001060 }
Jeff Sharkey48877892015-03-18 11:27:19 -07001061
Narayan Kamath157dd1d2019-06-12 13:06:30 +01001062 mHandler.obtainMessage(H_COMPLETE_UNLOCK_USER, userId).sendToTarget();
1063 }
1064
1065 private void completeUnlockUser(int userId) {
1066 // If user 0 has completed unlock, perform a one-time migration of legacy obb data
1067 // to its new location. This may take time depending on the size of the data to be copied
1068 // so it's done on the StorageManager handler thread.
1069 if (userId == 0) {
1070 mPmInternal.migrateLegacyObbData();
1071 }
1072
Jeff Sharkey48877892015-03-18 11:27:19 -07001073 // Record user as started so newly mounted volumes kick off events
1074 // correctly, then synthesize events for any already-mounted volumes.
yuanhuihuiefd1f122016-07-13 21:21:03 +08001075 synchronized (mLock) {
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07001076 for (int i = 0; i < mVolumes.size(); i++) {
1077 final VolumeInfo vol = mVolumes.valueAt(i);
Jeff Sharkey46349872015-07-28 10:49:47 -07001078 if (vol.isVisibleForRead(userId) && vol.isMountedReadable()) {
Svet Ganov6ee871e2015-07-10 14:29:33 -07001079 final StorageVolume userVol = vol.buildStorageVolume(mContext, userId, false);
Jeff Sharkey48877892015-03-18 11:27:19 -07001080 mHandler.obtainMessage(H_VOLUME_BROADCAST, userVol).sendToTarget();
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001081
Jeff Sharkey27de30d2015-04-18 16:20:27 -07001082 final String envState = VolumeInfo.getEnvironmentForState(vol.getState());
1083 mCallbacks.notifyStorageStateChanged(userVol.getPath(), envState, envState);
Jeff Sharkey48877892015-03-18 11:27:19 -07001084 }
1085 }
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07001086 mSystemUnlockedUsers = ArrayUtils.appendInt(mSystemUnlockedUsers, userId);
Jeff Sharkey48877892015-03-18 11:27:19 -07001087 }
1088 }
1089
1090 private void onCleanupUser(int userId) {
1091 Slog.d(TAG, "onCleanupUser " + userId);
1092
1093 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06001094 mVold.onUserStopped(userId);
Jin Qian12690d52017-10-13 18:17:04 -07001095 mStoraged.onUserStopped(userId);
Jeff Sharkeyace874b2017-09-07 15:27:33 -06001096 } catch (Exception e) {
1097 Slog.wtf(TAG, e);
Jeff Sharkey48877892015-03-18 11:27:19 -07001098 }
1099
yuanhuihuiefd1f122016-07-13 21:21:03 +08001100 synchronized (mLock) {
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07001101 mSystemUnlockedUsers = ArrayUtils.removeInt(mSystemUnlockedUsers, userId);
Jeff Sharkey48877892015-03-18 11:27:19 -07001102 }
1103 }
Jeff Sharkeyb049e212012-09-07 23:16:01 -07001104
Martijn Coenen7084c6a2019-11-22 16:32:09 +01001105 private void onStopUser(int userId) {
1106 Slog.i(TAG, "onStopUser " + userId);
1107 try {
1108 mStorageSessionController.onUserStopping(userId);
1109 } catch (Exception e) {
1110 Slog.wtf(TAG, e);
1111 }
1112 }
1113
Sudheer Shanka64501e52019-04-29 10:46:26 -07001114 private boolean supportsBlockCheckpoint() throws RemoteException {
Paul Lawrence15a54462019-04-30 11:14:25 -07001115 enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);
Sandeep Patil7d5c4912019-04-15 09:27:30 -07001116 return mVold.supportsBlockCheckpoint();
1117 }
1118
Jeff Sharkey9765e442017-12-14 22:15:14 -07001119 @Override
1120 public void onAwakeStateChanged(boolean isAwake) {
1121 // Ignored
1122 }
1123
1124 @Override
1125 public void onKeyguardStateChanged(boolean isShowing) {
1126 // Push down current secure keyguard status so that we ignore malicious
1127 // USB devices while locked.
1128 mSecureKeyguardShowing = isShowing
Martijn Coenen7c1df2d2020-01-07 10:21:42 +01001129 && mContext.getSystemService(KeyguardManager.class).isDeviceSecure(mCurrentUserId);
Jeff Sharkey9765e442017-12-14 22:15:14 -07001130 try {
1131 mVold.onSecureKeyguardStateChanged(mSecureKeyguardShowing);
1132 } catch (Exception e) {
1133 Slog.wtf(TAG, e);
1134 }
1135 }
1136
Christopher Tated417d622013-08-19 16:14:25 -07001137 void runIdleMaintenance(Runnable callback) {
1138 mHandler.sendMessage(mHandler.obtainMessage(H_FSTRIM, callback));
1139 }
1140
Christopher Tate7265abe2014-11-21 13:54:45 -08001141 // Binder entry point for kicking off an immediate fstrim
1142 @Override
1143 public void runMaintenance() {
Jeff Sharkey48877892015-03-18 11:27:19 -07001144 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
Christopher Tate7265abe2014-11-21 13:54:45 -08001145 runIdleMaintenance(null);
1146 }
1147
1148 @Override
1149 public long lastMaintenance() {
1150 return mLastMaintenance;
1151 }
1152
San Mehat4270e1e2010-01-29 05:32:19 -08001153 public void onDaemonConnected() {
Jeff Sharkey48877892015-03-18 11:27:19 -07001154 mDaemonConnected = true;
1155 mHandler.obtainMessage(H_DAEMON_CONNECTED).sendToTarget();
1156 }
1157
1158 private void handleDaemonConnected() {
Daniel Rosenberg137aed12019-03-15 18:41:11 -07001159 initIfBootedAndConnected();
1160 resetIfBootedAndConnected();
Jeff Sharkey48877892015-03-18 11:27:19 -07001161
Jeff Sharkey48877892015-03-18 11:27:19 -07001162 // On an encrypted device we can't see system properties yet, so pull
1163 // the system locale out of the mount service.
Inseob Kimc1246e62018-11-08 13:13:54 +09001164 if ("".equals(VoldProperties.encrypt_progress().orElse(""))) {
Jeff Sharkey48877892015-03-18 11:27:19 -07001165 copyLocaleFromMountService();
1166 }
San Mehat4270e1e2010-01-29 05:32:19 -08001167 }
1168
Elliott Hughesf839b4f2014-09-26 12:30:47 -07001169 private void copyLocaleFromMountService() {
1170 String systemLocale;
1171 try {
1172 systemLocale = getField(StorageManager.SYSTEM_LOCALE_KEY);
1173 } catch (RemoteException e) {
1174 return;
1175 }
1176 if (TextUtils.isEmpty(systemLocale)) {
1177 return;
1178 }
1179
1180 Slog.d(TAG, "Got locale " + systemLocale + " from mount service");
1181 Locale locale = Locale.forLanguageTag(systemLocale);
1182 Configuration config = new Configuration();
1183 config.setLocale(locale);
1184 try {
Sudheer Shankadc589ac2016-11-10 15:30:17 -08001185 ActivityManager.getService().updatePersistentConfiguration(config);
Elliott Hughesf839b4f2014-09-26 12:30:47 -07001186 } catch (RemoteException e) {
1187 Slog.e(TAG, "Error setting system locale from mount service", e);
1188 }
Elliott Hughes9c33f282014-10-13 12:39:56 -07001189
1190 // Temporary workaround for http://b/17945169.
1191 Slog.d(TAG, "Setting system properties to " + systemLocale + " from mount service");
Narayan Kamathd30dbb82015-01-15 14:48:15 +00001192 SystemProperties.set("persist.sys.locale", locale.toLanguageTag());
Elliott Hughesf839b4f2014-09-26 12:30:47 -07001193 }
1194
Jeff Sharkey8058fe62017-09-13 11:50:33 -06001195 private final IVoldListener mListener = new IVoldListener.Stub() {
1196 @Override
1197 public void onDiskCreated(String diskId, int flags) {
1198 synchronized (mLock) {
Jeff Sharkey901c0422018-04-20 13:11:20 -06001199 final String value = SystemProperties.get(StorageManager.PROP_ADOPTABLE);
1200 switch (value) {
1201 case "force_on":
1202 flags |= DiskInfo.FLAG_ADOPTABLE;
1203 break;
1204 case "force_off":
1205 flags &= ~DiskInfo.FLAG_ADOPTABLE;
1206 break;
Jeff Sharkey8058fe62017-09-13 11:50:33 -06001207 }
Jeff Sharkey8058fe62017-09-13 11:50:33 -06001208 mDisks.put(diskId, new DiskInfo(diskId, flags));
1209 }
1210 }
1211
1212 @Override
1213 public void onDiskScanned(String diskId) {
1214 synchronized (mLock) {
1215 final DiskInfo disk = mDisks.get(diskId);
1216 if (disk != null) {
1217 onDiskScannedLocked(disk);
1218 }
1219 }
1220 }
1221
1222 @Override
1223 public void onDiskMetadataChanged(String diskId, long sizeBytes, String label,
1224 String sysPath) {
1225 synchronized (mLock) {
1226 final DiskInfo disk = mDisks.get(diskId);
1227 if (disk != null) {
1228 disk.size = sizeBytes;
1229 disk.label = label;
1230 disk.sysPath = sysPath;
1231 }
1232 }
1233 }
1234
1235 @Override
1236 public void onDiskDestroyed(String diskId) {
1237 synchronized (mLock) {
1238 final DiskInfo disk = mDisks.remove(diskId);
1239 if (disk != null) {
1240 mCallbacks.notifyDiskDestroyed(disk);
1241 }
1242 }
1243 }
1244
1245 @Override
Zim17be6f92019-09-25 14:37:55 +01001246 public void onVolumeCreated(String volId, int type, String diskId, String partGuid,
1247 int userId) {
Jeff Sharkey8058fe62017-09-13 11:50:33 -06001248 synchronized (mLock) {
1249 final DiskInfo disk = mDisks.get(diskId);
1250 final VolumeInfo vol = new VolumeInfo(volId, type, disk, partGuid);
Zim17be6f92019-09-25 14:37:55 +01001251 vol.mountUserId = userId;
Jeff Sharkey8058fe62017-09-13 11:50:33 -06001252 mVolumes.put(volId, vol);
1253 onVolumeCreatedLocked(vol);
1254 }
1255 }
1256
1257 @Override
1258 public void onVolumeStateChanged(String volId, int state) {
1259 synchronized (mLock) {
1260 final VolumeInfo vol = mVolumes.get(volId);
1261 if (vol != null) {
1262 final int oldState = vol.state;
1263 final int newState = state;
1264 vol.state = newState;
1265 onVolumeStateChangedLocked(vol, oldState, newState);
1266 }
Ricky Wai4482ab52019-12-10 19:08:18 +00001267 try {
1268 if (vol.type == VolumeInfo.TYPE_PRIVATE && state == VolumeInfo.STATE_MOUNTED) {
1269 mInstaller.onPrivateVolumeMounted(vol.getFsUuid());
1270 }
1271 } catch (Installer.InstallerException e) {
1272 Slog.i(TAG, "Failed when private volume mounted " + vol, e);
1273 }
Jeff Sharkey8058fe62017-09-13 11:50:33 -06001274 }
1275 }
1276
1277 @Override
1278 public void onVolumeMetadataChanged(String volId, String fsType, String fsUuid,
1279 String fsLabel) {
1280 synchronized (mLock) {
1281 final VolumeInfo vol = mVolumes.get(volId);
1282 if (vol != null) {
1283 vol.fsType = fsType;
1284 vol.fsUuid = fsUuid;
1285 vol.fsLabel = fsLabel;
1286 }
1287 }
1288 }
1289
1290 @Override
1291 public void onVolumePathChanged(String volId, String path) {
1292 synchronized (mLock) {
1293 final VolumeInfo vol = mVolumes.get(volId);
1294 if (vol != null) {
1295 vol.path = path;
1296 }
1297 }
1298 }
1299
1300 @Override
1301 public void onVolumeInternalPathChanged(String volId, String internalPath) {
1302 synchronized (mLock) {
1303 final VolumeInfo vol = mVolumes.get(volId);
1304 if (vol != null) {
1305 vol.internalPath = internalPath;
1306 }
1307 }
1308 }
1309
1310 @Override
1311 public void onVolumeDestroyed(String volId) {
Zim17be6f92019-09-25 14:37:55 +01001312 VolumeInfo vol = null;
Jeff Sharkey8058fe62017-09-13 11:50:33 -06001313 synchronized (mLock) {
Zim17be6f92019-09-25 14:37:55 +01001314 vol = mVolumes.remove(volId);
1315 }
1316
1317 if (vol != null) {
1318 mStorageSessionController.onVolumeRemove(vol);
Ricky Wai4482ab52019-12-10 19:08:18 +00001319 try {
1320 if (vol.type == VolumeInfo.TYPE_PRIVATE) {
1321 mInstaller.onPrivateVolumeRemoved(vol.getFsUuid());
1322 }
1323 } catch (Installer.InstallerException e) {
1324 Slog.i(TAG, "Failed when private volume unmounted " + vol, e);
1325 }
Jeff Sharkey8058fe62017-09-13 11:50:33 -06001326 }
1327 }
1328 };
1329
Andreas Gampea36dc622018-02-05 17:19:22 -08001330 @GuardedBy("mLock")
Jeff Sharkeyeba260d2015-04-19 14:35:16 -07001331 private void onDiskScannedLocked(DiskInfo disk) {
Jeff Sharkey620b32b2015-04-23 19:36:02 -07001332 int volumeCount = 0;
Jeff Sharkeyeba260d2015-04-19 14:35:16 -07001333 for (int i = 0; i < mVolumes.size(); i++) {
1334 final VolumeInfo vol = mVolumes.valueAt(i);
1335 if (Objects.equals(disk.id, vol.getDiskId())) {
Jeff Sharkey620b32b2015-04-23 19:36:02 -07001336 volumeCount++;
Jeff Sharkeyeba260d2015-04-19 14:35:16 -07001337 }
1338 }
1339
Jeff Sharkeyc7acac62015-06-12 16:16:56 -07001340 final Intent intent = new Intent(DiskInfo.ACTION_DISK_SCANNED);
Jeff Sharkey7732e1e2016-03-30 17:14:23 -06001341 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT
1342 | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
Jeff Sharkeyc7acac62015-06-12 16:16:56 -07001343 intent.putExtra(DiskInfo.EXTRA_DISK_ID, disk.id);
1344 intent.putExtra(DiskInfo.EXTRA_VOLUME_COUNT, volumeCount);
Jeff Sharkeyabc3e852015-08-03 14:41:13 -07001345 mHandler.obtainMessage(H_INTERNAL_BROADCAST, intent).sendToTarget();
Jeff Sharkeyc7acac62015-06-12 16:16:56 -07001346
1347 final CountDownLatch latch = mDiskScanLatches.remove(disk.id);
1348 if (latch != null) {
1349 latch.countDown();
1350 }
1351
Jeff Sharkeyf5a6bd72015-05-19 14:42:38 -07001352 disk.volumeCount = volumeCount;
Jeff Sharkey620b32b2015-04-23 19:36:02 -07001353 mCallbacks.notifyDiskScanned(disk, volumeCount);
Jeff Sharkeyeba260d2015-04-19 14:35:16 -07001354 }
1355
Andreas Gampea36dc622018-02-05 17:19:22 -08001356 @GuardedBy("mLock")
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07001357 private void onVolumeCreatedLocked(VolumeInfo vol) {
Jeff Sharkey5790af02018-08-13 17:42:54 -06001358 if (mPmInternal.isOnlyCoreApps()) {
Jeff Sharkey6855c482016-03-31 14:34:38 -06001359 Slog.d(TAG, "System booted in core-only mode; ignoring volume " + vol.getId());
1360 return;
1361 }
Martijn Coenen7084c6a2019-11-22 16:32:09 +01001362 final ActivityManagerInternal amInternal =
1363 LocalServices.getService(ActivityManagerInternal.class);
1364
1365 if (mIsFuseEnabled && vol.mountUserId >= 0
1366 && !amInternal.isUserRunning(vol.mountUserId, 0)) {
1367 Slog.d(TAG, "Ignoring volume " + vol.getId() + " because user "
1368 + Integer.toString(vol.mountUserId) + " is no longer running.");
1369 return;
1370 }
Jeff Sharkey6855c482016-03-31 14:34:38 -06001371
Jeff Sharkey275e3e42015-04-24 16:10:32 -07001372 if (vol.type == VolumeInfo.TYPE_EMULATED) {
1373 final StorageManager storage = mContext.getSystemService(StorageManager.class);
1374 final VolumeInfo privateVol = storage.findPrivateForEmulated(vol);
1375
1376 if (Objects.equals(StorageManager.UUID_PRIVATE_INTERNAL, mPrimaryStorageUuid)
1377 && VolumeInfo.ID_PRIVATE_INTERNAL.equals(privateVol.id)) {
1378 Slog.v(TAG, "Found primary storage at " + vol);
1379 vol.mountFlags |= VolumeInfo.MOUNT_FLAG_PRIMARY;
1380 vol.mountFlags |= VolumeInfo.MOUNT_FLAG_VISIBLE;
1381 mHandler.obtainMessage(H_VOLUME_MOUNT, vol).sendToTarget();
1382
1383 } else if (Objects.equals(privateVol.fsUuid, mPrimaryStorageUuid)) {
1384 Slog.v(TAG, "Found primary storage at " + vol);
1385 vol.mountFlags |= VolumeInfo.MOUNT_FLAG_PRIMARY;
1386 vol.mountFlags |= VolumeInfo.MOUNT_FLAG_VISIBLE;
1387 mHandler.obtainMessage(H_VOLUME_MOUNT, vol).sendToTarget();
1388 }
Jeff Sharkeyb049e212012-09-07 23:16:01 -07001389
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07001390 } else if (vol.type == VolumeInfo.TYPE_PUBLIC) {
Jeff Sharkey275e3e42015-04-24 16:10:32 -07001391 // TODO: only look at first public partition
1392 if (Objects.equals(StorageManager.UUID_PRIMARY_PHYSICAL, mPrimaryStorageUuid)
1393 && vol.disk.isDefaultPrimary()) {
1394 Slog.v(TAG, "Found primary storage at " + vol);
Jeff Sharkey7e92ef32015-04-17 17:35:07 -07001395 vol.mountFlags |= VolumeInfo.MOUNT_FLAG_PRIMARY;
1396 vol.mountFlags |= VolumeInfo.MOUNT_FLAG_VISIBLE;
San Mehat4270e1e2010-01-29 05:32:19 -08001397 }
Jeff Sharkey7e92ef32015-04-17 17:35:07 -07001398
1399 // Adoptable public disks are visible to apps, since they meet
1400 // public API requirement of being in a stable location.
Jeff Sharkey275e3e42015-04-24 16:10:32 -07001401 if (vol.disk.isAdoptable()) {
Jeff Sharkey7e92ef32015-04-17 17:35:07 -07001402 vol.mountFlags |= VolumeInfo.MOUNT_FLAG_VISIBLE;
1403 }
1404
Jeff Sharkeyab15c392016-05-05 11:45:01 -06001405 vol.mountUserId = mCurrentUserId;
Jeff Sharkey48877892015-03-18 11:27:19 -07001406 mHandler.obtainMessage(H_VOLUME_MOUNT, vol).sendToTarget();
San Mehat4270e1e2010-01-29 05:32:19 -08001407
Jeff Sharkeyb2b9ab82015-04-05 21:10:42 -07001408 } else if (vol.type == VolumeInfo.TYPE_PRIVATE) {
1409 mHandler.obtainMessage(H_VOLUME_MOUNT, vol).sendToTarget();
1410
Risan05c41e62018-10-29 08:57:43 +09001411 } else if (vol.type == VolumeInfo.TYPE_STUB) {
1412 vol.mountUserId = mCurrentUserId;
1413 mHandler.obtainMessage(H_VOLUME_MOUNT, vol).sendToTarget();
San Mehat4270e1e2010-01-29 05:32:19 -08001414 } else {
Jeff Sharkey48877892015-03-18 11:27:19 -07001415 Slog.d(TAG, "Skipping automatic mounting of " + vol);
San Mehat4270e1e2010-01-29 05:32:19 -08001416 }
1417 }
1418
Jeff Sharkeye6c04f92015-04-18 21:38:05 -07001419 private boolean isBroadcastWorthy(VolumeInfo vol) {
1420 switch (vol.getType()) {
Jeff Sharkeyc7acac62015-06-12 16:16:56 -07001421 case VolumeInfo.TYPE_PRIVATE:
Jeff Sharkeye6c04f92015-04-18 21:38:05 -07001422 case VolumeInfo.TYPE_PUBLIC:
1423 case VolumeInfo.TYPE_EMULATED:
Risan05c41e62018-10-29 08:57:43 +09001424 case VolumeInfo.TYPE_STUB:
Jeff Sharkeye6c04f92015-04-18 21:38:05 -07001425 break;
1426 default:
1427 return false;
1428 }
1429
1430 switch (vol.getState()) {
1431 case VolumeInfo.STATE_MOUNTED:
1432 case VolumeInfo.STATE_MOUNTED_READ_ONLY:
1433 case VolumeInfo.STATE_EJECTING:
1434 case VolumeInfo.STATE_UNMOUNTED:
Jeff Sharkeyc7acac62015-06-12 16:16:56 -07001435 case VolumeInfo.STATE_UNMOUNTABLE:
Tony Mantlerf0d71052015-06-24 11:45:25 -07001436 case VolumeInfo.STATE_BAD_REMOVAL:
Jeff Sharkeye6c04f92015-04-18 21:38:05 -07001437 break;
1438 default:
1439 return false;
1440 }
1441
1442 return true;
1443 }
1444
Andreas Gampea36dc622018-02-05 17:19:22 -08001445 @GuardedBy("mLock")
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07001446 private void onVolumeStateChangedLocked(VolumeInfo vol, int oldState, int newState) {
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001447 // Remember that we saw this volume so we're ready to accept user
1448 // metadata, or so we can annoy them when a private volume is ejected
Jeff Sharkey3811f352019-05-14 11:54:36 -06001449 if (!TextUtils.isEmpty(vol.fsUuid)) {
Jeff Sharkey5cc0df22015-06-17 19:44:05 -07001450 VolumeRecord rec = mRecords.get(vol.fsUuid);
1451 if (rec == null) {
1452 rec = new VolumeRecord(vol.type, vol.fsUuid);
1453 rec.partGuid = vol.partGuid;
Jeff Sharkeye8a4b662015-06-27 15:43:45 -07001454 rec.createdMillis = System.currentTimeMillis();
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001455 if (vol.type == VolumeInfo.TYPE_PRIVATE) {
1456 rec.nickname = vol.disk.getDescription();
1457 }
1458 mRecords.put(rec.fsUuid, rec);
Jeff Sharkey5cc0df22015-06-17 19:44:05 -07001459 } else {
1460 // Handle upgrade case where we didn't store partition GUID
1461 if (TextUtils.isEmpty(rec.partGuid)) {
1462 rec.partGuid = vol.partGuid;
Jeff Sharkey5cc0df22015-06-17 19:44:05 -07001463 }
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001464 }
Jeff Sharkey3811f352019-05-14 11:54:36 -06001465
1466 rec.lastSeenMillis = System.currentTimeMillis();
1467 writeSettingsLocked();
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001468 }
1469
Jeff Sharkeye6c04f92015-04-18 21:38:05 -07001470 mCallbacks.notifyVolumeStateChanged(vol, oldState, newState);
1471
Yasuhiro Matsuda87a38b52015-07-24 22:10:16 +09001472 // Do not broadcast before boot has completed to avoid launching the
1473 // processes that receive the intent unnecessarily.
1474 if (mBootCompleted && isBroadcastWorthy(vol)) {
Jeff Sharkeye6c04f92015-04-18 21:38:05 -07001475 final Intent intent = new Intent(VolumeInfo.ACTION_VOLUME_STATE_CHANGED);
Jeff Sharkeyc7acac62015-06-12 16:16:56 -07001476 intent.putExtra(VolumeInfo.EXTRA_VOLUME_ID, vol.id);
1477 intent.putExtra(VolumeInfo.EXTRA_VOLUME_STATE, newState);
Tony Mantlerf0d71052015-06-24 11:45:25 -07001478 intent.putExtra(VolumeRecord.EXTRA_FS_UUID, vol.fsUuid);
Jeff Sharkey7732e1e2016-03-30 17:14:23 -06001479 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT
1480 | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
Jeff Sharkeyabc3e852015-08-03 14:41:13 -07001481 mHandler.obtainMessage(H_INTERNAL_BROADCAST, intent).sendToTarget();
Jeff Sharkeye6c04f92015-04-18 21:38:05 -07001482 }
Jeff Sharkeyb049e212012-09-07 23:16:01 -07001483
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001484 final String oldStateEnv = VolumeInfo.getEnvironmentForState(oldState);
1485 final String newStateEnv = VolumeInfo.getEnvironmentForState(newState);
Emily Bernier92aa5a22014-07-07 10:11:48 -04001486
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001487 if (!Objects.equals(oldStateEnv, newStateEnv)) {
1488 // Kick state changed event towards all started users. Any users
1489 // started after this point will trigger additional
1490 // user-specific broadcasts.
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07001491 for (int userId : mSystemUnlockedUsers) {
Jeff Sharkey46349872015-07-28 10:49:47 -07001492 if (vol.isVisibleForRead(userId)) {
Svet Ganov6ee871e2015-07-10 14:29:33 -07001493 final StorageVolume userVol = vol.buildStorageVolume(mContext, userId, false);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001494 mHandler.obtainMessage(H_VOLUME_BROADCAST, userVol).sendToTarget();
Jeff Sharkey48877892015-03-18 11:27:19 -07001495
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001496 mCallbacks.notifyStorageStateChanged(userVol.getPath(), oldStateEnv,
1497 newStateEnv);
San Mehat4270e1e2010-01-29 05:32:19 -08001498 }
1499 }
1500 }
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001501
Risan05c41e62018-10-29 08:57:43 +09001502 if ((vol.type == VolumeInfo.TYPE_PUBLIC || vol.type == VolumeInfo.TYPE_STUB)
1503 && vol.state == VolumeInfo.STATE_EJECTING) {
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001504 // TODO: this should eventually be handled by new ObbVolume state changes
1505 /*
1506 * Some OBBs might have been unmounted when this volume was
1507 * unmounted, so send a message to the handler to let it know to
1508 * remove those from the list of mounted OBBS.
1509 */
1510 mObbActionHandler.sendMessage(mObbActionHandler.obtainMessage(
1511 OBB_FLUSH_MOUNT_STATE, vol.path));
1512 }
Pavel Grafovce72ef02018-01-10 17:14:11 +00001513 maybeLogMediaMount(vol, newState);
1514 }
1515
1516 private void maybeLogMediaMount(VolumeInfo vol, int newState) {
1517 if (!SecurityLog.isLoggingEnabled()) {
1518 return;
1519 }
1520
1521 final DiskInfo disk = vol.getDisk();
1522 if (disk == null || (disk.flags & (DiskInfo.FLAG_SD | DiskInfo.FLAG_USB)) == 0) {
1523 return;
1524 }
1525
1526 // Sometimes there is a newline character.
1527 final String label = disk.label != null ? disk.label.trim() : "";
1528
1529 if (newState == VolumeInfo.STATE_MOUNTED
1530 || newState == VolumeInfo.STATE_MOUNTED_READ_ONLY) {
1531 SecurityLog.writeEvent(SecurityLog.TAG_MEDIA_MOUNT, vol.path, label);
1532 } else if (newState == VolumeInfo.STATE_UNMOUNTED
1533 || newState == VolumeInfo.STATE_BAD_REMOVAL) {
1534 SecurityLog.writeEvent(SecurityLog.TAG_MEDIA_UNMOUNT, vol.path, label);
1535 }
San Mehat4270e1e2010-01-29 05:32:19 -08001536 }
1537
Andreas Gampea36dc622018-02-05 17:19:22 -08001538 @GuardedBy("mLock")
Jeff Sharkey275e3e42015-04-24 16:10:32 -07001539 private void onMoveStatusLocked(int status) {
1540 if (mMoveCallback == null) {
1541 Slog.w(TAG, "Odd, status but no move requested");
1542 return;
1543 }
1544
1545 // TODO: estimate remaining time
1546 try {
Jeff Sharkey50a05452015-04-29 11:24:52 -07001547 mMoveCallback.onStatusChanged(-1, status, -1);
Jeff Sharkey275e3e42015-04-24 16:10:32 -07001548 } catch (RemoteException ignored) {
1549 }
1550
1551 // We've finished copying and we're about to clean up old data, so
1552 // remember that move was successful if we get rebooted
1553 if (status == MOVE_STATUS_COPY_FINISHED) {
1554 Slog.d(TAG, "Move to " + mMoveTargetUuid + " copy phase finshed; persisting");
1555
1556 mPrimaryStorageUuid = mMoveTargetUuid;
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001557 writeSettingsLocked();
Jeff Sharkey275e3e42015-04-24 16:10:32 -07001558 }
1559
1560 if (PackageManager.isMoveStatusFinished(status)) {
1561 Slog.d(TAG, "Move to " + mMoveTargetUuid + " finished with status " + status);
1562
1563 mMoveCallback = null;
1564 mMoveTargetUuid = null;
1565 }
1566 }
1567
Jeff Sharkey48877892015-03-18 11:27:19 -07001568 private void enforcePermission(String perm) {
1569 mContext.enforceCallingOrSelfPermission(perm, perm);
Mike Lockwooda5250c92011-05-23 13:44:04 -04001570 }
1571
Jeff Sharkey2e606d72015-07-27 14:19:54 -07001572 /**
1573 * Decide if volume is mountable per device policies.
1574 */
1575 private boolean isMountDisallowed(VolumeInfo vol) {
Philip P. Moltmannec3cbb22016-09-14 13:24:52 -07001576 UserManager userManager = mContext.getSystemService(UserManager.class);
1577
1578 boolean isUsbRestricted = false;
1579 if (vol.disk != null && vol.disk.isUsb()) {
1580 isUsbRestricted = userManager.hasUserRestriction(UserManager.DISALLOW_USB_FILE_TRANSFER,
Jeff Sharkey2e606d72015-07-27 14:19:54 -07001581 Binder.getCallingUserHandle());
Emily Bernier92aa5a22014-07-07 10:11:48 -04001582 }
Philip P. Moltmannec3cbb22016-09-14 13:24:52 -07001583
1584 boolean isTypeRestricted = false;
Risan05c41e62018-10-29 08:57:43 +09001585 if (vol.type == VolumeInfo.TYPE_PUBLIC || vol.type == VolumeInfo.TYPE_PRIVATE
1586 || vol.type == VolumeInfo.TYPE_STUB) {
Philip P. Moltmannec3cbb22016-09-14 13:24:52 -07001587 isTypeRestricted = userManager
1588 .hasUserRestriction(UserManager.DISALLOW_MOUNT_PHYSICAL_MEDIA,
1589 Binder.getCallingUserHandle());
1590 }
1591
1592 return isUsbRestricted || isTypeRestricted;
Emily Bernier92aa5a22014-07-07 10:11:48 -04001593 }
1594
Amith Yamasani462ac3a2015-06-30 14:21:01 -07001595 private void enforceAdminUser() {
1596 UserManager um = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
1597 final int callingUserId = UserHandle.getCallingUserId();
1598 boolean isAdmin;
1599 long token = Binder.clearCallingIdentity();
1600 try {
1601 isAdmin = um.getUserInfo(callingUserId).isAdmin();
1602 } finally {
1603 Binder.restoreCallingIdentity(token);
1604 }
1605 if (!isAdmin) {
1606 throw new SecurityException("Only admin users can adopt sd cards");
1607 }
1608 }
1609
Jeff Sharkeyb049e212012-09-07 23:16:01 -07001610 /**
Sudheer Shanka2250d562016-11-07 15:41:02 -08001611 * Constructs a new StorageManagerService instance
San Mehat207e5382010-02-04 20:46:54 -08001612 *
1613 * @param context Binder context for this service
1614 */
Sudheer Shanka2250d562016-11-07 15:41:02 -08001615 public StorageManagerService(Context context) {
Christopher Tated417d622013-08-19 16:14:25 -07001616 sSelf = this;
1617
Jeff Sharkey342b4bf2018-12-18 11:12:40 -07001618 // Snapshot feature flag used for this boot
1619 SystemProperties.set(StorageManager.PROP_ISOLATED_STORAGE_SNAPSHOT, Boolean.toString(
Jeff Sharkey06376802019-02-11 12:20:02 -07001620 SystemProperties.getBoolean(StorageManager.PROP_ISOLATED_STORAGE, true)));
shafik78fcd502019-09-25 13:50:04 +01001621
Zim69e9c092020-01-21 13:32:32 +00001622 // If there is no value in the property yet (first boot after data wipe), this value may be
1623 // incorrect until #updateFusePropFromSettings where we set the correct value and reboot if
1624 // different
1625 mIsFuseEnabled = SystemProperties.getBoolean(PROP_FUSE, false);
San Mehat207e5382010-02-04 20:46:54 -08001626 mContext = context;
Jeff Sharkey5d0c55c2019-01-24 14:32:31 -07001627 mResolver = mContext.getContentResolver();
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001628 mCallbacks = new Callbacks(FgThread.get().getLooper());
Jeff Sharkeyb9fe5372015-12-03 15:23:08 -07001629 mLockPatternUtils = new LockPatternUtils(mContext);
San Mehat207e5382010-02-04 20:46:54 -08001630
Dianne Hackbornefa92b22013-05-03 14:11:43 -07001631 HandlerThread hthread = new HandlerThread(TAG);
1632 hthread.start();
Sudheer Shanka2250d562016-11-07 15:41:02 -08001633 mHandler = new StorageManagerServiceHandler(hthread.getLooper());
Daniel Sandler5f27ef42010-03-16 15:42:02 -04001634
Sudheer Shanka2250d562016-11-07 15:41:02 -08001635 // Add OBB Action Handler to StorageManagerService thread.
Dianne Hackborn8d044e82013-04-30 17:24:15 -07001636 mObbActionHandler = new ObbActionHandler(IoThread.get().getLooper());
Kenny Roota02b8b02010-08-05 16:14:17 -07001637
Zim17be6f92019-09-25 14:37:55 +01001638 mStorageSessionController = new StorageSessionController(mContext, mIsFuseEnabled);
Zim42f1e9f2019-08-15 17:35:00 +01001639
Ricky Wai4482ab52019-12-10 19:08:18 +00001640 mInstaller = new Installer(mContext);
1641 mInstaller.onStart();
1642
Christopher Tate7265abe2014-11-21 13:54:45 -08001643 // Initialize the last-fstrim tracking if necessary
1644 File dataDir = Environment.getDataDirectory();
1645 File systemDir = new File(dataDir, "system");
1646 mLastMaintenanceFile = new File(systemDir, LAST_FSTRIM_FILE);
1647 if (!mLastMaintenanceFile.exists()) {
1648 // Not setting mLastMaintenance here means that we will force an
1649 // fstrim during reboot following the OTA that installs this code.
1650 try {
1651 (new FileOutputStream(mLastMaintenanceFile)).close();
1652 } catch (IOException e) {
1653 Slog.e(TAG, "Unable to create fstrim record " + mLastMaintenanceFile.getPath());
1654 }
1655 } else {
1656 mLastMaintenance = mLastMaintenanceFile.lastModified();
1657 }
1658
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001659 mSettingsFile = new AtomicFile(
Dianne Hackborne17b4452018-01-10 13:15:40 -08001660 new File(Environment.getDataSystemDirectory(), "storage.xml"), "storage-settings");
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001661
1662 synchronized (mLock) {
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001663 readSettingsLocked();
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001664 }
1665
Sudheer Shanka2250d562016-11-07 15:41:02 -08001666 LocalServices.addService(StorageManagerInternal.class, mStorageManagerInternal);
Svet Ganov6ee871e2015-07-10 14:29:33 -07001667
Jeff Sharkeybcd262d2015-06-10 09:41:17 -07001668 final IntentFilter userFilter = new IntentFilter();
1669 userFilter.addAction(Intent.ACTION_USER_ADDED);
1670 userFilter.addAction(Intent.ACTION_USER_REMOVED);
1671 mContext.registerReceiver(mUserReceiver, userFilter, null, mHandler);
1672
Jeff Sharkey5a9bb742015-11-03 10:15:57 -08001673 synchronized (mLock) {
1674 addInternalVolumeLocked();
1675 }
Amith Yamasania7892482015-08-07 11:09:05 -07001676
Kenny Root07714d42011-08-17 17:49:28 -07001677 // Add ourself to the Watchdog monitors if enabled.
1678 if (WATCHDOG_ENABLE) {
1679 Watchdog.getInstance().addMonitor(this);
1680 }
San Mehat207e5382010-02-04 20:46:54 -08001681 }
1682
Abhijeet Kaurb9847712019-11-19 16:35:47 +00001683 /**
1684 * Checks if user changed the persistent settings_fuse flag from Settings UI
1685 * and updates PROP_FUSE (reboots if changed).
1686 */
1687 private void updateFusePropFromSettings() {
Zim69e9c092020-01-21 13:32:32 +00001688 boolean defaultFuseFlag = false;
1689 boolean settingsFuseFlag = SystemProperties.getBoolean(PROP_SETTINGS_FUSE, defaultFuseFlag);
1690 Slog.d(TAG, "FUSE flags. Settings: " + settingsFuseFlag + ". Default: " + defaultFuseFlag);
1691
1692 if (TextUtils.isEmpty(SystemProperties.get(PROP_SETTINGS_FUSE))) {
1693 // Set default value of PROP_SETTINGS_FUSE and PROP_FUSE if it
1694 // is unset (neither true nor false).
1695 // This happens only on the first boot after wiping data partition
1696 SystemProperties.set(PROP_SETTINGS_FUSE, Boolean.toString(defaultFuseFlag));
1697 SystemProperties.set(PROP_FUSE, Boolean.toString(defaultFuseFlag));
Abhijeet Kaura4f40562019-12-09 13:55:42 +00001698 return;
1699 }
1700
Zim69e9c092020-01-21 13:32:32 +00001701 if (mIsFuseEnabled != settingsFuseFlag) {
1702 Slog.i(TAG, "Toggling persist.sys.fuse to " + settingsFuseFlag);
1703 SystemProperties.set(PROP_FUSE, Boolean.toString(settingsFuseFlag));
Shafik Nassar07dcbbc2020-01-28 18:35:25 +00001704 // Perform hard reboot to kick policy into place
1705 mContext.getSystemService(PowerManager.class).reboot("fuse_prop");
Abhijeet Kaurb9847712019-11-19 16:35:47 +00001706 }
1707 }
1708
Jeff Sharkeycd575992016-03-29 14:12:49 -06001709 private void start() {
peter.zhangb0d11d12019-06-13 16:39:30 +08001710 connectStoraged();
1711 connectVold();
Jeff Sharkeycd575992016-03-29 14:12:49 -06001712 }
1713
peter.zhangb0d11d12019-06-13 16:39:30 +08001714 private void connectStoraged() {
Jin Qian12690d52017-10-13 18:17:04 -07001715 IBinder binder = ServiceManager.getService("storaged");
1716 if (binder != null) {
1717 try {
1718 binder.linkToDeath(new DeathRecipient() {
1719 @Override
1720 public void binderDied() {
1721 Slog.w(TAG, "storaged died; reconnecting");
1722 mStoraged = null;
peter.zhangb0d11d12019-06-13 16:39:30 +08001723 connectStoraged();
Jin Qian12690d52017-10-13 18:17:04 -07001724 }
1725 }, 0);
1726 } catch (RemoteException e) {
1727 binder = null;
1728 }
1729 }
1730
1731 if (binder != null) {
1732 mStoraged = IStoraged.Stub.asInterface(binder);
1733 } else {
1734 Slog.w(TAG, "storaged not found; trying again");
1735 }
1736
peter.zhangb0d11d12019-06-13 16:39:30 +08001737 if (mStoraged == null) {
1738 BackgroundThread.getHandler().postDelayed(() -> {
1739 connectStoraged();
1740 }, DateUtils.SECOND_IN_MILLIS);
1741 } else {
1742 onDaemonConnected();
1743 }
1744 }
1745
1746 private void connectVold() {
1747 IBinder binder = ServiceManager.getService("vold");
Jeff Sharkey1019de92017-09-06 13:47:03 -06001748 if (binder != null) {
1749 try {
1750 binder.linkToDeath(new DeathRecipient() {
1751 @Override
1752 public void binderDied() {
1753 Slog.w(TAG, "vold died; reconnecting");
Jin Qian12690d52017-10-13 18:17:04 -07001754 mVold = null;
peter.zhangb0d11d12019-06-13 16:39:30 +08001755 connectVold();
Jeff Sharkey1019de92017-09-06 13:47:03 -06001756 }
1757 }, 0);
1758 } catch (RemoteException e) {
1759 binder = null;
1760 }
1761 }
1762
1763 if (binder != null) {
1764 mVold = IVold.Stub.asInterface(binder);
Jeff Sharkey8058fe62017-09-13 11:50:33 -06001765 try {
1766 mVold.setListener(mListener);
Jeff Sharkey8058fe62017-09-13 11:50:33 -06001767 } catch (RemoteException e) {
Jin Qian12690d52017-10-13 18:17:04 -07001768 mVold = null;
Jeff Sharkey8058fe62017-09-13 11:50:33 -06001769 Slog.w(TAG, "vold listener rejected; trying again", e);
1770 }
Jeff Sharkey1019de92017-09-06 13:47:03 -06001771 } else {
1772 Slog.w(TAG, "vold not found; trying again");
Jeff Sharkey1019de92017-09-06 13:47:03 -06001773 }
Jeff Sharkey8058fe62017-09-13 11:50:33 -06001774
peter.zhangb0d11d12019-06-13 16:39:30 +08001775 if (mVold == null) {
Jin Qian12690d52017-10-13 18:17:04 -07001776 BackgroundThread.getHandler().postDelayed(() -> {
peter.zhangb0d11d12019-06-13 16:39:30 +08001777 connectVold();
Jin Qian12690d52017-10-13 18:17:04 -07001778 }, DateUtils.SECOND_IN_MILLIS);
1779 } else {
1780 onDaemonConnected();
1781 }
Jeff Sharkey1019de92017-09-06 13:47:03 -06001782 }
1783
Jeff Sharkey11697f52018-12-13 10:14:42 -07001784 private void servicesReady() {
Sudheer Shankaff585072019-01-29 23:19:45 -08001785 mPmInternal = LocalServices.getService(PackageManagerInternal.class);
Sudheer Shankaff585072019-01-29 23:19:45 -08001786
1787 mIPackageManager = IPackageManager.Stub.asInterface(
1788 ServiceManager.getService("package"));
1789 mIAppOpsService = IAppOpsService.Stub.asInterface(
1790 ServiceManager.getService(Context.APP_OPS_SERVICE));
Zim74a9bba2019-09-03 20:49:13 +01001791
1792 ProviderInfo provider = mPmInternal.resolveContentProvider(
1793 MediaStore.AUTHORITY, PackageManager.MATCH_DIRECT_BOOT_AWARE
1794 | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
1795 UserHandle.getUserId(UserHandle.USER_SYSTEM));
1796 if (provider != null) {
Martijn Coenen44db1ac2019-12-03 16:06:19 +01001797 mMediaStoreAuthorityAppId = UserHandle.getAppId(provider.applicationInfo.uid);
Zim74a9bba2019-09-03 20:49:13 +01001798 }
1799
Martijn Coenen496ac002020-01-08 14:55:53 +01001800 provider = mPmInternal.resolveContentProvider(
1801 Downloads.Impl.AUTHORITY, PackageManager.MATCH_DIRECT_BOOT_AWARE
1802 | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
1803 UserHandle.getUserId(UserHandle.USER_SYSTEM));
1804
1805 if (provider != null) {
1806 mDownloadsAuthorityAppId = UserHandle.getAppId(provider.applicationInfo.uid);
1807 }
1808
Sudheer Shankaff585072019-01-29 23:19:45 -08001809 try {
1810 mIAppOpsService.startWatchingMode(OP_REQUEST_INSTALL_PACKAGES, null, mAppOpsCallback);
Sudheer Shanka783c90e2019-04-12 13:55:20 -07001811 mIAppOpsService.startWatchingMode(OP_LEGACY_STORAGE, null, mAppOpsCallback);
Sudheer Shankaff585072019-01-29 23:19:45 -08001812 } catch (RemoteException e) {
1813 }
Jeff Sharkey11697f52018-12-13 10:14:42 -07001814 }
1815
1816 private static long getLastAccessTime(AppOpsManager manager,
1817 int uid, String packageName, int[] ops) {
1818 long maxTime = 0;
1819 final List<AppOpsManager.PackageOps> pkgs = manager.getOpsForPackage(uid, packageName, ops);
Eugene Susla04d021c2018-12-17 14:49:59 -08001820 for (AppOpsManager.PackageOps pkg : CollectionUtils.emptyIfNull(pkgs)) {
1821 for (AppOpsManager.OpEntry op : CollectionUtils.emptyIfNull(pkg.getOps())) {
Svet Ganovaf189e32019-02-15 18:45:29 -08001822 maxTime = Math.max(maxTime, op.getLastAccessTime(
1823 AppOpsManager.OP_FLAGS_ALL_TRUSTED));
Jeff Sharkey11697f52018-12-13 10:14:42 -07001824 }
1825 }
1826 return maxTime;
1827 }
1828
Jeff Sharkey56e62932015-03-21 20:41:00 -07001829 private void systemReady() {
Wale Ogunwale6767eae2018-05-03 15:52:51 -07001830 LocalServices.getService(ActivityTaskManagerInternal.class)
Jeff Sharkey9765e442017-12-14 22:15:14 -07001831 .registerScreenObserver(this);
1832
Jeff Sharkeyb049e212012-09-07 23:16:01 -07001833 mHandler.obtainMessage(H_SYSTEM_READY).sendToTarget();
1834 }
1835
Yasuhiro Matsuda87a38b52015-07-24 22:10:16 +09001836 private void bootCompleted() {
1837 mBootCompleted = true;
Daniel Rosenberg137aed12019-03-15 18:41:11 -07001838 mHandler.obtainMessage(H_BOOT_COMPLETED).sendToTarget();
Abhijeet Kaur10c56552019-12-04 14:17:40 +00001839 updateFusePropFromSettings();
Daniel Rosenberg137aed12019-03-15 18:41:11 -07001840 }
1841
1842 private void handleBootCompleted() {
1843 initIfBootedAndConnected();
1844 resetIfBootedAndConnected();
Yasuhiro Matsuda87a38b52015-07-24 22:10:16 +09001845 }
1846
Jeff Sharkeyfced5342015-05-10 14:53:34 -07001847 private String getDefaultPrimaryStorageUuid() {
1848 if (SystemProperties.getBoolean(StorageManager.PROP_PRIMARY_PHYSICAL, false)) {
1849 return StorageManager.UUID_PRIMARY_PHYSICAL;
1850 } else {
1851 return StorageManager.UUID_PRIVATE_INTERNAL;
1852 }
1853 }
1854
Andreas Gampea36dc622018-02-05 17:19:22 -08001855 @GuardedBy("mLock")
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001856 private void readSettingsLocked() {
1857 mRecords.clear();
Jeff Sharkeyfced5342015-05-10 14:53:34 -07001858 mPrimaryStorageUuid = getDefaultPrimaryStorageUuid();
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001859
1860 FileInputStream fis = null;
1861 try {
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001862 fis = mSettingsFile.openRead();
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001863 final XmlPullParser in = Xml.newPullParser();
Wojciech Staszkiewicz9e9e2e72015-05-08 14:58:46 +01001864 in.setInput(fis, StandardCharsets.UTF_8.name());
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001865
1866 int type;
1867 while ((type = in.next()) != END_DOCUMENT) {
1868 if (type == START_TAG) {
1869 final String tag = in.getName();
Jeff Sharkey620b32b2015-04-23 19:36:02 -07001870 if (TAG_VOLUMES.equals(tag)) {
1871 final int version = readIntAttribute(in, ATTR_VERSION, VERSION_INIT);
Jeff Sharkeyfced5342015-05-10 14:53:34 -07001872 final boolean primaryPhysical = SystemProperties.getBoolean(
1873 StorageManager.PROP_PRIMARY_PHYSICAL, false);
1874 final boolean validAttr = (version >= VERSION_FIX_PRIMARY)
1875 || (version >= VERSION_ADD_PRIMARY && !primaryPhysical);
1876 if (validAttr) {
Jeff Sharkey620b32b2015-04-23 19:36:02 -07001877 mPrimaryStorageUuid = readStringAttribute(in,
1878 ATTR_PRIMARY_STORAGE_UUID);
Jeff Sharkey620b32b2015-04-23 19:36:02 -07001879 }
Jeff Sharkey620b32b2015-04-23 19:36:02 -07001880 } else if (TAG_VOLUME.equals(tag)) {
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001881 final VolumeRecord rec = readVolumeRecord(in);
1882 mRecords.put(rec.fsUuid, rec);
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001883 }
1884 }
1885 }
1886 } catch (FileNotFoundException e) {
1887 // Missing metadata is okay, probably first boot
1888 } catch (IOException e) {
1889 Slog.wtf(TAG, "Failed reading metadata", e);
1890 } catch (XmlPullParserException e) {
1891 Slog.wtf(TAG, "Failed reading metadata", e);
1892 } finally {
1893 IoUtils.closeQuietly(fis);
1894 }
1895 }
1896
Andreas Gampea36dc622018-02-05 17:19:22 -08001897 @GuardedBy("mLock")
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001898 private void writeSettingsLocked() {
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001899 FileOutputStream fos = null;
1900 try {
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001901 fos = mSettingsFile.startWrite();
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001902
1903 XmlSerializer out = new FastXmlSerializer();
Wojciech Staszkiewicz9e9e2e72015-05-08 14:58:46 +01001904 out.setOutput(fos, StandardCharsets.UTF_8.name());
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001905 out.startDocument(null, true);
1906 out.startTag(null, TAG_VOLUMES);
Jeff Sharkeyfced5342015-05-10 14:53:34 -07001907 writeIntAttribute(out, ATTR_VERSION, VERSION_FIX_PRIMARY);
Jeff Sharkey620b32b2015-04-23 19:36:02 -07001908 writeStringAttribute(out, ATTR_PRIMARY_STORAGE_UUID, mPrimaryStorageUuid);
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001909 final int size = mRecords.size();
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001910 for (int i = 0; i < size; i++) {
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001911 final VolumeRecord rec = mRecords.valueAt(i);
1912 writeVolumeRecord(out, rec);
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001913 }
1914 out.endTag(null, TAG_VOLUMES);
1915 out.endDocument();
1916
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001917 mSettingsFile.finishWrite(fos);
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001918 } catch (IOException e) {
1919 if (fos != null) {
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001920 mSettingsFile.failWrite(fos);
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001921 }
1922 }
1923 }
1924
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001925 public static VolumeRecord readVolumeRecord(XmlPullParser in) throws IOException {
1926 final int type = readIntAttribute(in, ATTR_TYPE);
1927 final String fsUuid = readStringAttribute(in, ATTR_FS_UUID);
1928 final VolumeRecord meta = new VolumeRecord(type, fsUuid);
Jeff Sharkey5cc0df22015-06-17 19:44:05 -07001929 meta.partGuid = readStringAttribute(in, ATTR_PART_GUID);
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001930 meta.nickname = readStringAttribute(in, ATTR_NICKNAME);
1931 meta.userFlags = readIntAttribute(in, ATTR_USER_FLAGS);
Jeff Sharkey3811f352019-05-14 11:54:36 -06001932 meta.createdMillis = readLongAttribute(in, ATTR_CREATED_MILLIS, 0);
1933 meta.lastSeenMillis = readLongAttribute(in, ATTR_LAST_SEEN_MILLIS, 0);
1934 meta.lastTrimMillis = readLongAttribute(in, ATTR_LAST_TRIM_MILLIS, 0);
1935 meta.lastBenchMillis = readLongAttribute(in, ATTR_LAST_BENCH_MILLIS, 0);
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001936 return meta;
1937 }
1938
1939 public static void writeVolumeRecord(XmlSerializer out, VolumeRecord rec) throws IOException {
1940 out.startTag(null, TAG_VOLUME);
1941 writeIntAttribute(out, ATTR_TYPE, rec.type);
1942 writeStringAttribute(out, ATTR_FS_UUID, rec.fsUuid);
Jeff Sharkey5cc0df22015-06-17 19:44:05 -07001943 writeStringAttribute(out, ATTR_PART_GUID, rec.partGuid);
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001944 writeStringAttribute(out, ATTR_NICKNAME, rec.nickname);
1945 writeIntAttribute(out, ATTR_USER_FLAGS, rec.userFlags);
Jeff Sharkeye8a4b662015-06-27 15:43:45 -07001946 writeLongAttribute(out, ATTR_CREATED_MILLIS, rec.createdMillis);
Jeff Sharkey3811f352019-05-14 11:54:36 -06001947 writeLongAttribute(out, ATTR_LAST_SEEN_MILLIS, rec.lastSeenMillis);
Jeff Sharkeye8a4b662015-06-27 15:43:45 -07001948 writeLongAttribute(out, ATTR_LAST_TRIM_MILLIS, rec.lastTrimMillis);
1949 writeLongAttribute(out, ATTR_LAST_BENCH_MILLIS, rec.lastBenchMillis);
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001950 out.endTag(null, TAG_VOLUME);
1951 }
1952
San Mehat207e5382010-02-04 20:46:54 -08001953 /**
San Mehat4270e1e2010-01-29 05:32:19 -08001954 * Exposed API calls below here
1955 */
1956
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001957 @Override
Sudheer Shanka2250d562016-11-07 15:41:02 -08001958 public void registerListener(IStorageEventListener listener) {
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001959 mCallbacks.register(listener);
San Mehat4270e1e2010-01-29 05:32:19 -08001960 }
1961
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001962 @Override
Sudheer Shanka2250d562016-11-07 15:41:02 -08001963 public void unregisterListener(IStorageEventListener listener) {
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001964 mCallbacks.unregister(listener);
San Mehat4270e1e2010-01-29 05:32:19 -08001965 }
1966
Jeff Sharkey48877892015-03-18 11:27:19 -07001967 @Override
Sudheer Shanka2250d562016-11-07 15:41:02 -08001968 public void shutdown(final IStorageShutdownObserver observer) {
Jeff Sharkey48877892015-03-18 11:27:19 -07001969 enforcePermission(android.Manifest.permission.SHUTDOWN);
San Mehat4270e1e2010-01-29 05:32:19 -08001970
San Mehata5078592010-03-25 09:36:54 -07001971 Slog.i(TAG, "Shutting down");
Jeff Sharkey48877892015-03-18 11:27:19 -07001972 mHandler.obtainMessage(H_SHUTDOWN, observer).sendToTarget();
San Mehat4270e1e2010-01-29 05:32:19 -08001973 }
1974
Jeff Sharkey48877892015-03-18 11:27:19 -07001975 @Override
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001976 public void mount(String volId) {
1977 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001978
Jeff Sharkeyef10ee02015-07-05 14:17:27 -07001979 final VolumeInfo vol = findVolumeByIdOrThrow(volId);
Jeff Sharkey2e606d72015-07-27 14:19:54 -07001980 if (isMountDisallowed(vol)) {
1981 throw new SecurityException("Mounting " + volId + " restricted by policy");
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001982 }
Zim17be6f92019-09-25 14:37:55 +01001983
Sudheer Shanka3f0645b2018-09-18 13:07:59 -07001984 mount(vol);
1985 }
1986
Zim17be6f92019-09-25 14:37:55 +01001987 private void mount(VolumeInfo vol) {
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001988 try {
Zim17be6f92019-09-25 14:37:55 +01001989 // TODO(b/135341433): Remove paranoid logging when FUSE is stable
1990 Slog.i(TAG, "Mounting volume " + vol);
Zim95eca1d2019-11-15 18:03:00 +00001991 mVold.mount(vol.id, vol.mountFlags, vol.mountUserId, new IVoldMountCallback.Stub() {
1992 @Override
Zim7924a512020-01-15 15:23:54 +00001993 public boolean onVolumeChecking(FileDescriptor fd, String path,
Zim95eca1d2019-11-15 18:03:00 +00001994 String internalPath) {
1995 vol.path = path;
1996 vol.internalPath = internalPath;
Zim7924a512020-01-15 15:23:54 +00001997 ParcelFileDescriptor pfd = new ParcelFileDescriptor(fd);
Zim95eca1d2019-11-15 18:03:00 +00001998 try {
Zim7924a512020-01-15 15:23:54 +00001999 mStorageSessionController.onVolumeMount(pfd, vol);
Zim95eca1d2019-11-15 18:03:00 +00002000 return true;
2001 } catch (ExternalStorageServiceException e) {
Zim7924a512020-01-15 15:23:54 +00002002 Slog.e(TAG, "Failed to mount volume " + vol, e);
2003
Zimb8ca0542020-01-16 22:54:48 +00002004 int nextResetSeconds = REMOTE_TIMEOUT_SECONDS * 2;
2005 Slog.i(TAG, "Scheduling reset in " + nextResetSeconds + "s");
Zim7924a512020-01-15 15:23:54 +00002006 mHandler.removeMessages(H_RESET);
2007 mHandler.sendMessageDelayed(mHandler.obtainMessage(H_RESET),
Zimb8ca0542020-01-16 22:54:48 +00002008 TimeUnit.SECONDS.toMillis(nextResetSeconds));
Zim95eca1d2019-11-15 18:03:00 +00002009 return false;
Zim7924a512020-01-15 15:23:54 +00002010 } finally {
2011 try {
2012 pfd.close();
2013 } catch (Exception e) {
2014 Slog.e(TAG, "Failed to close FUSE device fd", e);
2015 }
Zim95eca1d2019-11-15 18:03:00 +00002016 }
2017 }
2018 });
Zim17be6f92019-09-25 14:37:55 +01002019 Slog.i(TAG, "Mounted volume " + vol);
Jeff Sharkeyace874b2017-09-07 15:27:33 -06002020 } catch (Exception e) {
2021 Slog.wtf(TAG, e);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07002022 }
2023 }
2024
2025 @Override
2026 public void unmount(String volId) {
2027 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07002028
Jeff Sharkeyef10ee02015-07-05 14:17:27 -07002029 final VolumeInfo vol = findVolumeByIdOrThrow(volId);
Sudheer Shanka3f0645b2018-09-18 13:07:59 -07002030 unmount(vol);
2031 }
2032
2033 private void unmount(VolumeInfo vol) {
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07002034 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002035 mVold.unmount(vol.id);
Zim17be6f92019-09-25 14:37:55 +01002036 mStorageSessionController.onVolumeUnmount(vol);
Ricky Wai4482ab52019-12-10 19:08:18 +00002037 try {
2038 if (vol.type == VolumeInfo.TYPE_PRIVATE) {
2039 mInstaller.onPrivateVolumeRemoved(vol.getFsUuid());
2040 }
2041 } catch (Installer.InstallerException e) {
2042 Slog.e(TAG, "Failed unmount mirror data", e);
2043 }
Jeff Sharkeyace874b2017-09-07 15:27:33 -06002044 } catch (Exception e) {
2045 Slog.wtf(TAG, e);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07002046 }
2047 }
2048
2049 @Override
2050 public void format(String volId) {
Jeff Sharkey48877892015-03-18 11:27:19 -07002051 enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);
San Mehat5b77dab2010-01-26 13:28:50 -08002052
Jeff Sharkeyef10ee02015-07-05 14:17:27 -07002053 final VolumeInfo vol = findVolumeByIdOrThrow(volId);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07002054 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002055 mVold.format(vol.id, "auto");
Jeff Sharkeyace874b2017-09-07 15:27:33 -06002056 } catch (Exception e) {
2057 Slog.wtf(TAG, e);
Jeff Sharkey48877892015-03-18 11:27:19 -07002058 }
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07002059 }
2060
2061 @Override
Jeff Sharkey7e19f532017-11-06 13:54:11 -07002062 public void benchmark(String volId, IVoldTaskListener listener) {
Jeff Sharkey9756d752015-05-14 21:07:42 -07002063 enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);
Jeff Sharkey9756d752015-05-14 21:07:42 -07002064
2065 try {
Jeff Sharkeyb302c542017-09-15 12:57:59 -06002066 mVold.benchmark(volId, new IVoldTaskListener.Stub() {
2067 @Override
2068 public void onStatus(int status, PersistableBundle extras) {
Jeff Sharkey7e19f532017-11-06 13:54:11 -07002069 dispatchOnStatus(listener, status, extras);
Jeff Sharkeyb302c542017-09-15 12:57:59 -06002070 }
2071
2072 @Override
2073 public void onFinished(int status, PersistableBundle extras) {
Jeff Sharkey7e19f532017-11-06 13:54:11 -07002074 dispatchOnFinished(listener, status, extras);
Jeff Sharkeyb302c542017-09-15 12:57:59 -06002075
2076 final String path = extras.getString("path");
2077 final String ident = extras.getString("ident");
2078 final long create = extras.getLong("create");
2079 final long run = extras.getLong("run");
2080 final long destroy = extras.getLong("destroy");
2081
2082 final DropBoxManager dropBox = mContext.getSystemService(DropBoxManager.class);
2083 dropBox.addText(TAG_STORAGE_BENCHMARK, scrubPath(path)
2084 + " " + ident + " " + create + " " + run + " " + destroy);
2085
2086 synchronized (mLock) {
2087 final VolumeRecord rec = findRecordForPath(path);
2088 if (rec != null) {
2089 rec.lastBenchMillis = System.currentTimeMillis();
2090 writeSettingsLocked();
2091 }
2092 }
2093 }
2094 });
Jeff Sharkey7e19f532017-11-06 13:54:11 -07002095 } catch (RemoteException e) {
2096 throw e.rethrowAsRuntimeException();
Jeff Sharkey9756d752015-05-14 21:07:42 -07002097 }
2098 }
2099
2100 @Override
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07002101 public void partitionPublic(String diskId) {
2102 enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07002103
Jeff Sharkeyeba260d2015-04-19 14:35:16 -07002104 final CountDownLatch latch = findOrCreateDiskScanLatch(diskId);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07002105 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002106 mVold.partition(diskId, IVold.PARTITION_TYPE_PUBLIC, -1);
Jeff Sharkeyedcdaf62015-07-09 09:45:36 -07002107 waitForLatch(latch, "partitionPublic", 3 * DateUtils.MINUTE_IN_MILLIS);
Jeff Sharkeyace874b2017-09-07 15:27:33 -06002108 } catch (Exception e) {
2109 Slog.wtf(TAG, e);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07002110 }
2111 }
2112
2113 @Override
2114 public void partitionPrivate(String diskId) {
2115 enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);
Amith Yamasani462ac3a2015-06-30 14:21:01 -07002116 enforceAdminUser();
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07002117
Jeff Sharkeyeba260d2015-04-19 14:35:16 -07002118 final CountDownLatch latch = findOrCreateDiskScanLatch(diskId);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07002119 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002120 mVold.partition(diskId, IVold.PARTITION_TYPE_PRIVATE, -1);
Jeff Sharkeyedcdaf62015-07-09 09:45:36 -07002121 waitForLatch(latch, "partitionPrivate", 3 * DateUtils.MINUTE_IN_MILLIS);
Jeff Sharkeyace874b2017-09-07 15:27:33 -06002122 } catch (Exception e) {
2123 Slog.wtf(TAG, e);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07002124 }
2125 }
2126
2127 @Override
2128 public void partitionMixed(String diskId, int ratio) {
2129 enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);
Amith Yamasani462ac3a2015-06-30 14:21:01 -07002130 enforceAdminUser();
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07002131
Jeff Sharkeyeba260d2015-04-19 14:35:16 -07002132 final CountDownLatch latch = findOrCreateDiskScanLatch(diskId);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07002133 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002134 mVold.partition(diskId, IVold.PARTITION_TYPE_MIXED, ratio);
Jeff Sharkeyedcdaf62015-07-09 09:45:36 -07002135 waitForLatch(latch, "partitionMixed", 3 * DateUtils.MINUTE_IN_MILLIS);
Jeff Sharkeyace874b2017-09-07 15:27:33 -06002136 } catch (Exception e) {
2137 Slog.wtf(TAG, e);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07002138 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002139 }
2140
Jeff Sharkey48877892015-03-18 11:27:19 -07002141 @Override
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07002142 public void setVolumeNickname(String fsUuid, String nickname) {
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07002143 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07002144
Daulet Zhanguzinea1a7ca2020-01-03 09:46:50 +00002145 Objects.requireNonNull(fsUuid);
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07002146 synchronized (mLock) {
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07002147 final VolumeRecord rec = mRecords.get(fsUuid);
2148 rec.nickname = nickname;
Jeff Sharkey50a05452015-04-29 11:24:52 -07002149 mCallbacks.notifyVolumeRecordChanged(rec);
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07002150 writeSettingsLocked();
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07002151 }
2152 }
2153
2154 @Override
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07002155 public void setVolumeUserFlags(String fsUuid, int flags, int mask) {
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07002156 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07002157
Daulet Zhanguzinea1a7ca2020-01-03 09:46:50 +00002158 Objects.requireNonNull(fsUuid);
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07002159 synchronized (mLock) {
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07002160 final VolumeRecord rec = mRecords.get(fsUuid);
2161 rec.userFlags = (rec.userFlags & ~mask) | (flags & mask);
Jeff Sharkey50a05452015-04-29 11:24:52 -07002162 mCallbacks.notifyVolumeRecordChanged(rec);
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07002163 writeSettingsLocked();
2164 }
2165 }
2166
2167 @Override
2168 public void forgetVolume(String fsUuid) {
2169 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07002170
Daulet Zhanguzinea1a7ca2020-01-03 09:46:50 +00002171 Objects.requireNonNull(fsUuid);
Jeff Sharkey5a9bb742015-11-03 10:15:57 -08002172
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07002173 synchronized (mLock) {
Jeff Sharkey5cc0df22015-06-17 19:44:05 -07002174 final VolumeRecord rec = mRecords.remove(fsUuid);
2175 if (rec != null && !TextUtils.isEmpty(rec.partGuid)) {
Jeff Sharkeydb4b6192017-10-24 11:08:50 -06002176 mHandler.obtainMessage(H_PARTITION_FORGET, rec).sendToTarget();
Jeff Sharkey5cc0df22015-06-17 19:44:05 -07002177 }
2178 mCallbacks.notifyVolumeForgotten(fsUuid);
Jeff Sharkey50a05452015-04-29 11:24:52 -07002179
2180 // If this had been primary storage, revert back to internal and
2181 // reset vold so we bind into new volume into place.
2182 if (Objects.equals(mPrimaryStorageUuid, fsUuid)) {
Jeff Sharkeyfced5342015-05-10 14:53:34 -07002183 mPrimaryStorageUuid = getDefaultPrimaryStorageUuid();
Jeff Sharkey5a9bb742015-11-03 10:15:57 -08002184 mHandler.obtainMessage(H_RESET).sendToTarget();
Jeff Sharkey50a05452015-04-29 11:24:52 -07002185 }
2186
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07002187 writeSettingsLocked();
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07002188 }
2189 }
2190
Jeff Sharkey7d2af542015-05-12 15:27:15 -07002191 @Override
2192 public void forgetAllVolumes() {
2193 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
Jeff Sharkey7d2af542015-05-12 15:27:15 -07002194
Jeff Sharkey50a05452015-04-29 11:24:52 -07002195 synchronized (mLock) {
2196 for (int i = 0; i < mRecords.size(); i++) {
2197 final String fsUuid = mRecords.keyAt(i);
Jeff Sharkey5cc0df22015-06-17 19:44:05 -07002198 final VolumeRecord rec = mRecords.valueAt(i);
2199 if (!TextUtils.isEmpty(rec.partGuid)) {
Jeff Sharkeydb4b6192017-10-24 11:08:50 -06002200 mHandler.obtainMessage(H_PARTITION_FORGET, rec).sendToTarget();
Jeff Sharkey5cc0df22015-06-17 19:44:05 -07002201 }
Jeff Sharkey50a05452015-04-29 11:24:52 -07002202 mCallbacks.notifyVolumeForgotten(fsUuid);
2203 }
Jeff Sharkey50a05452015-04-29 11:24:52 -07002204 mRecords.clear();
Jeff Sharkey50a05452015-04-29 11:24:52 -07002205
Jeff Sharkeyfced5342015-05-10 14:53:34 -07002206 if (!Objects.equals(StorageManager.UUID_PRIVATE_INTERNAL, mPrimaryStorageUuid)) {
2207 mPrimaryStorageUuid = getDefaultPrimaryStorageUuid();
2208 }
2209
2210 writeSettingsLocked();
Jeff Sharkey5a9bb742015-11-03 10:15:57 -08002211 mHandler.obtainMessage(H_RESET).sendToTarget();
Jeff Sharkey50a05452015-04-29 11:24:52 -07002212 }
2213 }
2214
Jeff Sharkeydb4b6192017-10-24 11:08:50 -06002215 private void forgetPartition(String partGuid, String fsUuid) {
Jeff Sharkey5cc0df22015-06-17 19:44:05 -07002216 try {
Jeff Sharkeydb4b6192017-10-24 11:08:50 -06002217 mVold.forgetPartition(partGuid, fsUuid);
Jeff Sharkeyace874b2017-09-07 15:27:33 -06002218 } catch (Exception e) {
2219 Slog.wtf(TAG, e);
Jeff Sharkey5cc0df22015-06-17 19:44:05 -07002220 }
2221 }
2222
Jeff Sharkey31d0b702016-11-21 14:16:53 -07002223 @Override
Jeff Sharkey7e19f532017-11-06 13:54:11 -07002224 public void fstrim(int flags, IVoldTaskListener listener) {
Jeff Sharkey31d0b702016-11-21 14:16:53 -07002225 enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);
Jeff Sharkey31d0b702016-11-21 14:16:53 -07002226
2227 try {
Sandeep Patil7d5c4912019-04-15 09:27:30 -07002228 // Block based checkpoint process runs fstrim. So, if checkpoint is in progress
2229 // (first boot after OTA), We skip idle maintenance and make sure the last
2230 // fstrim time is still updated. If file based checkpoints are used, we run
2231 // idle maintenance (GC + fstrim) regardless of checkpoint status.
2232 if (!needsCheckpoint() || !supportsBlockCheckpoint()) {
2233 mVold.fstrim(flags, new IVoldTaskListener.Stub() {
2234 @Override
2235 public void onStatus(int status, PersistableBundle extras) {
2236 dispatchOnStatus(listener, status, extras);
Jeff Sharkey7e19f532017-11-06 13:54:11 -07002237
Sandeep Patil7d5c4912019-04-15 09:27:30 -07002238 // Ignore trim failures
2239 if (status != 0) return;
Jeff Sharkeyb302c542017-09-15 12:57:59 -06002240
Sandeep Patil7d5c4912019-04-15 09:27:30 -07002241 final String path = extras.getString("path");
2242 final long bytes = extras.getLong("bytes");
2243 final long time = extras.getLong("time");
Jeff Sharkeyb302c542017-09-15 12:57:59 -06002244
Sandeep Patil7d5c4912019-04-15 09:27:30 -07002245 final DropBoxManager dropBox = mContext.getSystemService(DropBoxManager.class);
2246 dropBox.addText(TAG_STORAGE_TRIM, scrubPath(path) + " " + bytes + " " + time);
Jeff Sharkeyb302c542017-09-15 12:57:59 -06002247
Sandeep Patil7d5c4912019-04-15 09:27:30 -07002248 synchronized (mLock) {
2249 final VolumeRecord rec = findRecordForPath(path);
2250 if (rec != null) {
2251 rec.lastTrimMillis = System.currentTimeMillis();
2252 writeSettingsLocked();
2253 }
Jeff Sharkeyb302c542017-09-15 12:57:59 -06002254 }
2255 }
Jeff Sharkeyb302c542017-09-15 12:57:59 -06002256
Sandeep Patil7d5c4912019-04-15 09:27:30 -07002257 @Override
2258 public void onFinished(int status, PersistableBundle extras) {
2259 dispatchOnFinished(listener, status, extras);
Jeff Sharkey7e19f532017-11-06 13:54:11 -07002260
Sandeep Patil7d5c4912019-04-15 09:27:30 -07002261 // TODO: benchmark when desired
2262 }
2263 });
2264 } else {
2265 Slog.i(TAG, "Skipping fstrim - block based checkpoint in progress");
2266 }
Jeff Sharkey7e19f532017-11-06 13:54:11 -07002267 } catch (RemoteException e) {
2268 throw e.rethrowAsRuntimeException();
Jeff Sharkey31d0b702016-11-21 14:16:53 -07002269 }
2270 }
2271
Jin Qiana85b9912017-10-17 15:48:18 -07002272 void runIdleMaint(Runnable callback) {
2273 enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);
2274
2275 try {
Sandeep Patil7d5c4912019-04-15 09:27:30 -07002276 // Block based checkpoint process runs fstrim. So, if checkpoint is in progress
2277 // (first boot after OTA), We skip idle maintenance and make sure the last
2278 // fstrim time is still updated. If file based checkpoints are used, we run
2279 // idle maintenance (GC + fstrim) regardless of checkpoint status.
2280 if (!needsCheckpoint() || !supportsBlockCheckpoint()) {
2281 mVold.runIdleMaint(new IVoldTaskListener.Stub() {
2282 @Override
2283 public void onStatus(int status, PersistableBundle extras) {
2284 // Not currently used
Jin Qiana85b9912017-10-17 15:48:18 -07002285 }
Sandeep Patil7d5c4912019-04-15 09:27:30 -07002286 @Override
2287 public void onFinished(int status, PersistableBundle extras) {
2288 if (callback != null) {
2289 BackgroundThread.getHandler().post(callback);
2290 }
2291 }
2292 });
2293 } else {
2294 Slog.i(TAG, "Skipping idle maintenance - block based checkpoint in progress");
2295 }
Jin Qiana85b9912017-10-17 15:48:18 -07002296 } catch (Exception e) {
2297 Slog.wtf(TAG, e);
2298 }
2299 }
2300
2301 @Override
2302 public void runIdleMaintenance() {
2303 runIdleMaint(null);
2304 }
2305
2306 void abortIdleMaint(Runnable callback) {
2307 enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);
2308
2309 try {
2310 mVold.abortIdleMaint(new IVoldTaskListener.Stub() {
2311 @Override
2312 public void onStatus(int status, PersistableBundle extras) {
2313 // Not currently used
2314 }
2315 @Override
2316 public void onFinished(int status, PersistableBundle extras) {
2317 if (callback != null) {
2318 BackgroundThread.getHandler().post(callback);
2319 }
2320 }
2321 });
2322 } catch (Exception e) {
2323 Slog.wtf(TAG, e);
2324 }
2325 }
2326
2327 @Override
2328 public void abortIdleMaintenance() {
2329 abortIdleMaint(null);
2330 }
2331
Svet Ganov6ee871e2015-07-10 14:29:33 -07002332 private void remountUidExternalStorage(int uid, int mode) {
Zim4f1a24d2019-11-27 16:35:58 +00002333 if (uid == Process.SYSTEM_UID) {
2334 // No need to remount uid for system because it has all access anyways
2335 return;
2336 }
2337
Jeff Sharkey9527b222015-06-24 15:24:48 -07002338 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002339 mVold.remountUid(uid, mode);
Jeff Sharkeyace874b2017-09-07 15:27:33 -06002340 } catch (Exception e) {
2341 Slog.wtf(TAG, e);
Jeff Sharkey9527b222015-06-24 15:24:48 -07002342 }
2343 }
2344
2345 @Override
Jeff Sharkey4c099d02015-05-15 13:45:00 -07002346 public void setDebugFlags(int flags, int mask) {
2347 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
Jeff Sharkey4c099d02015-05-15 13:45:00 -07002348
Jeff Sharkeyba512352015-11-12 20:17:45 -08002349 if ((mask & StorageManager.DEBUG_EMULATE_FBE) != 0) {
Jeff Sharkey00455bf2016-11-04 14:45:24 -06002350 if (!EMULATE_FBE_SUPPORTED) {
2351 throw new IllegalStateException(
2352 "Emulation not supported on this device");
2353 }
Paul Lawrence20be5d62016-02-26 13:51:17 -08002354 if (StorageManager.isFileEncryptedNativeOnly()) {
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07002355 throw new IllegalStateException(
Jeff Sharkey00455bf2016-11-04 14:45:24 -06002356 "Emulation not supported on device with native FBE");
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07002357 }
Jeff Sharkey5a785162016-03-21 13:02:06 -06002358 if (mLockPatternUtils.isCredentialRequiredToDecrypt(false)) {
2359 throw new IllegalStateException(
2360 "Emulation requires disabling 'Secure start-up' in Settings > Security");
2361 }
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07002362
Jeff Sharkey1176e512016-02-29 17:01:26 -07002363 final long token = Binder.clearCallingIdentity();
2364 try {
2365 final boolean emulateFbe = (flags & StorageManager.DEBUG_EMULATE_FBE) != 0;
2366 SystemProperties.set(StorageManager.PROP_EMULATE_FBE, Boolean.toString(emulateFbe));
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07002367
Jeff Sharkey1176e512016-02-29 17:01:26 -07002368 // Perform hard reboot to kick policy into place
2369 mContext.getSystemService(PowerManager.class).reboot(null);
2370 } finally {
2371 Binder.restoreCallingIdentity(token);
2372 }
Jeff Sharkeyba512352015-11-12 20:17:45 -08002373 }
Jeff Sharkey4c099d02015-05-15 13:45:00 -07002374
Jeff Sharkey901c0422018-04-20 13:11:20 -06002375 if ((mask & (StorageManager.DEBUG_ADOPTABLE_FORCE_ON
2376 | StorageManager.DEBUG_ADOPTABLE_FORCE_OFF)) != 0) {
2377 final String value;
2378 if ((flags & StorageManager.DEBUG_ADOPTABLE_FORCE_ON) != 0) {
2379 value = "force_on";
2380 } else if ((flags & StorageManager.DEBUG_ADOPTABLE_FORCE_OFF) != 0) {
2381 value = "force_off";
2382 } else {
2383 value = "";
2384 }
Jeff Sharkeyba512352015-11-12 20:17:45 -08002385
Jeff Sharkey901c0422018-04-20 13:11:20 -06002386 final long token = Binder.clearCallingIdentity();
2387 try {
2388 SystemProperties.set(StorageManager.PROP_ADOPTABLE, value);
2389
2390 // Reset storage to kick new setting into place
Jeff Sharkeyba512352015-11-12 20:17:45 -08002391 mHandler.obtainMessage(H_RESET).sendToTarget();
Jeff Sharkey901c0422018-04-20 13:11:20 -06002392 } finally {
2393 Binder.restoreCallingIdentity(token);
Jeff Sharkeyba512352015-11-12 20:17:45 -08002394 }
Jeff Sharkey4c099d02015-05-15 13:45:00 -07002395 }
Jeff Sharkey33dd1562016-04-07 11:05:33 -06002396
2397 if ((mask & (StorageManager.DEBUG_SDCARDFS_FORCE_ON
2398 | StorageManager.DEBUG_SDCARDFS_FORCE_OFF)) != 0) {
2399 final String value;
2400 if ((flags & StorageManager.DEBUG_SDCARDFS_FORCE_ON) != 0) {
2401 value = "force_on";
2402 } else if ((flags & StorageManager.DEBUG_SDCARDFS_FORCE_OFF) != 0) {
2403 value = "force_off";
2404 } else {
2405 value = "";
2406 }
2407
2408 final long token = Binder.clearCallingIdentity();
2409 try {
2410 SystemProperties.set(StorageManager.PROP_SDCARDFS, value);
2411
2412 // Reset storage to kick new setting into place
2413 mHandler.obtainMessage(H_RESET).sendToTarget();
2414 } finally {
2415 Binder.restoreCallingIdentity(token);
2416 }
2417 }
Jeff Sharkeye53e2d92017-03-25 23:14:06 -06002418
2419 if ((mask & StorageManager.DEBUG_VIRTUAL_DISK) != 0) {
2420 final boolean enabled = (flags & StorageManager.DEBUG_VIRTUAL_DISK) != 0;
2421
2422 final long token = Binder.clearCallingIdentity();
2423 try {
2424 SystemProperties.set(StorageManager.PROP_VIRTUAL_DISK, Boolean.toString(enabled));
2425
2426 // Reset storage to kick new setting into place
2427 mHandler.obtainMessage(H_RESET).sendToTarget();
2428 } finally {
2429 Binder.restoreCallingIdentity(token);
2430 }
2431 }
Sudheer Shankabe0febe2018-11-07 18:24:37 -08002432
Jeff Sharkeyb0c363b22018-12-15 11:53:03 -07002433 if ((mask & (StorageManager.DEBUG_ISOLATED_STORAGE_FORCE_ON
2434 | StorageManager.DEBUG_ISOLATED_STORAGE_FORCE_OFF)) != 0) {
2435 final int value;
2436 if ((flags & StorageManager.DEBUG_ISOLATED_STORAGE_FORCE_ON) != 0) {
2437 value = 1;
2438 } else if ((flags & StorageManager.DEBUG_ISOLATED_STORAGE_FORCE_OFF) != 0) {
2439 value = -1;
2440 } else {
2441 value = 0;
2442 }
Sudheer Shankabe0febe2018-11-07 18:24:37 -08002443
2444 final long token = Binder.clearCallingIdentity();
2445 try {
Jeff Sharkeyb0c363b22018-12-15 11:53:03 -07002446 Settings.Global.putInt(mContext.getContentResolver(),
2447 Settings.Global.ISOLATED_STORAGE_LOCAL, value);
2448 refreshIsolatedStorageSettings();
Sudheer Shankabe0febe2018-11-07 18:24:37 -08002449
2450 // Perform hard reboot to kick policy into place
Jeff Sharkey36274992019-02-27 12:09:57 -07002451 mHandler.post(() -> {
2452 mContext.getSystemService(PowerManager.class).reboot(null);
2453 });
2454 } finally {
2455 Binder.restoreCallingIdentity(token);
2456 }
2457 }
Jeff Sharkey4c099d02015-05-15 13:45:00 -07002458 }
2459
2460 @Override
Jeff Sharkey275e3e42015-04-24 16:10:32 -07002461 public String getPrimaryStorageUuid() {
Jeff Sharkey620b32b2015-04-23 19:36:02 -07002462 synchronized (mLock) {
2463 return mPrimaryStorageUuid;
2464 }
2465 }
2466
2467 @Override
Jeff Sharkey275e3e42015-04-24 16:10:32 -07002468 public void setPrimaryStorageUuid(String volumeUuid, IPackageMoveObserver callback) {
2469 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
Jeff Sharkey620b32b2015-04-23 19:36:02 -07002470
Jeff Sharkeya31460c2016-06-22 09:04:33 -06002471 final VolumeInfo from;
2472 final VolumeInfo to;
2473
Jeff Sharkey275e3e42015-04-24 16:10:32 -07002474 synchronized (mLock) {
Jeff Sharkeyfced5342015-05-10 14:53:34 -07002475 if (Objects.equals(mPrimaryStorageUuid, volumeUuid)) {
2476 throw new IllegalArgumentException("Primary storage already at " + volumeUuid);
Jeff Sharkey275e3e42015-04-24 16:10:32 -07002477 }
2478
2479 if (mMoveCallback != null) {
2480 throw new IllegalStateException("Move already in progress");
2481 }
2482 mMoveCallback = callback;
2483 mMoveTargetUuid = volumeUuid;
2484
Jeff Sharkeya65e6492017-06-21 13:45:11 -06002485 // We need all the users unlocked to move their primary storage
2486 final List<UserInfo> users = mContext.getSystemService(UserManager.class).getUsers();
2487 for (UserInfo user : users) {
2488 if (StorageManager.isFileEncryptedNativeOrEmulated()
2489 && !isUserKeyUnlocked(user.id)) {
2490 Slog.w(TAG, "Failing move due to locked user " + user.id);
2491 onMoveStatusLocked(PackageManager.MOVE_FAILED_LOCKED_USER);
2492 return;
2493 }
2494 }
2495
Jeff Sharkeyfced5342015-05-10 14:53:34 -07002496 // When moving to/from primary physical volume, we probably just nuked
2497 // the current storage location, so we have nothing to move.
2498 if (Objects.equals(StorageManager.UUID_PRIMARY_PHYSICAL, mPrimaryStorageUuid)
2499 || Objects.equals(StorageManager.UUID_PRIMARY_PHYSICAL, volumeUuid)) {
2500 Slog.d(TAG, "Skipping move to/from primary physical");
2501 onMoveStatusLocked(MOVE_STATUS_COPY_FINISHED);
2502 onMoveStatusLocked(PackageManager.MOVE_SUCCEEDED);
Jeff Sharkey5a9bb742015-11-03 10:15:57 -08002503 mHandler.obtainMessage(H_RESET).sendToTarget();
Jeff Sharkeya31460c2016-06-22 09:04:33 -06002504 return;
Jeff Sharkeyfced5342015-05-10 14:53:34 -07002505
2506 } else {
Jeff Sharkeya31460c2016-06-22 09:04:33 -06002507 from = findStorageForUuid(mPrimaryStorageUuid);
2508 to = findStorageForUuid(volumeUuid);
Jeff Sharkeyef10ee02015-07-05 14:17:27 -07002509
2510 if (from == null) {
2511 Slog.w(TAG, "Failing move due to missing from volume " + mPrimaryStorageUuid);
2512 onMoveStatusLocked(PackageManager.MOVE_FAILED_INTERNAL_ERROR);
2513 return;
2514 } else if (to == null) {
2515 Slog.w(TAG, "Failing move due to missing to volume " + volumeUuid);
2516 onMoveStatusLocked(PackageManager.MOVE_FAILED_INTERNAL_ERROR);
2517 return;
2518 }
Jeff Sharkey275e3e42015-04-24 16:10:32 -07002519 }
Jeff Sharkey620b32b2015-04-23 19:36:02 -07002520 }
Jeff Sharkeya31460c2016-06-22 09:04:33 -06002521
2522 try {
Jeff Sharkeyb302c542017-09-15 12:57:59 -06002523 mVold.moveStorage(from.id, to.id, new IVoldTaskListener.Stub() {
2524 @Override
2525 public void onStatus(int status, PersistableBundle extras) {
2526 synchronized (mLock) {
2527 onMoveStatusLocked(status);
2528 }
2529 }
2530
2531 @Override
2532 public void onFinished(int status, PersistableBundle extras) {
2533 // Not currently used
2534 }
2535 });
Jeff Sharkeyace874b2017-09-07 15:27:33 -06002536 } catch (Exception e) {
2537 Slog.wtf(TAG, e);
Jeff Sharkeya31460c2016-06-22 09:04:33 -06002538 }
Jeff Sharkey620b32b2015-04-23 19:36:02 -07002539 }
2540
San Mehatb1043402010-02-05 08:26:50 -08002541 private void warnOnNotMounted() {
Jeff Sharkey48877892015-03-18 11:27:19 -07002542 synchronized (mLock) {
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07002543 for (int i = 0; i < mVolumes.size(); i++) {
2544 final VolumeInfo vol = mVolumes.valueAt(i);
Jeff Sharkey27de30d2015-04-18 16:20:27 -07002545 if (vol.isPrimary() && vol.isMountedWritable()) {
Jeff Sharkey48877892015-03-18 11:27:19 -07002546 // Cool beans, we have a mounted primary volume
2547 return;
2548 }
Jeff Sharkey32ee8312012-09-30 13:21:31 -07002549 }
San Mehatb1043402010-02-05 08:26:50 -08002550 }
Jeff Sharkey48877892015-03-18 11:27:19 -07002551
2552 Slog.w(TAG, "No primary storage mounted!");
San Mehatb1043402010-02-05 08:26:50 -08002553 }
2554
Kenny Roota02b8b02010-08-05 16:14:17 -07002555 private boolean isUidOwnerOfPackageOrSystem(String packageName, int callerUid) {
2556 if (callerUid == android.os.Process.SYSTEM_UID) {
2557 return true;
2558 }
2559
Kenny Root02c87302010-07-01 08:10:18 -07002560 if (packageName == null) {
2561 return false;
2562 }
2563
Jeff Sharkey5790af02018-08-13 17:42:54 -06002564 final int packageUid = mPmInternal.getPackageUid(packageName,
Jeff Sharkeycd654482016-01-08 17:42:11 -07002565 PackageManager.MATCH_DEBUG_TRIAGED_MISSING, UserHandle.getUserId(callerUid));
Kenny Root02c87302010-07-01 08:10:18 -07002566
2567 if (DEBUG_OBB) {
2568 Slog.d(TAG, "packageName = " + packageName + ", packageUid = " +
2569 packageUid + ", callerUid = " + callerUid);
2570 }
2571
2572 return callerUid == packageUid;
2573 }
2574
Jeff Sharkey54402792017-09-15 16:05:19 -06002575 @Override
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002576 public String getMountedObbPath(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
Kenny Root02c87302010-07-01 08:10:18 -07002579 warnOnNotMounted();
2580
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002581 final ObbState state;
Rubin Xucd7a0142015-04-17 23:45:27 +01002582 synchronized (mObbMounts) {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002583 state = mObbPathToStateMap.get(rawPath);
2584 }
2585 if (state == null) {
2586 Slog.w(TAG, "Failed to find OBB mounted at " + rawPath);
2587 return null;
2588 }
2589
Jeff Sharkey54402792017-09-15 16:05:19 -06002590 return findVolumeByIdOrThrow(state.volId).getPath().getAbsolutePath();
Kenny Root02c87302010-07-01 08:10:18 -07002591 }
2592
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002593 @Override
2594 public boolean isObbMounted(String rawPath) {
Daulet Zhanguzinea1a7ca2020-01-03 09:46:50 +00002595 Objects.requireNonNull(rawPath, "rawPath cannot be null");
Kenny Rootaf9d6672010-10-08 09:21:39 -07002596 synchronized (mObbMounts) {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002597 return mObbPathToStateMap.containsKey(rawPath);
Kenny Rootaf9d6672010-10-08 09:21:39 -07002598 }
Kenny Root02c87302010-07-01 08:10:18 -07002599 }
2600
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002601 @Override
Sudheer Shanka25469aa2018-08-27 15:50:23 -07002602 public void mountObb(String rawPath, String canonicalPath, String key,
2603 IObbActionListener token, int nonce, ObbInfo obbInfo) {
Daulet Zhanguzinea1a7ca2020-01-03 09:46:50 +00002604 Objects.requireNonNull(rawPath, "rawPath cannot be null");
2605 Objects.requireNonNull(canonicalPath, "canonicalPath cannot be null");
2606 Objects.requireNonNull(token, "token cannot be null");
2607 Objects.requireNonNull(obbInfo, "obbIfno cannot be null");
Kenny Rootaf9d6672010-10-08 09:21:39 -07002608
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002609 final int callingUid = Binder.getCallingUid();
Jeff Sharkey41cd6812017-09-11 10:32:17 -06002610 final ObbState obbState = new ObbState(rawPath, canonicalPath,
2611 callingUid, token, nonce, null);
Sudheer Shanka25469aa2018-08-27 15:50:23 -07002612 final ObbAction action = new MountObbAction(obbState, key, callingUid, obbInfo);
Kenny Roota02b8b02010-08-05 16:14:17 -07002613 mObbActionHandler.sendMessage(mObbActionHandler.obtainMessage(OBB_RUN_ACTION, action));
2614
2615 if (DEBUG_OBB)
2616 Slog.i(TAG, "Send to OBB handler: " + action.toString());
Kenny Root02c87302010-07-01 08:10:18 -07002617 }
2618
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002619 @Override
2620 public void unmountObb(String rawPath, boolean force, IObbActionListener token, int nonce) {
Daulet Zhanguzinea1a7ca2020-01-03 09:46:50 +00002621 Objects.requireNonNull(rawPath, "rawPath cannot be null");
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002622
2623 final ObbState existingState;
Rubin Xucd7a0142015-04-17 23:45:27 +01002624 synchronized (mObbMounts) {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002625 existingState = mObbPathToStateMap.get(rawPath);
Kenny Rootf1121dc2010-09-29 07:30:53 -07002626 }
2627
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002628 if (existingState != null) {
2629 // TODO: separate state object from request data
2630 final int callingUid = Binder.getCallingUid();
Jeff Sharkey41cd6812017-09-11 10:32:17 -06002631 final ObbState newState = new ObbState(rawPath, existingState.canonicalPath,
2632 callingUid, token, nonce, existingState.volId);
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002633 final ObbAction action = new UnmountObbAction(newState, force);
2634 mObbActionHandler.sendMessage(mObbActionHandler.obtainMessage(OBB_RUN_ACTION, action));
Kenny Root02c87302010-07-01 08:10:18 -07002635
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002636 if (DEBUG_OBB)
2637 Slog.i(TAG, "Send to OBB handler: " + action.toString());
2638 } else {
2639 Slog.w(TAG, "Unknown OBB mount at " + rawPath);
2640 }
Kenny Roota02b8b02010-08-05 16:14:17 -07002641 }
2642
Ben Komalo444eca22011-09-01 15:17:44 -07002643 @Override
2644 public int getEncryptionState() {
2645 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
2646 "no permission to access the crypt keeper");
2647
Ben Komalo444eca22011-09-01 15:17:44 -07002648 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002649 return mVold.fdeComplete();
2650 } catch (Exception e) {
2651 Slog.wtf(TAG, e);
Sudheer Shankaf7341142016-10-18 17:15:18 -07002652 return StorageManager.ENCRYPTION_STATE_ERROR_UNKNOWN;
Ben Komalo444eca22011-09-01 15:17:44 -07002653 }
2654 }
2655
2656 @Override
Jason parks5af0b912010-11-29 09:05:25 -06002657 public int decryptStorage(String password) {
Jason parks8888c592011-01-20 22:46:41 -06002658 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
2659 "no permission to access the crypt keeper");
Jason parks5af0b912010-11-29 09:05:25 -06002660
Jeff Sharkey8058fe62017-09-13 11:50:33 -06002661 if (TextUtils.isEmpty(password)) {
2662 throw new IllegalArgumentException("password cannot be empty");
2663 }
2664
Jason parks5af0b912010-11-29 09:05:25 -06002665 if (DEBUG_EVENTS) {
2666 Slog.i(TAG, "decrypting storage...");
2667 }
2668
2669 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002670 mVold.fdeCheckPassword(password);
2671 mHandler.postDelayed(() -> {
2672 try {
2673 mVold.fdeRestart();
2674 } catch (Exception e) {
2675 Slog.wtf(TAG, e);
2676 }
2677 }, DateUtils.SECOND_IN_MILLIS);
2678 return 0;
Paul Crowleyfc0b5192018-07-02 13:58:10 -07002679 } catch (ServiceSpecificException e) {
2680 Slog.e(TAG, "fdeCheckPassword failed", e);
2681 return e.errorCode;
Jeff Sharkey54402792017-09-15 16:05:19 -06002682 } catch (Exception e) {
2683 Slog.wtf(TAG, e);
2684 return StorageManager.ENCRYPTION_STATE_ERROR_UNKNOWN;
Jason parks5af0b912010-11-29 09:05:25 -06002685 }
Jason parks5af0b912010-11-29 09:05:25 -06002686 }
2687
Jeff Sharkey54402792017-09-15 16:05:19 -06002688 @Override
Paul Lawrence46791e72014-04-03 09:10:26 -07002689 public int encryptStorage(int type, String password) {
Jason parks8888c592011-01-20 22:46:41 -06002690 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
2691 "no permission to access the crypt keeper");
Jason parks56aa5322011-01-07 09:01:15 -06002692
Jeff Sharkey8058fe62017-09-13 11:50:33 -06002693 if (type == StorageManager.CRYPT_TYPE_DEFAULT) {
2694 password = "";
2695 } else if (TextUtils.isEmpty(password)) {
2696 throw new IllegalArgumentException("password cannot be empty");
2697 }
2698
Jason parks56aa5322011-01-07 09:01:15 -06002699 if (DEBUG_EVENTS) {
Jason parks8888c592011-01-20 22:46:41 -06002700 Slog.i(TAG, "encrypting storage...");
Jason parks56aa5322011-01-07 09:01:15 -06002701 }
2702
2703 try {
Paul Lawrence89a0ae42017-12-22 10:11:10 -08002704 mVold.fdeEnable(type, password, 0);
Jeff Sharkey43e12112017-09-12 16:31:45 -06002705 } catch (Exception e) {
2706 Slog.wtf(TAG, e);
2707 return -1;
Jason parks56aa5322011-01-07 09:01:15 -06002708 }
2709
2710 return 0;
2711 }
2712
Paul Lawrence8e397362014-01-27 15:22:30 -08002713 /** Set the password for encrypting the master key.
2714 * @param type One of the CRYPTO_TYPE_XXX consts defined in StorageManager.
2715 * @param password The password to set.
2716 */
Jeff Sharkey54402792017-09-15 16:05:19 -06002717 @Override
Paul Lawrence8e397362014-01-27 15:22:30 -08002718 public int changeEncryptionPassword(int type, String password) {
Jason parksf7b3cd42011-01-27 09:28:25 -06002719 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
2720 "no permission to access the crypt keeper");
2721
Jeff Sharkeyae266462017-11-27 13:32:24 -07002722 if (StorageManager.isFileEncryptedNativeOnly()) {
2723 // Not supported on FBE devices
2724 return -1;
2725 }
2726
Jeff Sharkey8058fe62017-09-13 11:50:33 -06002727 if (type == StorageManager.CRYPT_TYPE_DEFAULT) {
2728 password = "";
2729 } else if (TextUtils.isEmpty(password)) {
2730 throw new IllegalArgumentException("password cannot be empty");
2731 }
2732
Jason parksf7b3cd42011-01-27 09:28:25 -06002733 if (DEBUG_EVENTS) {
2734 Slog.i(TAG, "changing encryption password...");
2735 }
2736
2737 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002738 mVold.fdeChangePassword(type, password);
2739 return 0;
2740 } catch (Exception e) {
2741 Slog.wtf(TAG, e);
2742 return -1;
Jason parksf7b3cd42011-01-27 09:28:25 -06002743 }
2744 }
2745
Christopher Tate32418be2011-10-10 13:51:12 -07002746 /**
2747 * Validate a user-supplied password string with cryptfs
2748 */
2749 @Override
2750 public int verifyEncryptionPassword(String password) throws RemoteException {
2751 // Only the system process is permitted to validate passwords
2752 if (Binder.getCallingUid() != android.os.Process.SYSTEM_UID) {
2753 throw new SecurityException("no permission to access the crypt keeper");
2754 }
2755
2756 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
2757 "no permission to access the crypt keeper");
2758
2759 if (TextUtils.isEmpty(password)) {
2760 throw new IllegalArgumentException("password cannot be empty");
2761 }
2762
Christopher Tate32418be2011-10-10 13:51:12 -07002763 if (DEBUG_EVENTS) {
2764 Slog.i(TAG, "validating encryption password...");
2765 }
2766
2767 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002768 mVold.fdeVerifyPassword(password);
2769 return 0;
2770 } catch (Exception e) {
2771 Slog.wtf(TAG, e);
2772 return -1;
Christopher Tate32418be2011-10-10 13:51:12 -07002773 }
2774 }
2775
Paul Lawrence8e397362014-01-27 15:22:30 -08002776 /**
2777 * Get the type of encryption used to encrypt the master key.
2778 * @return The type, one of the CRYPT_TYPE_XXX consts from StorageManager.
2779 */
2780 @Override
Svetoslav16e4a1a2014-09-29 18:16:20 -07002781 public int getPasswordType() {
Paul Lawrence76a40572017-03-15 11:08:04 -07002782 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
Paul Lawrence9de713d2016-05-02 22:45:33 +00002783 "no permission to access the crypt keeper");
2784
Paul Lawrence8e397362014-01-27 15:22:30 -08002785 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002786 return mVold.fdeGetPasswordType();
2787 } catch (Exception e) {
2788 Slog.wtf(TAG, e);
2789 return -1;
Paul Lawrence8e397362014-01-27 15:22:30 -08002790 }
2791 }
2792
Paul Lawrencee51dcf92014-03-18 10:56:00 -07002793 /**
2794 * Set a field in the crypto header.
2795 * @param field field to set
2796 * @param contents contents to set in field
2797 */
2798 @Override
2799 public void setField(String field, String contents) throws RemoteException {
Paul Lawrence76a40572017-03-15 11:08:04 -07002800 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
Paul Lawrence0bbd1082016-04-26 15:21:02 -07002801 "no permission to access the crypt keeper");
Paul Lawrencee51dcf92014-03-18 10:56:00 -07002802
yusukes14a8b1f2018-07-23 17:34:42 -07002803 if (!StorageManager.isBlockEncrypted()) {
2804 // Only supported on FDE devices
Jeff Sharkeyae266462017-11-27 13:32:24 -07002805 return;
2806 }
2807
Paul Lawrencee51dcf92014-03-18 10:56:00 -07002808 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002809 mVold.fdeSetField(field, contents);
2810 return;
2811 } catch (Exception e) {
2812 Slog.wtf(TAG, e);
2813 return;
Paul Lawrencee51dcf92014-03-18 10:56:00 -07002814 }
2815 }
2816
2817 /**
2818 * Gets a field from the crypto header.
2819 * @param field field to get
2820 * @return contents of field
2821 */
2822 @Override
2823 public String getField(String field) throws RemoteException {
Paul Lawrence76a40572017-03-15 11:08:04 -07002824 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
Paul Lawrence0bbd1082016-04-26 15:21:02 -07002825 "no permission to access the crypt keeper");
Paul Lawrencee51dcf92014-03-18 10:56:00 -07002826
yusukes14a8b1f2018-07-23 17:34:42 -07002827 if (!StorageManager.isBlockEncrypted()) {
2828 // Only supported on FDE devices
Jeff Sharkeyae266462017-11-27 13:32:24 -07002829 return null;
2830 }
2831
Paul Lawrencee51dcf92014-03-18 10:56:00 -07002832 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002833 return mVold.fdeGetField(field);
2834 } catch (Exception e) {
2835 Slog.wtf(TAG, e);
2836 return null;
Paul Lawrencee51dcf92014-03-18 10:56:00 -07002837 }
2838 }
2839
Paul Lawrence3806d9c2015-10-29 10:30:46 -07002840 /**
2841 * Is userdata convertible to file based encryption?
2842 * @return non zero for convertible
2843 */
2844 @Override
2845 public boolean isConvertibleToFBE() throws RemoteException {
Paul Lawrence76a40572017-03-15 11:08:04 -07002846 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
Paul Lawrence0bbd1082016-04-26 15:21:02 -07002847 "no permission to access the crypt keeper");
Paul Lawrence3806d9c2015-10-29 10:30:46 -07002848
Paul Lawrence3806d9c2015-10-29 10:30:46 -07002849 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002850 return mVold.isConvertibleToFbe();
2851 } catch (Exception e) {
2852 Slog.wtf(TAG, e);
2853 return false;
Paul Lawrence3806d9c2015-10-29 10:30:46 -07002854 }
2855 }
2856
Daniel Rosenberge129e5c2018-11-07 19:25:55 -08002857 /**
Martijn Coenenf04aca42019-03-11 10:35:34 +01002858 * Check whether the device supports filesystem checkpointing.
2859 *
2860 * @return true if the device supports filesystem checkpointing, false otherwise.
2861 */
2862 @Override
2863 public boolean supportsCheckpoint() throws RemoteException {
Martijn Coenenf04aca42019-03-11 10:35:34 +01002864 return mVold.supportsCheckpoint();
2865 }
2866
2867 /**
2868 * Signal that checkpointing partitions should start a checkpoint on the next boot.
2869 *
2870 * @param numTries Number of times to try booting in checkpoint mode, before we will boot
2871 * non-checkpoint mode and commit all changes immediately. Callers are
2872 * responsible for ensuring that boot is safe (eg, by rolling back updates).
2873 */
2874 @Override
2875 public void startCheckpoint(int numTries) throws RemoteException {
Nikita Ioffe6d749422020-01-14 22:19:01 +00002876 // Only the root, system_server and shell processes are permitted to start checkpoints
2877 final int callingUid = Binder.getCallingUid();
2878 if (callingUid != Process.SYSTEM_UID && callingUid != Process.ROOT_UID
2879 && callingUid != Process.SHELL_UID) {
Martijn Coenenf04aca42019-03-11 10:35:34 +01002880 throw new SecurityException("no permission to start filesystem checkpoint");
2881 }
2882
2883 mVold.startCheckpoint(numTries);
2884 }
2885
2886 /**
Daniel Rosenberge129e5c2018-11-07 19:25:55 -08002887 * Signal that checkpointing partitions should commit changes
2888 */
2889 @Override
2890 public void commitChanges() throws RemoteException {
2891 // Only the system process is permitted to commit checkpoints
2892 if (Binder.getCallingUid() != android.os.Process.SYSTEM_UID) {
2893 throw new SecurityException("no permission to commit checkpoint changes");
2894 }
2895
2896 mVold.commitChanges();
2897 }
2898
Daniel Rosenberge3a924d2019-03-19 18:19:08 -07002899 /**
2900 * Check if we should be mounting with checkpointing or are checkpointing now
2901 */
2902 @Override
2903 public boolean needsCheckpoint() throws RemoteException {
Paul Lawrence15a54462019-04-30 11:14:25 -07002904 enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);
Daniel Rosenberge3a924d2019-03-19 18:19:08 -07002905 return mVold.needsCheckpoint();
2906 }
2907
Daniel Rosenberg600799b2019-03-20 17:42:50 -07002908 /**
2909 * Abort the current set of changes and either try again, or abort entirely
2910 */
2911 @Override
2912 public void abortChanges(String message, boolean retry) throws RemoteException {
2913 // Only the system process is permitted to abort checkpoints
2914 if (Binder.getCallingUid() != android.os.Process.SYSTEM_UID) {
2915 throw new SecurityException("no permission to commit checkpoint changes");
2916 }
2917
2918 mVold.abortChanges(message, retry);
2919 }
2920
Jeff Sharkeyb049e212012-09-07 23:16:01 -07002921 @Override
Paul Lawrence945490c2014-03-27 16:37:28 +00002922 public String getPassword() throws RemoteException {
Paul Lawrence76a40572017-03-15 11:08:04 -07002923 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
Rubin Xucd7a0142015-04-17 23:45:27 +01002924 "only keyguard can retrieve password");
Paul Lawrence0bbd1082016-04-26 15:21:02 -07002925
Paul Lawrence945490c2014-03-27 16:37:28 +00002926 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002927 return mVold.fdeGetPassword();
2928 } catch (Exception e) {
2929 Slog.wtf(TAG, e);
Paul Lawrence24063b52015-01-06 13:11:23 -08002930 return null;
Paul Lawrence945490c2014-03-27 16:37:28 +00002931 }
2932 }
2933
2934 @Override
2935 public void clearPassword() throws RemoteException {
Paul Lawrence76a40572017-03-15 11:08:04 -07002936 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
Paul Lawrence0bbd1082016-04-26 15:21:02 -07002937 "only keyguard can clear password");
2938
Paul Lawrence945490c2014-03-27 16:37:28 +00002939 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002940 mVold.fdeClearPassword();
2941 return;
2942 } catch (Exception e) {
2943 Slog.wtf(TAG, e);
2944 return;
Paul Lawrence945490c2014-03-27 16:37:28 +00002945 }
2946 }
2947
2948 @Override
Lenka Trochtovac4dd0212015-11-18 12:22:06 +01002949 public void createUserKey(int userId, int serialNumber, boolean ephemeral) {
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002950 enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
Paul Crowleybcf48ed2015-04-22 13:36:59 +01002951
Paul Crowleybcf48ed2015-04-22 13:36:59 +01002952 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002953 mVold.createUserKey(userId, serialNumber, ephemeral);
Jeff Sharkey43e12112017-09-12 16:31:45 -06002954 } catch (Exception e) {
2955 Slog.wtf(TAG, e);
Paul Crowleybcf48ed2015-04-22 13:36:59 +01002956 }
2957 }
2958
Paul Crowley7ec733f2015-05-19 12:42:00 +01002959 @Override
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002960 public void destroyUserKey(int userId) {
2961 enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
Paul Crowley7ec733f2015-05-19 12:42:00 +01002962
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002963 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002964 mVold.destroyUserKey(userId);
Jeff Sharkey43e12112017-09-12 16:31:45 -06002965 } catch (Exception e) {
2966 Slog.wtf(TAG, e);
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002967 }
2968 }
2969
Jeff Sharkey43e12112017-09-12 16:31:45 -06002970 private String encodeBytes(byte[] bytes) {
Paul Crowleyfaeb3eb2016-02-08 15:58:29 +00002971 if (ArrayUtils.isEmpty(bytes)) {
Jeff Sharkey43e12112017-09-12 16:31:45 -06002972 return "!";
Paul Crowleyfaeb3eb2016-02-08 15:58:29 +00002973 } else {
Jeff Sharkey43e12112017-09-12 16:31:45 -06002974 return HexDump.toHexString(bytes);
Paul Crowleyfaeb3eb2016-02-08 15:58:29 +00002975 }
2976 }
2977
Paul Crowleycc701552016-05-17 14:18:49 -07002978 /*
2979 * Add this token/secret pair to the set of ways we can recover a disk encryption key.
2980 * Changing the token/secret for a disk encryption key is done in two phases: first, adding
2981 * a new token/secret pair with this call, then delting all other pairs with
2982 * fixateNewestUserKeyAuth. This allows other places where a credential is used, such as
2983 * Gatekeeper, to be updated between the two calls.
2984 */
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002985 @Override
Paul Crowleycc701552016-05-17 14:18:49 -07002986 public void addUserKeyAuth(int userId, int serialNumber, byte[] token, byte[] secret) {
Paul Crowleyfaeb3eb2016-02-08 15:58:29 +00002987 enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
Paul Crowleyfaeb3eb2016-02-08 15:58:29 +00002988
2989 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002990 mVold.addUserKeyAuth(userId, serialNumber, encodeBytes(token), encodeBytes(secret));
Jeff Sharkey43e12112017-09-12 16:31:45 -06002991 } catch (Exception e) {
2992 Slog.wtf(TAG, e);
Paul Crowleycc701552016-05-17 14:18:49 -07002993 }
2994 }
2995
2996 /*
Barani Muthukumaran9ba99ed2019-12-18 00:36:06 -08002997 * Clear disk encryption key bound to the associated token / secret pair. Removing the user
2998 * binding of the Disk encryption key is done in two phases: first, this call will retrieve
2999 * the disk encryption key using the provided token / secret pair and store it by
3000 * encrypting it with a keymaster key not bound to the user, then fixateNewestUserKeyAuth
3001 * is called to delete all other bindings of the disk encryption key.
3002 */
3003 @Override
3004 public void clearUserKeyAuth(int userId, int serialNumber, byte[] token, byte[] secret) {
3005 enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
3006
3007 try {
3008 mVold.clearUserKeyAuth(userId, serialNumber, encodeBytes(token), encodeBytes(secret));
3009 } catch (Exception e) {
3010 Slog.wtf(TAG, e);
3011 }
3012 }
3013
3014 /*
Paul Crowleycc701552016-05-17 14:18:49 -07003015 * Delete all disk encryption token/secret pairs except the most recently added one
3016 */
3017 @Override
3018 public void fixateNewestUserKeyAuth(int userId) {
3019 enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
Paul Crowleycc701552016-05-17 14:18:49 -07003020
3021 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06003022 mVold.fixateNewestUserKeyAuth(userId);
Jeff Sharkey43e12112017-09-12 16:31:45 -06003023 } catch (Exception e) {
3024 Slog.wtf(TAG, e);
Paul Crowleyfaeb3eb2016-02-08 15:58:29 +00003025 }
3026 }
3027
3028 @Override
3029 public void unlockUserKey(int userId, int serialNumber, byte[] token, byte[] secret) {
Sudheer Shanka03b20ec2019-02-21 15:11:00 -08003030 Slog.d(TAG, "unlockUserKey: " + userId);
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08003031 enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08003032
Jeff Sharkeyce18c812016-04-27 16:00:41 -06003033 if (StorageManager.isFileEncryptedNativeOrEmulated()) {
Jeff Sharkeyce18c812016-04-27 16:00:41 -06003034 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06003035 mVold.unlockUserKey(userId, serialNumber, encodeBytes(token),
3036 encodeBytes(secret));
Jeff Sharkey43e12112017-09-12 16:31:45 -06003037 } catch (Exception e) {
3038 Slog.wtf(TAG, e);
3039 return;
Jeff Sharkeyce18c812016-04-27 16:00:41 -06003040 }
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08003041 }
3042
3043 synchronized (mLock) {
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07003044 mLocalUnlockedUsers = ArrayUtils.appendInt(mLocalUnlockedUsers, userId);
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08003045 }
3046 }
3047
3048 @Override
3049 public void lockUserKey(int userId) {
3050 enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08003051
3052 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06003053 mVold.lockUserKey(userId);
Jeff Sharkey43e12112017-09-12 16:31:45 -06003054 } catch (Exception e) {
3055 Slog.wtf(TAG, e);
3056 return;
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08003057 }
3058
3059 synchronized (mLock) {
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07003060 mLocalUnlockedUsers = ArrayUtils.removeInt(mLocalUnlockedUsers, userId);
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08003061 }
3062 }
3063
3064 @Override
3065 public boolean isUserKeyUnlocked(int userId) {
Jeff Sharkeyce18c812016-04-27 16:00:41 -06003066 synchronized (mLock) {
3067 return ArrayUtils.contains(mLocalUnlockedUsers, userId);
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08003068 }
3069 }
3070
Narayan Kamath157dd1d2019-06-12 13:06:30 +01003071 private boolean isSystemUnlocked(int userId) {
3072 synchronized (mLock) {
3073 return ArrayUtils.contains(mSystemUnlockedUsers, userId);
3074 }
3075 }
3076
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08003077 @Override
Jeff Sharkey47f71082016-02-01 17:03:54 -07003078 public void prepareUserStorage(String volumeUuid, int userId, int serialNumber, int flags) {
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08003079 enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08003080
3081 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06003082 mVold.prepareUserStorage(volumeUuid, userId, serialNumber, flags);
Jeff Sharkey43e12112017-09-12 16:31:45 -06003083 } catch (Exception e) {
3084 Slog.wtf(TAG, e);
Paul Crowley7ec733f2015-05-19 12:42:00 +01003085 }
3086 }
3087
Paul Crowleybcf48ed2015-04-22 13:36:59 +01003088 @Override
Jeff Sharkeyfcf1e552016-04-14 20:44:58 -06003089 public void destroyUserStorage(String volumeUuid, int userId, int flags) {
3090 enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
Jeff Sharkeyfcf1e552016-04-14 20:44:58 -06003091
3092 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06003093 mVold.destroyUserStorage(volumeUuid, userId, flags);
Jeff Sharkey43e12112017-09-12 16:31:45 -06003094 } catch (Exception e) {
3095 Slog.wtf(TAG, e);
Jeff Sharkeyfcf1e552016-04-14 20:44:58 -06003096 }
3097 }
3098
Anton Hanssonbe9c9902019-05-28 13:45:26 +01003099 /** Not thread safe */
Daichi Hironoe56740d2017-02-02 13:56:45 +09003100 class AppFuseMountScope extends AppFuseBridge.MountScope {
Anton Hanssonbe9c9902019-05-28 13:45:26 +01003101 private boolean mMounted = false;
Daichi Hirono812c95d2017-02-08 16:20:20 +09003102
Ryo Hashimoto38bcbf02018-05-16 18:20:37 +09003103 public AppFuseMountScope(int uid, int mountId) {
3104 super(uid, mountId);
Daichi Hirono812c95d2017-02-08 16:20:20 +09003105 }
3106
3107 @Override
3108 public ParcelFileDescriptor open() throws NativeDaemonConnectorException {
Jeff Sharkey54402792017-09-15 16:05:19 -06003109 try {
Anton Hanssonbe9c9902019-05-28 13:45:26 +01003110 final FileDescriptor fd = mVold.mountAppFuse(uid, mountId);
3111 mMounted = true;
3112 return new ParcelFileDescriptor(fd);
Jeff Sharkey54402792017-09-15 16:05:19 -06003113 } catch (Exception e) {
3114 throw new NativeDaemonConnectorException("Failed to mount", e);
Daichi Hirono812c95d2017-02-08 16:20:20 +09003115 }
Daichi Hirono9fb00182016-11-08 14:12:17 +09003116 }
3117
3118 @Override
Ryo Hashimoto38bcbf02018-05-16 18:20:37 +09003119 public ParcelFileDescriptor openFile(int mountId, int fileId, int flags)
3120 throws NativeDaemonConnectorException {
3121 try {
3122 return new ParcelFileDescriptor(
3123 mVold.openAppFuseFile(uid, mountId, fileId, flags));
3124 } catch (Exception e) {
3125 throw new NativeDaemonConnectorException("Failed to open", e);
3126 }
3127 }
3128
3129 @Override
Daichi Hironoe56740d2017-02-02 13:56:45 +09003130 public void close() throws Exception {
Anton Hanssonbe9c9902019-05-28 13:45:26 +01003131 if (mMounted) {
Ryo Hashimoto38bcbf02018-05-16 18:20:37 +09003132 mVold.unmountAppFuse(uid, mountId);
Anton Hanssonbe9c9902019-05-28 13:45:26 +01003133 mMounted = false;
Daichi Hirono812c95d2017-02-08 16:20:20 +09003134 }
Daichi Hirono9fb00182016-11-08 14:12:17 +09003135 }
3136 }
3137
3138 @Override
Daichi Hirono812c95d2017-02-08 16:20:20 +09003139 public @Nullable AppFuseMount mountProxyFileDescriptorBridge() {
Daichi Hironoe56740d2017-02-02 13:56:45 +09003140 Slog.v(TAG, "mountProxyFileDescriptorBridge");
Daichi Hirono9fb00182016-11-08 14:12:17 +09003141 final int uid = Binder.getCallingUid();
Daichi Hirono9fb00182016-11-08 14:12:17 +09003142
Daichi Hironoe56740d2017-02-02 13:56:45 +09003143 while (true) {
3144 synchronized (mAppFuseLock) {
3145 boolean newlyCreated = false;
3146 if (mAppFuseBridge == null) {
3147 mAppFuseBridge = new AppFuseBridge();
3148 new Thread(mAppFuseBridge, AppFuseBridge.TAG).start();
3149 newlyCreated = true;
Daichi Hirono9fb00182016-11-08 14:12:17 +09003150 }
Daichi Hironoe56740d2017-02-02 13:56:45 +09003151 try {
3152 final int name = mNextAppFuseName++;
3153 try {
3154 return new AppFuseMount(
Ryo Hashimoto38bcbf02018-05-16 18:20:37 +09003155 name, mAppFuseBridge.addBridge(new AppFuseMountScope(uid, name)));
Daichi Hirono812c95d2017-02-08 16:20:20 +09003156 } catch (FuseUnavailableMountException e) {
Daichi Hironoe56740d2017-02-02 13:56:45 +09003157 if (newlyCreated) {
3158 // If newly created bridge fails, it's a real error.
Daichi Hirono812c95d2017-02-08 16:20:20 +09003159 Slog.e(TAG, "", e);
3160 return null;
Daichi Hironoe56740d2017-02-02 13:56:45 +09003161 }
3162 // It seems the thread of mAppFuseBridge has already been terminated.
3163 mAppFuseBridge = null;
3164 }
3165 } catch (NativeDaemonConnectorException e) {
3166 throw e.rethrowAsParcelableException();
3167 }
Daichi Hirono9fb00182016-11-08 14:12:17 +09003168 }
Daichi Hirono9fb00182016-11-08 14:12:17 +09003169 }
3170 }
3171
3172 @Override
Daichi Hirono812c95d2017-02-08 16:20:20 +09003173 public @Nullable ParcelFileDescriptor openProxyFileDescriptor(
3174 int mountId, int fileId, int mode) {
3175 Slog.v(TAG, "mountProxyFileDescriptor");
Jeff Sharkey39466322018-12-05 19:19:52 -07003176
3177 // We only support a narrow set of incoming mode flags
Jeff Sharkey3b1c2542018-12-13 15:01:38 -07003178 mode &= MODE_READ_WRITE;
Jeff Sharkey39466322018-12-05 19:19:52 -07003179
Daichi Hirono9fb00182016-11-08 14:12:17 +09003180 try {
3181 synchronized (mAppFuseLock) {
Daichi Hironoe56740d2017-02-02 13:56:45 +09003182 if (mAppFuseBridge == null) {
Daichi Hirono812c95d2017-02-08 16:20:20 +09003183 Slog.e(TAG, "FuseBridge has not been created");
3184 return null;
Daichi Hirono9fb00182016-11-08 14:12:17 +09003185 }
Ryo Hashimoto38bcbf02018-05-16 18:20:37 +09003186 return mAppFuseBridge.openFile(mountId, fileId, mode);
Daichi Hirono9fb00182016-11-08 14:12:17 +09003187 }
Daichi Hirono812c95d2017-02-08 16:20:20 +09003188 } catch (FuseUnavailableMountException | InterruptedException error) {
3189 Slog.v(TAG, "The mount point has already been invalid", error);
3190 return null;
Daichi Hirono9fb00182016-11-08 14:12:17 +09003191 }
3192 }
3193
Daichi Hirono9e8d9e22015-11-13 14:37:00 +09003194 @Override
Jeff Sharkeyae266462017-11-27 13:32:24 -07003195 public void mkdirs(String callingPkg, String appPath) {
Sudheer Shankaa63bfb32019-02-28 11:15:58 -08003196 final int callingUid = Binder.getCallingUid();
3197 final int userId = UserHandle.getUserId(callingUid);
Farid Zare Seisanac094512018-04-02 15:06:13 -07003198 final String propertyName = "sys.user." + userId + ".ce_available";
Jeff Sharkey2d8b4e82013-09-17 17:30:33 -07003199
Jeff Sharkey196c7552018-03-26 15:56:50 -06003200 // Ignore requests to create directories while storage is locked
Farid Zare Seisanac094512018-04-02 15:06:13 -07003201 if (!isUserKeyUnlocked(userId)) {
3202 throw new IllegalStateException("Failed to prepare " + appPath);
3203 }
3204
3205 // Ignore requests to create directories if CE storage is not available
Farid Zare Seisan7f6b8122018-03-30 11:19:10 -07003206 if ((userId == UserHandle.USER_SYSTEM)
3207 && !SystemProperties.getBoolean(propertyName, false)) {
Farid Zare Seisanac094512018-04-02 15:06:13 -07003208 throw new IllegalStateException("Failed to prepare " + appPath);
3209 }
Jeff Sharkey196c7552018-03-26 15:56:50 -06003210
Jeff Sharkey2d8b4e82013-09-17 17:30:33 -07003211 // Validate that reported package name belongs to caller
3212 final AppOpsManager appOps = (AppOpsManager) mContext.getSystemService(
3213 Context.APP_OPS_SERVICE);
Sudheer Shankaa63bfb32019-02-28 11:15:58 -08003214 appOps.checkPackage(callingUid, callingPkg);
Jeff Sharkey2d8b4e82013-09-17 17:30:33 -07003215
Jeff Sharkey48877892015-03-18 11:27:19 -07003216 File appFile = null;
Jeff Sharkey2d8b4e82013-09-17 17:30:33 -07003217 try {
Jeff Sharkey48877892015-03-18 11:27:19 -07003218 appFile = new File(appPath).getCanonicalFile();
Jeff Sharkey2d8b4e82013-09-17 17:30:33 -07003219 } catch (IOException e) {
Jeff Sharkeyae266462017-11-27 13:32:24 -07003220 throw new IllegalStateException("Failed to resolve " + appPath + ": " + e);
Jeff Sharkey2d8b4e82013-09-17 17:30:33 -07003221 }
3222
Martijn Coenen9fd2b642019-12-24 13:04:36 +01003223 appPath = appFile.getAbsolutePath();
3224 if (!appPath.endsWith("/")) {
3225 appPath = appPath + "/";
3226 }
3227 // Ensure that the path we're asked to create is a known application directory
3228 // path.
3229 final Matcher matcher = KNOWN_APP_DIR_PATHS.matcher(appPath);
3230 if (matcher.matches()) {
3231 // And that the package dir matches the calling package
3232 if (!matcher.group(3).equals(callingPkg)) {
3233 throw new SecurityException("Invalid mkdirs path: " + appFile
3234 + " does not contain calling package " + callingPkg);
Jeff Sharkey48877892015-03-18 11:27:19 -07003235 }
Martijn Coenen9fd2b642019-12-24 13:04:36 +01003236 // And that the user id part of the path (if any) matches the calling user id,
3237 // or if for a public volume (no user id), the user matches the current user
3238 if ((matcher.group(2) != null && !matcher.group(2).equals(Integer.toString(userId)))
3239 || (matcher.group(2) == null && userId != mCurrentUserId)) {
3240 throw new SecurityException("Invalid mkdirs path: " + appFile
3241 + " does not match calling user id " + userId);
3242 }
Jeff Sharkey2d8b4e82013-09-17 17:30:33 -07003243 try {
Martijn Coenen9fd2b642019-12-24 13:04:36 +01003244 mVold.setupAppDir(appPath, matcher.group(1), callingUid);
3245 } catch (RemoteException e) {
Sudheer Shanka64501e52019-04-29 10:46:26 -07003246 throw new IllegalStateException("Failed to prepare " + appPath + ": " + e);
Jeff Sharkey2d8b4e82013-09-17 17:30:33 -07003247 }
Jeff Sharkey2d8b4e82013-09-17 17:30:33 -07003248
Martijn Coenen9fd2b642019-12-24 13:04:36 +01003249 return;
3250 }
3251 throw new SecurityException("Invalid mkdirs path: " + appFile
3252 + " is not a known app path.");
Jeff Sharkey2d8b4e82013-09-17 17:30:33 -07003253 }
3254
3255 @Override
Jeff Sharkey46349872015-07-28 10:49:47 -07003256 public StorageVolume[] getVolumeList(int uid, String packageName, int flags) {
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07003257 final int userId = UserHandle.getUserId(uid);
Jeff Sharkeyc02bfae2016-03-27 15:06:53 -06003258
Jeff Sharkey46349872015-07-28 10:49:47 -07003259 final boolean forWrite = (flags & StorageManager.FLAG_FOR_WRITE) != 0;
Jeff Sharkeyc02bfae2016-03-27 15:06:53 -06003260 final boolean realState = (flags & StorageManager.FLAG_REAL_STATE) != 0;
3261 final boolean includeInvisible = (flags & StorageManager.FLAG_INCLUDE_INVISIBLE) != 0;
Jeff Sharkey04b4ba12019-12-15 22:42:42 -07003262 final boolean includeRecent = (flags & StorageManager.FLAG_INCLUDE_RECENT) != 0;
Jeff Sharkey46349872015-07-28 10:49:47 -07003263
Narayan Kamath157dd1d2019-06-12 13:06:30 +01003264 // Report all volumes as unmounted until we've recorded that user 0 has unlocked. There
3265 // are no guarantees that callers will see a consistent view of the volume before that
3266 // point
3267 final boolean systemUserUnlocked = isSystemUnlocked(UserHandle.USER_SYSTEM);
3268
Jeff Sharkey04b4ba12019-12-15 22:42:42 -07003269 final boolean userIsDemo;
Jeff Sharkeyc02bfae2016-03-27 15:06:53 -06003270 final boolean userKeyUnlocked;
3271 final boolean storagePermission;
3272 final long token = Binder.clearCallingIdentity();
Svetoslav38c3dbb2015-07-14 11:27:06 -07003273 try {
Jeff Sharkey04b4ba12019-12-15 22:42:42 -07003274 userIsDemo = LocalServices.getService(UserManagerInternal.class)
3275 .getUserInfo(userId).isDemo();
Jeff Sharkeyc02bfae2016-03-27 15:06:53 -06003276 userKeyUnlocked = isUserKeyUnlocked(userId);
Sudheer Shanka2250d562016-11-07 15:41:02 -08003277 storagePermission = mStorageManagerInternal.hasExternalStorage(uid, packageName);
Svetoslav38c3dbb2015-07-14 11:27:06 -07003278 } finally {
Jeff Sharkeyc02bfae2016-03-27 15:06:53 -06003279 Binder.restoreCallingIdentity(token);
Svetoslav38c3dbb2015-07-14 11:27:06 -07003280 }
Svet Ganov6ee871e2015-07-10 14:29:33 -07003281
Jeff Sharkeyc02bfae2016-03-27 15:06:53 -06003282 boolean foundPrimary = false;
3283
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07003284 final ArrayList<StorageVolume> res = new ArrayList<>();
Jeff Sharkey04b4ba12019-12-15 22:42:42 -07003285 final ArraySet<String> resUuids = new ArraySet<>();
Jeff Sharkey48877892015-03-18 11:27:19 -07003286 synchronized (mLock) {
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07003287 for (int i = 0; i < mVolumes.size(); i++) {
3288 final VolumeInfo vol = mVolumes.valueAt(i);
Jeff Sharkeyc02bfae2016-03-27 15:06:53 -06003289 switch (vol.getType()) {
3290 case VolumeInfo.TYPE_PUBLIC:
Risan05c41e62018-10-29 08:57:43 +09003291 case VolumeInfo.TYPE_STUB:
Jeff Sharkeyc02bfae2016-03-27 15:06:53 -06003292 break;
Zim17be6f92019-09-25 14:37:55 +01003293 case VolumeInfo.TYPE_EMULATED:
3294 if (vol.getMountUserId() == userId) {
3295 break;
3296 }
3297 // Skip if emulated volume not for userId
Jeff Sharkeyc02bfae2016-03-27 15:06:53 -06003298 default:
3299 continue;
3300 }
3301
3302 boolean match = false;
3303 if (forWrite) {
3304 match = vol.isVisibleForWrite(userId);
3305 } else {
Felipe Leme123a0e72016-06-10 11:09:11 -07003306 match = vol.isVisibleForRead(userId)
3307 || (includeInvisible && vol.getPath() != null);
Jeff Sharkeyc02bfae2016-03-27 15:06:53 -06003308 }
3309 if (!match) continue;
3310
3311 boolean reportUnmounted = false;
Narayan Kamath157dd1d2019-06-12 13:06:30 +01003312 if (!systemUserUnlocked) {
3313 reportUnmounted = true;
3314 } else if ((vol.getType() == VolumeInfo.TYPE_EMULATED) && !userKeyUnlocked) {
Jeff Sharkeyc02bfae2016-03-27 15:06:53 -06003315 reportUnmounted = true;
3316 } else if (!storagePermission && !realState) {
3317 reportUnmounted = true;
3318 }
3319
3320 final StorageVolume userVol = vol.buildStorageVolume(mContext, userId,
3321 reportUnmounted);
3322 if (vol.isPrimary()) {
3323 res.add(0, userVol);
3324 foundPrimary = true;
3325 } else {
3326 res.add(userVol);
Jeff Sharkeyb049e212012-09-07 23:16:01 -07003327 }
Jeff Sharkey04b4ba12019-12-15 22:42:42 -07003328 resUuids.add(userVol.getUuid());
Mike Lockwood8fa5f802011-03-24 08:12:30 -07003329 }
Jeff Sharkey04b4ba12019-12-15 22:42:42 -07003330
3331 if (includeRecent) {
3332 final long lastWeek = System.currentTimeMillis() - DateUtils.WEEK_IN_MILLIS;
3333 for (int i = 0; i < mRecords.size(); i++) {
3334 final VolumeRecord rec = mRecords.valueAt(i);
3335
3336 // Skip if we've already included it above
3337 if (resUuids.contains(rec.fsUuid)) continue;
3338
3339 // Treat as recent if mounted within the last week
3340 if (rec.lastSeenMillis > 0 && rec.lastSeenMillis < lastWeek) {
3341 final StorageVolume userVol = rec.buildStorageVolume(mContext);
3342 res.add(userVol);
3343 resUuids.add(userVol.getUuid());
3344 }
3345 }
3346 }
3347 }
3348
3349 // Synthesize a volume for preloaded media under demo users, so that
3350 // it's scanned into MediaStore
3351 if (userIsDemo) {
3352 final String id = "demo";
3353 final File path = Environment.getDataPreloadsMediaDirectory();
3354 final boolean primary = false;
3355 final boolean removable = false;
3356 final boolean emulated = true;
3357 final boolean allowMassStorage = false;
3358 final long maxFileSize = 0;
3359 final UserHandle user = new UserHandle(userId);
3360 final String envState = Environment.MEDIA_MOUNTED_READ_ONLY;
3361 final String description = mContext.getString(android.R.string.unknownName);
3362
3363 res.add(new StorageVolume(id, path, path, description, primary, removable,
3364 emulated, allowMassStorage, maxFileSize, user, id, envState));
Mike Lockwood8fa5f802011-03-24 08:12:30 -07003365 }
Jeff Sharkey48877892015-03-18 11:27:19 -07003366
3367 if (!foundPrimary) {
Jeff Sharkey11697f52018-12-13 10:14:42 -07003368 Slog.w(TAG, "No primary storage defined yet; hacking together a stub");
Jeff Sharkey48877892015-03-18 11:27:19 -07003369
3370 final boolean primaryPhysical = SystemProperties.getBoolean(
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07003371 StorageManager.PROP_PRIMARY_PHYSICAL, false);
Jeff Sharkey48877892015-03-18 11:27:19 -07003372
3373 final String id = "stub_primary";
3374 final File path = Environment.getLegacyExternalStorageDirectory();
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07003375 final String description = mContext.getString(android.R.string.unknownName);
Jeff Sharkey48877892015-03-18 11:27:19 -07003376 final boolean primary = true;
3377 final boolean removable = primaryPhysical;
3378 final boolean emulated = !primaryPhysical;
Jeff Sharkey48877892015-03-18 11:27:19 -07003379 final boolean allowMassStorage = false;
3380 final long maxFileSize = 0L;
3381 final UserHandle owner = new UserHandle(userId);
3382 final String uuid = null;
Jeff Sharkey48877892015-03-18 11:27:19 -07003383 final String state = Environment.MEDIA_REMOVED;
3384
Jerry Zhang71938e12018-05-10 18:28:29 -07003385 res.add(0, new StorageVolume(id, path, path,
Jerry Zhangf9c5c252017-08-16 18:07:51 -07003386 description, primary, removable, emulated,
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07003387 allowMassStorage, maxFileSize, owner, uuid, state));
Jeff Sharkey48877892015-03-18 11:27:19 -07003388 }
3389
3390 return res.toArray(new StorageVolume[res.size()]);
Mike Lockwood8fa5f802011-03-24 08:12:30 -07003391 }
3392
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07003393 @Override
3394 public DiskInfo[] getDisks() {
3395 synchronized (mLock) {
3396 final DiskInfo[] res = new DiskInfo[mDisks.size()];
3397 for (int i = 0; i < mDisks.size(); i++) {
3398 res[i] = mDisks.valueAt(i);
3399 }
3400 return res;
3401 }
3402 }
3403
3404 @Override
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07003405 public VolumeInfo[] getVolumes(int flags) {
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07003406 synchronized (mLock) {
3407 final VolumeInfo[] res = new VolumeInfo[mVolumes.size()];
3408 for (int i = 0; i < mVolumes.size(); i++) {
3409 res[i] = mVolumes.valueAt(i);
3410 }
3411 return res;
3412 }
3413 }
3414
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07003415 @Override
3416 public VolumeRecord[] getVolumeRecords(int flags) {
3417 synchronized (mLock) {
3418 final VolumeRecord[] res = new VolumeRecord[mRecords.size()];
3419 for (int i = 0; i < mRecords.size(); i++) {
3420 res[i] = mRecords.valueAt(i);
3421 }
3422 return res;
3423 }
3424 }
3425
Jeff Sharkey9bed0702017-01-23 20:37:05 -07003426 @Override
3427 public long getCacheQuotaBytes(String volumeUuid, int uid) {
3428 if (uid != Binder.getCallingUid()) {
3429 mContext.enforceCallingPermission(android.Manifest.permission.STORAGE_INTERNAL, TAG);
3430 }
Daniel Nishi80fdb012017-03-09 14:30:07 -08003431 final long token = Binder.clearCallingIdentity();
3432 final StorageStatsManager stats = mContext.getSystemService(StorageStatsManager.class);
3433 try {
3434 return stats.getCacheQuotaBytes(volumeUuid, uid);
3435 } finally {
3436 Binder.restoreCallingIdentity(token);
3437 }
Jeff Sharkey9bed0702017-01-23 20:37:05 -07003438 }
3439
3440 @Override
3441 public long getCacheSizeBytes(String volumeUuid, int uid) {
3442 if (uid != Binder.getCallingUid()) {
3443 mContext.enforceCallingPermission(android.Manifest.permission.STORAGE_INTERNAL, TAG);
3444 }
3445 final long token = Binder.clearCallingIdentity();
3446 try {
3447 return mContext.getSystemService(StorageStatsManager.class)
3448 .queryStatsForUid(volumeUuid, uid).getCacheBytes();
Jeff Sharkey789a8fc2017-04-16 13:18:35 -06003449 } catch (IOException e) {
3450 throw new ParcelableException(e);
Jeff Sharkey9bed0702017-01-23 20:37:05 -07003451 } finally {
3452 Binder.restoreCallingIdentity(token);
3453 }
3454 }
3455
Jeff Sharkey35e46d22017-06-09 10:01:20 -06003456 private int adjustAllocateFlags(int flags, int callingUid, String callingPackage) {
3457 // Require permission to allocate aggressively
3458 if ((flags & StorageManager.FLAG_ALLOCATE_AGGRESSIVE) != 0) {
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07003459 mContext.enforceCallingOrSelfPermission(
3460 android.Manifest.permission.ALLOCATE_AGGRESSIVE, TAG);
3461 }
3462
Jeff Sharkey35e46d22017-06-09 10:01:20 -06003463 // Apps normally can't directly defy reserved space
3464 flags &= ~StorageManager.FLAG_ALLOCATE_DEFY_ALL_RESERVED;
3465 flags &= ~StorageManager.FLAG_ALLOCATE_DEFY_HALF_RESERVED;
3466
3467 // However, if app is actively using the camera, then we're willing to
3468 // clear up to half of the reserved cache space, since the user might be
3469 // trying to capture an important memory.
3470 final AppOpsManager appOps = mContext.getSystemService(AppOpsManager.class);
3471 final long token = Binder.clearCallingIdentity();
3472 try {
3473 if (appOps.isOperationActive(AppOpsManager.OP_CAMERA, callingUid, callingPackage)) {
3474 Slog.d(TAG, "UID " + callingUid + " is actively using camera;"
3475 + " letting them defy reserved cached data");
3476 flags |= StorageManager.FLAG_ALLOCATE_DEFY_HALF_RESERVED;
3477 }
3478 } finally {
3479 Binder.restoreCallingIdentity(token);
3480 }
3481
3482 return flags;
3483 }
3484
3485 @Override
3486 public long getAllocatableBytes(String volumeUuid, int flags, String callingPackage) {
3487 flags = adjustAllocateFlags(flags, Binder.getCallingUid(), callingPackage);
3488
3489 final StorageManager storage = mContext.getSystemService(StorageManager.class);
3490 final StorageStatsManager stats = mContext.getSystemService(StorageStatsManager.class);
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07003491 final long token = Binder.clearCallingIdentity();
3492 try {
3493 // In general, apps can allocate as much space as they want, except
3494 // we never let them eat into either the minimum cache space or into
Jeff Sharkeyddff8072017-05-26 13:10:46 -06003495 // the low disk warning space. To avoid user confusion, this logic
3496 // should be kept in sync with getFreeBytes().
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07003497 final File path = storage.findPathForUuid(volumeUuid);
Jeff Sharkeyddff8072017-05-26 13:10:46 -06003498
Noah Zimmtb2558072019-07-25 16:15:06 -07003499 long usable = 0;
3500 long lowReserved = 0;
3501 long fullReserved = 0;
3502 long cacheClearable = 0;
Jeff Sharkeyddff8072017-05-26 13:10:46 -06003503
Noah Zimmtb2558072019-07-25 16:15:06 -07003504 if ((flags & StorageManager.FLAG_ALLOCATE_CACHE_ONLY) == 0) {
3505 usable = path.getUsableSpace();
3506 lowReserved = storage.getStorageLowBytes(path);
3507 fullReserved = storage.getStorageFullBytes(path);
3508 }
3509
3510 if ((flags & StorageManager.FLAG_ALLOCATE_NON_CACHE_ONLY) == 0
3511 && stats.isQuotaSupported(volumeUuid)) {
Jeff Sharkeyddff8072017-05-26 13:10:46 -06003512 final long cacheTotal = stats.getCacheBytes(volumeUuid);
Jeff Sharkey35e46d22017-06-09 10:01:20 -06003513 final long cacheReserved = storage.getStorageCacheBytes(path, flags);
Noah Zimmtb2558072019-07-25 16:15:06 -07003514 cacheClearable = Math.max(0, cacheTotal - cacheReserved);
3515 }
Jeff Sharkeyddff8072017-05-26 13:10:46 -06003516
Noah Zimmtb2558072019-07-25 16:15:06 -07003517 if ((flags & StorageManager.FLAG_ALLOCATE_AGGRESSIVE) != 0) {
3518 return Math.max(0, (usable + cacheClearable) - fullReserved);
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07003519 } else {
Noah Zimmtb2558072019-07-25 16:15:06 -07003520 return Math.max(0, (usable + cacheClearable) - lowReserved);
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07003521 }
Jeff Sharkey789a8fc2017-04-16 13:18:35 -06003522 } catch (IOException e) {
3523 throw new ParcelableException(e);
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07003524 } finally {
3525 Binder.restoreCallingIdentity(token);
3526 }
Jeff Sharkey500ce9e2017-02-12 02:39:24 -07003527 }
3528
3529 @Override
Jeff Sharkey35e46d22017-06-09 10:01:20 -06003530 public void allocateBytes(String volumeUuid, long bytes, int flags, String callingPackage) {
3531 flags = adjustAllocateFlags(flags, Binder.getCallingUid(), callingPackage);
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07003532
Noah Zimmtb2558072019-07-25 16:15:06 -07003533 final long allocatableBytes = getAllocatableBytes(volumeUuid,
3534 flags | StorageManager.FLAG_ALLOCATE_NON_CACHE_ONLY, callingPackage);
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07003535 if (bytes > allocatableBytes) {
Noah Zimmtb2558072019-07-25 16:15:06 -07003536 // If we don't have room without taking cache into account, check to see if we'd have
3537 // room if we included freeable cache space.
3538 final long cacheClearable = getAllocatableBytes(volumeUuid,
3539 flags | StorageManager.FLAG_ALLOCATE_CACHE_ONLY, callingPackage);
3540 if (bytes > allocatableBytes + cacheClearable) {
3541 throw new ParcelableException(new IOException("Failed to allocate " + bytes
3542 + " because only " + (allocatableBytes + cacheClearable) + " allocatable"));
3543 }
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07003544 }
3545
Jeff Sharkey35e46d22017-06-09 10:01:20 -06003546 final StorageManager storage = mContext.getSystemService(StorageManager.class);
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07003547 final long token = Binder.clearCallingIdentity();
3548 try {
Jeff Sharkey789a8fc2017-04-16 13:18:35 -06003549 // Free up enough disk space to satisfy both the requested allocation
3550 // and our low disk warning space.
3551 final File path = storage.findPathForUuid(volumeUuid);
Jeff Sharkeyddff8072017-05-26 13:10:46 -06003552 if ((flags & StorageManager.FLAG_ALLOCATE_AGGRESSIVE) != 0) {
3553 bytes += storage.getStorageFullBytes(path);
3554 } else {
3555 bytes += storage.getStorageLowBytes(path);
3556 }
Jeff Sharkey789a8fc2017-04-16 13:18:35 -06003557
Jeff Sharkey5790af02018-08-13 17:42:54 -06003558 mPmInternal.freeStorage(volumeUuid, bytes, flags);
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07003559 } catch (IOException e) {
3560 throw new ParcelableException(e);
3561 } finally {
3562 Binder.restoreCallingIdentity(token);
Jeff Sharkey500ce9e2017-02-12 02:39:24 -07003563 }
3564 }
3565
Sudheer Shankaff971bc2018-12-13 17:39:59 -08003566 private IAppOpsCallback.Stub mAppOpsCallback = new IAppOpsCallback.Stub() {
3567 @Override
3568 public void opChanged(int op, int uid, String packageName) throws RemoteException {
3569 if (!ENABLE_ISOLATED_STORAGE) return;
3570
Zim64726cb2019-11-27 13:06:34 +00003571 int mountMode = getMountMode(uid, packageName);
3572 boolean isUidActive = LocalServices.getService(ActivityManagerInternal.class)
3573 .getUidProcessState(uid) != PROCESS_STATE_NONEXISTENT;
3574
3575 if (isUidActive) {
3576 remountUidExternalStorage(uid, mountMode);
3577 }
Sudheer Shankaff971bc2018-12-13 17:39:59 -08003578 }
3579 };
3580
Kenny Rootaf9d6672010-10-08 09:21:39 -07003581 private void addObbStateLocked(ObbState obbState) throws RemoteException {
3582 final IBinder binder = obbState.getBinder();
3583 List<ObbState> obbStates = mObbMounts.get(binder);
Kenny Root5919ac62010-10-05 09:49:40 -07003584
Kenny Rootaf9d6672010-10-08 09:21:39 -07003585 if (obbStates == null) {
3586 obbStates = new ArrayList<ObbState>();
3587 mObbMounts.put(binder, obbStates);
3588 } else {
3589 for (final ObbState o : obbStates) {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003590 if (o.rawPath.equals(obbState.rawPath)) {
Kenny Rootaf9d6672010-10-08 09:21:39 -07003591 throw new IllegalStateException("Attempt to add ObbState twice. "
Sudheer Shanka2250d562016-11-07 15:41:02 -08003592 + "This indicates an error in the StorageManagerService logic.");
Kenny Root5919ac62010-10-05 09:49:40 -07003593 }
3594 }
Kenny Roota02b8b02010-08-05 16:14:17 -07003595 }
Kenny Rootaf9d6672010-10-08 09:21:39 -07003596
3597 obbStates.add(obbState);
3598 try {
3599 obbState.link();
3600 } catch (RemoteException e) {
3601 /*
3602 * The binder died before we could link it, so clean up our state
3603 * and return failure.
3604 */
3605 obbStates.remove(obbState);
3606 if (obbStates.isEmpty()) {
3607 mObbMounts.remove(binder);
3608 }
3609
3610 // Rethrow the error so mountObb can get it
3611 throw e;
3612 }
3613
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003614 mObbPathToStateMap.put(obbState.rawPath, obbState);
Kenny Roota02b8b02010-08-05 16:14:17 -07003615 }
3616
Kenny Rootaf9d6672010-10-08 09:21:39 -07003617 private void removeObbStateLocked(ObbState obbState) {
3618 final IBinder binder = obbState.getBinder();
3619 final List<ObbState> obbStates = mObbMounts.get(binder);
3620 if (obbStates != null) {
3621 if (obbStates.remove(obbState)) {
3622 obbState.unlink();
Kenny Root05105f72010-09-22 17:29:43 -07003623 }
Kenny Rootaf9d6672010-10-08 09:21:39 -07003624 if (obbStates.isEmpty()) {
3625 mObbMounts.remove(binder);
3626 }
Kenny Roota02b8b02010-08-05 16:14:17 -07003627 }
Kenny Roota02b8b02010-08-05 16:14:17 -07003628
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003629 mObbPathToStateMap.remove(obbState.rawPath);
Kenny Root38cf8862010-09-26 14:18:51 -07003630 }
3631
Kenny Roota02b8b02010-08-05 16:14:17 -07003632 private class ObbActionHandler extends Handler {
Kenny Roota02b8b02010-08-05 16:14:17 -07003633
3634 ObbActionHandler(Looper l) {
3635 super(l);
3636 }
3637
3638 @Override
3639 public void handleMessage(Message msg) {
3640 switch (msg.what) {
3641 case OBB_RUN_ACTION: {
Kenny Root480afe72010-10-07 10:17:50 -07003642 final ObbAction action = (ObbAction) msg.obj;
Kenny Roota02b8b02010-08-05 16:14:17 -07003643
3644 if (DEBUG_OBB)
3645 Slog.i(TAG, "OBB_RUN_ACTION: " + action.toString());
3646
Sudheer Shanka25469aa2018-08-27 15:50:23 -07003647 action.execute(this);
Kenny Roota02b8b02010-08-05 16:14:17 -07003648 break;
3649 }
Kenny Rootaf9d6672010-10-08 09:21:39 -07003650 case OBB_FLUSH_MOUNT_STATE: {
3651 final String path = (String) msg.obj;
3652
3653 if (DEBUG_OBB)
3654 Slog.i(TAG, "Flushing all OBB state for path " + path);
3655
3656 synchronized (mObbMounts) {
3657 final List<ObbState> obbStatesToRemove = new LinkedList<ObbState>();
3658
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003659 final Iterator<ObbState> i = mObbPathToStateMap.values().iterator();
Kenny Rootaf9d6672010-10-08 09:21:39 -07003660 while (i.hasNext()) {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003661 final ObbState state = i.next();
Kenny Rootaf9d6672010-10-08 09:21:39 -07003662
3663 /*
3664 * If this entry's source file is in the volume path
3665 * that got unmounted, remove it because it's no
3666 * longer valid.
3667 */
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003668 if (state.canonicalPath.startsWith(path)) {
3669 obbStatesToRemove.add(state);
Kenny Rootaf9d6672010-10-08 09:21:39 -07003670 }
3671 }
3672
3673 for (final ObbState obbState : obbStatesToRemove) {
3674 if (DEBUG_OBB)
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003675 Slog.i(TAG, "Removing state for " + obbState.rawPath);
Kenny Rootaf9d6672010-10-08 09:21:39 -07003676
3677 removeObbStateLocked(obbState);
3678
3679 try {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003680 obbState.token.onObbResult(obbState.rawPath, obbState.nonce,
Kenny Rootaf9d6672010-10-08 09:21:39 -07003681 OnObbStateChangeListener.UNMOUNTED);
3682 } catch (RemoteException e) {
3683 Slog.i(TAG, "Couldn't send unmount notification for OBB: "
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003684 + obbState.rawPath);
Kenny Rootaf9d6672010-10-08 09:21:39 -07003685 }
3686 }
3687 }
3688 break;
3689 }
Kenny Roota02b8b02010-08-05 16:14:17 -07003690 }
3691 }
Kenny Roota02b8b02010-08-05 16:14:17 -07003692 }
3693
Jeff Sharkey0095a822018-02-15 13:06:53 -07003694 private static class ObbException extends Exception {
3695 public final int status;
3696
3697 public ObbException(int status, String message) {
3698 super(message);
3699 this.status = status;
3700 }
3701
3702 public ObbException(int status, Throwable cause) {
3703 super(cause.getMessage(), cause);
3704 this.status = status;
3705 }
3706 }
3707
Kenny Roota02b8b02010-08-05 16:14:17 -07003708 abstract class ObbAction {
Kenny Roota02b8b02010-08-05 16:14:17 -07003709
3710 ObbState mObbState;
3711
3712 ObbAction(ObbState obbState) {
3713 mObbState = obbState;
3714 }
3715
3716 public void execute(ObbActionHandler handler) {
3717 try {
3718 if (DEBUG_OBB)
Ben Komalo444eca22011-09-01 15:17:44 -07003719 Slog.i(TAG, "Starting to execute action: " + toString());
Sudheer Shanka25469aa2018-08-27 15:50:23 -07003720 handleExecute();
Jeff Sharkey0095a822018-02-15 13:06:53 -07003721 } catch (ObbException e) {
3722 notifyObbStateChange(e);
Kenny Roota02b8b02010-08-05 16:14:17 -07003723 }
3724 }
3725
Jeff Sharkey0095a822018-02-15 13:06:53 -07003726 abstract void handleExecute() throws ObbException;
Kenny Root38cf8862010-09-26 14:18:51 -07003727
Jeff Sharkey0095a822018-02-15 13:06:53 -07003728 protected void notifyObbStateChange(ObbException e) {
3729 Slog.w(TAG, e);
3730 notifyObbStateChange(e.status);
3731 }
3732
3733 protected void notifyObbStateChange(int status) {
Kenny Rootaf9d6672010-10-08 09:21:39 -07003734 if (mObbState == null || mObbState.token == null) {
3735 return;
3736 }
3737
Kenny Root38cf8862010-09-26 14:18:51 -07003738 try {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003739 mObbState.token.onObbResult(mObbState.rawPath, mObbState.nonce, status);
Kenny Root38cf8862010-09-26 14:18:51 -07003740 } catch (RemoteException e) {
Sudheer Shanka2250d562016-11-07 15:41:02 -08003741 Slog.w(TAG, "StorageEventListener went away while calling onObbStateChanged");
Kenny Root38cf8862010-09-26 14:18:51 -07003742 }
3743 }
Kenny Roota02b8b02010-08-05 16:14:17 -07003744 }
3745
3746 class MountObbAction extends ObbAction {
Ben Komalo444eca22011-09-01 15:17:44 -07003747 private final String mKey;
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003748 private final int mCallingUid;
Sudheer Shanka25469aa2018-08-27 15:50:23 -07003749 private ObbInfo mObbInfo;
Kenny Roota02b8b02010-08-05 16:14:17 -07003750
Sudheer Shanka25469aa2018-08-27 15:50:23 -07003751 MountObbAction(ObbState obbState, String key, int callingUid, ObbInfo obbInfo) {
Kenny Roota02b8b02010-08-05 16:14:17 -07003752 super(obbState);
3753 mKey = key;
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003754 mCallingUid = callingUid;
Sudheer Shanka25469aa2018-08-27 15:50:23 -07003755 mObbInfo = obbInfo;
Kenny Roota02b8b02010-08-05 16:14:17 -07003756 }
3757
Jason parks5af0b912010-11-29 09:05:25 -06003758 @Override
Jeff Sharkey0095a822018-02-15 13:06:53 -07003759 public void handleExecute() throws ObbException {
Kenny Rootaf9d6672010-10-08 09:21:39 -07003760 warnOnNotMounted();
3761
Sudheer Shanka25469aa2018-08-27 15:50:23 -07003762 if (!isUidOwnerOfPackageOrSystem(mObbInfo.packageName, mCallingUid)) {
Jeff Sharkey0095a822018-02-15 13:06:53 -07003763 throw new ObbException(ERROR_PERMISSION_DENIED, "Denied attempt to mount OBB "
Sudheer Shanka25469aa2018-08-27 15:50:23 -07003764 + mObbInfo.filename + " which is owned by " + mObbInfo.packageName);
Kenny Roota02b8b02010-08-05 16:14:17 -07003765 }
3766
Kenny Rootaf9d6672010-10-08 09:21:39 -07003767 final boolean isMounted;
3768 synchronized (mObbMounts) {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003769 isMounted = mObbPathToStateMap.containsKey(mObbState.rawPath);
Kenny Rootaf9d6672010-10-08 09:21:39 -07003770 }
3771 if (isMounted) {
Jeff Sharkey0095a822018-02-15 13:06:53 -07003772 throw new ObbException(ERROR_ALREADY_MOUNTED,
Sudheer Shanka25469aa2018-08-27 15:50:23 -07003773 "Attempt to mount OBB which is already mounted: " + mObbInfo.filename);
Kenny Rootaf9d6672010-10-08 09:21:39 -07003774 }
3775
Kenny Rootaf9d6672010-10-08 09:21:39 -07003776 final String hashedKey;
Jeff Sharkey41cd6812017-09-11 10:32:17 -06003777 final String binderKey;
Kenny Rootaf9d6672010-10-08 09:21:39 -07003778 if (mKey == null) {
3779 hashedKey = "none";
Jeff Sharkey41cd6812017-09-11 10:32:17 -06003780 binderKey = "";
Kenny Rootaf9d6672010-10-08 09:21:39 -07003781 } else {
Kenny Rootaf9d6672010-10-08 09:21:39 -07003782 try {
Kenny Root3b1abba2010-10-13 15:00:07 -07003783 SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
3784
Sudheer Shanka25469aa2018-08-27 15:50:23 -07003785 KeySpec ks = new PBEKeySpec(mKey.toCharArray(), mObbInfo.salt,
Kenny Root3b1abba2010-10-13 15:00:07 -07003786 PBKDF2_HASH_ROUNDS, CRYPTO_ALGORITHM_KEY_SIZE);
3787 SecretKey key = factory.generateSecret(ks);
3788 BigInteger bi = new BigInteger(key.getEncoded());
3789 hashedKey = bi.toString(16);
Jeff Sharkey41cd6812017-09-11 10:32:17 -06003790 binderKey = hashedKey;
Jeff Sharkey0095a822018-02-15 13:06:53 -07003791 } catch (GeneralSecurityException e) {
3792 throw new ObbException(ERROR_INTERNAL, e);
Kenny Root38cf8862010-09-26 14:18:51 -07003793 }
Kenny Rootaf9d6672010-10-08 09:21:39 -07003794 }
Kenny Root38cf8862010-09-26 14:18:51 -07003795
Kenny Rootaf9d6672010-10-08 09:21:39 -07003796 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06003797 mObbState.volId = mVold.createObb(mObbState.canonicalPath, binderKey,
3798 mObbState.ownerGid);
Zim95eca1d2019-11-15 18:03:00 +00003799 mVold.mount(mObbState.volId, 0, -1, null);
Kenny Roota02b8b02010-08-05 16:14:17 -07003800
Kenny Rootaf9d6672010-10-08 09:21:39 -07003801 if (DEBUG_OBB)
Xiaohui Chen621b3fc2015-10-02 14:41:42 -07003802 Slog.d(TAG, "Successfully mounted OBB " + mObbState.canonicalPath);
Kenny Rootaf9d6672010-10-08 09:21:39 -07003803
3804 synchronized (mObbMounts) {
3805 addObbStateLocked(mObbState);
3806 }
3807
Jeff Sharkey0095a822018-02-15 13:06:53 -07003808 notifyObbStateChange(MOUNTED);
3809 } catch (Exception e) {
3810 throw new ObbException(ERROR_COULD_NOT_MOUNT, e);
Kenny Root02c87302010-07-01 08:10:18 -07003811 }
3812 }
3813
Jason parks5af0b912010-11-29 09:05:25 -06003814 @Override
Kenny Roota02b8b02010-08-05 16:14:17 -07003815 public String toString() {
3816 StringBuilder sb = new StringBuilder();
3817 sb.append("MountObbAction{");
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003818 sb.append(mObbState);
Kenny Roota02b8b02010-08-05 16:14:17 -07003819 sb.append('}');
3820 return sb.toString();
3821 }
3822 }
3823
3824 class UnmountObbAction extends ObbAction {
Ben Komalo444eca22011-09-01 15:17:44 -07003825 private final boolean mForceUnmount;
Kenny Roota02b8b02010-08-05 16:14:17 -07003826
3827 UnmountObbAction(ObbState obbState, boolean force) {
3828 super(obbState);
3829 mForceUnmount = force;
3830 }
3831
Jason parks5af0b912010-11-29 09:05:25 -06003832 @Override
Jeff Sharkey0095a822018-02-15 13:06:53 -07003833 public void handleExecute() throws ObbException {
Kenny Rootaf9d6672010-10-08 09:21:39 -07003834 warnOnNotMounted();
3835
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003836 final ObbState existingState;
Kenny Root38cf8862010-09-26 14:18:51 -07003837 synchronized (mObbMounts) {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003838 existingState = mObbPathToStateMap.get(mObbState.rawPath);
Kenny Rootaf9d6672010-10-08 09:21:39 -07003839 }
Kenny Root38cf8862010-09-26 14:18:51 -07003840
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003841 if (existingState == null) {
Jeff Sharkey0095a822018-02-15 13:06:53 -07003842 throw new ObbException(ERROR_NOT_MOUNTED, "Missing existingState");
Kenny Rootaf9d6672010-10-08 09:21:39 -07003843 }
3844
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003845 if (existingState.ownerGid != mObbState.ownerGid) {
Jeff Sharkey0095a822018-02-15 13:06:53 -07003846 notifyObbStateChange(new ObbException(ERROR_PERMISSION_DENIED,
3847 "Permission denied to unmount OBB " + existingState.rawPath
3848 + " (owned by GID " + existingState.ownerGid + ")"));
Kenny Rootaf9d6672010-10-08 09:21:39 -07003849 return;
3850 }
3851
Kenny Rootaf9d6672010-10-08 09:21:39 -07003852 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06003853 mVold.unmount(mObbState.volId);
3854 mVold.destroyObb(mObbState.volId);
3855 mObbState.volId = null;
Kenny Roota02b8b02010-08-05 16:14:17 -07003856
Kenny Rootaf9d6672010-10-08 09:21:39 -07003857 synchronized (mObbMounts) {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003858 removeObbStateLocked(existingState);
Kenny Root38cf8862010-09-26 14:18:51 -07003859 }
3860
Jeff Sharkey0095a822018-02-15 13:06:53 -07003861 notifyObbStateChange(UNMOUNTED);
3862 } catch (Exception e) {
3863 throw new ObbException(ERROR_COULD_NOT_UNMOUNT, e);
Kenny Roota02b8b02010-08-05 16:14:17 -07003864 }
3865 }
3866
Jason parks5af0b912010-11-29 09:05:25 -06003867 @Override
Kenny Roota02b8b02010-08-05 16:14:17 -07003868 public String toString() {
3869 StringBuilder sb = new StringBuilder();
3870 sb.append("UnmountObbAction{");
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003871 sb.append(mObbState);
Kenny Roota02b8b02010-08-05 16:14:17 -07003872 sb.append(",force=");
3873 sb.append(mForceUnmount);
Kenny Roota02b8b02010-08-05 16:14:17 -07003874 sb.append('}');
3875 return sb.toString();
3876 }
Kenny Root02c87302010-07-01 08:10:18 -07003877 }
Kenny Root38cf8862010-09-26 14:18:51 -07003878
Jeff Sharkey7e19f532017-11-06 13:54:11 -07003879 private void dispatchOnStatus(IVoldTaskListener listener, int status,
3880 PersistableBundle extras) {
3881 if (listener != null) {
3882 try {
3883 listener.onStatus(status, extras);
3884 } catch (RemoteException ignored) {
3885 }
3886 }
3887 }
3888
3889 private void dispatchOnFinished(IVoldTaskListener listener, int status,
3890 PersistableBundle extras) {
3891 if (listener != null) {
3892 try {
3893 listener.onFinished(status, extras);
3894 } catch (RemoteException ignored) {
3895 }
3896 }
3897 }
3898
Sudheer Shanka3a0df3b2018-12-12 12:43:43 -08003899 private int getMountMode(int uid, String packageName) {
Jeff Sharkey6fd69942019-03-26 17:53:35 -06003900 final int mode = getMountModeInternal(uid, packageName);
3901 if (LOCAL_LOGV) {
3902 Slog.v(TAG, "Resolved mode " + mode + " for " + packageName + "/"
3903 + UserHandle.formatUid(uid));
3904 }
3905 return mode;
3906 }
3907
3908 private int getMountModeInternal(int uid, String packageName) {
Sudheer Shanka3a0df3b2018-12-12 12:43:43 -08003909 try {
Jeff Sharkey6fd69942019-03-26 17:53:35 -06003910 // Get some easy cases out of the way first
Sudheer Shanka3a0df3b2018-12-12 12:43:43 -08003911 if (Process.isIsolated(uid)) {
3912 return Zygote.MOUNT_EXTERNAL_NONE;
3913 }
Sudheer Shankab1613982019-05-16 16:55:50 -07003914
3915 final String[] packagesForUid = mIPackageManager.getPackagesForUid(uid);
Sudheer Shanka1df72db2019-05-24 10:59:52 -07003916 if (ArrayUtils.isEmpty(packagesForUid)) {
3917 // It's possible the package got uninstalled already, so just ignore.
3918 return Zygote.MOUNT_EXTERNAL_NONE;
3919 }
Sudheer Shankab1613982019-05-16 16:55:50 -07003920 if (packageName == null) {
3921 packageName = packagesForUid[0];
3922 }
3923
Jeff Sharkey6fd69942019-03-26 17:53:35 -06003924 if (mPmInternal.isInstantApp(packageName, UserHandle.getUserId(uid))) {
Winson Chiu5118d492019-05-15 18:24:06 +00003925 return Zygote.MOUNT_EXTERNAL_NONE;
Jeff Sharkey6fd69942019-03-26 17:53:35 -06003926 }
3927
Martijn Coenen44db1ac2019-12-03 16:06:19 +01003928 if (mIsFuseEnabled && mMediaStoreAuthorityAppId == UserHandle.getAppId(uid)) {
3929 // Determine if caller requires pass_through mount; note that we do this for
3930 // all processes that share a UID with MediaProvider; but this is fine, since
3931 // those processes anyway share the same rights as MediaProvider.
Zim74a9bba2019-09-03 20:49:13 +01003932 return Zygote.MOUNT_EXTERNAL_PASS_THROUGH;
3933 }
3934
Martijn Coenen496ac002020-01-08 14:55:53 +01003935 if (mIsFuseEnabled && mDownloadsAuthorityAppId == UserHandle.getAppId(uid)) {
3936 // DownloadManager can write in app-private directories on behalf of apps;
3937 // give it write access to Android/
3938 return Zygote.MOUNT_EXTERNAL_ANDROID_WRITABLE;
3939 }
3940
3941 final boolean hasMtp = mIPackageManager.checkUidPermission(ACCESS_MTP, uid) ==
3942 PERMISSION_GRANTED;
3943 if (mIsFuseEnabled && hasMtp) {
3944 // The process hosting the MTP server should be able to write in Android/
3945 return Zygote.MOUNT_EXTERNAL_ANDROID_WRITABLE;
3946 }
3947
Jeff Sharkey6fd69942019-03-26 17:53:35 -06003948 // Determine if caller is holding runtime permission
Chad Brubaker45810af2019-04-08 19:19:48 -07003949 final boolean hasRead = StorageManager.checkPermissionAndCheckOp(mContext, false, 0,
Jeff Sharkey6fd69942019-03-26 17:53:35 -06003950 uid, packageName, READ_EXTERNAL_STORAGE, OP_READ_EXTERNAL_STORAGE);
Chad Brubaker45810af2019-04-08 19:19:48 -07003951 final boolean hasWrite = StorageManager.checkPermissionAndCheckOp(mContext, false, 0,
Jeff Sharkey6fd69942019-03-26 17:53:35 -06003952 uid, packageName, WRITE_EXTERNAL_STORAGE, OP_WRITE_EXTERNAL_STORAGE);
Jeff Sharkey6fd69942019-03-26 17:53:35 -06003953
3954 // We're only willing to give out broad access if they also hold
3955 // runtime permission; this is a firm CDD requirement
3956 final boolean hasFull = mIPackageManager.checkUidPermission(WRITE_MEDIA_STORAGE,
3957 uid) == PERMISSION_GRANTED;
Jeff Sharkey26874a22019-04-17 21:30:47 -06003958 if (hasFull && hasWrite) {
Jeff Sharkey6fd69942019-03-26 17:53:35 -06003959 return Zygote.MOUNT_EXTERNAL_FULL;
3960 }
3961
3962 // We're only willing to give out installer access if they also hold
3963 // runtime permission; this is a firm CDD requirement
3964 final boolean hasInstall = mIPackageManager.checkUidPermission(INSTALL_PACKAGES,
3965 uid) == PERMISSION_GRANTED;
Sudheer Shankab1613982019-05-16 16:55:50 -07003966 boolean hasInstallOp = false;
3967 // OP_REQUEST_INSTALL_PACKAGES is granted/denied per package but vold can't
3968 // update mountpoints of a specific package. So, check the appop for all packages
3969 // sharing the uid and allow same level of storage access for all packages even if
3970 // one of the packages has the appop granted.
3971 for (String uidPackageName : packagesForUid) {
3972 if (mIAppOpsService.checkOperation(
3973 OP_REQUEST_INSTALL_PACKAGES, uid, uidPackageName) == MODE_ALLOWED) {
3974 hasInstallOp = true;
3975 break;
3976 }
3977 }
Jeff Sharkey26874a22019-04-17 21:30:47 -06003978 if ((hasInstall || hasInstallOp) && hasWrite) {
Martijn Coenenfc9c3b62019-12-13 16:36:27 +01003979 return Zygote.MOUNT_EXTERNAL_INSTALLER;
Jeff Sharkey6fd69942019-03-26 17:53:35 -06003980 }
3981
3982 // Otherwise we're willing to give out sandboxed or non-sandboxed if
3983 // they hold the runtime permission
Nandana Duttdc15bb42020-01-03 16:43:46 +00003984 boolean hasLegacy = mIAppOpsService.checkOperation(OP_LEGACY_STORAGE,
Jeff Sharkey6fd69942019-03-26 17:53:35 -06003985 uid, packageName) == MODE_ALLOWED;
Nandana Duttdc15bb42020-01-03 16:43:46 +00003986
3987 // Hack(b/147137425): we have to honor hasRequestedLegacyExternalStorage for a short
3988 // while to enable 2 cases.
3989 // 1) Apps that want to be in scoped storage in R, but want to opt out in Q devices,
3990 // because they want to use raw file paths, would fail until fuse is enabled by default.
3991 // 2) Test apps that target current sdk will fail. They would fail even after fuse is
3992 // enabled, but we are fixing it with b/142395442. We are not planning to enable
3993 // fuse by default until b/142395442 is fixed.
3994 if (!hasLegacy && !mIsFuseEnabled) {
3995 ApplicationInfo ai = mIPackageManager.getApplicationInfo(packageName,
3996 0, UserHandle.getUserId(uid));
3997 hasLegacy = ai.hasRequestedLegacyExternalStorage();
3998 }
3999
Jeff Sharkey26874a22019-04-17 21:30:47 -06004000 if (hasLegacy && hasWrite) {
4001 return Zygote.MOUNT_EXTERNAL_WRITE;
4002 } else if (hasLegacy && hasRead) {
4003 return Zygote.MOUNT_EXTERNAL_READ;
Sudheer Shanka3a0df3b2018-12-12 12:43:43 -08004004 } else {
Sudheer Shanka783c90e2019-04-12 13:55:20 -07004005 return Zygote.MOUNT_EXTERNAL_DEFAULT;
Sudheer Shanka3a0df3b2018-12-12 12:43:43 -08004006 }
4007 } catch (RemoteException e) {
4008 // Should not happen
4009 }
4010 return Zygote.MOUNT_EXTERNAL_NONE;
4011 }
4012
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07004013 private static class Callbacks extends Handler {
4014 private static final int MSG_STORAGE_STATE_CHANGED = 1;
4015 private static final int MSG_VOLUME_STATE_CHANGED = 2;
Jeff Sharkey50a05452015-04-29 11:24:52 -07004016 private static final int MSG_VOLUME_RECORD_CHANGED = 3;
4017 private static final int MSG_VOLUME_FORGOTTEN = 4;
4018 private static final int MSG_DISK_SCANNED = 5;
Makoto Onuki9dc575d2015-06-12 16:10:25 -07004019 private static final int MSG_DISK_DESTROYED = 6;
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07004020
Sudheer Shanka2250d562016-11-07 15:41:02 -08004021 private final RemoteCallbackList<IStorageEventListener>
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07004022 mCallbacks = new RemoteCallbackList<>();
4023
4024 public Callbacks(Looper looper) {
4025 super(looper);
4026 }
4027
Sudheer Shanka2250d562016-11-07 15:41:02 -08004028 public void register(IStorageEventListener callback) {
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07004029 mCallbacks.register(callback);
4030 }
4031
Sudheer Shanka2250d562016-11-07 15:41:02 -08004032 public void unregister(IStorageEventListener callback) {
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07004033 mCallbacks.unregister(callback);
4034 }
4035
4036 @Override
4037 public void handleMessage(Message msg) {
4038 final SomeArgs args = (SomeArgs) msg.obj;
4039 final int n = mCallbacks.beginBroadcast();
4040 for (int i = 0; i < n; i++) {
Sudheer Shanka2250d562016-11-07 15:41:02 -08004041 final IStorageEventListener callback = mCallbacks.getBroadcastItem(i);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07004042 try {
4043 invokeCallback(callback, msg.what, args);
4044 } catch (RemoteException ignored) {
4045 }
4046 }
4047 mCallbacks.finishBroadcast();
4048 args.recycle();
4049 }
4050
Sudheer Shanka2250d562016-11-07 15:41:02 -08004051 private void invokeCallback(IStorageEventListener callback, int what, SomeArgs args)
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07004052 throws RemoteException {
4053 switch (what) {
4054 case MSG_STORAGE_STATE_CHANGED: {
4055 callback.onStorageStateChanged((String) args.arg1, (String) args.arg2,
4056 (String) args.arg3);
4057 break;
4058 }
4059 case MSG_VOLUME_STATE_CHANGED: {
4060 callback.onVolumeStateChanged((VolumeInfo) args.arg1, args.argi2, args.argi3);
4061 break;
4062 }
Jeff Sharkey50a05452015-04-29 11:24:52 -07004063 case MSG_VOLUME_RECORD_CHANGED: {
4064 callback.onVolumeRecordChanged((VolumeRecord) args.arg1);
4065 break;
4066 }
4067 case MSG_VOLUME_FORGOTTEN: {
4068 callback.onVolumeForgotten((String) args.arg1);
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07004069 break;
4070 }
Jeff Sharkey620b32b2015-04-23 19:36:02 -07004071 case MSG_DISK_SCANNED: {
4072 callback.onDiskScanned((DiskInfo) args.arg1, args.argi2);
Jeff Sharkey7e92ef32015-04-17 17:35:07 -07004073 break;
4074 }
Makoto Onuki9dc575d2015-06-12 16:10:25 -07004075 case MSG_DISK_DESTROYED: {
4076 callback.onDiskDestroyed((DiskInfo) args.arg1);
4077 break;
4078 }
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07004079 }
4080 }
4081
4082 private void notifyStorageStateChanged(String path, String oldState, String newState) {
4083 final SomeArgs args = SomeArgs.obtain();
4084 args.arg1 = path;
4085 args.arg2 = oldState;
4086 args.arg3 = newState;
4087 obtainMessage(MSG_STORAGE_STATE_CHANGED, args).sendToTarget();
4088 }
4089
4090 private void notifyVolumeStateChanged(VolumeInfo vol, int oldState, int newState) {
4091 final SomeArgs args = SomeArgs.obtain();
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07004092 args.arg1 = vol.clone();
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07004093 args.argi2 = oldState;
4094 args.argi3 = newState;
4095 obtainMessage(MSG_VOLUME_STATE_CHANGED, args).sendToTarget();
4096 }
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07004097
Jeff Sharkey50a05452015-04-29 11:24:52 -07004098 private void notifyVolumeRecordChanged(VolumeRecord rec) {
4099 final SomeArgs args = SomeArgs.obtain();
4100 args.arg1 = rec.clone();
4101 obtainMessage(MSG_VOLUME_RECORD_CHANGED, args).sendToTarget();
4102 }
4103
4104 private void notifyVolumeForgotten(String fsUuid) {
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07004105 final SomeArgs args = SomeArgs.obtain();
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07004106 args.arg1 = fsUuid;
Jeff Sharkey50a05452015-04-29 11:24:52 -07004107 obtainMessage(MSG_VOLUME_FORGOTTEN, args).sendToTarget();
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07004108 }
Jeff Sharkey7e92ef32015-04-17 17:35:07 -07004109
Jeff Sharkey620b32b2015-04-23 19:36:02 -07004110 private void notifyDiskScanned(DiskInfo disk, int volumeCount) {
Jeff Sharkey7e92ef32015-04-17 17:35:07 -07004111 final SomeArgs args = SomeArgs.obtain();
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07004112 args.arg1 = disk.clone();
Jeff Sharkey620b32b2015-04-23 19:36:02 -07004113 args.argi2 = volumeCount;
4114 obtainMessage(MSG_DISK_SCANNED, args).sendToTarget();
Jeff Sharkey7e92ef32015-04-17 17:35:07 -07004115 }
Makoto Onuki9dc575d2015-06-12 16:10:25 -07004116
4117 private void notifyDiskDestroyed(DiskInfo disk) {
4118 final SomeArgs args = SomeArgs.obtain();
4119 args.arg1 = disk.clone();
4120 obtainMessage(MSG_DISK_DESTROYED, args).sendToTarget();
4121 }
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07004122 }
4123
Kenny Root38cf8862010-09-26 14:18:51 -07004124 @Override
Jeff Sharkey5aca2b82013-10-16 16:21:54 -07004125 protected void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
Jeff Sharkeyfe9a53b2017-03-31 14:08:23 -06004126 if (!DumpUtils.checkDumpPermission(mContext, TAG, writer)) return;
Jeff Sharkey5aca2b82013-10-16 16:21:54 -07004127
4128 final IndentingPrintWriter pw = new IndentingPrintWriter(writer, " ", 160);
Jeff Sharkey27de30d2015-04-18 16:20:27 -07004129 synchronized (mLock) {
4130 pw.println("Disks:");
4131 pw.increaseIndent();
4132 for (int i = 0; i < mDisks.size(); i++) {
4133 final DiskInfo disk = mDisks.valueAt(i);
4134 disk.dump(pw);
4135 }
4136 pw.decreaseIndent();
4137
4138 pw.println();
4139 pw.println("Volumes:");
4140 pw.increaseIndent();
4141 for (int i = 0; i < mVolumes.size(); i++) {
4142 final VolumeInfo vol = mVolumes.valueAt(i);
4143 if (VolumeInfo.ID_PRIVATE_INTERNAL.equals(vol.id)) continue;
4144 vol.dump(pw);
4145 }
4146 pw.decreaseIndent();
4147
4148 pw.println();
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07004149 pw.println("Records:");
Jeff Sharkey27de30d2015-04-18 16:20:27 -07004150 pw.increaseIndent();
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07004151 for (int i = 0; i < mRecords.size(); i++) {
4152 final VolumeRecord note = mRecords.valueAt(i);
4153 note.dump(pw);
Jeff Sharkey27de30d2015-04-18 16:20:27 -07004154 }
4155 pw.decreaseIndent();
Jeff Sharkey275e3e42015-04-24 16:10:32 -07004156
4157 pw.println();
4158 pw.println("Primary storage UUID: " + mPrimaryStorageUuid);
Jeff Sharkeyb0c363b22018-12-15 11:53:03 -07004159
4160 pw.println();
Felipe Leme281389a2016-10-10 17:12:20 -07004161 final Pair<String, Long> pair = StorageManager.getPrimaryStoragePathAndSize();
4162 if (pair == null) {
4163 pw.println("Internal storage total size: N/A");
4164 } else {
4165 pw.print("Internal storage (");
4166 pw.print(pair.first);
4167 pw.print(") total size: ");
4168 pw.print(pair.second);
4169 pw.print(" (");
Jeff Sharkey9f2dc052018-01-07 16:47:31 -07004170 pw.print(DataUnit.MEBIBYTES.toBytes(pair.second));
4171 pw.println(" MiB)");
Felipe Leme281389a2016-10-10 17:12:20 -07004172 }
Jeff Sharkeyb0c363b22018-12-15 11:53:03 -07004173
4174 pw.println();
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07004175 pw.println("Local unlocked users: " + Arrays.toString(mLocalUnlockedUsers));
4176 pw.println("System unlocked users: " + Arrays.toString(mSystemUnlockedUsers));
Jeff Sharkeyb0c363b22018-12-15 11:53:03 -07004177
4178 final ContentResolver cr = mContext.getContentResolver();
4179 pw.println();
4180 pw.println("Isolated storage, local feature flag: "
4181 + Settings.Global.getInt(cr, Settings.Global.ISOLATED_STORAGE_LOCAL, 0));
4182 pw.println("Isolated storage, remote feature flag: "
4183 + Settings.Global.getInt(cr, Settings.Global.ISOLATED_STORAGE_REMOTE, 0));
4184 pw.println("Isolated storage, resolved: " + StorageManager.hasIsolatedStorage());
Jeff Sharkey27de30d2015-04-18 16:20:27 -07004185 }
Kenny Root38cf8862010-09-26 14:18:51 -07004186
Kenny Root38cf8862010-09-26 14:18:51 -07004187 synchronized (mObbMounts) {
Jeff Sharkey27de30d2015-04-18 16:20:27 -07004188 pw.println();
Jeff Sharkey5aca2b82013-10-16 16:21:54 -07004189 pw.println("mObbMounts:");
4190 pw.increaseIndent();
4191 final Iterator<Entry<IBinder, List<ObbState>>> binders = mObbMounts.entrySet()
4192 .iterator();
Kenny Rootaf9d6672010-10-08 09:21:39 -07004193 while (binders.hasNext()) {
4194 Entry<IBinder, List<ObbState>> e = binders.next();
Jeff Sharkey5aca2b82013-10-16 16:21:54 -07004195 pw.println(e.getKey() + ":");
4196 pw.increaseIndent();
Kenny Rootaf9d6672010-10-08 09:21:39 -07004197 final List<ObbState> obbStates = e.getValue();
Kenny Root38cf8862010-09-26 14:18:51 -07004198 for (final ObbState obbState : obbStates) {
Jeff Sharkey5aca2b82013-10-16 16:21:54 -07004199 pw.println(obbState);
Kenny Root38cf8862010-09-26 14:18:51 -07004200 }
Jeff Sharkey5aca2b82013-10-16 16:21:54 -07004201 pw.decreaseIndent();
Kenny Root38cf8862010-09-26 14:18:51 -07004202 }
Jeff Sharkey5aca2b82013-10-16 16:21:54 -07004203 pw.decreaseIndent();
Kenny Rootaf9d6672010-10-08 09:21:39 -07004204
Jeff Sharkey5aca2b82013-10-16 16:21:54 -07004205 pw.println();
4206 pw.println("mObbPathToStateMap:");
4207 pw.increaseIndent();
Kenny Rootaf9d6672010-10-08 09:21:39 -07004208 final Iterator<Entry<String, ObbState>> maps = mObbPathToStateMap.entrySet().iterator();
4209 while (maps.hasNext()) {
4210 final Entry<String, ObbState> e = maps.next();
Jeff Sharkey5aca2b82013-10-16 16:21:54 -07004211 pw.print(e.getKey());
4212 pw.print(" -> ");
4213 pw.println(e.getValue());
Kenny Rootaf9d6672010-10-08 09:21:39 -07004214 }
Jeff Sharkey5aca2b82013-10-16 16:21:54 -07004215 pw.decreaseIndent();
Kenny Root38cf8862010-09-26 14:18:51 -07004216 }
Kenny Root4161f9b2011-07-13 09:48:33 -07004217
Robert Greenwalt470fd722012-01-18 12:51:15 -08004218 pw.println();
Christopher Tate7265abe2014-11-21 13:54:45 -08004219 pw.print("Last maintenance: ");
Jeff Sharkeye8a4b662015-06-27 15:43:45 -07004220 pw.println(TimeUtils.formatForLogging(mLastMaintenance));
Kenny Root38cf8862010-09-26 14:18:51 -07004221 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004222
Jeff Sharkeyfa23c5a2011-08-09 21:44:24 -07004223 /** {@inheritDoc} */
Jeff Sharkey48877892015-03-18 11:27:19 -07004224 @Override
Jeff Sharkeyfa23c5a2011-08-09 21:44:24 -07004225 public void monitor() {
Jeff Sharkey54402792017-09-15 16:05:19 -06004226 try {
4227 mVold.monitor();
4228 } catch (Exception e) {
4229 Slog.wtf(TAG, e);
Paul Lawrence1c62cbb2015-06-03 14:14:52 -07004230 }
Jeff Sharkeyfa23c5a2011-08-09 21:44:24 -07004231 }
Svet Ganov6ee871e2015-07-10 14:29:33 -07004232
Sudheer Shanka2250d562016-11-07 15:41:02 -08004233 private final class StorageManagerInternalImpl extends StorageManagerInternal {
Svet Ganov6ee871e2015-07-10 14:29:33 -07004234 // Not guarded by a lock.
4235 private final CopyOnWriteArrayList<ExternalStorageMountPolicy> mPolicies =
4236 new CopyOnWriteArrayList<>();
4237
Risanaec0ee72018-10-31 10:10:12 +09004238 @GuardedBy("mResetListeners")
4239 private final List<StorageManagerInternal.ResetListener> mResetListeners =
4240 new ArrayList<>();
4241
Svet Ganov6ee871e2015-07-10 14:29:33 -07004242 @Override
4243 public void addExternalStoragePolicy(ExternalStorageMountPolicy policy) {
4244 // No locking - CopyOnWriteArrayList
4245 mPolicies.add(policy);
4246 }
4247
4248 @Override
4249 public void onExternalStoragePolicyChanged(int uid, String packageName) {
4250 final int mountMode = getExternalStorageMountMode(uid, packageName);
4251 remountUidExternalStorage(uid, mountMode);
4252 }
4253
4254 @Override
4255 public int getExternalStorageMountMode(int uid, String packageName) {
Sudheer Shanka3a0df3b2018-12-12 12:43:43 -08004256 if (ENABLE_ISOLATED_STORAGE) {
4257 return getMountMode(uid, packageName);
4258 }
Sudheer Shankab1613982019-05-16 16:55:50 -07004259 try {
4260 if (packageName == null) {
4261 final String[] packagesForUid = mIPackageManager.getPackagesForUid(uid);
4262 packageName = packagesForUid[0];
4263 }
4264 } catch (RemoteException e) {
4265 // Should not happen - same process
4266 }
Svet Ganov6ee871e2015-07-10 14:29:33 -07004267 // No locking - CopyOnWriteArrayList
4268 int mountMode = Integer.MAX_VALUE;
4269 for (ExternalStorageMountPolicy policy : mPolicies) {
4270 final int policyMode = policy.getMountMode(uid, packageName);
4271 if (policyMode == Zygote.MOUNT_EXTERNAL_NONE) {
4272 return Zygote.MOUNT_EXTERNAL_NONE;
4273 }
4274 mountMode = Math.min(mountMode, policyMode);
4275 }
4276 if (mountMode == Integer.MAX_VALUE) {
4277 return Zygote.MOUNT_EXTERNAL_NONE;
4278 }
4279 return mountMode;
4280 }
4281
Risanaec0ee72018-10-31 10:10:12 +09004282 @Override
4283 public void addResetListener(StorageManagerInternal.ResetListener listener) {
4284 synchronized (mResetListeners) {
4285 mResetListeners.add(listener);
4286 }
4287 }
4288
4289 public void onReset(IVold vold) {
4290 synchronized (mResetListeners) {
4291 for (StorageManagerInternal.ResetListener listener : mResetListeners) {
4292 listener.onReset(vold);
4293 }
4294 }
4295 }
4296
Martijn Coenen73918202019-12-09 17:02:44 +01004297 @Override
4298 public void resetUser(int userId) {
4299 // TODO(b/145931219): ideally, we only reset storage for the user in question,
4300 // but for now, reset everything.
4301 mHandler.obtainMessage(H_RESET).sendToTarget();
4302 }
4303
Svet Ganov6ee871e2015-07-10 14:29:33 -07004304 public boolean hasExternalStorage(int uid, String packageName) {
Amith Yamasani2bd5cff2015-07-22 14:42:31 -07004305 // No need to check for system uid. This avoids a deadlock between
4306 // PackageManagerService and AppOpsService.
4307 if (uid == Process.SYSTEM_UID) {
4308 return true;
4309 }
Sudheer Shanka3a0df3b2018-12-12 12:43:43 -08004310 if (ENABLE_ISOLATED_STORAGE) {
4311 return getMountMode(uid, packageName) != Zygote.MOUNT_EXTERNAL_NONE;
4312 }
Svet Ganov6ee871e2015-07-10 14:29:33 -07004313 // No locking - CopyOnWriteArrayList
4314 for (ExternalStorageMountPolicy policy : mPolicies) {
4315 final boolean policyHasStorage = policy.hasExternalStorage(uid, packageName);
4316 if (!policyHasStorage) {
4317 return false;
4318 }
4319 }
4320 return true;
4321 }
Sudheer Shankab1613982019-05-16 16:55:50 -07004322
4323 public void onAppOpsChanged(int code, int uid,
4324 @Nullable String packageName, int mode) {
Martijn Coenen28ec85a2020-01-28 17:02:23 +01004325 if (code == OP_REQUEST_INSTALL_PACKAGES && mIsFuseEnabled) {
4326 // When using FUSE, we basically have no other choice but to kill the app
4327 // after the app op is either granted or rejected.
4328 final IActivityManager am = ActivityManager.getService();
4329 try {
4330 am.killApplication(packageName,
4331 UserHandle.getAppId(uid),
4332 UserHandle.USER_ALL, AppOpsManager.opToName(code) + " changed.");
4333 } catch (RemoteException e) {
4334 }
4335
4336 return;
4337 }
Sudheer Shankab1613982019-05-16 16:55:50 -07004338 if (mode == MODE_ALLOWED && (code == OP_READ_EXTERNAL_STORAGE
4339 || code == OP_WRITE_EXTERNAL_STORAGE
4340 || code == OP_REQUEST_INSTALL_PACKAGES)) {
4341 final long token = Binder.clearCallingIdentity();
4342 try {
4343 final UserManagerInternal userManagerInternal =
4344 LocalServices.getService(UserManagerInternal.class);
4345 if (userManagerInternal.isUserInitialized(UserHandle.getUserId(uid))) {
4346 onExternalStoragePolicyChanged(uid, packageName);
4347 }
4348 } finally {
4349 Binder.restoreCallingIdentity(token);
4350 }
4351 }
4352 }
Svet Ganov6ee871e2015-07-10 14:29:33 -07004353 }
Jeff Sharkeyfa23c5a2011-08-09 21:44:24 -07004354}