blob: 0a6473ab92d9df36456006f49f37d4f76b41b857 [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
Sudheer Shanka3a0df3b2018-12-12 12:43:43 -080019import static android.Manifest.permission.INSTALL_PACKAGES;
Jeff Sharkey6fd69942019-03-26 17:53:35 -060020import static android.Manifest.permission.READ_EXTERNAL_STORAGE;
21import static android.Manifest.permission.WRITE_EXTERNAL_STORAGE;
Sudheer Shanka3a0df3b2018-12-12 12:43:43 -080022import static android.Manifest.permission.WRITE_MEDIA_STORAGE;
Zim64726cb2019-11-27 13:06:34 +000023import static android.app.ActivityManager.PROCESS_STATE_NONEXISTENT;
Sudheer Shanka3a0df3b2018-12-12 12:43:43 -080024import static android.app.AppOpsManager.MODE_ALLOWED;
Jeff Sharkey11697f52018-12-13 10:14:42 -070025import static android.app.AppOpsManager.OP_LEGACY_STORAGE;
Jeff Sharkey6fd69942019-03-26 17:53:35 -060026import static android.app.AppOpsManager.OP_READ_EXTERNAL_STORAGE;
Sudheer Shanka3a0df3b2018-12-12 12:43:43 -080027import static android.app.AppOpsManager.OP_REQUEST_INSTALL_PACKAGES;
Jeff Sharkey6fd69942019-03-26 17:53:35 -060028import static android.app.AppOpsManager.OP_WRITE_EXTERNAL_STORAGE;
Sudheer Shanka3a0df3b2018-12-12 12:43:43 -080029import static android.content.pm.PackageManager.PERMISSION_GRANTED;
Jeff Sharkey39466322018-12-05 19:19:52 -070030import static android.os.ParcelFileDescriptor.MODE_READ_WRITE;
Jeff Sharkey0095a822018-02-15 13:06:53 -070031import static android.os.storage.OnObbStateChangeListener.ERROR_ALREADY_MOUNTED;
32import static android.os.storage.OnObbStateChangeListener.ERROR_COULD_NOT_MOUNT;
33import static android.os.storage.OnObbStateChangeListener.ERROR_COULD_NOT_UNMOUNT;
34import static android.os.storage.OnObbStateChangeListener.ERROR_INTERNAL;
35import static android.os.storage.OnObbStateChangeListener.ERROR_NOT_MOUNTED;
36import static android.os.storage.OnObbStateChangeListener.ERROR_PERMISSION_DENIED;
37import static android.os.storage.OnObbStateChangeListener.MOUNTED;
38import static android.os.storage.OnObbStateChangeListener.UNMOUNTED;
Jeff Sharkey5790af02018-08-13 17:42:54 -060039
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -070040import static com.android.internal.util.XmlUtils.readIntAttribute;
Jeff Sharkeye8a4b662015-06-27 15:43:45 -070041import static com.android.internal.util.XmlUtils.readLongAttribute;
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -070042import static com.android.internal.util.XmlUtils.readStringAttribute;
43import static com.android.internal.util.XmlUtils.writeIntAttribute;
Jeff Sharkeye8a4b662015-06-27 15:43:45 -070044import static com.android.internal.util.XmlUtils.writeLongAttribute;
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -070045import static com.android.internal.util.XmlUtils.writeStringAttribute;
Jeff Sharkey5790af02018-08-13 17:42:54 -060046
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -070047import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT;
48import static org.xmlpull.v1.XmlPullParser.START_TAG;
49
Jason parks8888c592011-01-20 22:46:41 -060050import android.Manifest;
Jeff Sharkeyef10ee02015-07-05 14:17:27 -070051import android.annotation.Nullable;
Xiaohui Chen621b3fc2015-10-02 14:41:42 -070052import android.app.ActivityManager;
Martijn Coenen7084c6a2019-11-22 16:32:09 +010053import android.app.ActivityManagerInternal;
Jeff Sharkey2d8b4e82013-09-17 17:30:33 -070054import android.app.AppOpsManager;
Jeff Sharkey14cbe522015-07-08 14:06:37 -070055import android.app.IActivityManager;
Jeff Sharkey9765e442017-12-14 22:15:14 -070056import android.app.KeyguardManager;
Pavel Grafovce72ef02018-01-10 17:14:11 +000057import android.app.admin.SecurityLog;
Jeff Sharkey9bed0702017-01-23 20:37:05 -070058import android.app.usage.StorageStatsManager;
Jeff Sharkeybcd262d2015-06-10 09:41:17 -070059import android.content.BroadcastReceiver;
Jeff Sharkeyb0c363b22018-12-15 11:53:03 -070060import android.content.ContentResolver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080061import android.content.Context;
62import android.content.Intent;
Jeff Sharkeybcd262d2015-06-10 09:41:17 -070063import android.content.IntentFilter;
Sudheer Shanka3a0df3b2018-12-12 12:43:43 -080064import android.content.pm.IPackageManager;
Jeff Sharkey275e3e42015-04-24 16:10:32 -070065import android.content.pm.IPackageMoveObserver;
66import android.content.pm.PackageManager;
Sudheer Shanka0a541a52018-07-31 13:21:11 -070067import android.content.pm.PackageManagerInternal;
Jeff Sharkey14cbe522015-07-08 14:06:37 -070068import android.content.pm.ProviderInfo;
Jeff Sharkeybcd262d2015-06-10 09:41:17 -070069import android.content.pm.UserInfo;
Elliott Hughesf839b4f2014-09-26 12:30:47 -070070import android.content.res.Configuration;
Kenny Root02c87302010-07-01 08:10:18 -070071import android.content.res.ObbInfo;
Daniel Colascione766b6322018-01-08 19:10:36 -080072import android.database.ContentObserver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080073import android.net.Uri;
Kenny Root02c87302010-07-01 08:10:18 -070074import android.os.Binder;
Jeff Sharkey4c099d02015-05-15 13:45:00 -070075import android.os.DropBoxManager;
Kenny Roota02b8b02010-08-05 16:14:17 -070076import android.os.Environment;
Jeff Sharkeyb049e212012-09-07 23:16:01 -070077import android.os.Environment.UserEnvironment;
Jeff Sharkey48877892015-03-18 11:27:19 -070078import android.os.FileUtils;
Suchi Amalapurapuc42e29e2010-02-22 16:03:53 -080079import android.os.Handler;
Dianne Hackbornefa92b22013-05-03 14:11:43 -070080import android.os.HandlerThread;
Kenny Roota02b8b02010-08-05 16:14:17 -070081import android.os.IBinder;
Jin Qian12690d52017-10-13 18:17:04 -070082import android.os.IStoraged;
Jeff Sharkey1019de92017-09-06 13:47:03 -060083import android.os.IVold;
Jeff Sharkey8058fe62017-09-13 11:50:33 -060084import android.os.IVoldListener;
Zim95eca1d2019-11-15 18:03:00 +000085import android.os.IVoldMountCallback;
Jeff Sharkeyb302c542017-09-15 12:57:59 -060086import android.os.IVoldTaskListener;
Daniel Sandler5f27ef42010-03-16 15:42:02 -040087import android.os.Looper;
Suchi Amalapurapuc42e29e2010-02-22 16:03:53 -080088import android.os.Message;
Daichi Hirono9e8d9e22015-11-13 14:37:00 +090089import android.os.ParcelFileDescriptor;
Jeff Sharkey500ce9e2017-02-12 02:39:24 -070090import android.os.ParcelableException;
Jeff Sharkeyb302c542017-09-15 12:57:59 -060091import android.os.PersistableBundle;
Jeff Sharkeyce14cd02015-12-07 15:35:42 -070092import android.os.PowerManager;
Jeff Sharkey9527b222015-06-24 15:24:48 -070093import android.os.Process;
Jeff Sharkey7151a9a2015-04-04 15:22:37 -070094import android.os.RemoteCallbackList;
San Mehat4270e1e2010-01-29 05:32:19 -080095import android.os.RemoteException;
Suchi Amalapurapufd3530f2010-01-18 00:15:59 -080096import android.os.ServiceManager;
Paul Crowleyfc0b5192018-07-02 13:58:10 -070097import android.os.ServiceSpecificException;
Jeff Sharkeyedcdaf62015-07-09 09:45:36 -070098import android.os.SystemClock;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080099import android.os.SystemProperties;
Dianne Hackbornf02b60a2012-08-16 10:48:27 -0700100import android.os.UserHandle;
Emily Bernier92aa5a22014-07-07 10:11:48 -0400101import android.os.UserManager;
Sudheer Shankab1613982019-05-16 16:55:50 -0700102import android.os.UserManagerInternal;
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -0700103import android.os.storage.DiskInfo;
Kenny Roota02b8b02010-08-05 16:14:17 -0700104import android.os.storage.IObbActionListener;
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -0700105import android.os.storage.IStorageEventListener;
Sudheer Shanka2250d562016-11-07 15:41:02 -0800106import android.os.storage.IStorageManager;
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -0700107import android.os.storage.IStorageShutdownObserver;
Kenny Rootaf9d6672010-10-08 09:21:39 -0700108import android.os.storage.OnObbStateChangeListener;
Paul Lawrence46791e72014-04-03 09:10:26 -0700109import android.os.storage.StorageManager;
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -0700110import android.os.storage.StorageManagerInternal;
Mike Lockwood2f6a3882011-05-09 19:08:06 -0700111import android.os.storage.StorageVolume;
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -0700112import android.os.storage.VolumeInfo;
Jeff Sharkeyb36586a2015-04-27 08:42:28 -0700113import android.os.storage.VolumeRecord;
Jeff Sharkey5d0c55c2019-01-24 14:32:31 -0700114import android.provider.DeviceConfig;
Jeff Sharkey14cbe522015-07-08 14:06:37 -0700115import android.provider.MediaStore;
Jeff Sharkeye8a4b662015-06-27 15:43:45 -0700116import android.provider.Settings;
Inseob Kimc1246e62018-11-08 13:13:54 +0900117import android.sysprop.VoldProperties;
Jason parksf7b3cd42011-01-27 09:28:25 -0600118import android.text.TextUtils;
Jeff Sharkey1783f142015-04-17 10:52:51 -0700119import android.text.format.DateUtils;
Jeff Sharkey48877892015-03-18 11:27:19 -0700120import android.util.ArrayMap;
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700121import android.util.AtomicFile;
Jeff Sharkey9f2dc052018-01-07 16:47:31 -0700122import android.util.DataUnit;
Abhijeet Kaurb9847712019-11-19 16:35:47 +0000123import android.util.FeatureFlagUtils;
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -0700124import android.util.Log;
Felipe Leme281389a2016-10-10 17:12:20 -0700125import android.util.Pair;
San Mehata5078592010-03-25 09:36:54 -0700126import android.util.Slog;
Jeff Sharkeye8a4b662015-06-27 15:43:45 -0700127import android.util.TimeUtils;
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700128import android.util.Xml;
Jeff Sharkey48877892015-03-18 11:27:19 -0700129
Jeff Sharkey8b2c3a142012-11-12 11:45:05 -0800130import com.android.internal.annotations.GuardedBy;
Sudheer Shankaff971bc2018-12-13 17:39:59 -0800131import com.android.internal.app.IAppOpsCallback;
Sudheer Shanka3a0df3b2018-12-12 12:43:43 -0800132import com.android.internal.app.IAppOpsService;
Daichi Hirono9fb00182016-11-08 14:12:17 +0900133import com.android.internal.os.AppFuseMount;
Jeff Sharkey1019de92017-09-06 13:47:03 -0600134import com.android.internal.os.BackgroundThread;
Daichi Hirono812c95d2017-02-08 16:20:20 +0900135import com.android.internal.os.FuseUnavailableMountException;
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700136import com.android.internal.os.SomeArgs;
Jeff Sharkey9527b222015-06-24 15:24:48 -0700137import com.android.internal.os.Zygote;
Jeff Sharkey48877892015-03-18 11:27:19 -0700138import com.android.internal.util.ArrayUtils;
Jeff Sharkey11697f52018-12-13 10:14:42 -0700139import com.android.internal.util.CollectionUtils;
Jeff Sharkeyfe9a53b2017-03-31 14:08:23 -0600140import com.android.internal.util.DumpUtils;
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700141import com.android.internal.util.FastXmlSerializer;
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -0800142import com.android.internal.util.HexDump;
Jeff Sharkey5aca2b82013-10-16 16:21:54 -0700143import com.android.internal.util.IndentingPrintWriter;
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700144import com.android.internal.util.Preconditions;
Jeff Sharkeyb9fe5372015-12-03 15:23:08 -0700145import com.android.internal.widget.LockPatternUtils;
Daichi Hirono9fb00182016-11-08 14:12:17 +0900146import com.android.server.storage.AppFuseBridge;
Zim42f1e9f2019-08-15 17:35:00 +0100147import com.android.server.storage.StorageSessionController;
Zim17be6f92019-09-25 14:37:55 +0100148import com.android.server.storage.StorageSessionController.ExternalStorageServiceException;
Wale Ogunwale9e4f3e02018-05-17 09:35:39 -0700149import com.android.server.wm.ActivityTaskManagerInternal;
150import com.android.server.wm.ActivityTaskManagerInternal.ScreenObserver;
Jeff Sharkey5217cac2015-12-20 15:34:01 -0700151
Jeff Sharkey5790af02018-08-13 17:42:54 -0600152import libcore.io.IoUtils;
153import libcore.util.EmptyArray;
154
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700155import org.xmlpull.v1.XmlPullParser;
156import org.xmlpull.v1.XmlPullParserException;
157import org.xmlpull.v1.XmlSerializer;
158
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700159import java.io.File;
Kenny Root38cf8862010-09-26 14:18:51 -0700160import java.io.FileDescriptor;
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700161import java.io.FileInputStream;
162import java.io.FileNotFoundException;
Christopher Tate7265abe2014-11-21 13:54:45 -0800163import java.io.FileOutputStream;
Kenny Root05105f72010-09-22 17:29:43 -0700164import java.io.IOException;
Kenny Root38cf8862010-09-26 14:18:51 -0700165import java.io.PrintWriter;
Kenny Root3b1abba2010-10-13 15:00:07 -0700166import java.math.BigInteger;
Paul Lawrence8e397362014-01-27 15:22:30 -0800167import java.nio.charset.StandardCharsets;
Jeff Sharkey0095a822018-02-15 13:06:53 -0700168import java.security.GeneralSecurityException;
Kenny Root3b1abba2010-10-13 15:00:07 -0700169import java.security.spec.KeySpec;
San Mehat22dd86e2010-01-12 12:21:18 -0800170import java.util.ArrayList;
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -0800171import java.util.Arrays;
Kenny Roota02b8b02010-08-05 16:14:17 -0700172import java.util.HashMap;
Kenny Root38cf8862010-09-26 14:18:51 -0700173import java.util.Iterator;
Kenny Roota02b8b02010-08-05 16:14:17 -0700174import java.util.LinkedList;
175import java.util.List;
Elliott Hughesf839b4f2014-09-26 12:30:47 -0700176import java.util.Locale;
Kenny Roota02b8b02010-08-05 16:14:17 -0700177import java.util.Map;
Kenny Root38cf8862010-09-26 14:18:51 -0700178import java.util.Map.Entry;
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700179import java.util.Objects;
Svet Ganov6ee871e2015-07-10 14:29:33 -0700180import java.util.concurrent.CopyOnWriteArrayList;
Kenny Root51a573c2012-05-17 13:30:28 -0700181import java.util.concurrent.CountDownLatch;
182import java.util.concurrent.TimeUnit;
Jeff Sharkeyedcdaf62015-07-09 09:45:36 -0700183import java.util.concurrent.TimeoutException;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800184
Kenny Root3b1abba2010-10-13 15:00:07 -0700185import javax.crypto.SecretKey;
186import javax.crypto.SecretKeyFactory;
187import javax.crypto.spec.PBEKeySpec;
188
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800189/**
Jeff Sharkey48877892015-03-18 11:27:19 -0700190 * Service responsible for various storage media. Connects to {@code vold} to
191 * watch for and manage dynamically added storage, such as SD cards and USB mass
192 * storage. Also decides how storage should be presented to users on the device.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800193 */
Jeff Sharkey9765e442017-12-14 22:15:14 -0700194class StorageManagerService extends IStorageManager.Stub
195 implements Watchdog.Monitor, ScreenObserver {
Jason parks5af0b912010-11-29 09:05:25 -0600196
Christopher Tated417d622013-08-19 16:14:25 -0700197 // Static direct instance pointer for the tightly-coupled idle service to use
Sudheer Shanka2250d562016-11-07 15:41:02 -0800198 static StorageManagerService sSelf = null;
Christopher Tated417d622013-08-19 16:14:25 -0700199
Daniel Colascione766b6322018-01-08 19:10:36 -0800200 /* Read during boot to decide whether to enable zram when available */
201 private static final String ZRAM_ENABLED_PROPERTY =
Sudheer Shanka0a541a52018-07-31 13:21:11 -0700202 "persist.sys.zram_enabled";
203
Jeff Sharkey10ec9d82018-11-28 14:52:45 -0700204 private static final boolean ENABLE_ISOLATED_STORAGE = StorageManager.hasIsolatedStorage();
Sudheer Shanka0a541a52018-07-31 13:21:11 -0700205
Matt Pape19ea8a62019-03-18 10:38:25 -0700206 /**
207 * If {@code 1}, enables the isolated storage feature. If {@code -1},
208 * disables the isolated storage feature. If {@code 0}, uses the default
209 * value from the build system.
210 */
211 private static final String ISOLATED_STORAGE_ENABLED = "isolated_storage_enabled";
212
shafikb2992b62019-10-01 15:31:02 +0100213 /**
214 * If {@code 1}, enables FuseDaemon to intercept file system ops. If {@code -1},
215 * disables FuseDaemon. If {@code 0}, uses the default value from the build system.
216 */
217 private static final String FUSE_ENABLED = "fuse_enabled";
218
Jeff Sharkey56e62932015-03-21 20:41:00 -0700219 public static class Lifecycle extends SystemService {
Sudheer Shanka2250d562016-11-07 15:41:02 -0800220 private StorageManagerService mStorageManagerService;
Jeff Sharkey56e62932015-03-21 20:41:00 -0700221
222 public Lifecycle(Context context) {
223 super(context);
224 }
225
226 @Override
227 public void onStart() {
Sudheer Shanka2250d562016-11-07 15:41:02 -0800228 mStorageManagerService = new StorageManagerService(getContext());
229 publishBinderService("mount", mStorageManagerService);
230 mStorageManagerService.start();
Jeff Sharkey56e62932015-03-21 20:41:00 -0700231 }
232
233 @Override
234 public void onBootPhase(int phase) {
Jeff Sharkey11697f52018-12-13 10:14:42 -0700235 if (phase == SystemService.PHASE_SYSTEM_SERVICES_READY) {
236 mStorageManagerService.servicesReady();
237 } else if (phase == SystemService.PHASE_ACTIVITY_MANAGER_READY) {
Sudheer Shanka2250d562016-11-07 15:41:02 -0800238 mStorageManagerService.systemReady();
Yasuhiro Matsuda87a38b52015-07-24 22:10:16 +0900239 } else if (phase == SystemService.PHASE_BOOT_COMPLETED) {
Sudheer Shanka2250d562016-11-07 15:41:02 -0800240 mStorageManagerService.bootCompleted();
Jeff Sharkey56e62932015-03-21 20:41:00 -0700241 }
242 }
Jeff Sharkey48877892015-03-18 11:27:19 -0700243
244 @Override
Jeff Sharkeyab15c392016-05-05 11:45:01 -0600245 public void onSwitchUser(int userHandle) {
Sudheer Shanka2250d562016-11-07 15:41:02 -0800246 mStorageManagerService.mCurrentUserId = userHandle;
Jeff Sharkeyab15c392016-05-05 11:45:01 -0600247 }
248
249 @Override
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700250 public void onUnlockUser(int userHandle) {
Sudheer Shanka2250d562016-11-07 15:41:02 -0800251 mStorageManagerService.onUnlockUser(userHandle);
Jeff Sharkey48877892015-03-18 11:27:19 -0700252 }
253
254 @Override
255 public void onCleanupUser(int userHandle) {
Sudheer Shanka2250d562016-11-07 15:41:02 -0800256 mStorageManagerService.onCleanupUser(userHandle);
Jeff Sharkey48877892015-03-18 11:27:19 -0700257 }
Martijn Coenen7084c6a2019-11-22 16:32:09 +0100258
259 @Override
260 public void onStopUser(int userHandle) {
261 mStorageManagerService.onStopUser(userHandle);
262 }
Jeff Sharkey56e62932015-03-21 20:41:00 -0700263 }
264
Dianne Hackborn40e9f292012-11-27 19:12:23 -0800265 private static final boolean DEBUG_EVENTS = false;
Kenny Rootb7db2722011-01-25 16:39:35 -0800266 private static final boolean DEBUG_OBB = false;
Kenny Root02c87302010-07-01 08:10:18 -0700267
Jeff Sharkeyc3c72872018-06-06 15:35:53 -0600268 /**
269 * We now talk to vold over Binder, and it has its own internal lock to
270 * serialize certain calls. All long-running operations have been migrated
271 * to be async with callbacks, so we want watchdog to fire if vold wedges.
272 */
273 private static final boolean WATCHDOG_ENABLE = true;
Kenny Root07714d42011-08-17 17:49:28 -0700274
Jeff Sharkey00455bf2016-11-04 14:45:24 -0600275 /**
276 * Our goal is for all Android devices to be usable as development devices,
277 * which includes the new Direct Boot mode added in N. For devices that
278 * don't have native FBE support, we offer an emulation mode for developer
279 * testing purposes, but if it's prohibitively difficult to support this
280 * mode, it can be disabled for specific products using this flag.
281 */
282 private static final boolean EMULATE_FBE_SUPPORTED = true;
283
Sudheer Shanka2250d562016-11-07 15:41:02 -0800284 private static final String TAG = "StorageManagerService";
Jeff Sharkey6fd69942019-03-26 17:53:35 -0600285 private static final boolean LOCAL_LOGV = Log.isLoggable(TAG, Log.VERBOSE);
Jeff Sharkeye8a4b662015-06-27 15:43:45 -0700286
Jeff Sharkey9756d752015-05-14 21:07:42 -0700287 private static final String TAG_STORAGE_BENCHMARK = "storage_benchmark";
Jeff Sharkeye8a4b662015-06-27 15:43:45 -0700288 private static final String TAG_STORAGE_TRIM = "storage_trim";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800289
Jeff Sharkey275e3e42015-04-24 16:10:32 -0700290 /** Magic value sent by MoveTask.cpp */
291 private static final int MOVE_STATUS_COPY_FINISHED = 82;
292
Jeff Sharkey620b32b2015-04-23 19:36:02 -0700293 private static final int VERSION_INIT = 1;
294 private static final int VERSION_ADD_PRIMARY = 2;
Jeff Sharkeyfced5342015-05-10 14:53:34 -0700295 private static final int VERSION_FIX_PRIMARY = 3;
Jeff Sharkey620b32b2015-04-23 19:36:02 -0700296
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700297 private static final String TAG_VOLUMES = "volumes";
Jeff Sharkey620b32b2015-04-23 19:36:02 -0700298 private static final String ATTR_VERSION = "version";
299 private static final String ATTR_PRIMARY_STORAGE_UUID = "primaryStorageUuid";
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700300 private static final String TAG_VOLUME = "volume";
301 private static final String ATTR_TYPE = "type";
302 private static final String ATTR_FS_UUID = "fsUuid";
Jeff Sharkey5cc0df22015-06-17 19:44:05 -0700303 private static final String ATTR_PART_GUID = "partGuid";
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700304 private static final String ATTR_NICKNAME = "nickname";
305 private static final String ATTR_USER_FLAGS = "userFlags";
Jeff Sharkeye8a4b662015-06-27 15:43:45 -0700306 private static final String ATTR_CREATED_MILLIS = "createdMillis";
Jeff Sharkey3811f352019-05-14 11:54:36 -0600307 private static final String ATTR_LAST_SEEN_MILLIS = "lastSeenMillis";
Jeff Sharkeye8a4b662015-06-27 15:43:45 -0700308 private static final String ATTR_LAST_TRIM_MILLIS = "lastTrimMillis";
309 private static final String ATTR_LAST_BENCH_MILLIS = "lastBenchMillis";
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700310
Philip P. Moltmannc94ba822019-03-04 16:48:22 -0800311 private static final String[] ALL_STORAGE_PERMISSIONS = {
312 Manifest.permission.READ_EXTERNAL_STORAGE,
Philip P. Moltmann129a0b02019-03-27 12:24:45 -0700313 Manifest.permission.WRITE_EXTERNAL_STORAGE
Philip P. Moltmannc94ba822019-03-04 16:48:22 -0800314 };
315
Jeff Sharkeyb36586a2015-04-27 08:42:28 -0700316 private final AtomicFile mSettingsFile;
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700317
Jeff Sharkey48877892015-03-18 11:27:19 -0700318 /**
319 * <em>Never</em> hold the lock while performing downcalls into vold, since
320 * unsolicited events can suddenly appear to update data structures.
321 */
Jeff Sharkey5f3e9342017-03-13 14:53:11 -0600322 private final Object mLock = LockGuard.installNewLock(LockGuard.INDEX_STORAGE);
Jeff Sharkey48877892015-03-18 11:27:19 -0700323
Sudheer Shanka0a541a52018-07-31 13:21:11 -0700324 /**
325 * Similar to {@link #mLock}, never hold this lock while performing downcalls into vold.
326 * Also, never hold this while calling into PackageManagerService since it is used in callbacks
327 * from PackageManagerService.
328 *
329 * If both {@link #mLock} and this lock need to be held, {@link #mLock} should be acquired
330 * before this.
331 *
332 * Use -PL suffix for methods that need to called with this lock held.
333 */
334 private final Object mPackagesLock = new Object();
335
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700336 /** Set of users that we know are unlocked. */
Jeff Sharkey48877892015-03-18 11:27:19 -0700337 @GuardedBy("mLock")
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700338 private int[] mLocalUnlockedUsers = EmptyArray.INT;
339 /** Set of users that system knows are unlocked. */
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -0800340 @GuardedBy("mLock")
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700341 private int[] mSystemUnlockedUsers = EmptyArray.INT;
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700342
343 /** Map from disk ID to disk */
Jeff Sharkey48877892015-03-18 11:27:19 -0700344 @GuardedBy("mLock")
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -0700345 private ArrayMap<String, DiskInfo> mDisks = new ArrayMap<>();
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700346 /** Map from volume ID to disk */
Jeff Sharkey48877892015-03-18 11:27:19 -0700347 @GuardedBy("mLock")
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700348 private final ArrayMap<String, VolumeInfo> mVolumes = new ArrayMap<>();
Jeff Sharkey48877892015-03-18 11:27:19 -0700349
Jeff Sharkeyb36586a2015-04-27 08:42:28 -0700350 /** Map from UUID to record */
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700351 @GuardedBy("mLock")
Jeff Sharkeyb36586a2015-04-27 08:42:28 -0700352 private ArrayMap<String, VolumeRecord> mRecords = new ArrayMap<>();
Jeff Sharkey620b32b2015-04-23 19:36:02 -0700353 @GuardedBy("mLock")
354 private String mPrimaryStorageUuid;
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700355
Jeff Sharkeyeba260d2015-04-19 14:35:16 -0700356 /** Map from disk ID to latches */
357 @GuardedBy("mLock")
358 private ArrayMap<String, CountDownLatch> mDiskScanLatches = new ArrayMap<>();
359
Jeff Sharkey275e3e42015-04-24 16:10:32 -0700360 @GuardedBy("mLock")
361 private IPackageMoveObserver mMoveCallback;
362 @GuardedBy("mLock")
363 private String mMoveTargetUuid;
364
Martijn Coenen44db1ac2019-12-03 16:06:19 +0100365 private volatile int mMediaStoreAuthorityAppId = -1;
Zim74a9bba2019-09-03 20:49:13 +0100366
Jeff Sharkeyab15c392016-05-05 11:45:01 -0600367 private volatile int mCurrentUserId = UserHandle.USER_SYSTEM;
368
Daichi Hirono9fb00182016-11-08 14:12:17 +0900369 /** Holding lock for AppFuse business */
370 private final Object mAppFuseLock = new Object();
371
372 @GuardedBy("mAppFuseLock")
373 private int mNextAppFuseName = 0;
374
375 @GuardedBy("mAppFuseLock")
Daichi Hironoe56740d2017-02-02 13:56:45 +0900376 private AppFuseBridge mAppFuseBridge = null;
Daichi Hirono9fb00182016-11-08 14:12:17 +0900377
Jeff Sharkeyef10ee02015-07-05 14:17:27 -0700378 private VolumeInfo findVolumeByIdOrThrow(String id) {
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700379 synchronized (mLock) {
380 final VolumeInfo vol = mVolumes.get(id);
381 if (vol != null) {
382 return vol;
383 }
384 }
385 throw new IllegalArgumentException("No volume found for ID " + id);
386 }
387
Jeff Sharkeyef10ee02015-07-05 14:17:27 -0700388 private String findVolumeIdForPathOrThrow(String path) {
Jeff Sharkey48877892015-03-18 11:27:19 -0700389 synchronized (mLock) {
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -0700390 for (int i = 0; i < mVolumes.size(); i++) {
391 final VolumeInfo vol = mVolumes.valueAt(i);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700392 if (vol.path != null && path.startsWith(vol.path)) {
393 return vol.id;
Jeff Sharkey48877892015-03-18 11:27:19 -0700394 }
395 }
396 }
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700397 throw new IllegalArgumentException("No volume found for path " + path);
Jeff Sharkey48877892015-03-18 11:27:19 -0700398 }
399
Jeff Sharkeye8a4b662015-06-27 15:43:45 -0700400 private VolumeRecord findRecordForPath(String path) {
401 synchronized (mLock) {
402 for (int i = 0; i < mVolumes.size(); i++) {
403 final VolumeInfo vol = mVolumes.valueAt(i);
404 if (vol.path != null && path.startsWith(vol.path)) {
405 return mRecords.get(vol.fsUuid);
406 }
407 }
408 }
409 return null;
410 }
411
412 private String scrubPath(String path) {
413 if (path.startsWith(Environment.getDataDirectory().getAbsolutePath())) {
414 return "internal";
415 }
416 final VolumeRecord rec = findRecordForPath(path);
417 if (rec == null || rec.createdMillis == 0) {
418 return "unknown";
419 } else {
420 return "ext:" + (int) ((System.currentTimeMillis() - rec.createdMillis)
421 / DateUtils.WEEK_IN_MILLIS) + "w";
422 }
423 }
424
Jeff Sharkeyef10ee02015-07-05 14:17:27 -0700425 private @Nullable VolumeInfo findStorageForUuid(String volumeUuid) {
Jeff Sharkey275e3e42015-04-24 16:10:32 -0700426 final StorageManager storage = mContext.getSystemService(StorageManager.class);
427 if (Objects.equals(StorageManager.UUID_PRIVATE_INTERNAL, volumeUuid)) {
Zim17be6f92019-09-25 14:37:55 +0100428 return storage.findVolumeById(VolumeInfo.ID_EMULATED_INTERNAL + ";" + 0);
Jeff Sharkey275e3e42015-04-24 16:10:32 -0700429 } else if (Objects.equals(StorageManager.UUID_PRIMARY_PHYSICAL, volumeUuid)) {
430 return storage.getPrimaryPhysicalVolume();
431 } else {
432 return storage.findEmulatedForPrivate(storage.findVolumeByUuid(volumeUuid));
433 }
434 }
435
Jeff Sharkeye8a4b662015-06-27 15:43:45 -0700436 private boolean shouldBenchmark() {
437 final long benchInterval = Settings.Global.getLong(mContext.getContentResolver(),
438 Settings.Global.STORAGE_BENCHMARK_INTERVAL, DateUtils.WEEK_IN_MILLIS);
Jeff Sharkeye83d8a92015-09-09 14:53:38 -0700439 if (benchInterval == -1) {
440 return false;
441 } else if (benchInterval == 0) {
442 return true;
443 }
444
Jeff Sharkeye8a4b662015-06-27 15:43:45 -0700445 synchronized (mLock) {
446 for (int i = 0; i < mVolumes.size(); i++) {
447 final VolumeInfo vol = mVolumes.valueAt(i);
448 final VolumeRecord rec = mRecords.get(vol.fsUuid);
Jeff Sharkeye83d8a92015-09-09 14:53:38 -0700449 if (vol.isMountedWritable() && rec != null) {
Jeff Sharkeye8a4b662015-06-27 15:43:45 -0700450 final long benchAge = System.currentTimeMillis() - rec.lastBenchMillis;
451 if (benchAge >= benchInterval) {
452 return true;
453 }
454 }
455 }
456 return false;
457 }
458 }
459
Jeff Sharkeyeba260d2015-04-19 14:35:16 -0700460 private CountDownLatch findOrCreateDiskScanLatch(String diskId) {
461 synchronized (mLock) {
462 CountDownLatch latch = mDiskScanLatches.get(diskId);
463 if (latch == null) {
464 latch = new CountDownLatch(1);
465 mDiskScanLatches.put(diskId, latch);
466 }
467 return latch;
468 }
469 }
470
Paul Lawrence8e397362014-01-27 15:22:30 -0800471 /** List of crypto types.
472 * These must match CRYPT_TYPE_XXX in cryptfs.h AND their
473 * corresponding commands in CommandListener.cpp */
474 public static final String[] CRYPTO_TYPES
475 = { "password", "default", "pattern", "pin" };
476
Brian Carlstrom7395a8a2014-04-28 22:11:01 -0700477 private final Context mContext;
Jeff Sharkey5d0c55c2019-01-24 14:32:31 -0700478 private final ContentResolver mResolver;
Jeff Sharkeycd575992016-03-29 14:12:49 -0600479
Jeff Sharkey1019de92017-09-06 13:47:03 -0600480 private volatile IVold mVold;
Jin Qian12690d52017-10-13 18:17:04 -0700481 private volatile IStoraged mStoraged;
Jeff Sharkey1019de92017-09-06 13:47:03 -0600482
Yasuhiro Matsuda87a38b52015-07-24 22:10:16 +0900483 private volatile boolean mBootCompleted = false;
Jeff Sharkey48877892015-03-18 11:27:19 -0700484 private volatile boolean mDaemonConnected = false;
Jeff Sharkey9765e442017-12-14 22:15:14 -0700485 private volatile boolean mSecureKeyguardShowing = true;
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700486
Sudheer Shanka0a541a52018-07-31 13:21:11 -0700487 private PackageManagerInternal mPmInternal;
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700488
Sudheer Shanka3a0df3b2018-12-12 12:43:43 -0800489 private IPackageManager mIPackageManager;
490 private IAppOpsService mIAppOpsService;
491
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700492 private final Callbacks mCallbacks;
Jeff Sharkeyb9fe5372015-12-03 15:23:08 -0700493 private final LockPatternUtils mLockPatternUtils;
Jeff Sharkey48877892015-03-18 11:27:19 -0700494
San Mehat6cdd9c02010-02-09 14:45:20 -0800495 /**
Kenny Root3b1abba2010-10-13 15:00:07 -0700496 * The size of the crypto algorithm key in bits for OBB files. Currently
497 * Twofish is used which takes 128-bit keys.
498 */
499 private static final int CRYPTO_ALGORITHM_KEY_SIZE = 128;
500
501 /**
502 * The number of times to run SHA1 in the PBKDF2 function for OBB files.
503 * 1024 is reasonably secure and not too slow.
504 */
505 private static final int PBKDF2_HASH_ROUNDS = 1024;
506
507 /**
Kenny Roota02b8b02010-08-05 16:14:17 -0700508 * Mounted OBB tracking information. Used to track the current state of all
509 * OBBs.
Kenny Root02c87302010-07-01 08:10:18 -0700510 */
Kenny Root735de3b2010-09-30 14:11:39 -0700511 final private Map<IBinder, List<ObbState>> mObbMounts = new HashMap<IBinder, List<ObbState>>();
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700512
513 /** Map from raw paths to {@link ObbState}. */
Kenny Roota02b8b02010-08-05 16:14:17 -0700514 final private Map<String, ObbState> mObbPathToStateMap = new HashMap<String, ObbState>();
515
Svet Ganov6ee871e2015-07-10 14:29:33 -0700516 // Not guarded by a lock.
Sudheer Shanka2250d562016-11-07 15:41:02 -0800517 private final StorageManagerInternalImpl mStorageManagerInternal
518 = new StorageManagerInternalImpl();
Svet Ganov6ee871e2015-07-10 14:29:33 -0700519
Zim42f1e9f2019-08-15 17:35:00 +0100520 // Not guarded by a lock.
521 private final StorageSessionController mStorageSessionController;
522
Zim17be6f92019-09-25 14:37:55 +0100523 private final boolean mIsFuseEnabled;
524
Kenny Roota02b8b02010-08-05 16:14:17 -0700525 class ObbState implements IBinder.DeathRecipient {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700526 public ObbState(String rawPath, String canonicalPath, int callingUid,
Jeff Sharkey41cd6812017-09-11 10:32:17 -0600527 IObbActionListener token, int nonce, String volId) {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700528 this.rawPath = rawPath;
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700529 this.canonicalPath = canonicalPath;
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700530 this.ownerGid = UserHandle.getSharedAppGid(callingUid);
Kenny Rootaf9d6672010-10-08 09:21:39 -0700531 this.token = token;
532 this.nonce = nonce;
Jeff Sharkey41cd6812017-09-11 10:32:17 -0600533 this.volId = volId;
Kenny Roota02b8b02010-08-05 16:14:17 -0700534 }
535
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700536 final String rawPath;
537 final String canonicalPath;
Kenny Roota02b8b02010-08-05 16:14:17 -0700538
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700539 final int ownerGid;
Kenny Roota02b8b02010-08-05 16:14:17 -0700540
Kenny Rootaf9d6672010-10-08 09:21:39 -0700541 // Token of remote Binder caller
542 final IObbActionListener token;
543
544 // Identifier to pass back to the token
545 final int nonce;
Kenny Roota02b8b02010-08-05 16:14:17 -0700546
Jeff Sharkey41cd6812017-09-11 10:32:17 -0600547 String volId;
548
Kenny Root735de3b2010-09-30 14:11:39 -0700549 public IBinder getBinder() {
550 return token.asBinder();
551 }
552
Kenny Roota02b8b02010-08-05 16:14:17 -0700553 @Override
554 public void binderDied() {
555 ObbAction action = new UnmountObbAction(this, true);
556 mObbActionHandler.sendMessage(mObbActionHandler.obtainMessage(OBB_RUN_ACTION, action));
Kenny Root735de3b2010-09-30 14:11:39 -0700557 }
Kenny Roota02b8b02010-08-05 16:14:17 -0700558
Kenny Root5919ac62010-10-05 09:49:40 -0700559 public void link() throws RemoteException {
560 getBinder().linkToDeath(this, 0);
561 }
562
563 public void unlink() {
Kenny Root735de3b2010-09-30 14:11:39 -0700564 getBinder().unlinkToDeath(this, 0);
Kenny Roota02b8b02010-08-05 16:14:17 -0700565 }
Kenny Root38cf8862010-09-26 14:18:51 -0700566
567 @Override
568 public String toString() {
569 StringBuilder sb = new StringBuilder("ObbState{");
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700570 sb.append("rawPath=").append(rawPath);
571 sb.append(",canonicalPath=").append(canonicalPath);
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700572 sb.append(",ownerGid=").append(ownerGid);
573 sb.append(",token=").append(token);
574 sb.append(",binder=").append(getBinder());
Jeff Sharkey41cd6812017-09-11 10:32:17 -0600575 sb.append(",volId=").append(volId);
Kenny Root38cf8862010-09-26 14:18:51 -0700576 sb.append('}');
577 return sb.toString();
578 }
Kenny Roota02b8b02010-08-05 16:14:17 -0700579 }
580
581 // OBB Action Handler
582 final private ObbActionHandler mObbActionHandler;
583
584 // OBB action handler messages
585 private static final int OBB_RUN_ACTION = 1;
Sudheer Shanka25469aa2018-08-27 15:50:23 -0700586 private static final int OBB_FLUSH_MOUNT_STATE = 2;
Kenny Root02c87302010-07-01 08:10:18 -0700587
Christopher Tate7265abe2014-11-21 13:54:45 -0800588 // Last fstrim operation tracking
589 private static final String LAST_FSTRIM_FILE = "last-fstrim";
590 private final File mLastMaintenanceFile;
591 private long mLastMaintenance;
592
Kenny Root02c87302010-07-01 08:10:18 -0700593 // Handler messages
Jeff Sharkey48877892015-03-18 11:27:19 -0700594 private static final int H_SYSTEM_READY = 1;
595 private static final int H_DAEMON_CONNECTED = 2;
596 private static final int H_SHUTDOWN = 3;
597 private static final int H_FSTRIM = 4;
598 private static final int H_VOLUME_MOUNT = 5;
599 private static final int H_VOLUME_BROADCAST = 6;
Jeff Sharkeyabc3e852015-08-03 14:41:13 -0700600 private static final int H_INTERNAL_BROADCAST = 7;
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700601 private static final int H_VOLUME_UNMOUNT = 8;
Jeff Sharkey5a9bb742015-11-03 10:15:57 -0800602 private static final int H_PARTITION_FORGET = 9;
603 private static final int H_RESET = 10;
Jin Qiana85b9912017-10-17 15:48:18 -0700604 private static final int H_RUN_IDLE_MAINT = 11;
605 private static final int H_ABORT_IDLE_MAINT = 12;
Daniel Rosenberg137aed12019-03-15 18:41:11 -0700606 private static final int H_BOOT_COMPLETED = 13;
Narayan Kamath157dd1d2019-06-12 13:06:30 +0100607 private static final int H_COMPLETE_UNLOCK_USER = 14;
Suchi Amalapurapu6ffce2e2010-03-08 14:48:40 -0800608
Sudheer Shanka2250d562016-11-07 15:41:02 -0800609 class StorageManagerServiceHandler extends Handler {
610 public StorageManagerServiceHandler(Looper looper) {
Jeff Sharkey48877892015-03-18 11:27:19 -0700611 super(looper);
Daniel Sandler5f27ef42010-03-16 15:42:02 -0400612 }
613
Jason parks5af0b912010-11-29 09:05:25 -0600614 @Override
Suchi Amalapurapuc42e29e2010-02-22 16:03:53 -0800615 public void handleMessage(Message msg) {
616 switch (msg.what) {
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700617 case H_SYSTEM_READY: {
Jeff Sharkey48877892015-03-18 11:27:19 -0700618 handleSystemReady();
619 break;
620 }
Daniel Rosenberg137aed12019-03-15 18:41:11 -0700621 case H_BOOT_COMPLETED: {
622 handleBootCompleted();
623 break;
624 }
Jeff Sharkey48877892015-03-18 11:27:19 -0700625 case H_DAEMON_CONNECTED: {
626 handleDaemonConnected();
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700627 break;
628 }
Christopher Tated417d622013-08-19 16:14:25 -0700629 case H_FSTRIM: {
Christopher Tated417d622013-08-19 16:14:25 -0700630 Slog.i(TAG, "Running fstrim idle maintenance");
Christopher Tate7265abe2014-11-21 13:54:45 -0800631
632 // Remember when we kicked it off
633 try {
634 mLastMaintenance = System.currentTimeMillis();
635 mLastMaintenanceFile.setLastModified(mLastMaintenance);
636 } catch (Exception e) {
637 Slog.e(TAG, "Unable to record last fstrim!");
638 }
639
Jeff Sharkeyb302c542017-09-15 12:57:59 -0600640 // TODO: Reintroduce shouldBenchmark() test
Jeff Sharkey7e19f532017-11-06 13:54:11 -0700641 fstrim(0, null);
Christopher Tate7265abe2014-11-21 13:54:45 -0800642
Christopher Tated417d622013-08-19 16:14:25 -0700643 // invoke the completion callback, if any
Jeff Sharkeye8a4b662015-06-27 15:43:45 -0700644 // TODO: fstrim is non-blocking, so remove this useless callback
Christopher Tated417d622013-08-19 16:14:25 -0700645 Runnable callback = (Runnable) msg.obj;
646 if (callback != null) {
647 callback.run();
648 }
649 break;
650 }
Jeff Sharkey48877892015-03-18 11:27:19 -0700651 case H_SHUTDOWN: {
Sudheer Shanka2250d562016-11-07 15:41:02 -0800652 final IStorageShutdownObserver obs = (IStorageShutdownObserver) msg.obj;
Jeff Sharkey48877892015-03-18 11:27:19 -0700653 boolean success = false;
654 try {
Jeff Sharkey54402792017-09-15 16:05:19 -0600655 mVold.shutdown();
656 success = true;
Jeff Sharkeyace874b2017-09-07 15:27:33 -0600657 } catch (Exception e) {
658 Slog.wtf(TAG, e);
Jeff Sharkey48877892015-03-18 11:27:19 -0700659 }
660 if (obs != null) {
661 try {
662 obs.onShutDownComplete(success ? 0 : -1);
Jeff Sharkeyace874b2017-09-07 15:27:33 -0600663 } catch (Exception ignored) {
Jeff Sharkey48877892015-03-18 11:27:19 -0700664 }
665 }
666 break;
667 }
668 case H_VOLUME_MOUNT: {
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -0700669 final VolumeInfo vol = (VolumeInfo) msg.obj;
Jeff Sharkey2e606d72015-07-27 14:19:54 -0700670 if (isMountDisallowed(vol)) {
671 Slog.i(TAG, "Ignoring mount " + vol.getId() + " due to policy");
672 break;
673 }
Zim42f1e9f2019-08-15 17:35:00 +0100674
Zim17be6f92019-09-25 14:37:55 +0100675 mount(vol);
Jeff Sharkey48877892015-03-18 11:27:19 -0700676 break;
677 }
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700678 case H_VOLUME_UNMOUNT: {
679 final VolumeInfo vol = (VolumeInfo) msg.obj;
Sudheer Shanka3f0645b2018-09-18 13:07:59 -0700680 unmount(vol);
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700681 break;
682 }
Jeff Sharkey48877892015-03-18 11:27:19 -0700683 case H_VOLUME_BROADCAST: {
684 final StorageVolume userVol = (StorageVolume) msg.obj;
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700685 final String envState = userVol.getState();
686 Slog.d(TAG, "Volume " + userVol.getId() + " broadcasting " + envState + " to "
Jeff Sharkey48877892015-03-18 11:27:19 -0700687 + userVol.getOwner());
688
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700689 final String action = VolumeInfo.getBroadcastForEnvironment(envState);
Jeff Sharkey48877892015-03-18 11:27:19 -0700690 if (action != null) {
691 final Intent intent = new Intent(action,
692 Uri.fromFile(userVol.getPathFile()));
693 intent.putExtra(StorageVolume.EXTRA_STORAGE_VOLUME, userVol);
Jeff Sharkey082f83b2017-03-26 14:34:47 -0600694 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT
695 | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
Jeff Sharkey48877892015-03-18 11:27:19 -0700696 mContext.sendBroadcastAsUser(intent, userVol.getOwner());
697 }
698 break;
699 }
Jeff Sharkeyabc3e852015-08-03 14:41:13 -0700700 case H_INTERNAL_BROADCAST: {
701 // Internal broadcasts aimed at system components, not for
702 // third-party apps.
703 final Intent intent = (Intent) msg.obj;
704 mContext.sendBroadcastAsUser(intent, UserHandle.ALL,
705 android.Manifest.permission.WRITE_MEDIA_STORAGE);
Jeff Sharkey5a9bb742015-11-03 10:15:57 -0800706 break;
707 }
708 case H_PARTITION_FORGET: {
Jeff Sharkeydb4b6192017-10-24 11:08:50 -0600709 final VolumeRecord rec = (VolumeRecord) msg.obj;
710 forgetPartition(rec.partGuid, rec.fsUuid);
Jeff Sharkey5a9bb742015-11-03 10:15:57 -0800711 break;
712 }
713 case H_RESET: {
Daniel Rosenberg137aed12019-03-15 18:41:11 -0700714 resetIfBootedAndConnected();
Jeff Sharkey5a9bb742015-11-03 10:15:57 -0800715 break;
Jeff Sharkeyabc3e852015-08-03 14:41:13 -0700716 }
Jin Qiana85b9912017-10-17 15:48:18 -0700717 case H_RUN_IDLE_MAINT: {
718 Slog.i(TAG, "Running idle maintenance");
719 runIdleMaint((Runnable)msg.obj);
720 break;
721 }
722 case H_ABORT_IDLE_MAINT: {
723 Slog.i(TAG, "Aborting idle maintenance");
724 abortIdleMaint((Runnable)msg.obj);
725 break;
726 }
Narayan Kamath157dd1d2019-06-12 13:06:30 +0100727 case H_COMPLETE_UNLOCK_USER: {
728 completeUnlockUser((int) msg.obj);
729 break;
730 }
Suchi Amalapurapuc42e29e2010-02-22 16:03:53 -0800731 }
732 }
Jeff Sharkey48877892015-03-18 11:27:19 -0700733 }
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700734
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700735 private final Handler mHandler;
Suchi Amalapurapuc42e29e2010-02-22 16:03:53 -0800736
Jeff Sharkeybcd262d2015-06-10 09:41:17 -0700737 private BroadcastReceiver mUserReceiver = new BroadcastReceiver() {
738 @Override
739 public void onReceive(Context context, Intent intent) {
740 final String action = intent.getAction();
741 final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700742 Preconditions.checkArgument(userId >= 0);
Jeff Sharkeybcd262d2015-06-10 09:41:17 -0700743
744 try {
745 if (Intent.ACTION_USER_ADDED.equals(action)) {
746 final UserManager um = mContext.getSystemService(UserManager.class);
747 final int userSerialNumber = um.getUserSerialNumber(userId);
Jeff Sharkey54402792017-09-15 16:05:19 -0600748 mVold.onUserAdded(userId, userSerialNumber);
Jeff Sharkeybcd262d2015-06-10 09:41:17 -0700749 } else if (Intent.ACTION_USER_REMOVED.equals(action)) {
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700750 synchronized (mVolumes) {
751 final int size = mVolumes.size();
752 for (int i = 0; i < size; i++) {
753 final VolumeInfo vol = mVolumes.valueAt(i);
754 if (vol.mountUserId == userId) {
755 vol.mountUserId = UserHandle.USER_NULL;
756 mHandler.obtainMessage(H_VOLUME_UNMOUNT, vol).sendToTarget();
757 }
758 }
759 }
Jeff Sharkey54402792017-09-15 16:05:19 -0600760 mVold.onUserRemoved(userId);
Jeff Sharkeybcd262d2015-06-10 09:41:17 -0700761 }
Jeff Sharkeyace874b2017-09-07 15:27:33 -0600762 } catch (Exception e) {
763 Slog.wtf(TAG, e);
Jeff Sharkeybcd262d2015-06-10 09:41:17 -0700764 }
765 }
766 };
767
Jeff Sharkeyedcdaf62015-07-09 09:45:36 -0700768 private void waitForLatch(CountDownLatch latch, String condition, long timeoutMillis)
769 throws TimeoutException {
770 final long startMillis = SystemClock.elapsedRealtime();
Jeff Sharkeyeba260d2015-04-19 14:35:16 -0700771 while (true) {
Kenny Root51a573c2012-05-17 13:30:28 -0700772 try {
773 if (latch.await(5000, TimeUnit.MILLISECONDS)) {
San Mehat207e5382010-02-04 20:46:54 -0800774 return;
Kenny Root51a573c2012-05-17 13:30:28 -0700775 } else {
776 Slog.w(TAG, "Thread " + Thread.currentThread().getName()
Jeff Sharkey48877892015-03-18 11:27:19 -0700777 + " still waiting for " + condition + "...");
San Mehat207e5382010-02-04 20:46:54 -0800778 }
Kenny Root51a573c2012-05-17 13:30:28 -0700779 } catch (InterruptedException e) {
Jeff Sharkeyeba260d2015-04-19 14:35:16 -0700780 Slog.w(TAG, "Interrupt while waiting for " + condition);
San Mehat207e5382010-02-04 20:46:54 -0800781 }
Jeff Sharkeyedcdaf62015-07-09 09:45:36 -0700782 if (timeoutMillis > 0 && SystemClock.elapsedRealtime() > startMillis + timeoutMillis) {
783 throw new TimeoutException("Thread " + Thread.currentThread().getName()
784 + " gave up waiting for " + condition + " after " + timeoutMillis + "ms");
785 }
San Mehat207e5382010-02-04 20:46:54 -0800786 }
San Mehat1f6301e2010-01-07 22:40:27 -0800787 }
Kenny Root02c87302010-07-01 08:10:18 -0700788
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700789 private void handleSystemReady() {
Jeff Sharkey48877892015-03-18 11:27:19 -0700790 // Start scheduling nominally-daily fstrim operations
Christopher Tate115afda2014-06-06 19:06:26 -0700791 MountServiceIdler.scheduleIdlePass(mContext);
Daniel Colascione766b6322018-01-08 19:10:36 -0800792
793 // Toggle zram-enable system property in response to settings
794 mContext.getContentResolver().registerContentObserver(
795 Settings.Global.getUriFor(Settings.Global.ZRAM_ENABLED),
796 false /*notifyForDescendants*/,
797 new ContentObserver(null /* current thread */) {
798 @Override
799 public void onChange(boolean selfChange) {
800 refreshZramSettings();
801 }
802 });
803 refreshZramSettings();
Jeff Sharkeyb0c363b22018-12-15 11:53:03 -0700804
Srinivas Paladuguc8261752019-01-09 10:54:52 -0800805 // Schedule zram writeback unless zram is disabled by persist.sys.zram_enabled
806 String zramPropValue = SystemProperties.get(ZRAM_ENABLED_PROPERTY);
807 if (!zramPropValue.equals("0")
808 && mContext.getResources().getBoolean(
809 com.android.internal.R.bool.config_zramWriteback)) {
810 ZramWriteback.scheduleZramWriteback(mContext);
811 }
Jeff Sharkeyb0c363b22018-12-15 11:53:03 -0700812 // Toggle isolated-enable system property in response to settings
813 mContext.getContentResolver().registerContentObserver(
814 Settings.Global.getUriFor(Settings.Global.ISOLATED_STORAGE_REMOTE),
815 false /*notifyForDescendants*/,
816 new ContentObserver(null /* current thread */) {
817 @Override
818 public void onChange(boolean selfChange) {
819 refreshIsolatedStorageSettings();
820 }
821 });
Jeff Sharkey5d0c55c2019-01-24 14:32:31 -0700822 // For now, simply clone property when it changes
shafik91b34612019-09-23 15:41:44 +0100823 DeviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_STORAGE_NATIVE_BOOT,
Matt Pape15769e22019-04-19 12:31:24 -0700824 mContext.getMainExecutor(), (properties) -> {
Jeff Sharkey8b499a02019-01-28 13:31:50 -0700825 refreshIsolatedStorageSettings();
shafikb2992b62019-10-01 15:31:02 +0100826 refreshFuseSettings();
Jeff Sharkey5d0c55c2019-01-24 14:32:31 -0700827 });
Jeff Sharkeyb0c363b22018-12-15 11:53:03 -0700828 refreshIsolatedStorageSettings();
Daniel Colascione766b6322018-01-08 19:10:36 -0800829 }
830
831 /**
832 * Update the zram_enabled system property (which init reads to
833 * decide whether to enable zram) to reflect the zram_enabled
834 * preference (which we can change for experimentation purposes).
835 */
836 private void refreshZramSettings() {
837 String propertyValue = SystemProperties.get(ZRAM_ENABLED_PROPERTY);
838 if ("".equals(propertyValue)) {
839 return; // System doesn't have zram toggling support
840 }
841 String desiredPropertyValue =
842 Settings.Global.getInt(mContext.getContentResolver(),
843 Settings.Global.ZRAM_ENABLED,
844 1) != 0
845 ? "1" : "0";
846 if (!desiredPropertyValue.equals(propertyValue)) {
847 // Avoid redundant disk writes by setting only if we're
848 // changing the property value. There's no race: we're the
849 // sole writer.
850 SystemProperties.set(ZRAM_ENABLED_PROPERTY, desiredPropertyValue);
Srinivas Paladuguc8261752019-01-09 10:54:52 -0800851 // Schedule writeback only if zram is being enabled.
852 if (desiredPropertyValue.equals("1")
853 && mContext.getResources().getBoolean(
854 com.android.internal.R.bool.config_zramWriteback)) {
855 ZramWriteback.scheduleZramWriteback(mContext);
856 }
Daniel Colascione766b6322018-01-08 19:10:36 -0800857 }
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700858 }
859
Jeff Sharkeyb0c363b22018-12-15 11:53:03 -0700860 private void refreshIsolatedStorageSettings() {
Jeff Sharkey8b499a02019-01-28 13:31:50 -0700861 // Always copy value from newer DeviceConfig location
862 Settings.Global.putString(mResolver,
863 Settings.Global.ISOLATED_STORAGE_REMOTE,
shafik91b34612019-09-23 15:41:44 +0100864 DeviceConfig.getProperty(DeviceConfig.NAMESPACE_STORAGE_NATIVE_BOOT,
865 ISOLATED_STORAGE_ENABLED));
Jeff Sharkey8b499a02019-01-28 13:31:50 -0700866
Jeff Sharkeyb0c363b22018-12-15 11:53:03 -0700867 final int local = Settings.Global.getInt(mContext.getContentResolver(),
868 Settings.Global.ISOLATED_STORAGE_LOCAL, 0);
869 final int remote = Settings.Global.getInt(mContext.getContentResolver(),
870 Settings.Global.ISOLATED_STORAGE_REMOTE, 0);
871
872 // Walk down precedence chain; we prefer local settings first, then
873 // remote settings, before finally falling back to hard-coded default.
874 final boolean res;
875 if (local == -1) {
876 res = false;
877 } else if (local == 1) {
878 res = true;
879 } else if (remote == -1) {
880 res = false;
881 } else if (remote == 1) {
882 res = true;
883 } else {
Jeff Sharkey06376802019-02-11 12:20:02 -0700884 res = true;
Jeff Sharkeyb0c363b22018-12-15 11:53:03 -0700885 }
886
887 Slog.d(TAG, "Isolated storage local flag " + local + " and remote flag "
888 + remote + " resolved to " + res);
889 SystemProperties.set(StorageManager.PROP_ISOLATED_STORAGE, Boolean.toString(res));
890 }
891
Abhijeet Kaurb9847712019-11-19 16:35:47 +0000892 /**
893 * The most recent flag change takes precedence. Change fuse Settings flag if Device Config is
894 * changed. Settings flag change will in turn change fuse system property (persist.sys.fuse)
895 * whenever the user reboots.
896 */
shafikb2992b62019-10-01 15:31:02 +0100897 private void refreshFuseSettings() {
898 int isFuseEnabled = DeviceConfig.getInt(DeviceConfig.NAMESPACE_STORAGE_NATIVE_BOOT,
899 FUSE_ENABLED, 0);
900 if (isFuseEnabled == 1) {
Abhijeet Kaurb9847712019-11-19 16:35:47 +0000901 Slog.d(TAG, "Device Config flag for FUSE is enabled, turn Settings fuse flag on");
902 SystemProperties.set(FeatureFlagUtils.PERSIST_PREFIX
903 + FeatureFlagUtils.SETTINGS_FUSE_FLAG, "true");
shafikb2992b62019-10-01 15:31:02 +0100904 } else if (isFuseEnabled == -1) {
Abhijeet Kaurb9847712019-11-19 16:35:47 +0000905 Slog.d(TAG, "Device Config flag for FUSE is disabled, turn Settings fuse flag off");
906 SystemProperties.set(FeatureFlagUtils.PERSIST_PREFIX
907 + FeatureFlagUtils.SETTINGS_FUSE_FLAG, "false");
shafikb2992b62019-10-01 15:31:02 +0100908 }
909 // else, keep the build config.
Abhijeet Kaurb9847712019-11-19 16:35:47 +0000910 // This can be overridden by direct adjustment of persist.sys.fflag.override.settings_fuse
shafikb2992b62019-10-01 15:31:02 +0100911 }
912
Jeff Sharkey14cbe522015-07-08 14:06:37 -0700913 /**
914 * MediaProvider has a ton of code that makes assumptions about storage
915 * paths never changing, so we outright kill them to pick up new state.
916 */
917 @Deprecated
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700918 private void killMediaProvider(List<UserInfo> users) {
919 if (users == null) return;
920
Jeff Sharkeyb3cf9532015-07-17 15:12:39 -0700921 final long token = Binder.clearCallingIdentity();
922 try {
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700923 for (UserInfo user : users) {
924 // System user does not have media provider, so skip.
925 if (user.isSystemOnly()) continue;
926
Jeff Sharkey5790af02018-08-13 17:42:54 -0600927 final ProviderInfo provider = mPmInternal.resolveContentProvider(
928 MediaStore.AUTHORITY, PackageManager.MATCH_DIRECT_BOOT_AWARE
Jeff Sharkey8a372a02016-03-16 16:25:45 -0600929 | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
930 user.id);
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700931 if (provider != null) {
Sudheer Shankadc589ac2016-11-10 15:30:17 -0800932 final IActivityManager am = ActivityManager.getService();
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700933 try {
Jeff Sharkey85f449e2016-06-23 09:26:00 -0600934 am.killApplication(provider.applicationInfo.packageName,
935 UserHandle.getAppId(provider.applicationInfo.uid),
936 UserHandle.USER_ALL, "vold reset");
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700937 // We only need to run this once. It will kill all users' media processes.
938 break;
939 } catch (RemoteException e) {
940 }
Jeff Sharkeyb3cf9532015-07-17 15:12:39 -0700941 }
Jeff Sharkey14cbe522015-07-08 14:06:37 -0700942 }
Jeff Sharkeyb3cf9532015-07-17 15:12:39 -0700943 } finally {
944 Binder.restoreCallingIdentity(token);
Jeff Sharkey14cbe522015-07-08 14:06:37 -0700945 }
946 }
947
Andreas Gampea36dc622018-02-05 17:19:22 -0800948 @GuardedBy("mLock")
Jeff Sharkey5a9bb742015-11-03 10:15:57 -0800949 private void addInternalVolumeLocked() {
Amith Yamasania7892482015-08-07 11:09:05 -0700950 // Create a stub volume that represents internal storage
951 final VolumeInfo internal = new VolumeInfo(VolumeInfo.ID_PRIVATE_INTERNAL,
952 VolumeInfo.TYPE_PRIVATE, null, null);
953 internal.state = VolumeInfo.STATE_MOUNTED;
954 internal.path = Environment.getDataDirectory().getAbsolutePath();
955 mVolumes.put(internal.id, internal);
956 }
957
Daniel Rosenberg137aed12019-03-15 18:41:11 -0700958 private void initIfBootedAndConnected() {
959 Slog.d(TAG, "Thinking about init, mBootCompleted=" + mBootCompleted
Jeff Sharkey8924e872015-11-30 12:52:10 -0700960 + ", mDaemonConnected=" + mDaemonConnected);
Eric Biggers1127d922019-04-05 12:46:35 -0700961 if (mBootCompleted && mDaemonConnected
962 && !StorageManager.isFileEncryptedNativeOnly()) {
963 // When booting a device without native support, make sure that our
964 // user directories are locked or unlocked based on the current
965 // emulation status.
966 final boolean initLocked = StorageManager.isFileEncryptedEmulatedOnly();
967 Slog.d(TAG, "Setting up emulation state, initlocked=" + initLocked);
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700968 final List<UserInfo> users = mContext.getSystemService(UserManager.class).getUsers();
Jeff Sharkey8924e872015-11-30 12:52:10 -0700969 for (UserInfo user : users) {
970 try {
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700971 if (initLocked) {
Jeff Sharkey54402792017-09-15 16:05:19 -0600972 mVold.lockUserKey(user.id);
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700973 } else {
Jeff Sharkey54402792017-09-15 16:05:19 -0600974 mVold.unlockUserKey(user.id, user.serialNumber, encodeBytes(null),
975 encodeBytes(null));
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700976 }
Jeff Sharkey43e12112017-09-12 16:31:45 -0600977 } catch (Exception e) {
978 Slog.wtf(TAG, e);
Jeff Sharkey8924e872015-11-30 12:52:10 -0700979 }
980 }
981 }
982 }
983
Daniel Rosenberg137aed12019-03-15 18:41:11 -0700984 private void resetIfBootedAndConnected() {
985 Slog.d(TAG, "Thinking about reset, mBootCompleted=" + mBootCompleted
Jeff Sharkey48877892015-03-18 11:27:19 -0700986 + ", mDaemonConnected=" + mDaemonConnected);
Daniel Rosenberg137aed12019-03-15 18:41:11 -0700987 if (mBootCompleted && mDaemonConnected) {
Jeff Sharkey5a9bb742015-11-03 10:15:57 -0800988 final List<UserInfo> users = mContext.getSystemService(UserManager.class).getUsers();
Zim17be6f92019-09-25 14:37:55 +0100989
990 if (mIsFuseEnabled) {
991 mStorageSessionController.onReset(mVold, mHandler);
992 } else {
993 killMediaProvider(users);
994 }
Jeff Sharkey14cbe522015-07-08 14:06:37 -0700995
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700996 final int[] systemUnlockedUsers;
Jeff Sharkey5a9bb742015-11-03 10:15:57 -0800997 synchronized (mLock) {
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700998 systemUnlockedUsers = mSystemUnlockedUsers;
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700999
Jeff Sharkey5a9bb742015-11-03 10:15:57 -08001000 mDisks.clear();
1001 mVolumes.clear();
1002
1003 addInternalVolumeLocked();
1004 }
Jeff Sharkey59d577a2015-04-11 21:27:21 -07001005
Jeff Sharkey48877892015-03-18 11:27:19 -07001006 try {
Zim42f1e9f2019-08-15 17:35:00 +01001007 // TODO(b/135341433): Remove paranoid logging when FUSE is stable
Zim17be6f92019-09-25 14:37:55 +01001008 Slog.i(TAG, "Resetting vold...");
Jeff Sharkey54402792017-09-15 16:05:19 -06001009 mVold.reset();
Zim42f1e9f2019-08-15 17:35:00 +01001010 Slog.i(TAG, "Reset vold");
Jeff Sharkeybcd262d2015-06-10 09:41:17 -07001011
1012 // Tell vold about all existing and started users
Jeff Sharkeybcd262d2015-06-10 09:41:17 -07001013 for (UserInfo user : users) {
Jeff Sharkey54402792017-09-15 16:05:19 -06001014 mVold.onUserAdded(user.id, user.serialNumber);
Jeff Sharkeybcd262d2015-06-10 09:41:17 -07001015 }
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07001016 for (int userId : systemUnlockedUsers) {
Sudheer Shanka64501e52019-04-29 10:46:26 -07001017 mVold.onUserStarted(userId);
Jin Qian12690d52017-10-13 18:17:04 -07001018 mStoraged.onUserStarted(userId);
Jeff Sharkey50a05452015-04-29 11:24:52 -07001019 }
Jeff Sharkey9765e442017-12-14 22:15:14 -07001020 mVold.onSecureKeyguardStateChanged(mSecureKeyguardShowing);
Risanaec0ee72018-10-31 10:10:12 +09001021 mStorageManagerInternal.onReset(mVold);
Jeff Sharkeyace874b2017-09-07 15:27:33 -06001022 } catch (Exception e) {
1023 Slog.wtf(TAG, e);
Jeff Sharkeyb049e212012-09-07 23:16:01 -07001024 }
1025 }
Jeff Sharkey48877892015-03-18 11:27:19 -07001026 }
Jeff Sharkeyb049e212012-09-07 23:16:01 -07001027
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07001028 private void onUnlockUser(int userId) {
1029 Slog.d(TAG, "onUnlockUser " + userId);
Jeff Sharkey48877892015-03-18 11:27:19 -07001030
1031 // We purposefully block here to make sure that user-specific
1032 // staging area is ready so it's ready for zygote-forked apps to
1033 // bind mount against.
1034 try {
Zim17be6f92019-09-25 14:37:55 +01001035 mStorageSessionController.onUnlockUser(userId);
Sudheer Shanka64501e52019-04-29 10:46:26 -07001036 mVold.onUserStarted(userId);
Jin Qian12690d52017-10-13 18:17:04 -07001037 mStoraged.onUserStarted(userId);
Jeff Sharkeyace874b2017-09-07 15:27:33 -06001038 } catch (Exception e) {
1039 Slog.wtf(TAG, e);
Jeff Sharkeyb049e212012-09-07 23:16:01 -07001040 }
Jeff Sharkey48877892015-03-18 11:27:19 -07001041
Narayan Kamath157dd1d2019-06-12 13:06:30 +01001042 mHandler.obtainMessage(H_COMPLETE_UNLOCK_USER, userId).sendToTarget();
1043 }
1044
1045 private void completeUnlockUser(int userId) {
1046 // If user 0 has completed unlock, perform a one-time migration of legacy obb data
1047 // to its new location. This may take time depending on the size of the data to be copied
1048 // so it's done on the StorageManager handler thread.
1049 if (userId == 0) {
1050 mPmInternal.migrateLegacyObbData();
1051 }
1052
Jeff Sharkey48877892015-03-18 11:27:19 -07001053 // Record user as started so newly mounted volumes kick off events
1054 // correctly, then synthesize events for any already-mounted volumes.
yuanhuihuiefd1f122016-07-13 21:21:03 +08001055 synchronized (mLock) {
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07001056 for (int i = 0; i < mVolumes.size(); i++) {
1057 final VolumeInfo vol = mVolumes.valueAt(i);
Jeff Sharkey46349872015-07-28 10:49:47 -07001058 if (vol.isVisibleForRead(userId) && vol.isMountedReadable()) {
Svet Ganov6ee871e2015-07-10 14:29:33 -07001059 final StorageVolume userVol = vol.buildStorageVolume(mContext, userId, false);
Jeff Sharkey48877892015-03-18 11:27:19 -07001060 mHandler.obtainMessage(H_VOLUME_BROADCAST, userVol).sendToTarget();
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001061
Jeff Sharkey27de30d2015-04-18 16:20:27 -07001062 final String envState = VolumeInfo.getEnvironmentForState(vol.getState());
1063 mCallbacks.notifyStorageStateChanged(userVol.getPath(), envState, envState);
Jeff Sharkey48877892015-03-18 11:27:19 -07001064 }
1065 }
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07001066 mSystemUnlockedUsers = ArrayUtils.appendInt(mSystemUnlockedUsers, userId);
Jeff Sharkey48877892015-03-18 11:27:19 -07001067 }
1068 }
1069
1070 private void onCleanupUser(int userId) {
1071 Slog.d(TAG, "onCleanupUser " + userId);
1072
1073 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06001074 mVold.onUserStopped(userId);
Jin Qian12690d52017-10-13 18:17:04 -07001075 mStoraged.onUserStopped(userId);
Jeff Sharkeyace874b2017-09-07 15:27:33 -06001076 } catch (Exception e) {
1077 Slog.wtf(TAG, e);
Jeff Sharkey48877892015-03-18 11:27:19 -07001078 }
1079
yuanhuihuiefd1f122016-07-13 21:21:03 +08001080 synchronized (mLock) {
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07001081 mSystemUnlockedUsers = ArrayUtils.removeInt(mSystemUnlockedUsers, userId);
Jeff Sharkey48877892015-03-18 11:27:19 -07001082 }
1083 }
Jeff Sharkeyb049e212012-09-07 23:16:01 -07001084
Martijn Coenen7084c6a2019-11-22 16:32:09 +01001085 private void onStopUser(int userId) {
1086 Slog.i(TAG, "onStopUser " + userId);
1087 try {
1088 mStorageSessionController.onUserStopping(userId);
1089 } catch (Exception e) {
1090 Slog.wtf(TAG, e);
1091 }
1092 }
1093
Sudheer Shanka64501e52019-04-29 10:46:26 -07001094 private boolean supportsBlockCheckpoint() throws RemoteException {
Paul Lawrence15a54462019-04-30 11:14:25 -07001095 enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);
Sandeep Patil7d5c4912019-04-15 09:27:30 -07001096 return mVold.supportsBlockCheckpoint();
1097 }
1098
Jeff Sharkey9765e442017-12-14 22:15:14 -07001099 @Override
1100 public void onAwakeStateChanged(boolean isAwake) {
1101 // Ignored
1102 }
1103
1104 @Override
1105 public void onKeyguardStateChanged(boolean isShowing) {
1106 // Push down current secure keyguard status so that we ignore malicious
1107 // USB devices while locked.
1108 mSecureKeyguardShowing = isShowing
1109 && mContext.getSystemService(KeyguardManager.class).isDeviceSecure();
1110 try {
1111 mVold.onSecureKeyguardStateChanged(mSecureKeyguardShowing);
1112 } catch (Exception e) {
1113 Slog.wtf(TAG, e);
1114 }
1115 }
1116
Christopher Tated417d622013-08-19 16:14:25 -07001117 void runIdleMaintenance(Runnable callback) {
1118 mHandler.sendMessage(mHandler.obtainMessage(H_FSTRIM, callback));
1119 }
1120
Christopher Tate7265abe2014-11-21 13:54:45 -08001121 // Binder entry point for kicking off an immediate fstrim
1122 @Override
1123 public void runMaintenance() {
Jeff Sharkey48877892015-03-18 11:27:19 -07001124 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
Christopher Tate7265abe2014-11-21 13:54:45 -08001125 runIdleMaintenance(null);
1126 }
1127
1128 @Override
1129 public long lastMaintenance() {
1130 return mLastMaintenance;
1131 }
1132
San Mehat4270e1e2010-01-29 05:32:19 -08001133 public void onDaemonConnected() {
Jeff Sharkey48877892015-03-18 11:27:19 -07001134 mDaemonConnected = true;
1135 mHandler.obtainMessage(H_DAEMON_CONNECTED).sendToTarget();
1136 }
1137
1138 private void handleDaemonConnected() {
Daniel Rosenberg137aed12019-03-15 18:41:11 -07001139 initIfBootedAndConnected();
1140 resetIfBootedAndConnected();
Jeff Sharkey48877892015-03-18 11:27:19 -07001141
Jeff Sharkey48877892015-03-18 11:27:19 -07001142 // On an encrypted device we can't see system properties yet, so pull
1143 // the system locale out of the mount service.
Inseob Kimc1246e62018-11-08 13:13:54 +09001144 if ("".equals(VoldProperties.encrypt_progress().orElse(""))) {
Jeff Sharkey48877892015-03-18 11:27:19 -07001145 copyLocaleFromMountService();
1146 }
San Mehat4270e1e2010-01-29 05:32:19 -08001147 }
1148
Elliott Hughesf839b4f2014-09-26 12:30:47 -07001149 private void copyLocaleFromMountService() {
1150 String systemLocale;
1151 try {
1152 systemLocale = getField(StorageManager.SYSTEM_LOCALE_KEY);
1153 } catch (RemoteException e) {
1154 return;
1155 }
1156 if (TextUtils.isEmpty(systemLocale)) {
1157 return;
1158 }
1159
1160 Slog.d(TAG, "Got locale " + systemLocale + " from mount service");
1161 Locale locale = Locale.forLanguageTag(systemLocale);
1162 Configuration config = new Configuration();
1163 config.setLocale(locale);
1164 try {
Sudheer Shankadc589ac2016-11-10 15:30:17 -08001165 ActivityManager.getService().updatePersistentConfiguration(config);
Elliott Hughesf839b4f2014-09-26 12:30:47 -07001166 } catch (RemoteException e) {
1167 Slog.e(TAG, "Error setting system locale from mount service", e);
1168 }
Elliott Hughes9c33f282014-10-13 12:39:56 -07001169
1170 // Temporary workaround for http://b/17945169.
1171 Slog.d(TAG, "Setting system properties to " + systemLocale + " from mount service");
Narayan Kamathd30dbb82015-01-15 14:48:15 +00001172 SystemProperties.set("persist.sys.locale", locale.toLanguageTag());
Elliott Hughesf839b4f2014-09-26 12:30:47 -07001173 }
1174
Jeff Sharkey8058fe62017-09-13 11:50:33 -06001175 private final IVoldListener mListener = new IVoldListener.Stub() {
1176 @Override
1177 public void onDiskCreated(String diskId, int flags) {
1178 synchronized (mLock) {
Jeff Sharkey901c0422018-04-20 13:11:20 -06001179 final String value = SystemProperties.get(StorageManager.PROP_ADOPTABLE);
1180 switch (value) {
1181 case "force_on":
1182 flags |= DiskInfo.FLAG_ADOPTABLE;
1183 break;
1184 case "force_off":
1185 flags &= ~DiskInfo.FLAG_ADOPTABLE;
1186 break;
Jeff Sharkey8058fe62017-09-13 11:50:33 -06001187 }
Jeff Sharkey8058fe62017-09-13 11:50:33 -06001188 mDisks.put(diskId, new DiskInfo(diskId, flags));
1189 }
1190 }
1191
1192 @Override
1193 public void onDiskScanned(String diskId) {
1194 synchronized (mLock) {
1195 final DiskInfo disk = mDisks.get(diskId);
1196 if (disk != null) {
1197 onDiskScannedLocked(disk);
1198 }
1199 }
1200 }
1201
1202 @Override
1203 public void onDiskMetadataChanged(String diskId, long sizeBytes, String label,
1204 String sysPath) {
1205 synchronized (mLock) {
1206 final DiskInfo disk = mDisks.get(diskId);
1207 if (disk != null) {
1208 disk.size = sizeBytes;
1209 disk.label = label;
1210 disk.sysPath = sysPath;
1211 }
1212 }
1213 }
1214
1215 @Override
1216 public void onDiskDestroyed(String diskId) {
1217 synchronized (mLock) {
1218 final DiskInfo disk = mDisks.remove(diskId);
1219 if (disk != null) {
1220 mCallbacks.notifyDiskDestroyed(disk);
1221 }
1222 }
1223 }
1224
1225 @Override
Zim17be6f92019-09-25 14:37:55 +01001226 public void onVolumeCreated(String volId, int type, String diskId, String partGuid,
1227 int userId) {
Jeff Sharkey8058fe62017-09-13 11:50:33 -06001228 synchronized (mLock) {
1229 final DiskInfo disk = mDisks.get(diskId);
1230 final VolumeInfo vol = new VolumeInfo(volId, type, disk, partGuid);
Zim17be6f92019-09-25 14:37:55 +01001231 vol.mountUserId = userId;
Jeff Sharkey8058fe62017-09-13 11:50:33 -06001232 mVolumes.put(volId, vol);
1233 onVolumeCreatedLocked(vol);
1234 }
1235 }
1236
1237 @Override
1238 public void onVolumeStateChanged(String volId, int state) {
1239 synchronized (mLock) {
1240 final VolumeInfo vol = mVolumes.get(volId);
1241 if (vol != null) {
1242 final int oldState = vol.state;
1243 final int newState = state;
1244 vol.state = newState;
1245 onVolumeStateChangedLocked(vol, oldState, newState);
1246 }
1247 }
1248 }
1249
1250 @Override
1251 public void onVolumeMetadataChanged(String volId, String fsType, String fsUuid,
1252 String fsLabel) {
1253 synchronized (mLock) {
1254 final VolumeInfo vol = mVolumes.get(volId);
1255 if (vol != null) {
1256 vol.fsType = fsType;
1257 vol.fsUuid = fsUuid;
1258 vol.fsLabel = fsLabel;
1259 }
1260 }
1261 }
1262
1263 @Override
1264 public void onVolumePathChanged(String volId, String path) {
1265 synchronized (mLock) {
1266 final VolumeInfo vol = mVolumes.get(volId);
1267 if (vol != null) {
1268 vol.path = path;
1269 }
1270 }
1271 }
1272
1273 @Override
1274 public void onVolumeInternalPathChanged(String volId, String internalPath) {
1275 synchronized (mLock) {
1276 final VolumeInfo vol = mVolumes.get(volId);
1277 if (vol != null) {
1278 vol.internalPath = internalPath;
1279 }
1280 }
1281 }
1282
1283 @Override
1284 public void onVolumeDestroyed(String volId) {
Zim17be6f92019-09-25 14:37:55 +01001285 VolumeInfo vol = null;
Jeff Sharkey8058fe62017-09-13 11:50:33 -06001286 synchronized (mLock) {
Zim17be6f92019-09-25 14:37:55 +01001287 vol = mVolumes.remove(volId);
1288 }
1289
1290 if (vol != null) {
1291 mStorageSessionController.onVolumeRemove(vol);
Jeff Sharkey8058fe62017-09-13 11:50:33 -06001292 }
1293 }
1294 };
1295
Andreas Gampea36dc622018-02-05 17:19:22 -08001296 @GuardedBy("mLock")
Jeff Sharkeyeba260d2015-04-19 14:35:16 -07001297 private void onDiskScannedLocked(DiskInfo disk) {
Jeff Sharkey620b32b2015-04-23 19:36:02 -07001298 int volumeCount = 0;
Jeff Sharkeyeba260d2015-04-19 14:35:16 -07001299 for (int i = 0; i < mVolumes.size(); i++) {
1300 final VolumeInfo vol = mVolumes.valueAt(i);
1301 if (Objects.equals(disk.id, vol.getDiskId())) {
Jeff Sharkey620b32b2015-04-23 19:36:02 -07001302 volumeCount++;
Jeff Sharkeyeba260d2015-04-19 14:35:16 -07001303 }
1304 }
1305
Jeff Sharkeyc7acac62015-06-12 16:16:56 -07001306 final Intent intent = new Intent(DiskInfo.ACTION_DISK_SCANNED);
Jeff Sharkey7732e1e2016-03-30 17:14:23 -06001307 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT
1308 | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
Jeff Sharkeyc7acac62015-06-12 16:16:56 -07001309 intent.putExtra(DiskInfo.EXTRA_DISK_ID, disk.id);
1310 intent.putExtra(DiskInfo.EXTRA_VOLUME_COUNT, volumeCount);
Jeff Sharkeyabc3e852015-08-03 14:41:13 -07001311 mHandler.obtainMessage(H_INTERNAL_BROADCAST, intent).sendToTarget();
Jeff Sharkeyc7acac62015-06-12 16:16:56 -07001312
1313 final CountDownLatch latch = mDiskScanLatches.remove(disk.id);
1314 if (latch != null) {
1315 latch.countDown();
1316 }
1317
Jeff Sharkeyf5a6bd72015-05-19 14:42:38 -07001318 disk.volumeCount = volumeCount;
Jeff Sharkey620b32b2015-04-23 19:36:02 -07001319 mCallbacks.notifyDiskScanned(disk, volumeCount);
Jeff Sharkeyeba260d2015-04-19 14:35:16 -07001320 }
1321
Andreas Gampea36dc622018-02-05 17:19:22 -08001322 @GuardedBy("mLock")
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07001323 private void onVolumeCreatedLocked(VolumeInfo vol) {
Jeff Sharkey5790af02018-08-13 17:42:54 -06001324 if (mPmInternal.isOnlyCoreApps()) {
Jeff Sharkey6855c482016-03-31 14:34:38 -06001325 Slog.d(TAG, "System booted in core-only mode; ignoring volume " + vol.getId());
1326 return;
1327 }
Martijn Coenen7084c6a2019-11-22 16:32:09 +01001328 final ActivityManagerInternal amInternal =
1329 LocalServices.getService(ActivityManagerInternal.class);
1330
1331 if (mIsFuseEnabled && vol.mountUserId >= 0
1332 && !amInternal.isUserRunning(vol.mountUserId, 0)) {
1333 Slog.d(TAG, "Ignoring volume " + vol.getId() + " because user "
1334 + Integer.toString(vol.mountUserId) + " is no longer running.");
1335 return;
1336 }
Jeff Sharkey6855c482016-03-31 14:34:38 -06001337
Jeff Sharkey275e3e42015-04-24 16:10:32 -07001338 if (vol.type == VolumeInfo.TYPE_EMULATED) {
1339 final StorageManager storage = mContext.getSystemService(StorageManager.class);
1340 final VolumeInfo privateVol = storage.findPrivateForEmulated(vol);
1341
1342 if (Objects.equals(StorageManager.UUID_PRIVATE_INTERNAL, mPrimaryStorageUuid)
1343 && VolumeInfo.ID_PRIVATE_INTERNAL.equals(privateVol.id)) {
1344 Slog.v(TAG, "Found primary storage at " + vol);
1345 vol.mountFlags |= VolumeInfo.MOUNT_FLAG_PRIMARY;
1346 vol.mountFlags |= VolumeInfo.MOUNT_FLAG_VISIBLE;
1347 mHandler.obtainMessage(H_VOLUME_MOUNT, vol).sendToTarget();
1348
1349 } else if (Objects.equals(privateVol.fsUuid, mPrimaryStorageUuid)) {
1350 Slog.v(TAG, "Found primary storage at " + vol);
1351 vol.mountFlags |= VolumeInfo.MOUNT_FLAG_PRIMARY;
1352 vol.mountFlags |= VolumeInfo.MOUNT_FLAG_VISIBLE;
1353 mHandler.obtainMessage(H_VOLUME_MOUNT, vol).sendToTarget();
1354 }
Jeff Sharkeyb049e212012-09-07 23:16:01 -07001355
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07001356 } else if (vol.type == VolumeInfo.TYPE_PUBLIC) {
Jeff Sharkey275e3e42015-04-24 16:10:32 -07001357 // TODO: only look at first public partition
1358 if (Objects.equals(StorageManager.UUID_PRIMARY_PHYSICAL, mPrimaryStorageUuid)
1359 && vol.disk.isDefaultPrimary()) {
1360 Slog.v(TAG, "Found primary storage at " + vol);
Jeff Sharkey7e92ef32015-04-17 17:35:07 -07001361 vol.mountFlags |= VolumeInfo.MOUNT_FLAG_PRIMARY;
1362 vol.mountFlags |= VolumeInfo.MOUNT_FLAG_VISIBLE;
San Mehat4270e1e2010-01-29 05:32:19 -08001363 }
Jeff Sharkey7e92ef32015-04-17 17:35:07 -07001364
1365 // Adoptable public disks are visible to apps, since they meet
1366 // public API requirement of being in a stable location.
Jeff Sharkey275e3e42015-04-24 16:10:32 -07001367 if (vol.disk.isAdoptable()) {
Jeff Sharkey7e92ef32015-04-17 17:35:07 -07001368 vol.mountFlags |= VolumeInfo.MOUNT_FLAG_VISIBLE;
1369 }
1370
Jeff Sharkeyab15c392016-05-05 11:45:01 -06001371 vol.mountUserId = mCurrentUserId;
Jeff Sharkey48877892015-03-18 11:27:19 -07001372 mHandler.obtainMessage(H_VOLUME_MOUNT, vol).sendToTarget();
San Mehat4270e1e2010-01-29 05:32:19 -08001373
Jeff Sharkeyb2b9ab82015-04-05 21:10:42 -07001374 } else if (vol.type == VolumeInfo.TYPE_PRIVATE) {
1375 mHandler.obtainMessage(H_VOLUME_MOUNT, vol).sendToTarget();
1376
Risan05c41e62018-10-29 08:57:43 +09001377 } else if (vol.type == VolumeInfo.TYPE_STUB) {
1378 vol.mountUserId = mCurrentUserId;
1379 mHandler.obtainMessage(H_VOLUME_MOUNT, vol).sendToTarget();
San Mehat4270e1e2010-01-29 05:32:19 -08001380 } else {
Jeff Sharkey48877892015-03-18 11:27:19 -07001381 Slog.d(TAG, "Skipping automatic mounting of " + vol);
San Mehat4270e1e2010-01-29 05:32:19 -08001382 }
1383 }
1384
Jeff Sharkeye6c04f92015-04-18 21:38:05 -07001385 private boolean isBroadcastWorthy(VolumeInfo vol) {
1386 switch (vol.getType()) {
Jeff Sharkeyc7acac62015-06-12 16:16:56 -07001387 case VolumeInfo.TYPE_PRIVATE:
Jeff Sharkeye6c04f92015-04-18 21:38:05 -07001388 case VolumeInfo.TYPE_PUBLIC:
1389 case VolumeInfo.TYPE_EMULATED:
Risan05c41e62018-10-29 08:57:43 +09001390 case VolumeInfo.TYPE_STUB:
Jeff Sharkeye6c04f92015-04-18 21:38:05 -07001391 break;
1392 default:
1393 return false;
1394 }
1395
1396 switch (vol.getState()) {
1397 case VolumeInfo.STATE_MOUNTED:
1398 case VolumeInfo.STATE_MOUNTED_READ_ONLY:
1399 case VolumeInfo.STATE_EJECTING:
1400 case VolumeInfo.STATE_UNMOUNTED:
Jeff Sharkeyc7acac62015-06-12 16:16:56 -07001401 case VolumeInfo.STATE_UNMOUNTABLE:
Tony Mantlerf0d71052015-06-24 11:45:25 -07001402 case VolumeInfo.STATE_BAD_REMOVAL:
Jeff Sharkeye6c04f92015-04-18 21:38:05 -07001403 break;
1404 default:
1405 return false;
1406 }
1407
1408 return true;
1409 }
1410
Andreas Gampea36dc622018-02-05 17:19:22 -08001411 @GuardedBy("mLock")
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07001412 private void onVolumeStateChangedLocked(VolumeInfo vol, int oldState, int newState) {
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001413 // Remember that we saw this volume so we're ready to accept user
1414 // metadata, or so we can annoy them when a private volume is ejected
Jeff Sharkey3811f352019-05-14 11:54:36 -06001415 if (!TextUtils.isEmpty(vol.fsUuid)) {
Jeff Sharkey5cc0df22015-06-17 19:44:05 -07001416 VolumeRecord rec = mRecords.get(vol.fsUuid);
1417 if (rec == null) {
1418 rec = new VolumeRecord(vol.type, vol.fsUuid);
1419 rec.partGuid = vol.partGuid;
Jeff Sharkeye8a4b662015-06-27 15:43:45 -07001420 rec.createdMillis = System.currentTimeMillis();
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001421 if (vol.type == VolumeInfo.TYPE_PRIVATE) {
1422 rec.nickname = vol.disk.getDescription();
1423 }
1424 mRecords.put(rec.fsUuid, rec);
Jeff Sharkey5cc0df22015-06-17 19:44:05 -07001425 } else {
1426 // Handle upgrade case where we didn't store partition GUID
1427 if (TextUtils.isEmpty(rec.partGuid)) {
1428 rec.partGuid = vol.partGuid;
Jeff Sharkey5cc0df22015-06-17 19:44:05 -07001429 }
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001430 }
Jeff Sharkey3811f352019-05-14 11:54:36 -06001431
1432 rec.lastSeenMillis = System.currentTimeMillis();
1433 writeSettingsLocked();
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001434 }
1435
Jeff Sharkeye6c04f92015-04-18 21:38:05 -07001436 mCallbacks.notifyVolumeStateChanged(vol, oldState, newState);
1437
Yasuhiro Matsuda87a38b52015-07-24 22:10:16 +09001438 // Do not broadcast before boot has completed to avoid launching the
1439 // processes that receive the intent unnecessarily.
1440 if (mBootCompleted && isBroadcastWorthy(vol)) {
Jeff Sharkeye6c04f92015-04-18 21:38:05 -07001441 final Intent intent = new Intent(VolumeInfo.ACTION_VOLUME_STATE_CHANGED);
Jeff Sharkeyc7acac62015-06-12 16:16:56 -07001442 intent.putExtra(VolumeInfo.EXTRA_VOLUME_ID, vol.id);
1443 intent.putExtra(VolumeInfo.EXTRA_VOLUME_STATE, newState);
Tony Mantlerf0d71052015-06-24 11:45:25 -07001444 intent.putExtra(VolumeRecord.EXTRA_FS_UUID, vol.fsUuid);
Jeff Sharkey7732e1e2016-03-30 17:14:23 -06001445 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT
1446 | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
Jeff Sharkeyabc3e852015-08-03 14:41:13 -07001447 mHandler.obtainMessage(H_INTERNAL_BROADCAST, intent).sendToTarget();
Jeff Sharkeye6c04f92015-04-18 21:38:05 -07001448 }
Jeff Sharkeyb049e212012-09-07 23:16:01 -07001449
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001450 final String oldStateEnv = VolumeInfo.getEnvironmentForState(oldState);
1451 final String newStateEnv = VolumeInfo.getEnvironmentForState(newState);
Emily Bernier92aa5a22014-07-07 10:11:48 -04001452
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001453 if (!Objects.equals(oldStateEnv, newStateEnv)) {
1454 // Kick state changed event towards all started users. Any users
1455 // started after this point will trigger additional
1456 // user-specific broadcasts.
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07001457 for (int userId : mSystemUnlockedUsers) {
Jeff Sharkey46349872015-07-28 10:49:47 -07001458 if (vol.isVisibleForRead(userId)) {
Svet Ganov6ee871e2015-07-10 14:29:33 -07001459 final StorageVolume userVol = vol.buildStorageVolume(mContext, userId, false);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001460 mHandler.obtainMessage(H_VOLUME_BROADCAST, userVol).sendToTarget();
Jeff Sharkey48877892015-03-18 11:27:19 -07001461
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001462 mCallbacks.notifyStorageStateChanged(userVol.getPath(), oldStateEnv,
1463 newStateEnv);
San Mehat4270e1e2010-01-29 05:32:19 -08001464 }
1465 }
1466 }
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001467
Risan05c41e62018-10-29 08:57:43 +09001468 if ((vol.type == VolumeInfo.TYPE_PUBLIC || vol.type == VolumeInfo.TYPE_STUB)
1469 && vol.state == VolumeInfo.STATE_EJECTING) {
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001470 // TODO: this should eventually be handled by new ObbVolume state changes
1471 /*
1472 * Some OBBs might have been unmounted when this volume was
1473 * unmounted, so send a message to the handler to let it know to
1474 * remove those from the list of mounted OBBS.
1475 */
1476 mObbActionHandler.sendMessage(mObbActionHandler.obtainMessage(
1477 OBB_FLUSH_MOUNT_STATE, vol.path));
1478 }
Pavel Grafovce72ef02018-01-10 17:14:11 +00001479 maybeLogMediaMount(vol, newState);
1480 }
1481
1482 private void maybeLogMediaMount(VolumeInfo vol, int newState) {
1483 if (!SecurityLog.isLoggingEnabled()) {
1484 return;
1485 }
1486
1487 final DiskInfo disk = vol.getDisk();
1488 if (disk == null || (disk.flags & (DiskInfo.FLAG_SD | DiskInfo.FLAG_USB)) == 0) {
1489 return;
1490 }
1491
1492 // Sometimes there is a newline character.
1493 final String label = disk.label != null ? disk.label.trim() : "";
1494
1495 if (newState == VolumeInfo.STATE_MOUNTED
1496 || newState == VolumeInfo.STATE_MOUNTED_READ_ONLY) {
1497 SecurityLog.writeEvent(SecurityLog.TAG_MEDIA_MOUNT, vol.path, label);
1498 } else if (newState == VolumeInfo.STATE_UNMOUNTED
1499 || newState == VolumeInfo.STATE_BAD_REMOVAL) {
1500 SecurityLog.writeEvent(SecurityLog.TAG_MEDIA_UNMOUNT, vol.path, label);
1501 }
San Mehat4270e1e2010-01-29 05:32:19 -08001502 }
1503
Andreas Gampea36dc622018-02-05 17:19:22 -08001504 @GuardedBy("mLock")
Jeff Sharkey275e3e42015-04-24 16:10:32 -07001505 private void onMoveStatusLocked(int status) {
1506 if (mMoveCallback == null) {
1507 Slog.w(TAG, "Odd, status but no move requested");
1508 return;
1509 }
1510
1511 // TODO: estimate remaining time
1512 try {
Jeff Sharkey50a05452015-04-29 11:24:52 -07001513 mMoveCallback.onStatusChanged(-1, status, -1);
Jeff Sharkey275e3e42015-04-24 16:10:32 -07001514 } catch (RemoteException ignored) {
1515 }
1516
1517 // We've finished copying and we're about to clean up old data, so
1518 // remember that move was successful if we get rebooted
1519 if (status == MOVE_STATUS_COPY_FINISHED) {
1520 Slog.d(TAG, "Move to " + mMoveTargetUuid + " copy phase finshed; persisting");
1521
1522 mPrimaryStorageUuid = mMoveTargetUuid;
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001523 writeSettingsLocked();
Jeff Sharkey275e3e42015-04-24 16:10:32 -07001524 }
1525
1526 if (PackageManager.isMoveStatusFinished(status)) {
1527 Slog.d(TAG, "Move to " + mMoveTargetUuid + " finished with status " + status);
1528
1529 mMoveCallback = null;
1530 mMoveTargetUuid = null;
1531 }
1532 }
1533
Jeff Sharkey48877892015-03-18 11:27:19 -07001534 private void enforcePermission(String perm) {
1535 mContext.enforceCallingOrSelfPermission(perm, perm);
Mike Lockwooda5250c92011-05-23 13:44:04 -04001536 }
1537
Jeff Sharkey2e606d72015-07-27 14:19:54 -07001538 /**
1539 * Decide if volume is mountable per device policies.
1540 */
1541 private boolean isMountDisallowed(VolumeInfo vol) {
Philip P. Moltmannec3cbb22016-09-14 13:24:52 -07001542 UserManager userManager = mContext.getSystemService(UserManager.class);
1543
1544 boolean isUsbRestricted = false;
1545 if (vol.disk != null && vol.disk.isUsb()) {
1546 isUsbRestricted = userManager.hasUserRestriction(UserManager.DISALLOW_USB_FILE_TRANSFER,
Jeff Sharkey2e606d72015-07-27 14:19:54 -07001547 Binder.getCallingUserHandle());
Emily Bernier92aa5a22014-07-07 10:11:48 -04001548 }
Philip P. Moltmannec3cbb22016-09-14 13:24:52 -07001549
1550 boolean isTypeRestricted = false;
Risan05c41e62018-10-29 08:57:43 +09001551 if (vol.type == VolumeInfo.TYPE_PUBLIC || vol.type == VolumeInfo.TYPE_PRIVATE
1552 || vol.type == VolumeInfo.TYPE_STUB) {
Philip P. Moltmannec3cbb22016-09-14 13:24:52 -07001553 isTypeRestricted = userManager
1554 .hasUserRestriction(UserManager.DISALLOW_MOUNT_PHYSICAL_MEDIA,
1555 Binder.getCallingUserHandle());
1556 }
1557
1558 return isUsbRestricted || isTypeRestricted;
Emily Bernier92aa5a22014-07-07 10:11:48 -04001559 }
1560
Amith Yamasani462ac3a2015-06-30 14:21:01 -07001561 private void enforceAdminUser() {
1562 UserManager um = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
1563 final int callingUserId = UserHandle.getCallingUserId();
1564 boolean isAdmin;
1565 long token = Binder.clearCallingIdentity();
1566 try {
1567 isAdmin = um.getUserInfo(callingUserId).isAdmin();
1568 } finally {
1569 Binder.restoreCallingIdentity(token);
1570 }
1571 if (!isAdmin) {
1572 throw new SecurityException("Only admin users can adopt sd cards");
1573 }
1574 }
1575
Jeff Sharkeyb049e212012-09-07 23:16:01 -07001576 /**
Sudheer Shanka2250d562016-11-07 15:41:02 -08001577 * Constructs a new StorageManagerService instance
San Mehat207e5382010-02-04 20:46:54 -08001578 *
1579 * @param context Binder context for this service
1580 */
Sudheer Shanka2250d562016-11-07 15:41:02 -08001581 public StorageManagerService(Context context) {
Christopher Tated417d622013-08-19 16:14:25 -07001582 sSelf = this;
1583
Jeff Sharkey342b4bf2018-12-18 11:12:40 -07001584 // Snapshot feature flag used for this boot
1585 SystemProperties.set(StorageManager.PROP_ISOLATED_STORAGE_SNAPSHOT, Boolean.toString(
Jeff Sharkey06376802019-02-11 12:20:02 -07001586 SystemProperties.getBoolean(StorageManager.PROP_ISOLATED_STORAGE, true)));
shafik78fcd502019-09-25 13:50:04 +01001587 SystemProperties.set(StorageManager.PROP_FUSE_SNAPSHOT, Boolean.toString(
1588 SystemProperties.getBoolean(StorageManager.PROP_FUSE, false)));
1589
Zim17be6f92019-09-25 14:37:55 +01001590 mIsFuseEnabled = SystemProperties.getBoolean(StorageManager.PROP_FUSE_SNAPSHOT, false);
San Mehat207e5382010-02-04 20:46:54 -08001591 mContext = context;
Jeff Sharkey5d0c55c2019-01-24 14:32:31 -07001592 mResolver = mContext.getContentResolver();
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001593 mCallbacks = new Callbacks(FgThread.get().getLooper());
Jeff Sharkeyb9fe5372015-12-03 15:23:08 -07001594 mLockPatternUtils = new LockPatternUtils(mContext);
San Mehat207e5382010-02-04 20:46:54 -08001595
Dianne Hackbornefa92b22013-05-03 14:11:43 -07001596 HandlerThread hthread = new HandlerThread(TAG);
1597 hthread.start();
Sudheer Shanka2250d562016-11-07 15:41:02 -08001598 mHandler = new StorageManagerServiceHandler(hthread.getLooper());
Daniel Sandler5f27ef42010-03-16 15:42:02 -04001599
Sudheer Shanka2250d562016-11-07 15:41:02 -08001600 // Add OBB Action Handler to StorageManagerService thread.
Dianne Hackborn8d044e82013-04-30 17:24:15 -07001601 mObbActionHandler = new ObbActionHandler(IoThread.get().getLooper());
Kenny Roota02b8b02010-08-05 16:14:17 -07001602
Zim17be6f92019-09-25 14:37:55 +01001603 mStorageSessionController = new StorageSessionController(mContext, mIsFuseEnabled);
Zim42f1e9f2019-08-15 17:35:00 +01001604
Christopher Tate7265abe2014-11-21 13:54:45 -08001605 // Initialize the last-fstrim tracking if necessary
1606 File dataDir = Environment.getDataDirectory();
1607 File systemDir = new File(dataDir, "system");
1608 mLastMaintenanceFile = new File(systemDir, LAST_FSTRIM_FILE);
1609 if (!mLastMaintenanceFile.exists()) {
1610 // Not setting mLastMaintenance here means that we will force an
1611 // fstrim during reboot following the OTA that installs this code.
1612 try {
1613 (new FileOutputStream(mLastMaintenanceFile)).close();
1614 } catch (IOException e) {
1615 Slog.e(TAG, "Unable to create fstrim record " + mLastMaintenanceFile.getPath());
1616 }
1617 } else {
1618 mLastMaintenance = mLastMaintenanceFile.lastModified();
1619 }
1620
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001621 mSettingsFile = new AtomicFile(
Dianne Hackborne17b4452018-01-10 13:15:40 -08001622 new File(Environment.getDataSystemDirectory(), "storage.xml"), "storage-settings");
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001623
1624 synchronized (mLock) {
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001625 readSettingsLocked();
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001626 }
1627
Sudheer Shanka2250d562016-11-07 15:41:02 -08001628 LocalServices.addService(StorageManagerInternal.class, mStorageManagerInternal);
Svet Ganov6ee871e2015-07-10 14:29:33 -07001629
Jeff Sharkeybcd262d2015-06-10 09:41:17 -07001630 final IntentFilter userFilter = new IntentFilter();
1631 userFilter.addAction(Intent.ACTION_USER_ADDED);
1632 userFilter.addAction(Intent.ACTION_USER_REMOVED);
1633 mContext.registerReceiver(mUserReceiver, userFilter, null, mHandler);
1634
Jeff Sharkey5a9bb742015-11-03 10:15:57 -08001635 synchronized (mLock) {
1636 addInternalVolumeLocked();
1637 }
Amith Yamasania7892482015-08-07 11:09:05 -07001638
Kenny Root07714d42011-08-17 17:49:28 -07001639 // Add ourself to the Watchdog monitors if enabled.
1640 if (WATCHDOG_ENABLE) {
1641 Watchdog.getInstance().addMonitor(this);
1642 }
San Mehat207e5382010-02-04 20:46:54 -08001643 }
1644
Abhijeet Kaurb9847712019-11-19 16:35:47 +00001645 /**
1646 * Checks if user changed the persistent settings_fuse flag from Settings UI
1647 * and updates PROP_FUSE (reboots if changed).
1648 */
1649 private void updateFusePropFromSettings() {
1650 Boolean settingsFuseFlag = SystemProperties.getBoolean((FeatureFlagUtils.PERSIST_PREFIX
1651 + FeatureFlagUtils.SETTINGS_FUSE_FLAG), false);
1652 Slog.d(TAG, "The value of Settings Fuse Flag is " + settingsFuseFlag);
1653 if (SystemProperties.getBoolean(StorageManager.PROP_FUSE, false) != settingsFuseFlag) {
1654 Slog.d(TAG, "Set persist.sys.fuse to " + settingsFuseFlag);
1655 SystemProperties.set(StorageManager.PROP_FUSE, Boolean.toString(settingsFuseFlag));
1656 // Perform hard reboot to kick policy into place
1657 mContext.getSystemService(PowerManager.class).reboot("Reboot device for FUSE system"
1658 + "property change to take effect");
1659 }
1660 }
1661
Jeff Sharkeycd575992016-03-29 14:12:49 -06001662 private void start() {
peter.zhangb0d11d12019-06-13 16:39:30 +08001663 connectStoraged();
1664 connectVold();
Jeff Sharkeycd575992016-03-29 14:12:49 -06001665 }
1666
peter.zhangb0d11d12019-06-13 16:39:30 +08001667 private void connectStoraged() {
Jin Qian12690d52017-10-13 18:17:04 -07001668 IBinder binder = ServiceManager.getService("storaged");
1669 if (binder != null) {
1670 try {
1671 binder.linkToDeath(new DeathRecipient() {
1672 @Override
1673 public void binderDied() {
1674 Slog.w(TAG, "storaged died; reconnecting");
1675 mStoraged = null;
peter.zhangb0d11d12019-06-13 16:39:30 +08001676 connectStoraged();
Jin Qian12690d52017-10-13 18:17:04 -07001677 }
1678 }, 0);
1679 } catch (RemoteException e) {
1680 binder = null;
1681 }
1682 }
1683
1684 if (binder != null) {
1685 mStoraged = IStoraged.Stub.asInterface(binder);
1686 } else {
1687 Slog.w(TAG, "storaged not found; trying again");
1688 }
1689
peter.zhangb0d11d12019-06-13 16:39:30 +08001690 if (mStoraged == null) {
1691 BackgroundThread.getHandler().postDelayed(() -> {
1692 connectStoraged();
1693 }, DateUtils.SECOND_IN_MILLIS);
1694 } else {
1695 onDaemonConnected();
1696 }
1697 }
1698
1699 private void connectVold() {
1700 IBinder binder = ServiceManager.getService("vold");
Jeff Sharkey1019de92017-09-06 13:47:03 -06001701 if (binder != null) {
1702 try {
1703 binder.linkToDeath(new DeathRecipient() {
1704 @Override
1705 public void binderDied() {
1706 Slog.w(TAG, "vold died; reconnecting");
Jin Qian12690d52017-10-13 18:17:04 -07001707 mVold = null;
peter.zhangb0d11d12019-06-13 16:39:30 +08001708 connectVold();
Jeff Sharkey1019de92017-09-06 13:47:03 -06001709 }
1710 }, 0);
1711 } catch (RemoteException e) {
1712 binder = null;
1713 }
1714 }
1715
1716 if (binder != null) {
1717 mVold = IVold.Stub.asInterface(binder);
Jeff Sharkey8058fe62017-09-13 11:50:33 -06001718 try {
1719 mVold.setListener(mListener);
Jeff Sharkey8058fe62017-09-13 11:50:33 -06001720 } catch (RemoteException e) {
Jin Qian12690d52017-10-13 18:17:04 -07001721 mVold = null;
Jeff Sharkey8058fe62017-09-13 11:50:33 -06001722 Slog.w(TAG, "vold listener rejected; trying again", e);
1723 }
Jeff Sharkey1019de92017-09-06 13:47:03 -06001724 } else {
1725 Slog.w(TAG, "vold not found; trying again");
Jeff Sharkey1019de92017-09-06 13:47:03 -06001726 }
Jeff Sharkey8058fe62017-09-13 11:50:33 -06001727
peter.zhangb0d11d12019-06-13 16:39:30 +08001728 if (mVold == null) {
Jin Qian12690d52017-10-13 18:17:04 -07001729 BackgroundThread.getHandler().postDelayed(() -> {
peter.zhangb0d11d12019-06-13 16:39:30 +08001730 connectVold();
Jin Qian12690d52017-10-13 18:17:04 -07001731 }, DateUtils.SECOND_IN_MILLIS);
1732 } else {
1733 onDaemonConnected();
1734 }
Jeff Sharkey1019de92017-09-06 13:47:03 -06001735 }
1736
Jeff Sharkey11697f52018-12-13 10:14:42 -07001737 private void servicesReady() {
Sudheer Shankaff585072019-01-29 23:19:45 -08001738 mPmInternal = LocalServices.getService(PackageManagerInternal.class);
Sudheer Shankaff585072019-01-29 23:19:45 -08001739
1740 mIPackageManager = IPackageManager.Stub.asInterface(
1741 ServiceManager.getService("package"));
1742 mIAppOpsService = IAppOpsService.Stub.asInterface(
1743 ServiceManager.getService(Context.APP_OPS_SERVICE));
Zim74a9bba2019-09-03 20:49:13 +01001744
1745 ProviderInfo provider = mPmInternal.resolveContentProvider(
1746 MediaStore.AUTHORITY, PackageManager.MATCH_DIRECT_BOOT_AWARE
1747 | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
1748 UserHandle.getUserId(UserHandle.USER_SYSTEM));
1749 if (provider != null) {
Martijn Coenen44db1ac2019-12-03 16:06:19 +01001750 mMediaStoreAuthorityAppId = UserHandle.getAppId(provider.applicationInfo.uid);
Zim74a9bba2019-09-03 20:49:13 +01001751 }
1752
Sudheer Shankaff585072019-01-29 23:19:45 -08001753 try {
1754 mIAppOpsService.startWatchingMode(OP_REQUEST_INSTALL_PACKAGES, null, mAppOpsCallback);
Sudheer Shanka783c90e2019-04-12 13:55:20 -07001755 mIAppOpsService.startWatchingMode(OP_LEGACY_STORAGE, null, mAppOpsCallback);
Sudheer Shankaff585072019-01-29 23:19:45 -08001756 } catch (RemoteException e) {
1757 }
Jeff Sharkey11697f52018-12-13 10:14:42 -07001758 }
1759
1760 private static long getLastAccessTime(AppOpsManager manager,
1761 int uid, String packageName, int[] ops) {
1762 long maxTime = 0;
1763 final List<AppOpsManager.PackageOps> pkgs = manager.getOpsForPackage(uid, packageName, ops);
Eugene Susla04d021c2018-12-17 14:49:59 -08001764 for (AppOpsManager.PackageOps pkg : CollectionUtils.emptyIfNull(pkgs)) {
1765 for (AppOpsManager.OpEntry op : CollectionUtils.emptyIfNull(pkg.getOps())) {
Svet Ganovaf189e32019-02-15 18:45:29 -08001766 maxTime = Math.max(maxTime, op.getLastAccessTime(
1767 AppOpsManager.OP_FLAGS_ALL_TRUSTED));
Jeff Sharkey11697f52018-12-13 10:14:42 -07001768 }
1769 }
1770 return maxTime;
1771 }
1772
Jeff Sharkey56e62932015-03-21 20:41:00 -07001773 private void systemReady() {
Wale Ogunwale6767eae2018-05-03 15:52:51 -07001774 LocalServices.getService(ActivityTaskManagerInternal.class)
Jeff Sharkey9765e442017-12-14 22:15:14 -07001775 .registerScreenObserver(this);
1776
Jeff Sharkeyb049e212012-09-07 23:16:01 -07001777 mHandler.obtainMessage(H_SYSTEM_READY).sendToTarget();
1778 }
1779
Yasuhiro Matsuda87a38b52015-07-24 22:10:16 +09001780 private void bootCompleted() {
1781 mBootCompleted = true;
Daniel Rosenberg137aed12019-03-15 18:41:11 -07001782 mHandler.obtainMessage(H_BOOT_COMPLETED).sendToTarget();
Abhijeet Kaur10c56552019-12-04 14:17:40 +00001783 updateFusePropFromSettings();
Daniel Rosenberg137aed12019-03-15 18:41:11 -07001784 }
1785
1786 private void handleBootCompleted() {
1787 initIfBootedAndConnected();
1788 resetIfBootedAndConnected();
Yasuhiro Matsuda87a38b52015-07-24 22:10:16 +09001789 }
1790
Jeff Sharkeyfced5342015-05-10 14:53:34 -07001791 private String getDefaultPrimaryStorageUuid() {
1792 if (SystemProperties.getBoolean(StorageManager.PROP_PRIMARY_PHYSICAL, false)) {
1793 return StorageManager.UUID_PRIMARY_PHYSICAL;
1794 } else {
1795 return StorageManager.UUID_PRIVATE_INTERNAL;
1796 }
1797 }
1798
Andreas Gampea36dc622018-02-05 17:19:22 -08001799 @GuardedBy("mLock")
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001800 private void readSettingsLocked() {
1801 mRecords.clear();
Jeff Sharkeyfced5342015-05-10 14:53:34 -07001802 mPrimaryStorageUuid = getDefaultPrimaryStorageUuid();
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001803
1804 FileInputStream fis = null;
1805 try {
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001806 fis = mSettingsFile.openRead();
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001807 final XmlPullParser in = Xml.newPullParser();
Wojciech Staszkiewicz9e9e2e72015-05-08 14:58:46 +01001808 in.setInput(fis, StandardCharsets.UTF_8.name());
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001809
1810 int type;
1811 while ((type = in.next()) != END_DOCUMENT) {
1812 if (type == START_TAG) {
1813 final String tag = in.getName();
Jeff Sharkey620b32b2015-04-23 19:36:02 -07001814 if (TAG_VOLUMES.equals(tag)) {
1815 final int version = readIntAttribute(in, ATTR_VERSION, VERSION_INIT);
Jeff Sharkeyfced5342015-05-10 14:53:34 -07001816 final boolean primaryPhysical = SystemProperties.getBoolean(
1817 StorageManager.PROP_PRIMARY_PHYSICAL, false);
1818 final boolean validAttr = (version >= VERSION_FIX_PRIMARY)
1819 || (version >= VERSION_ADD_PRIMARY && !primaryPhysical);
1820 if (validAttr) {
Jeff Sharkey620b32b2015-04-23 19:36:02 -07001821 mPrimaryStorageUuid = readStringAttribute(in,
1822 ATTR_PRIMARY_STORAGE_UUID);
Jeff Sharkey620b32b2015-04-23 19:36:02 -07001823 }
Jeff Sharkey620b32b2015-04-23 19:36:02 -07001824 } else if (TAG_VOLUME.equals(tag)) {
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001825 final VolumeRecord rec = readVolumeRecord(in);
1826 mRecords.put(rec.fsUuid, rec);
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001827 }
1828 }
1829 }
1830 } catch (FileNotFoundException e) {
1831 // Missing metadata is okay, probably first boot
1832 } catch (IOException e) {
1833 Slog.wtf(TAG, "Failed reading metadata", e);
1834 } catch (XmlPullParserException e) {
1835 Slog.wtf(TAG, "Failed reading metadata", e);
1836 } finally {
1837 IoUtils.closeQuietly(fis);
1838 }
1839 }
1840
Andreas Gampea36dc622018-02-05 17:19:22 -08001841 @GuardedBy("mLock")
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001842 private void writeSettingsLocked() {
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001843 FileOutputStream fos = null;
1844 try {
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001845 fos = mSettingsFile.startWrite();
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001846
1847 XmlSerializer out = new FastXmlSerializer();
Wojciech Staszkiewicz9e9e2e72015-05-08 14:58:46 +01001848 out.setOutput(fos, StandardCharsets.UTF_8.name());
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001849 out.startDocument(null, true);
1850 out.startTag(null, TAG_VOLUMES);
Jeff Sharkeyfced5342015-05-10 14:53:34 -07001851 writeIntAttribute(out, ATTR_VERSION, VERSION_FIX_PRIMARY);
Jeff Sharkey620b32b2015-04-23 19:36:02 -07001852 writeStringAttribute(out, ATTR_PRIMARY_STORAGE_UUID, mPrimaryStorageUuid);
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001853 final int size = mRecords.size();
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001854 for (int i = 0; i < size; i++) {
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001855 final VolumeRecord rec = mRecords.valueAt(i);
1856 writeVolumeRecord(out, rec);
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001857 }
1858 out.endTag(null, TAG_VOLUMES);
1859 out.endDocument();
1860
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001861 mSettingsFile.finishWrite(fos);
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001862 } catch (IOException e) {
1863 if (fos != null) {
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001864 mSettingsFile.failWrite(fos);
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001865 }
1866 }
1867 }
1868
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001869 public static VolumeRecord readVolumeRecord(XmlPullParser in) throws IOException {
1870 final int type = readIntAttribute(in, ATTR_TYPE);
1871 final String fsUuid = readStringAttribute(in, ATTR_FS_UUID);
1872 final VolumeRecord meta = new VolumeRecord(type, fsUuid);
Jeff Sharkey5cc0df22015-06-17 19:44:05 -07001873 meta.partGuid = readStringAttribute(in, ATTR_PART_GUID);
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001874 meta.nickname = readStringAttribute(in, ATTR_NICKNAME);
1875 meta.userFlags = readIntAttribute(in, ATTR_USER_FLAGS);
Jeff Sharkey3811f352019-05-14 11:54:36 -06001876 meta.createdMillis = readLongAttribute(in, ATTR_CREATED_MILLIS, 0);
1877 meta.lastSeenMillis = readLongAttribute(in, ATTR_LAST_SEEN_MILLIS, 0);
1878 meta.lastTrimMillis = readLongAttribute(in, ATTR_LAST_TRIM_MILLIS, 0);
1879 meta.lastBenchMillis = readLongAttribute(in, ATTR_LAST_BENCH_MILLIS, 0);
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001880 return meta;
1881 }
1882
1883 public static void writeVolumeRecord(XmlSerializer out, VolumeRecord rec) throws IOException {
1884 out.startTag(null, TAG_VOLUME);
1885 writeIntAttribute(out, ATTR_TYPE, rec.type);
1886 writeStringAttribute(out, ATTR_FS_UUID, rec.fsUuid);
Jeff Sharkey5cc0df22015-06-17 19:44:05 -07001887 writeStringAttribute(out, ATTR_PART_GUID, rec.partGuid);
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001888 writeStringAttribute(out, ATTR_NICKNAME, rec.nickname);
1889 writeIntAttribute(out, ATTR_USER_FLAGS, rec.userFlags);
Jeff Sharkeye8a4b662015-06-27 15:43:45 -07001890 writeLongAttribute(out, ATTR_CREATED_MILLIS, rec.createdMillis);
Jeff Sharkey3811f352019-05-14 11:54:36 -06001891 writeLongAttribute(out, ATTR_LAST_SEEN_MILLIS, rec.lastSeenMillis);
Jeff Sharkeye8a4b662015-06-27 15:43:45 -07001892 writeLongAttribute(out, ATTR_LAST_TRIM_MILLIS, rec.lastTrimMillis);
1893 writeLongAttribute(out, ATTR_LAST_BENCH_MILLIS, rec.lastBenchMillis);
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001894 out.endTag(null, TAG_VOLUME);
1895 }
1896
San Mehat207e5382010-02-04 20:46:54 -08001897 /**
San Mehat4270e1e2010-01-29 05:32:19 -08001898 * Exposed API calls below here
1899 */
1900
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001901 @Override
Sudheer Shanka2250d562016-11-07 15:41:02 -08001902 public void registerListener(IStorageEventListener listener) {
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001903 mCallbacks.register(listener);
San Mehat4270e1e2010-01-29 05:32:19 -08001904 }
1905
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001906 @Override
Sudheer Shanka2250d562016-11-07 15:41:02 -08001907 public void unregisterListener(IStorageEventListener listener) {
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001908 mCallbacks.unregister(listener);
San Mehat4270e1e2010-01-29 05:32:19 -08001909 }
1910
Jeff Sharkey48877892015-03-18 11:27:19 -07001911 @Override
Sudheer Shanka2250d562016-11-07 15:41:02 -08001912 public void shutdown(final IStorageShutdownObserver observer) {
Jeff Sharkey48877892015-03-18 11:27:19 -07001913 enforcePermission(android.Manifest.permission.SHUTDOWN);
San Mehat4270e1e2010-01-29 05:32:19 -08001914
San Mehata5078592010-03-25 09:36:54 -07001915 Slog.i(TAG, "Shutting down");
Jeff Sharkey48877892015-03-18 11:27:19 -07001916 mHandler.obtainMessage(H_SHUTDOWN, observer).sendToTarget();
San Mehat4270e1e2010-01-29 05:32:19 -08001917 }
1918
Jeff Sharkey48877892015-03-18 11:27:19 -07001919 @Override
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001920 public void mount(String volId) {
1921 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001922
Jeff Sharkeyef10ee02015-07-05 14:17:27 -07001923 final VolumeInfo vol = findVolumeByIdOrThrow(volId);
Jeff Sharkey2e606d72015-07-27 14:19:54 -07001924 if (isMountDisallowed(vol)) {
1925 throw new SecurityException("Mounting " + volId + " restricted by policy");
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001926 }
Zim17be6f92019-09-25 14:37:55 +01001927
Sudheer Shanka3f0645b2018-09-18 13:07:59 -07001928 mount(vol);
1929 }
1930
Zim17be6f92019-09-25 14:37:55 +01001931 private void mount(VolumeInfo vol) {
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001932 try {
Zim17be6f92019-09-25 14:37:55 +01001933 // TODO(b/135341433): Remove paranoid logging when FUSE is stable
1934 Slog.i(TAG, "Mounting volume " + vol);
Zim95eca1d2019-11-15 18:03:00 +00001935 mVold.mount(vol.id, vol.mountFlags, vol.mountUserId, new IVoldMountCallback.Stub() {
1936 @Override
1937 public boolean onVolumeChecking(FileDescriptor deviceFd, String path,
1938 String internalPath) {
1939 vol.path = path;
1940 vol.internalPath = internalPath;
1941 try {
1942 mStorageSessionController.onVolumeMount(deviceFd, vol);
1943 return true;
1944 } catch (ExternalStorageServiceException e) {
1945 Slog.i(TAG, "Failed to mount volume " + vol, e);
1946 return false;
1947 }
1948 }
1949 });
Zim17be6f92019-09-25 14:37:55 +01001950 Slog.i(TAG, "Mounted volume " + vol);
Jeff Sharkeyace874b2017-09-07 15:27:33 -06001951 } catch (Exception e) {
1952 Slog.wtf(TAG, e);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001953 }
1954 }
1955
1956 @Override
1957 public void unmount(String volId) {
1958 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001959
Jeff Sharkeyef10ee02015-07-05 14:17:27 -07001960 final VolumeInfo vol = findVolumeByIdOrThrow(volId);
Sudheer Shanka3f0645b2018-09-18 13:07:59 -07001961 unmount(vol);
1962 }
1963
1964 private void unmount(VolumeInfo vol) {
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001965 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06001966 mVold.unmount(vol.id);
Zim17be6f92019-09-25 14:37:55 +01001967 mStorageSessionController.onVolumeUnmount(vol);
Jeff Sharkeyace874b2017-09-07 15:27:33 -06001968 } catch (Exception e) {
1969 Slog.wtf(TAG, e);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001970 }
1971 }
1972
1973 @Override
1974 public void format(String volId) {
Jeff Sharkey48877892015-03-18 11:27:19 -07001975 enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);
San Mehat5b77dab2010-01-26 13:28:50 -08001976
Jeff Sharkeyef10ee02015-07-05 14:17:27 -07001977 final VolumeInfo vol = findVolumeByIdOrThrow(volId);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001978 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06001979 mVold.format(vol.id, "auto");
Jeff Sharkeyace874b2017-09-07 15:27:33 -06001980 } catch (Exception e) {
1981 Slog.wtf(TAG, e);
Jeff Sharkey48877892015-03-18 11:27:19 -07001982 }
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001983 }
1984
1985 @Override
Jeff Sharkey7e19f532017-11-06 13:54:11 -07001986 public void benchmark(String volId, IVoldTaskListener listener) {
Jeff Sharkey9756d752015-05-14 21:07:42 -07001987 enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);
Jeff Sharkey9756d752015-05-14 21:07:42 -07001988
1989 try {
Jeff Sharkeyb302c542017-09-15 12:57:59 -06001990 mVold.benchmark(volId, new IVoldTaskListener.Stub() {
1991 @Override
1992 public void onStatus(int status, PersistableBundle extras) {
Jeff Sharkey7e19f532017-11-06 13:54:11 -07001993 dispatchOnStatus(listener, status, extras);
Jeff Sharkeyb302c542017-09-15 12:57:59 -06001994 }
1995
1996 @Override
1997 public void onFinished(int status, PersistableBundle extras) {
Jeff Sharkey7e19f532017-11-06 13:54:11 -07001998 dispatchOnFinished(listener, status, extras);
Jeff Sharkeyb302c542017-09-15 12:57:59 -06001999
2000 final String path = extras.getString("path");
2001 final String ident = extras.getString("ident");
2002 final long create = extras.getLong("create");
2003 final long run = extras.getLong("run");
2004 final long destroy = extras.getLong("destroy");
2005
2006 final DropBoxManager dropBox = mContext.getSystemService(DropBoxManager.class);
2007 dropBox.addText(TAG_STORAGE_BENCHMARK, scrubPath(path)
2008 + " " + ident + " " + create + " " + run + " " + destroy);
2009
2010 synchronized (mLock) {
2011 final VolumeRecord rec = findRecordForPath(path);
2012 if (rec != null) {
2013 rec.lastBenchMillis = System.currentTimeMillis();
2014 writeSettingsLocked();
2015 }
2016 }
2017 }
2018 });
Jeff Sharkey7e19f532017-11-06 13:54:11 -07002019 } catch (RemoteException e) {
2020 throw e.rethrowAsRuntimeException();
Jeff Sharkey9756d752015-05-14 21:07:42 -07002021 }
2022 }
2023
2024 @Override
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07002025 public void partitionPublic(String diskId) {
2026 enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07002027
Jeff Sharkeyeba260d2015-04-19 14:35:16 -07002028 final CountDownLatch latch = findOrCreateDiskScanLatch(diskId);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07002029 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002030 mVold.partition(diskId, IVold.PARTITION_TYPE_PUBLIC, -1);
Jeff Sharkeyedcdaf62015-07-09 09:45:36 -07002031 waitForLatch(latch, "partitionPublic", 3 * DateUtils.MINUTE_IN_MILLIS);
Jeff Sharkeyace874b2017-09-07 15:27:33 -06002032 } catch (Exception e) {
2033 Slog.wtf(TAG, e);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07002034 }
2035 }
2036
2037 @Override
2038 public void partitionPrivate(String diskId) {
2039 enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);
Amith Yamasani462ac3a2015-06-30 14:21:01 -07002040 enforceAdminUser();
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07002041
Jeff Sharkeyeba260d2015-04-19 14:35:16 -07002042 final CountDownLatch latch = findOrCreateDiskScanLatch(diskId);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07002043 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002044 mVold.partition(diskId, IVold.PARTITION_TYPE_PRIVATE, -1);
Jeff Sharkeyedcdaf62015-07-09 09:45:36 -07002045 waitForLatch(latch, "partitionPrivate", 3 * DateUtils.MINUTE_IN_MILLIS);
Jeff Sharkeyace874b2017-09-07 15:27:33 -06002046 } catch (Exception e) {
2047 Slog.wtf(TAG, e);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07002048 }
2049 }
2050
2051 @Override
2052 public void partitionMixed(String diskId, int ratio) {
2053 enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);
Amith Yamasani462ac3a2015-06-30 14:21:01 -07002054 enforceAdminUser();
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07002055
Jeff Sharkeyeba260d2015-04-19 14:35:16 -07002056 final CountDownLatch latch = findOrCreateDiskScanLatch(diskId);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07002057 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002058 mVold.partition(diskId, IVold.PARTITION_TYPE_MIXED, ratio);
Jeff Sharkeyedcdaf62015-07-09 09:45:36 -07002059 waitForLatch(latch, "partitionMixed", 3 * DateUtils.MINUTE_IN_MILLIS);
Jeff Sharkeyace874b2017-09-07 15:27:33 -06002060 } catch (Exception e) {
2061 Slog.wtf(TAG, e);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07002062 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002063 }
2064
Jeff Sharkey48877892015-03-18 11:27:19 -07002065 @Override
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07002066 public void setVolumeNickname(String fsUuid, String nickname) {
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07002067 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07002068
Jeff Sharkey50a05452015-04-29 11:24:52 -07002069 Preconditions.checkNotNull(fsUuid);
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07002070 synchronized (mLock) {
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07002071 final VolumeRecord rec = mRecords.get(fsUuid);
2072 rec.nickname = nickname;
Jeff Sharkey50a05452015-04-29 11:24:52 -07002073 mCallbacks.notifyVolumeRecordChanged(rec);
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07002074 writeSettingsLocked();
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07002075 }
2076 }
2077
2078 @Override
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07002079 public void setVolumeUserFlags(String fsUuid, int flags, int mask) {
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07002080 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07002081
Jeff Sharkey50a05452015-04-29 11:24:52 -07002082 Preconditions.checkNotNull(fsUuid);
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07002083 synchronized (mLock) {
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07002084 final VolumeRecord rec = mRecords.get(fsUuid);
2085 rec.userFlags = (rec.userFlags & ~mask) | (flags & mask);
Jeff Sharkey50a05452015-04-29 11:24:52 -07002086 mCallbacks.notifyVolumeRecordChanged(rec);
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07002087 writeSettingsLocked();
2088 }
2089 }
2090
2091 @Override
2092 public void forgetVolume(String fsUuid) {
2093 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07002094
Jeff Sharkey50a05452015-04-29 11:24:52 -07002095 Preconditions.checkNotNull(fsUuid);
Jeff Sharkey5a9bb742015-11-03 10:15:57 -08002096
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07002097 synchronized (mLock) {
Jeff Sharkey5cc0df22015-06-17 19:44:05 -07002098 final VolumeRecord rec = mRecords.remove(fsUuid);
2099 if (rec != null && !TextUtils.isEmpty(rec.partGuid)) {
Jeff Sharkeydb4b6192017-10-24 11:08:50 -06002100 mHandler.obtainMessage(H_PARTITION_FORGET, rec).sendToTarget();
Jeff Sharkey5cc0df22015-06-17 19:44:05 -07002101 }
2102 mCallbacks.notifyVolumeForgotten(fsUuid);
Jeff Sharkey50a05452015-04-29 11:24:52 -07002103
2104 // If this had been primary storage, revert back to internal and
2105 // reset vold so we bind into new volume into place.
2106 if (Objects.equals(mPrimaryStorageUuid, fsUuid)) {
Jeff Sharkeyfced5342015-05-10 14:53:34 -07002107 mPrimaryStorageUuid = getDefaultPrimaryStorageUuid();
Jeff Sharkey5a9bb742015-11-03 10:15:57 -08002108 mHandler.obtainMessage(H_RESET).sendToTarget();
Jeff Sharkey50a05452015-04-29 11:24:52 -07002109 }
2110
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07002111 writeSettingsLocked();
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07002112 }
2113 }
2114
Jeff Sharkey7d2af542015-05-12 15:27:15 -07002115 @Override
2116 public void forgetAllVolumes() {
2117 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
Jeff Sharkey7d2af542015-05-12 15:27:15 -07002118
Jeff Sharkey50a05452015-04-29 11:24:52 -07002119 synchronized (mLock) {
2120 for (int i = 0; i < mRecords.size(); i++) {
2121 final String fsUuid = mRecords.keyAt(i);
Jeff Sharkey5cc0df22015-06-17 19:44:05 -07002122 final VolumeRecord rec = mRecords.valueAt(i);
2123 if (!TextUtils.isEmpty(rec.partGuid)) {
Jeff Sharkeydb4b6192017-10-24 11:08:50 -06002124 mHandler.obtainMessage(H_PARTITION_FORGET, rec).sendToTarget();
Jeff Sharkey5cc0df22015-06-17 19:44:05 -07002125 }
Jeff Sharkey50a05452015-04-29 11:24:52 -07002126 mCallbacks.notifyVolumeForgotten(fsUuid);
2127 }
Jeff Sharkey50a05452015-04-29 11:24:52 -07002128 mRecords.clear();
Jeff Sharkey50a05452015-04-29 11:24:52 -07002129
Jeff Sharkeyfced5342015-05-10 14:53:34 -07002130 if (!Objects.equals(StorageManager.UUID_PRIVATE_INTERNAL, mPrimaryStorageUuid)) {
2131 mPrimaryStorageUuid = getDefaultPrimaryStorageUuid();
2132 }
2133
2134 writeSettingsLocked();
Jeff Sharkey5a9bb742015-11-03 10:15:57 -08002135 mHandler.obtainMessage(H_RESET).sendToTarget();
Jeff Sharkey50a05452015-04-29 11:24:52 -07002136 }
2137 }
2138
Jeff Sharkeydb4b6192017-10-24 11:08:50 -06002139 private void forgetPartition(String partGuid, String fsUuid) {
Jeff Sharkey5cc0df22015-06-17 19:44:05 -07002140 try {
Jeff Sharkeydb4b6192017-10-24 11:08:50 -06002141 mVold.forgetPartition(partGuid, fsUuid);
Jeff Sharkeyace874b2017-09-07 15:27:33 -06002142 } catch (Exception e) {
2143 Slog.wtf(TAG, e);
Jeff Sharkey5cc0df22015-06-17 19:44:05 -07002144 }
2145 }
2146
Jeff Sharkey31d0b702016-11-21 14:16:53 -07002147 @Override
Jeff Sharkey7e19f532017-11-06 13:54:11 -07002148 public void fstrim(int flags, IVoldTaskListener listener) {
Jeff Sharkey31d0b702016-11-21 14:16:53 -07002149 enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);
Jeff Sharkey31d0b702016-11-21 14:16:53 -07002150
2151 try {
Sandeep Patil7d5c4912019-04-15 09:27:30 -07002152 // Block based checkpoint process runs fstrim. So, if checkpoint is in progress
2153 // (first boot after OTA), We skip idle maintenance and make sure the last
2154 // fstrim time is still updated. If file based checkpoints are used, we run
2155 // idle maintenance (GC + fstrim) regardless of checkpoint status.
2156 if (!needsCheckpoint() || !supportsBlockCheckpoint()) {
2157 mVold.fstrim(flags, new IVoldTaskListener.Stub() {
2158 @Override
2159 public void onStatus(int status, PersistableBundle extras) {
2160 dispatchOnStatus(listener, status, extras);
Jeff Sharkey7e19f532017-11-06 13:54:11 -07002161
Sandeep Patil7d5c4912019-04-15 09:27:30 -07002162 // Ignore trim failures
2163 if (status != 0) return;
Jeff Sharkeyb302c542017-09-15 12:57:59 -06002164
Sandeep Patil7d5c4912019-04-15 09:27:30 -07002165 final String path = extras.getString("path");
2166 final long bytes = extras.getLong("bytes");
2167 final long time = extras.getLong("time");
Jeff Sharkeyb302c542017-09-15 12:57:59 -06002168
Sandeep Patil7d5c4912019-04-15 09:27:30 -07002169 final DropBoxManager dropBox = mContext.getSystemService(DropBoxManager.class);
2170 dropBox.addText(TAG_STORAGE_TRIM, scrubPath(path) + " " + bytes + " " + time);
Jeff Sharkeyb302c542017-09-15 12:57:59 -06002171
Sandeep Patil7d5c4912019-04-15 09:27:30 -07002172 synchronized (mLock) {
2173 final VolumeRecord rec = findRecordForPath(path);
2174 if (rec != null) {
2175 rec.lastTrimMillis = System.currentTimeMillis();
2176 writeSettingsLocked();
2177 }
Jeff Sharkeyb302c542017-09-15 12:57:59 -06002178 }
2179 }
Jeff Sharkeyb302c542017-09-15 12:57:59 -06002180
Sandeep Patil7d5c4912019-04-15 09:27:30 -07002181 @Override
2182 public void onFinished(int status, PersistableBundle extras) {
2183 dispatchOnFinished(listener, status, extras);
Jeff Sharkey7e19f532017-11-06 13:54:11 -07002184
Sandeep Patil7d5c4912019-04-15 09:27:30 -07002185 // TODO: benchmark when desired
2186 }
2187 });
2188 } else {
2189 Slog.i(TAG, "Skipping fstrim - block based checkpoint in progress");
2190 }
Jeff Sharkey7e19f532017-11-06 13:54:11 -07002191 } catch (RemoteException e) {
2192 throw e.rethrowAsRuntimeException();
Jeff Sharkey31d0b702016-11-21 14:16:53 -07002193 }
2194 }
2195
Jin Qiana85b9912017-10-17 15:48:18 -07002196 void runIdleMaint(Runnable callback) {
2197 enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);
2198
2199 try {
Sandeep Patil7d5c4912019-04-15 09:27:30 -07002200 // Block based checkpoint process runs fstrim. So, if checkpoint is in progress
2201 // (first boot after OTA), We skip idle maintenance and make sure the last
2202 // fstrim time is still updated. If file based checkpoints are used, we run
2203 // idle maintenance (GC + fstrim) regardless of checkpoint status.
2204 if (!needsCheckpoint() || !supportsBlockCheckpoint()) {
2205 mVold.runIdleMaint(new IVoldTaskListener.Stub() {
2206 @Override
2207 public void onStatus(int status, PersistableBundle extras) {
2208 // Not currently used
Jin Qiana85b9912017-10-17 15:48:18 -07002209 }
Sandeep Patil7d5c4912019-04-15 09:27:30 -07002210 @Override
2211 public void onFinished(int status, PersistableBundle extras) {
2212 if (callback != null) {
2213 BackgroundThread.getHandler().post(callback);
2214 }
2215 }
2216 });
2217 } else {
2218 Slog.i(TAG, "Skipping idle maintenance - block based checkpoint in progress");
2219 }
Jin Qiana85b9912017-10-17 15:48:18 -07002220 } catch (Exception e) {
2221 Slog.wtf(TAG, e);
2222 }
2223 }
2224
2225 @Override
2226 public void runIdleMaintenance() {
2227 runIdleMaint(null);
2228 }
2229
2230 void abortIdleMaint(Runnable callback) {
2231 enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);
2232
2233 try {
2234 mVold.abortIdleMaint(new IVoldTaskListener.Stub() {
2235 @Override
2236 public void onStatus(int status, PersistableBundle extras) {
2237 // Not currently used
2238 }
2239 @Override
2240 public void onFinished(int status, PersistableBundle extras) {
2241 if (callback != null) {
2242 BackgroundThread.getHandler().post(callback);
2243 }
2244 }
2245 });
2246 } catch (Exception e) {
2247 Slog.wtf(TAG, e);
2248 }
2249 }
2250
2251 @Override
2252 public void abortIdleMaintenance() {
2253 abortIdleMaint(null);
2254 }
2255
Svet Ganov6ee871e2015-07-10 14:29:33 -07002256 private void remountUidExternalStorage(int uid, int mode) {
Zim4f1a24d2019-11-27 16:35:58 +00002257 if (uid == Process.SYSTEM_UID) {
2258 // No need to remount uid for system because it has all access anyways
2259 return;
2260 }
2261
Jeff Sharkey9527b222015-06-24 15:24:48 -07002262 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002263 mVold.remountUid(uid, mode);
Jeff Sharkeyace874b2017-09-07 15:27:33 -06002264 } catch (Exception e) {
2265 Slog.wtf(TAG, e);
Jeff Sharkey9527b222015-06-24 15:24:48 -07002266 }
2267 }
2268
2269 @Override
Jeff Sharkey4c099d02015-05-15 13:45:00 -07002270 public void setDebugFlags(int flags, int mask) {
2271 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
Jeff Sharkey4c099d02015-05-15 13:45:00 -07002272
Jeff Sharkeyba512352015-11-12 20:17:45 -08002273 if ((mask & StorageManager.DEBUG_EMULATE_FBE) != 0) {
Jeff Sharkey00455bf2016-11-04 14:45:24 -06002274 if (!EMULATE_FBE_SUPPORTED) {
2275 throw new IllegalStateException(
2276 "Emulation not supported on this device");
2277 }
Paul Lawrence20be5d62016-02-26 13:51:17 -08002278 if (StorageManager.isFileEncryptedNativeOnly()) {
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07002279 throw new IllegalStateException(
Jeff Sharkey00455bf2016-11-04 14:45:24 -06002280 "Emulation not supported on device with native FBE");
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07002281 }
Jeff Sharkey5a785162016-03-21 13:02:06 -06002282 if (mLockPatternUtils.isCredentialRequiredToDecrypt(false)) {
2283 throw new IllegalStateException(
2284 "Emulation requires disabling 'Secure start-up' in Settings > Security");
2285 }
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07002286
Jeff Sharkey1176e512016-02-29 17:01:26 -07002287 final long token = Binder.clearCallingIdentity();
2288 try {
2289 final boolean emulateFbe = (flags & StorageManager.DEBUG_EMULATE_FBE) != 0;
2290 SystemProperties.set(StorageManager.PROP_EMULATE_FBE, Boolean.toString(emulateFbe));
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07002291
Jeff Sharkey1176e512016-02-29 17:01:26 -07002292 // Perform hard reboot to kick policy into place
2293 mContext.getSystemService(PowerManager.class).reboot(null);
2294 } finally {
2295 Binder.restoreCallingIdentity(token);
2296 }
Jeff Sharkeyba512352015-11-12 20:17:45 -08002297 }
Jeff Sharkey4c099d02015-05-15 13:45:00 -07002298
Jeff Sharkey901c0422018-04-20 13:11:20 -06002299 if ((mask & (StorageManager.DEBUG_ADOPTABLE_FORCE_ON
2300 | StorageManager.DEBUG_ADOPTABLE_FORCE_OFF)) != 0) {
2301 final String value;
2302 if ((flags & StorageManager.DEBUG_ADOPTABLE_FORCE_ON) != 0) {
2303 value = "force_on";
2304 } else if ((flags & StorageManager.DEBUG_ADOPTABLE_FORCE_OFF) != 0) {
2305 value = "force_off";
2306 } else {
2307 value = "";
2308 }
Jeff Sharkeyba512352015-11-12 20:17:45 -08002309
Jeff Sharkey901c0422018-04-20 13:11:20 -06002310 final long token = Binder.clearCallingIdentity();
2311 try {
2312 SystemProperties.set(StorageManager.PROP_ADOPTABLE, value);
2313
2314 // Reset storage to kick new setting into place
Jeff Sharkeyba512352015-11-12 20:17:45 -08002315 mHandler.obtainMessage(H_RESET).sendToTarget();
Jeff Sharkey901c0422018-04-20 13:11:20 -06002316 } finally {
2317 Binder.restoreCallingIdentity(token);
Jeff Sharkeyba512352015-11-12 20:17:45 -08002318 }
Jeff Sharkey4c099d02015-05-15 13:45:00 -07002319 }
Jeff Sharkey33dd1562016-04-07 11:05:33 -06002320
2321 if ((mask & (StorageManager.DEBUG_SDCARDFS_FORCE_ON
2322 | StorageManager.DEBUG_SDCARDFS_FORCE_OFF)) != 0) {
2323 final String value;
2324 if ((flags & StorageManager.DEBUG_SDCARDFS_FORCE_ON) != 0) {
2325 value = "force_on";
2326 } else if ((flags & StorageManager.DEBUG_SDCARDFS_FORCE_OFF) != 0) {
2327 value = "force_off";
2328 } else {
2329 value = "";
2330 }
2331
2332 final long token = Binder.clearCallingIdentity();
2333 try {
2334 SystemProperties.set(StorageManager.PROP_SDCARDFS, value);
2335
2336 // Reset storage to kick new setting into place
2337 mHandler.obtainMessage(H_RESET).sendToTarget();
2338 } finally {
2339 Binder.restoreCallingIdentity(token);
2340 }
2341 }
Jeff Sharkeye53e2d92017-03-25 23:14:06 -06002342
2343 if ((mask & StorageManager.DEBUG_VIRTUAL_DISK) != 0) {
2344 final boolean enabled = (flags & StorageManager.DEBUG_VIRTUAL_DISK) != 0;
2345
2346 final long token = Binder.clearCallingIdentity();
2347 try {
2348 SystemProperties.set(StorageManager.PROP_VIRTUAL_DISK, Boolean.toString(enabled));
2349
2350 // Reset storage to kick new setting into place
2351 mHandler.obtainMessage(H_RESET).sendToTarget();
2352 } finally {
2353 Binder.restoreCallingIdentity(token);
2354 }
2355 }
Sudheer Shankabe0febe2018-11-07 18:24:37 -08002356
Jeff Sharkeyb0c363b22018-12-15 11:53:03 -07002357 if ((mask & (StorageManager.DEBUG_ISOLATED_STORAGE_FORCE_ON
2358 | StorageManager.DEBUG_ISOLATED_STORAGE_FORCE_OFF)) != 0) {
2359 final int value;
2360 if ((flags & StorageManager.DEBUG_ISOLATED_STORAGE_FORCE_ON) != 0) {
2361 value = 1;
2362 } else if ((flags & StorageManager.DEBUG_ISOLATED_STORAGE_FORCE_OFF) != 0) {
2363 value = -1;
2364 } else {
2365 value = 0;
2366 }
Sudheer Shankabe0febe2018-11-07 18:24:37 -08002367
2368 final long token = Binder.clearCallingIdentity();
2369 try {
Jeff Sharkeyb0c363b22018-12-15 11:53:03 -07002370 Settings.Global.putInt(mContext.getContentResolver(),
2371 Settings.Global.ISOLATED_STORAGE_LOCAL, value);
2372 refreshIsolatedStorageSettings();
Sudheer Shankabe0febe2018-11-07 18:24:37 -08002373
2374 // Perform hard reboot to kick policy into place
Jeff Sharkey36274992019-02-27 12:09:57 -07002375 mHandler.post(() -> {
2376 mContext.getSystemService(PowerManager.class).reboot(null);
2377 });
2378 } finally {
2379 Binder.restoreCallingIdentity(token);
2380 }
2381 }
Jeff Sharkey4c099d02015-05-15 13:45:00 -07002382 }
2383
2384 @Override
Jeff Sharkey275e3e42015-04-24 16:10:32 -07002385 public String getPrimaryStorageUuid() {
Jeff Sharkey620b32b2015-04-23 19:36:02 -07002386 synchronized (mLock) {
2387 return mPrimaryStorageUuid;
2388 }
2389 }
2390
2391 @Override
Jeff Sharkey275e3e42015-04-24 16:10:32 -07002392 public void setPrimaryStorageUuid(String volumeUuid, IPackageMoveObserver callback) {
2393 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
Jeff Sharkey620b32b2015-04-23 19:36:02 -07002394
Jeff Sharkeya31460c2016-06-22 09:04:33 -06002395 final VolumeInfo from;
2396 final VolumeInfo to;
2397
Jeff Sharkey275e3e42015-04-24 16:10:32 -07002398 synchronized (mLock) {
Jeff Sharkeyfced5342015-05-10 14:53:34 -07002399 if (Objects.equals(mPrimaryStorageUuid, volumeUuid)) {
2400 throw new IllegalArgumentException("Primary storage already at " + volumeUuid);
Jeff Sharkey275e3e42015-04-24 16:10:32 -07002401 }
2402
2403 if (mMoveCallback != null) {
2404 throw new IllegalStateException("Move already in progress");
2405 }
2406 mMoveCallback = callback;
2407 mMoveTargetUuid = volumeUuid;
2408
Jeff Sharkeya65e6492017-06-21 13:45:11 -06002409 // We need all the users unlocked to move their primary storage
2410 final List<UserInfo> users = mContext.getSystemService(UserManager.class).getUsers();
2411 for (UserInfo user : users) {
2412 if (StorageManager.isFileEncryptedNativeOrEmulated()
2413 && !isUserKeyUnlocked(user.id)) {
2414 Slog.w(TAG, "Failing move due to locked user " + user.id);
2415 onMoveStatusLocked(PackageManager.MOVE_FAILED_LOCKED_USER);
2416 return;
2417 }
2418 }
2419
Jeff Sharkeyfced5342015-05-10 14:53:34 -07002420 // When moving to/from primary physical volume, we probably just nuked
2421 // the current storage location, so we have nothing to move.
2422 if (Objects.equals(StorageManager.UUID_PRIMARY_PHYSICAL, mPrimaryStorageUuid)
2423 || Objects.equals(StorageManager.UUID_PRIMARY_PHYSICAL, volumeUuid)) {
2424 Slog.d(TAG, "Skipping move to/from primary physical");
2425 onMoveStatusLocked(MOVE_STATUS_COPY_FINISHED);
2426 onMoveStatusLocked(PackageManager.MOVE_SUCCEEDED);
Jeff Sharkey5a9bb742015-11-03 10:15:57 -08002427 mHandler.obtainMessage(H_RESET).sendToTarget();
Jeff Sharkeya31460c2016-06-22 09:04:33 -06002428 return;
Jeff Sharkeyfced5342015-05-10 14:53:34 -07002429
2430 } else {
Jeff Sharkeya31460c2016-06-22 09:04:33 -06002431 from = findStorageForUuid(mPrimaryStorageUuid);
2432 to = findStorageForUuid(volumeUuid);
Jeff Sharkeyef10ee02015-07-05 14:17:27 -07002433
2434 if (from == null) {
2435 Slog.w(TAG, "Failing move due to missing from volume " + mPrimaryStorageUuid);
2436 onMoveStatusLocked(PackageManager.MOVE_FAILED_INTERNAL_ERROR);
2437 return;
2438 } else if (to == null) {
2439 Slog.w(TAG, "Failing move due to missing to volume " + volumeUuid);
2440 onMoveStatusLocked(PackageManager.MOVE_FAILED_INTERNAL_ERROR);
2441 return;
2442 }
Jeff Sharkey275e3e42015-04-24 16:10:32 -07002443 }
Jeff Sharkey620b32b2015-04-23 19:36:02 -07002444 }
Jeff Sharkeya31460c2016-06-22 09:04:33 -06002445
2446 try {
Jeff Sharkeyb302c542017-09-15 12:57:59 -06002447 mVold.moveStorage(from.id, to.id, new IVoldTaskListener.Stub() {
2448 @Override
2449 public void onStatus(int status, PersistableBundle extras) {
2450 synchronized (mLock) {
2451 onMoveStatusLocked(status);
2452 }
2453 }
2454
2455 @Override
2456 public void onFinished(int status, PersistableBundle extras) {
2457 // Not currently used
2458 }
2459 });
Jeff Sharkeyace874b2017-09-07 15:27:33 -06002460 } catch (Exception e) {
2461 Slog.wtf(TAG, e);
Jeff Sharkeya31460c2016-06-22 09:04:33 -06002462 }
Jeff Sharkey620b32b2015-04-23 19:36:02 -07002463 }
2464
San Mehatb1043402010-02-05 08:26:50 -08002465 private void warnOnNotMounted() {
Jeff Sharkey48877892015-03-18 11:27:19 -07002466 synchronized (mLock) {
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07002467 for (int i = 0; i < mVolumes.size(); i++) {
2468 final VolumeInfo vol = mVolumes.valueAt(i);
Jeff Sharkey27de30d2015-04-18 16:20:27 -07002469 if (vol.isPrimary() && vol.isMountedWritable()) {
Jeff Sharkey48877892015-03-18 11:27:19 -07002470 // Cool beans, we have a mounted primary volume
2471 return;
2472 }
Jeff Sharkey32ee8312012-09-30 13:21:31 -07002473 }
San Mehatb1043402010-02-05 08:26:50 -08002474 }
Jeff Sharkey48877892015-03-18 11:27:19 -07002475
2476 Slog.w(TAG, "No primary storage mounted!");
San Mehatb1043402010-02-05 08:26:50 -08002477 }
2478
Kenny Roota02b8b02010-08-05 16:14:17 -07002479 private boolean isUidOwnerOfPackageOrSystem(String packageName, int callerUid) {
2480 if (callerUid == android.os.Process.SYSTEM_UID) {
2481 return true;
2482 }
2483
Kenny Root02c87302010-07-01 08:10:18 -07002484 if (packageName == null) {
2485 return false;
2486 }
2487
Jeff Sharkey5790af02018-08-13 17:42:54 -06002488 final int packageUid = mPmInternal.getPackageUid(packageName,
Jeff Sharkeycd654482016-01-08 17:42:11 -07002489 PackageManager.MATCH_DEBUG_TRIAGED_MISSING, UserHandle.getUserId(callerUid));
Kenny Root02c87302010-07-01 08:10:18 -07002490
2491 if (DEBUG_OBB) {
2492 Slog.d(TAG, "packageName = " + packageName + ", packageUid = " +
2493 packageUid + ", callerUid = " + callerUid);
2494 }
2495
2496 return callerUid == packageUid;
2497 }
2498
Jeff Sharkey54402792017-09-15 16:05:19 -06002499 @Override
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002500 public String getMountedObbPath(String rawPath) {
2501 Preconditions.checkNotNull(rawPath, "rawPath cannot be null");
Kenny Rootaf9d6672010-10-08 09:21:39 -07002502
Kenny Root02c87302010-07-01 08:10:18 -07002503 warnOnNotMounted();
2504
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002505 final ObbState state;
Rubin Xucd7a0142015-04-17 23:45:27 +01002506 synchronized (mObbMounts) {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002507 state = mObbPathToStateMap.get(rawPath);
2508 }
2509 if (state == null) {
2510 Slog.w(TAG, "Failed to find OBB mounted at " + rawPath);
2511 return null;
2512 }
2513
Jeff Sharkey54402792017-09-15 16:05:19 -06002514 return findVolumeByIdOrThrow(state.volId).getPath().getAbsolutePath();
Kenny Root02c87302010-07-01 08:10:18 -07002515 }
2516
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002517 @Override
2518 public boolean isObbMounted(String rawPath) {
2519 Preconditions.checkNotNull(rawPath, "rawPath cannot be null");
Kenny Rootaf9d6672010-10-08 09:21:39 -07002520 synchronized (mObbMounts) {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002521 return mObbPathToStateMap.containsKey(rawPath);
Kenny Rootaf9d6672010-10-08 09:21:39 -07002522 }
Kenny Root02c87302010-07-01 08:10:18 -07002523 }
2524
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002525 @Override
Sudheer Shanka25469aa2018-08-27 15:50:23 -07002526 public void mountObb(String rawPath, String canonicalPath, String key,
2527 IObbActionListener token, int nonce, ObbInfo obbInfo) {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002528 Preconditions.checkNotNull(rawPath, "rawPath cannot be null");
2529 Preconditions.checkNotNull(canonicalPath, "canonicalPath cannot be null");
2530 Preconditions.checkNotNull(token, "token cannot be null");
Sudheer Shanka25469aa2018-08-27 15:50:23 -07002531 Preconditions.checkNotNull(obbInfo, "obbIfno cannot be null");
Kenny Rootaf9d6672010-10-08 09:21:39 -07002532
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002533 final int callingUid = Binder.getCallingUid();
Jeff Sharkey41cd6812017-09-11 10:32:17 -06002534 final ObbState obbState = new ObbState(rawPath, canonicalPath,
2535 callingUid, token, nonce, null);
Sudheer Shanka25469aa2018-08-27 15:50:23 -07002536 final ObbAction action = new MountObbAction(obbState, key, callingUid, obbInfo);
Kenny Roota02b8b02010-08-05 16:14:17 -07002537 mObbActionHandler.sendMessage(mObbActionHandler.obtainMessage(OBB_RUN_ACTION, action));
2538
2539 if (DEBUG_OBB)
2540 Slog.i(TAG, "Send to OBB handler: " + action.toString());
Kenny Root02c87302010-07-01 08:10:18 -07002541 }
2542
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002543 @Override
2544 public void unmountObb(String rawPath, boolean force, IObbActionListener token, int nonce) {
2545 Preconditions.checkNotNull(rawPath, "rawPath cannot be null");
2546
2547 final ObbState existingState;
Rubin Xucd7a0142015-04-17 23:45:27 +01002548 synchronized (mObbMounts) {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002549 existingState = mObbPathToStateMap.get(rawPath);
Kenny Rootf1121dc2010-09-29 07:30:53 -07002550 }
2551
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002552 if (existingState != null) {
2553 // TODO: separate state object from request data
2554 final int callingUid = Binder.getCallingUid();
Jeff Sharkey41cd6812017-09-11 10:32:17 -06002555 final ObbState newState = new ObbState(rawPath, existingState.canonicalPath,
2556 callingUid, token, nonce, existingState.volId);
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002557 final ObbAction action = new UnmountObbAction(newState, force);
2558 mObbActionHandler.sendMessage(mObbActionHandler.obtainMessage(OBB_RUN_ACTION, action));
Kenny Root02c87302010-07-01 08:10:18 -07002559
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002560 if (DEBUG_OBB)
2561 Slog.i(TAG, "Send to OBB handler: " + action.toString());
2562 } else {
2563 Slog.w(TAG, "Unknown OBB mount at " + rawPath);
2564 }
Kenny Roota02b8b02010-08-05 16:14:17 -07002565 }
2566
Ben Komalo444eca22011-09-01 15:17:44 -07002567 @Override
2568 public int getEncryptionState() {
2569 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
2570 "no permission to access the crypt keeper");
2571
Ben Komalo444eca22011-09-01 15:17:44 -07002572 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002573 return mVold.fdeComplete();
2574 } catch (Exception e) {
2575 Slog.wtf(TAG, e);
Sudheer Shankaf7341142016-10-18 17:15:18 -07002576 return StorageManager.ENCRYPTION_STATE_ERROR_UNKNOWN;
Ben Komalo444eca22011-09-01 15:17:44 -07002577 }
2578 }
2579
2580 @Override
Jason parks5af0b912010-11-29 09:05:25 -06002581 public int decryptStorage(String password) {
Jason parks8888c592011-01-20 22:46:41 -06002582 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
2583 "no permission to access the crypt keeper");
Jason parks5af0b912010-11-29 09:05:25 -06002584
Jeff Sharkey8058fe62017-09-13 11:50:33 -06002585 if (TextUtils.isEmpty(password)) {
2586 throw new IllegalArgumentException("password cannot be empty");
2587 }
2588
Jason parks5af0b912010-11-29 09:05:25 -06002589 if (DEBUG_EVENTS) {
2590 Slog.i(TAG, "decrypting storage...");
2591 }
2592
2593 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002594 mVold.fdeCheckPassword(password);
2595 mHandler.postDelayed(() -> {
2596 try {
2597 mVold.fdeRestart();
2598 } catch (Exception e) {
2599 Slog.wtf(TAG, e);
2600 }
2601 }, DateUtils.SECOND_IN_MILLIS);
2602 return 0;
Paul Crowleyfc0b5192018-07-02 13:58:10 -07002603 } catch (ServiceSpecificException e) {
2604 Slog.e(TAG, "fdeCheckPassword failed", e);
2605 return e.errorCode;
Jeff Sharkey54402792017-09-15 16:05:19 -06002606 } catch (Exception e) {
2607 Slog.wtf(TAG, e);
2608 return StorageManager.ENCRYPTION_STATE_ERROR_UNKNOWN;
Jason parks5af0b912010-11-29 09:05:25 -06002609 }
Jason parks5af0b912010-11-29 09:05:25 -06002610 }
2611
Jeff Sharkey54402792017-09-15 16:05:19 -06002612 @Override
Paul Lawrence46791e72014-04-03 09:10:26 -07002613 public int encryptStorage(int type, String password) {
Jason parks8888c592011-01-20 22:46:41 -06002614 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
2615 "no permission to access the crypt keeper");
Jason parks56aa5322011-01-07 09:01:15 -06002616
Jeff Sharkey8058fe62017-09-13 11:50:33 -06002617 if (type == StorageManager.CRYPT_TYPE_DEFAULT) {
2618 password = "";
2619 } else if (TextUtils.isEmpty(password)) {
2620 throw new IllegalArgumentException("password cannot be empty");
2621 }
2622
Jason parks56aa5322011-01-07 09:01:15 -06002623 if (DEBUG_EVENTS) {
Jason parks8888c592011-01-20 22:46:41 -06002624 Slog.i(TAG, "encrypting storage...");
Jason parks56aa5322011-01-07 09:01:15 -06002625 }
2626
2627 try {
Paul Lawrence89a0ae42017-12-22 10:11:10 -08002628 mVold.fdeEnable(type, password, 0);
Jeff Sharkey43e12112017-09-12 16:31:45 -06002629 } catch (Exception e) {
2630 Slog.wtf(TAG, e);
2631 return -1;
Jason parks56aa5322011-01-07 09:01:15 -06002632 }
2633
2634 return 0;
2635 }
2636
Paul Lawrence8e397362014-01-27 15:22:30 -08002637 /** Set the password for encrypting the master key.
2638 * @param type One of the CRYPTO_TYPE_XXX consts defined in StorageManager.
2639 * @param password The password to set.
2640 */
Jeff Sharkey54402792017-09-15 16:05:19 -06002641 @Override
Paul Lawrence8e397362014-01-27 15:22:30 -08002642 public int changeEncryptionPassword(int type, String password) {
Jason parksf7b3cd42011-01-27 09:28:25 -06002643 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
2644 "no permission to access the crypt keeper");
2645
Jeff Sharkeyae266462017-11-27 13:32:24 -07002646 if (StorageManager.isFileEncryptedNativeOnly()) {
2647 // Not supported on FBE devices
2648 return -1;
2649 }
2650
Jeff Sharkey8058fe62017-09-13 11:50:33 -06002651 if (type == StorageManager.CRYPT_TYPE_DEFAULT) {
2652 password = "";
2653 } else if (TextUtils.isEmpty(password)) {
2654 throw new IllegalArgumentException("password cannot be empty");
2655 }
2656
Jason parksf7b3cd42011-01-27 09:28:25 -06002657 if (DEBUG_EVENTS) {
2658 Slog.i(TAG, "changing encryption password...");
2659 }
2660
2661 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002662 mVold.fdeChangePassword(type, password);
2663 return 0;
2664 } catch (Exception e) {
2665 Slog.wtf(TAG, e);
2666 return -1;
Jason parksf7b3cd42011-01-27 09:28:25 -06002667 }
2668 }
2669
Christopher Tate32418be2011-10-10 13:51:12 -07002670 /**
2671 * Validate a user-supplied password string with cryptfs
2672 */
2673 @Override
2674 public int verifyEncryptionPassword(String password) throws RemoteException {
2675 // Only the system process is permitted to validate passwords
2676 if (Binder.getCallingUid() != android.os.Process.SYSTEM_UID) {
2677 throw new SecurityException("no permission to access the crypt keeper");
2678 }
2679
2680 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
2681 "no permission to access the crypt keeper");
2682
2683 if (TextUtils.isEmpty(password)) {
2684 throw new IllegalArgumentException("password cannot be empty");
2685 }
2686
Christopher Tate32418be2011-10-10 13:51:12 -07002687 if (DEBUG_EVENTS) {
2688 Slog.i(TAG, "validating encryption password...");
2689 }
2690
2691 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002692 mVold.fdeVerifyPassword(password);
2693 return 0;
2694 } catch (Exception e) {
2695 Slog.wtf(TAG, e);
2696 return -1;
Christopher Tate32418be2011-10-10 13:51:12 -07002697 }
2698 }
2699
Paul Lawrence8e397362014-01-27 15:22:30 -08002700 /**
2701 * Get the type of encryption used to encrypt the master key.
2702 * @return The type, one of the CRYPT_TYPE_XXX consts from StorageManager.
2703 */
2704 @Override
Svetoslav16e4a1a2014-09-29 18:16:20 -07002705 public int getPasswordType() {
Paul Lawrence76a40572017-03-15 11:08:04 -07002706 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
Paul Lawrence9de713d2016-05-02 22:45:33 +00002707 "no permission to access the crypt keeper");
2708
Paul Lawrence8e397362014-01-27 15:22:30 -08002709 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002710 return mVold.fdeGetPasswordType();
2711 } catch (Exception e) {
2712 Slog.wtf(TAG, e);
2713 return -1;
Paul Lawrence8e397362014-01-27 15:22:30 -08002714 }
2715 }
2716
Paul Lawrencee51dcf92014-03-18 10:56:00 -07002717 /**
2718 * Set a field in the crypto header.
2719 * @param field field to set
2720 * @param contents contents to set in field
2721 */
2722 @Override
2723 public void setField(String field, String contents) throws RemoteException {
Paul Lawrence76a40572017-03-15 11:08:04 -07002724 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
Paul Lawrence0bbd1082016-04-26 15:21:02 -07002725 "no permission to access the crypt keeper");
Paul Lawrencee51dcf92014-03-18 10:56:00 -07002726
yusukes14a8b1f2018-07-23 17:34:42 -07002727 if (!StorageManager.isBlockEncrypted()) {
2728 // Only supported on FDE devices
Jeff Sharkeyae266462017-11-27 13:32:24 -07002729 return;
2730 }
2731
Paul Lawrencee51dcf92014-03-18 10:56:00 -07002732 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002733 mVold.fdeSetField(field, contents);
2734 return;
2735 } catch (Exception e) {
2736 Slog.wtf(TAG, e);
2737 return;
Paul Lawrencee51dcf92014-03-18 10:56:00 -07002738 }
2739 }
2740
2741 /**
2742 * Gets a field from the crypto header.
2743 * @param field field to get
2744 * @return contents of field
2745 */
2746 @Override
2747 public String getField(String field) throws RemoteException {
Paul Lawrence76a40572017-03-15 11:08:04 -07002748 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
Paul Lawrence0bbd1082016-04-26 15:21:02 -07002749 "no permission to access the crypt keeper");
Paul Lawrencee51dcf92014-03-18 10:56:00 -07002750
yusukes14a8b1f2018-07-23 17:34:42 -07002751 if (!StorageManager.isBlockEncrypted()) {
2752 // Only supported on FDE devices
Jeff Sharkeyae266462017-11-27 13:32:24 -07002753 return null;
2754 }
2755
Paul Lawrencee51dcf92014-03-18 10:56:00 -07002756 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002757 return mVold.fdeGetField(field);
2758 } catch (Exception e) {
2759 Slog.wtf(TAG, e);
2760 return null;
Paul Lawrencee51dcf92014-03-18 10:56:00 -07002761 }
2762 }
2763
Paul Lawrence3806d9c2015-10-29 10:30:46 -07002764 /**
2765 * Is userdata convertible to file based encryption?
2766 * @return non zero for convertible
2767 */
2768 @Override
2769 public boolean isConvertibleToFBE() throws RemoteException {
Paul Lawrence76a40572017-03-15 11:08:04 -07002770 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
Paul Lawrence0bbd1082016-04-26 15:21:02 -07002771 "no permission to access the crypt keeper");
Paul Lawrence3806d9c2015-10-29 10:30:46 -07002772
Paul Lawrence3806d9c2015-10-29 10:30:46 -07002773 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002774 return mVold.isConvertibleToFbe();
2775 } catch (Exception e) {
2776 Slog.wtf(TAG, e);
2777 return false;
Paul Lawrence3806d9c2015-10-29 10:30:46 -07002778 }
2779 }
2780
Daniel Rosenberge129e5c2018-11-07 19:25:55 -08002781 /**
Martijn Coenenf04aca42019-03-11 10:35:34 +01002782 * Check whether the device supports filesystem checkpointing.
2783 *
2784 * @return true if the device supports filesystem checkpointing, false otherwise.
2785 */
2786 @Override
2787 public boolean supportsCheckpoint() throws RemoteException {
Martijn Coenenf04aca42019-03-11 10:35:34 +01002788 return mVold.supportsCheckpoint();
2789 }
2790
2791 /**
2792 * Signal that checkpointing partitions should start a checkpoint on the next boot.
2793 *
2794 * @param numTries Number of times to try booting in checkpoint mode, before we will boot
2795 * non-checkpoint mode and commit all changes immediately. Callers are
2796 * responsible for ensuring that boot is safe (eg, by rolling back updates).
2797 */
2798 @Override
2799 public void startCheckpoint(int numTries) throws RemoteException {
2800 // Only the system process is permitted to start checkpoints
2801 if (Binder.getCallingUid() != android.os.Process.SYSTEM_UID) {
2802 throw new SecurityException("no permission to start filesystem checkpoint");
2803 }
2804
2805 mVold.startCheckpoint(numTries);
2806 }
2807
2808 /**
Daniel Rosenberge129e5c2018-11-07 19:25:55 -08002809 * Signal that checkpointing partitions should commit changes
2810 */
2811 @Override
2812 public void commitChanges() throws RemoteException {
2813 // Only the system process is permitted to commit checkpoints
2814 if (Binder.getCallingUid() != android.os.Process.SYSTEM_UID) {
2815 throw new SecurityException("no permission to commit checkpoint changes");
2816 }
2817
2818 mVold.commitChanges();
2819 }
2820
Daniel Rosenberge3a924d2019-03-19 18:19:08 -07002821 /**
2822 * Check if we should be mounting with checkpointing or are checkpointing now
2823 */
2824 @Override
2825 public boolean needsCheckpoint() throws RemoteException {
Paul Lawrence15a54462019-04-30 11:14:25 -07002826 enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);
Daniel Rosenberge3a924d2019-03-19 18:19:08 -07002827 return mVold.needsCheckpoint();
2828 }
2829
Daniel Rosenberg600799b2019-03-20 17:42:50 -07002830 /**
2831 * Abort the current set of changes and either try again, or abort entirely
2832 */
2833 @Override
2834 public void abortChanges(String message, boolean retry) throws RemoteException {
2835 // Only the system process is permitted to abort checkpoints
2836 if (Binder.getCallingUid() != android.os.Process.SYSTEM_UID) {
2837 throw new SecurityException("no permission to commit checkpoint changes");
2838 }
2839
2840 mVold.abortChanges(message, retry);
2841 }
2842
Jeff Sharkeyb049e212012-09-07 23:16:01 -07002843 @Override
Paul Lawrence945490c2014-03-27 16:37:28 +00002844 public String getPassword() throws RemoteException {
Paul Lawrence76a40572017-03-15 11:08:04 -07002845 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
Rubin Xucd7a0142015-04-17 23:45:27 +01002846 "only keyguard can retrieve password");
Paul Lawrence0bbd1082016-04-26 15:21:02 -07002847
Paul Lawrence945490c2014-03-27 16:37:28 +00002848 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002849 return mVold.fdeGetPassword();
2850 } catch (Exception e) {
2851 Slog.wtf(TAG, e);
Paul Lawrence24063b52015-01-06 13:11:23 -08002852 return null;
Paul Lawrence945490c2014-03-27 16:37:28 +00002853 }
2854 }
2855
2856 @Override
2857 public void clearPassword() throws RemoteException {
Paul Lawrence76a40572017-03-15 11:08:04 -07002858 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
Paul Lawrence0bbd1082016-04-26 15:21:02 -07002859 "only keyguard can clear password");
2860
Paul Lawrence945490c2014-03-27 16:37:28 +00002861 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002862 mVold.fdeClearPassword();
2863 return;
2864 } catch (Exception e) {
2865 Slog.wtf(TAG, e);
2866 return;
Paul Lawrence945490c2014-03-27 16:37:28 +00002867 }
2868 }
2869
2870 @Override
Lenka Trochtovac4dd0212015-11-18 12:22:06 +01002871 public void createUserKey(int userId, int serialNumber, boolean ephemeral) {
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002872 enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
Paul Crowleybcf48ed2015-04-22 13:36:59 +01002873
Paul Crowleybcf48ed2015-04-22 13:36:59 +01002874 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002875 mVold.createUserKey(userId, serialNumber, ephemeral);
Jeff Sharkey43e12112017-09-12 16:31:45 -06002876 } catch (Exception e) {
2877 Slog.wtf(TAG, e);
Paul Crowleybcf48ed2015-04-22 13:36:59 +01002878 }
2879 }
2880
Paul Crowley7ec733f2015-05-19 12:42:00 +01002881 @Override
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002882 public void destroyUserKey(int userId) {
2883 enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
Paul Crowley7ec733f2015-05-19 12:42:00 +01002884
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002885 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002886 mVold.destroyUserKey(userId);
Jeff Sharkey43e12112017-09-12 16:31:45 -06002887 } catch (Exception e) {
2888 Slog.wtf(TAG, e);
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002889 }
2890 }
2891
Jeff Sharkey43e12112017-09-12 16:31:45 -06002892 private String encodeBytes(byte[] bytes) {
Paul Crowleyfaeb3eb2016-02-08 15:58:29 +00002893 if (ArrayUtils.isEmpty(bytes)) {
Jeff Sharkey43e12112017-09-12 16:31:45 -06002894 return "!";
Paul Crowleyfaeb3eb2016-02-08 15:58:29 +00002895 } else {
Jeff Sharkey43e12112017-09-12 16:31:45 -06002896 return HexDump.toHexString(bytes);
Paul Crowleyfaeb3eb2016-02-08 15:58:29 +00002897 }
2898 }
2899
Paul Crowleycc701552016-05-17 14:18:49 -07002900 /*
2901 * Add this token/secret pair to the set of ways we can recover a disk encryption key.
2902 * Changing the token/secret for a disk encryption key is done in two phases: first, adding
2903 * a new token/secret pair with this call, then delting all other pairs with
2904 * fixateNewestUserKeyAuth. This allows other places where a credential is used, such as
2905 * Gatekeeper, to be updated between the two calls.
2906 */
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002907 @Override
Paul Crowleycc701552016-05-17 14:18:49 -07002908 public void addUserKeyAuth(int userId, int serialNumber, byte[] token, byte[] secret) {
Paul Crowleyfaeb3eb2016-02-08 15:58:29 +00002909 enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
Paul Crowleyfaeb3eb2016-02-08 15:58:29 +00002910
2911 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002912 mVold.addUserKeyAuth(userId, serialNumber, encodeBytes(token), encodeBytes(secret));
Jeff Sharkey43e12112017-09-12 16:31:45 -06002913 } catch (Exception e) {
2914 Slog.wtf(TAG, e);
Paul Crowleycc701552016-05-17 14:18:49 -07002915 }
2916 }
2917
2918 /*
2919 * Delete all disk encryption token/secret pairs except the most recently added one
2920 */
2921 @Override
2922 public void fixateNewestUserKeyAuth(int userId) {
2923 enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
Paul Crowleycc701552016-05-17 14:18:49 -07002924
2925 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002926 mVold.fixateNewestUserKeyAuth(userId);
Jeff Sharkey43e12112017-09-12 16:31:45 -06002927 } catch (Exception e) {
2928 Slog.wtf(TAG, e);
Paul Crowleyfaeb3eb2016-02-08 15:58:29 +00002929 }
2930 }
2931
2932 @Override
2933 public void unlockUserKey(int userId, int serialNumber, byte[] token, byte[] secret) {
Sudheer Shanka03b20ec2019-02-21 15:11:00 -08002934 Slog.d(TAG, "unlockUserKey: " + userId);
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002935 enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002936
Jeff Sharkeyce18c812016-04-27 16:00:41 -06002937 if (StorageManager.isFileEncryptedNativeOrEmulated()) {
Jeff Sharkeyce18c812016-04-27 16:00:41 -06002938 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002939 mVold.unlockUserKey(userId, serialNumber, encodeBytes(token),
2940 encodeBytes(secret));
Jeff Sharkey43e12112017-09-12 16:31:45 -06002941 } catch (Exception e) {
2942 Slog.wtf(TAG, e);
2943 return;
Jeff Sharkeyce18c812016-04-27 16:00:41 -06002944 }
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002945 }
2946
2947 synchronized (mLock) {
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07002948 mLocalUnlockedUsers = ArrayUtils.appendInt(mLocalUnlockedUsers, userId);
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002949 }
2950 }
2951
2952 @Override
2953 public void lockUserKey(int userId) {
2954 enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002955
2956 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002957 mVold.lockUserKey(userId);
Jeff Sharkey43e12112017-09-12 16:31:45 -06002958 } catch (Exception e) {
2959 Slog.wtf(TAG, e);
2960 return;
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002961 }
2962
2963 synchronized (mLock) {
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07002964 mLocalUnlockedUsers = ArrayUtils.removeInt(mLocalUnlockedUsers, userId);
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002965 }
2966 }
2967
2968 @Override
2969 public boolean isUserKeyUnlocked(int userId) {
Jeff Sharkeyce18c812016-04-27 16:00:41 -06002970 synchronized (mLock) {
2971 return ArrayUtils.contains(mLocalUnlockedUsers, userId);
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002972 }
2973 }
2974
Narayan Kamath157dd1d2019-06-12 13:06:30 +01002975 private boolean isSystemUnlocked(int userId) {
2976 synchronized (mLock) {
2977 return ArrayUtils.contains(mSystemUnlockedUsers, userId);
2978 }
2979 }
2980
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002981 @Override
Jeff Sharkey47f71082016-02-01 17:03:54 -07002982 public void prepareUserStorage(String volumeUuid, int userId, int serialNumber, int flags) {
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002983 enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002984
2985 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002986 mVold.prepareUserStorage(volumeUuid, userId, serialNumber, flags);
Jeff Sharkey43e12112017-09-12 16:31:45 -06002987 } catch (Exception e) {
2988 Slog.wtf(TAG, e);
Paul Crowley7ec733f2015-05-19 12:42:00 +01002989 }
2990 }
2991
Paul Crowleybcf48ed2015-04-22 13:36:59 +01002992 @Override
Jeff Sharkeyfcf1e552016-04-14 20:44:58 -06002993 public void destroyUserStorage(String volumeUuid, int userId, int flags) {
2994 enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
Jeff Sharkeyfcf1e552016-04-14 20:44:58 -06002995
2996 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002997 mVold.destroyUserStorage(volumeUuid, userId, flags);
Jeff Sharkey43e12112017-09-12 16:31:45 -06002998 } catch (Exception e) {
2999 Slog.wtf(TAG, e);
Jeff Sharkeyfcf1e552016-04-14 20:44:58 -06003000 }
3001 }
3002
Anton Hanssonbe9c9902019-05-28 13:45:26 +01003003 /** Not thread safe */
Daichi Hironoe56740d2017-02-02 13:56:45 +09003004 class AppFuseMountScope extends AppFuseBridge.MountScope {
Anton Hanssonbe9c9902019-05-28 13:45:26 +01003005 private boolean mMounted = false;
Daichi Hirono812c95d2017-02-08 16:20:20 +09003006
Ryo Hashimoto38bcbf02018-05-16 18:20:37 +09003007 public AppFuseMountScope(int uid, int mountId) {
3008 super(uid, mountId);
Daichi Hirono812c95d2017-02-08 16:20:20 +09003009 }
3010
3011 @Override
3012 public ParcelFileDescriptor open() throws NativeDaemonConnectorException {
Jeff Sharkey54402792017-09-15 16:05:19 -06003013 try {
Anton Hanssonbe9c9902019-05-28 13:45:26 +01003014 final FileDescriptor fd = mVold.mountAppFuse(uid, mountId);
3015 mMounted = true;
3016 return new ParcelFileDescriptor(fd);
Jeff Sharkey54402792017-09-15 16:05:19 -06003017 } catch (Exception e) {
3018 throw new NativeDaemonConnectorException("Failed to mount", e);
Daichi Hirono812c95d2017-02-08 16:20:20 +09003019 }
Daichi Hirono9fb00182016-11-08 14:12:17 +09003020 }
3021
3022 @Override
Ryo Hashimoto38bcbf02018-05-16 18:20:37 +09003023 public ParcelFileDescriptor openFile(int mountId, int fileId, int flags)
3024 throws NativeDaemonConnectorException {
3025 try {
3026 return new ParcelFileDescriptor(
3027 mVold.openAppFuseFile(uid, mountId, fileId, flags));
3028 } catch (Exception e) {
3029 throw new NativeDaemonConnectorException("Failed to open", e);
3030 }
3031 }
3032
3033 @Override
Daichi Hironoe56740d2017-02-02 13:56:45 +09003034 public void close() throws Exception {
Anton Hanssonbe9c9902019-05-28 13:45:26 +01003035 if (mMounted) {
Ryo Hashimoto38bcbf02018-05-16 18:20:37 +09003036 mVold.unmountAppFuse(uid, mountId);
Anton Hanssonbe9c9902019-05-28 13:45:26 +01003037 mMounted = false;
Daichi Hirono812c95d2017-02-08 16:20:20 +09003038 }
Daichi Hirono9fb00182016-11-08 14:12:17 +09003039 }
3040 }
3041
3042 @Override
Daichi Hirono812c95d2017-02-08 16:20:20 +09003043 public @Nullable AppFuseMount mountProxyFileDescriptorBridge() {
Daichi Hironoe56740d2017-02-02 13:56:45 +09003044 Slog.v(TAG, "mountProxyFileDescriptorBridge");
Daichi Hirono9fb00182016-11-08 14:12:17 +09003045 final int uid = Binder.getCallingUid();
Daichi Hirono9fb00182016-11-08 14:12:17 +09003046
Daichi Hironoe56740d2017-02-02 13:56:45 +09003047 while (true) {
3048 synchronized (mAppFuseLock) {
3049 boolean newlyCreated = false;
3050 if (mAppFuseBridge == null) {
3051 mAppFuseBridge = new AppFuseBridge();
3052 new Thread(mAppFuseBridge, AppFuseBridge.TAG).start();
3053 newlyCreated = true;
Daichi Hirono9fb00182016-11-08 14:12:17 +09003054 }
Daichi Hironoe56740d2017-02-02 13:56:45 +09003055 try {
3056 final int name = mNextAppFuseName++;
3057 try {
3058 return new AppFuseMount(
Ryo Hashimoto38bcbf02018-05-16 18:20:37 +09003059 name, mAppFuseBridge.addBridge(new AppFuseMountScope(uid, name)));
Daichi Hirono812c95d2017-02-08 16:20:20 +09003060 } catch (FuseUnavailableMountException e) {
Daichi Hironoe56740d2017-02-02 13:56:45 +09003061 if (newlyCreated) {
3062 // If newly created bridge fails, it's a real error.
Daichi Hirono812c95d2017-02-08 16:20:20 +09003063 Slog.e(TAG, "", e);
3064 return null;
Daichi Hironoe56740d2017-02-02 13:56:45 +09003065 }
3066 // It seems the thread of mAppFuseBridge has already been terminated.
3067 mAppFuseBridge = null;
3068 }
3069 } catch (NativeDaemonConnectorException e) {
3070 throw e.rethrowAsParcelableException();
3071 }
Daichi Hirono9fb00182016-11-08 14:12:17 +09003072 }
Daichi Hirono9fb00182016-11-08 14:12:17 +09003073 }
3074 }
3075
3076 @Override
Daichi Hirono812c95d2017-02-08 16:20:20 +09003077 public @Nullable ParcelFileDescriptor openProxyFileDescriptor(
3078 int mountId, int fileId, int mode) {
3079 Slog.v(TAG, "mountProxyFileDescriptor");
Jeff Sharkey39466322018-12-05 19:19:52 -07003080
3081 // We only support a narrow set of incoming mode flags
Jeff Sharkey3b1c2542018-12-13 15:01:38 -07003082 mode &= MODE_READ_WRITE;
Jeff Sharkey39466322018-12-05 19:19:52 -07003083
Daichi Hirono9fb00182016-11-08 14:12:17 +09003084 try {
3085 synchronized (mAppFuseLock) {
Daichi Hironoe56740d2017-02-02 13:56:45 +09003086 if (mAppFuseBridge == null) {
Daichi Hirono812c95d2017-02-08 16:20:20 +09003087 Slog.e(TAG, "FuseBridge has not been created");
3088 return null;
Daichi Hirono9fb00182016-11-08 14:12:17 +09003089 }
Ryo Hashimoto38bcbf02018-05-16 18:20:37 +09003090 return mAppFuseBridge.openFile(mountId, fileId, mode);
Daichi Hirono9fb00182016-11-08 14:12:17 +09003091 }
Daichi Hirono812c95d2017-02-08 16:20:20 +09003092 } catch (FuseUnavailableMountException | InterruptedException error) {
3093 Slog.v(TAG, "The mount point has already been invalid", error);
3094 return null;
Daichi Hirono9fb00182016-11-08 14:12:17 +09003095 }
3096 }
3097
Daichi Hirono9e8d9e22015-11-13 14:37:00 +09003098 @Override
Jeff Sharkeyae266462017-11-27 13:32:24 -07003099 public void mkdirs(String callingPkg, String appPath) {
Zim17be6f92019-09-25 14:37:55 +01003100 if (mIsFuseEnabled) {
3101 // TODO(b/144332951): Calling into Vold is risky because the FUSE daemon can go down
3102 // anytime and Vold will hang forever. We should either remove this call
3103 // or at least call into the FUSE daemon to mkdir instead
3104 Slog.w(TAG, "Not making dir for package " + callingPkg + " with path " + appPath);
3105 return;
3106 }
3107
Sudheer Shankaa63bfb32019-02-28 11:15:58 -08003108 final int callingUid = Binder.getCallingUid();
3109 final int userId = UserHandle.getUserId(callingUid);
Jeff Sharkey2d8b4e82013-09-17 17:30:33 -07003110 final UserEnvironment userEnv = new UserEnvironment(userId);
Farid Zare Seisanac094512018-04-02 15:06:13 -07003111 final String propertyName = "sys.user." + userId + ".ce_available";
Jeff Sharkey2d8b4e82013-09-17 17:30:33 -07003112
Jeff Sharkey196c7552018-03-26 15:56:50 -06003113 // Ignore requests to create directories while storage is locked
Farid Zare Seisanac094512018-04-02 15:06:13 -07003114 if (!isUserKeyUnlocked(userId)) {
3115 throw new IllegalStateException("Failed to prepare " + appPath);
3116 }
3117
3118 // Ignore requests to create directories if CE storage is not available
Farid Zare Seisan7f6b8122018-03-30 11:19:10 -07003119 if ((userId == UserHandle.USER_SYSTEM)
3120 && !SystemProperties.getBoolean(propertyName, false)) {
Farid Zare Seisanac094512018-04-02 15:06:13 -07003121 throw new IllegalStateException("Failed to prepare " + appPath);
3122 }
Jeff Sharkey196c7552018-03-26 15:56:50 -06003123
Jeff Sharkey2d8b4e82013-09-17 17:30:33 -07003124 // Validate that reported package name belongs to caller
3125 final AppOpsManager appOps = (AppOpsManager) mContext.getSystemService(
3126 Context.APP_OPS_SERVICE);
Sudheer Shankaa63bfb32019-02-28 11:15:58 -08003127 appOps.checkPackage(callingUid, callingPkg);
Jeff Sharkey2d8b4e82013-09-17 17:30:33 -07003128
Jeff Sharkey48877892015-03-18 11:27:19 -07003129 File appFile = null;
Jeff Sharkey2d8b4e82013-09-17 17:30:33 -07003130 try {
Jeff Sharkey48877892015-03-18 11:27:19 -07003131 appFile = new File(appPath).getCanonicalFile();
Jeff Sharkey2d8b4e82013-09-17 17:30:33 -07003132 } catch (IOException e) {
Jeff Sharkeyae266462017-11-27 13:32:24 -07003133 throw new IllegalStateException("Failed to resolve " + appPath + ": " + e);
Jeff Sharkey2d8b4e82013-09-17 17:30:33 -07003134 }
3135
3136 // Try translating the app path into a vold path, but require that it
3137 // belong to the calling package.
Jeff Sharkey48877892015-03-18 11:27:19 -07003138 if (FileUtils.contains(userEnv.buildExternalStorageAppDataDirs(callingPkg), appFile) ||
3139 FileUtils.contains(userEnv.buildExternalStorageAppObbDirs(callingPkg), appFile) ||
3140 FileUtils.contains(userEnv.buildExternalStorageAppMediaDirs(callingPkg), appFile)) {
3141 appPath = appFile.getAbsolutePath();
3142 if (!appPath.endsWith("/")) {
3143 appPath = appPath + "/";
3144 }
3145
Jeff Sharkey2d8b4e82013-09-17 17:30:33 -07003146 try {
Sudheer Shanka64501e52019-04-29 10:46:26 -07003147 mVold.mkdirs(appPath);
Jeff Sharkey27a108c2017-11-30 17:11:40 -07003148 return;
Jeff Sharkeyace874b2017-09-07 15:27:33 -06003149 } catch (Exception e) {
Sudheer Shanka64501e52019-04-29 10:46:26 -07003150 throw new IllegalStateException("Failed to prepare " + appPath + ": " + e);
Jeff Sharkey2d8b4e82013-09-17 17:30:33 -07003151 }
3152 }
3153
Jeff Sharkey48877892015-03-18 11:27:19 -07003154 throw new SecurityException("Invalid mkdirs path: " + appFile);
Jeff Sharkey2d8b4e82013-09-17 17:30:33 -07003155 }
3156
3157 @Override
Jeff Sharkey46349872015-07-28 10:49:47 -07003158 public StorageVolume[] getVolumeList(int uid, String packageName, int flags) {
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07003159 final int userId = UserHandle.getUserId(uid);
Jeff Sharkeyc02bfae2016-03-27 15:06:53 -06003160
Jeff Sharkey46349872015-07-28 10:49:47 -07003161 final boolean forWrite = (flags & StorageManager.FLAG_FOR_WRITE) != 0;
Jeff Sharkeyc02bfae2016-03-27 15:06:53 -06003162 final boolean realState = (flags & StorageManager.FLAG_REAL_STATE) != 0;
3163 final boolean includeInvisible = (flags & StorageManager.FLAG_INCLUDE_INVISIBLE) != 0;
Jeff Sharkey46349872015-07-28 10:49:47 -07003164
Narayan Kamath157dd1d2019-06-12 13:06:30 +01003165 // Report all volumes as unmounted until we've recorded that user 0 has unlocked. There
3166 // are no guarantees that callers will see a consistent view of the volume before that
3167 // point
3168 final boolean systemUserUnlocked = isSystemUnlocked(UserHandle.USER_SYSTEM);
3169
Jeff Sharkeyc02bfae2016-03-27 15:06:53 -06003170 final boolean userKeyUnlocked;
3171 final boolean storagePermission;
3172 final long token = Binder.clearCallingIdentity();
Svetoslav38c3dbb2015-07-14 11:27:06 -07003173 try {
Jeff Sharkeyc02bfae2016-03-27 15:06:53 -06003174 userKeyUnlocked = isUserKeyUnlocked(userId);
Sudheer Shanka2250d562016-11-07 15:41:02 -08003175 storagePermission = mStorageManagerInternal.hasExternalStorage(uid, packageName);
Svetoslav38c3dbb2015-07-14 11:27:06 -07003176 } finally {
Jeff Sharkeyc02bfae2016-03-27 15:06:53 -06003177 Binder.restoreCallingIdentity(token);
Svetoslav38c3dbb2015-07-14 11:27:06 -07003178 }
Svet Ganov6ee871e2015-07-10 14:29:33 -07003179
Jeff Sharkeyc02bfae2016-03-27 15:06:53 -06003180 boolean foundPrimary = false;
3181
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07003182 final ArrayList<StorageVolume> res = new ArrayList<>();
Jeff Sharkey48877892015-03-18 11:27:19 -07003183 synchronized (mLock) {
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07003184 for (int i = 0; i < mVolumes.size(); i++) {
3185 final VolumeInfo vol = mVolumes.valueAt(i);
Jeff Sharkeyc02bfae2016-03-27 15:06:53 -06003186 switch (vol.getType()) {
3187 case VolumeInfo.TYPE_PUBLIC:
Risan05c41e62018-10-29 08:57:43 +09003188 case VolumeInfo.TYPE_STUB:
Jeff Sharkeyc02bfae2016-03-27 15:06:53 -06003189 break;
Zim17be6f92019-09-25 14:37:55 +01003190 case VolumeInfo.TYPE_EMULATED:
3191 if (vol.getMountUserId() == userId) {
3192 break;
3193 }
3194 // Skip if emulated volume not for userId
Jeff Sharkeyc02bfae2016-03-27 15:06:53 -06003195 default:
3196 continue;
3197 }
3198
3199 boolean match = false;
3200 if (forWrite) {
3201 match = vol.isVisibleForWrite(userId);
3202 } else {
Felipe Leme123a0e72016-06-10 11:09:11 -07003203 match = vol.isVisibleForRead(userId)
3204 || (includeInvisible && vol.getPath() != null);
Jeff Sharkeyc02bfae2016-03-27 15:06:53 -06003205 }
3206 if (!match) continue;
3207
3208 boolean reportUnmounted = false;
Narayan Kamath157dd1d2019-06-12 13:06:30 +01003209 if (!systemUserUnlocked) {
3210 reportUnmounted = true;
3211 } else if ((vol.getType() == VolumeInfo.TYPE_EMULATED) && !userKeyUnlocked) {
Jeff Sharkeyc02bfae2016-03-27 15:06:53 -06003212 reportUnmounted = true;
3213 } else if (!storagePermission && !realState) {
3214 reportUnmounted = true;
3215 }
3216
3217 final StorageVolume userVol = vol.buildStorageVolume(mContext, userId,
3218 reportUnmounted);
3219 if (vol.isPrimary()) {
3220 res.add(0, userVol);
3221 foundPrimary = true;
3222 } else {
3223 res.add(userVol);
Jeff Sharkeyb049e212012-09-07 23:16:01 -07003224 }
Mike Lockwood8fa5f802011-03-24 08:12:30 -07003225 }
Mike Lockwood8fa5f802011-03-24 08:12:30 -07003226 }
Jeff Sharkey48877892015-03-18 11:27:19 -07003227
3228 if (!foundPrimary) {
Jeff Sharkey11697f52018-12-13 10:14:42 -07003229 Slog.w(TAG, "No primary storage defined yet; hacking together a stub");
Jeff Sharkey48877892015-03-18 11:27:19 -07003230
3231 final boolean primaryPhysical = SystemProperties.getBoolean(
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07003232 StorageManager.PROP_PRIMARY_PHYSICAL, false);
Jeff Sharkey48877892015-03-18 11:27:19 -07003233
3234 final String id = "stub_primary";
3235 final File path = Environment.getLegacyExternalStorageDirectory();
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07003236 final String description = mContext.getString(android.R.string.unknownName);
Jeff Sharkey48877892015-03-18 11:27:19 -07003237 final boolean primary = true;
3238 final boolean removable = primaryPhysical;
3239 final boolean emulated = !primaryPhysical;
Jeff Sharkey48877892015-03-18 11:27:19 -07003240 final boolean allowMassStorage = false;
3241 final long maxFileSize = 0L;
3242 final UserHandle owner = new UserHandle(userId);
3243 final String uuid = null;
Jeff Sharkey48877892015-03-18 11:27:19 -07003244 final String state = Environment.MEDIA_REMOVED;
3245
Jerry Zhang71938e12018-05-10 18:28:29 -07003246 res.add(0, new StorageVolume(id, path, path,
Jerry Zhangf9c5c252017-08-16 18:07:51 -07003247 description, primary, removable, emulated,
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07003248 allowMassStorage, maxFileSize, owner, uuid, state));
Jeff Sharkey48877892015-03-18 11:27:19 -07003249 }
3250
3251 return res.toArray(new StorageVolume[res.size()]);
Mike Lockwood8fa5f802011-03-24 08:12:30 -07003252 }
3253
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07003254 @Override
3255 public DiskInfo[] getDisks() {
3256 synchronized (mLock) {
3257 final DiskInfo[] res = new DiskInfo[mDisks.size()];
3258 for (int i = 0; i < mDisks.size(); i++) {
3259 res[i] = mDisks.valueAt(i);
3260 }
3261 return res;
3262 }
3263 }
3264
3265 @Override
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07003266 public VolumeInfo[] getVolumes(int flags) {
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07003267 synchronized (mLock) {
3268 final VolumeInfo[] res = new VolumeInfo[mVolumes.size()];
3269 for (int i = 0; i < mVolumes.size(); i++) {
3270 res[i] = mVolumes.valueAt(i);
3271 }
3272 return res;
3273 }
3274 }
3275
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07003276 @Override
3277 public VolumeRecord[] getVolumeRecords(int flags) {
3278 synchronized (mLock) {
3279 final VolumeRecord[] res = new VolumeRecord[mRecords.size()];
3280 for (int i = 0; i < mRecords.size(); i++) {
3281 res[i] = mRecords.valueAt(i);
3282 }
3283 return res;
3284 }
3285 }
3286
Jeff Sharkey9bed0702017-01-23 20:37:05 -07003287 @Override
3288 public long getCacheQuotaBytes(String volumeUuid, int uid) {
3289 if (uid != Binder.getCallingUid()) {
3290 mContext.enforceCallingPermission(android.Manifest.permission.STORAGE_INTERNAL, TAG);
3291 }
Daniel Nishi80fdb012017-03-09 14:30:07 -08003292 final long token = Binder.clearCallingIdentity();
3293 final StorageStatsManager stats = mContext.getSystemService(StorageStatsManager.class);
3294 try {
3295 return stats.getCacheQuotaBytes(volumeUuid, uid);
3296 } finally {
3297 Binder.restoreCallingIdentity(token);
3298 }
Jeff Sharkey9bed0702017-01-23 20:37:05 -07003299 }
3300
3301 @Override
3302 public long getCacheSizeBytes(String volumeUuid, int uid) {
3303 if (uid != Binder.getCallingUid()) {
3304 mContext.enforceCallingPermission(android.Manifest.permission.STORAGE_INTERNAL, TAG);
3305 }
3306 final long token = Binder.clearCallingIdentity();
3307 try {
3308 return mContext.getSystemService(StorageStatsManager.class)
3309 .queryStatsForUid(volumeUuid, uid).getCacheBytes();
Jeff Sharkey789a8fc2017-04-16 13:18:35 -06003310 } catch (IOException e) {
3311 throw new ParcelableException(e);
Jeff Sharkey9bed0702017-01-23 20:37:05 -07003312 } finally {
3313 Binder.restoreCallingIdentity(token);
3314 }
3315 }
3316
Jeff Sharkey35e46d22017-06-09 10:01:20 -06003317 private int adjustAllocateFlags(int flags, int callingUid, String callingPackage) {
3318 // Require permission to allocate aggressively
3319 if ((flags & StorageManager.FLAG_ALLOCATE_AGGRESSIVE) != 0) {
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07003320 mContext.enforceCallingOrSelfPermission(
3321 android.Manifest.permission.ALLOCATE_AGGRESSIVE, TAG);
3322 }
3323
Jeff Sharkey35e46d22017-06-09 10:01:20 -06003324 // Apps normally can't directly defy reserved space
3325 flags &= ~StorageManager.FLAG_ALLOCATE_DEFY_ALL_RESERVED;
3326 flags &= ~StorageManager.FLAG_ALLOCATE_DEFY_HALF_RESERVED;
3327
3328 // However, if app is actively using the camera, then we're willing to
3329 // clear up to half of the reserved cache space, since the user might be
3330 // trying to capture an important memory.
3331 final AppOpsManager appOps = mContext.getSystemService(AppOpsManager.class);
3332 final long token = Binder.clearCallingIdentity();
3333 try {
3334 if (appOps.isOperationActive(AppOpsManager.OP_CAMERA, callingUid, callingPackage)) {
3335 Slog.d(TAG, "UID " + callingUid + " is actively using camera;"
3336 + " letting them defy reserved cached data");
3337 flags |= StorageManager.FLAG_ALLOCATE_DEFY_HALF_RESERVED;
3338 }
3339 } finally {
3340 Binder.restoreCallingIdentity(token);
3341 }
3342
3343 return flags;
3344 }
3345
3346 @Override
3347 public long getAllocatableBytes(String volumeUuid, int flags, String callingPackage) {
3348 flags = adjustAllocateFlags(flags, Binder.getCallingUid(), callingPackage);
3349
3350 final StorageManager storage = mContext.getSystemService(StorageManager.class);
3351 final StorageStatsManager stats = mContext.getSystemService(StorageStatsManager.class);
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07003352 final long token = Binder.clearCallingIdentity();
3353 try {
3354 // In general, apps can allocate as much space as they want, except
3355 // we never let them eat into either the minimum cache space or into
Jeff Sharkeyddff8072017-05-26 13:10:46 -06003356 // the low disk warning space. To avoid user confusion, this logic
3357 // should be kept in sync with getFreeBytes().
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07003358 final File path = storage.findPathForUuid(volumeUuid);
Jeff Sharkeyddff8072017-05-26 13:10:46 -06003359
Noah Zimmtb2558072019-07-25 16:15:06 -07003360 long usable = 0;
3361 long lowReserved = 0;
3362 long fullReserved = 0;
3363 long cacheClearable = 0;
Jeff Sharkeyddff8072017-05-26 13:10:46 -06003364
Noah Zimmtb2558072019-07-25 16:15:06 -07003365 if ((flags & StorageManager.FLAG_ALLOCATE_CACHE_ONLY) == 0) {
3366 usable = path.getUsableSpace();
3367 lowReserved = storage.getStorageLowBytes(path);
3368 fullReserved = storage.getStorageFullBytes(path);
3369 }
3370
3371 if ((flags & StorageManager.FLAG_ALLOCATE_NON_CACHE_ONLY) == 0
3372 && stats.isQuotaSupported(volumeUuid)) {
Jeff Sharkeyddff8072017-05-26 13:10:46 -06003373 final long cacheTotal = stats.getCacheBytes(volumeUuid);
Jeff Sharkey35e46d22017-06-09 10:01:20 -06003374 final long cacheReserved = storage.getStorageCacheBytes(path, flags);
Noah Zimmtb2558072019-07-25 16:15:06 -07003375 cacheClearable = Math.max(0, cacheTotal - cacheReserved);
3376 }
Jeff Sharkeyddff8072017-05-26 13:10:46 -06003377
Noah Zimmtb2558072019-07-25 16:15:06 -07003378 if ((flags & StorageManager.FLAG_ALLOCATE_AGGRESSIVE) != 0) {
3379 return Math.max(0, (usable + cacheClearable) - fullReserved);
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07003380 } else {
Noah Zimmtb2558072019-07-25 16:15:06 -07003381 return Math.max(0, (usable + cacheClearable) - lowReserved);
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07003382 }
Jeff Sharkey789a8fc2017-04-16 13:18:35 -06003383 } catch (IOException e) {
3384 throw new ParcelableException(e);
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07003385 } finally {
3386 Binder.restoreCallingIdentity(token);
3387 }
Jeff Sharkey500ce9e2017-02-12 02:39:24 -07003388 }
3389
3390 @Override
Jeff Sharkey35e46d22017-06-09 10:01:20 -06003391 public void allocateBytes(String volumeUuid, long bytes, int flags, String callingPackage) {
3392 flags = adjustAllocateFlags(flags, Binder.getCallingUid(), callingPackage);
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07003393
Noah Zimmtb2558072019-07-25 16:15:06 -07003394 final long allocatableBytes = getAllocatableBytes(volumeUuid,
3395 flags | StorageManager.FLAG_ALLOCATE_NON_CACHE_ONLY, callingPackage);
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07003396 if (bytes > allocatableBytes) {
Noah Zimmtb2558072019-07-25 16:15:06 -07003397 // If we don't have room without taking cache into account, check to see if we'd have
3398 // room if we included freeable cache space.
3399 final long cacheClearable = getAllocatableBytes(volumeUuid,
3400 flags | StorageManager.FLAG_ALLOCATE_CACHE_ONLY, callingPackage);
3401 if (bytes > allocatableBytes + cacheClearable) {
3402 throw new ParcelableException(new IOException("Failed to allocate " + bytes
3403 + " because only " + (allocatableBytes + cacheClearable) + " allocatable"));
3404 }
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07003405 }
3406
Jeff Sharkey35e46d22017-06-09 10:01:20 -06003407 final StorageManager storage = mContext.getSystemService(StorageManager.class);
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07003408 final long token = Binder.clearCallingIdentity();
3409 try {
Jeff Sharkey789a8fc2017-04-16 13:18:35 -06003410 // Free up enough disk space to satisfy both the requested allocation
3411 // and our low disk warning space.
3412 final File path = storage.findPathForUuid(volumeUuid);
Jeff Sharkeyddff8072017-05-26 13:10:46 -06003413 if ((flags & StorageManager.FLAG_ALLOCATE_AGGRESSIVE) != 0) {
3414 bytes += storage.getStorageFullBytes(path);
3415 } else {
3416 bytes += storage.getStorageLowBytes(path);
3417 }
Jeff Sharkey789a8fc2017-04-16 13:18:35 -06003418
Jeff Sharkey5790af02018-08-13 17:42:54 -06003419 mPmInternal.freeStorage(volumeUuid, bytes, flags);
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07003420 } catch (IOException e) {
3421 throw new ParcelableException(e);
3422 } finally {
3423 Binder.restoreCallingIdentity(token);
Jeff Sharkey500ce9e2017-02-12 02:39:24 -07003424 }
3425 }
3426
Sudheer Shankaff971bc2018-12-13 17:39:59 -08003427 private IAppOpsCallback.Stub mAppOpsCallback = new IAppOpsCallback.Stub() {
3428 @Override
3429 public void opChanged(int op, int uid, String packageName) throws RemoteException {
3430 if (!ENABLE_ISOLATED_STORAGE) return;
3431
Zim64726cb2019-11-27 13:06:34 +00003432 int mountMode = getMountMode(uid, packageName);
3433 boolean isUidActive = LocalServices.getService(ActivityManagerInternal.class)
3434 .getUidProcessState(uid) != PROCESS_STATE_NONEXISTENT;
3435
3436 if (isUidActive) {
3437 remountUidExternalStorage(uid, mountMode);
3438 }
Sudheer Shankaff971bc2018-12-13 17:39:59 -08003439 }
3440 };
3441
Kenny Rootaf9d6672010-10-08 09:21:39 -07003442 private void addObbStateLocked(ObbState obbState) throws RemoteException {
3443 final IBinder binder = obbState.getBinder();
3444 List<ObbState> obbStates = mObbMounts.get(binder);
Kenny Root5919ac62010-10-05 09:49:40 -07003445
Kenny Rootaf9d6672010-10-08 09:21:39 -07003446 if (obbStates == null) {
3447 obbStates = new ArrayList<ObbState>();
3448 mObbMounts.put(binder, obbStates);
3449 } else {
3450 for (final ObbState o : obbStates) {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003451 if (o.rawPath.equals(obbState.rawPath)) {
Kenny Rootaf9d6672010-10-08 09:21:39 -07003452 throw new IllegalStateException("Attempt to add ObbState twice. "
Sudheer Shanka2250d562016-11-07 15:41:02 -08003453 + "This indicates an error in the StorageManagerService logic.");
Kenny Root5919ac62010-10-05 09:49:40 -07003454 }
3455 }
Kenny Roota02b8b02010-08-05 16:14:17 -07003456 }
Kenny Rootaf9d6672010-10-08 09:21:39 -07003457
3458 obbStates.add(obbState);
3459 try {
3460 obbState.link();
3461 } catch (RemoteException e) {
3462 /*
3463 * The binder died before we could link it, so clean up our state
3464 * and return failure.
3465 */
3466 obbStates.remove(obbState);
3467 if (obbStates.isEmpty()) {
3468 mObbMounts.remove(binder);
3469 }
3470
3471 // Rethrow the error so mountObb can get it
3472 throw e;
3473 }
3474
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003475 mObbPathToStateMap.put(obbState.rawPath, obbState);
Kenny Roota02b8b02010-08-05 16:14:17 -07003476 }
3477
Kenny Rootaf9d6672010-10-08 09:21:39 -07003478 private void removeObbStateLocked(ObbState obbState) {
3479 final IBinder binder = obbState.getBinder();
3480 final List<ObbState> obbStates = mObbMounts.get(binder);
3481 if (obbStates != null) {
3482 if (obbStates.remove(obbState)) {
3483 obbState.unlink();
Kenny Root05105f72010-09-22 17:29:43 -07003484 }
Kenny Rootaf9d6672010-10-08 09:21:39 -07003485 if (obbStates.isEmpty()) {
3486 mObbMounts.remove(binder);
3487 }
Kenny Roota02b8b02010-08-05 16:14:17 -07003488 }
Kenny Roota02b8b02010-08-05 16:14:17 -07003489
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003490 mObbPathToStateMap.remove(obbState.rawPath);
Kenny Root38cf8862010-09-26 14:18:51 -07003491 }
3492
Kenny Roota02b8b02010-08-05 16:14:17 -07003493 private class ObbActionHandler extends Handler {
Kenny Roota02b8b02010-08-05 16:14:17 -07003494
3495 ObbActionHandler(Looper l) {
3496 super(l);
3497 }
3498
3499 @Override
3500 public void handleMessage(Message msg) {
3501 switch (msg.what) {
3502 case OBB_RUN_ACTION: {
Kenny Root480afe72010-10-07 10:17:50 -07003503 final ObbAction action = (ObbAction) msg.obj;
Kenny Roota02b8b02010-08-05 16:14:17 -07003504
3505 if (DEBUG_OBB)
3506 Slog.i(TAG, "OBB_RUN_ACTION: " + action.toString());
3507
Sudheer Shanka25469aa2018-08-27 15:50:23 -07003508 action.execute(this);
Kenny Roota02b8b02010-08-05 16:14:17 -07003509 break;
3510 }
Kenny Rootaf9d6672010-10-08 09:21:39 -07003511 case OBB_FLUSH_MOUNT_STATE: {
3512 final String path = (String) msg.obj;
3513
3514 if (DEBUG_OBB)
3515 Slog.i(TAG, "Flushing all OBB state for path " + path);
3516
3517 synchronized (mObbMounts) {
3518 final List<ObbState> obbStatesToRemove = new LinkedList<ObbState>();
3519
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003520 final Iterator<ObbState> i = mObbPathToStateMap.values().iterator();
Kenny Rootaf9d6672010-10-08 09:21:39 -07003521 while (i.hasNext()) {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003522 final ObbState state = i.next();
Kenny Rootaf9d6672010-10-08 09:21:39 -07003523
3524 /*
3525 * If this entry's source file is in the volume path
3526 * that got unmounted, remove it because it's no
3527 * longer valid.
3528 */
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003529 if (state.canonicalPath.startsWith(path)) {
3530 obbStatesToRemove.add(state);
Kenny Rootaf9d6672010-10-08 09:21:39 -07003531 }
3532 }
3533
3534 for (final ObbState obbState : obbStatesToRemove) {
3535 if (DEBUG_OBB)
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003536 Slog.i(TAG, "Removing state for " + obbState.rawPath);
Kenny Rootaf9d6672010-10-08 09:21:39 -07003537
3538 removeObbStateLocked(obbState);
3539
3540 try {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003541 obbState.token.onObbResult(obbState.rawPath, obbState.nonce,
Kenny Rootaf9d6672010-10-08 09:21:39 -07003542 OnObbStateChangeListener.UNMOUNTED);
3543 } catch (RemoteException e) {
3544 Slog.i(TAG, "Couldn't send unmount notification for OBB: "
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003545 + obbState.rawPath);
Kenny Rootaf9d6672010-10-08 09:21:39 -07003546 }
3547 }
3548 }
3549 break;
3550 }
Kenny Roota02b8b02010-08-05 16:14:17 -07003551 }
3552 }
Kenny Roota02b8b02010-08-05 16:14:17 -07003553 }
3554
Jeff Sharkey0095a822018-02-15 13:06:53 -07003555 private static class ObbException extends Exception {
3556 public final int status;
3557
3558 public ObbException(int status, String message) {
3559 super(message);
3560 this.status = status;
3561 }
3562
3563 public ObbException(int status, Throwable cause) {
3564 super(cause.getMessage(), cause);
3565 this.status = status;
3566 }
3567 }
3568
Kenny Roota02b8b02010-08-05 16:14:17 -07003569 abstract class ObbAction {
Kenny Roota02b8b02010-08-05 16:14:17 -07003570
3571 ObbState mObbState;
3572
3573 ObbAction(ObbState obbState) {
3574 mObbState = obbState;
3575 }
3576
3577 public void execute(ObbActionHandler handler) {
3578 try {
3579 if (DEBUG_OBB)
Ben Komalo444eca22011-09-01 15:17:44 -07003580 Slog.i(TAG, "Starting to execute action: " + toString());
Sudheer Shanka25469aa2018-08-27 15:50:23 -07003581 handleExecute();
Jeff Sharkey0095a822018-02-15 13:06:53 -07003582 } catch (ObbException e) {
3583 notifyObbStateChange(e);
Kenny Roota02b8b02010-08-05 16:14:17 -07003584 }
3585 }
3586
Jeff Sharkey0095a822018-02-15 13:06:53 -07003587 abstract void handleExecute() throws ObbException;
Kenny Root38cf8862010-09-26 14:18:51 -07003588
Jeff Sharkey0095a822018-02-15 13:06:53 -07003589 protected void notifyObbStateChange(ObbException e) {
3590 Slog.w(TAG, e);
3591 notifyObbStateChange(e.status);
3592 }
3593
3594 protected void notifyObbStateChange(int status) {
Kenny Rootaf9d6672010-10-08 09:21:39 -07003595 if (mObbState == null || mObbState.token == null) {
3596 return;
3597 }
3598
Kenny Root38cf8862010-09-26 14:18:51 -07003599 try {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003600 mObbState.token.onObbResult(mObbState.rawPath, mObbState.nonce, status);
Kenny Root38cf8862010-09-26 14:18:51 -07003601 } catch (RemoteException e) {
Sudheer Shanka2250d562016-11-07 15:41:02 -08003602 Slog.w(TAG, "StorageEventListener went away while calling onObbStateChanged");
Kenny Root38cf8862010-09-26 14:18:51 -07003603 }
3604 }
Kenny Roota02b8b02010-08-05 16:14:17 -07003605 }
3606
3607 class MountObbAction extends ObbAction {
Ben Komalo444eca22011-09-01 15:17:44 -07003608 private final String mKey;
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003609 private final int mCallingUid;
Sudheer Shanka25469aa2018-08-27 15:50:23 -07003610 private ObbInfo mObbInfo;
Kenny Roota02b8b02010-08-05 16:14:17 -07003611
Sudheer Shanka25469aa2018-08-27 15:50:23 -07003612 MountObbAction(ObbState obbState, String key, int callingUid, ObbInfo obbInfo) {
Kenny Roota02b8b02010-08-05 16:14:17 -07003613 super(obbState);
3614 mKey = key;
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003615 mCallingUid = callingUid;
Sudheer Shanka25469aa2018-08-27 15:50:23 -07003616 mObbInfo = obbInfo;
Kenny Roota02b8b02010-08-05 16:14:17 -07003617 }
3618
Jason parks5af0b912010-11-29 09:05:25 -06003619 @Override
Jeff Sharkey0095a822018-02-15 13:06:53 -07003620 public void handleExecute() throws ObbException {
Kenny Rootaf9d6672010-10-08 09:21:39 -07003621 warnOnNotMounted();
3622
Sudheer Shanka25469aa2018-08-27 15:50:23 -07003623 if (!isUidOwnerOfPackageOrSystem(mObbInfo.packageName, mCallingUid)) {
Jeff Sharkey0095a822018-02-15 13:06:53 -07003624 throw new ObbException(ERROR_PERMISSION_DENIED, "Denied attempt to mount OBB "
Sudheer Shanka25469aa2018-08-27 15:50:23 -07003625 + mObbInfo.filename + " which is owned by " + mObbInfo.packageName);
Kenny Roota02b8b02010-08-05 16:14:17 -07003626 }
3627
Kenny Rootaf9d6672010-10-08 09:21:39 -07003628 final boolean isMounted;
3629 synchronized (mObbMounts) {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003630 isMounted = mObbPathToStateMap.containsKey(mObbState.rawPath);
Kenny Rootaf9d6672010-10-08 09:21:39 -07003631 }
3632 if (isMounted) {
Jeff Sharkey0095a822018-02-15 13:06:53 -07003633 throw new ObbException(ERROR_ALREADY_MOUNTED,
Sudheer Shanka25469aa2018-08-27 15:50:23 -07003634 "Attempt to mount OBB which is already mounted: " + mObbInfo.filename);
Kenny Rootaf9d6672010-10-08 09:21:39 -07003635 }
3636
Kenny Rootaf9d6672010-10-08 09:21:39 -07003637 final String hashedKey;
Jeff Sharkey41cd6812017-09-11 10:32:17 -06003638 final String binderKey;
Kenny Rootaf9d6672010-10-08 09:21:39 -07003639 if (mKey == null) {
3640 hashedKey = "none";
Jeff Sharkey41cd6812017-09-11 10:32:17 -06003641 binderKey = "";
Kenny Rootaf9d6672010-10-08 09:21:39 -07003642 } else {
Kenny Rootaf9d6672010-10-08 09:21:39 -07003643 try {
Kenny Root3b1abba2010-10-13 15:00:07 -07003644 SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
3645
Sudheer Shanka25469aa2018-08-27 15:50:23 -07003646 KeySpec ks = new PBEKeySpec(mKey.toCharArray(), mObbInfo.salt,
Kenny Root3b1abba2010-10-13 15:00:07 -07003647 PBKDF2_HASH_ROUNDS, CRYPTO_ALGORITHM_KEY_SIZE);
3648 SecretKey key = factory.generateSecret(ks);
3649 BigInteger bi = new BigInteger(key.getEncoded());
3650 hashedKey = bi.toString(16);
Jeff Sharkey41cd6812017-09-11 10:32:17 -06003651 binderKey = hashedKey;
Jeff Sharkey0095a822018-02-15 13:06:53 -07003652 } catch (GeneralSecurityException e) {
3653 throw new ObbException(ERROR_INTERNAL, e);
Kenny Root38cf8862010-09-26 14:18:51 -07003654 }
Kenny Rootaf9d6672010-10-08 09:21:39 -07003655 }
Kenny Root38cf8862010-09-26 14:18:51 -07003656
Kenny Rootaf9d6672010-10-08 09:21:39 -07003657 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06003658 mObbState.volId = mVold.createObb(mObbState.canonicalPath, binderKey,
3659 mObbState.ownerGid);
Zim95eca1d2019-11-15 18:03:00 +00003660 mVold.mount(mObbState.volId, 0, -1, null);
Kenny Roota02b8b02010-08-05 16:14:17 -07003661
Kenny Rootaf9d6672010-10-08 09:21:39 -07003662 if (DEBUG_OBB)
Xiaohui Chen621b3fc2015-10-02 14:41:42 -07003663 Slog.d(TAG, "Successfully mounted OBB " + mObbState.canonicalPath);
Kenny Rootaf9d6672010-10-08 09:21:39 -07003664
3665 synchronized (mObbMounts) {
3666 addObbStateLocked(mObbState);
3667 }
3668
Jeff Sharkey0095a822018-02-15 13:06:53 -07003669 notifyObbStateChange(MOUNTED);
3670 } catch (Exception e) {
3671 throw new ObbException(ERROR_COULD_NOT_MOUNT, e);
Kenny Root02c87302010-07-01 08:10:18 -07003672 }
3673 }
3674
Jason parks5af0b912010-11-29 09:05:25 -06003675 @Override
Kenny Roota02b8b02010-08-05 16:14:17 -07003676 public String toString() {
3677 StringBuilder sb = new StringBuilder();
3678 sb.append("MountObbAction{");
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003679 sb.append(mObbState);
Kenny Roota02b8b02010-08-05 16:14:17 -07003680 sb.append('}');
3681 return sb.toString();
3682 }
3683 }
3684
3685 class UnmountObbAction extends ObbAction {
Ben Komalo444eca22011-09-01 15:17:44 -07003686 private final boolean mForceUnmount;
Kenny Roota02b8b02010-08-05 16:14:17 -07003687
3688 UnmountObbAction(ObbState obbState, boolean force) {
3689 super(obbState);
3690 mForceUnmount = force;
3691 }
3692
Jason parks5af0b912010-11-29 09:05:25 -06003693 @Override
Jeff Sharkey0095a822018-02-15 13:06:53 -07003694 public void handleExecute() throws ObbException {
Kenny Rootaf9d6672010-10-08 09:21:39 -07003695 warnOnNotMounted();
3696
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003697 final ObbState existingState;
Kenny Root38cf8862010-09-26 14:18:51 -07003698 synchronized (mObbMounts) {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003699 existingState = mObbPathToStateMap.get(mObbState.rawPath);
Kenny Rootaf9d6672010-10-08 09:21:39 -07003700 }
Kenny Root38cf8862010-09-26 14:18:51 -07003701
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003702 if (existingState == null) {
Jeff Sharkey0095a822018-02-15 13:06:53 -07003703 throw new ObbException(ERROR_NOT_MOUNTED, "Missing existingState");
Kenny Rootaf9d6672010-10-08 09:21:39 -07003704 }
3705
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003706 if (existingState.ownerGid != mObbState.ownerGid) {
Jeff Sharkey0095a822018-02-15 13:06:53 -07003707 notifyObbStateChange(new ObbException(ERROR_PERMISSION_DENIED,
3708 "Permission denied to unmount OBB " + existingState.rawPath
3709 + " (owned by GID " + existingState.ownerGid + ")"));
Kenny Rootaf9d6672010-10-08 09:21:39 -07003710 return;
3711 }
3712
Kenny Rootaf9d6672010-10-08 09:21:39 -07003713 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06003714 mVold.unmount(mObbState.volId);
3715 mVold.destroyObb(mObbState.volId);
3716 mObbState.volId = null;
Kenny Roota02b8b02010-08-05 16:14:17 -07003717
Kenny Rootaf9d6672010-10-08 09:21:39 -07003718 synchronized (mObbMounts) {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003719 removeObbStateLocked(existingState);
Kenny Root38cf8862010-09-26 14:18:51 -07003720 }
3721
Jeff Sharkey0095a822018-02-15 13:06:53 -07003722 notifyObbStateChange(UNMOUNTED);
3723 } catch (Exception e) {
3724 throw new ObbException(ERROR_COULD_NOT_UNMOUNT, e);
Kenny Roota02b8b02010-08-05 16:14:17 -07003725 }
3726 }
3727
Jason parks5af0b912010-11-29 09:05:25 -06003728 @Override
Kenny Roota02b8b02010-08-05 16:14:17 -07003729 public String toString() {
3730 StringBuilder sb = new StringBuilder();
3731 sb.append("UnmountObbAction{");
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003732 sb.append(mObbState);
Kenny Roota02b8b02010-08-05 16:14:17 -07003733 sb.append(",force=");
3734 sb.append(mForceUnmount);
Kenny Roota02b8b02010-08-05 16:14:17 -07003735 sb.append('}');
3736 return sb.toString();
3737 }
Kenny Root02c87302010-07-01 08:10:18 -07003738 }
Kenny Root38cf8862010-09-26 14:18:51 -07003739
Jeff Sharkey7e19f532017-11-06 13:54:11 -07003740 private void dispatchOnStatus(IVoldTaskListener listener, int status,
3741 PersistableBundle extras) {
3742 if (listener != null) {
3743 try {
3744 listener.onStatus(status, extras);
3745 } catch (RemoteException ignored) {
3746 }
3747 }
3748 }
3749
3750 private void dispatchOnFinished(IVoldTaskListener listener, int status,
3751 PersistableBundle extras) {
3752 if (listener != null) {
3753 try {
3754 listener.onFinished(status, extras);
3755 } catch (RemoteException ignored) {
3756 }
3757 }
3758 }
3759
Sudheer Shanka3a0df3b2018-12-12 12:43:43 -08003760 private int getMountMode(int uid, String packageName) {
Jeff Sharkey6fd69942019-03-26 17:53:35 -06003761 final int mode = getMountModeInternal(uid, packageName);
3762 if (LOCAL_LOGV) {
3763 Slog.v(TAG, "Resolved mode " + mode + " for " + packageName + "/"
3764 + UserHandle.formatUid(uid));
3765 }
3766 return mode;
3767 }
3768
3769 private int getMountModeInternal(int uid, String packageName) {
Sudheer Shanka3a0df3b2018-12-12 12:43:43 -08003770 try {
Jeff Sharkey6fd69942019-03-26 17:53:35 -06003771 // Get some easy cases out of the way first
Sudheer Shanka3a0df3b2018-12-12 12:43:43 -08003772 if (Process.isIsolated(uid)) {
3773 return Zygote.MOUNT_EXTERNAL_NONE;
3774 }
Sudheer Shankab1613982019-05-16 16:55:50 -07003775
3776 final String[] packagesForUid = mIPackageManager.getPackagesForUid(uid);
Sudheer Shanka1df72db2019-05-24 10:59:52 -07003777 if (ArrayUtils.isEmpty(packagesForUid)) {
3778 // It's possible the package got uninstalled already, so just ignore.
3779 return Zygote.MOUNT_EXTERNAL_NONE;
3780 }
Sudheer Shankab1613982019-05-16 16:55:50 -07003781 if (packageName == null) {
3782 packageName = packagesForUid[0];
3783 }
3784
Jeff Sharkey6fd69942019-03-26 17:53:35 -06003785 if (mPmInternal.isInstantApp(packageName, UserHandle.getUserId(uid))) {
Winson Chiu5118d492019-05-15 18:24:06 +00003786 return Zygote.MOUNT_EXTERNAL_NONE;
Jeff Sharkey6fd69942019-03-26 17:53:35 -06003787 }
3788
Martijn Coenen44db1ac2019-12-03 16:06:19 +01003789 if (mIsFuseEnabled && mMediaStoreAuthorityAppId == UserHandle.getAppId(uid)) {
3790 // Determine if caller requires pass_through mount; note that we do this for
3791 // all processes that share a UID with MediaProvider; but this is fine, since
3792 // those processes anyway share the same rights as MediaProvider.
Zim74a9bba2019-09-03 20:49:13 +01003793 return Zygote.MOUNT_EXTERNAL_PASS_THROUGH;
3794 }
3795
Jeff Sharkey6fd69942019-03-26 17:53:35 -06003796 // Determine if caller is holding runtime permission
Chad Brubaker45810af2019-04-08 19:19:48 -07003797 final boolean hasRead = StorageManager.checkPermissionAndCheckOp(mContext, false, 0,
Jeff Sharkey6fd69942019-03-26 17:53:35 -06003798 uid, packageName, READ_EXTERNAL_STORAGE, OP_READ_EXTERNAL_STORAGE);
Chad Brubaker45810af2019-04-08 19:19:48 -07003799 final boolean hasWrite = StorageManager.checkPermissionAndCheckOp(mContext, false, 0,
Jeff Sharkey6fd69942019-03-26 17:53:35 -06003800 uid, packageName, WRITE_EXTERNAL_STORAGE, OP_WRITE_EXTERNAL_STORAGE);
Jeff Sharkey6fd69942019-03-26 17:53:35 -06003801
3802 // We're only willing to give out broad access if they also hold
3803 // runtime permission; this is a firm CDD requirement
3804 final boolean hasFull = mIPackageManager.checkUidPermission(WRITE_MEDIA_STORAGE,
3805 uid) == PERMISSION_GRANTED;
Jeff Sharkey26874a22019-04-17 21:30:47 -06003806 if (hasFull && hasWrite) {
Jeff Sharkey6fd69942019-03-26 17:53:35 -06003807 return Zygote.MOUNT_EXTERNAL_FULL;
3808 }
3809
3810 // We're only willing to give out installer access if they also hold
3811 // runtime permission; this is a firm CDD requirement
3812 final boolean hasInstall = mIPackageManager.checkUidPermission(INSTALL_PACKAGES,
3813 uid) == PERMISSION_GRANTED;
Sudheer Shankab1613982019-05-16 16:55:50 -07003814 boolean hasInstallOp = false;
3815 // OP_REQUEST_INSTALL_PACKAGES is granted/denied per package but vold can't
3816 // update mountpoints of a specific package. So, check the appop for all packages
3817 // sharing the uid and allow same level of storage access for all packages even if
3818 // one of the packages has the appop granted.
3819 for (String uidPackageName : packagesForUid) {
3820 if (mIAppOpsService.checkOperation(
3821 OP_REQUEST_INSTALL_PACKAGES, uid, uidPackageName) == MODE_ALLOWED) {
3822 hasInstallOp = true;
3823 break;
3824 }
3825 }
Jeff Sharkey26874a22019-04-17 21:30:47 -06003826 if ((hasInstall || hasInstallOp) && hasWrite) {
3827 return Zygote.MOUNT_EXTERNAL_WRITE;
Jeff Sharkey6fd69942019-03-26 17:53:35 -06003828 }
3829
3830 // Otherwise we're willing to give out sandboxed or non-sandboxed if
3831 // they hold the runtime permission
3832 final boolean hasLegacy = mIAppOpsService.checkOperation(OP_LEGACY_STORAGE,
3833 uid, packageName) == MODE_ALLOWED;
Jeff Sharkey26874a22019-04-17 21:30:47 -06003834 if (hasLegacy && hasWrite) {
3835 return Zygote.MOUNT_EXTERNAL_WRITE;
3836 } else if (hasLegacy && hasRead) {
3837 return Zygote.MOUNT_EXTERNAL_READ;
Sudheer Shanka3a0df3b2018-12-12 12:43:43 -08003838 } else {
Sudheer Shanka783c90e2019-04-12 13:55:20 -07003839 return Zygote.MOUNT_EXTERNAL_DEFAULT;
Sudheer Shanka3a0df3b2018-12-12 12:43:43 -08003840 }
3841 } catch (RemoteException e) {
3842 // Should not happen
3843 }
3844 return Zygote.MOUNT_EXTERNAL_NONE;
3845 }
3846
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07003847 private static class Callbacks extends Handler {
3848 private static final int MSG_STORAGE_STATE_CHANGED = 1;
3849 private static final int MSG_VOLUME_STATE_CHANGED = 2;
Jeff Sharkey50a05452015-04-29 11:24:52 -07003850 private static final int MSG_VOLUME_RECORD_CHANGED = 3;
3851 private static final int MSG_VOLUME_FORGOTTEN = 4;
3852 private static final int MSG_DISK_SCANNED = 5;
Makoto Onuki9dc575d2015-06-12 16:10:25 -07003853 private static final int MSG_DISK_DESTROYED = 6;
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07003854
Sudheer Shanka2250d562016-11-07 15:41:02 -08003855 private final RemoteCallbackList<IStorageEventListener>
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07003856 mCallbacks = new RemoteCallbackList<>();
3857
3858 public Callbacks(Looper looper) {
3859 super(looper);
3860 }
3861
Sudheer Shanka2250d562016-11-07 15:41:02 -08003862 public void register(IStorageEventListener callback) {
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07003863 mCallbacks.register(callback);
3864 }
3865
Sudheer Shanka2250d562016-11-07 15:41:02 -08003866 public void unregister(IStorageEventListener callback) {
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07003867 mCallbacks.unregister(callback);
3868 }
3869
3870 @Override
3871 public void handleMessage(Message msg) {
3872 final SomeArgs args = (SomeArgs) msg.obj;
3873 final int n = mCallbacks.beginBroadcast();
3874 for (int i = 0; i < n; i++) {
Sudheer Shanka2250d562016-11-07 15:41:02 -08003875 final IStorageEventListener callback = mCallbacks.getBroadcastItem(i);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07003876 try {
3877 invokeCallback(callback, msg.what, args);
3878 } catch (RemoteException ignored) {
3879 }
3880 }
3881 mCallbacks.finishBroadcast();
3882 args.recycle();
3883 }
3884
Sudheer Shanka2250d562016-11-07 15:41:02 -08003885 private void invokeCallback(IStorageEventListener callback, int what, SomeArgs args)
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07003886 throws RemoteException {
3887 switch (what) {
3888 case MSG_STORAGE_STATE_CHANGED: {
3889 callback.onStorageStateChanged((String) args.arg1, (String) args.arg2,
3890 (String) args.arg3);
3891 break;
3892 }
3893 case MSG_VOLUME_STATE_CHANGED: {
3894 callback.onVolumeStateChanged((VolumeInfo) args.arg1, args.argi2, args.argi3);
3895 break;
3896 }
Jeff Sharkey50a05452015-04-29 11:24:52 -07003897 case MSG_VOLUME_RECORD_CHANGED: {
3898 callback.onVolumeRecordChanged((VolumeRecord) args.arg1);
3899 break;
3900 }
3901 case MSG_VOLUME_FORGOTTEN: {
3902 callback.onVolumeForgotten((String) args.arg1);
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07003903 break;
3904 }
Jeff Sharkey620b32b2015-04-23 19:36:02 -07003905 case MSG_DISK_SCANNED: {
3906 callback.onDiskScanned((DiskInfo) args.arg1, args.argi2);
Jeff Sharkey7e92ef32015-04-17 17:35:07 -07003907 break;
3908 }
Makoto Onuki9dc575d2015-06-12 16:10:25 -07003909 case MSG_DISK_DESTROYED: {
3910 callback.onDiskDestroyed((DiskInfo) args.arg1);
3911 break;
3912 }
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07003913 }
3914 }
3915
3916 private void notifyStorageStateChanged(String path, String oldState, String newState) {
3917 final SomeArgs args = SomeArgs.obtain();
3918 args.arg1 = path;
3919 args.arg2 = oldState;
3920 args.arg3 = newState;
3921 obtainMessage(MSG_STORAGE_STATE_CHANGED, args).sendToTarget();
3922 }
3923
3924 private void notifyVolumeStateChanged(VolumeInfo vol, int oldState, int newState) {
3925 final SomeArgs args = SomeArgs.obtain();
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07003926 args.arg1 = vol.clone();
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07003927 args.argi2 = oldState;
3928 args.argi3 = newState;
3929 obtainMessage(MSG_VOLUME_STATE_CHANGED, args).sendToTarget();
3930 }
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07003931
Jeff Sharkey50a05452015-04-29 11:24:52 -07003932 private void notifyVolumeRecordChanged(VolumeRecord rec) {
3933 final SomeArgs args = SomeArgs.obtain();
3934 args.arg1 = rec.clone();
3935 obtainMessage(MSG_VOLUME_RECORD_CHANGED, args).sendToTarget();
3936 }
3937
3938 private void notifyVolumeForgotten(String fsUuid) {
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07003939 final SomeArgs args = SomeArgs.obtain();
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07003940 args.arg1 = fsUuid;
Jeff Sharkey50a05452015-04-29 11:24:52 -07003941 obtainMessage(MSG_VOLUME_FORGOTTEN, args).sendToTarget();
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07003942 }
Jeff Sharkey7e92ef32015-04-17 17:35:07 -07003943
Jeff Sharkey620b32b2015-04-23 19:36:02 -07003944 private void notifyDiskScanned(DiskInfo disk, int volumeCount) {
Jeff Sharkey7e92ef32015-04-17 17:35:07 -07003945 final SomeArgs args = SomeArgs.obtain();
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07003946 args.arg1 = disk.clone();
Jeff Sharkey620b32b2015-04-23 19:36:02 -07003947 args.argi2 = volumeCount;
3948 obtainMessage(MSG_DISK_SCANNED, args).sendToTarget();
Jeff Sharkey7e92ef32015-04-17 17:35:07 -07003949 }
Makoto Onuki9dc575d2015-06-12 16:10:25 -07003950
3951 private void notifyDiskDestroyed(DiskInfo disk) {
3952 final SomeArgs args = SomeArgs.obtain();
3953 args.arg1 = disk.clone();
3954 obtainMessage(MSG_DISK_DESTROYED, args).sendToTarget();
3955 }
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07003956 }
3957
Kenny Root38cf8862010-09-26 14:18:51 -07003958 @Override
Jeff Sharkey5aca2b82013-10-16 16:21:54 -07003959 protected void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
Jeff Sharkeyfe9a53b2017-03-31 14:08:23 -06003960 if (!DumpUtils.checkDumpPermission(mContext, TAG, writer)) return;
Jeff Sharkey5aca2b82013-10-16 16:21:54 -07003961
3962 final IndentingPrintWriter pw = new IndentingPrintWriter(writer, " ", 160);
Jeff Sharkey27de30d2015-04-18 16:20:27 -07003963 synchronized (mLock) {
3964 pw.println("Disks:");
3965 pw.increaseIndent();
3966 for (int i = 0; i < mDisks.size(); i++) {
3967 final DiskInfo disk = mDisks.valueAt(i);
3968 disk.dump(pw);
3969 }
3970 pw.decreaseIndent();
3971
3972 pw.println();
3973 pw.println("Volumes:");
3974 pw.increaseIndent();
3975 for (int i = 0; i < mVolumes.size(); i++) {
3976 final VolumeInfo vol = mVolumes.valueAt(i);
3977 if (VolumeInfo.ID_PRIVATE_INTERNAL.equals(vol.id)) continue;
3978 vol.dump(pw);
3979 }
3980 pw.decreaseIndent();
3981
3982 pw.println();
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07003983 pw.println("Records:");
Jeff Sharkey27de30d2015-04-18 16:20:27 -07003984 pw.increaseIndent();
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07003985 for (int i = 0; i < mRecords.size(); i++) {
3986 final VolumeRecord note = mRecords.valueAt(i);
3987 note.dump(pw);
Jeff Sharkey27de30d2015-04-18 16:20:27 -07003988 }
3989 pw.decreaseIndent();
Jeff Sharkey275e3e42015-04-24 16:10:32 -07003990
3991 pw.println();
3992 pw.println("Primary storage UUID: " + mPrimaryStorageUuid);
Jeff Sharkeyb0c363b22018-12-15 11:53:03 -07003993
3994 pw.println();
Felipe Leme281389a2016-10-10 17:12:20 -07003995 final Pair<String, Long> pair = StorageManager.getPrimaryStoragePathAndSize();
3996 if (pair == null) {
3997 pw.println("Internal storage total size: N/A");
3998 } else {
3999 pw.print("Internal storage (");
4000 pw.print(pair.first);
4001 pw.print(") total size: ");
4002 pw.print(pair.second);
4003 pw.print(" (");
Jeff Sharkey9f2dc052018-01-07 16:47:31 -07004004 pw.print(DataUnit.MEBIBYTES.toBytes(pair.second));
4005 pw.println(" MiB)");
Felipe Leme281389a2016-10-10 17:12:20 -07004006 }
Jeff Sharkeyb0c363b22018-12-15 11:53:03 -07004007
4008 pw.println();
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07004009 pw.println("Local unlocked users: " + Arrays.toString(mLocalUnlockedUsers));
4010 pw.println("System unlocked users: " + Arrays.toString(mSystemUnlockedUsers));
Jeff Sharkeyb0c363b22018-12-15 11:53:03 -07004011
4012 final ContentResolver cr = mContext.getContentResolver();
4013 pw.println();
4014 pw.println("Isolated storage, local feature flag: "
4015 + Settings.Global.getInt(cr, Settings.Global.ISOLATED_STORAGE_LOCAL, 0));
4016 pw.println("Isolated storage, remote feature flag: "
4017 + Settings.Global.getInt(cr, Settings.Global.ISOLATED_STORAGE_REMOTE, 0));
4018 pw.println("Isolated storage, resolved: " + StorageManager.hasIsolatedStorage());
Jeff Sharkey27de30d2015-04-18 16:20:27 -07004019 }
Kenny Root38cf8862010-09-26 14:18:51 -07004020
Kenny Root38cf8862010-09-26 14:18:51 -07004021 synchronized (mObbMounts) {
Jeff Sharkey27de30d2015-04-18 16:20:27 -07004022 pw.println();
Jeff Sharkey5aca2b82013-10-16 16:21:54 -07004023 pw.println("mObbMounts:");
4024 pw.increaseIndent();
4025 final Iterator<Entry<IBinder, List<ObbState>>> binders = mObbMounts.entrySet()
4026 .iterator();
Kenny Rootaf9d6672010-10-08 09:21:39 -07004027 while (binders.hasNext()) {
4028 Entry<IBinder, List<ObbState>> e = binders.next();
Jeff Sharkey5aca2b82013-10-16 16:21:54 -07004029 pw.println(e.getKey() + ":");
4030 pw.increaseIndent();
Kenny Rootaf9d6672010-10-08 09:21:39 -07004031 final List<ObbState> obbStates = e.getValue();
Kenny Root38cf8862010-09-26 14:18:51 -07004032 for (final ObbState obbState : obbStates) {
Jeff Sharkey5aca2b82013-10-16 16:21:54 -07004033 pw.println(obbState);
Kenny Root38cf8862010-09-26 14:18:51 -07004034 }
Jeff Sharkey5aca2b82013-10-16 16:21:54 -07004035 pw.decreaseIndent();
Kenny Root38cf8862010-09-26 14:18:51 -07004036 }
Jeff Sharkey5aca2b82013-10-16 16:21:54 -07004037 pw.decreaseIndent();
Kenny Rootaf9d6672010-10-08 09:21:39 -07004038
Jeff Sharkey5aca2b82013-10-16 16:21:54 -07004039 pw.println();
4040 pw.println("mObbPathToStateMap:");
4041 pw.increaseIndent();
Kenny Rootaf9d6672010-10-08 09:21:39 -07004042 final Iterator<Entry<String, ObbState>> maps = mObbPathToStateMap.entrySet().iterator();
4043 while (maps.hasNext()) {
4044 final Entry<String, ObbState> e = maps.next();
Jeff Sharkey5aca2b82013-10-16 16:21:54 -07004045 pw.print(e.getKey());
4046 pw.print(" -> ");
4047 pw.println(e.getValue());
Kenny Rootaf9d6672010-10-08 09:21:39 -07004048 }
Jeff Sharkey5aca2b82013-10-16 16:21:54 -07004049 pw.decreaseIndent();
Kenny Root38cf8862010-09-26 14:18:51 -07004050 }
Kenny Root4161f9b2011-07-13 09:48:33 -07004051
Robert Greenwalt470fd722012-01-18 12:51:15 -08004052 pw.println();
Christopher Tate7265abe2014-11-21 13:54:45 -08004053 pw.print("Last maintenance: ");
Jeff Sharkeye8a4b662015-06-27 15:43:45 -07004054 pw.println(TimeUtils.formatForLogging(mLastMaintenance));
Kenny Root38cf8862010-09-26 14:18:51 -07004055 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004056
Jeff Sharkeyfa23c5a2011-08-09 21:44:24 -07004057 /** {@inheritDoc} */
Jeff Sharkey48877892015-03-18 11:27:19 -07004058 @Override
Jeff Sharkeyfa23c5a2011-08-09 21:44:24 -07004059 public void monitor() {
Jeff Sharkey54402792017-09-15 16:05:19 -06004060 try {
4061 mVold.monitor();
4062 } catch (Exception e) {
4063 Slog.wtf(TAG, e);
Paul Lawrence1c62cbb2015-06-03 14:14:52 -07004064 }
Jeff Sharkeyfa23c5a2011-08-09 21:44:24 -07004065 }
Svet Ganov6ee871e2015-07-10 14:29:33 -07004066
Sudheer Shanka2250d562016-11-07 15:41:02 -08004067 private final class StorageManagerInternalImpl extends StorageManagerInternal {
Svet Ganov6ee871e2015-07-10 14:29:33 -07004068 // Not guarded by a lock.
4069 private final CopyOnWriteArrayList<ExternalStorageMountPolicy> mPolicies =
4070 new CopyOnWriteArrayList<>();
4071
Risanaec0ee72018-10-31 10:10:12 +09004072 @GuardedBy("mResetListeners")
4073 private final List<StorageManagerInternal.ResetListener> mResetListeners =
4074 new ArrayList<>();
4075
Svet Ganov6ee871e2015-07-10 14:29:33 -07004076 @Override
4077 public void addExternalStoragePolicy(ExternalStorageMountPolicy policy) {
4078 // No locking - CopyOnWriteArrayList
4079 mPolicies.add(policy);
4080 }
4081
4082 @Override
4083 public void onExternalStoragePolicyChanged(int uid, String packageName) {
4084 final int mountMode = getExternalStorageMountMode(uid, packageName);
4085 remountUidExternalStorage(uid, mountMode);
4086 }
4087
4088 @Override
4089 public int getExternalStorageMountMode(int uid, String packageName) {
Sudheer Shanka3a0df3b2018-12-12 12:43:43 -08004090 if (ENABLE_ISOLATED_STORAGE) {
4091 return getMountMode(uid, packageName);
4092 }
Sudheer Shankab1613982019-05-16 16:55:50 -07004093 try {
4094 if (packageName == null) {
4095 final String[] packagesForUid = mIPackageManager.getPackagesForUid(uid);
4096 packageName = packagesForUid[0];
4097 }
4098 } catch (RemoteException e) {
4099 // Should not happen - same process
4100 }
Svet Ganov6ee871e2015-07-10 14:29:33 -07004101 // No locking - CopyOnWriteArrayList
4102 int mountMode = Integer.MAX_VALUE;
4103 for (ExternalStorageMountPolicy policy : mPolicies) {
4104 final int policyMode = policy.getMountMode(uid, packageName);
4105 if (policyMode == Zygote.MOUNT_EXTERNAL_NONE) {
4106 return Zygote.MOUNT_EXTERNAL_NONE;
4107 }
4108 mountMode = Math.min(mountMode, policyMode);
4109 }
4110 if (mountMode == Integer.MAX_VALUE) {
4111 return Zygote.MOUNT_EXTERNAL_NONE;
4112 }
4113 return mountMode;
4114 }
4115
Risanaec0ee72018-10-31 10:10:12 +09004116 @Override
4117 public void addResetListener(StorageManagerInternal.ResetListener listener) {
4118 synchronized (mResetListeners) {
4119 mResetListeners.add(listener);
4120 }
4121 }
4122
4123 public void onReset(IVold vold) {
4124 synchronized (mResetListeners) {
4125 for (StorageManagerInternal.ResetListener listener : mResetListeners) {
4126 listener.onReset(vold);
4127 }
4128 }
4129 }
4130
Martijn Coenen73918202019-12-09 17:02:44 +01004131 @Override
4132 public void resetUser(int userId) {
4133 // TODO(b/145931219): ideally, we only reset storage for the user in question,
4134 // but for now, reset everything.
4135 mHandler.obtainMessage(H_RESET).sendToTarget();
4136 }
4137
Svet Ganov6ee871e2015-07-10 14:29:33 -07004138 public boolean hasExternalStorage(int uid, String packageName) {
Amith Yamasani2bd5cff2015-07-22 14:42:31 -07004139 // No need to check for system uid. This avoids a deadlock between
4140 // PackageManagerService and AppOpsService.
4141 if (uid == Process.SYSTEM_UID) {
4142 return true;
4143 }
Sudheer Shanka3a0df3b2018-12-12 12:43:43 -08004144 if (ENABLE_ISOLATED_STORAGE) {
4145 return getMountMode(uid, packageName) != Zygote.MOUNT_EXTERNAL_NONE;
4146 }
Svet Ganov6ee871e2015-07-10 14:29:33 -07004147 // No locking - CopyOnWriteArrayList
4148 for (ExternalStorageMountPolicy policy : mPolicies) {
4149 final boolean policyHasStorage = policy.hasExternalStorage(uid, packageName);
4150 if (!policyHasStorage) {
4151 return false;
4152 }
4153 }
4154 return true;
4155 }
Sudheer Shankab1613982019-05-16 16:55:50 -07004156
4157 public void onAppOpsChanged(int code, int uid,
4158 @Nullable String packageName, int mode) {
4159 if (mode == MODE_ALLOWED && (code == OP_READ_EXTERNAL_STORAGE
4160 || code == OP_WRITE_EXTERNAL_STORAGE
4161 || code == OP_REQUEST_INSTALL_PACKAGES)) {
4162 final long token = Binder.clearCallingIdentity();
4163 try {
4164 final UserManagerInternal userManagerInternal =
4165 LocalServices.getService(UserManagerInternal.class);
4166 if (userManagerInternal.isUserInitialized(UserHandle.getUserId(uid))) {
4167 onExternalStoragePolicyChanged(uid, packageName);
4168 }
4169 } finally {
4170 Binder.restoreCallingIdentity(token);
4171 }
4172 }
4173 }
Svet Ganov6ee871e2015-07-10 14:29:33 -07004174 }
Jeff Sharkeyfa23c5a2011-08-09 21:44:24 -07004175}