blob: 19b0bf795393aabfda83b920f92d1c7bc8e280ef [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;
20import static android.Manifest.permission.WRITE_MEDIA_STORAGE;
21import static android.app.AppOpsManager.MODE_ALLOWED;
Jeff Sharkey11697f52018-12-13 10:14:42 -070022import static android.app.AppOpsManager.OP_LEGACY_STORAGE;
Sudheer Shanka3a0df3b2018-12-12 12:43:43 -080023import static android.app.AppOpsManager.OP_REQUEST_INSTALL_PACKAGES;
Jeff Sharkey11697f52018-12-13 10:14:42 -070024import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_AWARE;
25import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_UNAWARE;
26import static android.content.pm.PackageManager.MATCH_UNINSTALLED_PACKAGES;
Sudheer Shanka3a0df3b2018-12-12 12:43:43 -080027import static android.content.pm.PackageManager.PERMISSION_GRANTED;
Jeff Sharkey39466322018-12-05 19:19:52 -070028import static android.os.ParcelFileDescriptor.MODE_READ_WRITE;
Jeff Sharkey0095a822018-02-15 13:06:53 -070029import static android.os.storage.OnObbStateChangeListener.ERROR_ALREADY_MOUNTED;
30import static android.os.storage.OnObbStateChangeListener.ERROR_COULD_NOT_MOUNT;
31import static android.os.storage.OnObbStateChangeListener.ERROR_COULD_NOT_UNMOUNT;
32import static android.os.storage.OnObbStateChangeListener.ERROR_INTERNAL;
33import static android.os.storage.OnObbStateChangeListener.ERROR_NOT_MOUNTED;
34import static android.os.storage.OnObbStateChangeListener.ERROR_PERMISSION_DENIED;
35import static android.os.storage.OnObbStateChangeListener.MOUNTED;
36import static android.os.storage.OnObbStateChangeListener.UNMOUNTED;
Jeff Sharkey5790af02018-08-13 17:42:54 -060037
Jeff Sharkey11697f52018-12-13 10:14:42 -070038import static com.android.internal.util.XmlUtils.readBooleanAttribute;
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -070039import static com.android.internal.util.XmlUtils.readIntAttribute;
Jeff Sharkeye8a4b662015-06-27 15:43:45 -070040import static com.android.internal.util.XmlUtils.readLongAttribute;
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -070041import static com.android.internal.util.XmlUtils.readStringAttribute;
Jeff Sharkey11697f52018-12-13 10:14:42 -070042import static com.android.internal.util.XmlUtils.writeBooleanAttribute;
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -070043import 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;
Sudheer Shanka87915d62018-11-06 10:57:35 -080053import 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 Shanka0a541a52018-07-31 13:21:11 -070064import android.content.pm.ApplicationInfo;
Sudheer Shanka3a0df3b2018-12-12 12:43:43 -080065import android.content.pm.IPackageManager;
Jeff Sharkey275e3e42015-04-24 16:10:32 -070066import android.content.pm.IPackageMoveObserver;
Jeff Sharkey11697f52018-12-13 10:14:42 -070067import android.content.pm.PackageInfo;
Jeff Sharkey275e3e42015-04-24 16:10:32 -070068import android.content.pm.PackageManager;
Sudheer Shanka0a541a52018-07-31 13:21:11 -070069import android.content.pm.PackageManagerInternal;
Jeff Sharkey14cbe522015-07-08 14:06:37 -070070import android.content.pm.ProviderInfo;
Jeff Sharkeybcd262d2015-06-10 09:41:17 -070071import android.content.pm.UserInfo;
Elliott Hughesf839b4f2014-09-26 12:30:47 -070072import android.content.res.Configuration;
Kenny Root02c87302010-07-01 08:10:18 -070073import android.content.res.ObbInfo;
Daniel Colascione766b6322018-01-08 19:10:36 -080074import android.database.ContentObserver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080075import android.net.Uri;
Kenny Root02c87302010-07-01 08:10:18 -070076import android.os.Binder;
Jeff Sharkey4c099d02015-05-15 13:45:00 -070077import android.os.DropBoxManager;
Kenny Roota02b8b02010-08-05 16:14:17 -070078import android.os.Environment;
Jeff Sharkeyb049e212012-09-07 23:16:01 -070079import android.os.Environment.UserEnvironment;
Jeff Sharkey48877892015-03-18 11:27:19 -070080import android.os.FileUtils;
Suchi Amalapurapuc42e29e2010-02-22 16:03:53 -080081import android.os.Handler;
Dianne Hackbornefa92b22013-05-03 14:11:43 -070082import android.os.HandlerThread;
Kenny Roota02b8b02010-08-05 16:14:17 -070083import android.os.IBinder;
Jin Qian12690d52017-10-13 18:17:04 -070084import android.os.IStoraged;
Jeff Sharkey1019de92017-09-06 13:47:03 -060085import android.os.IVold;
Jeff Sharkey8058fe62017-09-13 11:50:33 -060086import android.os.IVoldListener;
Jeff Sharkeyb302c542017-09-15 12:57:59 -060087import android.os.IVoldTaskListener;
Daniel Sandler5f27ef42010-03-16 15:42:02 -040088import android.os.Looper;
Suchi Amalapurapuc42e29e2010-02-22 16:03:53 -080089import android.os.Message;
Daichi Hirono9e8d9e22015-11-13 14:37:00 +090090import android.os.ParcelFileDescriptor;
Jeff Sharkey500ce9e2017-02-12 02:39:24 -070091import android.os.ParcelableException;
Jeff Sharkeyb302c542017-09-15 12:57:59 -060092import android.os.PersistableBundle;
Jeff Sharkeyce14cd02015-12-07 15:35:42 -070093import android.os.PowerManager;
Jeff Sharkey9527b222015-06-24 15:24:48 -070094import android.os.Process;
Jeff Sharkey7151a9a2015-04-04 15:22:37 -070095import android.os.RemoteCallbackList;
San Mehat4270e1e2010-01-29 05:32:19 -080096import android.os.RemoteException;
Suchi Amalapurapufd3530f2010-01-18 00:15:59 -080097import android.os.ServiceManager;
Paul Crowleyfc0b5192018-07-02 13:58:10 -070098import android.os.ServiceSpecificException;
Jeff Sharkeyedcdaf62015-07-09 09:45:36 -070099import android.os.SystemClock;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800100import android.os.SystemProperties;
Dianne Hackbornf02b60a2012-08-16 10:48:27 -0700101import android.os.UserHandle;
Emily Bernier92aa5a22014-07-07 10:11:48 -0400102import android.os.UserManager;
Sudheer Shanka0a541a52018-07-31 13:21:11 -0700103import android.os.UserManagerInternal;
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -0700104import android.os.storage.DiskInfo;
Kenny Roota02b8b02010-08-05 16:14:17 -0700105import android.os.storage.IObbActionListener;
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -0700106import android.os.storage.IStorageEventListener;
Sudheer Shanka2250d562016-11-07 15:41:02 -0800107import android.os.storage.IStorageManager;
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -0700108import android.os.storage.IStorageShutdownObserver;
Kenny Rootaf9d6672010-10-08 09:21:39 -0700109import android.os.storage.OnObbStateChangeListener;
Paul Lawrence46791e72014-04-03 09:10:26 -0700110import android.os.storage.StorageManager;
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -0700111import android.os.storage.StorageManagerInternal;
Mike Lockwood2f6a3882011-05-09 19:08:06 -0700112import android.os.storage.StorageVolume;
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -0700113import android.os.storage.VolumeInfo;
Jeff Sharkeyb36586a2015-04-27 08:42:28 -0700114import android.os.storage.VolumeRecord;
Jeff Sharkey5d0c55c2019-01-24 14:32:31 -0700115import android.provider.DeviceConfig;
Jeff Sharkey14cbe522015-07-08 14:06:37 -0700116import android.provider.MediaStore;
Jeff Sharkeye8a4b662015-06-27 15:43:45 -0700117import android.provider.Settings;
Inseob Kimc1246e62018-11-08 13:13:54 +0900118import android.sysprop.VoldProperties;
Jason parksf7b3cd42011-01-27 09:28:25 -0600119import android.text.TextUtils;
Jeff Sharkey1783f142015-04-17 10:52:51 -0700120import android.text.format.DateUtils;
Jeff Sharkey48877892015-03-18 11:27:19 -0700121import android.util.ArrayMap;
Sudheer Shanka0a541a52018-07-31 13:21:11 -0700122import android.util.ArraySet;
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700123import android.util.AtomicFile;
Jeff Sharkey9f2dc052018-01-07 16:47:31 -0700124import android.util.DataUnit;
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -0700125import android.util.Log;
Felipe Leme281389a2016-10-10 17:12:20 -0700126import android.util.Pair;
San Mehata5078592010-03-25 09:36:54 -0700127import android.util.Slog;
Sudheer Shanka0a541a52018-07-31 13:21:11 -0700128import android.util.SparseArray;
Jeff Sharkeye8a4b662015-06-27 15:43:45 -0700129import android.util.TimeUtils;
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700130import android.util.Xml;
Jeff Sharkey48877892015-03-18 11:27:19 -0700131
Jeff Sharkey8b2c3a142012-11-12 11:45:05 -0800132import com.android.internal.annotations.GuardedBy;
Sudheer Shankaff971bc2018-12-13 17:39:59 -0800133import com.android.internal.app.IAppOpsCallback;
Sudheer Shanka3a0df3b2018-12-12 12:43:43 -0800134import com.android.internal.app.IAppOpsService;
Daichi Hirono9fb00182016-11-08 14:12:17 +0900135import com.android.internal.os.AppFuseMount;
Jeff Sharkey1019de92017-09-06 13:47:03 -0600136import com.android.internal.os.BackgroundThread;
Daichi Hirono812c95d2017-02-08 16:20:20 +0900137import com.android.internal.os.FuseUnavailableMountException;
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700138import com.android.internal.os.SomeArgs;
Jeff Sharkey9527b222015-06-24 15:24:48 -0700139import com.android.internal.os.Zygote;
Jeff Sharkey48877892015-03-18 11:27:19 -0700140import com.android.internal.util.ArrayUtils;
Jeff Sharkey11697f52018-12-13 10:14:42 -0700141import com.android.internal.util.CollectionUtils;
Jeff Sharkeyfe9a53b2017-03-31 14:08:23 -0600142import com.android.internal.util.DumpUtils;
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700143import com.android.internal.util.FastXmlSerializer;
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -0800144import com.android.internal.util.HexDump;
Jeff Sharkey5aca2b82013-10-16 16:21:54 -0700145import com.android.internal.util.IndentingPrintWriter;
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700146import com.android.internal.util.Preconditions;
Jeff Sharkeyb9fe5372015-12-03 15:23:08 -0700147import com.android.internal.widget.LockPatternUtils;
Daichi Hirono9fb00182016-11-08 14:12:17 +0900148import com.android.server.storage.AppFuseBridge;
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;
Jeff Sharkey5790af02018-08-13 17:42:54 -0600184import java.util.regex.Matcher;
185import java.util.regex.Pattern;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800186
Kenny Root3b1abba2010-10-13 15:00:07 -0700187import javax.crypto.SecretKey;
188import javax.crypto.SecretKeyFactory;
189import javax.crypto.spec.PBEKeySpec;
190
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800191/**
Jeff Sharkey48877892015-03-18 11:27:19 -0700192 * Service responsible for various storage media. Connects to {@code vold} to
193 * watch for and manage dynamically added storage, such as SD cards and USB mass
194 * storage. Also decides how storage should be presented to users on the device.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800195 */
Jeff Sharkey9765e442017-12-14 22:15:14 -0700196class StorageManagerService extends IStorageManager.Stub
197 implements Watchdog.Monitor, ScreenObserver {
Jason parks5af0b912010-11-29 09:05:25 -0600198
Christopher Tated417d622013-08-19 16:14:25 -0700199 // Static direct instance pointer for the tightly-coupled idle service to use
Sudheer Shanka2250d562016-11-07 15:41:02 -0800200 static StorageManagerService sSelf = null;
Christopher Tated417d622013-08-19 16:14:25 -0700201
Daniel Colascione766b6322018-01-08 19:10:36 -0800202 /* Read during boot to decide whether to enable zram when available */
203 private static final String ZRAM_ENABLED_PROPERTY =
Sudheer Shanka0a541a52018-07-31 13:21:11 -0700204 "persist.sys.zram_enabled";
205
Jeff Sharkey10ec9d82018-11-28 14:52:45 -0700206 private static final boolean ENABLE_ISOLATED_STORAGE = StorageManager.hasIsolatedStorage();
Sudheer Shanka0a541a52018-07-31 13:21:11 -0700207
Jeff Sharkey36274992019-02-27 12:09:57 -0700208 private static final boolean ENABLE_LEGACY_GREYLIST = SystemProperties
209 .getBoolean(StorageManager.PROP_LEGACY_GREYLIST, true);
210
Jeff Sharkey56e62932015-03-21 20:41:00 -0700211 public static class Lifecycle extends SystemService {
Sudheer Shanka2250d562016-11-07 15:41:02 -0800212 private StorageManagerService mStorageManagerService;
Jeff Sharkey56e62932015-03-21 20:41:00 -0700213
214 public Lifecycle(Context context) {
215 super(context);
216 }
217
218 @Override
219 public void onStart() {
Sudheer Shanka2250d562016-11-07 15:41:02 -0800220 mStorageManagerService = new StorageManagerService(getContext());
221 publishBinderService("mount", mStorageManagerService);
222 mStorageManagerService.start();
Jeff Sharkey56e62932015-03-21 20:41:00 -0700223 }
224
225 @Override
226 public void onBootPhase(int phase) {
Jeff Sharkey11697f52018-12-13 10:14:42 -0700227 if (phase == SystemService.PHASE_SYSTEM_SERVICES_READY) {
228 mStorageManagerService.servicesReady();
229 } else if (phase == SystemService.PHASE_ACTIVITY_MANAGER_READY) {
Sudheer Shanka2250d562016-11-07 15:41:02 -0800230 mStorageManagerService.systemReady();
Yasuhiro Matsuda87a38b52015-07-24 22:10:16 +0900231 } else if (phase == SystemService.PHASE_BOOT_COMPLETED) {
Sudheer Shanka2250d562016-11-07 15:41:02 -0800232 mStorageManagerService.bootCompleted();
Jeff Sharkey56e62932015-03-21 20:41:00 -0700233 }
234 }
Jeff Sharkey48877892015-03-18 11:27:19 -0700235
236 @Override
Jeff Sharkeyab15c392016-05-05 11:45:01 -0600237 public void onSwitchUser(int userHandle) {
Sudheer Shanka2250d562016-11-07 15:41:02 -0800238 mStorageManagerService.mCurrentUserId = userHandle;
Jeff Sharkeyab15c392016-05-05 11:45:01 -0600239 }
240
241 @Override
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700242 public void onUnlockUser(int userHandle) {
Sudheer Shanka2250d562016-11-07 15:41:02 -0800243 mStorageManagerService.onUnlockUser(userHandle);
Jeff Sharkey48877892015-03-18 11:27:19 -0700244 }
245
246 @Override
247 public void onCleanupUser(int userHandle) {
Sudheer Shanka2250d562016-11-07 15:41:02 -0800248 mStorageManagerService.onCleanupUser(userHandle);
Jeff Sharkey48877892015-03-18 11:27:19 -0700249 }
Jeff Sharkey56e62932015-03-21 20:41:00 -0700250 }
251
Dianne Hackborn40e9f292012-11-27 19:12:23 -0800252 private static final boolean DEBUG_EVENTS = false;
Kenny Rootb7db2722011-01-25 16:39:35 -0800253 private static final boolean DEBUG_OBB = false;
Kenny Root02c87302010-07-01 08:10:18 -0700254
Jeff Sharkeyc3c72872018-06-06 15:35:53 -0600255 /**
256 * We now talk to vold over Binder, and it has its own internal lock to
257 * serialize certain calls. All long-running operations have been migrated
258 * to be async with callbacks, so we want watchdog to fire if vold wedges.
259 */
260 private static final boolean WATCHDOG_ENABLE = true;
Kenny Root07714d42011-08-17 17:49:28 -0700261
Jeff Sharkey00455bf2016-11-04 14:45:24 -0600262 /**
263 * Our goal is for all Android devices to be usable as development devices,
264 * which includes the new Direct Boot mode added in N. For devices that
265 * don't have native FBE support, we offer an emulation mode for developer
266 * testing purposes, but if it's prohibitively difficult to support this
267 * mode, it can be disabled for specific products using this flag.
268 */
269 private static final boolean EMULATE_FBE_SUPPORTED = true;
270
Sudheer Shanka2250d562016-11-07 15:41:02 -0800271 private static final String TAG = "StorageManagerService";
Jeff Sharkeye8a4b662015-06-27 15:43:45 -0700272
Jeff Sharkey9756d752015-05-14 21:07:42 -0700273 private static final String TAG_STORAGE_BENCHMARK = "storage_benchmark";
Jeff Sharkeye8a4b662015-06-27 15:43:45 -0700274 private static final String TAG_STORAGE_TRIM = "storage_trim";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800275
Jeff Sharkey275e3e42015-04-24 16:10:32 -0700276 /** Magic value sent by MoveTask.cpp */
277 private static final int MOVE_STATUS_COPY_FINISHED = 82;
278
Jeff Sharkey620b32b2015-04-23 19:36:02 -0700279 private static final int VERSION_INIT = 1;
280 private static final int VERSION_ADD_PRIMARY = 2;
Jeff Sharkeyfced5342015-05-10 14:53:34 -0700281 private static final int VERSION_FIX_PRIMARY = 3;
Jeff Sharkey620b32b2015-04-23 19:36:02 -0700282
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700283 private static final String TAG_VOLUMES = "volumes";
Jeff Sharkey620b32b2015-04-23 19:36:02 -0700284 private static final String ATTR_VERSION = "version";
285 private static final String ATTR_PRIMARY_STORAGE_UUID = "primaryStorageUuid";
Jeff Sharkey11697f52018-12-13 10:14:42 -0700286 private static final String ATTR_ISOLATED_STORAGE = "isolatedStorage";
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700287 private static final String TAG_VOLUME = "volume";
288 private static final String ATTR_TYPE = "type";
289 private static final String ATTR_FS_UUID = "fsUuid";
Jeff Sharkey5cc0df22015-06-17 19:44:05 -0700290 private static final String ATTR_PART_GUID = "partGuid";
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700291 private static final String ATTR_NICKNAME = "nickname";
292 private static final String ATTR_USER_FLAGS = "userFlags";
Jeff Sharkeye8a4b662015-06-27 15:43:45 -0700293 private static final String ATTR_CREATED_MILLIS = "createdMillis";
294 private static final String ATTR_LAST_TRIM_MILLIS = "lastTrimMillis";
295 private static final String ATTR_LAST_BENCH_MILLIS = "lastBenchMillis";
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700296
Jeff Sharkeyb36586a2015-04-27 08:42:28 -0700297 private final AtomicFile mSettingsFile;
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700298
Jeff Sharkey48877892015-03-18 11:27:19 -0700299 /**
300 * <em>Never</em> hold the lock while performing downcalls into vold, since
301 * unsolicited events can suddenly appear to update data structures.
302 */
Jeff Sharkey5f3e9342017-03-13 14:53:11 -0600303 private final Object mLock = LockGuard.installNewLock(LockGuard.INDEX_STORAGE);
Jeff Sharkey48877892015-03-18 11:27:19 -0700304
Sudheer Shanka0a541a52018-07-31 13:21:11 -0700305 /**
306 * Similar to {@link #mLock}, never hold this lock while performing downcalls into vold.
307 * Also, never hold this while calling into PackageManagerService since it is used in callbacks
308 * from PackageManagerService.
309 *
310 * If both {@link #mLock} and this lock need to be held, {@link #mLock} should be acquired
311 * before this.
312 *
313 * Use -PL suffix for methods that need to called with this lock held.
314 */
315 private final Object mPackagesLock = new Object();
316
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700317 /** Set of users that we know are unlocked. */
Jeff Sharkey48877892015-03-18 11:27:19 -0700318 @GuardedBy("mLock")
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700319 private int[] mLocalUnlockedUsers = EmptyArray.INT;
320 /** Set of users that system knows are unlocked. */
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -0800321 @GuardedBy("mLock")
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700322 private int[] mSystemUnlockedUsers = EmptyArray.INT;
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700323
324 /** Map from disk ID to disk */
Jeff Sharkey48877892015-03-18 11:27:19 -0700325 @GuardedBy("mLock")
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -0700326 private ArrayMap<String, DiskInfo> mDisks = new ArrayMap<>();
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700327 /** Map from volume ID to disk */
Jeff Sharkey48877892015-03-18 11:27:19 -0700328 @GuardedBy("mLock")
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700329 private final ArrayMap<String, VolumeInfo> mVolumes = new ArrayMap<>();
Jeff Sharkey48877892015-03-18 11:27:19 -0700330
Jeff Sharkeyb36586a2015-04-27 08:42:28 -0700331 /** Map from UUID to record */
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700332 @GuardedBy("mLock")
Jeff Sharkeyb36586a2015-04-27 08:42:28 -0700333 private ArrayMap<String, VolumeRecord> mRecords = new ArrayMap<>();
Jeff Sharkey620b32b2015-04-23 19:36:02 -0700334 @GuardedBy("mLock")
335 private String mPrimaryStorageUuid;
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700336
Jeff Sharkey11697f52018-12-13 10:14:42 -0700337 /** Flag indicating isolated storage state of last boot */
338 @GuardedBy("mLock")
339 private boolean mLastIsolatedStorage = false;
340
Jeff Sharkeyeba260d2015-04-19 14:35:16 -0700341 /** Map from disk ID to latches */
342 @GuardedBy("mLock")
343 private ArrayMap<String, CountDownLatch> mDiskScanLatches = new ArrayMap<>();
344
Jeff Sharkey275e3e42015-04-24 16:10:32 -0700345 @GuardedBy("mLock")
346 private IPackageMoveObserver mMoveCallback;
347 @GuardedBy("mLock")
348 private String mMoveTargetUuid;
349
Sudheer Shanka0a541a52018-07-31 13:21:11 -0700350 @GuardedBy("mPackagesLock")
351 private final SparseArray<ArraySet<String>> mPackages = new SparseArray<>();
352
Jeff Sharkeyab15c392016-05-05 11:45:01 -0600353 private volatile int mCurrentUserId = UserHandle.USER_SYSTEM;
354
Daichi Hirono9fb00182016-11-08 14:12:17 +0900355 /** Holding lock for AppFuse business */
356 private final Object mAppFuseLock = new Object();
357
358 @GuardedBy("mAppFuseLock")
359 private int mNextAppFuseName = 0;
360
361 @GuardedBy("mAppFuseLock")
Daichi Hironoe56740d2017-02-02 13:56:45 +0900362 private AppFuseBridge mAppFuseBridge = null;
Daichi Hirono9fb00182016-11-08 14:12:17 +0900363
Jeff Sharkeyef10ee02015-07-05 14:17:27 -0700364 private VolumeInfo findVolumeByIdOrThrow(String id) {
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700365 synchronized (mLock) {
366 final VolumeInfo vol = mVolumes.get(id);
367 if (vol != null) {
368 return vol;
369 }
370 }
371 throw new IllegalArgumentException("No volume found for ID " + id);
372 }
373
Jeff Sharkeyef10ee02015-07-05 14:17:27 -0700374 private String findVolumeIdForPathOrThrow(String path) {
Jeff Sharkey48877892015-03-18 11:27:19 -0700375 synchronized (mLock) {
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -0700376 for (int i = 0; i < mVolumes.size(); i++) {
377 final VolumeInfo vol = mVolumes.valueAt(i);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700378 if (vol.path != null && path.startsWith(vol.path)) {
379 return vol.id;
Jeff Sharkey48877892015-03-18 11:27:19 -0700380 }
381 }
382 }
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700383 throw new IllegalArgumentException("No volume found for path " + path);
Jeff Sharkey48877892015-03-18 11:27:19 -0700384 }
385
Jeff Sharkeye8a4b662015-06-27 15:43:45 -0700386 private VolumeRecord findRecordForPath(String path) {
387 synchronized (mLock) {
388 for (int i = 0; i < mVolumes.size(); i++) {
389 final VolumeInfo vol = mVolumes.valueAt(i);
390 if (vol.path != null && path.startsWith(vol.path)) {
391 return mRecords.get(vol.fsUuid);
392 }
393 }
394 }
395 return null;
396 }
397
398 private String scrubPath(String path) {
399 if (path.startsWith(Environment.getDataDirectory().getAbsolutePath())) {
400 return "internal";
401 }
402 final VolumeRecord rec = findRecordForPath(path);
403 if (rec == null || rec.createdMillis == 0) {
404 return "unknown";
405 } else {
406 return "ext:" + (int) ((System.currentTimeMillis() - rec.createdMillis)
407 / DateUtils.WEEK_IN_MILLIS) + "w";
408 }
409 }
410
Jeff Sharkeyef10ee02015-07-05 14:17:27 -0700411 private @Nullable VolumeInfo findStorageForUuid(String volumeUuid) {
Jeff Sharkey275e3e42015-04-24 16:10:32 -0700412 final StorageManager storage = mContext.getSystemService(StorageManager.class);
413 if (Objects.equals(StorageManager.UUID_PRIVATE_INTERNAL, volumeUuid)) {
Jeff Sharkeyef10ee02015-07-05 14:17:27 -0700414 return storage.findVolumeById(VolumeInfo.ID_EMULATED_INTERNAL);
Jeff Sharkey275e3e42015-04-24 16:10:32 -0700415 } else if (Objects.equals(StorageManager.UUID_PRIMARY_PHYSICAL, volumeUuid)) {
416 return storage.getPrimaryPhysicalVolume();
417 } else {
418 return storage.findEmulatedForPrivate(storage.findVolumeByUuid(volumeUuid));
419 }
420 }
421
Jeff Sharkeye8a4b662015-06-27 15:43:45 -0700422 private boolean shouldBenchmark() {
423 final long benchInterval = Settings.Global.getLong(mContext.getContentResolver(),
424 Settings.Global.STORAGE_BENCHMARK_INTERVAL, DateUtils.WEEK_IN_MILLIS);
Jeff Sharkeye83d8a92015-09-09 14:53:38 -0700425 if (benchInterval == -1) {
426 return false;
427 } else if (benchInterval == 0) {
428 return true;
429 }
430
Jeff Sharkeye8a4b662015-06-27 15:43:45 -0700431 synchronized (mLock) {
432 for (int i = 0; i < mVolumes.size(); i++) {
433 final VolumeInfo vol = mVolumes.valueAt(i);
434 final VolumeRecord rec = mRecords.get(vol.fsUuid);
Jeff Sharkeye83d8a92015-09-09 14:53:38 -0700435 if (vol.isMountedWritable() && rec != null) {
Jeff Sharkeye8a4b662015-06-27 15:43:45 -0700436 final long benchAge = System.currentTimeMillis() - rec.lastBenchMillis;
437 if (benchAge >= benchInterval) {
438 return true;
439 }
440 }
441 }
442 return false;
443 }
444 }
445
Jeff Sharkeyeba260d2015-04-19 14:35:16 -0700446 private CountDownLatch findOrCreateDiskScanLatch(String diskId) {
447 synchronized (mLock) {
448 CountDownLatch latch = mDiskScanLatches.get(diskId);
449 if (latch == null) {
450 latch = new CountDownLatch(1);
451 mDiskScanLatches.put(diskId, latch);
452 }
453 return latch;
454 }
455 }
456
Paul Lawrence8e397362014-01-27 15:22:30 -0800457 /** List of crypto types.
458 * These must match CRYPT_TYPE_XXX in cryptfs.h AND their
459 * corresponding commands in CommandListener.cpp */
460 public static final String[] CRYPTO_TYPES
461 = { "password", "default", "pattern", "pin" };
462
Brian Carlstrom7395a8a2014-04-28 22:11:01 -0700463 private final Context mContext;
Jeff Sharkey5d0c55c2019-01-24 14:32:31 -0700464 private final ContentResolver mResolver;
Jeff Sharkeycd575992016-03-29 14:12:49 -0600465
Jeff Sharkey1019de92017-09-06 13:47:03 -0600466 private volatile IVold mVold;
Jin Qian12690d52017-10-13 18:17:04 -0700467 private volatile IStoraged mStoraged;
Jeff Sharkey1019de92017-09-06 13:47:03 -0600468
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700469 private volatile boolean mSystemReady = false;
Yasuhiro Matsuda87a38b52015-07-24 22:10:16 +0900470 private volatile boolean mBootCompleted = false;
Jeff Sharkey48877892015-03-18 11:27:19 -0700471 private volatile boolean mDaemonConnected = false;
Jeff Sharkey9765e442017-12-14 22:15:14 -0700472 private volatile boolean mSecureKeyguardShowing = true;
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700473
Sudheer Shanka0a541a52018-07-31 13:21:11 -0700474 private PackageManagerInternal mPmInternal;
Jeff Sharkey5790af02018-08-13 17:42:54 -0600475 private UserManagerInternal mUmInternal;
Sudheer Shanka87915d62018-11-06 10:57:35 -0800476 private ActivityManagerInternal mAmInternal;
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700477
Sudheer Shanka3a0df3b2018-12-12 12:43:43 -0800478 private IPackageManager mIPackageManager;
479 private IAppOpsService mIAppOpsService;
480
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700481 private final Callbacks mCallbacks;
Jeff Sharkeyb9fe5372015-12-03 15:23:08 -0700482 private final LockPatternUtils mLockPatternUtils;
Jeff Sharkey48877892015-03-18 11:27:19 -0700483
San Mehat6cdd9c02010-02-09 14:45:20 -0800484 /**
Kenny Root3b1abba2010-10-13 15:00:07 -0700485 * The size of the crypto algorithm key in bits for OBB files. Currently
486 * Twofish is used which takes 128-bit keys.
487 */
488 private static final int CRYPTO_ALGORITHM_KEY_SIZE = 128;
489
490 /**
491 * The number of times to run SHA1 in the PBKDF2 function for OBB files.
492 * 1024 is reasonably secure and not too slow.
493 */
494 private static final int PBKDF2_HASH_ROUNDS = 1024;
495
496 /**
Kenny Roota02b8b02010-08-05 16:14:17 -0700497 * Mounted OBB tracking information. Used to track the current state of all
498 * OBBs.
Kenny Root02c87302010-07-01 08:10:18 -0700499 */
Kenny Root735de3b2010-09-30 14:11:39 -0700500 final private Map<IBinder, List<ObbState>> mObbMounts = new HashMap<IBinder, List<ObbState>>();
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700501
502 /** Map from raw paths to {@link ObbState}. */
Kenny Roota02b8b02010-08-05 16:14:17 -0700503 final private Map<String, ObbState> mObbPathToStateMap = new HashMap<String, ObbState>();
504
Svet Ganov6ee871e2015-07-10 14:29:33 -0700505 // Not guarded by a lock.
Sudheer Shanka2250d562016-11-07 15:41:02 -0800506 private final StorageManagerInternalImpl mStorageManagerInternal
507 = new StorageManagerInternalImpl();
Svet Ganov6ee871e2015-07-10 14:29:33 -0700508
Kenny Roota02b8b02010-08-05 16:14:17 -0700509 class ObbState implements IBinder.DeathRecipient {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700510 public ObbState(String rawPath, String canonicalPath, int callingUid,
Jeff Sharkey41cd6812017-09-11 10:32:17 -0600511 IObbActionListener token, int nonce, String volId) {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700512 this.rawPath = rawPath;
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700513 this.canonicalPath = canonicalPath;
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700514 this.ownerGid = UserHandle.getSharedAppGid(callingUid);
Kenny Rootaf9d6672010-10-08 09:21:39 -0700515 this.token = token;
516 this.nonce = nonce;
Jeff Sharkey41cd6812017-09-11 10:32:17 -0600517 this.volId = volId;
Kenny Roota02b8b02010-08-05 16:14:17 -0700518 }
519
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700520 final String rawPath;
521 final String canonicalPath;
Kenny Roota02b8b02010-08-05 16:14:17 -0700522
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700523 final int ownerGid;
Kenny Roota02b8b02010-08-05 16:14:17 -0700524
Kenny Rootaf9d6672010-10-08 09:21:39 -0700525 // Token of remote Binder caller
526 final IObbActionListener token;
527
528 // Identifier to pass back to the token
529 final int nonce;
Kenny Roota02b8b02010-08-05 16:14:17 -0700530
Jeff Sharkey41cd6812017-09-11 10:32:17 -0600531 String volId;
532
Kenny Root735de3b2010-09-30 14:11:39 -0700533 public IBinder getBinder() {
534 return token.asBinder();
535 }
536
Kenny Roota02b8b02010-08-05 16:14:17 -0700537 @Override
538 public void binderDied() {
539 ObbAction action = new UnmountObbAction(this, true);
540 mObbActionHandler.sendMessage(mObbActionHandler.obtainMessage(OBB_RUN_ACTION, action));
Kenny Root735de3b2010-09-30 14:11:39 -0700541 }
Kenny Roota02b8b02010-08-05 16:14:17 -0700542
Kenny Root5919ac62010-10-05 09:49:40 -0700543 public void link() throws RemoteException {
544 getBinder().linkToDeath(this, 0);
545 }
546
547 public void unlink() {
Kenny Root735de3b2010-09-30 14:11:39 -0700548 getBinder().unlinkToDeath(this, 0);
Kenny Roota02b8b02010-08-05 16:14:17 -0700549 }
Kenny Root38cf8862010-09-26 14:18:51 -0700550
551 @Override
552 public String toString() {
553 StringBuilder sb = new StringBuilder("ObbState{");
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700554 sb.append("rawPath=").append(rawPath);
555 sb.append(",canonicalPath=").append(canonicalPath);
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700556 sb.append(",ownerGid=").append(ownerGid);
557 sb.append(",token=").append(token);
558 sb.append(",binder=").append(getBinder());
Jeff Sharkey41cd6812017-09-11 10:32:17 -0600559 sb.append(",volId=").append(volId);
Kenny Root38cf8862010-09-26 14:18:51 -0700560 sb.append('}');
561 return sb.toString();
562 }
Kenny Roota02b8b02010-08-05 16:14:17 -0700563 }
564
565 // OBB Action Handler
566 final private ObbActionHandler mObbActionHandler;
567
568 // OBB action handler messages
569 private static final int OBB_RUN_ACTION = 1;
Sudheer Shanka25469aa2018-08-27 15:50:23 -0700570 private static final int OBB_FLUSH_MOUNT_STATE = 2;
Kenny Root02c87302010-07-01 08:10:18 -0700571
Christopher Tate7265abe2014-11-21 13:54:45 -0800572 // Last fstrim operation tracking
573 private static final String LAST_FSTRIM_FILE = "last-fstrim";
574 private final File mLastMaintenanceFile;
575 private long mLastMaintenance;
576
Kenny Root02c87302010-07-01 08:10:18 -0700577 // Handler messages
Jeff Sharkey48877892015-03-18 11:27:19 -0700578 private static final int H_SYSTEM_READY = 1;
579 private static final int H_DAEMON_CONNECTED = 2;
580 private static final int H_SHUTDOWN = 3;
581 private static final int H_FSTRIM = 4;
582 private static final int H_VOLUME_MOUNT = 5;
583 private static final int H_VOLUME_BROADCAST = 6;
Jeff Sharkeyabc3e852015-08-03 14:41:13 -0700584 private static final int H_INTERNAL_BROADCAST = 7;
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700585 private static final int H_VOLUME_UNMOUNT = 8;
Jeff Sharkey5a9bb742015-11-03 10:15:57 -0800586 private static final int H_PARTITION_FORGET = 9;
587 private static final int H_RESET = 10;
Jin Qiana85b9912017-10-17 15:48:18 -0700588 private static final int H_RUN_IDLE_MAINT = 11;
589 private static final int H_ABORT_IDLE_MAINT = 12;
Suchi Amalapurapu6ffce2e2010-03-08 14:48:40 -0800590
Sudheer Shanka2250d562016-11-07 15:41:02 -0800591 class StorageManagerServiceHandler extends Handler {
592 public StorageManagerServiceHandler(Looper looper) {
Jeff Sharkey48877892015-03-18 11:27:19 -0700593 super(looper);
Daniel Sandler5f27ef42010-03-16 15:42:02 -0400594 }
595
Jason parks5af0b912010-11-29 09:05:25 -0600596 @Override
Suchi Amalapurapuc42e29e2010-02-22 16:03:53 -0800597 public void handleMessage(Message msg) {
598 switch (msg.what) {
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700599 case H_SYSTEM_READY: {
Jeff Sharkey48877892015-03-18 11:27:19 -0700600 handleSystemReady();
601 break;
602 }
603 case H_DAEMON_CONNECTED: {
604 handleDaemonConnected();
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700605 break;
606 }
Christopher Tated417d622013-08-19 16:14:25 -0700607 case H_FSTRIM: {
Christopher Tated417d622013-08-19 16:14:25 -0700608 Slog.i(TAG, "Running fstrim idle maintenance");
Christopher Tate7265abe2014-11-21 13:54:45 -0800609
610 // Remember when we kicked it off
611 try {
612 mLastMaintenance = System.currentTimeMillis();
613 mLastMaintenanceFile.setLastModified(mLastMaintenance);
614 } catch (Exception e) {
615 Slog.e(TAG, "Unable to record last fstrim!");
616 }
617
Jeff Sharkeyb302c542017-09-15 12:57:59 -0600618 // TODO: Reintroduce shouldBenchmark() test
Jeff Sharkey7e19f532017-11-06 13:54:11 -0700619 fstrim(0, null);
Christopher Tate7265abe2014-11-21 13:54:45 -0800620
Christopher Tated417d622013-08-19 16:14:25 -0700621 // invoke the completion callback, if any
Jeff Sharkeye8a4b662015-06-27 15:43:45 -0700622 // TODO: fstrim is non-blocking, so remove this useless callback
Christopher Tated417d622013-08-19 16:14:25 -0700623 Runnable callback = (Runnable) msg.obj;
624 if (callback != null) {
625 callback.run();
626 }
627 break;
628 }
Jeff Sharkey48877892015-03-18 11:27:19 -0700629 case H_SHUTDOWN: {
Sudheer Shanka2250d562016-11-07 15:41:02 -0800630 final IStorageShutdownObserver obs = (IStorageShutdownObserver) msg.obj;
Jeff Sharkey48877892015-03-18 11:27:19 -0700631 boolean success = false;
632 try {
Jeff Sharkey54402792017-09-15 16:05:19 -0600633 mVold.shutdown();
634 success = true;
Jeff Sharkeyace874b2017-09-07 15:27:33 -0600635 } catch (Exception e) {
636 Slog.wtf(TAG, e);
Jeff Sharkey48877892015-03-18 11:27:19 -0700637 }
638 if (obs != null) {
639 try {
640 obs.onShutDownComplete(success ? 0 : -1);
Jeff Sharkeyace874b2017-09-07 15:27:33 -0600641 } catch (Exception ignored) {
Jeff Sharkey48877892015-03-18 11:27:19 -0700642 }
643 }
644 break;
645 }
646 case H_VOLUME_MOUNT: {
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -0700647 final VolumeInfo vol = (VolumeInfo) msg.obj;
Jeff Sharkey2e606d72015-07-27 14:19:54 -0700648 if (isMountDisallowed(vol)) {
649 Slog.i(TAG, "Ignoring mount " + vol.getId() + " due to policy");
650 break;
651 }
Sudheer Shanka3f0645b2018-09-18 13:07:59 -0700652 mount(vol);
Jeff Sharkey48877892015-03-18 11:27:19 -0700653 break;
654 }
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700655 case H_VOLUME_UNMOUNT: {
656 final VolumeInfo vol = (VolumeInfo) msg.obj;
Sudheer Shanka3f0645b2018-09-18 13:07:59 -0700657 unmount(vol);
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700658 break;
659 }
Jeff Sharkey48877892015-03-18 11:27:19 -0700660 case H_VOLUME_BROADCAST: {
661 final StorageVolume userVol = (StorageVolume) msg.obj;
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700662 final String envState = userVol.getState();
663 Slog.d(TAG, "Volume " + userVol.getId() + " broadcasting " + envState + " to "
Jeff Sharkey48877892015-03-18 11:27:19 -0700664 + userVol.getOwner());
665
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700666 final String action = VolumeInfo.getBroadcastForEnvironment(envState);
Jeff Sharkey48877892015-03-18 11:27:19 -0700667 if (action != null) {
668 final Intent intent = new Intent(action,
669 Uri.fromFile(userVol.getPathFile()));
670 intent.putExtra(StorageVolume.EXTRA_STORAGE_VOLUME, userVol);
Jeff Sharkey082f83b2017-03-26 14:34:47 -0600671 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT
672 | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
Jeff Sharkey48877892015-03-18 11:27:19 -0700673 mContext.sendBroadcastAsUser(intent, userVol.getOwner());
674 }
675 break;
676 }
Jeff Sharkeyabc3e852015-08-03 14:41:13 -0700677 case H_INTERNAL_BROADCAST: {
678 // Internal broadcasts aimed at system components, not for
679 // third-party apps.
680 final Intent intent = (Intent) msg.obj;
681 mContext.sendBroadcastAsUser(intent, UserHandle.ALL,
682 android.Manifest.permission.WRITE_MEDIA_STORAGE);
Jeff Sharkey5a9bb742015-11-03 10:15:57 -0800683 break;
684 }
685 case H_PARTITION_FORGET: {
Jeff Sharkeydb4b6192017-10-24 11:08:50 -0600686 final VolumeRecord rec = (VolumeRecord) msg.obj;
687 forgetPartition(rec.partGuid, rec.fsUuid);
Jeff Sharkey5a9bb742015-11-03 10:15:57 -0800688 break;
689 }
690 case H_RESET: {
691 resetIfReadyAndConnected();
692 break;
Jeff Sharkeyabc3e852015-08-03 14:41:13 -0700693 }
Jin Qiana85b9912017-10-17 15:48:18 -0700694 case H_RUN_IDLE_MAINT: {
695 Slog.i(TAG, "Running idle maintenance");
696 runIdleMaint((Runnable)msg.obj);
697 break;
698 }
699 case H_ABORT_IDLE_MAINT: {
700 Slog.i(TAG, "Aborting idle maintenance");
701 abortIdleMaint((Runnable)msg.obj);
702 break;
703 }
704
Suchi Amalapurapuc42e29e2010-02-22 16:03:53 -0800705 }
706 }
Jeff Sharkey48877892015-03-18 11:27:19 -0700707 }
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700708
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700709 private final Handler mHandler;
Suchi Amalapurapuc42e29e2010-02-22 16:03:53 -0800710
Jeff Sharkeybcd262d2015-06-10 09:41:17 -0700711 private BroadcastReceiver mUserReceiver = new BroadcastReceiver() {
712 @Override
713 public void onReceive(Context context, Intent intent) {
714 final String action = intent.getAction();
715 final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700716 Preconditions.checkArgument(userId >= 0);
Jeff Sharkeybcd262d2015-06-10 09:41:17 -0700717
718 try {
719 if (Intent.ACTION_USER_ADDED.equals(action)) {
720 final UserManager um = mContext.getSystemService(UserManager.class);
721 final int userSerialNumber = um.getUserSerialNumber(userId);
Jeff Sharkey54402792017-09-15 16:05:19 -0600722 mVold.onUserAdded(userId, userSerialNumber);
Jeff Sharkeybcd262d2015-06-10 09:41:17 -0700723 } else if (Intent.ACTION_USER_REMOVED.equals(action)) {
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700724 synchronized (mVolumes) {
725 final int size = mVolumes.size();
726 for (int i = 0; i < size; i++) {
727 final VolumeInfo vol = mVolumes.valueAt(i);
728 if (vol.mountUserId == userId) {
729 vol.mountUserId = UserHandle.USER_NULL;
730 mHandler.obtainMessage(H_VOLUME_UNMOUNT, vol).sendToTarget();
731 }
732 }
733 }
Jeff Sharkey54402792017-09-15 16:05:19 -0600734 mVold.onUserRemoved(userId);
Jeff Sharkeybcd262d2015-06-10 09:41:17 -0700735 }
Jeff Sharkeyace874b2017-09-07 15:27:33 -0600736 } catch (Exception e) {
737 Slog.wtf(TAG, e);
Jeff Sharkeybcd262d2015-06-10 09:41:17 -0700738 }
739 }
740 };
741
Jeff Sharkeyedcdaf62015-07-09 09:45:36 -0700742 private void waitForLatch(CountDownLatch latch, String condition, long timeoutMillis)
743 throws TimeoutException {
744 final long startMillis = SystemClock.elapsedRealtime();
Jeff Sharkeyeba260d2015-04-19 14:35:16 -0700745 while (true) {
Kenny Root51a573c2012-05-17 13:30:28 -0700746 try {
747 if (latch.await(5000, TimeUnit.MILLISECONDS)) {
San Mehat207e5382010-02-04 20:46:54 -0800748 return;
Kenny Root51a573c2012-05-17 13:30:28 -0700749 } else {
750 Slog.w(TAG, "Thread " + Thread.currentThread().getName()
Jeff Sharkey48877892015-03-18 11:27:19 -0700751 + " still waiting for " + condition + "...");
San Mehat207e5382010-02-04 20:46:54 -0800752 }
Kenny Root51a573c2012-05-17 13:30:28 -0700753 } catch (InterruptedException e) {
Jeff Sharkeyeba260d2015-04-19 14:35:16 -0700754 Slog.w(TAG, "Interrupt while waiting for " + condition);
San Mehat207e5382010-02-04 20:46:54 -0800755 }
Jeff Sharkeyedcdaf62015-07-09 09:45:36 -0700756 if (timeoutMillis > 0 && SystemClock.elapsedRealtime() > startMillis + timeoutMillis) {
757 throw new TimeoutException("Thread " + Thread.currentThread().getName()
758 + " gave up waiting for " + condition + " after " + timeoutMillis + "ms");
759 }
San Mehat207e5382010-02-04 20:46:54 -0800760 }
San Mehat1f6301e2010-01-07 22:40:27 -0800761 }
Kenny Root02c87302010-07-01 08:10:18 -0700762
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700763 private void handleSystemReady() {
Jeff Sharkey8924e872015-11-30 12:52:10 -0700764 initIfReadyAndConnected();
Jeff Sharkey5a9bb742015-11-03 10:15:57 -0800765 resetIfReadyAndConnected();
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700766
Jeff Sharkey48877892015-03-18 11:27:19 -0700767 // Start scheduling nominally-daily fstrim operations
Christopher Tate115afda2014-06-06 19:06:26 -0700768 MountServiceIdler.scheduleIdlePass(mContext);
Daniel Colascione766b6322018-01-08 19:10:36 -0800769
770 // Toggle zram-enable system property in response to settings
771 mContext.getContentResolver().registerContentObserver(
772 Settings.Global.getUriFor(Settings.Global.ZRAM_ENABLED),
773 false /*notifyForDescendants*/,
774 new ContentObserver(null /* current thread */) {
775 @Override
776 public void onChange(boolean selfChange) {
777 refreshZramSettings();
778 }
779 });
780 refreshZramSettings();
Jeff Sharkeyb0c363b22018-12-15 11:53:03 -0700781
Srinivas Paladuguc8261752019-01-09 10:54:52 -0800782 // Schedule zram writeback unless zram is disabled by persist.sys.zram_enabled
783 String zramPropValue = SystemProperties.get(ZRAM_ENABLED_PROPERTY);
784 if (!zramPropValue.equals("0")
785 && mContext.getResources().getBoolean(
786 com.android.internal.R.bool.config_zramWriteback)) {
787 ZramWriteback.scheduleZramWriteback(mContext);
788 }
Jeff Sharkeyb0c363b22018-12-15 11:53:03 -0700789 // Toggle isolated-enable system property in response to settings
790 mContext.getContentResolver().registerContentObserver(
791 Settings.Global.getUriFor(Settings.Global.ISOLATED_STORAGE_REMOTE),
792 false /*notifyForDescendants*/,
793 new ContentObserver(null /* current thread */) {
794 @Override
795 public void onChange(boolean selfChange) {
796 refreshIsolatedStorageSettings();
797 }
798 });
Jeff Sharkey5d0c55c2019-01-24 14:32:31 -0700799 // For now, simply clone property when it changes
800 DeviceConfig.addOnPropertyChangedListener(DeviceConfig.Storage.NAMESPACE,
801 mContext.getMainExecutor(), (namespace, name, value) -> {
Jeff Sharkey8b499a02019-01-28 13:31:50 -0700802 refreshIsolatedStorageSettings();
Jeff Sharkey5d0c55c2019-01-24 14:32:31 -0700803 });
Jeff Sharkeyb0c363b22018-12-15 11:53:03 -0700804 refreshIsolatedStorageSettings();
Daniel Colascione766b6322018-01-08 19:10:36 -0800805 }
806
807 /**
808 * Update the zram_enabled system property (which init reads to
809 * decide whether to enable zram) to reflect the zram_enabled
810 * preference (which we can change for experimentation purposes).
811 */
812 private void refreshZramSettings() {
813 String propertyValue = SystemProperties.get(ZRAM_ENABLED_PROPERTY);
814 if ("".equals(propertyValue)) {
815 return; // System doesn't have zram toggling support
816 }
817 String desiredPropertyValue =
818 Settings.Global.getInt(mContext.getContentResolver(),
819 Settings.Global.ZRAM_ENABLED,
820 1) != 0
821 ? "1" : "0";
822 if (!desiredPropertyValue.equals(propertyValue)) {
823 // Avoid redundant disk writes by setting only if we're
824 // changing the property value. There's no race: we're the
825 // sole writer.
826 SystemProperties.set(ZRAM_ENABLED_PROPERTY, desiredPropertyValue);
Srinivas Paladuguc8261752019-01-09 10:54:52 -0800827 // Schedule writeback only if zram is being enabled.
828 if (desiredPropertyValue.equals("1")
829 && mContext.getResources().getBoolean(
830 com.android.internal.R.bool.config_zramWriteback)) {
831 ZramWriteback.scheduleZramWriteback(mContext);
832 }
Daniel Colascione766b6322018-01-08 19:10:36 -0800833 }
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700834 }
835
Jeff Sharkeyb0c363b22018-12-15 11:53:03 -0700836 private void refreshIsolatedStorageSettings() {
Jeff Sharkey8b499a02019-01-28 13:31:50 -0700837 // Always copy value from newer DeviceConfig location
838 Settings.Global.putString(mResolver,
839 Settings.Global.ISOLATED_STORAGE_REMOTE,
840 DeviceConfig.getProperty(DeviceConfig.Storage.NAMESPACE,
841 DeviceConfig.Storage.ISOLATED_STORAGE_ENABLED));
842
Jeff Sharkeyb0c363b22018-12-15 11:53:03 -0700843 final int local = Settings.Global.getInt(mContext.getContentResolver(),
844 Settings.Global.ISOLATED_STORAGE_LOCAL, 0);
845 final int remote = Settings.Global.getInt(mContext.getContentResolver(),
846 Settings.Global.ISOLATED_STORAGE_REMOTE, 0);
847
848 // Walk down precedence chain; we prefer local settings first, then
849 // remote settings, before finally falling back to hard-coded default.
850 final boolean res;
851 if (local == -1) {
852 res = false;
853 } else if (local == 1) {
854 res = true;
855 } else if (remote == -1) {
856 res = false;
857 } else if (remote == 1) {
858 res = true;
859 } else {
Jeff Sharkey06376802019-02-11 12:20:02 -0700860 res = true;
Jeff Sharkeyb0c363b22018-12-15 11:53:03 -0700861 }
862
863 Slog.d(TAG, "Isolated storage local flag " + local + " and remote flag "
864 + remote + " resolved to " + res);
865 SystemProperties.set(StorageManager.PROP_ISOLATED_STORAGE, Boolean.toString(res));
866 }
867
Jeff Sharkey14cbe522015-07-08 14:06:37 -0700868 /**
869 * MediaProvider has a ton of code that makes assumptions about storage
870 * paths never changing, so we outright kill them to pick up new state.
871 */
872 @Deprecated
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700873 private void killMediaProvider(List<UserInfo> users) {
874 if (users == null) return;
875
Jeff Sharkeyb3cf9532015-07-17 15:12:39 -0700876 final long token = Binder.clearCallingIdentity();
877 try {
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700878 for (UserInfo user : users) {
879 // System user does not have media provider, so skip.
880 if (user.isSystemOnly()) continue;
881
Jeff Sharkey5790af02018-08-13 17:42:54 -0600882 final ProviderInfo provider = mPmInternal.resolveContentProvider(
883 MediaStore.AUTHORITY, PackageManager.MATCH_DIRECT_BOOT_AWARE
Jeff Sharkey8a372a02016-03-16 16:25:45 -0600884 | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
885 user.id);
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700886 if (provider != null) {
Sudheer Shankadc589ac2016-11-10 15:30:17 -0800887 final IActivityManager am = ActivityManager.getService();
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700888 try {
Jeff Sharkey85f449e2016-06-23 09:26:00 -0600889 am.killApplication(provider.applicationInfo.packageName,
890 UserHandle.getAppId(provider.applicationInfo.uid),
891 UserHandle.USER_ALL, "vold reset");
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700892 // We only need to run this once. It will kill all users' media processes.
893 break;
894 } catch (RemoteException e) {
895 }
Jeff Sharkeyb3cf9532015-07-17 15:12:39 -0700896 }
Jeff Sharkey14cbe522015-07-08 14:06:37 -0700897 }
Jeff Sharkeyb3cf9532015-07-17 15:12:39 -0700898 } finally {
899 Binder.restoreCallingIdentity(token);
Jeff Sharkey14cbe522015-07-08 14:06:37 -0700900 }
901 }
902
Andreas Gampea36dc622018-02-05 17:19:22 -0800903 @GuardedBy("mLock")
Jeff Sharkey5a9bb742015-11-03 10:15:57 -0800904 private void addInternalVolumeLocked() {
Amith Yamasania7892482015-08-07 11:09:05 -0700905 // Create a stub volume that represents internal storage
906 final VolumeInfo internal = new VolumeInfo(VolumeInfo.ID_PRIVATE_INTERNAL,
907 VolumeInfo.TYPE_PRIVATE, null, null);
908 internal.state = VolumeInfo.STATE_MOUNTED;
909 internal.path = Environment.getDataDirectory().getAbsolutePath();
910 mVolumes.put(internal.id, internal);
911 }
912
Jeff Sharkey8924e872015-11-30 12:52:10 -0700913 private void initIfReadyAndConnected() {
914 Slog.d(TAG, "Thinking about init, mSystemReady=" + mSystemReady
915 + ", mDaemonConnected=" + mDaemonConnected);
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700916 if (mSystemReady && mDaemonConnected
Paul Lawrence20be5d62016-02-26 13:51:17 -0800917 && !StorageManager.isFileEncryptedNativeOnly()) {
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700918 // When booting a device without native support, make sure that our
919 // user directories are locked or unlocked based on the current
920 // emulation status.
Paul Lawrence20be5d62016-02-26 13:51:17 -0800921 final boolean initLocked = StorageManager.isFileEncryptedEmulatedOnly();
Paul Crowleyd94ab732016-02-15 06:44:51 +0000922 Slog.d(TAG, "Setting up emulation state, initlocked=" + initLocked);
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700923 final List<UserInfo> users = mContext.getSystemService(UserManager.class).getUsers();
Jeff Sharkey8924e872015-11-30 12:52:10 -0700924 for (UserInfo user : users) {
925 try {
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700926 if (initLocked) {
Jeff Sharkey54402792017-09-15 16:05:19 -0600927 mVold.lockUserKey(user.id);
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700928 } else {
Jeff Sharkey54402792017-09-15 16:05:19 -0600929 mVold.unlockUserKey(user.id, user.serialNumber, encodeBytes(null),
930 encodeBytes(null));
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700931 }
Jeff Sharkey43e12112017-09-12 16:31:45 -0600932 } catch (Exception e) {
933 Slog.wtf(TAG, e);
Jeff Sharkey8924e872015-11-30 12:52:10 -0700934 }
935 }
936 }
937 }
938
Jeff Sharkey5a9bb742015-11-03 10:15:57 -0800939 private void resetIfReadyAndConnected() {
Jeff Sharkey48877892015-03-18 11:27:19 -0700940 Slog.d(TAG, "Thinking about reset, mSystemReady=" + mSystemReady
941 + ", mDaemonConnected=" + mDaemonConnected);
942 if (mSystemReady && mDaemonConnected) {
Jeff Sharkey5a9bb742015-11-03 10:15:57 -0800943 final List<UserInfo> users = mContext.getSystemService(UserManager.class).getUsers();
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700944 killMediaProvider(users);
Jeff Sharkey14cbe522015-07-08 14:06:37 -0700945
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700946 final int[] systemUnlockedUsers;
Jeff Sharkey5a9bb742015-11-03 10:15:57 -0800947 synchronized (mLock) {
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700948 systemUnlockedUsers = mSystemUnlockedUsers;
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700949
Jeff Sharkey5a9bb742015-11-03 10:15:57 -0800950 mDisks.clear();
951 mVolumes.clear();
952
953 addInternalVolumeLocked();
954 }
Jeff Sharkey59d577a2015-04-11 21:27:21 -0700955
Jeff Sharkey48877892015-03-18 11:27:19 -0700956 try {
Jeff Sharkey54402792017-09-15 16:05:19 -0600957 mVold.reset();
Jeff Sharkeybcd262d2015-06-10 09:41:17 -0700958
959 // Tell vold about all existing and started users
Jeff Sharkeybcd262d2015-06-10 09:41:17 -0700960 for (UserInfo user : users) {
Jeff Sharkey54402792017-09-15 16:05:19 -0600961 mVold.onUserAdded(user.id, user.serialNumber);
Jeff Sharkeybcd262d2015-06-10 09:41:17 -0700962 }
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700963 for (int userId : systemUnlockedUsers) {
Sudheer Shanka2ac25a92018-10-25 10:59:32 -0700964 sendUserStartedCallback(userId);
Jin Qian12690d52017-10-13 18:17:04 -0700965 mStoraged.onUserStarted(userId);
Jeff Sharkey50a05452015-04-29 11:24:52 -0700966 }
Jeff Sharkey9765e442017-12-14 22:15:14 -0700967 mVold.onSecureKeyguardStateChanged(mSecureKeyguardShowing);
Risanaec0ee72018-10-31 10:10:12 +0900968 mStorageManagerInternal.onReset(mVold);
Jeff Sharkeyace874b2017-09-07 15:27:33 -0600969 } catch (Exception e) {
970 Slog.wtf(TAG, e);
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700971 }
972 }
Jeff Sharkey48877892015-03-18 11:27:19 -0700973 }
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700974
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700975 private void onUnlockUser(int userId) {
976 Slog.d(TAG, "onUnlockUser " + userId);
Jeff Sharkey48877892015-03-18 11:27:19 -0700977
978 // We purposefully block here to make sure that user-specific
979 // staging area is ready so it's ready for zygote-forked apps to
980 // bind mount against.
981 try {
Sudheer Shanka2ac25a92018-10-25 10:59:32 -0700982 sendUserStartedCallback(userId);
Jin Qian12690d52017-10-13 18:17:04 -0700983 mStoraged.onUserStarted(userId);
Jeff Sharkeyace874b2017-09-07 15:27:33 -0600984 } catch (Exception e) {
985 Slog.wtf(TAG, e);
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700986 }
Jeff Sharkey48877892015-03-18 11:27:19 -0700987
988 // Record user as started so newly mounted volumes kick off events
989 // correctly, then synthesize events for any already-mounted volumes.
yuanhuihuiefd1f122016-07-13 21:21:03 +0800990 synchronized (mLock) {
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -0700991 for (int i = 0; i < mVolumes.size(); i++) {
992 final VolumeInfo vol = mVolumes.valueAt(i);
Jeff Sharkey46349872015-07-28 10:49:47 -0700993 if (vol.isVisibleForRead(userId) && vol.isMountedReadable()) {
Svet Ganov6ee871e2015-07-10 14:29:33 -0700994 final StorageVolume userVol = vol.buildStorageVolume(mContext, userId, false);
Jeff Sharkey48877892015-03-18 11:27:19 -0700995 mHandler.obtainMessage(H_VOLUME_BROADCAST, userVol).sendToTarget();
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700996
Jeff Sharkey27de30d2015-04-18 16:20:27 -0700997 final String envState = VolumeInfo.getEnvironmentForState(vol.getState());
998 mCallbacks.notifyStorageStateChanged(userVol.getPath(), envState, envState);
Jeff Sharkey48877892015-03-18 11:27:19 -0700999 }
1000 }
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07001001 mSystemUnlockedUsers = ArrayUtils.appendInt(mSystemUnlockedUsers, userId);
Jeff Sharkey48877892015-03-18 11:27:19 -07001002 }
1003 }
1004
1005 private void onCleanupUser(int userId) {
1006 Slog.d(TAG, "onCleanupUser " + userId);
1007
1008 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06001009 mVold.onUserStopped(userId);
Jin Qian12690d52017-10-13 18:17:04 -07001010 mStoraged.onUserStopped(userId);
Jeff Sharkeyace874b2017-09-07 15:27:33 -06001011 } catch (Exception e) {
1012 Slog.wtf(TAG, e);
Jeff Sharkey48877892015-03-18 11:27:19 -07001013 }
1014
Sudheer Shanka2ac25a92018-10-25 10:59:32 -07001015 synchronized (mPackagesLock) {
1016 mPackages.delete(userId);
1017 }
1018
yuanhuihuiefd1f122016-07-13 21:21:03 +08001019 synchronized (mLock) {
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07001020 mSystemUnlockedUsers = ArrayUtils.removeInt(mSystemUnlockedUsers, userId);
Jeff Sharkey48877892015-03-18 11:27:19 -07001021 }
1022 }
Jeff Sharkeyb049e212012-09-07 23:16:01 -07001023
Sudheer Shanka2ac25a92018-10-25 10:59:32 -07001024 private void sendUserStartedCallback(int userId) throws Exception {
1025 if (!ENABLE_ISOLATED_STORAGE) {
1026 mVold.onUserStarted(userId, EmptyArray.STRING, EmptyArray.INT, EmptyArray.STRING);
1027 }
1028
1029 final String[] packages;
1030 final int[] appIds;
1031 final String[] sandboxIds;
1032 final SparseArray<String> sharedUserIds = mPmInternal.getAppsWithSharedUserIds();
1033 final List<ApplicationInfo> appInfos =
1034 mContext.getPackageManager().getInstalledApplicationsAsUser(
1035 PackageManager.MATCH_UNINSTALLED_PACKAGES, userId);
1036 synchronized (mPackagesLock) {
1037 final ArraySet<String> userPackages = new ArraySet<>();
1038 final ArrayMap<String, Integer> packageToAppId = new ArrayMap<>();
1039 for (int i = appInfos.size() - 1; i >= 0; --i) {
1040 final ApplicationInfo appInfo = appInfos.get(i);
1041 if (appInfo.isInstantApp()) {
1042 continue;
1043 }
1044 userPackages.add(appInfo.packageName);
1045 packageToAppId.put(appInfo.packageName, UserHandle.getAppId(appInfo.uid));
1046 }
1047 mPackages.put(userId, userPackages);
1048
1049 packages = new String[userPackages.size()];
1050 appIds = new int[userPackages.size()];
1051 sandboxIds = new String[userPackages.size()];
1052 for (int i = userPackages.size() - 1; i >= 0; --i) {
1053 packages[i] = userPackages.valueAt(i);
1054 appIds[i] = packageToAppId.get(packages[i]);
1055 sandboxIds[i] = getSandboxId(packages[i], sharedUserIds.get(appIds[i]));
1056 }
1057 }
1058 mVold.onUserStarted(userId, packages, appIds, sandboxIds);
1059 }
1060
Jeff Sharkey9765e442017-12-14 22:15:14 -07001061 @Override
1062 public void onAwakeStateChanged(boolean isAwake) {
1063 // Ignored
1064 }
1065
1066 @Override
1067 public void onKeyguardStateChanged(boolean isShowing) {
1068 // Push down current secure keyguard status so that we ignore malicious
1069 // USB devices while locked.
1070 mSecureKeyguardShowing = isShowing
1071 && mContext.getSystemService(KeyguardManager.class).isDeviceSecure();
1072 try {
1073 mVold.onSecureKeyguardStateChanged(mSecureKeyguardShowing);
1074 } catch (Exception e) {
1075 Slog.wtf(TAG, e);
1076 }
1077 }
1078
Christopher Tated417d622013-08-19 16:14:25 -07001079 void runIdleMaintenance(Runnable callback) {
1080 mHandler.sendMessage(mHandler.obtainMessage(H_FSTRIM, callback));
1081 }
1082
Christopher Tate7265abe2014-11-21 13:54:45 -08001083 // Binder entry point for kicking off an immediate fstrim
1084 @Override
1085 public void runMaintenance() {
Jeff Sharkey48877892015-03-18 11:27:19 -07001086 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
Christopher Tate7265abe2014-11-21 13:54:45 -08001087 runIdleMaintenance(null);
1088 }
1089
1090 @Override
1091 public long lastMaintenance() {
1092 return mLastMaintenance;
1093 }
1094
San Mehat4270e1e2010-01-29 05:32:19 -08001095 public void onDaemonConnected() {
Jeff Sharkey48877892015-03-18 11:27:19 -07001096 mDaemonConnected = true;
1097 mHandler.obtainMessage(H_DAEMON_CONNECTED).sendToTarget();
1098 }
1099
1100 private void handleDaemonConnected() {
Jeff Sharkey8924e872015-11-30 12:52:10 -07001101 initIfReadyAndConnected();
Jeff Sharkey5a9bb742015-11-03 10:15:57 -08001102 resetIfReadyAndConnected();
Jeff Sharkey48877892015-03-18 11:27:19 -07001103
Jeff Sharkey48877892015-03-18 11:27:19 -07001104 // On an encrypted device we can't see system properties yet, so pull
1105 // the system locale out of the mount service.
Inseob Kimc1246e62018-11-08 13:13:54 +09001106 if ("".equals(VoldProperties.encrypt_progress().orElse(""))) {
Jeff Sharkey48877892015-03-18 11:27:19 -07001107 copyLocaleFromMountService();
1108 }
San Mehat4270e1e2010-01-29 05:32:19 -08001109 }
1110
Elliott Hughesf839b4f2014-09-26 12:30:47 -07001111 private void copyLocaleFromMountService() {
1112 String systemLocale;
1113 try {
1114 systemLocale = getField(StorageManager.SYSTEM_LOCALE_KEY);
1115 } catch (RemoteException e) {
1116 return;
1117 }
1118 if (TextUtils.isEmpty(systemLocale)) {
1119 return;
1120 }
1121
1122 Slog.d(TAG, "Got locale " + systemLocale + " from mount service");
1123 Locale locale = Locale.forLanguageTag(systemLocale);
1124 Configuration config = new Configuration();
1125 config.setLocale(locale);
1126 try {
Sudheer Shankadc589ac2016-11-10 15:30:17 -08001127 ActivityManager.getService().updatePersistentConfiguration(config);
Elliott Hughesf839b4f2014-09-26 12:30:47 -07001128 } catch (RemoteException e) {
1129 Slog.e(TAG, "Error setting system locale from mount service", e);
1130 }
Elliott Hughes9c33f282014-10-13 12:39:56 -07001131
1132 // Temporary workaround for http://b/17945169.
1133 Slog.d(TAG, "Setting system properties to " + systemLocale + " from mount service");
Narayan Kamathd30dbb82015-01-15 14:48:15 +00001134 SystemProperties.set("persist.sys.locale", locale.toLanguageTag());
Elliott Hughesf839b4f2014-09-26 12:30:47 -07001135 }
1136
Jeff Sharkey8058fe62017-09-13 11:50:33 -06001137 private final IVoldListener mListener = new IVoldListener.Stub() {
1138 @Override
1139 public void onDiskCreated(String diskId, int flags) {
1140 synchronized (mLock) {
Jeff Sharkey901c0422018-04-20 13:11:20 -06001141 final String value = SystemProperties.get(StorageManager.PROP_ADOPTABLE);
1142 switch (value) {
1143 case "force_on":
1144 flags |= DiskInfo.FLAG_ADOPTABLE;
1145 break;
1146 case "force_off":
1147 flags &= ~DiskInfo.FLAG_ADOPTABLE;
1148 break;
Jeff Sharkey8058fe62017-09-13 11:50:33 -06001149 }
Jeff Sharkey8058fe62017-09-13 11:50:33 -06001150 mDisks.put(diskId, new DiskInfo(diskId, flags));
1151 }
1152 }
1153
1154 @Override
1155 public void onDiskScanned(String diskId) {
1156 synchronized (mLock) {
1157 final DiskInfo disk = mDisks.get(diskId);
1158 if (disk != null) {
1159 onDiskScannedLocked(disk);
1160 }
1161 }
1162 }
1163
1164 @Override
1165 public void onDiskMetadataChanged(String diskId, long sizeBytes, String label,
1166 String sysPath) {
1167 synchronized (mLock) {
1168 final DiskInfo disk = mDisks.get(diskId);
1169 if (disk != null) {
1170 disk.size = sizeBytes;
1171 disk.label = label;
1172 disk.sysPath = sysPath;
1173 }
1174 }
1175 }
1176
1177 @Override
1178 public void onDiskDestroyed(String diskId) {
1179 synchronized (mLock) {
1180 final DiskInfo disk = mDisks.remove(diskId);
1181 if (disk != null) {
1182 mCallbacks.notifyDiskDestroyed(disk);
1183 }
1184 }
1185 }
1186
1187 @Override
1188 public void onVolumeCreated(String volId, int type, String diskId, String partGuid) {
1189 synchronized (mLock) {
1190 final DiskInfo disk = mDisks.get(diskId);
1191 final VolumeInfo vol = new VolumeInfo(volId, type, disk, partGuid);
1192 mVolumes.put(volId, vol);
1193 onVolumeCreatedLocked(vol);
1194 }
1195 }
1196
1197 @Override
1198 public void onVolumeStateChanged(String volId, int state) {
1199 synchronized (mLock) {
1200 final VolumeInfo vol = mVolumes.get(volId);
1201 if (vol != null) {
1202 final int oldState = vol.state;
1203 final int newState = state;
1204 vol.state = newState;
1205 onVolumeStateChangedLocked(vol, oldState, newState);
1206 }
1207 }
1208 }
1209
1210 @Override
1211 public void onVolumeMetadataChanged(String volId, String fsType, String fsUuid,
1212 String fsLabel) {
1213 synchronized (mLock) {
1214 final VolumeInfo vol = mVolumes.get(volId);
1215 if (vol != null) {
1216 vol.fsType = fsType;
1217 vol.fsUuid = fsUuid;
1218 vol.fsLabel = fsLabel;
1219 }
1220 }
1221 }
1222
1223 @Override
1224 public void onVolumePathChanged(String volId, String path) {
1225 synchronized (mLock) {
1226 final VolumeInfo vol = mVolumes.get(volId);
1227 if (vol != null) {
1228 vol.path = path;
1229 }
1230 }
1231 }
1232
1233 @Override
1234 public void onVolumeInternalPathChanged(String volId, String internalPath) {
1235 synchronized (mLock) {
1236 final VolumeInfo vol = mVolumes.get(volId);
1237 if (vol != null) {
1238 vol.internalPath = internalPath;
1239 }
1240 }
1241 }
1242
1243 @Override
1244 public void onVolumeDestroyed(String volId) {
1245 synchronized (mLock) {
1246 mVolumes.remove(volId);
1247 }
1248 }
1249 };
1250
Andreas Gampea36dc622018-02-05 17:19:22 -08001251 @GuardedBy("mLock")
Jeff Sharkeyeba260d2015-04-19 14:35:16 -07001252 private void onDiskScannedLocked(DiskInfo disk) {
Jeff Sharkey620b32b2015-04-23 19:36:02 -07001253 int volumeCount = 0;
Jeff Sharkeyeba260d2015-04-19 14:35:16 -07001254 for (int i = 0; i < mVolumes.size(); i++) {
1255 final VolumeInfo vol = mVolumes.valueAt(i);
1256 if (Objects.equals(disk.id, vol.getDiskId())) {
Jeff Sharkey620b32b2015-04-23 19:36:02 -07001257 volumeCount++;
Jeff Sharkeyeba260d2015-04-19 14:35:16 -07001258 }
1259 }
1260
Jeff Sharkeyc7acac62015-06-12 16:16:56 -07001261 final Intent intent = new Intent(DiskInfo.ACTION_DISK_SCANNED);
Jeff Sharkey7732e1e2016-03-30 17:14:23 -06001262 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT
1263 | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
Jeff Sharkeyc7acac62015-06-12 16:16:56 -07001264 intent.putExtra(DiskInfo.EXTRA_DISK_ID, disk.id);
1265 intent.putExtra(DiskInfo.EXTRA_VOLUME_COUNT, volumeCount);
Jeff Sharkeyabc3e852015-08-03 14:41:13 -07001266 mHandler.obtainMessage(H_INTERNAL_BROADCAST, intent).sendToTarget();
Jeff Sharkeyc7acac62015-06-12 16:16:56 -07001267
1268 final CountDownLatch latch = mDiskScanLatches.remove(disk.id);
1269 if (latch != null) {
1270 latch.countDown();
1271 }
1272
Jeff Sharkeyf5a6bd72015-05-19 14:42:38 -07001273 disk.volumeCount = volumeCount;
Jeff Sharkey620b32b2015-04-23 19:36:02 -07001274 mCallbacks.notifyDiskScanned(disk, volumeCount);
Jeff Sharkeyeba260d2015-04-19 14:35:16 -07001275 }
1276
Andreas Gampea36dc622018-02-05 17:19:22 -08001277 @GuardedBy("mLock")
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07001278 private void onVolumeCreatedLocked(VolumeInfo vol) {
Jeff Sharkey5790af02018-08-13 17:42:54 -06001279 if (mPmInternal.isOnlyCoreApps()) {
Jeff Sharkey6855c482016-03-31 14:34:38 -06001280 Slog.d(TAG, "System booted in core-only mode; ignoring volume " + vol.getId());
1281 return;
1282 }
1283
Jeff Sharkey275e3e42015-04-24 16:10:32 -07001284 if (vol.type == VolumeInfo.TYPE_EMULATED) {
1285 final StorageManager storage = mContext.getSystemService(StorageManager.class);
1286 final VolumeInfo privateVol = storage.findPrivateForEmulated(vol);
1287
1288 if (Objects.equals(StorageManager.UUID_PRIVATE_INTERNAL, mPrimaryStorageUuid)
1289 && VolumeInfo.ID_PRIVATE_INTERNAL.equals(privateVol.id)) {
1290 Slog.v(TAG, "Found primary storage at " + vol);
1291 vol.mountFlags |= VolumeInfo.MOUNT_FLAG_PRIMARY;
1292 vol.mountFlags |= VolumeInfo.MOUNT_FLAG_VISIBLE;
1293 mHandler.obtainMessage(H_VOLUME_MOUNT, vol).sendToTarget();
1294
1295 } else if (Objects.equals(privateVol.fsUuid, mPrimaryStorageUuid)) {
1296 Slog.v(TAG, "Found primary storage at " + vol);
1297 vol.mountFlags |= VolumeInfo.MOUNT_FLAG_PRIMARY;
1298 vol.mountFlags |= VolumeInfo.MOUNT_FLAG_VISIBLE;
1299 mHandler.obtainMessage(H_VOLUME_MOUNT, vol).sendToTarget();
1300 }
Jeff Sharkeyb049e212012-09-07 23:16:01 -07001301
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07001302 } else if (vol.type == VolumeInfo.TYPE_PUBLIC) {
Jeff Sharkey275e3e42015-04-24 16:10:32 -07001303 // TODO: only look at first public partition
1304 if (Objects.equals(StorageManager.UUID_PRIMARY_PHYSICAL, mPrimaryStorageUuid)
1305 && vol.disk.isDefaultPrimary()) {
1306 Slog.v(TAG, "Found primary storage at " + vol);
Jeff Sharkey7e92ef32015-04-17 17:35:07 -07001307 vol.mountFlags |= VolumeInfo.MOUNT_FLAG_PRIMARY;
1308 vol.mountFlags |= VolumeInfo.MOUNT_FLAG_VISIBLE;
San Mehat4270e1e2010-01-29 05:32:19 -08001309 }
Jeff Sharkey7e92ef32015-04-17 17:35:07 -07001310
1311 // Adoptable public disks are visible to apps, since they meet
1312 // public API requirement of being in a stable location.
Jeff Sharkey275e3e42015-04-24 16:10:32 -07001313 if (vol.disk.isAdoptable()) {
Jeff Sharkey7e92ef32015-04-17 17:35:07 -07001314 vol.mountFlags |= VolumeInfo.MOUNT_FLAG_VISIBLE;
1315 }
1316
Jeff Sharkeyab15c392016-05-05 11:45:01 -06001317 vol.mountUserId = mCurrentUserId;
Jeff Sharkey48877892015-03-18 11:27:19 -07001318 mHandler.obtainMessage(H_VOLUME_MOUNT, vol).sendToTarget();
San Mehat4270e1e2010-01-29 05:32:19 -08001319
Jeff Sharkeyb2b9ab82015-04-05 21:10:42 -07001320 } else if (vol.type == VolumeInfo.TYPE_PRIVATE) {
1321 mHandler.obtainMessage(H_VOLUME_MOUNT, vol).sendToTarget();
1322
Risan05c41e62018-10-29 08:57:43 +09001323 } else if (vol.type == VolumeInfo.TYPE_STUB) {
1324 vol.mountUserId = mCurrentUserId;
1325 mHandler.obtainMessage(H_VOLUME_MOUNT, vol).sendToTarget();
San Mehat4270e1e2010-01-29 05:32:19 -08001326 } else {
Jeff Sharkey48877892015-03-18 11:27:19 -07001327 Slog.d(TAG, "Skipping automatic mounting of " + vol);
San Mehat4270e1e2010-01-29 05:32:19 -08001328 }
1329 }
1330
Jeff Sharkeye6c04f92015-04-18 21:38:05 -07001331 private boolean isBroadcastWorthy(VolumeInfo vol) {
1332 switch (vol.getType()) {
Jeff Sharkeyc7acac62015-06-12 16:16:56 -07001333 case VolumeInfo.TYPE_PRIVATE:
Jeff Sharkeye6c04f92015-04-18 21:38:05 -07001334 case VolumeInfo.TYPE_PUBLIC:
1335 case VolumeInfo.TYPE_EMULATED:
Risan05c41e62018-10-29 08:57:43 +09001336 case VolumeInfo.TYPE_STUB:
Jeff Sharkeye6c04f92015-04-18 21:38:05 -07001337 break;
1338 default:
1339 return false;
1340 }
1341
1342 switch (vol.getState()) {
1343 case VolumeInfo.STATE_MOUNTED:
1344 case VolumeInfo.STATE_MOUNTED_READ_ONLY:
1345 case VolumeInfo.STATE_EJECTING:
1346 case VolumeInfo.STATE_UNMOUNTED:
Jeff Sharkeyc7acac62015-06-12 16:16:56 -07001347 case VolumeInfo.STATE_UNMOUNTABLE:
Tony Mantlerf0d71052015-06-24 11:45:25 -07001348 case VolumeInfo.STATE_BAD_REMOVAL:
Jeff Sharkeye6c04f92015-04-18 21:38:05 -07001349 break;
1350 default:
1351 return false;
1352 }
1353
1354 return true;
1355 }
1356
Andreas Gampea36dc622018-02-05 17:19:22 -08001357 @GuardedBy("mLock")
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07001358 private void onVolumeStateChangedLocked(VolumeInfo vol, int oldState, int newState) {
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001359 // Remember that we saw this volume so we're ready to accept user
1360 // metadata, or so we can annoy them when a private volume is ejected
1361 if (vol.isMountedReadable() && !TextUtils.isEmpty(vol.fsUuid)) {
Jeff Sharkey5cc0df22015-06-17 19:44:05 -07001362 VolumeRecord rec = mRecords.get(vol.fsUuid);
1363 if (rec == null) {
1364 rec = new VolumeRecord(vol.type, vol.fsUuid);
1365 rec.partGuid = vol.partGuid;
Jeff Sharkeye8a4b662015-06-27 15:43:45 -07001366 rec.createdMillis = System.currentTimeMillis();
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001367 if (vol.type == VolumeInfo.TYPE_PRIVATE) {
1368 rec.nickname = vol.disk.getDescription();
1369 }
1370 mRecords.put(rec.fsUuid, rec);
1371 writeSettingsLocked();
Jeff Sharkey5cc0df22015-06-17 19:44:05 -07001372 } else {
1373 // Handle upgrade case where we didn't store partition GUID
1374 if (TextUtils.isEmpty(rec.partGuid)) {
1375 rec.partGuid = vol.partGuid;
1376 writeSettingsLocked();
1377 }
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001378 }
1379 }
1380
Jeff Sharkeye6c04f92015-04-18 21:38:05 -07001381 mCallbacks.notifyVolumeStateChanged(vol, oldState, newState);
1382
Yasuhiro Matsuda87a38b52015-07-24 22:10:16 +09001383 // Do not broadcast before boot has completed to avoid launching the
1384 // processes that receive the intent unnecessarily.
1385 if (mBootCompleted && isBroadcastWorthy(vol)) {
Jeff Sharkeye6c04f92015-04-18 21:38:05 -07001386 final Intent intent = new Intent(VolumeInfo.ACTION_VOLUME_STATE_CHANGED);
Jeff Sharkeyc7acac62015-06-12 16:16:56 -07001387 intent.putExtra(VolumeInfo.EXTRA_VOLUME_ID, vol.id);
1388 intent.putExtra(VolumeInfo.EXTRA_VOLUME_STATE, newState);
Tony Mantlerf0d71052015-06-24 11:45:25 -07001389 intent.putExtra(VolumeRecord.EXTRA_FS_UUID, vol.fsUuid);
Jeff Sharkey7732e1e2016-03-30 17:14:23 -06001390 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT
1391 | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
Jeff Sharkeyabc3e852015-08-03 14:41:13 -07001392 mHandler.obtainMessage(H_INTERNAL_BROADCAST, intent).sendToTarget();
Jeff Sharkeye6c04f92015-04-18 21:38:05 -07001393 }
Jeff Sharkeyb049e212012-09-07 23:16:01 -07001394
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001395 final String oldStateEnv = VolumeInfo.getEnvironmentForState(oldState);
1396 final String newStateEnv = VolumeInfo.getEnvironmentForState(newState);
Emily Bernier92aa5a22014-07-07 10:11:48 -04001397
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001398 if (!Objects.equals(oldStateEnv, newStateEnv)) {
1399 // Kick state changed event towards all started users. Any users
1400 // started after this point will trigger additional
1401 // user-specific broadcasts.
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07001402 for (int userId : mSystemUnlockedUsers) {
Jeff Sharkey46349872015-07-28 10:49:47 -07001403 if (vol.isVisibleForRead(userId)) {
Svet Ganov6ee871e2015-07-10 14:29:33 -07001404 final StorageVolume userVol = vol.buildStorageVolume(mContext, userId, false);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001405 mHandler.obtainMessage(H_VOLUME_BROADCAST, userVol).sendToTarget();
Jeff Sharkey48877892015-03-18 11:27:19 -07001406
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001407 mCallbacks.notifyStorageStateChanged(userVol.getPath(), oldStateEnv,
1408 newStateEnv);
San Mehat4270e1e2010-01-29 05:32:19 -08001409 }
1410 }
1411 }
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001412
Risan05c41e62018-10-29 08:57:43 +09001413 if ((vol.type == VolumeInfo.TYPE_PUBLIC || vol.type == VolumeInfo.TYPE_STUB)
1414 && vol.state == VolumeInfo.STATE_EJECTING) {
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001415 // TODO: this should eventually be handled by new ObbVolume state changes
1416 /*
1417 * Some OBBs might have been unmounted when this volume was
1418 * unmounted, so send a message to the handler to let it know to
1419 * remove those from the list of mounted OBBS.
1420 */
1421 mObbActionHandler.sendMessage(mObbActionHandler.obtainMessage(
1422 OBB_FLUSH_MOUNT_STATE, vol.path));
1423 }
Pavel Grafovce72ef02018-01-10 17:14:11 +00001424 maybeLogMediaMount(vol, newState);
1425 }
1426
1427 private void maybeLogMediaMount(VolumeInfo vol, int newState) {
1428 if (!SecurityLog.isLoggingEnabled()) {
1429 return;
1430 }
1431
1432 final DiskInfo disk = vol.getDisk();
1433 if (disk == null || (disk.flags & (DiskInfo.FLAG_SD | DiskInfo.FLAG_USB)) == 0) {
1434 return;
1435 }
1436
1437 // Sometimes there is a newline character.
1438 final String label = disk.label != null ? disk.label.trim() : "";
1439
1440 if (newState == VolumeInfo.STATE_MOUNTED
1441 || newState == VolumeInfo.STATE_MOUNTED_READ_ONLY) {
1442 SecurityLog.writeEvent(SecurityLog.TAG_MEDIA_MOUNT, vol.path, label);
1443 } else if (newState == VolumeInfo.STATE_UNMOUNTED
1444 || newState == VolumeInfo.STATE_BAD_REMOVAL) {
1445 SecurityLog.writeEvent(SecurityLog.TAG_MEDIA_UNMOUNT, vol.path, label);
1446 }
San Mehat4270e1e2010-01-29 05:32:19 -08001447 }
1448
Andreas Gampea36dc622018-02-05 17:19:22 -08001449 @GuardedBy("mLock")
Jeff Sharkey275e3e42015-04-24 16:10:32 -07001450 private void onMoveStatusLocked(int status) {
1451 if (mMoveCallback == null) {
1452 Slog.w(TAG, "Odd, status but no move requested");
1453 return;
1454 }
1455
1456 // TODO: estimate remaining time
1457 try {
Jeff Sharkey50a05452015-04-29 11:24:52 -07001458 mMoveCallback.onStatusChanged(-1, status, -1);
Jeff Sharkey275e3e42015-04-24 16:10:32 -07001459 } catch (RemoteException ignored) {
1460 }
1461
1462 // We've finished copying and we're about to clean up old data, so
1463 // remember that move was successful if we get rebooted
1464 if (status == MOVE_STATUS_COPY_FINISHED) {
1465 Slog.d(TAG, "Move to " + mMoveTargetUuid + " copy phase finshed; persisting");
1466
1467 mPrimaryStorageUuid = mMoveTargetUuid;
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001468 writeSettingsLocked();
Jeff Sharkey275e3e42015-04-24 16:10:32 -07001469 }
1470
1471 if (PackageManager.isMoveStatusFinished(status)) {
1472 Slog.d(TAG, "Move to " + mMoveTargetUuid + " finished with status " + status);
1473
1474 mMoveCallback = null;
1475 mMoveTargetUuid = null;
1476 }
1477 }
1478
Jeff Sharkey48877892015-03-18 11:27:19 -07001479 private void enforcePermission(String perm) {
1480 mContext.enforceCallingOrSelfPermission(perm, perm);
Mike Lockwooda5250c92011-05-23 13:44:04 -04001481 }
1482
Jeff Sharkey2e606d72015-07-27 14:19:54 -07001483 /**
1484 * Decide if volume is mountable per device policies.
1485 */
1486 private boolean isMountDisallowed(VolumeInfo vol) {
Philip P. Moltmannec3cbb22016-09-14 13:24:52 -07001487 UserManager userManager = mContext.getSystemService(UserManager.class);
1488
1489 boolean isUsbRestricted = false;
1490 if (vol.disk != null && vol.disk.isUsb()) {
1491 isUsbRestricted = userManager.hasUserRestriction(UserManager.DISALLOW_USB_FILE_TRANSFER,
Jeff Sharkey2e606d72015-07-27 14:19:54 -07001492 Binder.getCallingUserHandle());
Emily Bernier92aa5a22014-07-07 10:11:48 -04001493 }
Philip P. Moltmannec3cbb22016-09-14 13:24:52 -07001494
1495 boolean isTypeRestricted = false;
Risan05c41e62018-10-29 08:57:43 +09001496 if (vol.type == VolumeInfo.TYPE_PUBLIC || vol.type == VolumeInfo.TYPE_PRIVATE
1497 || vol.type == VolumeInfo.TYPE_STUB) {
Philip P. Moltmannec3cbb22016-09-14 13:24:52 -07001498 isTypeRestricted = userManager
1499 .hasUserRestriction(UserManager.DISALLOW_MOUNT_PHYSICAL_MEDIA,
1500 Binder.getCallingUserHandle());
1501 }
1502
1503 return isUsbRestricted || isTypeRestricted;
Emily Bernier92aa5a22014-07-07 10:11:48 -04001504 }
1505
Amith Yamasani462ac3a2015-06-30 14:21:01 -07001506 private void enforceAdminUser() {
1507 UserManager um = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
1508 final int callingUserId = UserHandle.getCallingUserId();
1509 boolean isAdmin;
1510 long token = Binder.clearCallingIdentity();
1511 try {
1512 isAdmin = um.getUserInfo(callingUserId).isAdmin();
1513 } finally {
1514 Binder.restoreCallingIdentity(token);
1515 }
1516 if (!isAdmin) {
1517 throw new SecurityException("Only admin users can adopt sd cards");
1518 }
1519 }
1520
Jeff Sharkeyb049e212012-09-07 23:16:01 -07001521 /**
Sudheer Shanka2250d562016-11-07 15:41:02 -08001522 * Constructs a new StorageManagerService instance
San Mehat207e5382010-02-04 20:46:54 -08001523 *
1524 * @param context Binder context for this service
1525 */
Sudheer Shanka2250d562016-11-07 15:41:02 -08001526 public StorageManagerService(Context context) {
Christopher Tated417d622013-08-19 16:14:25 -07001527 sSelf = this;
1528
Jeff Sharkey342b4bf2018-12-18 11:12:40 -07001529 // Snapshot feature flag used for this boot
1530 SystemProperties.set(StorageManager.PROP_ISOLATED_STORAGE_SNAPSHOT, Boolean.toString(
Jeff Sharkey06376802019-02-11 12:20:02 -07001531 SystemProperties.getBoolean(StorageManager.PROP_ISOLATED_STORAGE, true)));
Jeff Sharkey342b4bf2018-12-18 11:12:40 -07001532
San Mehat207e5382010-02-04 20:46:54 -08001533 mContext = context;
Jeff Sharkey5d0c55c2019-01-24 14:32:31 -07001534 mResolver = mContext.getContentResolver();
1535
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001536 mCallbacks = new Callbacks(FgThread.get().getLooper());
Jeff Sharkeyb9fe5372015-12-03 15:23:08 -07001537 mLockPatternUtils = new LockPatternUtils(mContext);
San Mehat207e5382010-02-04 20:46:54 -08001538
Dianne Hackbornefa92b22013-05-03 14:11:43 -07001539 HandlerThread hthread = new HandlerThread(TAG);
1540 hthread.start();
Sudheer Shanka2250d562016-11-07 15:41:02 -08001541 mHandler = new StorageManagerServiceHandler(hthread.getLooper());
Daniel Sandler5f27ef42010-03-16 15:42:02 -04001542
Sudheer Shanka2250d562016-11-07 15:41:02 -08001543 // Add OBB Action Handler to StorageManagerService thread.
Dianne Hackborn8d044e82013-04-30 17:24:15 -07001544 mObbActionHandler = new ObbActionHandler(IoThread.get().getLooper());
Kenny Roota02b8b02010-08-05 16:14:17 -07001545
Christopher Tate7265abe2014-11-21 13:54:45 -08001546 // Initialize the last-fstrim tracking if necessary
1547 File dataDir = Environment.getDataDirectory();
1548 File systemDir = new File(dataDir, "system");
1549 mLastMaintenanceFile = new File(systemDir, LAST_FSTRIM_FILE);
1550 if (!mLastMaintenanceFile.exists()) {
1551 // Not setting mLastMaintenance here means that we will force an
1552 // fstrim during reboot following the OTA that installs this code.
1553 try {
1554 (new FileOutputStream(mLastMaintenanceFile)).close();
1555 } catch (IOException e) {
1556 Slog.e(TAG, "Unable to create fstrim record " + mLastMaintenanceFile.getPath());
1557 }
1558 } else {
1559 mLastMaintenance = mLastMaintenanceFile.lastModified();
1560 }
1561
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001562 mSettingsFile = new AtomicFile(
Dianne Hackborne17b4452018-01-10 13:15:40 -08001563 new File(Environment.getDataSystemDirectory(), "storage.xml"), "storage-settings");
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001564
1565 synchronized (mLock) {
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001566 readSettingsLocked();
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001567 }
1568
Sudheer Shanka2250d562016-11-07 15:41:02 -08001569 LocalServices.addService(StorageManagerInternal.class, mStorageManagerInternal);
Svet Ganov6ee871e2015-07-10 14:29:33 -07001570
Jeff Sharkeybcd262d2015-06-10 09:41:17 -07001571 final IntentFilter userFilter = new IntentFilter();
1572 userFilter.addAction(Intent.ACTION_USER_ADDED);
1573 userFilter.addAction(Intent.ACTION_USER_REMOVED);
1574 mContext.registerReceiver(mUserReceiver, userFilter, null, mHandler);
1575
Jeff Sharkey5a9bb742015-11-03 10:15:57 -08001576 synchronized (mLock) {
1577 addInternalVolumeLocked();
1578 }
Amith Yamasania7892482015-08-07 11:09:05 -07001579
Kenny Root07714d42011-08-17 17:49:28 -07001580 // Add ourself to the Watchdog monitors if enabled.
1581 if (WATCHDOG_ENABLE) {
1582 Watchdog.getInstance().addMonitor(this);
1583 }
San Mehat207e5382010-02-04 20:46:54 -08001584 }
1585
Jeff Sharkeycd575992016-03-29 14:12:49 -06001586 private void start() {
Jeff Sharkey1019de92017-09-06 13:47:03 -06001587 connect();
Jeff Sharkeycd575992016-03-29 14:12:49 -06001588 }
1589
Sudheer Shanka0a541a52018-07-31 13:21:11 -07001590 private static String getSandboxId(String packageName, String sharedUserId) {
Sudheer Shankad68bd602018-11-13 17:43:39 -08001591 return sharedUserId == null
1592 ? packageName : StorageManager.SHARED_SANDBOX_PREFIX + sharedUserId;
Sudheer Shanka0a541a52018-07-31 13:21:11 -07001593 }
Sudheer Shanka0a541a52018-07-31 13:21:11 -07001594
Jeff Sharkey1019de92017-09-06 13:47:03 -06001595 private void connect() {
Jin Qian12690d52017-10-13 18:17:04 -07001596 IBinder binder = ServiceManager.getService("storaged");
1597 if (binder != null) {
1598 try {
1599 binder.linkToDeath(new DeathRecipient() {
1600 @Override
1601 public void binderDied() {
1602 Slog.w(TAG, "storaged died; reconnecting");
1603 mStoraged = null;
1604 connect();
1605 }
1606 }, 0);
1607 } catch (RemoteException e) {
1608 binder = null;
1609 }
1610 }
1611
1612 if (binder != null) {
1613 mStoraged = IStoraged.Stub.asInterface(binder);
1614 } else {
1615 Slog.w(TAG, "storaged not found; trying again");
1616 }
1617
1618 binder = ServiceManager.getService("vold");
Jeff Sharkey1019de92017-09-06 13:47:03 -06001619 if (binder != null) {
1620 try {
1621 binder.linkToDeath(new DeathRecipient() {
1622 @Override
1623 public void binderDied() {
1624 Slog.w(TAG, "vold died; reconnecting");
Jin Qian12690d52017-10-13 18:17:04 -07001625 mVold = null;
Jeff Sharkey1019de92017-09-06 13:47:03 -06001626 connect();
1627 }
1628 }, 0);
1629 } catch (RemoteException e) {
1630 binder = null;
1631 }
1632 }
1633
1634 if (binder != null) {
1635 mVold = IVold.Stub.asInterface(binder);
Jeff Sharkey8058fe62017-09-13 11:50:33 -06001636 try {
1637 mVold.setListener(mListener);
Jeff Sharkey8058fe62017-09-13 11:50:33 -06001638 } catch (RemoteException e) {
Jin Qian12690d52017-10-13 18:17:04 -07001639 mVold = null;
Jeff Sharkey8058fe62017-09-13 11:50:33 -06001640 Slog.w(TAG, "vold listener rejected; trying again", e);
1641 }
Jeff Sharkey1019de92017-09-06 13:47:03 -06001642 } else {
1643 Slog.w(TAG, "vold not found; trying again");
Jeff Sharkey1019de92017-09-06 13:47:03 -06001644 }
Jeff Sharkey8058fe62017-09-13 11:50:33 -06001645
Jin Qian12690d52017-10-13 18:17:04 -07001646 if (mStoraged == null || mVold == null) {
1647 BackgroundThread.getHandler().postDelayed(() -> {
1648 connect();
1649 }, DateUtils.SECOND_IN_MILLIS);
1650 } else {
1651 onDaemonConnected();
1652 }
Jeff Sharkey1019de92017-09-06 13:47:03 -06001653 }
1654
Jeff Sharkey11697f52018-12-13 10:14:42 -07001655 private void servicesReady() {
Sudheer Shankaff585072019-01-29 23:19:45 -08001656 mPmInternal = LocalServices.getService(PackageManagerInternal.class);
1657 mUmInternal = LocalServices.getService(UserManagerInternal.class);
1658 mAmInternal = LocalServices.getService(ActivityManagerInternal.class);
1659
1660 mIPackageManager = IPackageManager.Stub.asInterface(
1661 ServiceManager.getService("package"));
1662 mIAppOpsService = IAppOpsService.Stub.asInterface(
1663 ServiceManager.getService(Context.APP_OPS_SERVICE));
1664 try {
1665 mIAppOpsService.startWatchingMode(OP_REQUEST_INSTALL_PACKAGES, null, mAppOpsCallback);
1666 } catch (RemoteException e) {
1667 }
1668
Jeff Sharkey11697f52018-12-13 10:14:42 -07001669 synchronized (mLock) {
1670 final boolean thisIsolatedStorage = StorageManager.hasIsolatedStorage();
1671 if (mLastIsolatedStorage == thisIsolatedStorage) {
1672 // Nothing changed since last boot; keep rolling forward
1673 return;
1674 } else if (thisIsolatedStorage) {
1675 // This boot enables isolated storage; apply legacy behavior
1676 applyLegacyStorage();
1677 }
1678
1679 // Always remember the new state we just booted with
1680 writeSettingsLocked();
1681 }
1682 }
1683
1684 /**
1685 * If we're enabling isolated storage, we need to remember which existing
1686 * apps have already been using shared storage, and grant them legacy access
1687 * to keep them running smoothly.
1688 */
1689 private void applyLegacyStorage() {
1690 final AppOpsManager appOps = mContext.getSystemService(AppOpsManager.class);
1691 final UserManagerInternal um = LocalServices.getService(UserManagerInternal.class);
1692 for (int userId : um.getUserIds()) {
1693 final PackageManager pm;
1694 try {
1695 pm = mContext.createPackageContextAsUser(mContext.getPackageName(),
1696 0, UserHandle.of(userId)).getPackageManager();
1697 } catch (PackageManager.NameNotFoundException e) {
1698 throw new RuntimeException(e);
1699 }
1700
1701 final List<PackageInfo> pkgs = pm.getPackagesHoldingPermissions(new String[] {
1702 android.Manifest.permission.READ_EXTERNAL_STORAGE,
1703 android.Manifest.permission.WRITE_EXTERNAL_STORAGE
1704 }, MATCH_UNINSTALLED_PACKAGES | MATCH_DIRECT_BOOT_AWARE | MATCH_DIRECT_BOOT_UNAWARE);
1705 for (PackageInfo pkg : pkgs) {
1706 final int uid = pkg.applicationInfo.uid;
1707 final String packageName = pkg.applicationInfo.packageName;
1708
1709 final long lastAccess = getLastAccessTime(appOps, uid, packageName, new int[] {
1710 AppOpsManager.OP_READ_EXTERNAL_STORAGE,
1711 AppOpsManager.OP_WRITE_EXTERNAL_STORAGE,
1712 });
1713
1714 Log.d(TAG, "Found " + uid + " " + packageName
1715 + " with granted storage access, last accessed " + lastAccess);
1716 if (lastAccess > 0) {
1717 appOps.setMode(AppOpsManager.OP_LEGACY_STORAGE,
1718 uid, packageName, AppOpsManager.MODE_ALLOWED);
1719 }
1720 }
1721 }
1722 }
1723
1724 private static long getLastAccessTime(AppOpsManager manager,
1725 int uid, String packageName, int[] ops) {
1726 long maxTime = 0;
1727 final List<AppOpsManager.PackageOps> pkgs = manager.getOpsForPackage(uid, packageName, ops);
Eugene Susla04d021c2018-12-17 14:49:59 -08001728 for (AppOpsManager.PackageOps pkg : CollectionUtils.emptyIfNull(pkgs)) {
1729 for (AppOpsManager.OpEntry op : CollectionUtils.emptyIfNull(pkg.getOps())) {
Svet Ganovaf189e32019-02-15 18:45:29 -08001730 maxTime = Math.max(maxTime, op.getLastAccessTime(
1731 AppOpsManager.OP_FLAGS_ALL_TRUSTED));
Jeff Sharkey11697f52018-12-13 10:14:42 -07001732 }
1733 }
1734 return maxTime;
1735 }
1736
Jeff Sharkey56e62932015-03-21 20:41:00 -07001737 private void systemReady() {
Wale Ogunwale6767eae2018-05-03 15:52:51 -07001738 LocalServices.getService(ActivityTaskManagerInternal.class)
Jeff Sharkey9765e442017-12-14 22:15:14 -07001739 .registerScreenObserver(this);
1740
Jeff Sharkeyb049e212012-09-07 23:16:01 -07001741 mSystemReady = true;
1742 mHandler.obtainMessage(H_SYSTEM_READY).sendToTarget();
1743 }
1744
Yasuhiro Matsuda87a38b52015-07-24 22:10:16 +09001745 private void bootCompleted() {
1746 mBootCompleted = true;
1747 }
1748
Jeff Sharkeyfced5342015-05-10 14:53:34 -07001749 private String getDefaultPrimaryStorageUuid() {
1750 if (SystemProperties.getBoolean(StorageManager.PROP_PRIMARY_PHYSICAL, false)) {
1751 return StorageManager.UUID_PRIMARY_PHYSICAL;
1752 } else {
1753 return StorageManager.UUID_PRIVATE_INTERNAL;
1754 }
1755 }
1756
Andreas Gampea36dc622018-02-05 17:19:22 -08001757 @GuardedBy("mLock")
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001758 private void readSettingsLocked() {
1759 mRecords.clear();
Jeff Sharkeyfced5342015-05-10 14:53:34 -07001760 mPrimaryStorageUuid = getDefaultPrimaryStorageUuid();
Jeff Sharkey11697f52018-12-13 10:14:42 -07001761 mLastIsolatedStorage = false;
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001762
1763 FileInputStream fis = null;
1764 try {
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001765 fis = mSettingsFile.openRead();
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001766 final XmlPullParser in = Xml.newPullParser();
Wojciech Staszkiewicz9e9e2e72015-05-08 14:58:46 +01001767 in.setInput(fis, StandardCharsets.UTF_8.name());
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001768
1769 int type;
1770 while ((type = in.next()) != END_DOCUMENT) {
1771 if (type == START_TAG) {
1772 final String tag = in.getName();
Jeff Sharkey620b32b2015-04-23 19:36:02 -07001773 if (TAG_VOLUMES.equals(tag)) {
1774 final int version = readIntAttribute(in, ATTR_VERSION, VERSION_INIT);
Jeff Sharkeyfced5342015-05-10 14:53:34 -07001775 final boolean primaryPhysical = SystemProperties.getBoolean(
1776 StorageManager.PROP_PRIMARY_PHYSICAL, false);
1777 final boolean validAttr = (version >= VERSION_FIX_PRIMARY)
1778 || (version >= VERSION_ADD_PRIMARY && !primaryPhysical);
1779 if (validAttr) {
Jeff Sharkey620b32b2015-04-23 19:36:02 -07001780 mPrimaryStorageUuid = readStringAttribute(in,
1781 ATTR_PRIMARY_STORAGE_UUID);
Jeff Sharkey620b32b2015-04-23 19:36:02 -07001782 }
Jeff Sharkey11697f52018-12-13 10:14:42 -07001783 mLastIsolatedStorage = readBooleanAttribute(in,
1784 ATTR_ISOLATED_STORAGE, false);
Jeff Sharkey620b32b2015-04-23 19:36:02 -07001785
1786 } else if (TAG_VOLUME.equals(tag)) {
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001787 final VolumeRecord rec = readVolumeRecord(in);
1788 mRecords.put(rec.fsUuid, rec);
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001789 }
1790 }
1791 }
1792 } catch (FileNotFoundException e) {
1793 // Missing metadata is okay, probably first boot
1794 } catch (IOException e) {
1795 Slog.wtf(TAG, "Failed reading metadata", e);
1796 } catch (XmlPullParserException e) {
1797 Slog.wtf(TAG, "Failed reading metadata", e);
1798 } finally {
1799 IoUtils.closeQuietly(fis);
1800 }
1801 }
1802
Andreas Gampea36dc622018-02-05 17:19:22 -08001803 @GuardedBy("mLock")
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001804 private void writeSettingsLocked() {
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001805 FileOutputStream fos = null;
1806 try {
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001807 fos = mSettingsFile.startWrite();
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001808
1809 XmlSerializer out = new FastXmlSerializer();
Wojciech Staszkiewicz9e9e2e72015-05-08 14:58:46 +01001810 out.setOutput(fos, StandardCharsets.UTF_8.name());
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001811 out.startDocument(null, true);
1812 out.startTag(null, TAG_VOLUMES);
Jeff Sharkeyfced5342015-05-10 14:53:34 -07001813 writeIntAttribute(out, ATTR_VERSION, VERSION_FIX_PRIMARY);
Jeff Sharkey620b32b2015-04-23 19:36:02 -07001814 writeStringAttribute(out, ATTR_PRIMARY_STORAGE_UUID, mPrimaryStorageUuid);
Jeff Sharkey11697f52018-12-13 10:14:42 -07001815 writeBooleanAttribute(out, ATTR_ISOLATED_STORAGE, StorageManager.hasIsolatedStorage());
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001816 final int size = mRecords.size();
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001817 for (int i = 0; i < size; i++) {
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001818 final VolumeRecord rec = mRecords.valueAt(i);
1819 writeVolumeRecord(out, rec);
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001820 }
1821 out.endTag(null, TAG_VOLUMES);
1822 out.endDocument();
1823
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001824 mSettingsFile.finishWrite(fos);
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001825 } catch (IOException e) {
1826 if (fos != null) {
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001827 mSettingsFile.failWrite(fos);
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001828 }
1829 }
1830 }
1831
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001832 public static VolumeRecord readVolumeRecord(XmlPullParser in) throws IOException {
1833 final int type = readIntAttribute(in, ATTR_TYPE);
1834 final String fsUuid = readStringAttribute(in, ATTR_FS_UUID);
1835 final VolumeRecord meta = new VolumeRecord(type, fsUuid);
Jeff Sharkey5cc0df22015-06-17 19:44:05 -07001836 meta.partGuid = readStringAttribute(in, ATTR_PART_GUID);
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001837 meta.nickname = readStringAttribute(in, ATTR_NICKNAME);
1838 meta.userFlags = readIntAttribute(in, ATTR_USER_FLAGS);
Jeff Sharkeye8a4b662015-06-27 15:43:45 -07001839 meta.createdMillis = readLongAttribute(in, ATTR_CREATED_MILLIS);
1840 meta.lastTrimMillis = readLongAttribute(in, ATTR_LAST_TRIM_MILLIS);
1841 meta.lastBenchMillis = readLongAttribute(in, ATTR_LAST_BENCH_MILLIS);
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001842 return meta;
1843 }
1844
1845 public static void writeVolumeRecord(XmlSerializer out, VolumeRecord rec) throws IOException {
1846 out.startTag(null, TAG_VOLUME);
1847 writeIntAttribute(out, ATTR_TYPE, rec.type);
1848 writeStringAttribute(out, ATTR_FS_UUID, rec.fsUuid);
Jeff Sharkey5cc0df22015-06-17 19:44:05 -07001849 writeStringAttribute(out, ATTR_PART_GUID, rec.partGuid);
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001850 writeStringAttribute(out, ATTR_NICKNAME, rec.nickname);
1851 writeIntAttribute(out, ATTR_USER_FLAGS, rec.userFlags);
Jeff Sharkeye8a4b662015-06-27 15:43:45 -07001852 writeLongAttribute(out, ATTR_CREATED_MILLIS, rec.createdMillis);
1853 writeLongAttribute(out, ATTR_LAST_TRIM_MILLIS, rec.lastTrimMillis);
1854 writeLongAttribute(out, ATTR_LAST_BENCH_MILLIS, rec.lastBenchMillis);
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001855 out.endTag(null, TAG_VOLUME);
1856 }
1857
San Mehat207e5382010-02-04 20:46:54 -08001858 /**
San Mehat4270e1e2010-01-29 05:32:19 -08001859 * Exposed API calls below here
1860 */
1861
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001862 @Override
Sudheer Shanka2250d562016-11-07 15:41:02 -08001863 public void registerListener(IStorageEventListener listener) {
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001864 mCallbacks.register(listener);
San Mehat4270e1e2010-01-29 05:32:19 -08001865 }
1866
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001867 @Override
Sudheer Shanka2250d562016-11-07 15:41:02 -08001868 public void unregisterListener(IStorageEventListener listener) {
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001869 mCallbacks.unregister(listener);
San Mehat4270e1e2010-01-29 05:32:19 -08001870 }
1871
Jeff Sharkey48877892015-03-18 11:27:19 -07001872 @Override
Sudheer Shanka2250d562016-11-07 15:41:02 -08001873 public void shutdown(final IStorageShutdownObserver observer) {
Jeff Sharkey48877892015-03-18 11:27:19 -07001874 enforcePermission(android.Manifest.permission.SHUTDOWN);
San Mehat4270e1e2010-01-29 05:32:19 -08001875
San Mehata5078592010-03-25 09:36:54 -07001876 Slog.i(TAG, "Shutting down");
Jeff Sharkey48877892015-03-18 11:27:19 -07001877 mHandler.obtainMessage(H_SHUTDOWN, observer).sendToTarget();
San Mehat4270e1e2010-01-29 05:32:19 -08001878 }
1879
Jeff Sharkey48877892015-03-18 11:27:19 -07001880 @Override
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001881 public void mount(String volId) {
1882 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001883
Jeff Sharkeyef10ee02015-07-05 14:17:27 -07001884 final VolumeInfo vol = findVolumeByIdOrThrow(volId);
Jeff Sharkey2e606d72015-07-27 14:19:54 -07001885 if (isMountDisallowed(vol)) {
1886 throw new SecurityException("Mounting " + volId + " restricted by policy");
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001887 }
Sudheer Shanka3f0645b2018-09-18 13:07:59 -07001888 mount(vol);
1889 }
1890
1891 private void mount(VolumeInfo vol) {
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001892 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06001893 mVold.mount(vol.id, vol.mountFlags, vol.mountUserId);
Jeff Sharkeyace874b2017-09-07 15:27:33 -06001894 } catch (Exception e) {
1895 Slog.wtf(TAG, e);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001896 }
1897 }
1898
1899 @Override
1900 public void unmount(String volId) {
1901 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001902
Jeff Sharkeyef10ee02015-07-05 14:17:27 -07001903 final VolumeInfo vol = findVolumeByIdOrThrow(volId);
Sudheer Shanka3f0645b2018-09-18 13:07:59 -07001904 unmount(vol);
1905 }
1906
1907 private void unmount(VolumeInfo vol) {
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001908 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06001909 mVold.unmount(vol.id);
Jeff Sharkeyace874b2017-09-07 15:27:33 -06001910 } catch (Exception e) {
1911 Slog.wtf(TAG, e);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001912 }
1913 }
1914
1915 @Override
1916 public void format(String volId) {
Jeff Sharkey48877892015-03-18 11:27:19 -07001917 enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);
San Mehat5b77dab2010-01-26 13:28:50 -08001918
Jeff Sharkeyef10ee02015-07-05 14:17:27 -07001919 final VolumeInfo vol = findVolumeByIdOrThrow(volId);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001920 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06001921 mVold.format(vol.id, "auto");
Jeff Sharkeyace874b2017-09-07 15:27:33 -06001922 } catch (Exception e) {
1923 Slog.wtf(TAG, e);
Jeff Sharkey48877892015-03-18 11:27:19 -07001924 }
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001925 }
1926
1927 @Override
Jeff Sharkey7e19f532017-11-06 13:54:11 -07001928 public void benchmark(String volId, IVoldTaskListener listener) {
Jeff Sharkey9756d752015-05-14 21:07:42 -07001929 enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);
Jeff Sharkey9756d752015-05-14 21:07:42 -07001930
1931 try {
Jeff Sharkeyb302c542017-09-15 12:57:59 -06001932 mVold.benchmark(volId, new IVoldTaskListener.Stub() {
1933 @Override
1934 public void onStatus(int status, PersistableBundle extras) {
Jeff Sharkey7e19f532017-11-06 13:54:11 -07001935 dispatchOnStatus(listener, status, extras);
Jeff Sharkeyb302c542017-09-15 12:57:59 -06001936 }
1937
1938 @Override
1939 public void onFinished(int status, PersistableBundle extras) {
Jeff Sharkey7e19f532017-11-06 13:54:11 -07001940 dispatchOnFinished(listener, status, extras);
Jeff Sharkeyb302c542017-09-15 12:57:59 -06001941
1942 final String path = extras.getString("path");
1943 final String ident = extras.getString("ident");
1944 final long create = extras.getLong("create");
1945 final long run = extras.getLong("run");
1946 final long destroy = extras.getLong("destroy");
1947
1948 final DropBoxManager dropBox = mContext.getSystemService(DropBoxManager.class);
1949 dropBox.addText(TAG_STORAGE_BENCHMARK, scrubPath(path)
1950 + " " + ident + " " + create + " " + run + " " + destroy);
1951
1952 synchronized (mLock) {
1953 final VolumeRecord rec = findRecordForPath(path);
1954 if (rec != null) {
1955 rec.lastBenchMillis = System.currentTimeMillis();
1956 writeSettingsLocked();
1957 }
1958 }
1959 }
1960 });
Jeff Sharkey7e19f532017-11-06 13:54:11 -07001961 } catch (RemoteException e) {
1962 throw e.rethrowAsRuntimeException();
Jeff Sharkey9756d752015-05-14 21:07:42 -07001963 }
1964 }
1965
1966 @Override
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001967 public void partitionPublic(String diskId) {
1968 enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001969
Jeff Sharkeyeba260d2015-04-19 14:35:16 -07001970 final CountDownLatch latch = findOrCreateDiskScanLatch(diskId);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001971 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06001972 mVold.partition(diskId, IVold.PARTITION_TYPE_PUBLIC, -1);
Jeff Sharkeyedcdaf62015-07-09 09:45:36 -07001973 waitForLatch(latch, "partitionPublic", 3 * DateUtils.MINUTE_IN_MILLIS);
Jeff Sharkeyace874b2017-09-07 15:27:33 -06001974 } catch (Exception e) {
1975 Slog.wtf(TAG, e);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001976 }
1977 }
1978
1979 @Override
1980 public void partitionPrivate(String diskId) {
1981 enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);
Amith Yamasani462ac3a2015-06-30 14:21:01 -07001982 enforceAdminUser();
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001983
Jeff Sharkeyeba260d2015-04-19 14:35:16 -07001984 final CountDownLatch latch = findOrCreateDiskScanLatch(diskId);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001985 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06001986 mVold.partition(diskId, IVold.PARTITION_TYPE_PRIVATE, -1);
Jeff Sharkeyedcdaf62015-07-09 09:45:36 -07001987 waitForLatch(latch, "partitionPrivate", 3 * DateUtils.MINUTE_IN_MILLIS);
Jeff Sharkeyace874b2017-09-07 15:27:33 -06001988 } catch (Exception e) {
1989 Slog.wtf(TAG, e);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001990 }
1991 }
1992
1993 @Override
1994 public void partitionMixed(String diskId, int ratio) {
1995 enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);
Amith Yamasani462ac3a2015-06-30 14:21:01 -07001996 enforceAdminUser();
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001997
Jeff Sharkeyeba260d2015-04-19 14:35:16 -07001998 final CountDownLatch latch = findOrCreateDiskScanLatch(diskId);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001999 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002000 mVold.partition(diskId, IVold.PARTITION_TYPE_MIXED, ratio);
Jeff Sharkeyedcdaf62015-07-09 09:45:36 -07002001 waitForLatch(latch, "partitionMixed", 3 * DateUtils.MINUTE_IN_MILLIS);
Jeff Sharkeyace874b2017-09-07 15:27:33 -06002002 } catch (Exception e) {
2003 Slog.wtf(TAG, e);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07002004 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002005 }
2006
Jeff Sharkey48877892015-03-18 11:27:19 -07002007 @Override
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07002008 public void setVolumeNickname(String fsUuid, String nickname) {
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07002009 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07002010
Jeff Sharkey50a05452015-04-29 11:24:52 -07002011 Preconditions.checkNotNull(fsUuid);
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07002012 synchronized (mLock) {
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07002013 final VolumeRecord rec = mRecords.get(fsUuid);
2014 rec.nickname = nickname;
Jeff Sharkey50a05452015-04-29 11:24:52 -07002015 mCallbacks.notifyVolumeRecordChanged(rec);
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07002016 writeSettingsLocked();
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07002017 }
2018 }
2019
2020 @Override
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07002021 public void setVolumeUserFlags(String fsUuid, int flags, int mask) {
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07002022 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07002023
Jeff Sharkey50a05452015-04-29 11:24:52 -07002024 Preconditions.checkNotNull(fsUuid);
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07002025 synchronized (mLock) {
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07002026 final VolumeRecord rec = mRecords.get(fsUuid);
2027 rec.userFlags = (rec.userFlags & ~mask) | (flags & mask);
Jeff Sharkey50a05452015-04-29 11:24:52 -07002028 mCallbacks.notifyVolumeRecordChanged(rec);
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07002029 writeSettingsLocked();
2030 }
2031 }
2032
2033 @Override
2034 public void forgetVolume(String fsUuid) {
2035 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07002036
Jeff Sharkey50a05452015-04-29 11:24:52 -07002037 Preconditions.checkNotNull(fsUuid);
Jeff Sharkey5a9bb742015-11-03 10:15:57 -08002038
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07002039 synchronized (mLock) {
Jeff Sharkey5cc0df22015-06-17 19:44:05 -07002040 final VolumeRecord rec = mRecords.remove(fsUuid);
2041 if (rec != null && !TextUtils.isEmpty(rec.partGuid)) {
Jeff Sharkeydb4b6192017-10-24 11:08:50 -06002042 mHandler.obtainMessage(H_PARTITION_FORGET, rec).sendToTarget();
Jeff Sharkey5cc0df22015-06-17 19:44:05 -07002043 }
2044 mCallbacks.notifyVolumeForgotten(fsUuid);
Jeff Sharkey50a05452015-04-29 11:24:52 -07002045
2046 // If this had been primary storage, revert back to internal and
2047 // reset vold so we bind into new volume into place.
2048 if (Objects.equals(mPrimaryStorageUuid, fsUuid)) {
Jeff Sharkeyfced5342015-05-10 14:53:34 -07002049 mPrimaryStorageUuid = getDefaultPrimaryStorageUuid();
Jeff Sharkey5a9bb742015-11-03 10:15:57 -08002050 mHandler.obtainMessage(H_RESET).sendToTarget();
Jeff Sharkey50a05452015-04-29 11:24:52 -07002051 }
2052
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07002053 writeSettingsLocked();
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07002054 }
2055 }
2056
Jeff Sharkey7d2af542015-05-12 15:27:15 -07002057 @Override
2058 public void forgetAllVolumes() {
2059 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
Jeff Sharkey7d2af542015-05-12 15:27:15 -07002060
Jeff Sharkey50a05452015-04-29 11:24:52 -07002061 synchronized (mLock) {
2062 for (int i = 0; i < mRecords.size(); i++) {
2063 final String fsUuid = mRecords.keyAt(i);
Jeff Sharkey5cc0df22015-06-17 19:44:05 -07002064 final VolumeRecord rec = mRecords.valueAt(i);
2065 if (!TextUtils.isEmpty(rec.partGuid)) {
Jeff Sharkeydb4b6192017-10-24 11:08:50 -06002066 mHandler.obtainMessage(H_PARTITION_FORGET, rec).sendToTarget();
Jeff Sharkey5cc0df22015-06-17 19:44:05 -07002067 }
Jeff Sharkey50a05452015-04-29 11:24:52 -07002068 mCallbacks.notifyVolumeForgotten(fsUuid);
2069 }
Jeff Sharkey50a05452015-04-29 11:24:52 -07002070 mRecords.clear();
Jeff Sharkey50a05452015-04-29 11:24:52 -07002071
Jeff Sharkeyfced5342015-05-10 14:53:34 -07002072 if (!Objects.equals(StorageManager.UUID_PRIVATE_INTERNAL, mPrimaryStorageUuid)) {
2073 mPrimaryStorageUuid = getDefaultPrimaryStorageUuid();
2074 }
2075
2076 writeSettingsLocked();
Jeff Sharkey5a9bb742015-11-03 10:15:57 -08002077 mHandler.obtainMessage(H_RESET).sendToTarget();
Jeff Sharkey50a05452015-04-29 11:24:52 -07002078 }
2079 }
2080
Jeff Sharkeydb4b6192017-10-24 11:08:50 -06002081 private void forgetPartition(String partGuid, String fsUuid) {
Jeff Sharkey5cc0df22015-06-17 19:44:05 -07002082 try {
Jeff Sharkeydb4b6192017-10-24 11:08:50 -06002083 mVold.forgetPartition(partGuid, fsUuid);
Jeff Sharkeyace874b2017-09-07 15:27:33 -06002084 } catch (Exception e) {
2085 Slog.wtf(TAG, e);
Jeff Sharkey5cc0df22015-06-17 19:44:05 -07002086 }
2087 }
2088
Jeff Sharkey31d0b702016-11-21 14:16:53 -07002089 @Override
Jeff Sharkey7e19f532017-11-06 13:54:11 -07002090 public void fstrim(int flags, IVoldTaskListener listener) {
Jeff Sharkey31d0b702016-11-21 14:16:53 -07002091 enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);
Jeff Sharkey31d0b702016-11-21 14:16:53 -07002092
2093 try {
Jeff Sharkeyb302c542017-09-15 12:57:59 -06002094 mVold.fstrim(flags, new IVoldTaskListener.Stub() {
2095 @Override
2096 public void onStatus(int status, PersistableBundle extras) {
Jeff Sharkey7e19f532017-11-06 13:54:11 -07002097 dispatchOnStatus(listener, status, extras);
2098
Jeff Sharkeyb302c542017-09-15 12:57:59 -06002099 // Ignore trim failures
2100 if (status != 0) return;
2101
2102 final String path = extras.getString("path");
2103 final long bytes = extras.getLong("bytes");
2104 final long time = extras.getLong("time");
2105
2106 final DropBoxManager dropBox = mContext.getSystemService(DropBoxManager.class);
2107 dropBox.addText(TAG_STORAGE_TRIM, scrubPath(path) + " " + bytes + " " + time);
2108
2109 synchronized (mLock) {
2110 final VolumeRecord rec = findRecordForPath(path);
2111 if (rec != null) {
2112 rec.lastTrimMillis = System.currentTimeMillis();
2113 writeSettingsLocked();
2114 }
2115 }
2116 }
2117
2118 @Override
2119 public void onFinished(int status, PersistableBundle extras) {
Jeff Sharkey7e19f532017-11-06 13:54:11 -07002120 dispatchOnFinished(listener, status, extras);
2121
Jeff Sharkeyb302c542017-09-15 12:57:59 -06002122 // TODO: benchmark when desired
2123 }
2124 });
Jeff Sharkey7e19f532017-11-06 13:54:11 -07002125 } catch (RemoteException e) {
2126 throw e.rethrowAsRuntimeException();
Jeff Sharkey31d0b702016-11-21 14:16:53 -07002127 }
2128 }
2129
Jin Qiana85b9912017-10-17 15:48:18 -07002130 void runIdleMaint(Runnable callback) {
2131 enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);
2132
2133 try {
2134 mVold.runIdleMaint(new IVoldTaskListener.Stub() {
2135 @Override
2136 public void onStatus(int status, PersistableBundle extras) {
2137 // Not currently used
2138 }
2139 @Override
2140 public void onFinished(int status, PersistableBundle extras) {
2141 if (callback != null) {
2142 BackgroundThread.getHandler().post(callback);
2143 }
2144 }
2145 });
2146 } catch (Exception e) {
2147 Slog.wtf(TAG, e);
2148 }
2149 }
2150
2151 @Override
2152 public void runIdleMaintenance() {
2153 runIdleMaint(null);
2154 }
2155
2156 void abortIdleMaint(Runnable callback) {
2157 enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);
2158
2159 try {
2160 mVold.abortIdleMaint(new IVoldTaskListener.Stub() {
2161 @Override
2162 public void onStatus(int status, PersistableBundle extras) {
2163 // Not currently used
2164 }
2165 @Override
2166 public void onFinished(int status, PersistableBundle extras) {
2167 if (callback != null) {
2168 BackgroundThread.getHandler().post(callback);
2169 }
2170 }
2171 });
2172 } catch (Exception e) {
2173 Slog.wtf(TAG, e);
2174 }
2175 }
2176
2177 @Override
2178 public void abortIdleMaintenance() {
2179 abortIdleMaint(null);
2180 }
2181
Svet Ganov6ee871e2015-07-10 14:29:33 -07002182 private void remountUidExternalStorage(int uid, int mode) {
Jeff Sharkey9527b222015-06-24 15:24:48 -07002183 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002184 mVold.remountUid(uid, mode);
Jeff Sharkeyace874b2017-09-07 15:27:33 -06002185 } catch (Exception e) {
2186 Slog.wtf(TAG, e);
Jeff Sharkey9527b222015-06-24 15:24:48 -07002187 }
2188 }
2189
2190 @Override
Jeff Sharkey4c099d02015-05-15 13:45:00 -07002191 public void setDebugFlags(int flags, int mask) {
2192 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
Jeff Sharkey4c099d02015-05-15 13:45:00 -07002193
Jeff Sharkeyba512352015-11-12 20:17:45 -08002194 if ((mask & StorageManager.DEBUG_EMULATE_FBE) != 0) {
Jeff Sharkey00455bf2016-11-04 14:45:24 -06002195 if (!EMULATE_FBE_SUPPORTED) {
2196 throw new IllegalStateException(
2197 "Emulation not supported on this device");
2198 }
Paul Lawrence20be5d62016-02-26 13:51:17 -08002199 if (StorageManager.isFileEncryptedNativeOnly()) {
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07002200 throw new IllegalStateException(
Jeff Sharkey00455bf2016-11-04 14:45:24 -06002201 "Emulation not supported on device with native FBE");
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07002202 }
Jeff Sharkey5a785162016-03-21 13:02:06 -06002203 if (mLockPatternUtils.isCredentialRequiredToDecrypt(false)) {
2204 throw new IllegalStateException(
2205 "Emulation requires disabling 'Secure start-up' in Settings > Security");
2206 }
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07002207
Jeff Sharkey1176e512016-02-29 17:01:26 -07002208 final long token = Binder.clearCallingIdentity();
2209 try {
2210 final boolean emulateFbe = (flags & StorageManager.DEBUG_EMULATE_FBE) != 0;
2211 SystemProperties.set(StorageManager.PROP_EMULATE_FBE, Boolean.toString(emulateFbe));
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07002212
Jeff Sharkey1176e512016-02-29 17:01:26 -07002213 // Perform hard reboot to kick policy into place
2214 mContext.getSystemService(PowerManager.class).reboot(null);
2215 } finally {
2216 Binder.restoreCallingIdentity(token);
2217 }
Jeff Sharkeyba512352015-11-12 20:17:45 -08002218 }
Jeff Sharkey4c099d02015-05-15 13:45:00 -07002219
Jeff Sharkey901c0422018-04-20 13:11:20 -06002220 if ((mask & (StorageManager.DEBUG_ADOPTABLE_FORCE_ON
2221 | StorageManager.DEBUG_ADOPTABLE_FORCE_OFF)) != 0) {
2222 final String value;
2223 if ((flags & StorageManager.DEBUG_ADOPTABLE_FORCE_ON) != 0) {
2224 value = "force_on";
2225 } else if ((flags & StorageManager.DEBUG_ADOPTABLE_FORCE_OFF) != 0) {
2226 value = "force_off";
2227 } else {
2228 value = "";
2229 }
Jeff Sharkeyba512352015-11-12 20:17:45 -08002230
Jeff Sharkey901c0422018-04-20 13:11:20 -06002231 final long token = Binder.clearCallingIdentity();
2232 try {
2233 SystemProperties.set(StorageManager.PROP_ADOPTABLE, value);
2234
2235 // Reset storage to kick new setting into place
Jeff Sharkeyba512352015-11-12 20:17:45 -08002236 mHandler.obtainMessage(H_RESET).sendToTarget();
Jeff Sharkey901c0422018-04-20 13:11:20 -06002237 } finally {
2238 Binder.restoreCallingIdentity(token);
Jeff Sharkeyba512352015-11-12 20:17:45 -08002239 }
Jeff Sharkey4c099d02015-05-15 13:45:00 -07002240 }
Jeff Sharkey33dd1562016-04-07 11:05:33 -06002241
2242 if ((mask & (StorageManager.DEBUG_SDCARDFS_FORCE_ON
2243 | StorageManager.DEBUG_SDCARDFS_FORCE_OFF)) != 0) {
2244 final String value;
2245 if ((flags & StorageManager.DEBUG_SDCARDFS_FORCE_ON) != 0) {
2246 value = "force_on";
2247 } else if ((flags & StorageManager.DEBUG_SDCARDFS_FORCE_OFF) != 0) {
2248 value = "force_off";
2249 } else {
2250 value = "";
2251 }
2252
2253 final long token = Binder.clearCallingIdentity();
2254 try {
2255 SystemProperties.set(StorageManager.PROP_SDCARDFS, value);
2256
2257 // Reset storage to kick new setting into place
2258 mHandler.obtainMessage(H_RESET).sendToTarget();
2259 } finally {
2260 Binder.restoreCallingIdentity(token);
2261 }
2262 }
Jeff Sharkeye53e2d92017-03-25 23:14:06 -06002263
2264 if ((mask & StorageManager.DEBUG_VIRTUAL_DISK) != 0) {
2265 final boolean enabled = (flags & StorageManager.DEBUG_VIRTUAL_DISK) != 0;
2266
2267 final long token = Binder.clearCallingIdentity();
2268 try {
2269 SystemProperties.set(StorageManager.PROP_VIRTUAL_DISK, Boolean.toString(enabled));
2270
2271 // Reset storage to kick new setting into place
2272 mHandler.obtainMessage(H_RESET).sendToTarget();
2273 } finally {
2274 Binder.restoreCallingIdentity(token);
2275 }
2276 }
Sudheer Shankabe0febe2018-11-07 18:24:37 -08002277
Jeff Sharkeyb0c363b22018-12-15 11:53:03 -07002278 if ((mask & (StorageManager.DEBUG_ISOLATED_STORAGE_FORCE_ON
2279 | StorageManager.DEBUG_ISOLATED_STORAGE_FORCE_OFF)) != 0) {
2280 final int value;
2281 if ((flags & StorageManager.DEBUG_ISOLATED_STORAGE_FORCE_ON) != 0) {
2282 value = 1;
2283 } else if ((flags & StorageManager.DEBUG_ISOLATED_STORAGE_FORCE_OFF) != 0) {
2284 value = -1;
2285 } else {
2286 value = 0;
2287 }
Sudheer Shankabe0febe2018-11-07 18:24:37 -08002288
2289 final long token = Binder.clearCallingIdentity();
2290 try {
Jeff Sharkeyb0c363b22018-12-15 11:53:03 -07002291 Settings.Global.putInt(mContext.getContentResolver(),
2292 Settings.Global.ISOLATED_STORAGE_LOCAL, value);
2293 refreshIsolatedStorageSettings();
Sudheer Shankabe0febe2018-11-07 18:24:37 -08002294
2295 // Perform hard reboot to kick policy into place
Jeff Sharkey36274992019-02-27 12:09:57 -07002296 mHandler.post(() -> {
2297 mContext.getSystemService(PowerManager.class).reboot(null);
2298 });
2299 } finally {
2300 Binder.restoreCallingIdentity(token);
2301 }
2302 }
2303
2304 if ((mask & StorageManager.DEBUG_LEGACY_GREYLIST) != 0) {
2305 final boolean enabled = (flags & StorageManager.DEBUG_LEGACY_GREYLIST) != 0;
2306
2307 final long token = Binder.clearCallingIdentity();
2308 try {
2309 SystemProperties.set(StorageManager.PROP_LEGACY_GREYLIST,
2310 Boolean.toString(enabled));
2311
2312 // Perform hard reboot to kick policy into place
2313 mHandler.post(() -> {
2314 mContext.getSystemService(PowerManager.class).reboot(null);
2315 });
Sudheer Shankabe0febe2018-11-07 18:24:37 -08002316 } finally {
2317 Binder.restoreCallingIdentity(token);
2318 }
2319 }
Jeff Sharkey4c099d02015-05-15 13:45:00 -07002320 }
2321
2322 @Override
Jeff Sharkey275e3e42015-04-24 16:10:32 -07002323 public String getPrimaryStorageUuid() {
Jeff Sharkey620b32b2015-04-23 19:36:02 -07002324 synchronized (mLock) {
2325 return mPrimaryStorageUuid;
2326 }
2327 }
2328
2329 @Override
Jeff Sharkey275e3e42015-04-24 16:10:32 -07002330 public void setPrimaryStorageUuid(String volumeUuid, IPackageMoveObserver callback) {
2331 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
Jeff Sharkey620b32b2015-04-23 19:36:02 -07002332
Jeff Sharkeya31460c2016-06-22 09:04:33 -06002333 final VolumeInfo from;
2334 final VolumeInfo to;
2335
Jeff Sharkey275e3e42015-04-24 16:10:32 -07002336 synchronized (mLock) {
Jeff Sharkeyfced5342015-05-10 14:53:34 -07002337 if (Objects.equals(mPrimaryStorageUuid, volumeUuid)) {
2338 throw new IllegalArgumentException("Primary storage already at " + volumeUuid);
Jeff Sharkey275e3e42015-04-24 16:10:32 -07002339 }
2340
2341 if (mMoveCallback != null) {
2342 throw new IllegalStateException("Move already in progress");
2343 }
2344 mMoveCallback = callback;
2345 mMoveTargetUuid = volumeUuid;
2346
Jeff Sharkeya65e6492017-06-21 13:45:11 -06002347 // We need all the users unlocked to move their primary storage
2348 final List<UserInfo> users = mContext.getSystemService(UserManager.class).getUsers();
2349 for (UserInfo user : users) {
2350 if (StorageManager.isFileEncryptedNativeOrEmulated()
2351 && !isUserKeyUnlocked(user.id)) {
2352 Slog.w(TAG, "Failing move due to locked user " + user.id);
2353 onMoveStatusLocked(PackageManager.MOVE_FAILED_LOCKED_USER);
2354 return;
2355 }
2356 }
2357
Jeff Sharkeyfced5342015-05-10 14:53:34 -07002358 // When moving to/from primary physical volume, we probably just nuked
2359 // the current storage location, so we have nothing to move.
2360 if (Objects.equals(StorageManager.UUID_PRIMARY_PHYSICAL, mPrimaryStorageUuid)
2361 || Objects.equals(StorageManager.UUID_PRIMARY_PHYSICAL, volumeUuid)) {
2362 Slog.d(TAG, "Skipping move to/from primary physical");
2363 onMoveStatusLocked(MOVE_STATUS_COPY_FINISHED);
2364 onMoveStatusLocked(PackageManager.MOVE_SUCCEEDED);
Jeff Sharkey5a9bb742015-11-03 10:15:57 -08002365 mHandler.obtainMessage(H_RESET).sendToTarget();
Jeff Sharkeya31460c2016-06-22 09:04:33 -06002366 return;
Jeff Sharkeyfced5342015-05-10 14:53:34 -07002367
2368 } else {
Jeff Sharkeya31460c2016-06-22 09:04:33 -06002369 from = findStorageForUuid(mPrimaryStorageUuid);
2370 to = findStorageForUuid(volumeUuid);
Jeff Sharkeyef10ee02015-07-05 14:17:27 -07002371
2372 if (from == null) {
2373 Slog.w(TAG, "Failing move due to missing from volume " + mPrimaryStorageUuid);
2374 onMoveStatusLocked(PackageManager.MOVE_FAILED_INTERNAL_ERROR);
2375 return;
2376 } else if (to == null) {
2377 Slog.w(TAG, "Failing move due to missing to volume " + volumeUuid);
2378 onMoveStatusLocked(PackageManager.MOVE_FAILED_INTERNAL_ERROR);
2379 return;
2380 }
Jeff Sharkey275e3e42015-04-24 16:10:32 -07002381 }
Jeff Sharkey620b32b2015-04-23 19:36:02 -07002382 }
Jeff Sharkeya31460c2016-06-22 09:04:33 -06002383
2384 try {
Jeff Sharkeyb302c542017-09-15 12:57:59 -06002385 mVold.moveStorage(from.id, to.id, new IVoldTaskListener.Stub() {
2386 @Override
2387 public void onStatus(int status, PersistableBundle extras) {
2388 synchronized (mLock) {
2389 onMoveStatusLocked(status);
2390 }
2391 }
2392
2393 @Override
2394 public void onFinished(int status, PersistableBundle extras) {
2395 // Not currently used
2396 }
2397 });
Jeff Sharkeyace874b2017-09-07 15:27:33 -06002398 } catch (Exception e) {
2399 Slog.wtf(TAG, e);
Jeff Sharkeya31460c2016-06-22 09:04:33 -06002400 }
Jeff Sharkey620b32b2015-04-23 19:36:02 -07002401 }
2402
San Mehatb1043402010-02-05 08:26:50 -08002403 private void warnOnNotMounted() {
Jeff Sharkey48877892015-03-18 11:27:19 -07002404 synchronized (mLock) {
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07002405 for (int i = 0; i < mVolumes.size(); i++) {
2406 final VolumeInfo vol = mVolumes.valueAt(i);
Jeff Sharkey27de30d2015-04-18 16:20:27 -07002407 if (vol.isPrimary() && vol.isMountedWritable()) {
Jeff Sharkey48877892015-03-18 11:27:19 -07002408 // Cool beans, we have a mounted primary volume
2409 return;
2410 }
Jeff Sharkey32ee8312012-09-30 13:21:31 -07002411 }
San Mehatb1043402010-02-05 08:26:50 -08002412 }
Jeff Sharkey48877892015-03-18 11:27:19 -07002413
2414 Slog.w(TAG, "No primary storage mounted!");
San Mehatb1043402010-02-05 08:26:50 -08002415 }
2416
Kenny Roota02b8b02010-08-05 16:14:17 -07002417 private boolean isUidOwnerOfPackageOrSystem(String packageName, int callerUid) {
2418 if (callerUid == android.os.Process.SYSTEM_UID) {
2419 return true;
2420 }
2421
Kenny Root02c87302010-07-01 08:10:18 -07002422 if (packageName == null) {
2423 return false;
2424 }
2425
Jeff Sharkey5790af02018-08-13 17:42:54 -06002426 final int packageUid = mPmInternal.getPackageUid(packageName,
Jeff Sharkeycd654482016-01-08 17:42:11 -07002427 PackageManager.MATCH_DEBUG_TRIAGED_MISSING, UserHandle.getUserId(callerUid));
Kenny Root02c87302010-07-01 08:10:18 -07002428
2429 if (DEBUG_OBB) {
2430 Slog.d(TAG, "packageName = " + packageName + ", packageUid = " +
2431 packageUid + ", callerUid = " + callerUid);
2432 }
2433
2434 return callerUid == packageUid;
2435 }
2436
Jeff Sharkey54402792017-09-15 16:05:19 -06002437 @Override
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002438 public String getMountedObbPath(String rawPath) {
2439 Preconditions.checkNotNull(rawPath, "rawPath cannot be null");
Kenny Rootaf9d6672010-10-08 09:21:39 -07002440
Kenny Root02c87302010-07-01 08:10:18 -07002441 warnOnNotMounted();
2442
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002443 final ObbState state;
Rubin Xucd7a0142015-04-17 23:45:27 +01002444 synchronized (mObbMounts) {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002445 state = mObbPathToStateMap.get(rawPath);
2446 }
2447 if (state == null) {
2448 Slog.w(TAG, "Failed to find OBB mounted at " + rawPath);
2449 return null;
2450 }
2451
Jeff Sharkey54402792017-09-15 16:05:19 -06002452 return findVolumeByIdOrThrow(state.volId).getPath().getAbsolutePath();
Kenny Root02c87302010-07-01 08:10:18 -07002453 }
2454
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002455 @Override
2456 public boolean isObbMounted(String rawPath) {
2457 Preconditions.checkNotNull(rawPath, "rawPath cannot be null");
Kenny Rootaf9d6672010-10-08 09:21:39 -07002458 synchronized (mObbMounts) {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002459 return mObbPathToStateMap.containsKey(rawPath);
Kenny Rootaf9d6672010-10-08 09:21:39 -07002460 }
Kenny Root02c87302010-07-01 08:10:18 -07002461 }
2462
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002463 @Override
Sudheer Shanka25469aa2018-08-27 15:50:23 -07002464 public void mountObb(String rawPath, String canonicalPath, String key,
2465 IObbActionListener token, int nonce, ObbInfo obbInfo) {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002466 Preconditions.checkNotNull(rawPath, "rawPath cannot be null");
2467 Preconditions.checkNotNull(canonicalPath, "canonicalPath cannot be null");
2468 Preconditions.checkNotNull(token, "token cannot be null");
Sudheer Shanka25469aa2018-08-27 15:50:23 -07002469 Preconditions.checkNotNull(obbInfo, "obbIfno cannot be null");
Kenny Rootaf9d6672010-10-08 09:21:39 -07002470
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002471 final int callingUid = Binder.getCallingUid();
Jeff Sharkey41cd6812017-09-11 10:32:17 -06002472 final ObbState obbState = new ObbState(rawPath, canonicalPath,
2473 callingUid, token, nonce, null);
Sudheer Shanka25469aa2018-08-27 15:50:23 -07002474 final ObbAction action = new MountObbAction(obbState, key, callingUid, obbInfo);
Kenny Roota02b8b02010-08-05 16:14:17 -07002475 mObbActionHandler.sendMessage(mObbActionHandler.obtainMessage(OBB_RUN_ACTION, action));
2476
2477 if (DEBUG_OBB)
2478 Slog.i(TAG, "Send to OBB handler: " + action.toString());
Kenny Root02c87302010-07-01 08:10:18 -07002479 }
2480
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002481 @Override
2482 public void unmountObb(String rawPath, boolean force, IObbActionListener token, int nonce) {
2483 Preconditions.checkNotNull(rawPath, "rawPath cannot be null");
2484
2485 final ObbState existingState;
Rubin Xucd7a0142015-04-17 23:45:27 +01002486 synchronized (mObbMounts) {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002487 existingState = mObbPathToStateMap.get(rawPath);
Kenny Rootf1121dc2010-09-29 07:30:53 -07002488 }
2489
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002490 if (existingState != null) {
2491 // TODO: separate state object from request data
2492 final int callingUid = Binder.getCallingUid();
Jeff Sharkey41cd6812017-09-11 10:32:17 -06002493 final ObbState newState = new ObbState(rawPath, existingState.canonicalPath,
2494 callingUid, token, nonce, existingState.volId);
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002495 final ObbAction action = new UnmountObbAction(newState, force);
2496 mObbActionHandler.sendMessage(mObbActionHandler.obtainMessage(OBB_RUN_ACTION, action));
Kenny Root02c87302010-07-01 08:10:18 -07002497
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002498 if (DEBUG_OBB)
2499 Slog.i(TAG, "Send to OBB handler: " + action.toString());
2500 } else {
2501 Slog.w(TAG, "Unknown OBB mount at " + rawPath);
2502 }
Kenny Roota02b8b02010-08-05 16:14:17 -07002503 }
2504
Ben Komalo444eca22011-09-01 15:17:44 -07002505 @Override
2506 public int getEncryptionState() {
2507 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
2508 "no permission to access the crypt keeper");
2509
Ben Komalo444eca22011-09-01 15:17:44 -07002510 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002511 return mVold.fdeComplete();
2512 } catch (Exception e) {
2513 Slog.wtf(TAG, e);
Sudheer Shankaf7341142016-10-18 17:15:18 -07002514 return StorageManager.ENCRYPTION_STATE_ERROR_UNKNOWN;
Ben Komalo444eca22011-09-01 15:17:44 -07002515 }
2516 }
2517
2518 @Override
Jason parks5af0b912010-11-29 09:05:25 -06002519 public int decryptStorage(String password) {
Jason parks8888c592011-01-20 22:46:41 -06002520 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
2521 "no permission to access the crypt keeper");
Jason parks5af0b912010-11-29 09:05:25 -06002522
Jeff Sharkey8058fe62017-09-13 11:50:33 -06002523 if (TextUtils.isEmpty(password)) {
2524 throw new IllegalArgumentException("password cannot be empty");
2525 }
2526
Jason parks5af0b912010-11-29 09:05:25 -06002527 if (DEBUG_EVENTS) {
2528 Slog.i(TAG, "decrypting storage...");
2529 }
2530
2531 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002532 mVold.fdeCheckPassword(password);
2533 mHandler.postDelayed(() -> {
2534 try {
2535 mVold.fdeRestart();
2536 } catch (Exception e) {
2537 Slog.wtf(TAG, e);
2538 }
2539 }, DateUtils.SECOND_IN_MILLIS);
2540 return 0;
Paul Crowleyfc0b5192018-07-02 13:58:10 -07002541 } catch (ServiceSpecificException e) {
2542 Slog.e(TAG, "fdeCheckPassword failed", e);
2543 return e.errorCode;
Jeff Sharkey54402792017-09-15 16:05:19 -06002544 } catch (Exception e) {
2545 Slog.wtf(TAG, e);
2546 return StorageManager.ENCRYPTION_STATE_ERROR_UNKNOWN;
Jason parks5af0b912010-11-29 09:05:25 -06002547 }
Jason parks5af0b912010-11-29 09:05:25 -06002548 }
2549
Jeff Sharkey54402792017-09-15 16:05:19 -06002550 @Override
Paul Lawrence46791e72014-04-03 09:10:26 -07002551 public int encryptStorage(int type, String password) {
Jason parks8888c592011-01-20 22:46:41 -06002552 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
2553 "no permission to access the crypt keeper");
Jason parks56aa5322011-01-07 09:01:15 -06002554
Jeff Sharkey8058fe62017-09-13 11:50:33 -06002555 if (type == StorageManager.CRYPT_TYPE_DEFAULT) {
2556 password = "";
2557 } else if (TextUtils.isEmpty(password)) {
2558 throw new IllegalArgumentException("password cannot be empty");
2559 }
2560
Jason parks56aa5322011-01-07 09:01:15 -06002561 if (DEBUG_EVENTS) {
Jason parks8888c592011-01-20 22:46:41 -06002562 Slog.i(TAG, "encrypting storage...");
Jason parks56aa5322011-01-07 09:01:15 -06002563 }
2564
2565 try {
Paul Lawrence89a0ae42017-12-22 10:11:10 -08002566 mVold.fdeEnable(type, password, 0);
Jeff Sharkey43e12112017-09-12 16:31:45 -06002567 } catch (Exception e) {
2568 Slog.wtf(TAG, e);
2569 return -1;
Jason parks56aa5322011-01-07 09:01:15 -06002570 }
2571
2572 return 0;
2573 }
2574
Paul Lawrence8e397362014-01-27 15:22:30 -08002575 /** Set the password for encrypting the master key.
2576 * @param type One of the CRYPTO_TYPE_XXX consts defined in StorageManager.
2577 * @param password The password to set.
2578 */
Jeff Sharkey54402792017-09-15 16:05:19 -06002579 @Override
Paul Lawrence8e397362014-01-27 15:22:30 -08002580 public int changeEncryptionPassword(int type, String password) {
Jason parksf7b3cd42011-01-27 09:28:25 -06002581 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
2582 "no permission to access the crypt keeper");
2583
Jeff Sharkeyae266462017-11-27 13:32:24 -07002584 if (StorageManager.isFileEncryptedNativeOnly()) {
2585 // Not supported on FBE devices
2586 return -1;
2587 }
2588
Jeff Sharkey8058fe62017-09-13 11:50:33 -06002589 if (type == StorageManager.CRYPT_TYPE_DEFAULT) {
2590 password = "";
2591 } else if (TextUtils.isEmpty(password)) {
2592 throw new IllegalArgumentException("password cannot be empty");
2593 }
2594
Jason parksf7b3cd42011-01-27 09:28:25 -06002595 if (DEBUG_EVENTS) {
2596 Slog.i(TAG, "changing encryption password...");
2597 }
2598
2599 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002600 mVold.fdeChangePassword(type, password);
2601 return 0;
2602 } catch (Exception e) {
2603 Slog.wtf(TAG, e);
2604 return -1;
Jason parksf7b3cd42011-01-27 09:28:25 -06002605 }
2606 }
2607
Christopher Tate32418be2011-10-10 13:51:12 -07002608 /**
2609 * Validate a user-supplied password string with cryptfs
2610 */
2611 @Override
2612 public int verifyEncryptionPassword(String password) throws RemoteException {
2613 // Only the system process is permitted to validate passwords
2614 if (Binder.getCallingUid() != android.os.Process.SYSTEM_UID) {
2615 throw new SecurityException("no permission to access the crypt keeper");
2616 }
2617
2618 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
2619 "no permission to access the crypt keeper");
2620
2621 if (TextUtils.isEmpty(password)) {
2622 throw new IllegalArgumentException("password cannot be empty");
2623 }
2624
Christopher Tate32418be2011-10-10 13:51:12 -07002625 if (DEBUG_EVENTS) {
2626 Slog.i(TAG, "validating encryption password...");
2627 }
2628
2629 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002630 mVold.fdeVerifyPassword(password);
2631 return 0;
2632 } catch (Exception e) {
2633 Slog.wtf(TAG, e);
2634 return -1;
Christopher Tate32418be2011-10-10 13:51:12 -07002635 }
2636 }
2637
Paul Lawrence8e397362014-01-27 15:22:30 -08002638 /**
2639 * Get the type of encryption used to encrypt the master key.
2640 * @return The type, one of the CRYPT_TYPE_XXX consts from StorageManager.
2641 */
2642 @Override
Svetoslav16e4a1a2014-09-29 18:16:20 -07002643 public int getPasswordType() {
Paul Lawrence76a40572017-03-15 11:08:04 -07002644 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
Paul Lawrence9de713d2016-05-02 22:45:33 +00002645 "no permission to access the crypt keeper");
2646
Paul Lawrence8e397362014-01-27 15:22:30 -08002647 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002648 return mVold.fdeGetPasswordType();
2649 } catch (Exception e) {
2650 Slog.wtf(TAG, e);
2651 return -1;
Paul Lawrence8e397362014-01-27 15:22:30 -08002652 }
2653 }
2654
Paul Lawrencee51dcf92014-03-18 10:56:00 -07002655 /**
2656 * Set a field in the crypto header.
2657 * @param field field to set
2658 * @param contents contents to set in field
2659 */
2660 @Override
2661 public void setField(String field, String contents) throws RemoteException {
Paul Lawrence76a40572017-03-15 11:08:04 -07002662 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
Paul Lawrence0bbd1082016-04-26 15:21:02 -07002663 "no permission to access the crypt keeper");
Paul Lawrencee51dcf92014-03-18 10:56:00 -07002664
yusukes14a8b1f2018-07-23 17:34:42 -07002665 if (!StorageManager.isBlockEncrypted()) {
2666 // Only supported on FDE devices
Jeff Sharkeyae266462017-11-27 13:32:24 -07002667 return;
2668 }
2669
Paul Lawrencee51dcf92014-03-18 10:56:00 -07002670 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002671 mVold.fdeSetField(field, contents);
2672 return;
2673 } catch (Exception e) {
2674 Slog.wtf(TAG, e);
2675 return;
Paul Lawrencee51dcf92014-03-18 10:56:00 -07002676 }
2677 }
2678
2679 /**
2680 * Gets a field from the crypto header.
2681 * @param field field to get
2682 * @return contents of field
2683 */
2684 @Override
2685 public String getField(String field) throws RemoteException {
Paul Lawrence76a40572017-03-15 11:08:04 -07002686 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
Paul Lawrence0bbd1082016-04-26 15:21:02 -07002687 "no permission to access the crypt keeper");
Paul Lawrencee51dcf92014-03-18 10:56:00 -07002688
yusukes14a8b1f2018-07-23 17:34:42 -07002689 if (!StorageManager.isBlockEncrypted()) {
2690 // Only supported on FDE devices
Jeff Sharkeyae266462017-11-27 13:32:24 -07002691 return null;
2692 }
2693
Paul Lawrencee51dcf92014-03-18 10:56:00 -07002694 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002695 return mVold.fdeGetField(field);
2696 } catch (Exception e) {
2697 Slog.wtf(TAG, e);
2698 return null;
Paul Lawrencee51dcf92014-03-18 10:56:00 -07002699 }
2700 }
2701
Paul Lawrence3806d9c2015-10-29 10:30:46 -07002702 /**
2703 * Is userdata convertible to file based encryption?
2704 * @return non zero for convertible
2705 */
2706 @Override
2707 public boolean isConvertibleToFBE() throws RemoteException {
Paul Lawrence76a40572017-03-15 11:08:04 -07002708 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
Paul Lawrence0bbd1082016-04-26 15:21:02 -07002709 "no permission to access the crypt keeper");
Paul Lawrence3806d9c2015-10-29 10:30:46 -07002710
Paul Lawrence3806d9c2015-10-29 10:30:46 -07002711 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002712 return mVold.isConvertibleToFbe();
2713 } catch (Exception e) {
2714 Slog.wtf(TAG, e);
2715 return false;
Paul Lawrence3806d9c2015-10-29 10:30:46 -07002716 }
2717 }
2718
Daniel Rosenberge129e5c2018-11-07 19:25:55 -08002719 /**
Martijn Coenenf04aca42019-03-11 10:35:34 +01002720 * Check whether the device supports filesystem checkpointing.
2721 *
2722 * @return true if the device supports filesystem checkpointing, false otherwise.
2723 */
2724 @Override
2725 public boolean supportsCheckpoint() throws RemoteException {
2726 // Only the system process is permitted to start checkpoints
2727 if (Binder.getCallingUid() != android.os.Process.SYSTEM_UID) {
2728 throw new SecurityException("no permission to check filesystem checkpoint support");
2729 }
2730
2731 return mVold.supportsCheckpoint();
2732 }
2733
2734 /**
2735 * Signal that checkpointing partitions should start a checkpoint on the next boot.
2736 *
2737 * @param numTries Number of times to try booting in checkpoint mode, before we will boot
2738 * non-checkpoint mode and commit all changes immediately. Callers are
2739 * responsible for ensuring that boot is safe (eg, by rolling back updates).
2740 */
2741 @Override
2742 public void startCheckpoint(int numTries) throws RemoteException {
2743 // Only the system process is permitted to start checkpoints
2744 if (Binder.getCallingUid() != android.os.Process.SYSTEM_UID) {
2745 throw new SecurityException("no permission to start filesystem checkpoint");
2746 }
2747
2748 mVold.startCheckpoint(numTries);
2749 }
2750
2751 /**
Daniel Rosenberge129e5c2018-11-07 19:25:55 -08002752 * Signal that checkpointing partitions should commit changes
2753 */
2754 @Override
2755 public void commitChanges() throws RemoteException {
2756 // Only the system process is permitted to commit checkpoints
2757 if (Binder.getCallingUid() != android.os.Process.SYSTEM_UID) {
2758 throw new SecurityException("no permission to commit checkpoint changes");
2759 }
2760
2761 mVold.commitChanges();
2762 }
2763
Jeff Sharkeyb049e212012-09-07 23:16:01 -07002764 @Override
Paul Lawrence945490c2014-03-27 16:37:28 +00002765 public String getPassword() throws RemoteException {
Paul Lawrence76a40572017-03-15 11:08:04 -07002766 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
Rubin Xucd7a0142015-04-17 23:45:27 +01002767 "only keyguard can retrieve password");
Paul Lawrence0bbd1082016-04-26 15:21:02 -07002768
Paul Lawrence945490c2014-03-27 16:37:28 +00002769 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002770 return mVold.fdeGetPassword();
2771 } catch (Exception e) {
2772 Slog.wtf(TAG, e);
Paul Lawrence24063b52015-01-06 13:11:23 -08002773 return null;
Paul Lawrence945490c2014-03-27 16:37:28 +00002774 }
2775 }
2776
2777 @Override
2778 public void clearPassword() throws RemoteException {
Paul Lawrence76a40572017-03-15 11:08:04 -07002779 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
Paul Lawrence0bbd1082016-04-26 15:21:02 -07002780 "only keyguard can clear password");
2781
Paul Lawrence945490c2014-03-27 16:37:28 +00002782 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002783 mVold.fdeClearPassword();
2784 return;
2785 } catch (Exception e) {
2786 Slog.wtf(TAG, e);
2787 return;
Paul Lawrence945490c2014-03-27 16:37:28 +00002788 }
2789 }
2790
2791 @Override
Lenka Trochtovac4dd0212015-11-18 12:22:06 +01002792 public void createUserKey(int userId, int serialNumber, boolean ephemeral) {
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002793 enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
Paul Crowleybcf48ed2015-04-22 13:36:59 +01002794
Paul Crowleybcf48ed2015-04-22 13:36:59 +01002795 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002796 mVold.createUserKey(userId, serialNumber, ephemeral);
Jeff Sharkey43e12112017-09-12 16:31:45 -06002797 } catch (Exception e) {
2798 Slog.wtf(TAG, e);
Paul Crowleybcf48ed2015-04-22 13:36:59 +01002799 }
2800 }
2801
Paul Crowley7ec733f2015-05-19 12:42:00 +01002802 @Override
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002803 public void destroyUserKey(int userId) {
2804 enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
Paul Crowley7ec733f2015-05-19 12:42:00 +01002805
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002806 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002807 mVold.destroyUserKey(userId);
Jeff Sharkey43e12112017-09-12 16:31:45 -06002808 } catch (Exception e) {
2809 Slog.wtf(TAG, e);
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002810 }
2811 }
2812
Jeff Sharkey43e12112017-09-12 16:31:45 -06002813 private String encodeBytes(byte[] bytes) {
Paul Crowleyfaeb3eb2016-02-08 15:58:29 +00002814 if (ArrayUtils.isEmpty(bytes)) {
Jeff Sharkey43e12112017-09-12 16:31:45 -06002815 return "!";
Paul Crowleyfaeb3eb2016-02-08 15:58:29 +00002816 } else {
Jeff Sharkey43e12112017-09-12 16:31:45 -06002817 return HexDump.toHexString(bytes);
Paul Crowleyfaeb3eb2016-02-08 15:58:29 +00002818 }
2819 }
2820
Paul Crowleycc701552016-05-17 14:18:49 -07002821 /*
2822 * Add this token/secret pair to the set of ways we can recover a disk encryption key.
2823 * Changing the token/secret for a disk encryption key is done in two phases: first, adding
2824 * a new token/secret pair with this call, then delting all other pairs with
2825 * fixateNewestUserKeyAuth. This allows other places where a credential is used, such as
2826 * Gatekeeper, to be updated between the two calls.
2827 */
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002828 @Override
Paul Crowleycc701552016-05-17 14:18:49 -07002829 public void addUserKeyAuth(int userId, int serialNumber, byte[] token, byte[] secret) {
Paul Crowleyfaeb3eb2016-02-08 15:58:29 +00002830 enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
Paul Crowleyfaeb3eb2016-02-08 15:58:29 +00002831
2832 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002833 mVold.addUserKeyAuth(userId, serialNumber, encodeBytes(token), encodeBytes(secret));
Jeff Sharkey43e12112017-09-12 16:31:45 -06002834 } catch (Exception e) {
2835 Slog.wtf(TAG, e);
Paul Crowleycc701552016-05-17 14:18:49 -07002836 }
2837 }
2838
2839 /*
2840 * Delete all disk encryption token/secret pairs except the most recently added one
2841 */
2842 @Override
2843 public void fixateNewestUserKeyAuth(int userId) {
2844 enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
Paul Crowleycc701552016-05-17 14:18:49 -07002845
2846 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002847 mVold.fixateNewestUserKeyAuth(userId);
Jeff Sharkey43e12112017-09-12 16:31:45 -06002848 } catch (Exception e) {
2849 Slog.wtf(TAG, e);
Paul Crowleyfaeb3eb2016-02-08 15:58:29 +00002850 }
2851 }
2852
2853 @Override
2854 public void unlockUserKey(int userId, int serialNumber, byte[] token, byte[] secret) {
Sudheer Shanka03b20ec2019-02-21 15:11:00 -08002855 Slog.d(TAG, "unlockUserKey: " + userId);
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002856 enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002857
Jeff Sharkeyce18c812016-04-27 16:00:41 -06002858 if (StorageManager.isFileEncryptedNativeOrEmulated()) {
Rubin Xu3bf722a2016-12-15 16:07:38 +00002859 // When a user has secure lock screen, require secret to actually unlock.
2860 // This check is mostly in place for emulation mode.
2861 if (mLockPatternUtils.isSecure(userId) && ArrayUtils.isEmpty(secret)) {
2862 throw new IllegalStateException("Secret required to unlock secure user " + userId);
Jeff Sharkeyce18c812016-04-27 16:00:41 -06002863 }
Jeff Sharkeyb9fe5372015-12-03 15:23:08 -07002864
Jeff Sharkeyce18c812016-04-27 16:00:41 -06002865 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002866 mVold.unlockUserKey(userId, serialNumber, encodeBytes(token),
2867 encodeBytes(secret));
Jeff Sharkey43e12112017-09-12 16:31:45 -06002868 } catch (Exception e) {
2869 Slog.wtf(TAG, e);
2870 return;
Jeff Sharkeyce18c812016-04-27 16:00:41 -06002871 }
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002872 }
2873
2874 synchronized (mLock) {
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07002875 mLocalUnlockedUsers = ArrayUtils.appendInt(mLocalUnlockedUsers, userId);
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002876 }
2877 }
2878
2879 @Override
2880 public void lockUserKey(int userId) {
2881 enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002882
2883 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002884 mVold.lockUserKey(userId);
Jeff Sharkey43e12112017-09-12 16:31:45 -06002885 } catch (Exception e) {
2886 Slog.wtf(TAG, e);
2887 return;
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002888 }
2889
2890 synchronized (mLock) {
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07002891 mLocalUnlockedUsers = ArrayUtils.removeInt(mLocalUnlockedUsers, userId);
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002892 }
2893 }
2894
2895 @Override
2896 public boolean isUserKeyUnlocked(int userId) {
Jeff Sharkeyce18c812016-04-27 16:00:41 -06002897 synchronized (mLock) {
2898 return ArrayUtils.contains(mLocalUnlockedUsers, userId);
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002899 }
2900 }
2901
2902 @Override
Jeff Sharkey47f71082016-02-01 17:03:54 -07002903 public void prepareUserStorage(String volumeUuid, int userId, int serialNumber, int flags) {
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002904 enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002905
2906 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002907 mVold.prepareUserStorage(volumeUuid, userId, serialNumber, flags);
Jeff Sharkey43e12112017-09-12 16:31:45 -06002908 } catch (Exception e) {
2909 Slog.wtf(TAG, e);
Paul Crowley7ec733f2015-05-19 12:42:00 +01002910 }
2911 }
2912
Paul Crowleybcf48ed2015-04-22 13:36:59 +01002913 @Override
Jeff Sharkeyfcf1e552016-04-14 20:44:58 -06002914 public void destroyUserStorage(String volumeUuid, int userId, int flags) {
2915 enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
Jeff Sharkeyfcf1e552016-04-14 20:44:58 -06002916
2917 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002918 mVold.destroyUserStorage(volumeUuid, userId, flags);
Jeff Sharkey43e12112017-09-12 16:31:45 -06002919 } catch (Exception e) {
2920 Slog.wtf(TAG, e);
Jeff Sharkeyfcf1e552016-04-14 20:44:58 -06002921 }
2922 }
2923
Daichi Hironoe56740d2017-02-02 13:56:45 +09002924 class AppFuseMountScope extends AppFuseBridge.MountScope {
Daichi Hirono812c95d2017-02-08 16:20:20 +09002925 boolean opened = false;
2926
Ryo Hashimoto38bcbf02018-05-16 18:20:37 +09002927 public AppFuseMountScope(int uid, int mountId) {
2928 super(uid, mountId);
Daichi Hirono812c95d2017-02-08 16:20:20 +09002929 }
2930
2931 @Override
2932 public ParcelFileDescriptor open() throws NativeDaemonConnectorException {
Jeff Sharkey54402792017-09-15 16:05:19 -06002933 try {
2934 return new ParcelFileDescriptor(
Ryo Hashimoto38bcbf02018-05-16 18:20:37 +09002935 mVold.mountAppFuse(uid, mountId));
Jeff Sharkey54402792017-09-15 16:05:19 -06002936 } catch (Exception e) {
2937 throw new NativeDaemonConnectorException("Failed to mount", e);
Daichi Hirono812c95d2017-02-08 16:20:20 +09002938 }
Daichi Hirono9fb00182016-11-08 14:12:17 +09002939 }
2940
2941 @Override
Ryo Hashimoto38bcbf02018-05-16 18:20:37 +09002942 public ParcelFileDescriptor openFile(int mountId, int fileId, int flags)
2943 throws NativeDaemonConnectorException {
2944 try {
2945 return new ParcelFileDescriptor(
2946 mVold.openAppFuseFile(uid, mountId, fileId, flags));
2947 } catch (Exception e) {
2948 throw new NativeDaemonConnectorException("Failed to open", e);
2949 }
2950 }
2951
2952 @Override
Daichi Hironoe56740d2017-02-02 13:56:45 +09002953 public void close() throws Exception {
Daichi Hirono812c95d2017-02-08 16:20:20 +09002954 if (opened) {
Ryo Hashimoto38bcbf02018-05-16 18:20:37 +09002955 mVold.unmountAppFuse(uid, mountId);
Daichi Hirono812c95d2017-02-08 16:20:20 +09002956 opened = false;
2957 }
Daichi Hirono9fb00182016-11-08 14:12:17 +09002958 }
2959 }
2960
2961 @Override
Daichi Hirono812c95d2017-02-08 16:20:20 +09002962 public @Nullable AppFuseMount mountProxyFileDescriptorBridge() {
Daichi Hironoe56740d2017-02-02 13:56:45 +09002963 Slog.v(TAG, "mountProxyFileDescriptorBridge");
Daichi Hirono9fb00182016-11-08 14:12:17 +09002964 final int uid = Binder.getCallingUid();
Daichi Hirono9fb00182016-11-08 14:12:17 +09002965
Daichi Hironoe56740d2017-02-02 13:56:45 +09002966 while (true) {
2967 synchronized (mAppFuseLock) {
2968 boolean newlyCreated = false;
2969 if (mAppFuseBridge == null) {
2970 mAppFuseBridge = new AppFuseBridge();
2971 new Thread(mAppFuseBridge, AppFuseBridge.TAG).start();
2972 newlyCreated = true;
Daichi Hirono9fb00182016-11-08 14:12:17 +09002973 }
Daichi Hironoe56740d2017-02-02 13:56:45 +09002974 try {
2975 final int name = mNextAppFuseName++;
2976 try {
2977 return new AppFuseMount(
Ryo Hashimoto38bcbf02018-05-16 18:20:37 +09002978 name, mAppFuseBridge.addBridge(new AppFuseMountScope(uid, name)));
Daichi Hirono812c95d2017-02-08 16:20:20 +09002979 } catch (FuseUnavailableMountException e) {
Daichi Hironoe56740d2017-02-02 13:56:45 +09002980 if (newlyCreated) {
2981 // If newly created bridge fails, it's a real error.
Daichi Hirono812c95d2017-02-08 16:20:20 +09002982 Slog.e(TAG, "", e);
2983 return null;
Daichi Hironoe56740d2017-02-02 13:56:45 +09002984 }
2985 // It seems the thread of mAppFuseBridge has already been terminated.
2986 mAppFuseBridge = null;
2987 }
2988 } catch (NativeDaemonConnectorException e) {
2989 throw e.rethrowAsParcelableException();
2990 }
Daichi Hirono9fb00182016-11-08 14:12:17 +09002991 }
Daichi Hirono9fb00182016-11-08 14:12:17 +09002992 }
2993 }
2994
2995 @Override
Daichi Hirono812c95d2017-02-08 16:20:20 +09002996 public @Nullable ParcelFileDescriptor openProxyFileDescriptor(
2997 int mountId, int fileId, int mode) {
2998 Slog.v(TAG, "mountProxyFileDescriptor");
Jeff Sharkey39466322018-12-05 19:19:52 -07002999
3000 // We only support a narrow set of incoming mode flags
Jeff Sharkey3b1c2542018-12-13 15:01:38 -07003001 mode &= MODE_READ_WRITE;
Jeff Sharkey39466322018-12-05 19:19:52 -07003002
Daichi Hirono9fb00182016-11-08 14:12:17 +09003003 try {
3004 synchronized (mAppFuseLock) {
Daichi Hironoe56740d2017-02-02 13:56:45 +09003005 if (mAppFuseBridge == null) {
Daichi Hirono812c95d2017-02-08 16:20:20 +09003006 Slog.e(TAG, "FuseBridge has not been created");
3007 return null;
Daichi Hirono9fb00182016-11-08 14:12:17 +09003008 }
Ryo Hashimoto38bcbf02018-05-16 18:20:37 +09003009 return mAppFuseBridge.openFile(mountId, fileId, mode);
Daichi Hirono9fb00182016-11-08 14:12:17 +09003010 }
Daichi Hirono812c95d2017-02-08 16:20:20 +09003011 } catch (FuseUnavailableMountException | InterruptedException error) {
3012 Slog.v(TAG, "The mount point has already been invalid", error);
3013 return null;
Daichi Hirono9fb00182016-11-08 14:12:17 +09003014 }
3015 }
3016
Daichi Hirono9e8d9e22015-11-13 14:37:00 +09003017 @Override
Jeff Sharkeyae266462017-11-27 13:32:24 -07003018 public void mkdirs(String callingPkg, String appPath) {
Sudheer Shankaa63bfb32019-02-28 11:15:58 -08003019 final int callingPid = Binder.getCallingPid();
3020 final int callingUid = Binder.getCallingUid();
3021 final int userId = UserHandle.getUserId(callingUid);
Jeff Sharkey2d8b4e82013-09-17 17:30:33 -07003022 final UserEnvironment userEnv = new UserEnvironment(userId);
Farid Zare Seisanac094512018-04-02 15:06:13 -07003023 final String propertyName = "sys.user." + userId + ".ce_available";
Jeff Sharkey2d8b4e82013-09-17 17:30:33 -07003024
Jeff Sharkey196c7552018-03-26 15:56:50 -06003025 // Ignore requests to create directories while storage is locked
Farid Zare Seisanac094512018-04-02 15:06:13 -07003026 if (!isUserKeyUnlocked(userId)) {
3027 throw new IllegalStateException("Failed to prepare " + appPath);
3028 }
3029
3030 // Ignore requests to create directories if CE storage is not available
Farid Zare Seisan7f6b8122018-03-30 11:19:10 -07003031 if ((userId == UserHandle.USER_SYSTEM)
3032 && !SystemProperties.getBoolean(propertyName, false)) {
Farid Zare Seisanac094512018-04-02 15:06:13 -07003033 throw new IllegalStateException("Failed to prepare " + appPath);
3034 }
Jeff Sharkey196c7552018-03-26 15:56:50 -06003035
Jeff Sharkey2d8b4e82013-09-17 17:30:33 -07003036 // Validate that reported package name belongs to caller
3037 final AppOpsManager appOps = (AppOpsManager) mContext.getSystemService(
3038 Context.APP_OPS_SERVICE);
Sudheer Shankaa63bfb32019-02-28 11:15:58 -08003039 appOps.checkPackage(callingUid, callingPkg);
Jeff Sharkey2d8b4e82013-09-17 17:30:33 -07003040
Jeff Sharkey48877892015-03-18 11:27:19 -07003041 File appFile = null;
Jeff Sharkey2d8b4e82013-09-17 17:30:33 -07003042 try {
Jeff Sharkey48877892015-03-18 11:27:19 -07003043 appFile = new File(appPath).getCanonicalFile();
Jeff Sharkey2d8b4e82013-09-17 17:30:33 -07003044 } catch (IOException e) {
Jeff Sharkeyae266462017-11-27 13:32:24 -07003045 throw new IllegalStateException("Failed to resolve " + appPath + ": " + e);
Jeff Sharkey2d8b4e82013-09-17 17:30:33 -07003046 }
3047
3048 // Try translating the app path into a vold path, but require that it
3049 // belong to the calling package.
Jeff Sharkey48877892015-03-18 11:27:19 -07003050 if (FileUtils.contains(userEnv.buildExternalStorageAppDataDirs(callingPkg), appFile) ||
3051 FileUtils.contains(userEnv.buildExternalStorageAppObbDirs(callingPkg), appFile) ||
3052 FileUtils.contains(userEnv.buildExternalStorageAppMediaDirs(callingPkg), appFile)) {
3053 appPath = appFile.getAbsolutePath();
3054 if (!appPath.endsWith("/")) {
3055 appPath = appPath + "/";
3056 }
3057
Sudheer Shankaa63bfb32019-02-28 11:15:58 -08003058 final String systemPath = translateAppToSystem(appPath, callingPid, callingUid);
3059
Jeff Sharkey2d8b4e82013-09-17 17:30:33 -07003060 try {
Sudheer Shankaa63bfb32019-02-28 11:15:58 -08003061 mVold.mkdirs(systemPath);
Jeff Sharkey27a108c2017-11-30 17:11:40 -07003062 return;
Jeff Sharkeyace874b2017-09-07 15:27:33 -06003063 } catch (Exception e) {
Sudheer Shankaa63bfb32019-02-28 11:15:58 -08003064 throw new IllegalStateException("Failed to prepare " + systemPath + ": " + e);
Jeff Sharkey2d8b4e82013-09-17 17:30:33 -07003065 }
3066 }
3067
Jeff Sharkey48877892015-03-18 11:27:19 -07003068 throw new SecurityException("Invalid mkdirs path: " + appFile);
Jeff Sharkey2d8b4e82013-09-17 17:30:33 -07003069 }
3070
3071 @Override
Jeff Sharkey46349872015-07-28 10:49:47 -07003072 public StorageVolume[] getVolumeList(int uid, String packageName, int flags) {
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07003073 final int userId = UserHandle.getUserId(uid);
Jeff Sharkeyc02bfae2016-03-27 15:06:53 -06003074
Jeff Sharkey46349872015-07-28 10:49:47 -07003075 final boolean forWrite = (flags & StorageManager.FLAG_FOR_WRITE) != 0;
Jeff Sharkeyc02bfae2016-03-27 15:06:53 -06003076 final boolean realState = (flags & StorageManager.FLAG_REAL_STATE) != 0;
3077 final boolean includeInvisible = (flags & StorageManager.FLAG_INCLUDE_INVISIBLE) != 0;
Jeff Sharkey46349872015-07-28 10:49:47 -07003078
Jeff Sharkeyc02bfae2016-03-27 15:06:53 -06003079 final boolean userKeyUnlocked;
3080 final boolean storagePermission;
3081 final long token = Binder.clearCallingIdentity();
Svetoslav38c3dbb2015-07-14 11:27:06 -07003082 try {
Jeff Sharkeyc02bfae2016-03-27 15:06:53 -06003083 userKeyUnlocked = isUserKeyUnlocked(userId);
Sudheer Shanka2250d562016-11-07 15:41:02 -08003084 storagePermission = mStorageManagerInternal.hasExternalStorage(uid, packageName);
Svetoslav38c3dbb2015-07-14 11:27:06 -07003085 } finally {
Jeff Sharkeyc02bfae2016-03-27 15:06:53 -06003086 Binder.restoreCallingIdentity(token);
Svetoslav38c3dbb2015-07-14 11:27:06 -07003087 }
Svet Ganov6ee871e2015-07-10 14:29:33 -07003088
Jeff Sharkeyc02bfae2016-03-27 15:06:53 -06003089 boolean foundPrimary = false;
3090
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07003091 final ArrayList<StorageVolume> res = new ArrayList<>();
Jeff Sharkey48877892015-03-18 11:27:19 -07003092 synchronized (mLock) {
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07003093 for (int i = 0; i < mVolumes.size(); i++) {
3094 final VolumeInfo vol = mVolumes.valueAt(i);
Jeff Sharkeyc02bfae2016-03-27 15:06:53 -06003095 switch (vol.getType()) {
3096 case VolumeInfo.TYPE_PUBLIC:
Risan05c41e62018-10-29 08:57:43 +09003097 case VolumeInfo.TYPE_STUB:
Jeff Sharkeyc02bfae2016-03-27 15:06:53 -06003098 case VolumeInfo.TYPE_EMULATED:
3099 break;
3100 default:
3101 continue;
3102 }
3103
3104 boolean match = false;
3105 if (forWrite) {
3106 match = vol.isVisibleForWrite(userId);
3107 } else {
Felipe Leme123a0e72016-06-10 11:09:11 -07003108 match = vol.isVisibleForRead(userId)
3109 || (includeInvisible && vol.getPath() != null);
Jeff Sharkeyc02bfae2016-03-27 15:06:53 -06003110 }
3111 if (!match) continue;
3112
3113 boolean reportUnmounted = false;
3114 if ((vol.getType() == VolumeInfo.TYPE_EMULATED) && !userKeyUnlocked) {
3115 reportUnmounted = true;
3116 } else if (!storagePermission && !realState) {
3117 reportUnmounted = true;
3118 }
3119
3120 final StorageVolume userVol = vol.buildStorageVolume(mContext, userId,
3121 reportUnmounted);
3122 if (vol.isPrimary()) {
3123 res.add(0, userVol);
3124 foundPrimary = true;
3125 } else {
3126 res.add(userVol);
Jeff Sharkeyb049e212012-09-07 23:16:01 -07003127 }
Mike Lockwood8fa5f802011-03-24 08:12:30 -07003128 }
Mike Lockwood8fa5f802011-03-24 08:12:30 -07003129 }
Jeff Sharkey48877892015-03-18 11:27:19 -07003130
3131 if (!foundPrimary) {
Jeff Sharkey11697f52018-12-13 10:14:42 -07003132 Slog.w(TAG, "No primary storage defined yet; hacking together a stub");
Jeff Sharkey48877892015-03-18 11:27:19 -07003133
3134 final boolean primaryPhysical = SystemProperties.getBoolean(
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07003135 StorageManager.PROP_PRIMARY_PHYSICAL, false);
Jeff Sharkey48877892015-03-18 11:27:19 -07003136
3137 final String id = "stub_primary";
3138 final File path = Environment.getLegacyExternalStorageDirectory();
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07003139 final String description = mContext.getString(android.R.string.unknownName);
Jeff Sharkey48877892015-03-18 11:27:19 -07003140 final boolean primary = true;
3141 final boolean removable = primaryPhysical;
3142 final boolean emulated = !primaryPhysical;
Jeff Sharkey48877892015-03-18 11:27:19 -07003143 final boolean allowMassStorage = false;
3144 final long maxFileSize = 0L;
3145 final UserHandle owner = new UserHandle(userId);
3146 final String uuid = null;
Jeff Sharkey48877892015-03-18 11:27:19 -07003147 final String state = Environment.MEDIA_REMOVED;
3148
Jerry Zhang71938e12018-05-10 18:28:29 -07003149 res.add(0, new StorageVolume(id, path, path,
Jerry Zhangf9c5c252017-08-16 18:07:51 -07003150 description, primary, removable, emulated,
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07003151 allowMassStorage, maxFileSize, owner, uuid, state));
Jeff Sharkey48877892015-03-18 11:27:19 -07003152 }
3153
3154 return res.toArray(new StorageVolume[res.size()]);
Mike Lockwood8fa5f802011-03-24 08:12:30 -07003155 }
3156
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07003157 @Override
3158 public DiskInfo[] getDisks() {
3159 synchronized (mLock) {
3160 final DiskInfo[] res = new DiskInfo[mDisks.size()];
3161 for (int i = 0; i < mDisks.size(); i++) {
3162 res[i] = mDisks.valueAt(i);
3163 }
3164 return res;
3165 }
3166 }
3167
3168 @Override
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07003169 public VolumeInfo[] getVolumes(int flags) {
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07003170 synchronized (mLock) {
3171 final VolumeInfo[] res = new VolumeInfo[mVolumes.size()];
3172 for (int i = 0; i < mVolumes.size(); i++) {
3173 res[i] = mVolumes.valueAt(i);
3174 }
3175 return res;
3176 }
3177 }
3178
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07003179 @Override
3180 public VolumeRecord[] getVolumeRecords(int flags) {
3181 synchronized (mLock) {
3182 final VolumeRecord[] res = new VolumeRecord[mRecords.size()];
3183 for (int i = 0; i < mRecords.size(); i++) {
3184 res[i] = mRecords.valueAt(i);
3185 }
3186 return res;
3187 }
3188 }
3189
Jeff Sharkey9bed0702017-01-23 20:37:05 -07003190 @Override
3191 public long getCacheQuotaBytes(String volumeUuid, int uid) {
3192 if (uid != Binder.getCallingUid()) {
3193 mContext.enforceCallingPermission(android.Manifest.permission.STORAGE_INTERNAL, TAG);
3194 }
Daniel Nishi80fdb012017-03-09 14:30:07 -08003195 final long token = Binder.clearCallingIdentity();
3196 final StorageStatsManager stats = mContext.getSystemService(StorageStatsManager.class);
3197 try {
3198 return stats.getCacheQuotaBytes(volumeUuid, uid);
3199 } finally {
3200 Binder.restoreCallingIdentity(token);
3201 }
Jeff Sharkey9bed0702017-01-23 20:37:05 -07003202 }
3203
3204 @Override
3205 public long getCacheSizeBytes(String volumeUuid, int uid) {
3206 if (uid != Binder.getCallingUid()) {
3207 mContext.enforceCallingPermission(android.Manifest.permission.STORAGE_INTERNAL, TAG);
3208 }
3209 final long token = Binder.clearCallingIdentity();
3210 try {
3211 return mContext.getSystemService(StorageStatsManager.class)
3212 .queryStatsForUid(volumeUuid, uid).getCacheBytes();
Jeff Sharkey789a8fc2017-04-16 13:18:35 -06003213 } catch (IOException e) {
3214 throw new ParcelableException(e);
Jeff Sharkey9bed0702017-01-23 20:37:05 -07003215 } finally {
3216 Binder.restoreCallingIdentity(token);
3217 }
3218 }
3219
Jeff Sharkey35e46d22017-06-09 10:01:20 -06003220 private int adjustAllocateFlags(int flags, int callingUid, String callingPackage) {
3221 // Require permission to allocate aggressively
3222 if ((flags & StorageManager.FLAG_ALLOCATE_AGGRESSIVE) != 0) {
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07003223 mContext.enforceCallingOrSelfPermission(
3224 android.Manifest.permission.ALLOCATE_AGGRESSIVE, TAG);
3225 }
3226
Jeff Sharkey35e46d22017-06-09 10:01:20 -06003227 // Apps normally can't directly defy reserved space
3228 flags &= ~StorageManager.FLAG_ALLOCATE_DEFY_ALL_RESERVED;
3229 flags &= ~StorageManager.FLAG_ALLOCATE_DEFY_HALF_RESERVED;
3230
3231 // However, if app is actively using the camera, then we're willing to
3232 // clear up to half of the reserved cache space, since the user might be
3233 // trying to capture an important memory.
3234 final AppOpsManager appOps = mContext.getSystemService(AppOpsManager.class);
3235 final long token = Binder.clearCallingIdentity();
3236 try {
3237 if (appOps.isOperationActive(AppOpsManager.OP_CAMERA, callingUid, callingPackage)) {
3238 Slog.d(TAG, "UID " + callingUid + " is actively using camera;"
3239 + " letting them defy reserved cached data");
3240 flags |= StorageManager.FLAG_ALLOCATE_DEFY_HALF_RESERVED;
3241 }
3242 } finally {
3243 Binder.restoreCallingIdentity(token);
3244 }
3245
3246 return flags;
3247 }
3248
3249 @Override
3250 public long getAllocatableBytes(String volumeUuid, int flags, String callingPackage) {
3251 flags = adjustAllocateFlags(flags, Binder.getCallingUid(), callingPackage);
3252
3253 final StorageManager storage = mContext.getSystemService(StorageManager.class);
3254 final StorageStatsManager stats = mContext.getSystemService(StorageStatsManager.class);
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07003255 final long token = Binder.clearCallingIdentity();
3256 try {
3257 // In general, apps can allocate as much space as they want, except
3258 // we never let them eat into either the minimum cache space or into
Jeff Sharkeyddff8072017-05-26 13:10:46 -06003259 // the low disk warning space. To avoid user confusion, this logic
3260 // should be kept in sync with getFreeBytes().
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07003261 final File path = storage.findPathForUuid(volumeUuid);
Jeff Sharkeyddff8072017-05-26 13:10:46 -06003262
3263 final long usable = path.getUsableSpace();
3264 final long lowReserved = storage.getStorageLowBytes(path);
3265 final long fullReserved = storage.getStorageFullBytes(path);
3266
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07003267 if (stats.isQuotaSupported(volumeUuid)) {
Jeff Sharkeyddff8072017-05-26 13:10:46 -06003268 final long cacheTotal = stats.getCacheBytes(volumeUuid);
Jeff Sharkey35e46d22017-06-09 10:01:20 -06003269 final long cacheReserved = storage.getStorageCacheBytes(path, flags);
Jeff Sharkeyddff8072017-05-26 13:10:46 -06003270 final long cacheClearable = Math.max(0, cacheTotal - cacheReserved);
3271
Jeff Sharkey35e46d22017-06-09 10:01:20 -06003272 if ((flags & StorageManager.FLAG_ALLOCATE_AGGRESSIVE) != 0) {
3273 return Math.max(0, (usable + cacheClearable) - fullReserved);
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07003274 } else {
Jeff Sharkeyddff8072017-05-26 13:10:46 -06003275 return Math.max(0, (usable + cacheClearable) - lowReserved);
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07003276 }
3277 } else {
3278 // When we don't have fast quota information, we ignore cached
3279 // data and only consider unused bytes.
Jeff Sharkey35e46d22017-06-09 10:01:20 -06003280 if ((flags & StorageManager.FLAG_ALLOCATE_AGGRESSIVE) != 0) {
Jeff Sharkeyddff8072017-05-26 13:10:46 -06003281 return Math.max(0, usable - fullReserved);
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07003282 } else {
Jeff Sharkeyddff8072017-05-26 13:10:46 -06003283 return Math.max(0, usable - lowReserved);
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07003284 }
3285 }
Jeff Sharkey789a8fc2017-04-16 13:18:35 -06003286 } catch (IOException e) {
3287 throw new ParcelableException(e);
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07003288 } finally {
3289 Binder.restoreCallingIdentity(token);
3290 }
Jeff Sharkey500ce9e2017-02-12 02:39:24 -07003291 }
3292
3293 @Override
Jeff Sharkey35e46d22017-06-09 10:01:20 -06003294 public void allocateBytes(String volumeUuid, long bytes, int flags, String callingPackage) {
3295 flags = adjustAllocateFlags(flags, Binder.getCallingUid(), callingPackage);
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07003296
Jeff Sharkey35e46d22017-06-09 10:01:20 -06003297 final long allocatableBytes = getAllocatableBytes(volumeUuid, flags, callingPackage);
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07003298 if (bytes > allocatableBytes) {
3299 throw new ParcelableException(new IOException("Failed to allocate " + bytes
3300 + " because only " + allocatableBytes + " allocatable"));
3301 }
3302
Jeff Sharkey35e46d22017-06-09 10:01:20 -06003303 final StorageManager storage = mContext.getSystemService(StorageManager.class);
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07003304 final long token = Binder.clearCallingIdentity();
3305 try {
Jeff Sharkey789a8fc2017-04-16 13:18:35 -06003306 // Free up enough disk space to satisfy both the requested allocation
3307 // and our low disk warning space.
3308 final File path = storage.findPathForUuid(volumeUuid);
Jeff Sharkeyddff8072017-05-26 13:10:46 -06003309 if ((flags & StorageManager.FLAG_ALLOCATE_AGGRESSIVE) != 0) {
3310 bytes += storage.getStorageFullBytes(path);
3311 } else {
3312 bytes += storage.getStorageLowBytes(path);
3313 }
Jeff Sharkey789a8fc2017-04-16 13:18:35 -06003314
Jeff Sharkey5790af02018-08-13 17:42:54 -06003315 mPmInternal.freeStorage(volumeUuid, bytes, flags);
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07003316 } catch (IOException e) {
3317 throw new ParcelableException(e);
3318 } finally {
3319 Binder.restoreCallingIdentity(token);
Jeff Sharkey500ce9e2017-02-12 02:39:24 -07003320 }
3321 }
3322
Sudheer Shankaff971bc2018-12-13 17:39:59 -08003323 private IAppOpsCallback.Stub mAppOpsCallback = new IAppOpsCallback.Stub() {
3324 @Override
3325 public void opChanged(int op, int uid, String packageName) throws RemoteException {
3326 if (!ENABLE_ISOLATED_STORAGE) return;
3327
3328 remountUidExternalStorage(uid, getMountMode(uid, packageName));
3329 }
3330 };
3331
Jeff Sharkey5790af02018-08-13 17:42:54 -06003332 private static final Pattern PATTERN_TRANSLATE = Pattern.compile(
3333 "(?i)^(/storage/[^/]+/(?:[0-9]+/)?)(.*)");
3334
3335 @Override
Sudheer Shanka87915d62018-11-06 10:57:35 -08003336 public String translateAppToSystem(String path, int pid, int uid) {
3337 return translateInternal(path, pid, uid, true);
Jeff Sharkey5790af02018-08-13 17:42:54 -06003338 }
3339
3340 @Override
Sudheer Shanka87915d62018-11-06 10:57:35 -08003341 public String translateSystemToApp(String path, int pid, int uid) {
3342 return translateInternal(path, pid, uid, false);
Jeff Sharkey5790af02018-08-13 17:42:54 -06003343 }
3344
Sudheer Shanka87915d62018-11-06 10:57:35 -08003345 private String translateInternal(String path, int pid, int uid, boolean toSystem) {
Jeff Sharkey5790af02018-08-13 17:42:54 -06003346 if (!ENABLE_ISOLATED_STORAGE) return path;
3347
3348 if (path.contains("/../")) {
3349 throw new SecurityException("Shady looking path " + path);
3350 }
3351
Sudheer Shanka3a0df3b2018-12-12 12:43:43 -08003352 final int mountMode = mAmInternal.getStorageMountMode(pid, uid);
Sudheer Shanka0b6da532019-01-09 12:06:51 -08003353 if (mountMode == Zygote.MOUNT_EXTERNAL_FULL
3354 || mountMode == Zygote.MOUNT_EXTERNAL_LEGACY) {
Sudheer Shanka87915d62018-11-06 10:57:35 -08003355 return path;
3356 }
Jeff Sharkey5790af02018-08-13 17:42:54 -06003357
3358 final Matcher m = PATTERN_TRANSLATE.matcher(path);
3359 if (m.matches()) {
3360 final String device = m.group(1);
3361 final String devicePath = m.group(2);
3362
Sudheer Shanka3a0df3b2018-12-12 12:43:43 -08003363 if (mountMode == Zygote.MOUNT_EXTERNAL_INSTALLER
3364 && devicePath.startsWith("Android/obb/")) {
3365 return path;
3366 }
3367
Jeff Sharkey5790af02018-08-13 17:42:54 -06003368 // Does path belong to any packages belonging to this UID? If so,
3369 // they get to go straight through to legacy paths.
Sudheer Shanka87915d62018-11-06 10:57:35 -08003370 final String[] pkgs = mContext.getPackageManager().getPackagesForUid(uid);
Jeff Sharkey5790af02018-08-13 17:42:54 -06003371 for (String pkg : pkgs) {
3372 if (devicePath.startsWith("Android/data/" + pkg + "/") ||
3373 devicePath.startsWith("Android/media/" + pkg + "/") ||
3374 devicePath.startsWith("Android/obb/" + pkg + "/")) {
3375 return path;
3376 }
3377 }
3378
Sudheer Shanka87915d62018-11-06 10:57:35 -08003379 final String sharedUserId = mPmInternal.getSharedUserIdForPackage(pkgs[0]);
3380 final String sandboxId = getSandboxId(pkgs[0], sharedUserId);
3381
Jeff Sharkey5790af02018-08-13 17:42:54 -06003382 if (toSystem) {
3383 // Everything else goes into sandbox.
Sudheer Shanka31ad0a12018-10-20 20:59:00 -07003384 return device + "Android/sandbox/" + sandboxId + "/" + devicePath;
Jeff Sharkey5790af02018-08-13 17:42:54 -06003385 } else {
3386 // Does path belong to this sandbox? If so, leave sandbox.
Sudheer Shanka31ad0a12018-10-20 20:59:00 -07003387 final String sandboxPrefix = "Android/sandbox/" + sandboxId + "/";
Jeff Sharkey5790af02018-08-13 17:42:54 -06003388 if (devicePath.startsWith(sandboxPrefix)) {
3389 return device + devicePath.substring(sandboxPrefix.length());
3390 }
3391
3392 // Path isn't valid inside sandbox!
3393 throw new SecurityException(
3394 "Path " + path + " isn't valid inside sandbox " + sandboxId);
3395 }
3396 }
3397
3398 return path;
3399 }
3400
Kenny Rootaf9d6672010-10-08 09:21:39 -07003401 private void addObbStateLocked(ObbState obbState) throws RemoteException {
3402 final IBinder binder = obbState.getBinder();
3403 List<ObbState> obbStates = mObbMounts.get(binder);
Kenny Root5919ac62010-10-05 09:49:40 -07003404
Kenny Rootaf9d6672010-10-08 09:21:39 -07003405 if (obbStates == null) {
3406 obbStates = new ArrayList<ObbState>();
3407 mObbMounts.put(binder, obbStates);
3408 } else {
3409 for (final ObbState o : obbStates) {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003410 if (o.rawPath.equals(obbState.rawPath)) {
Kenny Rootaf9d6672010-10-08 09:21:39 -07003411 throw new IllegalStateException("Attempt to add ObbState twice. "
Sudheer Shanka2250d562016-11-07 15:41:02 -08003412 + "This indicates an error in the StorageManagerService logic.");
Kenny Root5919ac62010-10-05 09:49:40 -07003413 }
3414 }
Kenny Roota02b8b02010-08-05 16:14:17 -07003415 }
Kenny Rootaf9d6672010-10-08 09:21:39 -07003416
3417 obbStates.add(obbState);
3418 try {
3419 obbState.link();
3420 } catch (RemoteException e) {
3421 /*
3422 * The binder died before we could link it, so clean up our state
3423 * and return failure.
3424 */
3425 obbStates.remove(obbState);
3426 if (obbStates.isEmpty()) {
3427 mObbMounts.remove(binder);
3428 }
3429
3430 // Rethrow the error so mountObb can get it
3431 throw e;
3432 }
3433
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003434 mObbPathToStateMap.put(obbState.rawPath, obbState);
Kenny Roota02b8b02010-08-05 16:14:17 -07003435 }
3436
Kenny Rootaf9d6672010-10-08 09:21:39 -07003437 private void removeObbStateLocked(ObbState obbState) {
3438 final IBinder binder = obbState.getBinder();
3439 final List<ObbState> obbStates = mObbMounts.get(binder);
3440 if (obbStates != null) {
3441 if (obbStates.remove(obbState)) {
3442 obbState.unlink();
Kenny Root05105f72010-09-22 17:29:43 -07003443 }
Kenny Rootaf9d6672010-10-08 09:21:39 -07003444 if (obbStates.isEmpty()) {
3445 mObbMounts.remove(binder);
3446 }
Kenny Roota02b8b02010-08-05 16:14:17 -07003447 }
Kenny Roota02b8b02010-08-05 16:14:17 -07003448
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003449 mObbPathToStateMap.remove(obbState.rawPath);
Kenny Root38cf8862010-09-26 14:18:51 -07003450 }
3451
Kenny Roota02b8b02010-08-05 16:14:17 -07003452 private class ObbActionHandler extends Handler {
Kenny Roota02b8b02010-08-05 16:14:17 -07003453
3454 ObbActionHandler(Looper l) {
3455 super(l);
3456 }
3457
3458 @Override
3459 public void handleMessage(Message msg) {
3460 switch (msg.what) {
3461 case OBB_RUN_ACTION: {
Kenny Root480afe72010-10-07 10:17:50 -07003462 final ObbAction action = (ObbAction) msg.obj;
Kenny Roota02b8b02010-08-05 16:14:17 -07003463
3464 if (DEBUG_OBB)
3465 Slog.i(TAG, "OBB_RUN_ACTION: " + action.toString());
3466
Sudheer Shanka25469aa2018-08-27 15:50:23 -07003467 action.execute(this);
Kenny Roota02b8b02010-08-05 16:14:17 -07003468 break;
3469 }
Kenny Rootaf9d6672010-10-08 09:21:39 -07003470 case OBB_FLUSH_MOUNT_STATE: {
3471 final String path = (String) msg.obj;
3472
3473 if (DEBUG_OBB)
3474 Slog.i(TAG, "Flushing all OBB state for path " + path);
3475
3476 synchronized (mObbMounts) {
3477 final List<ObbState> obbStatesToRemove = new LinkedList<ObbState>();
3478
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003479 final Iterator<ObbState> i = mObbPathToStateMap.values().iterator();
Kenny Rootaf9d6672010-10-08 09:21:39 -07003480 while (i.hasNext()) {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003481 final ObbState state = i.next();
Kenny Rootaf9d6672010-10-08 09:21:39 -07003482
3483 /*
3484 * If this entry's source file is in the volume path
3485 * that got unmounted, remove it because it's no
3486 * longer valid.
3487 */
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003488 if (state.canonicalPath.startsWith(path)) {
3489 obbStatesToRemove.add(state);
Kenny Rootaf9d6672010-10-08 09:21:39 -07003490 }
3491 }
3492
3493 for (final ObbState obbState : obbStatesToRemove) {
3494 if (DEBUG_OBB)
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003495 Slog.i(TAG, "Removing state for " + obbState.rawPath);
Kenny Rootaf9d6672010-10-08 09:21:39 -07003496
3497 removeObbStateLocked(obbState);
3498
3499 try {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003500 obbState.token.onObbResult(obbState.rawPath, obbState.nonce,
Kenny Rootaf9d6672010-10-08 09:21:39 -07003501 OnObbStateChangeListener.UNMOUNTED);
3502 } catch (RemoteException e) {
3503 Slog.i(TAG, "Couldn't send unmount notification for OBB: "
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003504 + obbState.rawPath);
Kenny Rootaf9d6672010-10-08 09:21:39 -07003505 }
3506 }
3507 }
3508 break;
3509 }
Kenny Roota02b8b02010-08-05 16:14:17 -07003510 }
3511 }
Kenny Roota02b8b02010-08-05 16:14:17 -07003512 }
3513
Jeff Sharkey0095a822018-02-15 13:06:53 -07003514 private static class ObbException extends Exception {
3515 public final int status;
3516
3517 public ObbException(int status, String message) {
3518 super(message);
3519 this.status = status;
3520 }
3521
3522 public ObbException(int status, Throwable cause) {
3523 super(cause.getMessage(), cause);
3524 this.status = status;
3525 }
3526 }
3527
Kenny Roota02b8b02010-08-05 16:14:17 -07003528 abstract class ObbAction {
Kenny Roota02b8b02010-08-05 16:14:17 -07003529
3530 ObbState mObbState;
3531
3532 ObbAction(ObbState obbState) {
3533 mObbState = obbState;
3534 }
3535
3536 public void execute(ObbActionHandler handler) {
3537 try {
3538 if (DEBUG_OBB)
Ben Komalo444eca22011-09-01 15:17:44 -07003539 Slog.i(TAG, "Starting to execute action: " + toString());
Sudheer Shanka25469aa2018-08-27 15:50:23 -07003540 handleExecute();
Jeff Sharkey0095a822018-02-15 13:06:53 -07003541 } catch (ObbException e) {
3542 notifyObbStateChange(e);
Kenny Roota02b8b02010-08-05 16:14:17 -07003543 }
3544 }
3545
Jeff Sharkey0095a822018-02-15 13:06:53 -07003546 abstract void handleExecute() throws ObbException;
Kenny Root38cf8862010-09-26 14:18:51 -07003547
Jeff Sharkey0095a822018-02-15 13:06:53 -07003548 protected void notifyObbStateChange(ObbException e) {
3549 Slog.w(TAG, e);
3550 notifyObbStateChange(e.status);
3551 }
3552
3553 protected void notifyObbStateChange(int status) {
Kenny Rootaf9d6672010-10-08 09:21:39 -07003554 if (mObbState == null || mObbState.token == null) {
3555 return;
3556 }
3557
Kenny Root38cf8862010-09-26 14:18:51 -07003558 try {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003559 mObbState.token.onObbResult(mObbState.rawPath, mObbState.nonce, status);
Kenny Root38cf8862010-09-26 14:18:51 -07003560 } catch (RemoteException e) {
Sudheer Shanka2250d562016-11-07 15:41:02 -08003561 Slog.w(TAG, "StorageEventListener went away while calling onObbStateChanged");
Kenny Root38cf8862010-09-26 14:18:51 -07003562 }
3563 }
Kenny Roota02b8b02010-08-05 16:14:17 -07003564 }
3565
3566 class MountObbAction extends ObbAction {
Ben Komalo444eca22011-09-01 15:17:44 -07003567 private final String mKey;
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003568 private final int mCallingUid;
Sudheer Shanka25469aa2018-08-27 15:50:23 -07003569 private ObbInfo mObbInfo;
Kenny Roota02b8b02010-08-05 16:14:17 -07003570
Sudheer Shanka25469aa2018-08-27 15:50:23 -07003571 MountObbAction(ObbState obbState, String key, int callingUid, ObbInfo obbInfo) {
Kenny Roota02b8b02010-08-05 16:14:17 -07003572 super(obbState);
3573 mKey = key;
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003574 mCallingUid = callingUid;
Sudheer Shanka25469aa2018-08-27 15:50:23 -07003575 mObbInfo = obbInfo;
Kenny Roota02b8b02010-08-05 16:14:17 -07003576 }
3577
Jason parks5af0b912010-11-29 09:05:25 -06003578 @Override
Jeff Sharkey0095a822018-02-15 13:06:53 -07003579 public void handleExecute() throws ObbException {
Kenny Rootaf9d6672010-10-08 09:21:39 -07003580 warnOnNotMounted();
3581
Sudheer Shanka25469aa2018-08-27 15:50:23 -07003582 if (!isUidOwnerOfPackageOrSystem(mObbInfo.packageName, mCallingUid)) {
Jeff Sharkey0095a822018-02-15 13:06:53 -07003583 throw new ObbException(ERROR_PERMISSION_DENIED, "Denied attempt to mount OBB "
Sudheer Shanka25469aa2018-08-27 15:50:23 -07003584 + mObbInfo.filename + " which is owned by " + mObbInfo.packageName);
Kenny Roota02b8b02010-08-05 16:14:17 -07003585 }
3586
Kenny Rootaf9d6672010-10-08 09:21:39 -07003587 final boolean isMounted;
3588 synchronized (mObbMounts) {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003589 isMounted = mObbPathToStateMap.containsKey(mObbState.rawPath);
Kenny Rootaf9d6672010-10-08 09:21:39 -07003590 }
3591 if (isMounted) {
Jeff Sharkey0095a822018-02-15 13:06:53 -07003592 throw new ObbException(ERROR_ALREADY_MOUNTED,
Sudheer Shanka25469aa2018-08-27 15:50:23 -07003593 "Attempt to mount OBB which is already mounted: " + mObbInfo.filename);
Kenny Rootaf9d6672010-10-08 09:21:39 -07003594 }
3595
Kenny Rootaf9d6672010-10-08 09:21:39 -07003596 final String hashedKey;
Jeff Sharkey41cd6812017-09-11 10:32:17 -06003597 final String binderKey;
Kenny Rootaf9d6672010-10-08 09:21:39 -07003598 if (mKey == null) {
3599 hashedKey = "none";
Jeff Sharkey41cd6812017-09-11 10:32:17 -06003600 binderKey = "";
Kenny Rootaf9d6672010-10-08 09:21:39 -07003601 } else {
Kenny Rootaf9d6672010-10-08 09:21:39 -07003602 try {
Kenny Root3b1abba2010-10-13 15:00:07 -07003603 SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
3604
Sudheer Shanka25469aa2018-08-27 15:50:23 -07003605 KeySpec ks = new PBEKeySpec(mKey.toCharArray(), mObbInfo.salt,
Kenny Root3b1abba2010-10-13 15:00:07 -07003606 PBKDF2_HASH_ROUNDS, CRYPTO_ALGORITHM_KEY_SIZE);
3607 SecretKey key = factory.generateSecret(ks);
3608 BigInteger bi = new BigInteger(key.getEncoded());
3609 hashedKey = bi.toString(16);
Jeff Sharkey41cd6812017-09-11 10:32:17 -06003610 binderKey = hashedKey;
Jeff Sharkey0095a822018-02-15 13:06:53 -07003611 } catch (GeneralSecurityException e) {
3612 throw new ObbException(ERROR_INTERNAL, e);
Kenny Root38cf8862010-09-26 14:18:51 -07003613 }
Kenny Rootaf9d6672010-10-08 09:21:39 -07003614 }
Kenny Root38cf8862010-09-26 14:18:51 -07003615
Kenny Rootaf9d6672010-10-08 09:21:39 -07003616 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06003617 mObbState.volId = mVold.createObb(mObbState.canonicalPath, binderKey,
3618 mObbState.ownerGid);
3619 mVold.mount(mObbState.volId, 0, -1);
Kenny Roota02b8b02010-08-05 16:14:17 -07003620
Kenny Rootaf9d6672010-10-08 09:21:39 -07003621 if (DEBUG_OBB)
Xiaohui Chen621b3fc2015-10-02 14:41:42 -07003622 Slog.d(TAG, "Successfully mounted OBB " + mObbState.canonicalPath);
Kenny Rootaf9d6672010-10-08 09:21:39 -07003623
3624 synchronized (mObbMounts) {
3625 addObbStateLocked(mObbState);
3626 }
3627
Jeff Sharkey0095a822018-02-15 13:06:53 -07003628 notifyObbStateChange(MOUNTED);
3629 } catch (Exception e) {
3630 throw new ObbException(ERROR_COULD_NOT_MOUNT, e);
Kenny Root02c87302010-07-01 08:10:18 -07003631 }
3632 }
3633
Jason parks5af0b912010-11-29 09:05:25 -06003634 @Override
Kenny Roota02b8b02010-08-05 16:14:17 -07003635 public String toString() {
3636 StringBuilder sb = new StringBuilder();
3637 sb.append("MountObbAction{");
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003638 sb.append(mObbState);
Kenny Roota02b8b02010-08-05 16:14:17 -07003639 sb.append('}');
3640 return sb.toString();
3641 }
3642 }
3643
3644 class UnmountObbAction extends ObbAction {
Ben Komalo444eca22011-09-01 15:17:44 -07003645 private final boolean mForceUnmount;
Kenny Roota02b8b02010-08-05 16:14:17 -07003646
3647 UnmountObbAction(ObbState obbState, boolean force) {
3648 super(obbState);
3649 mForceUnmount = force;
3650 }
3651
Jason parks5af0b912010-11-29 09:05:25 -06003652 @Override
Jeff Sharkey0095a822018-02-15 13:06:53 -07003653 public void handleExecute() throws ObbException {
Kenny Rootaf9d6672010-10-08 09:21:39 -07003654 warnOnNotMounted();
3655
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003656 final ObbState existingState;
Kenny Root38cf8862010-09-26 14:18:51 -07003657 synchronized (mObbMounts) {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003658 existingState = mObbPathToStateMap.get(mObbState.rawPath);
Kenny Rootaf9d6672010-10-08 09:21:39 -07003659 }
Kenny Root38cf8862010-09-26 14:18:51 -07003660
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003661 if (existingState == null) {
Jeff Sharkey0095a822018-02-15 13:06:53 -07003662 throw new ObbException(ERROR_NOT_MOUNTED, "Missing existingState");
Kenny Rootaf9d6672010-10-08 09:21:39 -07003663 }
3664
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003665 if (existingState.ownerGid != mObbState.ownerGid) {
Jeff Sharkey0095a822018-02-15 13:06:53 -07003666 notifyObbStateChange(new ObbException(ERROR_PERMISSION_DENIED,
3667 "Permission denied to unmount OBB " + existingState.rawPath
3668 + " (owned by GID " + existingState.ownerGid + ")"));
Kenny Rootaf9d6672010-10-08 09:21:39 -07003669 return;
3670 }
3671
Kenny Rootaf9d6672010-10-08 09:21:39 -07003672 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06003673 mVold.unmount(mObbState.volId);
3674 mVold.destroyObb(mObbState.volId);
3675 mObbState.volId = null;
Kenny Roota02b8b02010-08-05 16:14:17 -07003676
Kenny Rootaf9d6672010-10-08 09:21:39 -07003677 synchronized (mObbMounts) {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003678 removeObbStateLocked(existingState);
Kenny Root38cf8862010-09-26 14:18:51 -07003679 }
3680
Jeff Sharkey0095a822018-02-15 13:06:53 -07003681 notifyObbStateChange(UNMOUNTED);
3682 } catch (Exception e) {
3683 throw new ObbException(ERROR_COULD_NOT_UNMOUNT, e);
Kenny Roota02b8b02010-08-05 16:14:17 -07003684 }
3685 }
3686
Jason parks5af0b912010-11-29 09:05:25 -06003687 @Override
Kenny Roota02b8b02010-08-05 16:14:17 -07003688 public String toString() {
3689 StringBuilder sb = new StringBuilder();
3690 sb.append("UnmountObbAction{");
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003691 sb.append(mObbState);
Kenny Roota02b8b02010-08-05 16:14:17 -07003692 sb.append(",force=");
3693 sb.append(mForceUnmount);
Kenny Roota02b8b02010-08-05 16:14:17 -07003694 sb.append('}');
3695 return sb.toString();
3696 }
Kenny Root02c87302010-07-01 08:10:18 -07003697 }
Kenny Root38cf8862010-09-26 14:18:51 -07003698
Jeff Sharkey7e19f532017-11-06 13:54:11 -07003699 private void dispatchOnStatus(IVoldTaskListener listener, int status,
3700 PersistableBundle extras) {
3701 if (listener != null) {
3702 try {
3703 listener.onStatus(status, extras);
3704 } catch (RemoteException ignored) {
3705 }
3706 }
3707 }
3708
3709 private void dispatchOnFinished(IVoldTaskListener listener, int status,
3710 PersistableBundle extras) {
3711 if (listener != null) {
3712 try {
3713 listener.onFinished(status, extras);
3714 } catch (RemoteException ignored) {
3715 }
3716 }
3717 }
3718
Sudheer Shanka3a0df3b2018-12-12 12:43:43 -08003719 private int getMountMode(int uid, String packageName) {
3720 try {
3721 if (Process.isIsolated(uid)) {
3722 return Zygote.MOUNT_EXTERNAL_NONE;
3723 }
3724 if (mIPackageManager.checkUidPermission(WRITE_MEDIA_STORAGE, uid)
3725 == PERMISSION_GRANTED) {
3726 return Zygote.MOUNT_EXTERNAL_FULL;
Jeff Sharkey11697f52018-12-13 10:14:42 -07003727 } else if (mIAppOpsService.checkOperation(OP_LEGACY_STORAGE, uid,
3728 packageName) == MODE_ALLOWED) {
Sudheer Shanka0b6da532019-01-09 12:06:51 -08003729 return Zygote.MOUNT_EXTERNAL_LEGACY;
Sudheer Shanka3a0df3b2018-12-12 12:43:43 -08003730 } else if (mIPackageManager.checkUidPermission(INSTALL_PACKAGES, uid)
3731 == PERMISSION_GRANTED || mIAppOpsService.checkOperation(
3732 OP_REQUEST_INSTALL_PACKAGES, uid, packageName) == MODE_ALLOWED) {
3733 return Zygote.MOUNT_EXTERNAL_INSTALLER;
Sudheer Shanka0f26cbd2019-01-18 18:25:38 -08003734 } else if (mPmInternal.isInstantApp(packageName, UserHandle.getUserId(uid))) {
3735 return Zygote.MOUNT_EXTERNAL_NONE;
Sudheer Shanka3a0df3b2018-12-12 12:43:43 -08003736 } else {
Jeff Sharkey36274992019-02-27 12:09:57 -07003737 if (ENABLE_LEGACY_GREYLIST) {
3738 // STOPSHIP: remove this temporary workaround once developers
3739 // fix bugs where they're opening _data paths in native code
3740 switch (packageName) {
3741 case "com.facebook.katana": // b/123996076
3742 case "jp.naver.line.android": // b/124767356
3743 case "com.mxtech.videoplayer.ad": // b/124531483
Jeff Sharkey8e451252019-03-18 20:07:47 -06003744 case "com.whatsapp": // b/124766614
Jeff Sharkey36274992019-02-27 12:09:57 -07003745 return Zygote.MOUNT_EXTERNAL_LEGACY;
3746 }
Jeff Sharkey0ebbd462019-02-19 23:45:57 -07003747 }
Jeff Sharkey36274992019-02-27 12:09:57 -07003748 return Zygote.MOUNT_EXTERNAL_WRITE;
Sudheer Shanka3a0df3b2018-12-12 12:43:43 -08003749 }
3750 } catch (RemoteException e) {
3751 // Should not happen
3752 }
3753 return Zygote.MOUNT_EXTERNAL_NONE;
3754 }
3755
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07003756 private static class Callbacks extends Handler {
3757 private static final int MSG_STORAGE_STATE_CHANGED = 1;
3758 private static final int MSG_VOLUME_STATE_CHANGED = 2;
Jeff Sharkey50a05452015-04-29 11:24:52 -07003759 private static final int MSG_VOLUME_RECORD_CHANGED = 3;
3760 private static final int MSG_VOLUME_FORGOTTEN = 4;
3761 private static final int MSG_DISK_SCANNED = 5;
Makoto Onuki9dc575d2015-06-12 16:10:25 -07003762 private static final int MSG_DISK_DESTROYED = 6;
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07003763
Sudheer Shanka2250d562016-11-07 15:41:02 -08003764 private final RemoteCallbackList<IStorageEventListener>
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07003765 mCallbacks = new RemoteCallbackList<>();
3766
3767 public Callbacks(Looper looper) {
3768 super(looper);
3769 }
3770
Sudheer Shanka2250d562016-11-07 15:41:02 -08003771 public void register(IStorageEventListener callback) {
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07003772 mCallbacks.register(callback);
3773 }
3774
Sudheer Shanka2250d562016-11-07 15:41:02 -08003775 public void unregister(IStorageEventListener callback) {
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07003776 mCallbacks.unregister(callback);
3777 }
3778
3779 @Override
3780 public void handleMessage(Message msg) {
3781 final SomeArgs args = (SomeArgs) msg.obj;
3782 final int n = mCallbacks.beginBroadcast();
3783 for (int i = 0; i < n; i++) {
Sudheer Shanka2250d562016-11-07 15:41:02 -08003784 final IStorageEventListener callback = mCallbacks.getBroadcastItem(i);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07003785 try {
3786 invokeCallback(callback, msg.what, args);
3787 } catch (RemoteException ignored) {
3788 }
3789 }
3790 mCallbacks.finishBroadcast();
3791 args.recycle();
3792 }
3793
Sudheer Shanka2250d562016-11-07 15:41:02 -08003794 private void invokeCallback(IStorageEventListener callback, int what, SomeArgs args)
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07003795 throws RemoteException {
3796 switch (what) {
3797 case MSG_STORAGE_STATE_CHANGED: {
3798 callback.onStorageStateChanged((String) args.arg1, (String) args.arg2,
3799 (String) args.arg3);
3800 break;
3801 }
3802 case MSG_VOLUME_STATE_CHANGED: {
3803 callback.onVolumeStateChanged((VolumeInfo) args.arg1, args.argi2, args.argi3);
3804 break;
3805 }
Jeff Sharkey50a05452015-04-29 11:24:52 -07003806 case MSG_VOLUME_RECORD_CHANGED: {
3807 callback.onVolumeRecordChanged((VolumeRecord) args.arg1);
3808 break;
3809 }
3810 case MSG_VOLUME_FORGOTTEN: {
3811 callback.onVolumeForgotten((String) args.arg1);
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07003812 break;
3813 }
Jeff Sharkey620b32b2015-04-23 19:36:02 -07003814 case MSG_DISK_SCANNED: {
3815 callback.onDiskScanned((DiskInfo) args.arg1, args.argi2);
Jeff Sharkey7e92ef32015-04-17 17:35:07 -07003816 break;
3817 }
Makoto Onuki9dc575d2015-06-12 16:10:25 -07003818 case MSG_DISK_DESTROYED: {
3819 callback.onDiskDestroyed((DiskInfo) args.arg1);
3820 break;
3821 }
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07003822 }
3823 }
3824
3825 private void notifyStorageStateChanged(String path, String oldState, String newState) {
3826 final SomeArgs args = SomeArgs.obtain();
3827 args.arg1 = path;
3828 args.arg2 = oldState;
3829 args.arg3 = newState;
3830 obtainMessage(MSG_STORAGE_STATE_CHANGED, args).sendToTarget();
3831 }
3832
3833 private void notifyVolumeStateChanged(VolumeInfo vol, int oldState, int newState) {
3834 final SomeArgs args = SomeArgs.obtain();
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07003835 args.arg1 = vol.clone();
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07003836 args.argi2 = oldState;
3837 args.argi3 = newState;
3838 obtainMessage(MSG_VOLUME_STATE_CHANGED, args).sendToTarget();
3839 }
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07003840
Jeff Sharkey50a05452015-04-29 11:24:52 -07003841 private void notifyVolumeRecordChanged(VolumeRecord rec) {
3842 final SomeArgs args = SomeArgs.obtain();
3843 args.arg1 = rec.clone();
3844 obtainMessage(MSG_VOLUME_RECORD_CHANGED, args).sendToTarget();
3845 }
3846
3847 private void notifyVolumeForgotten(String fsUuid) {
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07003848 final SomeArgs args = SomeArgs.obtain();
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07003849 args.arg1 = fsUuid;
Jeff Sharkey50a05452015-04-29 11:24:52 -07003850 obtainMessage(MSG_VOLUME_FORGOTTEN, args).sendToTarget();
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07003851 }
Jeff Sharkey7e92ef32015-04-17 17:35:07 -07003852
Jeff Sharkey620b32b2015-04-23 19:36:02 -07003853 private void notifyDiskScanned(DiskInfo disk, int volumeCount) {
Jeff Sharkey7e92ef32015-04-17 17:35:07 -07003854 final SomeArgs args = SomeArgs.obtain();
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07003855 args.arg1 = disk.clone();
Jeff Sharkey620b32b2015-04-23 19:36:02 -07003856 args.argi2 = volumeCount;
3857 obtainMessage(MSG_DISK_SCANNED, args).sendToTarget();
Jeff Sharkey7e92ef32015-04-17 17:35:07 -07003858 }
Makoto Onuki9dc575d2015-06-12 16:10:25 -07003859
3860 private void notifyDiskDestroyed(DiskInfo disk) {
3861 final SomeArgs args = SomeArgs.obtain();
3862 args.arg1 = disk.clone();
3863 obtainMessage(MSG_DISK_DESTROYED, args).sendToTarget();
3864 }
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07003865 }
3866
Kenny Root38cf8862010-09-26 14:18:51 -07003867 @Override
Jeff Sharkey5aca2b82013-10-16 16:21:54 -07003868 protected void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
Jeff Sharkeyfe9a53b2017-03-31 14:08:23 -06003869 if (!DumpUtils.checkDumpPermission(mContext, TAG, writer)) return;
Jeff Sharkey5aca2b82013-10-16 16:21:54 -07003870
3871 final IndentingPrintWriter pw = new IndentingPrintWriter(writer, " ", 160);
Jeff Sharkey27de30d2015-04-18 16:20:27 -07003872 synchronized (mLock) {
3873 pw.println("Disks:");
3874 pw.increaseIndent();
3875 for (int i = 0; i < mDisks.size(); i++) {
3876 final DiskInfo disk = mDisks.valueAt(i);
3877 disk.dump(pw);
3878 }
3879 pw.decreaseIndent();
3880
3881 pw.println();
3882 pw.println("Volumes:");
3883 pw.increaseIndent();
3884 for (int i = 0; i < mVolumes.size(); i++) {
3885 final VolumeInfo vol = mVolumes.valueAt(i);
3886 if (VolumeInfo.ID_PRIVATE_INTERNAL.equals(vol.id)) continue;
3887 vol.dump(pw);
3888 }
3889 pw.decreaseIndent();
3890
3891 pw.println();
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07003892 pw.println("Records:");
Jeff Sharkey27de30d2015-04-18 16:20:27 -07003893 pw.increaseIndent();
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07003894 for (int i = 0; i < mRecords.size(); i++) {
3895 final VolumeRecord note = mRecords.valueAt(i);
3896 note.dump(pw);
Jeff Sharkey27de30d2015-04-18 16:20:27 -07003897 }
3898 pw.decreaseIndent();
Jeff Sharkey275e3e42015-04-24 16:10:32 -07003899
3900 pw.println();
3901 pw.println("Primary storage UUID: " + mPrimaryStorageUuid);
Jeff Sharkeyb0c363b22018-12-15 11:53:03 -07003902
3903 pw.println();
Felipe Leme281389a2016-10-10 17:12:20 -07003904 final Pair<String, Long> pair = StorageManager.getPrimaryStoragePathAndSize();
3905 if (pair == null) {
3906 pw.println("Internal storage total size: N/A");
3907 } else {
3908 pw.print("Internal storage (");
3909 pw.print(pair.first);
3910 pw.print(") total size: ");
3911 pw.print(pair.second);
3912 pw.print(" (");
Jeff Sharkey9f2dc052018-01-07 16:47:31 -07003913 pw.print(DataUnit.MEBIBYTES.toBytes(pair.second));
3914 pw.println(" MiB)");
Felipe Leme281389a2016-10-10 17:12:20 -07003915 }
Jeff Sharkeyb0c363b22018-12-15 11:53:03 -07003916
3917 pw.println();
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07003918 pw.println("Local unlocked users: " + Arrays.toString(mLocalUnlockedUsers));
3919 pw.println("System unlocked users: " + Arrays.toString(mSystemUnlockedUsers));
Jeff Sharkeyb0c363b22018-12-15 11:53:03 -07003920
3921 final ContentResolver cr = mContext.getContentResolver();
3922 pw.println();
3923 pw.println("Isolated storage, local feature flag: "
3924 + Settings.Global.getInt(cr, Settings.Global.ISOLATED_STORAGE_LOCAL, 0));
3925 pw.println("Isolated storage, remote feature flag: "
3926 + Settings.Global.getInt(cr, Settings.Global.ISOLATED_STORAGE_REMOTE, 0));
3927 pw.println("Isolated storage, resolved: " + StorageManager.hasIsolatedStorage());
Jeff Sharkey27de30d2015-04-18 16:20:27 -07003928 }
Kenny Root38cf8862010-09-26 14:18:51 -07003929
Kenny Root38cf8862010-09-26 14:18:51 -07003930 synchronized (mObbMounts) {
Jeff Sharkey27de30d2015-04-18 16:20:27 -07003931 pw.println();
Jeff Sharkey5aca2b82013-10-16 16:21:54 -07003932 pw.println("mObbMounts:");
3933 pw.increaseIndent();
3934 final Iterator<Entry<IBinder, List<ObbState>>> binders = mObbMounts.entrySet()
3935 .iterator();
Kenny Rootaf9d6672010-10-08 09:21:39 -07003936 while (binders.hasNext()) {
3937 Entry<IBinder, List<ObbState>> e = binders.next();
Jeff Sharkey5aca2b82013-10-16 16:21:54 -07003938 pw.println(e.getKey() + ":");
3939 pw.increaseIndent();
Kenny Rootaf9d6672010-10-08 09:21:39 -07003940 final List<ObbState> obbStates = e.getValue();
Kenny Root38cf8862010-09-26 14:18:51 -07003941 for (final ObbState obbState : obbStates) {
Jeff Sharkey5aca2b82013-10-16 16:21:54 -07003942 pw.println(obbState);
Kenny Root38cf8862010-09-26 14:18:51 -07003943 }
Jeff Sharkey5aca2b82013-10-16 16:21:54 -07003944 pw.decreaseIndent();
Kenny Root38cf8862010-09-26 14:18:51 -07003945 }
Jeff Sharkey5aca2b82013-10-16 16:21:54 -07003946 pw.decreaseIndent();
Kenny Rootaf9d6672010-10-08 09:21:39 -07003947
Jeff Sharkey5aca2b82013-10-16 16:21:54 -07003948 pw.println();
3949 pw.println("mObbPathToStateMap:");
3950 pw.increaseIndent();
Kenny Rootaf9d6672010-10-08 09:21:39 -07003951 final Iterator<Entry<String, ObbState>> maps = mObbPathToStateMap.entrySet().iterator();
3952 while (maps.hasNext()) {
3953 final Entry<String, ObbState> e = maps.next();
Jeff Sharkey5aca2b82013-10-16 16:21:54 -07003954 pw.print(e.getKey());
3955 pw.print(" -> ");
3956 pw.println(e.getValue());
Kenny Rootaf9d6672010-10-08 09:21:39 -07003957 }
Jeff Sharkey5aca2b82013-10-16 16:21:54 -07003958 pw.decreaseIndent();
Kenny Root38cf8862010-09-26 14:18:51 -07003959 }
Kenny Root4161f9b2011-07-13 09:48:33 -07003960
Robert Greenwalt470fd722012-01-18 12:51:15 -08003961 pw.println();
Christopher Tate7265abe2014-11-21 13:54:45 -08003962 pw.print("Last maintenance: ");
Jeff Sharkeye8a4b662015-06-27 15:43:45 -07003963 pw.println(TimeUtils.formatForLogging(mLastMaintenance));
Kenny Root38cf8862010-09-26 14:18:51 -07003964 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003965
Jeff Sharkeyfa23c5a2011-08-09 21:44:24 -07003966 /** {@inheritDoc} */
Jeff Sharkey48877892015-03-18 11:27:19 -07003967 @Override
Jeff Sharkeyfa23c5a2011-08-09 21:44:24 -07003968 public void monitor() {
Jeff Sharkey54402792017-09-15 16:05:19 -06003969 try {
3970 mVold.monitor();
3971 } catch (Exception e) {
3972 Slog.wtf(TAG, e);
Paul Lawrence1c62cbb2015-06-03 14:14:52 -07003973 }
Jeff Sharkeyfa23c5a2011-08-09 21:44:24 -07003974 }
Svet Ganov6ee871e2015-07-10 14:29:33 -07003975
Sudheer Shanka2250d562016-11-07 15:41:02 -08003976 private final class StorageManagerInternalImpl extends StorageManagerInternal {
Svet Ganov6ee871e2015-07-10 14:29:33 -07003977 // Not guarded by a lock.
3978 private final CopyOnWriteArrayList<ExternalStorageMountPolicy> mPolicies =
3979 new CopyOnWriteArrayList<>();
3980
Risanaec0ee72018-10-31 10:10:12 +09003981 @GuardedBy("mResetListeners")
3982 private final List<StorageManagerInternal.ResetListener> mResetListeners =
3983 new ArrayList<>();
3984
Svet Ganov6ee871e2015-07-10 14:29:33 -07003985 @Override
3986 public void addExternalStoragePolicy(ExternalStorageMountPolicy policy) {
3987 // No locking - CopyOnWriteArrayList
3988 mPolicies.add(policy);
3989 }
3990
3991 @Override
3992 public void onExternalStoragePolicyChanged(int uid, String packageName) {
Sudheer Shanka0a541a52018-07-31 13:21:11 -07003993 // No runtime storage permissions in isolated storage world, so nothing to do here.
Jeff Sharkeyc58fdf32018-08-15 18:49:34 -06003994 if (ENABLE_ISOLATED_STORAGE) return;
Svet Ganov6ee871e2015-07-10 14:29:33 -07003995 final int mountMode = getExternalStorageMountMode(uid, packageName);
3996 remountUidExternalStorage(uid, mountMode);
3997 }
3998
3999 @Override
4000 public int getExternalStorageMountMode(int uid, String packageName) {
Sudheer Shanka3a0df3b2018-12-12 12:43:43 -08004001 if (ENABLE_ISOLATED_STORAGE) {
4002 return getMountMode(uid, packageName);
4003 }
Svet Ganov6ee871e2015-07-10 14:29:33 -07004004 // No locking - CopyOnWriteArrayList
4005 int mountMode = Integer.MAX_VALUE;
4006 for (ExternalStorageMountPolicy policy : mPolicies) {
4007 final int policyMode = policy.getMountMode(uid, packageName);
4008 if (policyMode == Zygote.MOUNT_EXTERNAL_NONE) {
4009 return Zygote.MOUNT_EXTERNAL_NONE;
4010 }
4011 mountMode = Math.min(mountMode, policyMode);
4012 }
4013 if (mountMode == Integer.MAX_VALUE) {
4014 return Zygote.MOUNT_EXTERNAL_NONE;
4015 }
4016 return mountMode;
4017 }
4018
Risanaec0ee72018-10-31 10:10:12 +09004019 @Override
4020 public void addResetListener(StorageManagerInternal.ResetListener listener) {
4021 synchronized (mResetListeners) {
4022 mResetListeners.add(listener);
4023 }
4024 }
4025
4026 public void onReset(IVold vold) {
4027 synchronized (mResetListeners) {
4028 for (StorageManagerInternal.ResetListener listener : mResetListeners) {
4029 listener.onReset(vold);
4030 }
4031 }
4032 }
4033
Svet Ganov6ee871e2015-07-10 14:29:33 -07004034 public boolean hasExternalStorage(int uid, String packageName) {
Amith Yamasani2bd5cff2015-07-22 14:42:31 -07004035 // No need to check for system uid. This avoids a deadlock between
4036 // PackageManagerService and AppOpsService.
4037 if (uid == Process.SYSTEM_UID) {
4038 return true;
4039 }
Sudheer Shanka3a0df3b2018-12-12 12:43:43 -08004040 if (ENABLE_ISOLATED_STORAGE) {
4041 return getMountMode(uid, packageName) != Zygote.MOUNT_EXTERNAL_NONE;
4042 }
Svet Ganov6ee871e2015-07-10 14:29:33 -07004043 // No locking - CopyOnWriteArrayList
4044 for (ExternalStorageMountPolicy policy : mPolicies) {
4045 final boolean policyHasStorage = policy.hasExternalStorage(uid, packageName);
4046 if (!policyHasStorage) {
4047 return false;
4048 }
4049 }
4050 return true;
4051 }
Sudheer Shanka8ff30b12018-08-06 17:29:44 -07004052
4053 @Override
Sudheer Shanka584b0682018-10-04 16:26:16 -07004054 public void prepareSandboxForApp(String packageName, int appId, String sharedUserId,
Sudheer Shanka8ff30b12018-08-06 17:29:44 -07004055 int userId) {
4056 final String sandboxId;
4057 synchronized (mPackagesLock) {
Sudheer Shanka2ac25a92018-10-25 10:59:32 -07004058 final ArraySet<String> userPackages = mPackages.get(userId);
Sudheer Shanka8ff30b12018-08-06 17:29:44 -07004059 // If userPackages is empty, it means the user is not started yet, so no need to
4060 // do anything now.
Sudheer Shanka2ac25a92018-10-25 10:59:32 -07004061 if (userPackages == null || userPackages.contains(packageName)) {
Sudheer Shanka8ff30b12018-08-06 17:29:44 -07004062 return;
4063 }
4064 userPackages.add(packageName);
Sudheer Shanka03fd40b2019-02-06 12:39:14 -08004065 sandboxId = StorageManagerService.this.getSandboxId(packageName, sharedUserId);
Sudheer Shanka8ff30b12018-08-06 17:29:44 -07004066 }
4067
4068 try {
Sudheer Shanka584b0682018-10-04 16:26:16 -07004069 mVold.prepareSandboxForApp(packageName, appId, sandboxId, userId);
4070 } catch (Exception e) {
4071 Slog.wtf(TAG, e);
4072 }
4073 }
4074
4075 @Override
Sudheer Shanka2ac25a92018-10-25 10:59:32 -07004076 public void destroySandboxForApp(String packageName, String sharedUserId, int userId) {
Sudheer Shanka584b0682018-10-04 16:26:16 -07004077 if (!ENABLE_ISOLATED_STORAGE) {
4078 return;
4079 }
Sudheer Shanka03fd40b2019-02-06 12:39:14 -08004080 final String sandboxId = StorageManagerService.this.getSandboxId(
4081 packageName, sharedUserId);
Sudheer Shanka584b0682018-10-04 16:26:16 -07004082 synchronized (mPackagesLock) {
Sudheer Shanka2ac25a92018-10-25 10:59:32 -07004083 final ArraySet<String> userPackages = mPackages.get(userId);
4084 // If the userPackages is null, it means the user is not started but we still
4085 // need to delete the sandbox data though.
4086 if (userPackages != null) {
4087 userPackages.remove(packageName);
Sudheer Shanka584b0682018-10-04 16:26:16 -07004088 }
4089 }
4090 try {
Sudheer Shanka2ac25a92018-10-25 10:59:32 -07004091 mVold.destroySandboxForApp(packageName, sandboxId, userId);
Sudheer Shanka8ff30b12018-08-06 17:29:44 -07004092 } catch (Exception e) {
4093 Slog.wtf(TAG, e);
4094 }
4095 }
Sudheer Shanka3f0645b2018-09-18 13:07:59 -07004096
4097 @Override
Sudheer Shanka03fd40b2019-02-06 12:39:14 -08004098 public String getSandboxId(String packageName) {
4099 return StorageManagerService.this.getSandboxId(packageName,
4100 mPmInternal.getSharedUserIdForPackage(packageName));
4101 }
Svet Ganov6ee871e2015-07-10 14:29:33 -07004102 }
Jeff Sharkeyfa23c5a2011-08-09 21:44:24 -07004103}