blob: e7d7434b5dc899ddad3a9a6714aad52a96da557a [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 Sharkey56e62932015-03-21 20:41:00 -0700208 public static class Lifecycle extends SystemService {
Sudheer Shanka2250d562016-11-07 15:41:02 -0800209 private StorageManagerService mStorageManagerService;
Jeff Sharkey56e62932015-03-21 20:41:00 -0700210
211 public Lifecycle(Context context) {
212 super(context);
213 }
214
215 @Override
216 public void onStart() {
Sudheer Shanka2250d562016-11-07 15:41:02 -0800217 mStorageManagerService = new StorageManagerService(getContext());
218 publishBinderService("mount", mStorageManagerService);
219 mStorageManagerService.start();
Jeff Sharkey56e62932015-03-21 20:41:00 -0700220 }
221
222 @Override
223 public void onBootPhase(int phase) {
Jeff Sharkey11697f52018-12-13 10:14:42 -0700224 if (phase == SystemService.PHASE_SYSTEM_SERVICES_READY) {
225 mStorageManagerService.servicesReady();
226 } else if (phase == SystemService.PHASE_ACTIVITY_MANAGER_READY) {
Sudheer Shanka2250d562016-11-07 15:41:02 -0800227 mStorageManagerService.systemReady();
Yasuhiro Matsuda87a38b52015-07-24 22:10:16 +0900228 } else if (phase == SystemService.PHASE_BOOT_COMPLETED) {
Sudheer Shanka2250d562016-11-07 15:41:02 -0800229 mStorageManagerService.bootCompleted();
Jeff Sharkey56e62932015-03-21 20:41:00 -0700230 }
231 }
Jeff Sharkey48877892015-03-18 11:27:19 -0700232
233 @Override
Jeff Sharkeyab15c392016-05-05 11:45:01 -0600234 public void onSwitchUser(int userHandle) {
Sudheer Shanka2250d562016-11-07 15:41:02 -0800235 mStorageManagerService.mCurrentUserId = userHandle;
Jeff Sharkeyab15c392016-05-05 11:45:01 -0600236 }
237
238 @Override
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700239 public void onUnlockUser(int userHandle) {
Sudheer Shanka2250d562016-11-07 15:41:02 -0800240 mStorageManagerService.onUnlockUser(userHandle);
Jeff Sharkey48877892015-03-18 11:27:19 -0700241 }
242
243 @Override
244 public void onCleanupUser(int userHandle) {
Sudheer Shanka2250d562016-11-07 15:41:02 -0800245 mStorageManagerService.onCleanupUser(userHandle);
Jeff Sharkey48877892015-03-18 11:27:19 -0700246 }
Jeff Sharkey56e62932015-03-21 20:41:00 -0700247 }
248
Dianne Hackborn40e9f292012-11-27 19:12:23 -0800249 private static final boolean DEBUG_EVENTS = false;
Kenny Rootb7db2722011-01-25 16:39:35 -0800250 private static final boolean DEBUG_OBB = false;
Kenny Root02c87302010-07-01 08:10:18 -0700251
Jeff Sharkeyc3c72872018-06-06 15:35:53 -0600252 /**
253 * We now talk to vold over Binder, and it has its own internal lock to
254 * serialize certain calls. All long-running operations have been migrated
255 * to be async with callbacks, so we want watchdog to fire if vold wedges.
256 */
257 private static final boolean WATCHDOG_ENABLE = true;
Kenny Root07714d42011-08-17 17:49:28 -0700258
Jeff Sharkey00455bf2016-11-04 14:45:24 -0600259 /**
260 * Our goal is for all Android devices to be usable as development devices,
261 * which includes the new Direct Boot mode added in N. For devices that
262 * don't have native FBE support, we offer an emulation mode for developer
263 * testing purposes, but if it's prohibitively difficult to support this
264 * mode, it can be disabled for specific products using this flag.
265 */
266 private static final boolean EMULATE_FBE_SUPPORTED = true;
267
Sudheer Shanka2250d562016-11-07 15:41:02 -0800268 private static final String TAG = "StorageManagerService";
Jeff Sharkeye8a4b662015-06-27 15:43:45 -0700269
Jeff Sharkey9756d752015-05-14 21:07:42 -0700270 private static final String TAG_STORAGE_BENCHMARK = "storage_benchmark";
Jeff Sharkeye8a4b662015-06-27 15:43:45 -0700271 private static final String TAG_STORAGE_TRIM = "storage_trim";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800272
Jeff Sharkey275e3e42015-04-24 16:10:32 -0700273 /** Magic value sent by MoveTask.cpp */
274 private static final int MOVE_STATUS_COPY_FINISHED = 82;
275
Jeff Sharkey620b32b2015-04-23 19:36:02 -0700276 private static final int VERSION_INIT = 1;
277 private static final int VERSION_ADD_PRIMARY = 2;
Jeff Sharkeyfced5342015-05-10 14:53:34 -0700278 private static final int VERSION_FIX_PRIMARY = 3;
Jeff Sharkey620b32b2015-04-23 19:36:02 -0700279
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700280 private static final String TAG_VOLUMES = "volumes";
Jeff Sharkey620b32b2015-04-23 19:36:02 -0700281 private static final String ATTR_VERSION = "version";
282 private static final String ATTR_PRIMARY_STORAGE_UUID = "primaryStorageUuid";
Jeff Sharkey11697f52018-12-13 10:14:42 -0700283 private static final String ATTR_ISOLATED_STORAGE = "isolatedStorage";
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700284 private static final String TAG_VOLUME = "volume";
285 private static final String ATTR_TYPE = "type";
286 private static final String ATTR_FS_UUID = "fsUuid";
Jeff Sharkey5cc0df22015-06-17 19:44:05 -0700287 private static final String ATTR_PART_GUID = "partGuid";
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700288 private static final String ATTR_NICKNAME = "nickname";
289 private static final String ATTR_USER_FLAGS = "userFlags";
Jeff Sharkeye8a4b662015-06-27 15:43:45 -0700290 private static final String ATTR_CREATED_MILLIS = "createdMillis";
291 private static final String ATTR_LAST_TRIM_MILLIS = "lastTrimMillis";
292 private static final String ATTR_LAST_BENCH_MILLIS = "lastBenchMillis";
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700293
Jeff Sharkeyb36586a2015-04-27 08:42:28 -0700294 private final AtomicFile mSettingsFile;
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700295
Jeff Sharkey48877892015-03-18 11:27:19 -0700296 /**
297 * <em>Never</em> hold the lock while performing downcalls into vold, since
298 * unsolicited events can suddenly appear to update data structures.
299 */
Jeff Sharkey5f3e9342017-03-13 14:53:11 -0600300 private final Object mLock = LockGuard.installNewLock(LockGuard.INDEX_STORAGE);
Jeff Sharkey48877892015-03-18 11:27:19 -0700301
Sudheer Shanka0a541a52018-07-31 13:21:11 -0700302 /**
303 * Similar to {@link #mLock}, never hold this lock while performing downcalls into vold.
304 * Also, never hold this while calling into PackageManagerService since it is used in callbacks
305 * from PackageManagerService.
306 *
307 * If both {@link #mLock} and this lock need to be held, {@link #mLock} should be acquired
308 * before this.
309 *
310 * Use -PL suffix for methods that need to called with this lock held.
311 */
312 private final Object mPackagesLock = new Object();
313
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700314 /** Set of users that we know are unlocked. */
Jeff Sharkey48877892015-03-18 11:27:19 -0700315 @GuardedBy("mLock")
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700316 private int[] mLocalUnlockedUsers = EmptyArray.INT;
317 /** Set of users that system knows are unlocked. */
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -0800318 @GuardedBy("mLock")
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700319 private int[] mSystemUnlockedUsers = EmptyArray.INT;
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700320
321 /** Map from disk ID to disk */
Jeff Sharkey48877892015-03-18 11:27:19 -0700322 @GuardedBy("mLock")
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -0700323 private ArrayMap<String, DiskInfo> mDisks = new ArrayMap<>();
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700324 /** Map from volume ID to disk */
Jeff Sharkey48877892015-03-18 11:27:19 -0700325 @GuardedBy("mLock")
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700326 private final ArrayMap<String, VolumeInfo> mVolumes = new ArrayMap<>();
Jeff Sharkey48877892015-03-18 11:27:19 -0700327
Jeff Sharkeyb36586a2015-04-27 08:42:28 -0700328 /** Map from UUID to record */
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700329 @GuardedBy("mLock")
Jeff Sharkeyb36586a2015-04-27 08:42:28 -0700330 private ArrayMap<String, VolumeRecord> mRecords = new ArrayMap<>();
Jeff Sharkey620b32b2015-04-23 19:36:02 -0700331 @GuardedBy("mLock")
332 private String mPrimaryStorageUuid;
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700333
Jeff Sharkey11697f52018-12-13 10:14:42 -0700334 /** Flag indicating isolated storage state of last boot */
335 @GuardedBy("mLock")
336 private boolean mLastIsolatedStorage = false;
337
Jeff Sharkeyeba260d2015-04-19 14:35:16 -0700338 /** Map from disk ID to latches */
339 @GuardedBy("mLock")
340 private ArrayMap<String, CountDownLatch> mDiskScanLatches = new ArrayMap<>();
341
Jeff Sharkey275e3e42015-04-24 16:10:32 -0700342 @GuardedBy("mLock")
343 private IPackageMoveObserver mMoveCallback;
344 @GuardedBy("mLock")
345 private String mMoveTargetUuid;
346
Sudheer Shanka0a541a52018-07-31 13:21:11 -0700347 @GuardedBy("mPackagesLock")
348 private final SparseArray<ArraySet<String>> mPackages = new SparseArray<>();
349
Sudheer Shanka3f0645b2018-09-18 13:07:59 -0700350 /**
351 * List of volumes visible to any user.
352 * TODO: may be have a map of userId -> volumes?
353 */
354 private final CopyOnWriteArrayList<VolumeInfo> mVisibleVols = new CopyOnWriteArrayList<>();
355
Jeff Sharkeyab15c392016-05-05 11:45:01 -0600356 private volatile int mCurrentUserId = UserHandle.USER_SYSTEM;
357
Daichi Hirono9fb00182016-11-08 14:12:17 +0900358 /** Holding lock for AppFuse business */
359 private final Object mAppFuseLock = new Object();
360
361 @GuardedBy("mAppFuseLock")
362 private int mNextAppFuseName = 0;
363
364 @GuardedBy("mAppFuseLock")
Daichi Hironoe56740d2017-02-02 13:56:45 +0900365 private AppFuseBridge mAppFuseBridge = null;
Daichi Hirono9fb00182016-11-08 14:12:17 +0900366
Jeff Sharkeyef10ee02015-07-05 14:17:27 -0700367 private VolumeInfo findVolumeByIdOrThrow(String id) {
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700368 synchronized (mLock) {
369 final VolumeInfo vol = mVolumes.get(id);
370 if (vol != null) {
371 return vol;
372 }
373 }
374 throw new IllegalArgumentException("No volume found for ID " + id);
375 }
376
Jeff Sharkeyef10ee02015-07-05 14:17:27 -0700377 private String findVolumeIdForPathOrThrow(String path) {
Jeff Sharkey48877892015-03-18 11:27:19 -0700378 synchronized (mLock) {
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -0700379 for (int i = 0; i < mVolumes.size(); i++) {
380 final VolumeInfo vol = mVolumes.valueAt(i);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700381 if (vol.path != null && path.startsWith(vol.path)) {
382 return vol.id;
Jeff Sharkey48877892015-03-18 11:27:19 -0700383 }
384 }
385 }
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700386 throw new IllegalArgumentException("No volume found for path " + path);
Jeff Sharkey48877892015-03-18 11:27:19 -0700387 }
388
Jeff Sharkeye8a4b662015-06-27 15:43:45 -0700389 private VolumeRecord findRecordForPath(String path) {
390 synchronized (mLock) {
391 for (int i = 0; i < mVolumes.size(); i++) {
392 final VolumeInfo vol = mVolumes.valueAt(i);
393 if (vol.path != null && path.startsWith(vol.path)) {
394 return mRecords.get(vol.fsUuid);
395 }
396 }
397 }
398 return null;
399 }
400
401 private String scrubPath(String path) {
402 if (path.startsWith(Environment.getDataDirectory().getAbsolutePath())) {
403 return "internal";
404 }
405 final VolumeRecord rec = findRecordForPath(path);
406 if (rec == null || rec.createdMillis == 0) {
407 return "unknown";
408 } else {
409 return "ext:" + (int) ((System.currentTimeMillis() - rec.createdMillis)
410 / DateUtils.WEEK_IN_MILLIS) + "w";
411 }
412 }
413
Jeff Sharkeyef10ee02015-07-05 14:17:27 -0700414 private @Nullable VolumeInfo findStorageForUuid(String volumeUuid) {
Jeff Sharkey275e3e42015-04-24 16:10:32 -0700415 final StorageManager storage = mContext.getSystemService(StorageManager.class);
416 if (Objects.equals(StorageManager.UUID_PRIVATE_INTERNAL, volumeUuid)) {
Jeff Sharkeyef10ee02015-07-05 14:17:27 -0700417 return storage.findVolumeById(VolumeInfo.ID_EMULATED_INTERNAL);
Jeff Sharkey275e3e42015-04-24 16:10:32 -0700418 } else if (Objects.equals(StorageManager.UUID_PRIMARY_PHYSICAL, volumeUuid)) {
419 return storage.getPrimaryPhysicalVolume();
420 } else {
421 return storage.findEmulatedForPrivate(storage.findVolumeByUuid(volumeUuid));
422 }
423 }
424
Jeff Sharkeye8a4b662015-06-27 15:43:45 -0700425 private boolean shouldBenchmark() {
426 final long benchInterval = Settings.Global.getLong(mContext.getContentResolver(),
427 Settings.Global.STORAGE_BENCHMARK_INTERVAL, DateUtils.WEEK_IN_MILLIS);
Jeff Sharkeye83d8a92015-09-09 14:53:38 -0700428 if (benchInterval == -1) {
429 return false;
430 } else if (benchInterval == 0) {
431 return true;
432 }
433
Jeff Sharkeye8a4b662015-06-27 15:43:45 -0700434 synchronized (mLock) {
435 for (int i = 0; i < mVolumes.size(); i++) {
436 final VolumeInfo vol = mVolumes.valueAt(i);
437 final VolumeRecord rec = mRecords.get(vol.fsUuid);
Jeff Sharkeye83d8a92015-09-09 14:53:38 -0700438 if (vol.isMountedWritable() && rec != null) {
Jeff Sharkeye8a4b662015-06-27 15:43:45 -0700439 final long benchAge = System.currentTimeMillis() - rec.lastBenchMillis;
440 if (benchAge >= benchInterval) {
441 return true;
442 }
443 }
444 }
445 return false;
446 }
447 }
448
Jeff Sharkeyeba260d2015-04-19 14:35:16 -0700449 private CountDownLatch findOrCreateDiskScanLatch(String diskId) {
450 synchronized (mLock) {
451 CountDownLatch latch = mDiskScanLatches.get(diskId);
452 if (latch == null) {
453 latch = new CountDownLatch(1);
454 mDiskScanLatches.put(diskId, latch);
455 }
456 return latch;
457 }
458 }
459
Paul Lawrence8e397362014-01-27 15:22:30 -0800460 /** List of crypto types.
461 * These must match CRYPT_TYPE_XXX in cryptfs.h AND their
462 * corresponding commands in CommandListener.cpp */
463 public static final String[] CRYPTO_TYPES
464 = { "password", "default", "pattern", "pin" };
465
Brian Carlstrom7395a8a2014-04-28 22:11:01 -0700466 private final Context mContext;
Jeff Sharkey5d0c55c2019-01-24 14:32:31 -0700467 private final ContentResolver mResolver;
Jeff Sharkeycd575992016-03-29 14:12:49 -0600468
Jeff Sharkey1019de92017-09-06 13:47:03 -0600469 private volatile IVold mVold;
Jin Qian12690d52017-10-13 18:17:04 -0700470 private volatile IStoraged mStoraged;
Jeff Sharkey1019de92017-09-06 13:47:03 -0600471
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700472 private volatile boolean mSystemReady = false;
Yasuhiro Matsuda87a38b52015-07-24 22:10:16 +0900473 private volatile boolean mBootCompleted = false;
Jeff Sharkey48877892015-03-18 11:27:19 -0700474 private volatile boolean mDaemonConnected = false;
Jeff Sharkey9765e442017-12-14 22:15:14 -0700475 private volatile boolean mSecureKeyguardShowing = true;
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700476
Sudheer Shanka0a541a52018-07-31 13:21:11 -0700477 private PackageManagerInternal mPmInternal;
Jeff Sharkey5790af02018-08-13 17:42:54 -0600478 private UserManagerInternal mUmInternal;
Sudheer Shanka87915d62018-11-06 10:57:35 -0800479 private ActivityManagerInternal mAmInternal;
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700480
Sudheer Shanka3a0df3b2018-12-12 12:43:43 -0800481 private IPackageManager mIPackageManager;
482 private IAppOpsService mIAppOpsService;
483
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700484 private final Callbacks mCallbacks;
Jeff Sharkeyb9fe5372015-12-03 15:23:08 -0700485 private final LockPatternUtils mLockPatternUtils;
Jeff Sharkey48877892015-03-18 11:27:19 -0700486
San Mehat6cdd9c02010-02-09 14:45:20 -0800487 /**
Kenny Root3b1abba2010-10-13 15:00:07 -0700488 * The size of the crypto algorithm key in bits for OBB files. Currently
489 * Twofish is used which takes 128-bit keys.
490 */
491 private static final int CRYPTO_ALGORITHM_KEY_SIZE = 128;
492
493 /**
494 * The number of times to run SHA1 in the PBKDF2 function for OBB files.
495 * 1024 is reasonably secure and not too slow.
496 */
497 private static final int PBKDF2_HASH_ROUNDS = 1024;
498
499 /**
Kenny Roota02b8b02010-08-05 16:14:17 -0700500 * Mounted OBB tracking information. Used to track the current state of all
501 * OBBs.
Kenny Root02c87302010-07-01 08:10:18 -0700502 */
Kenny Root735de3b2010-09-30 14:11:39 -0700503 final private Map<IBinder, List<ObbState>> mObbMounts = new HashMap<IBinder, List<ObbState>>();
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700504
505 /** Map from raw paths to {@link ObbState}. */
Kenny Roota02b8b02010-08-05 16:14:17 -0700506 final private Map<String, ObbState> mObbPathToStateMap = new HashMap<String, ObbState>();
507
Svet Ganov6ee871e2015-07-10 14:29:33 -0700508 // Not guarded by a lock.
Sudheer Shanka2250d562016-11-07 15:41:02 -0800509 private final StorageManagerInternalImpl mStorageManagerInternal
510 = new StorageManagerInternalImpl();
Svet Ganov6ee871e2015-07-10 14:29:33 -0700511
Kenny Roota02b8b02010-08-05 16:14:17 -0700512 class ObbState implements IBinder.DeathRecipient {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700513 public ObbState(String rawPath, String canonicalPath, int callingUid,
Jeff Sharkey41cd6812017-09-11 10:32:17 -0600514 IObbActionListener token, int nonce, String volId) {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700515 this.rawPath = rawPath;
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700516 this.canonicalPath = canonicalPath;
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700517 this.ownerGid = UserHandle.getSharedAppGid(callingUid);
Kenny Rootaf9d6672010-10-08 09:21:39 -0700518 this.token = token;
519 this.nonce = nonce;
Jeff Sharkey41cd6812017-09-11 10:32:17 -0600520 this.volId = volId;
Kenny Roota02b8b02010-08-05 16:14:17 -0700521 }
522
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700523 final String rawPath;
524 final String canonicalPath;
Kenny Roota02b8b02010-08-05 16:14:17 -0700525
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700526 final int ownerGid;
Kenny Roota02b8b02010-08-05 16:14:17 -0700527
Kenny Rootaf9d6672010-10-08 09:21:39 -0700528 // Token of remote Binder caller
529 final IObbActionListener token;
530
531 // Identifier to pass back to the token
532 final int nonce;
Kenny Roota02b8b02010-08-05 16:14:17 -0700533
Jeff Sharkey41cd6812017-09-11 10:32:17 -0600534 String volId;
535
Kenny Root735de3b2010-09-30 14:11:39 -0700536 public IBinder getBinder() {
537 return token.asBinder();
538 }
539
Kenny Roota02b8b02010-08-05 16:14:17 -0700540 @Override
541 public void binderDied() {
542 ObbAction action = new UnmountObbAction(this, true);
543 mObbActionHandler.sendMessage(mObbActionHandler.obtainMessage(OBB_RUN_ACTION, action));
Kenny Root735de3b2010-09-30 14:11:39 -0700544 }
Kenny Roota02b8b02010-08-05 16:14:17 -0700545
Kenny Root5919ac62010-10-05 09:49:40 -0700546 public void link() throws RemoteException {
547 getBinder().linkToDeath(this, 0);
548 }
549
550 public void unlink() {
Kenny Root735de3b2010-09-30 14:11:39 -0700551 getBinder().unlinkToDeath(this, 0);
Kenny Roota02b8b02010-08-05 16:14:17 -0700552 }
Kenny Root38cf8862010-09-26 14:18:51 -0700553
554 @Override
555 public String toString() {
556 StringBuilder sb = new StringBuilder("ObbState{");
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700557 sb.append("rawPath=").append(rawPath);
558 sb.append(",canonicalPath=").append(canonicalPath);
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700559 sb.append(",ownerGid=").append(ownerGid);
560 sb.append(",token=").append(token);
561 sb.append(",binder=").append(getBinder());
Jeff Sharkey41cd6812017-09-11 10:32:17 -0600562 sb.append(",volId=").append(volId);
Kenny Root38cf8862010-09-26 14:18:51 -0700563 sb.append('}');
564 return sb.toString();
565 }
Kenny Roota02b8b02010-08-05 16:14:17 -0700566 }
567
568 // OBB Action Handler
569 final private ObbActionHandler mObbActionHandler;
570
571 // OBB action handler messages
572 private static final int OBB_RUN_ACTION = 1;
Sudheer Shanka25469aa2018-08-27 15:50:23 -0700573 private static final int OBB_FLUSH_MOUNT_STATE = 2;
Kenny Root02c87302010-07-01 08:10:18 -0700574
Christopher Tate7265abe2014-11-21 13:54:45 -0800575 // Last fstrim operation tracking
576 private static final String LAST_FSTRIM_FILE = "last-fstrim";
577 private final File mLastMaintenanceFile;
578 private long mLastMaintenance;
579
Kenny Root02c87302010-07-01 08:10:18 -0700580 // Handler messages
Jeff Sharkey48877892015-03-18 11:27:19 -0700581 private static final int H_SYSTEM_READY = 1;
582 private static final int H_DAEMON_CONNECTED = 2;
583 private static final int H_SHUTDOWN = 3;
584 private static final int H_FSTRIM = 4;
585 private static final int H_VOLUME_MOUNT = 5;
586 private static final int H_VOLUME_BROADCAST = 6;
Jeff Sharkeyabc3e852015-08-03 14:41:13 -0700587 private static final int H_INTERNAL_BROADCAST = 7;
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700588 private static final int H_VOLUME_UNMOUNT = 8;
Jeff Sharkey5a9bb742015-11-03 10:15:57 -0800589 private static final int H_PARTITION_FORGET = 9;
590 private static final int H_RESET = 10;
Jin Qiana85b9912017-10-17 15:48:18 -0700591 private static final int H_RUN_IDLE_MAINT = 11;
592 private static final int H_ABORT_IDLE_MAINT = 12;
Suchi Amalapurapu6ffce2e2010-03-08 14:48:40 -0800593
Sudheer Shanka2250d562016-11-07 15:41:02 -0800594 class StorageManagerServiceHandler extends Handler {
595 public StorageManagerServiceHandler(Looper looper) {
Jeff Sharkey48877892015-03-18 11:27:19 -0700596 super(looper);
Daniel Sandler5f27ef42010-03-16 15:42:02 -0400597 }
598
Jason parks5af0b912010-11-29 09:05:25 -0600599 @Override
Suchi Amalapurapuc42e29e2010-02-22 16:03:53 -0800600 public void handleMessage(Message msg) {
601 switch (msg.what) {
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700602 case H_SYSTEM_READY: {
Jeff Sharkey48877892015-03-18 11:27:19 -0700603 handleSystemReady();
604 break;
605 }
606 case H_DAEMON_CONNECTED: {
607 handleDaemonConnected();
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700608 break;
609 }
Christopher Tated417d622013-08-19 16:14:25 -0700610 case H_FSTRIM: {
Christopher Tated417d622013-08-19 16:14:25 -0700611 Slog.i(TAG, "Running fstrim idle maintenance");
Christopher Tate7265abe2014-11-21 13:54:45 -0800612
613 // Remember when we kicked it off
614 try {
615 mLastMaintenance = System.currentTimeMillis();
616 mLastMaintenanceFile.setLastModified(mLastMaintenance);
617 } catch (Exception e) {
618 Slog.e(TAG, "Unable to record last fstrim!");
619 }
620
Jeff Sharkeyb302c542017-09-15 12:57:59 -0600621 // TODO: Reintroduce shouldBenchmark() test
Jeff Sharkey7e19f532017-11-06 13:54:11 -0700622 fstrim(0, null);
Christopher Tate7265abe2014-11-21 13:54:45 -0800623
Christopher Tated417d622013-08-19 16:14:25 -0700624 // invoke the completion callback, if any
Jeff Sharkeye8a4b662015-06-27 15:43:45 -0700625 // TODO: fstrim is non-blocking, so remove this useless callback
Christopher Tated417d622013-08-19 16:14:25 -0700626 Runnable callback = (Runnable) msg.obj;
627 if (callback != null) {
628 callback.run();
629 }
630 break;
631 }
Jeff Sharkey48877892015-03-18 11:27:19 -0700632 case H_SHUTDOWN: {
Sudheer Shanka2250d562016-11-07 15:41:02 -0800633 final IStorageShutdownObserver obs = (IStorageShutdownObserver) msg.obj;
Jeff Sharkey48877892015-03-18 11:27:19 -0700634 boolean success = false;
635 try {
Jeff Sharkey54402792017-09-15 16:05:19 -0600636 mVold.shutdown();
637 success = true;
Jeff Sharkeyace874b2017-09-07 15:27:33 -0600638 } catch (Exception e) {
639 Slog.wtf(TAG, e);
Jeff Sharkey48877892015-03-18 11:27:19 -0700640 }
641 if (obs != null) {
642 try {
643 obs.onShutDownComplete(success ? 0 : -1);
Jeff Sharkeyace874b2017-09-07 15:27:33 -0600644 } catch (Exception ignored) {
Jeff Sharkey48877892015-03-18 11:27:19 -0700645 }
646 }
647 break;
648 }
649 case H_VOLUME_MOUNT: {
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -0700650 final VolumeInfo vol = (VolumeInfo) msg.obj;
Jeff Sharkey2e606d72015-07-27 14:19:54 -0700651 if (isMountDisallowed(vol)) {
652 Slog.i(TAG, "Ignoring mount " + vol.getId() + " due to policy");
653 break;
654 }
Sudheer Shanka3f0645b2018-09-18 13:07:59 -0700655 mount(vol);
Jeff Sharkey48877892015-03-18 11:27:19 -0700656 break;
657 }
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700658 case H_VOLUME_UNMOUNT: {
659 final VolumeInfo vol = (VolumeInfo) msg.obj;
Sudheer Shanka3f0645b2018-09-18 13:07:59 -0700660 unmount(vol);
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700661 break;
662 }
Jeff Sharkey48877892015-03-18 11:27:19 -0700663 case H_VOLUME_BROADCAST: {
664 final StorageVolume userVol = (StorageVolume) msg.obj;
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700665 final String envState = userVol.getState();
666 Slog.d(TAG, "Volume " + userVol.getId() + " broadcasting " + envState + " to "
Jeff Sharkey48877892015-03-18 11:27:19 -0700667 + userVol.getOwner());
668
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700669 final String action = VolumeInfo.getBroadcastForEnvironment(envState);
Jeff Sharkey48877892015-03-18 11:27:19 -0700670 if (action != null) {
671 final Intent intent = new Intent(action,
672 Uri.fromFile(userVol.getPathFile()));
673 intent.putExtra(StorageVolume.EXTRA_STORAGE_VOLUME, userVol);
Jeff Sharkey082f83b2017-03-26 14:34:47 -0600674 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT
675 | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
Jeff Sharkey48877892015-03-18 11:27:19 -0700676 mContext.sendBroadcastAsUser(intent, userVol.getOwner());
677 }
678 break;
679 }
Jeff Sharkeyabc3e852015-08-03 14:41:13 -0700680 case H_INTERNAL_BROADCAST: {
681 // Internal broadcasts aimed at system components, not for
682 // third-party apps.
683 final Intent intent = (Intent) msg.obj;
684 mContext.sendBroadcastAsUser(intent, UserHandle.ALL,
685 android.Manifest.permission.WRITE_MEDIA_STORAGE);
Jeff Sharkey5a9bb742015-11-03 10:15:57 -0800686 break;
687 }
688 case H_PARTITION_FORGET: {
Jeff Sharkeydb4b6192017-10-24 11:08:50 -0600689 final VolumeRecord rec = (VolumeRecord) msg.obj;
690 forgetPartition(rec.partGuid, rec.fsUuid);
Jeff Sharkey5a9bb742015-11-03 10:15:57 -0800691 break;
692 }
693 case H_RESET: {
694 resetIfReadyAndConnected();
695 break;
Jeff Sharkeyabc3e852015-08-03 14:41:13 -0700696 }
Jin Qiana85b9912017-10-17 15:48:18 -0700697 case H_RUN_IDLE_MAINT: {
698 Slog.i(TAG, "Running idle maintenance");
699 runIdleMaint((Runnable)msg.obj);
700 break;
701 }
702 case H_ABORT_IDLE_MAINT: {
703 Slog.i(TAG, "Aborting idle maintenance");
704 abortIdleMaint((Runnable)msg.obj);
705 break;
706 }
707
Suchi Amalapurapuc42e29e2010-02-22 16:03:53 -0800708 }
709 }
Jeff Sharkey48877892015-03-18 11:27:19 -0700710 }
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700711
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700712 private final Handler mHandler;
Suchi Amalapurapuc42e29e2010-02-22 16:03:53 -0800713
Jeff Sharkeybcd262d2015-06-10 09:41:17 -0700714 private BroadcastReceiver mUserReceiver = new BroadcastReceiver() {
715 @Override
716 public void onReceive(Context context, Intent intent) {
717 final String action = intent.getAction();
718 final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700719 Preconditions.checkArgument(userId >= 0);
Jeff Sharkeybcd262d2015-06-10 09:41:17 -0700720
721 try {
722 if (Intent.ACTION_USER_ADDED.equals(action)) {
723 final UserManager um = mContext.getSystemService(UserManager.class);
724 final int userSerialNumber = um.getUserSerialNumber(userId);
Jeff Sharkey54402792017-09-15 16:05:19 -0600725 mVold.onUserAdded(userId, userSerialNumber);
Jeff Sharkeybcd262d2015-06-10 09:41:17 -0700726 } else if (Intent.ACTION_USER_REMOVED.equals(action)) {
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700727 synchronized (mVolumes) {
728 final int size = mVolumes.size();
729 for (int i = 0; i < size; i++) {
730 final VolumeInfo vol = mVolumes.valueAt(i);
731 if (vol.mountUserId == userId) {
732 vol.mountUserId = UserHandle.USER_NULL;
733 mHandler.obtainMessage(H_VOLUME_UNMOUNT, vol).sendToTarget();
734 }
735 }
736 }
Jeff Sharkey54402792017-09-15 16:05:19 -0600737 mVold.onUserRemoved(userId);
Jeff Sharkeybcd262d2015-06-10 09:41:17 -0700738 }
Jeff Sharkeyace874b2017-09-07 15:27:33 -0600739 } catch (Exception e) {
740 Slog.wtf(TAG, e);
Jeff Sharkeybcd262d2015-06-10 09:41:17 -0700741 }
742 }
743 };
744
Jeff Sharkeyedcdaf62015-07-09 09:45:36 -0700745 private void waitForLatch(CountDownLatch latch, String condition, long timeoutMillis)
746 throws TimeoutException {
747 final long startMillis = SystemClock.elapsedRealtime();
Jeff Sharkeyeba260d2015-04-19 14:35:16 -0700748 while (true) {
Kenny Root51a573c2012-05-17 13:30:28 -0700749 try {
750 if (latch.await(5000, TimeUnit.MILLISECONDS)) {
San Mehat207e5382010-02-04 20:46:54 -0800751 return;
Kenny Root51a573c2012-05-17 13:30:28 -0700752 } else {
753 Slog.w(TAG, "Thread " + Thread.currentThread().getName()
Jeff Sharkey48877892015-03-18 11:27:19 -0700754 + " still waiting for " + condition + "...");
San Mehat207e5382010-02-04 20:46:54 -0800755 }
Kenny Root51a573c2012-05-17 13:30:28 -0700756 } catch (InterruptedException e) {
Jeff Sharkeyeba260d2015-04-19 14:35:16 -0700757 Slog.w(TAG, "Interrupt while waiting for " + condition);
San Mehat207e5382010-02-04 20:46:54 -0800758 }
Jeff Sharkeyedcdaf62015-07-09 09:45:36 -0700759 if (timeoutMillis > 0 && SystemClock.elapsedRealtime() > startMillis + timeoutMillis) {
760 throw new TimeoutException("Thread " + Thread.currentThread().getName()
761 + " gave up waiting for " + condition + " after " + timeoutMillis + "ms");
762 }
San Mehat207e5382010-02-04 20:46:54 -0800763 }
San Mehat1f6301e2010-01-07 22:40:27 -0800764 }
Kenny Root02c87302010-07-01 08:10:18 -0700765
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700766 private void handleSystemReady() {
Jeff Sharkey8924e872015-11-30 12:52:10 -0700767 initIfReadyAndConnected();
Jeff Sharkey5a9bb742015-11-03 10:15:57 -0800768 resetIfReadyAndConnected();
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700769
Jeff Sharkey48877892015-03-18 11:27:19 -0700770 // Start scheduling nominally-daily fstrim operations
Christopher Tate115afda2014-06-06 19:06:26 -0700771 MountServiceIdler.scheduleIdlePass(mContext);
Daniel Colascione766b6322018-01-08 19:10:36 -0800772
773 // Toggle zram-enable system property in response to settings
774 mContext.getContentResolver().registerContentObserver(
775 Settings.Global.getUriFor(Settings.Global.ZRAM_ENABLED),
776 false /*notifyForDescendants*/,
777 new ContentObserver(null /* current thread */) {
778 @Override
779 public void onChange(boolean selfChange) {
780 refreshZramSettings();
781 }
782 });
783 refreshZramSettings();
Jeff Sharkeyb0c363b22018-12-15 11:53:03 -0700784
Srinivas Paladuguc8261752019-01-09 10:54:52 -0800785 // Schedule zram writeback unless zram is disabled by persist.sys.zram_enabled
786 String zramPropValue = SystemProperties.get(ZRAM_ENABLED_PROPERTY);
787 if (!zramPropValue.equals("0")
788 && mContext.getResources().getBoolean(
789 com.android.internal.R.bool.config_zramWriteback)) {
790 ZramWriteback.scheduleZramWriteback(mContext);
791 }
Jeff Sharkeyb0c363b22018-12-15 11:53:03 -0700792 // Toggle isolated-enable system property in response to settings
793 mContext.getContentResolver().registerContentObserver(
794 Settings.Global.getUriFor(Settings.Global.ISOLATED_STORAGE_REMOTE),
795 false /*notifyForDescendants*/,
796 new ContentObserver(null /* current thread */) {
797 @Override
798 public void onChange(boolean selfChange) {
799 refreshIsolatedStorageSettings();
800 }
801 });
Jeff Sharkey5d0c55c2019-01-24 14:32:31 -0700802 // For now, simply clone property when it changes
803 DeviceConfig.addOnPropertyChangedListener(DeviceConfig.Storage.NAMESPACE,
804 mContext.getMainExecutor(), (namespace, name, value) -> {
Jeff Sharkey8b499a02019-01-28 13:31:50 -0700805 refreshIsolatedStorageSettings();
Jeff Sharkey5d0c55c2019-01-24 14:32:31 -0700806 });
Jeff Sharkeyb0c363b22018-12-15 11:53:03 -0700807 refreshIsolatedStorageSettings();
Daniel Colascione766b6322018-01-08 19:10:36 -0800808 }
809
810 /**
811 * Update the zram_enabled system property (which init reads to
812 * decide whether to enable zram) to reflect the zram_enabled
813 * preference (which we can change for experimentation purposes).
814 */
815 private void refreshZramSettings() {
816 String propertyValue = SystemProperties.get(ZRAM_ENABLED_PROPERTY);
817 if ("".equals(propertyValue)) {
818 return; // System doesn't have zram toggling support
819 }
820 String desiredPropertyValue =
821 Settings.Global.getInt(mContext.getContentResolver(),
822 Settings.Global.ZRAM_ENABLED,
823 1) != 0
824 ? "1" : "0";
825 if (!desiredPropertyValue.equals(propertyValue)) {
826 // Avoid redundant disk writes by setting only if we're
827 // changing the property value. There's no race: we're the
828 // sole writer.
829 SystemProperties.set(ZRAM_ENABLED_PROPERTY, desiredPropertyValue);
Srinivas Paladuguc8261752019-01-09 10:54:52 -0800830 // Schedule writeback only if zram is being enabled.
831 if (desiredPropertyValue.equals("1")
832 && mContext.getResources().getBoolean(
833 com.android.internal.R.bool.config_zramWriteback)) {
834 ZramWriteback.scheduleZramWriteback(mContext);
835 }
Daniel Colascione766b6322018-01-08 19:10:36 -0800836 }
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700837 }
838
Jeff Sharkeyb0c363b22018-12-15 11:53:03 -0700839 private void refreshIsolatedStorageSettings() {
Jeff Sharkey8b499a02019-01-28 13:31:50 -0700840 // Always copy value from newer DeviceConfig location
841 Settings.Global.putString(mResolver,
842 Settings.Global.ISOLATED_STORAGE_REMOTE,
843 DeviceConfig.getProperty(DeviceConfig.Storage.NAMESPACE,
844 DeviceConfig.Storage.ISOLATED_STORAGE_ENABLED));
845
Jeff Sharkeyb0c363b22018-12-15 11:53:03 -0700846 final int local = Settings.Global.getInt(mContext.getContentResolver(),
847 Settings.Global.ISOLATED_STORAGE_LOCAL, 0);
848 final int remote = Settings.Global.getInt(mContext.getContentResolver(),
849 Settings.Global.ISOLATED_STORAGE_REMOTE, 0);
850
851 // Walk down precedence chain; we prefer local settings first, then
852 // remote settings, before finally falling back to hard-coded default.
853 final boolean res;
854 if (local == -1) {
855 res = false;
856 } else if (local == 1) {
857 res = true;
858 } else if (remote == -1) {
859 res = false;
860 } else if (remote == 1) {
861 res = true;
862 } else {
863 res = false;
864 }
865
866 Slog.d(TAG, "Isolated storage local flag " + local + " and remote flag "
867 + remote + " resolved to " + res);
868 SystemProperties.set(StorageManager.PROP_ISOLATED_STORAGE, Boolean.toString(res));
869 }
870
Jeff Sharkey14cbe522015-07-08 14:06:37 -0700871 /**
872 * MediaProvider has a ton of code that makes assumptions about storage
873 * paths never changing, so we outright kill them to pick up new state.
874 */
875 @Deprecated
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700876 private void killMediaProvider(List<UserInfo> users) {
877 if (users == null) return;
878
Jeff Sharkeyb3cf9532015-07-17 15:12:39 -0700879 final long token = Binder.clearCallingIdentity();
880 try {
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700881 for (UserInfo user : users) {
882 // System user does not have media provider, so skip.
883 if (user.isSystemOnly()) continue;
884
Jeff Sharkey5790af02018-08-13 17:42:54 -0600885 final ProviderInfo provider = mPmInternal.resolveContentProvider(
886 MediaStore.AUTHORITY, PackageManager.MATCH_DIRECT_BOOT_AWARE
Jeff Sharkey8a372a02016-03-16 16:25:45 -0600887 | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
888 user.id);
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700889 if (provider != null) {
Sudheer Shankadc589ac2016-11-10 15:30:17 -0800890 final IActivityManager am = ActivityManager.getService();
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700891 try {
Jeff Sharkey85f449e2016-06-23 09:26:00 -0600892 am.killApplication(provider.applicationInfo.packageName,
893 UserHandle.getAppId(provider.applicationInfo.uid),
894 UserHandle.USER_ALL, "vold reset");
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700895 // We only need to run this once. It will kill all users' media processes.
896 break;
897 } catch (RemoteException e) {
898 }
Jeff Sharkeyb3cf9532015-07-17 15:12:39 -0700899 }
Jeff Sharkey14cbe522015-07-08 14:06:37 -0700900 }
Jeff Sharkeyb3cf9532015-07-17 15:12:39 -0700901 } finally {
902 Binder.restoreCallingIdentity(token);
Jeff Sharkey14cbe522015-07-08 14:06:37 -0700903 }
904 }
905
Andreas Gampea36dc622018-02-05 17:19:22 -0800906 @GuardedBy("mLock")
Jeff Sharkey5a9bb742015-11-03 10:15:57 -0800907 private void addInternalVolumeLocked() {
Amith Yamasania7892482015-08-07 11:09:05 -0700908 // Create a stub volume that represents internal storage
909 final VolumeInfo internal = new VolumeInfo(VolumeInfo.ID_PRIVATE_INTERNAL,
910 VolumeInfo.TYPE_PRIVATE, null, null);
911 internal.state = VolumeInfo.STATE_MOUNTED;
912 internal.path = Environment.getDataDirectory().getAbsolutePath();
913 mVolumes.put(internal.id, internal);
914 }
915
Jeff Sharkey8924e872015-11-30 12:52:10 -0700916 private void initIfReadyAndConnected() {
917 Slog.d(TAG, "Thinking about init, mSystemReady=" + mSystemReady
918 + ", mDaemonConnected=" + mDaemonConnected);
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700919 if (mSystemReady && mDaemonConnected
Paul Lawrence20be5d62016-02-26 13:51:17 -0800920 && !StorageManager.isFileEncryptedNativeOnly()) {
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700921 // When booting a device without native support, make sure that our
922 // user directories are locked or unlocked based on the current
923 // emulation status.
Paul Lawrence20be5d62016-02-26 13:51:17 -0800924 final boolean initLocked = StorageManager.isFileEncryptedEmulatedOnly();
Paul Crowleyd94ab732016-02-15 06:44:51 +0000925 Slog.d(TAG, "Setting up emulation state, initlocked=" + initLocked);
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700926 final List<UserInfo> users = mContext.getSystemService(UserManager.class).getUsers();
Jeff Sharkey8924e872015-11-30 12:52:10 -0700927 for (UserInfo user : users) {
928 try {
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700929 if (initLocked) {
Jeff Sharkey54402792017-09-15 16:05:19 -0600930 mVold.lockUserKey(user.id);
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700931 } else {
Jeff Sharkey54402792017-09-15 16:05:19 -0600932 mVold.unlockUserKey(user.id, user.serialNumber, encodeBytes(null),
933 encodeBytes(null));
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700934 }
Jeff Sharkey43e12112017-09-12 16:31:45 -0600935 } catch (Exception e) {
936 Slog.wtf(TAG, e);
Jeff Sharkey8924e872015-11-30 12:52:10 -0700937 }
938 }
939 }
940 }
941
Jeff Sharkey5a9bb742015-11-03 10:15:57 -0800942 private void resetIfReadyAndConnected() {
Jeff Sharkey48877892015-03-18 11:27:19 -0700943 Slog.d(TAG, "Thinking about reset, mSystemReady=" + mSystemReady
944 + ", mDaemonConnected=" + mDaemonConnected);
945 if (mSystemReady && mDaemonConnected) {
Jeff Sharkey5a9bb742015-11-03 10:15:57 -0800946 final List<UserInfo> users = mContext.getSystemService(UserManager.class).getUsers();
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700947 killMediaProvider(users);
Jeff Sharkey14cbe522015-07-08 14:06:37 -0700948
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700949 final int[] systemUnlockedUsers;
Jeff Sharkey5a9bb742015-11-03 10:15:57 -0800950 synchronized (mLock) {
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700951 systemUnlockedUsers = mSystemUnlockedUsers;
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700952
Jeff Sharkey5a9bb742015-11-03 10:15:57 -0800953 mDisks.clear();
954 mVolumes.clear();
955
956 addInternalVolumeLocked();
957 }
Jeff Sharkey59d577a2015-04-11 21:27:21 -0700958
Sudheer Shanka3f0645b2018-09-18 13:07:59 -0700959 mVisibleVols.clear();
960
Jeff Sharkey48877892015-03-18 11:27:19 -0700961 try {
Jeff Sharkey54402792017-09-15 16:05:19 -0600962 mVold.reset();
Jeff Sharkeybcd262d2015-06-10 09:41:17 -0700963
964 // Tell vold about all existing and started users
Jeff Sharkeybcd262d2015-06-10 09:41:17 -0700965 for (UserInfo user : users) {
Jeff Sharkey54402792017-09-15 16:05:19 -0600966 mVold.onUserAdded(user.id, user.serialNumber);
Jeff Sharkeybcd262d2015-06-10 09:41:17 -0700967 }
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700968 for (int userId : systemUnlockedUsers) {
Sudheer Shanka2ac25a92018-10-25 10:59:32 -0700969 sendUserStartedCallback(userId);
Jin Qian12690d52017-10-13 18:17:04 -0700970 mStoraged.onUserStarted(userId);
Jeff Sharkey50a05452015-04-29 11:24:52 -0700971 }
Jeff Sharkey9765e442017-12-14 22:15:14 -0700972 mVold.onSecureKeyguardStateChanged(mSecureKeyguardShowing);
Risanaec0ee72018-10-31 10:10:12 +0900973 mStorageManagerInternal.onReset(mVold);
Jeff Sharkeyace874b2017-09-07 15:27:33 -0600974 } catch (Exception e) {
975 Slog.wtf(TAG, e);
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700976 }
977 }
Jeff Sharkey48877892015-03-18 11:27:19 -0700978 }
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700979
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700980 private void onUnlockUser(int userId) {
981 Slog.d(TAG, "onUnlockUser " + userId);
Jeff Sharkey48877892015-03-18 11:27:19 -0700982
983 // We purposefully block here to make sure that user-specific
984 // staging area is ready so it's ready for zygote-forked apps to
985 // bind mount against.
986 try {
Sudheer Shanka2ac25a92018-10-25 10:59:32 -0700987 sendUserStartedCallback(userId);
Jin Qian12690d52017-10-13 18:17:04 -0700988 mStoraged.onUserStarted(userId);
Jeff Sharkeyace874b2017-09-07 15:27:33 -0600989 } catch (Exception e) {
990 Slog.wtf(TAG, e);
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700991 }
Jeff Sharkey48877892015-03-18 11:27:19 -0700992
993 // Record user as started so newly mounted volumes kick off events
994 // correctly, then synthesize events for any already-mounted volumes.
yuanhuihuiefd1f122016-07-13 21:21:03 +0800995 synchronized (mLock) {
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -0700996 for (int i = 0; i < mVolumes.size(); i++) {
997 final VolumeInfo vol = mVolumes.valueAt(i);
Jeff Sharkey46349872015-07-28 10:49:47 -0700998 if (vol.isVisibleForRead(userId) && vol.isMountedReadable()) {
Svet Ganov6ee871e2015-07-10 14:29:33 -0700999 final StorageVolume userVol = vol.buildStorageVolume(mContext, userId, false);
Jeff Sharkey48877892015-03-18 11:27:19 -07001000 mHandler.obtainMessage(H_VOLUME_BROADCAST, userVol).sendToTarget();
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001001
Jeff Sharkey27de30d2015-04-18 16:20:27 -07001002 final String envState = VolumeInfo.getEnvironmentForState(vol.getState());
1003 mCallbacks.notifyStorageStateChanged(userVol.getPath(), envState, envState);
Jeff Sharkey48877892015-03-18 11:27:19 -07001004 }
1005 }
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07001006 mSystemUnlockedUsers = ArrayUtils.appendInt(mSystemUnlockedUsers, userId);
Jeff Sharkey48877892015-03-18 11:27:19 -07001007 }
1008 }
1009
1010 private void onCleanupUser(int userId) {
1011 Slog.d(TAG, "onCleanupUser " + userId);
1012
1013 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06001014 mVold.onUserStopped(userId);
Jin Qian12690d52017-10-13 18:17:04 -07001015 mStoraged.onUserStopped(userId);
Jeff Sharkeyace874b2017-09-07 15:27:33 -06001016 } catch (Exception e) {
1017 Slog.wtf(TAG, e);
Jeff Sharkey48877892015-03-18 11:27:19 -07001018 }
1019
Sudheer Shanka2ac25a92018-10-25 10:59:32 -07001020 synchronized (mPackagesLock) {
1021 mPackages.delete(userId);
1022 }
1023
yuanhuihuiefd1f122016-07-13 21:21:03 +08001024 synchronized (mLock) {
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07001025 mSystemUnlockedUsers = ArrayUtils.removeInt(mSystemUnlockedUsers, userId);
Jeff Sharkey48877892015-03-18 11:27:19 -07001026 }
1027 }
Jeff Sharkeyb049e212012-09-07 23:16:01 -07001028
Sudheer Shanka2ac25a92018-10-25 10:59:32 -07001029 private void sendUserStartedCallback(int userId) throws Exception {
1030 if (!ENABLE_ISOLATED_STORAGE) {
1031 mVold.onUserStarted(userId, EmptyArray.STRING, EmptyArray.INT, EmptyArray.STRING);
1032 }
1033
1034 final String[] packages;
1035 final int[] appIds;
1036 final String[] sandboxIds;
1037 final SparseArray<String> sharedUserIds = mPmInternal.getAppsWithSharedUserIds();
1038 final List<ApplicationInfo> appInfos =
1039 mContext.getPackageManager().getInstalledApplicationsAsUser(
1040 PackageManager.MATCH_UNINSTALLED_PACKAGES, userId);
1041 synchronized (mPackagesLock) {
1042 final ArraySet<String> userPackages = new ArraySet<>();
1043 final ArrayMap<String, Integer> packageToAppId = new ArrayMap<>();
1044 for (int i = appInfos.size() - 1; i >= 0; --i) {
1045 final ApplicationInfo appInfo = appInfos.get(i);
1046 if (appInfo.isInstantApp()) {
1047 continue;
1048 }
1049 userPackages.add(appInfo.packageName);
1050 packageToAppId.put(appInfo.packageName, UserHandle.getAppId(appInfo.uid));
1051 }
1052 mPackages.put(userId, userPackages);
1053
1054 packages = new String[userPackages.size()];
1055 appIds = new int[userPackages.size()];
1056 sandboxIds = new String[userPackages.size()];
1057 for (int i = userPackages.size() - 1; i >= 0; --i) {
1058 packages[i] = userPackages.valueAt(i);
1059 appIds[i] = packageToAppId.get(packages[i]);
1060 sandboxIds[i] = getSandboxId(packages[i], sharedUserIds.get(appIds[i]));
1061 }
1062 }
1063 mVold.onUserStarted(userId, packages, appIds, sandboxIds);
1064 }
1065
Jeff Sharkey9765e442017-12-14 22:15:14 -07001066 @Override
1067 public void onAwakeStateChanged(boolean isAwake) {
1068 // Ignored
1069 }
1070
1071 @Override
1072 public void onKeyguardStateChanged(boolean isShowing) {
1073 // Push down current secure keyguard status so that we ignore malicious
1074 // USB devices while locked.
1075 mSecureKeyguardShowing = isShowing
1076 && mContext.getSystemService(KeyguardManager.class).isDeviceSecure();
1077 try {
1078 mVold.onSecureKeyguardStateChanged(mSecureKeyguardShowing);
1079 } catch (Exception e) {
1080 Slog.wtf(TAG, e);
1081 }
1082 }
1083
Christopher Tated417d622013-08-19 16:14:25 -07001084 void runIdleMaintenance(Runnable callback) {
1085 mHandler.sendMessage(mHandler.obtainMessage(H_FSTRIM, callback));
1086 }
1087
Christopher Tate7265abe2014-11-21 13:54:45 -08001088 // Binder entry point for kicking off an immediate fstrim
1089 @Override
1090 public void runMaintenance() {
Jeff Sharkey48877892015-03-18 11:27:19 -07001091 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
Christopher Tate7265abe2014-11-21 13:54:45 -08001092 runIdleMaintenance(null);
1093 }
1094
1095 @Override
1096 public long lastMaintenance() {
1097 return mLastMaintenance;
1098 }
1099
San Mehat4270e1e2010-01-29 05:32:19 -08001100 public void onDaemonConnected() {
Jeff Sharkey48877892015-03-18 11:27:19 -07001101 mDaemonConnected = true;
1102 mHandler.obtainMessage(H_DAEMON_CONNECTED).sendToTarget();
1103 }
1104
1105 private void handleDaemonConnected() {
Jeff Sharkey8924e872015-11-30 12:52:10 -07001106 initIfReadyAndConnected();
Jeff Sharkey5a9bb742015-11-03 10:15:57 -08001107 resetIfReadyAndConnected();
Jeff Sharkey48877892015-03-18 11:27:19 -07001108
Jeff Sharkey48877892015-03-18 11:27:19 -07001109 // On an encrypted device we can't see system properties yet, so pull
1110 // the system locale out of the mount service.
Inseob Kimc1246e62018-11-08 13:13:54 +09001111 if ("".equals(VoldProperties.encrypt_progress().orElse(""))) {
Jeff Sharkey48877892015-03-18 11:27:19 -07001112 copyLocaleFromMountService();
1113 }
San Mehat4270e1e2010-01-29 05:32:19 -08001114 }
1115
Elliott Hughesf839b4f2014-09-26 12:30:47 -07001116 private void copyLocaleFromMountService() {
1117 String systemLocale;
1118 try {
1119 systemLocale = getField(StorageManager.SYSTEM_LOCALE_KEY);
1120 } catch (RemoteException e) {
1121 return;
1122 }
1123 if (TextUtils.isEmpty(systemLocale)) {
1124 return;
1125 }
1126
1127 Slog.d(TAG, "Got locale " + systemLocale + " from mount service");
1128 Locale locale = Locale.forLanguageTag(systemLocale);
1129 Configuration config = new Configuration();
1130 config.setLocale(locale);
1131 try {
Sudheer Shankadc589ac2016-11-10 15:30:17 -08001132 ActivityManager.getService().updatePersistentConfiguration(config);
Elliott Hughesf839b4f2014-09-26 12:30:47 -07001133 } catch (RemoteException e) {
1134 Slog.e(TAG, "Error setting system locale from mount service", e);
1135 }
Elliott Hughes9c33f282014-10-13 12:39:56 -07001136
1137 // Temporary workaround for http://b/17945169.
1138 Slog.d(TAG, "Setting system properties to " + systemLocale + " from mount service");
Narayan Kamathd30dbb82015-01-15 14:48:15 +00001139 SystemProperties.set("persist.sys.locale", locale.toLanguageTag());
Elliott Hughesf839b4f2014-09-26 12:30:47 -07001140 }
1141
Jeff Sharkey8058fe62017-09-13 11:50:33 -06001142 private final IVoldListener mListener = new IVoldListener.Stub() {
1143 @Override
1144 public void onDiskCreated(String diskId, int flags) {
1145 synchronized (mLock) {
Jeff Sharkey901c0422018-04-20 13:11:20 -06001146 final String value = SystemProperties.get(StorageManager.PROP_ADOPTABLE);
1147 switch (value) {
1148 case "force_on":
1149 flags |= DiskInfo.FLAG_ADOPTABLE;
1150 break;
1151 case "force_off":
1152 flags &= ~DiskInfo.FLAG_ADOPTABLE;
1153 break;
Jeff Sharkey8058fe62017-09-13 11:50:33 -06001154 }
Jeff Sharkey8058fe62017-09-13 11:50:33 -06001155 mDisks.put(diskId, new DiskInfo(diskId, flags));
1156 }
1157 }
1158
1159 @Override
1160 public void onDiskScanned(String diskId) {
1161 synchronized (mLock) {
1162 final DiskInfo disk = mDisks.get(diskId);
1163 if (disk != null) {
1164 onDiskScannedLocked(disk);
1165 }
1166 }
1167 }
1168
1169 @Override
1170 public void onDiskMetadataChanged(String diskId, long sizeBytes, String label,
1171 String sysPath) {
1172 synchronized (mLock) {
1173 final DiskInfo disk = mDisks.get(diskId);
1174 if (disk != null) {
1175 disk.size = sizeBytes;
1176 disk.label = label;
1177 disk.sysPath = sysPath;
1178 }
1179 }
1180 }
1181
1182 @Override
1183 public void onDiskDestroyed(String diskId) {
1184 synchronized (mLock) {
1185 final DiskInfo disk = mDisks.remove(diskId);
1186 if (disk != null) {
1187 mCallbacks.notifyDiskDestroyed(disk);
1188 }
1189 }
1190 }
1191
1192 @Override
1193 public void onVolumeCreated(String volId, int type, String diskId, String partGuid) {
1194 synchronized (mLock) {
1195 final DiskInfo disk = mDisks.get(diskId);
1196 final VolumeInfo vol = new VolumeInfo(volId, type, disk, partGuid);
1197 mVolumes.put(volId, vol);
1198 onVolumeCreatedLocked(vol);
1199 }
1200 }
1201
1202 @Override
1203 public void onVolumeStateChanged(String volId, int state) {
1204 synchronized (mLock) {
1205 final VolumeInfo vol = mVolumes.get(volId);
1206 if (vol != null) {
1207 final int oldState = vol.state;
1208 final int newState = state;
1209 vol.state = newState;
1210 onVolumeStateChangedLocked(vol, oldState, newState);
1211 }
1212 }
1213 }
1214
1215 @Override
1216 public void onVolumeMetadataChanged(String volId, String fsType, String fsUuid,
1217 String fsLabel) {
1218 synchronized (mLock) {
1219 final VolumeInfo vol = mVolumes.get(volId);
1220 if (vol != null) {
1221 vol.fsType = fsType;
1222 vol.fsUuid = fsUuid;
1223 vol.fsLabel = fsLabel;
1224 }
1225 }
1226 }
1227
1228 @Override
1229 public void onVolumePathChanged(String volId, String path) {
1230 synchronized (mLock) {
1231 final VolumeInfo vol = mVolumes.get(volId);
1232 if (vol != null) {
1233 vol.path = path;
1234 }
1235 }
1236 }
1237
1238 @Override
1239 public void onVolumeInternalPathChanged(String volId, String internalPath) {
1240 synchronized (mLock) {
1241 final VolumeInfo vol = mVolumes.get(volId);
1242 if (vol != null) {
1243 vol.internalPath = internalPath;
1244 }
1245 }
1246 }
1247
1248 @Override
1249 public void onVolumeDestroyed(String volId) {
1250 synchronized (mLock) {
1251 mVolumes.remove(volId);
1252 }
1253 }
1254 };
1255
Andreas Gampea36dc622018-02-05 17:19:22 -08001256 @GuardedBy("mLock")
Jeff Sharkeyeba260d2015-04-19 14:35:16 -07001257 private void onDiskScannedLocked(DiskInfo disk) {
Jeff Sharkey620b32b2015-04-23 19:36:02 -07001258 int volumeCount = 0;
Jeff Sharkeyeba260d2015-04-19 14:35:16 -07001259 for (int i = 0; i < mVolumes.size(); i++) {
1260 final VolumeInfo vol = mVolumes.valueAt(i);
1261 if (Objects.equals(disk.id, vol.getDiskId())) {
Jeff Sharkey620b32b2015-04-23 19:36:02 -07001262 volumeCount++;
Jeff Sharkeyeba260d2015-04-19 14:35:16 -07001263 }
1264 }
1265
Jeff Sharkeyc7acac62015-06-12 16:16:56 -07001266 final Intent intent = new Intent(DiskInfo.ACTION_DISK_SCANNED);
Jeff Sharkey7732e1e2016-03-30 17:14:23 -06001267 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT
1268 | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
Jeff Sharkeyc7acac62015-06-12 16:16:56 -07001269 intent.putExtra(DiskInfo.EXTRA_DISK_ID, disk.id);
1270 intent.putExtra(DiskInfo.EXTRA_VOLUME_COUNT, volumeCount);
Jeff Sharkeyabc3e852015-08-03 14:41:13 -07001271 mHandler.obtainMessage(H_INTERNAL_BROADCAST, intent).sendToTarget();
Jeff Sharkeyc7acac62015-06-12 16:16:56 -07001272
1273 final CountDownLatch latch = mDiskScanLatches.remove(disk.id);
1274 if (latch != null) {
1275 latch.countDown();
1276 }
1277
Jeff Sharkeyf5a6bd72015-05-19 14:42:38 -07001278 disk.volumeCount = volumeCount;
Jeff Sharkey620b32b2015-04-23 19:36:02 -07001279 mCallbacks.notifyDiskScanned(disk, volumeCount);
Jeff Sharkeyeba260d2015-04-19 14:35:16 -07001280 }
1281
Andreas Gampea36dc622018-02-05 17:19:22 -08001282 @GuardedBy("mLock")
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07001283 private void onVolumeCreatedLocked(VolumeInfo vol) {
Jeff Sharkey5790af02018-08-13 17:42:54 -06001284 if (mPmInternal.isOnlyCoreApps()) {
Jeff Sharkey6855c482016-03-31 14:34:38 -06001285 Slog.d(TAG, "System booted in core-only mode; ignoring volume " + vol.getId());
1286 return;
1287 }
1288
Jeff Sharkey275e3e42015-04-24 16:10:32 -07001289 if (vol.type == VolumeInfo.TYPE_EMULATED) {
1290 final StorageManager storage = mContext.getSystemService(StorageManager.class);
1291 final VolumeInfo privateVol = storage.findPrivateForEmulated(vol);
1292
1293 if (Objects.equals(StorageManager.UUID_PRIVATE_INTERNAL, mPrimaryStorageUuid)
1294 && VolumeInfo.ID_PRIVATE_INTERNAL.equals(privateVol.id)) {
1295 Slog.v(TAG, "Found primary storage at " + vol);
1296 vol.mountFlags |= VolumeInfo.MOUNT_FLAG_PRIMARY;
1297 vol.mountFlags |= VolumeInfo.MOUNT_FLAG_VISIBLE;
1298 mHandler.obtainMessage(H_VOLUME_MOUNT, vol).sendToTarget();
1299
1300 } else if (Objects.equals(privateVol.fsUuid, mPrimaryStorageUuid)) {
1301 Slog.v(TAG, "Found primary storage at " + vol);
1302 vol.mountFlags |= VolumeInfo.MOUNT_FLAG_PRIMARY;
1303 vol.mountFlags |= VolumeInfo.MOUNT_FLAG_VISIBLE;
1304 mHandler.obtainMessage(H_VOLUME_MOUNT, vol).sendToTarget();
1305 }
Jeff Sharkeyb049e212012-09-07 23:16:01 -07001306
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07001307 } else if (vol.type == VolumeInfo.TYPE_PUBLIC) {
Jeff Sharkey275e3e42015-04-24 16:10:32 -07001308 // TODO: only look at first public partition
1309 if (Objects.equals(StorageManager.UUID_PRIMARY_PHYSICAL, mPrimaryStorageUuid)
1310 && vol.disk.isDefaultPrimary()) {
1311 Slog.v(TAG, "Found primary storage at " + vol);
Jeff Sharkey7e92ef32015-04-17 17:35:07 -07001312 vol.mountFlags |= VolumeInfo.MOUNT_FLAG_PRIMARY;
1313 vol.mountFlags |= VolumeInfo.MOUNT_FLAG_VISIBLE;
San Mehat4270e1e2010-01-29 05:32:19 -08001314 }
Jeff Sharkey7e92ef32015-04-17 17:35:07 -07001315
1316 // Adoptable public disks are visible to apps, since they meet
1317 // public API requirement of being in a stable location.
Jeff Sharkey275e3e42015-04-24 16:10:32 -07001318 if (vol.disk.isAdoptable()) {
Jeff Sharkey7e92ef32015-04-17 17:35:07 -07001319 vol.mountFlags |= VolumeInfo.MOUNT_FLAG_VISIBLE;
1320 }
1321
Jeff Sharkeyab15c392016-05-05 11:45:01 -06001322 vol.mountUserId = mCurrentUserId;
Jeff Sharkey48877892015-03-18 11:27:19 -07001323 mHandler.obtainMessage(H_VOLUME_MOUNT, vol).sendToTarget();
San Mehat4270e1e2010-01-29 05:32:19 -08001324
Jeff Sharkeyb2b9ab82015-04-05 21:10:42 -07001325 } else if (vol.type == VolumeInfo.TYPE_PRIVATE) {
1326 mHandler.obtainMessage(H_VOLUME_MOUNT, vol).sendToTarget();
1327
Risan05c41e62018-10-29 08:57:43 +09001328 } else if (vol.type == VolumeInfo.TYPE_STUB) {
1329 vol.mountUserId = mCurrentUserId;
1330 mHandler.obtainMessage(H_VOLUME_MOUNT, vol).sendToTarget();
San Mehat4270e1e2010-01-29 05:32:19 -08001331 } else {
Jeff Sharkey48877892015-03-18 11:27:19 -07001332 Slog.d(TAG, "Skipping automatic mounting of " + vol);
San Mehat4270e1e2010-01-29 05:32:19 -08001333 }
1334 }
1335
Jeff Sharkeye6c04f92015-04-18 21:38:05 -07001336 private boolean isBroadcastWorthy(VolumeInfo vol) {
1337 switch (vol.getType()) {
Jeff Sharkeyc7acac62015-06-12 16:16:56 -07001338 case VolumeInfo.TYPE_PRIVATE:
Jeff Sharkeye6c04f92015-04-18 21:38:05 -07001339 case VolumeInfo.TYPE_PUBLIC:
1340 case VolumeInfo.TYPE_EMULATED:
Risan05c41e62018-10-29 08:57:43 +09001341 case VolumeInfo.TYPE_STUB:
Jeff Sharkeye6c04f92015-04-18 21:38:05 -07001342 break;
1343 default:
1344 return false;
1345 }
1346
1347 switch (vol.getState()) {
1348 case VolumeInfo.STATE_MOUNTED:
1349 case VolumeInfo.STATE_MOUNTED_READ_ONLY:
1350 case VolumeInfo.STATE_EJECTING:
1351 case VolumeInfo.STATE_UNMOUNTED:
Jeff Sharkeyc7acac62015-06-12 16:16:56 -07001352 case VolumeInfo.STATE_UNMOUNTABLE:
Tony Mantlerf0d71052015-06-24 11:45:25 -07001353 case VolumeInfo.STATE_BAD_REMOVAL:
Jeff Sharkeye6c04f92015-04-18 21:38:05 -07001354 break;
1355 default:
1356 return false;
1357 }
1358
1359 return true;
1360 }
1361
Andreas Gampea36dc622018-02-05 17:19:22 -08001362 @GuardedBy("mLock")
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07001363 private void onVolumeStateChangedLocked(VolumeInfo vol, int oldState, int newState) {
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001364 // Remember that we saw this volume so we're ready to accept user
1365 // metadata, or so we can annoy them when a private volume is ejected
1366 if (vol.isMountedReadable() && !TextUtils.isEmpty(vol.fsUuid)) {
Jeff Sharkey5cc0df22015-06-17 19:44:05 -07001367 VolumeRecord rec = mRecords.get(vol.fsUuid);
1368 if (rec == null) {
1369 rec = new VolumeRecord(vol.type, vol.fsUuid);
1370 rec.partGuid = vol.partGuid;
Jeff Sharkeye8a4b662015-06-27 15:43:45 -07001371 rec.createdMillis = System.currentTimeMillis();
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001372 if (vol.type == VolumeInfo.TYPE_PRIVATE) {
1373 rec.nickname = vol.disk.getDescription();
1374 }
1375 mRecords.put(rec.fsUuid, rec);
1376 writeSettingsLocked();
Jeff Sharkey5cc0df22015-06-17 19:44:05 -07001377 } else {
1378 // Handle upgrade case where we didn't store partition GUID
1379 if (TextUtils.isEmpty(rec.partGuid)) {
1380 rec.partGuid = vol.partGuid;
1381 writeSettingsLocked();
1382 }
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001383 }
1384 }
1385
Jeff Sharkeye6c04f92015-04-18 21:38:05 -07001386 mCallbacks.notifyVolumeStateChanged(vol, oldState, newState);
1387
Yasuhiro Matsuda87a38b52015-07-24 22:10:16 +09001388 // Do not broadcast before boot has completed to avoid launching the
1389 // processes that receive the intent unnecessarily.
1390 if (mBootCompleted && isBroadcastWorthy(vol)) {
Jeff Sharkeye6c04f92015-04-18 21:38:05 -07001391 final Intent intent = new Intent(VolumeInfo.ACTION_VOLUME_STATE_CHANGED);
Jeff Sharkeyc7acac62015-06-12 16:16:56 -07001392 intent.putExtra(VolumeInfo.EXTRA_VOLUME_ID, vol.id);
1393 intent.putExtra(VolumeInfo.EXTRA_VOLUME_STATE, newState);
Tony Mantlerf0d71052015-06-24 11:45:25 -07001394 intent.putExtra(VolumeRecord.EXTRA_FS_UUID, vol.fsUuid);
Jeff Sharkey7732e1e2016-03-30 17:14:23 -06001395 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT
1396 | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
Jeff Sharkeyabc3e852015-08-03 14:41:13 -07001397 mHandler.obtainMessage(H_INTERNAL_BROADCAST, intent).sendToTarget();
Jeff Sharkeye6c04f92015-04-18 21:38:05 -07001398 }
Jeff Sharkeyb049e212012-09-07 23:16:01 -07001399
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001400 final String oldStateEnv = VolumeInfo.getEnvironmentForState(oldState);
1401 final String newStateEnv = VolumeInfo.getEnvironmentForState(newState);
Emily Bernier92aa5a22014-07-07 10:11:48 -04001402
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001403 if (!Objects.equals(oldStateEnv, newStateEnv)) {
1404 // Kick state changed event towards all started users. Any users
1405 // started after this point will trigger additional
1406 // user-specific broadcasts.
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07001407 for (int userId : mSystemUnlockedUsers) {
Jeff Sharkey46349872015-07-28 10:49:47 -07001408 if (vol.isVisibleForRead(userId)) {
Svet Ganov6ee871e2015-07-10 14:29:33 -07001409 final StorageVolume userVol = vol.buildStorageVolume(mContext, userId, false);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001410 mHandler.obtainMessage(H_VOLUME_BROADCAST, userVol).sendToTarget();
Jeff Sharkey48877892015-03-18 11:27:19 -07001411
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001412 mCallbacks.notifyStorageStateChanged(userVol.getPath(), oldStateEnv,
1413 newStateEnv);
San Mehat4270e1e2010-01-29 05:32:19 -08001414 }
1415 }
1416 }
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001417
Risan05c41e62018-10-29 08:57:43 +09001418 if ((vol.type == VolumeInfo.TYPE_PUBLIC || vol.type == VolumeInfo.TYPE_STUB)
1419 && vol.state == VolumeInfo.STATE_EJECTING) {
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001420 // TODO: this should eventually be handled by new ObbVolume state changes
1421 /*
1422 * Some OBBs might have been unmounted when this volume was
1423 * unmounted, so send a message to the handler to let it know to
1424 * remove those from the list of mounted OBBS.
1425 */
1426 mObbActionHandler.sendMessage(mObbActionHandler.obtainMessage(
1427 OBB_FLUSH_MOUNT_STATE, vol.path));
1428 }
Pavel Grafovce72ef02018-01-10 17:14:11 +00001429 maybeLogMediaMount(vol, newState);
1430 }
1431
1432 private void maybeLogMediaMount(VolumeInfo vol, int newState) {
1433 if (!SecurityLog.isLoggingEnabled()) {
1434 return;
1435 }
1436
1437 final DiskInfo disk = vol.getDisk();
1438 if (disk == null || (disk.flags & (DiskInfo.FLAG_SD | DiskInfo.FLAG_USB)) == 0) {
1439 return;
1440 }
1441
1442 // Sometimes there is a newline character.
1443 final String label = disk.label != null ? disk.label.trim() : "";
1444
1445 if (newState == VolumeInfo.STATE_MOUNTED
1446 || newState == VolumeInfo.STATE_MOUNTED_READ_ONLY) {
1447 SecurityLog.writeEvent(SecurityLog.TAG_MEDIA_MOUNT, vol.path, label);
1448 } else if (newState == VolumeInfo.STATE_UNMOUNTED
1449 || newState == VolumeInfo.STATE_BAD_REMOVAL) {
1450 SecurityLog.writeEvent(SecurityLog.TAG_MEDIA_UNMOUNT, vol.path, label);
1451 }
San Mehat4270e1e2010-01-29 05:32:19 -08001452 }
1453
Andreas Gampea36dc622018-02-05 17:19:22 -08001454 @GuardedBy("mLock")
Jeff Sharkey275e3e42015-04-24 16:10:32 -07001455 private void onMoveStatusLocked(int status) {
1456 if (mMoveCallback == null) {
1457 Slog.w(TAG, "Odd, status but no move requested");
1458 return;
1459 }
1460
1461 // TODO: estimate remaining time
1462 try {
Jeff Sharkey50a05452015-04-29 11:24:52 -07001463 mMoveCallback.onStatusChanged(-1, status, -1);
Jeff Sharkey275e3e42015-04-24 16:10:32 -07001464 } catch (RemoteException ignored) {
1465 }
1466
1467 // We've finished copying and we're about to clean up old data, so
1468 // remember that move was successful if we get rebooted
1469 if (status == MOVE_STATUS_COPY_FINISHED) {
1470 Slog.d(TAG, "Move to " + mMoveTargetUuid + " copy phase finshed; persisting");
1471
1472 mPrimaryStorageUuid = mMoveTargetUuid;
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001473 writeSettingsLocked();
Jeff Sharkey275e3e42015-04-24 16:10:32 -07001474 }
1475
1476 if (PackageManager.isMoveStatusFinished(status)) {
1477 Slog.d(TAG, "Move to " + mMoveTargetUuid + " finished with status " + status);
1478
1479 mMoveCallback = null;
1480 mMoveTargetUuid = null;
1481 }
1482 }
1483
Jeff Sharkey48877892015-03-18 11:27:19 -07001484 private void enforcePermission(String perm) {
1485 mContext.enforceCallingOrSelfPermission(perm, perm);
Mike Lockwooda5250c92011-05-23 13:44:04 -04001486 }
1487
Jeff Sharkey2e606d72015-07-27 14:19:54 -07001488 /**
1489 * Decide if volume is mountable per device policies.
1490 */
1491 private boolean isMountDisallowed(VolumeInfo vol) {
Philip P. Moltmannec3cbb22016-09-14 13:24:52 -07001492 UserManager userManager = mContext.getSystemService(UserManager.class);
1493
1494 boolean isUsbRestricted = false;
1495 if (vol.disk != null && vol.disk.isUsb()) {
1496 isUsbRestricted = userManager.hasUserRestriction(UserManager.DISALLOW_USB_FILE_TRANSFER,
Jeff Sharkey2e606d72015-07-27 14:19:54 -07001497 Binder.getCallingUserHandle());
Emily Bernier92aa5a22014-07-07 10:11:48 -04001498 }
Philip P. Moltmannec3cbb22016-09-14 13:24:52 -07001499
1500 boolean isTypeRestricted = false;
Risan05c41e62018-10-29 08:57:43 +09001501 if (vol.type == VolumeInfo.TYPE_PUBLIC || vol.type == VolumeInfo.TYPE_PRIVATE
1502 || vol.type == VolumeInfo.TYPE_STUB) {
Philip P. Moltmannec3cbb22016-09-14 13:24:52 -07001503 isTypeRestricted = userManager
1504 .hasUserRestriction(UserManager.DISALLOW_MOUNT_PHYSICAL_MEDIA,
1505 Binder.getCallingUserHandle());
1506 }
1507
1508 return isUsbRestricted || isTypeRestricted;
Emily Bernier92aa5a22014-07-07 10:11:48 -04001509 }
1510
Amith Yamasani462ac3a2015-06-30 14:21:01 -07001511 private void enforceAdminUser() {
1512 UserManager um = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
1513 final int callingUserId = UserHandle.getCallingUserId();
1514 boolean isAdmin;
1515 long token = Binder.clearCallingIdentity();
1516 try {
1517 isAdmin = um.getUserInfo(callingUserId).isAdmin();
1518 } finally {
1519 Binder.restoreCallingIdentity(token);
1520 }
1521 if (!isAdmin) {
1522 throw new SecurityException("Only admin users can adopt sd cards");
1523 }
1524 }
1525
Jeff Sharkeyb049e212012-09-07 23:16:01 -07001526 /**
Sudheer Shanka2250d562016-11-07 15:41:02 -08001527 * Constructs a new StorageManagerService instance
San Mehat207e5382010-02-04 20:46:54 -08001528 *
1529 * @param context Binder context for this service
1530 */
Sudheer Shanka2250d562016-11-07 15:41:02 -08001531 public StorageManagerService(Context context) {
Christopher Tated417d622013-08-19 16:14:25 -07001532 sSelf = this;
1533
Jeff Sharkey342b4bf2018-12-18 11:12:40 -07001534 // Snapshot feature flag used for this boot
1535 SystemProperties.set(StorageManager.PROP_ISOLATED_STORAGE_SNAPSHOT, Boolean.toString(
1536 SystemProperties.getBoolean(StorageManager.PROP_ISOLATED_STORAGE, false)));
1537
San Mehat207e5382010-02-04 20:46:54 -08001538 mContext = context;
Jeff Sharkey5d0c55c2019-01-24 14:32:31 -07001539 mResolver = mContext.getContentResolver();
1540
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001541 mCallbacks = new Callbacks(FgThread.get().getLooper());
Jeff Sharkeyb9fe5372015-12-03 15:23:08 -07001542 mLockPatternUtils = new LockPatternUtils(mContext);
San Mehat207e5382010-02-04 20:46:54 -08001543
Dianne Hackbornefa92b22013-05-03 14:11:43 -07001544 HandlerThread hthread = new HandlerThread(TAG);
1545 hthread.start();
Sudheer Shanka2250d562016-11-07 15:41:02 -08001546 mHandler = new StorageManagerServiceHandler(hthread.getLooper());
Daniel Sandler5f27ef42010-03-16 15:42:02 -04001547
Sudheer Shanka2250d562016-11-07 15:41:02 -08001548 // Add OBB Action Handler to StorageManagerService thread.
Dianne Hackborn8d044e82013-04-30 17:24:15 -07001549 mObbActionHandler = new ObbActionHandler(IoThread.get().getLooper());
Kenny Roota02b8b02010-08-05 16:14:17 -07001550
Christopher Tate7265abe2014-11-21 13:54:45 -08001551 // Initialize the last-fstrim tracking if necessary
1552 File dataDir = Environment.getDataDirectory();
1553 File systemDir = new File(dataDir, "system");
1554 mLastMaintenanceFile = new File(systemDir, LAST_FSTRIM_FILE);
1555 if (!mLastMaintenanceFile.exists()) {
1556 // Not setting mLastMaintenance here means that we will force an
1557 // fstrim during reboot following the OTA that installs this code.
1558 try {
1559 (new FileOutputStream(mLastMaintenanceFile)).close();
1560 } catch (IOException e) {
1561 Slog.e(TAG, "Unable to create fstrim record " + mLastMaintenanceFile.getPath());
1562 }
1563 } else {
1564 mLastMaintenance = mLastMaintenanceFile.lastModified();
1565 }
1566
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001567 mSettingsFile = new AtomicFile(
Dianne Hackborne17b4452018-01-10 13:15:40 -08001568 new File(Environment.getDataSystemDirectory(), "storage.xml"), "storage-settings");
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001569
1570 synchronized (mLock) {
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001571 readSettingsLocked();
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001572 }
1573
Sudheer Shanka2250d562016-11-07 15:41:02 -08001574 LocalServices.addService(StorageManagerInternal.class, mStorageManagerInternal);
Svet Ganov6ee871e2015-07-10 14:29:33 -07001575
Jeff Sharkeybcd262d2015-06-10 09:41:17 -07001576 final IntentFilter userFilter = new IntentFilter();
1577 userFilter.addAction(Intent.ACTION_USER_ADDED);
1578 userFilter.addAction(Intent.ACTION_USER_REMOVED);
1579 mContext.registerReceiver(mUserReceiver, userFilter, null, mHandler);
1580
Jeff Sharkey5a9bb742015-11-03 10:15:57 -08001581 synchronized (mLock) {
1582 addInternalVolumeLocked();
1583 }
Amith Yamasania7892482015-08-07 11:09:05 -07001584
Kenny Root07714d42011-08-17 17:49:28 -07001585 // Add ourself to the Watchdog monitors if enabled.
1586 if (WATCHDOG_ENABLE) {
1587 Watchdog.getInstance().addMonitor(this);
1588 }
San Mehat207e5382010-02-04 20:46:54 -08001589 }
1590
Jeff Sharkeycd575992016-03-29 14:12:49 -06001591 private void start() {
Jeff Sharkey1019de92017-09-06 13:47:03 -06001592 connect();
Jeff Sharkeycd575992016-03-29 14:12:49 -06001593 }
1594
Sudheer Shanka0a541a52018-07-31 13:21:11 -07001595 private static String getSandboxId(String packageName, String sharedUserId) {
Sudheer Shankad68bd602018-11-13 17:43:39 -08001596 return sharedUserId == null
1597 ? packageName : StorageManager.SHARED_SANDBOX_PREFIX + sharedUserId;
Sudheer Shanka0a541a52018-07-31 13:21:11 -07001598 }
Sudheer Shanka0a541a52018-07-31 13:21:11 -07001599
Jeff Sharkey1019de92017-09-06 13:47:03 -06001600 private void connect() {
Jin Qian12690d52017-10-13 18:17:04 -07001601 IBinder binder = ServiceManager.getService("storaged");
1602 if (binder != null) {
1603 try {
1604 binder.linkToDeath(new DeathRecipient() {
1605 @Override
1606 public void binderDied() {
1607 Slog.w(TAG, "storaged died; reconnecting");
1608 mStoraged = null;
1609 connect();
1610 }
1611 }, 0);
1612 } catch (RemoteException e) {
1613 binder = null;
1614 }
1615 }
1616
1617 if (binder != null) {
1618 mStoraged = IStoraged.Stub.asInterface(binder);
1619 } else {
1620 Slog.w(TAG, "storaged not found; trying again");
1621 }
1622
1623 binder = ServiceManager.getService("vold");
Jeff Sharkey1019de92017-09-06 13:47:03 -06001624 if (binder != null) {
1625 try {
1626 binder.linkToDeath(new DeathRecipient() {
1627 @Override
1628 public void binderDied() {
1629 Slog.w(TAG, "vold died; reconnecting");
Jin Qian12690d52017-10-13 18:17:04 -07001630 mVold = null;
Jeff Sharkey1019de92017-09-06 13:47:03 -06001631 connect();
1632 }
1633 }, 0);
1634 } catch (RemoteException e) {
1635 binder = null;
1636 }
1637 }
1638
1639 if (binder != null) {
1640 mVold = IVold.Stub.asInterface(binder);
Jeff Sharkey8058fe62017-09-13 11:50:33 -06001641 try {
1642 mVold.setListener(mListener);
Jeff Sharkey8058fe62017-09-13 11:50:33 -06001643 } catch (RemoteException e) {
Jin Qian12690d52017-10-13 18:17:04 -07001644 mVold = null;
Jeff Sharkey8058fe62017-09-13 11:50:33 -06001645 Slog.w(TAG, "vold listener rejected; trying again", e);
1646 }
Jeff Sharkey1019de92017-09-06 13:47:03 -06001647 } else {
1648 Slog.w(TAG, "vold not found; trying again");
Jeff Sharkey1019de92017-09-06 13:47:03 -06001649 }
Jeff Sharkey8058fe62017-09-13 11:50:33 -06001650
Jin Qian12690d52017-10-13 18:17:04 -07001651 if (mStoraged == null || mVold == null) {
1652 BackgroundThread.getHandler().postDelayed(() -> {
1653 connect();
1654 }, DateUtils.SECOND_IN_MILLIS);
1655 } else {
1656 onDaemonConnected();
1657 }
Jeff Sharkey1019de92017-09-06 13:47:03 -06001658 }
1659
Jeff Sharkey11697f52018-12-13 10:14:42 -07001660 private void servicesReady() {
Sudheer Shankaff585072019-01-29 23:19:45 -08001661 mPmInternal = LocalServices.getService(PackageManagerInternal.class);
1662 mUmInternal = LocalServices.getService(UserManagerInternal.class);
1663 mAmInternal = LocalServices.getService(ActivityManagerInternal.class);
1664
1665 mIPackageManager = IPackageManager.Stub.asInterface(
1666 ServiceManager.getService("package"));
1667 mIAppOpsService = IAppOpsService.Stub.asInterface(
1668 ServiceManager.getService(Context.APP_OPS_SERVICE));
1669 try {
1670 mIAppOpsService.startWatchingMode(OP_REQUEST_INSTALL_PACKAGES, null, mAppOpsCallback);
1671 } catch (RemoteException e) {
1672 }
1673
Jeff Sharkey11697f52018-12-13 10:14:42 -07001674 synchronized (mLock) {
1675 final boolean thisIsolatedStorage = StorageManager.hasIsolatedStorage();
1676 if (mLastIsolatedStorage == thisIsolatedStorage) {
1677 // Nothing changed since last boot; keep rolling forward
1678 return;
1679 } else if (thisIsolatedStorage) {
1680 // This boot enables isolated storage; apply legacy behavior
1681 applyLegacyStorage();
1682 }
1683
1684 // Always remember the new state we just booted with
1685 writeSettingsLocked();
1686 }
1687 }
1688
1689 /**
1690 * If we're enabling isolated storage, we need to remember which existing
1691 * apps have already been using shared storage, and grant them legacy access
1692 * to keep them running smoothly.
1693 */
1694 private void applyLegacyStorage() {
1695 final AppOpsManager appOps = mContext.getSystemService(AppOpsManager.class);
1696 final UserManagerInternal um = LocalServices.getService(UserManagerInternal.class);
1697 for (int userId : um.getUserIds()) {
1698 final PackageManager pm;
1699 try {
1700 pm = mContext.createPackageContextAsUser(mContext.getPackageName(),
1701 0, UserHandle.of(userId)).getPackageManager();
1702 } catch (PackageManager.NameNotFoundException e) {
1703 throw new RuntimeException(e);
1704 }
1705
1706 final List<PackageInfo> pkgs = pm.getPackagesHoldingPermissions(new String[] {
1707 android.Manifest.permission.READ_EXTERNAL_STORAGE,
1708 android.Manifest.permission.WRITE_EXTERNAL_STORAGE
1709 }, MATCH_UNINSTALLED_PACKAGES | MATCH_DIRECT_BOOT_AWARE | MATCH_DIRECT_BOOT_UNAWARE);
1710 for (PackageInfo pkg : pkgs) {
1711 final int uid = pkg.applicationInfo.uid;
1712 final String packageName = pkg.applicationInfo.packageName;
1713
1714 final long lastAccess = getLastAccessTime(appOps, uid, packageName, new int[] {
1715 AppOpsManager.OP_READ_EXTERNAL_STORAGE,
1716 AppOpsManager.OP_WRITE_EXTERNAL_STORAGE,
1717 });
1718
1719 Log.d(TAG, "Found " + uid + " " + packageName
1720 + " with granted storage access, last accessed " + lastAccess);
1721 if (lastAccess > 0) {
1722 appOps.setMode(AppOpsManager.OP_LEGACY_STORAGE,
1723 uid, packageName, AppOpsManager.MODE_ALLOWED);
1724 }
1725 }
1726 }
1727 }
1728
1729 private static long getLastAccessTime(AppOpsManager manager,
1730 int uid, String packageName, int[] ops) {
1731 long maxTime = 0;
1732 final List<AppOpsManager.PackageOps> pkgs = manager.getOpsForPackage(uid, packageName, ops);
Eugene Susla04d021c2018-12-17 14:49:59 -08001733 for (AppOpsManager.PackageOps pkg : CollectionUtils.emptyIfNull(pkgs)) {
1734 for (AppOpsManager.OpEntry op : CollectionUtils.emptyIfNull(pkg.getOps())) {
Jeff Sharkey11697f52018-12-13 10:14:42 -07001735 maxTime = Math.max(maxTime, op.getLastAccessTime());
1736 }
1737 }
1738 return maxTime;
1739 }
1740
Jeff Sharkey56e62932015-03-21 20:41:00 -07001741 private void systemReady() {
Wale Ogunwale6767eae2018-05-03 15:52:51 -07001742 LocalServices.getService(ActivityTaskManagerInternal.class)
Jeff Sharkey9765e442017-12-14 22:15:14 -07001743 .registerScreenObserver(this);
1744
Jeff Sharkeyb049e212012-09-07 23:16:01 -07001745 mSystemReady = true;
1746 mHandler.obtainMessage(H_SYSTEM_READY).sendToTarget();
1747 }
1748
Yasuhiro Matsuda87a38b52015-07-24 22:10:16 +09001749 private void bootCompleted() {
1750 mBootCompleted = true;
1751 }
1752
Jeff Sharkeyfced5342015-05-10 14:53:34 -07001753 private String getDefaultPrimaryStorageUuid() {
1754 if (SystemProperties.getBoolean(StorageManager.PROP_PRIMARY_PHYSICAL, false)) {
1755 return StorageManager.UUID_PRIMARY_PHYSICAL;
1756 } else {
1757 return StorageManager.UUID_PRIVATE_INTERNAL;
1758 }
1759 }
1760
Andreas Gampea36dc622018-02-05 17:19:22 -08001761 @GuardedBy("mLock")
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001762 private void readSettingsLocked() {
1763 mRecords.clear();
Jeff Sharkeyfced5342015-05-10 14:53:34 -07001764 mPrimaryStorageUuid = getDefaultPrimaryStorageUuid();
Jeff Sharkey11697f52018-12-13 10:14:42 -07001765 mLastIsolatedStorage = false;
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001766
1767 FileInputStream fis = null;
1768 try {
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001769 fis = mSettingsFile.openRead();
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001770 final XmlPullParser in = Xml.newPullParser();
Wojciech Staszkiewicz9e9e2e72015-05-08 14:58:46 +01001771 in.setInput(fis, StandardCharsets.UTF_8.name());
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001772
1773 int type;
1774 while ((type = in.next()) != END_DOCUMENT) {
1775 if (type == START_TAG) {
1776 final String tag = in.getName();
Jeff Sharkey620b32b2015-04-23 19:36:02 -07001777 if (TAG_VOLUMES.equals(tag)) {
1778 final int version = readIntAttribute(in, ATTR_VERSION, VERSION_INIT);
Jeff Sharkeyfced5342015-05-10 14:53:34 -07001779 final boolean primaryPhysical = SystemProperties.getBoolean(
1780 StorageManager.PROP_PRIMARY_PHYSICAL, false);
1781 final boolean validAttr = (version >= VERSION_FIX_PRIMARY)
1782 || (version >= VERSION_ADD_PRIMARY && !primaryPhysical);
1783 if (validAttr) {
Jeff Sharkey620b32b2015-04-23 19:36:02 -07001784 mPrimaryStorageUuid = readStringAttribute(in,
1785 ATTR_PRIMARY_STORAGE_UUID);
Jeff Sharkey620b32b2015-04-23 19:36:02 -07001786 }
Jeff Sharkey11697f52018-12-13 10:14:42 -07001787 mLastIsolatedStorage = readBooleanAttribute(in,
1788 ATTR_ISOLATED_STORAGE, false);
Jeff Sharkey620b32b2015-04-23 19:36:02 -07001789
1790 } else if (TAG_VOLUME.equals(tag)) {
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001791 final VolumeRecord rec = readVolumeRecord(in);
1792 mRecords.put(rec.fsUuid, rec);
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001793 }
1794 }
1795 }
1796 } catch (FileNotFoundException e) {
1797 // Missing metadata is okay, probably first boot
1798 } catch (IOException e) {
1799 Slog.wtf(TAG, "Failed reading metadata", e);
1800 } catch (XmlPullParserException e) {
1801 Slog.wtf(TAG, "Failed reading metadata", e);
1802 } finally {
1803 IoUtils.closeQuietly(fis);
1804 }
1805 }
1806
Andreas Gampea36dc622018-02-05 17:19:22 -08001807 @GuardedBy("mLock")
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001808 private void writeSettingsLocked() {
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001809 FileOutputStream fos = null;
1810 try {
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001811 fos = mSettingsFile.startWrite();
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001812
1813 XmlSerializer out = new FastXmlSerializer();
Wojciech Staszkiewicz9e9e2e72015-05-08 14:58:46 +01001814 out.setOutput(fos, StandardCharsets.UTF_8.name());
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001815 out.startDocument(null, true);
1816 out.startTag(null, TAG_VOLUMES);
Jeff Sharkeyfced5342015-05-10 14:53:34 -07001817 writeIntAttribute(out, ATTR_VERSION, VERSION_FIX_PRIMARY);
Jeff Sharkey620b32b2015-04-23 19:36:02 -07001818 writeStringAttribute(out, ATTR_PRIMARY_STORAGE_UUID, mPrimaryStorageUuid);
Jeff Sharkey11697f52018-12-13 10:14:42 -07001819 writeBooleanAttribute(out, ATTR_ISOLATED_STORAGE, StorageManager.hasIsolatedStorage());
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001820 final int size = mRecords.size();
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001821 for (int i = 0; i < size; i++) {
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001822 final VolumeRecord rec = mRecords.valueAt(i);
1823 writeVolumeRecord(out, rec);
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001824 }
1825 out.endTag(null, TAG_VOLUMES);
1826 out.endDocument();
1827
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001828 mSettingsFile.finishWrite(fos);
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001829 } catch (IOException e) {
1830 if (fos != null) {
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001831 mSettingsFile.failWrite(fos);
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001832 }
1833 }
1834 }
1835
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001836 public static VolumeRecord readVolumeRecord(XmlPullParser in) throws IOException {
1837 final int type = readIntAttribute(in, ATTR_TYPE);
1838 final String fsUuid = readStringAttribute(in, ATTR_FS_UUID);
1839 final VolumeRecord meta = new VolumeRecord(type, fsUuid);
Jeff Sharkey5cc0df22015-06-17 19:44:05 -07001840 meta.partGuid = readStringAttribute(in, ATTR_PART_GUID);
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001841 meta.nickname = readStringAttribute(in, ATTR_NICKNAME);
1842 meta.userFlags = readIntAttribute(in, ATTR_USER_FLAGS);
Jeff Sharkeye8a4b662015-06-27 15:43:45 -07001843 meta.createdMillis = readLongAttribute(in, ATTR_CREATED_MILLIS);
1844 meta.lastTrimMillis = readLongAttribute(in, ATTR_LAST_TRIM_MILLIS);
1845 meta.lastBenchMillis = readLongAttribute(in, ATTR_LAST_BENCH_MILLIS);
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001846 return meta;
1847 }
1848
1849 public static void writeVolumeRecord(XmlSerializer out, VolumeRecord rec) throws IOException {
1850 out.startTag(null, TAG_VOLUME);
1851 writeIntAttribute(out, ATTR_TYPE, rec.type);
1852 writeStringAttribute(out, ATTR_FS_UUID, rec.fsUuid);
Jeff Sharkey5cc0df22015-06-17 19:44:05 -07001853 writeStringAttribute(out, ATTR_PART_GUID, rec.partGuid);
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001854 writeStringAttribute(out, ATTR_NICKNAME, rec.nickname);
1855 writeIntAttribute(out, ATTR_USER_FLAGS, rec.userFlags);
Jeff Sharkeye8a4b662015-06-27 15:43:45 -07001856 writeLongAttribute(out, ATTR_CREATED_MILLIS, rec.createdMillis);
1857 writeLongAttribute(out, ATTR_LAST_TRIM_MILLIS, rec.lastTrimMillis);
1858 writeLongAttribute(out, ATTR_LAST_BENCH_MILLIS, rec.lastBenchMillis);
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001859 out.endTag(null, TAG_VOLUME);
1860 }
1861
San Mehat207e5382010-02-04 20:46:54 -08001862 /**
San Mehat4270e1e2010-01-29 05:32:19 -08001863 * Exposed API calls below here
1864 */
1865
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001866 @Override
Sudheer Shanka2250d562016-11-07 15:41:02 -08001867 public void registerListener(IStorageEventListener listener) {
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001868 mCallbacks.register(listener);
San Mehat4270e1e2010-01-29 05:32:19 -08001869 }
1870
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001871 @Override
Sudheer Shanka2250d562016-11-07 15:41:02 -08001872 public void unregisterListener(IStorageEventListener listener) {
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001873 mCallbacks.unregister(listener);
San Mehat4270e1e2010-01-29 05:32:19 -08001874 }
1875
Jeff Sharkey48877892015-03-18 11:27:19 -07001876 @Override
Sudheer Shanka2250d562016-11-07 15:41:02 -08001877 public void shutdown(final IStorageShutdownObserver observer) {
Jeff Sharkey48877892015-03-18 11:27:19 -07001878 enforcePermission(android.Manifest.permission.SHUTDOWN);
San Mehat4270e1e2010-01-29 05:32:19 -08001879
San Mehata5078592010-03-25 09:36:54 -07001880 Slog.i(TAG, "Shutting down");
Jeff Sharkey48877892015-03-18 11:27:19 -07001881 mHandler.obtainMessage(H_SHUTDOWN, observer).sendToTarget();
San Mehat4270e1e2010-01-29 05:32:19 -08001882 }
1883
Jeff Sharkey48877892015-03-18 11:27:19 -07001884 @Override
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001885 public void mount(String volId) {
1886 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001887
Jeff Sharkeyef10ee02015-07-05 14:17:27 -07001888 final VolumeInfo vol = findVolumeByIdOrThrow(volId);
Jeff Sharkey2e606d72015-07-27 14:19:54 -07001889 if (isMountDisallowed(vol)) {
1890 throw new SecurityException("Mounting " + volId + " restricted by policy");
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001891 }
Sudheer Shanka3f0645b2018-09-18 13:07:59 -07001892 mount(vol);
1893 }
1894
1895 private void mount(VolumeInfo vol) {
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001896 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06001897 mVold.mount(vol.id, vol.mountFlags, vol.mountUserId);
Sudheer Shanka3f0645b2018-09-18 13:07:59 -07001898 if ((vol.mountFlags & VolumeInfo.MOUNT_FLAG_VISIBLE) != 0) {
1899 mVisibleVols.add(vol);
1900 }
Jeff Sharkeyace874b2017-09-07 15:27:33 -06001901 } catch (Exception e) {
1902 Slog.wtf(TAG, e);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001903 }
1904 }
1905
1906 @Override
1907 public void unmount(String volId) {
1908 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001909
Jeff Sharkeyef10ee02015-07-05 14:17:27 -07001910 final VolumeInfo vol = findVolumeByIdOrThrow(volId);
Sudheer Shanka3f0645b2018-09-18 13:07:59 -07001911 unmount(vol);
1912 }
1913
1914 private void unmount(VolumeInfo vol) {
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001915 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06001916 mVold.unmount(vol.id);
Sudheer Shanka3f0645b2018-09-18 13:07:59 -07001917 if ((vol.mountFlags & VolumeInfo.MOUNT_FLAG_VISIBLE) != 0) {
1918 mVisibleVols.remove(vol);
1919 }
Jeff Sharkeyace874b2017-09-07 15:27:33 -06001920 } catch (Exception e) {
1921 Slog.wtf(TAG, e);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001922 }
1923 }
1924
1925 @Override
1926 public void format(String volId) {
Jeff Sharkey48877892015-03-18 11:27:19 -07001927 enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);
San Mehat5b77dab2010-01-26 13:28:50 -08001928
Jeff Sharkeyef10ee02015-07-05 14:17:27 -07001929 final VolumeInfo vol = findVolumeByIdOrThrow(volId);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001930 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06001931 mVold.format(vol.id, "auto");
Jeff Sharkeyace874b2017-09-07 15:27:33 -06001932 } catch (Exception e) {
1933 Slog.wtf(TAG, e);
Jeff Sharkey48877892015-03-18 11:27:19 -07001934 }
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001935 }
1936
1937 @Override
Jeff Sharkey7e19f532017-11-06 13:54:11 -07001938 public void benchmark(String volId, IVoldTaskListener listener) {
Jeff Sharkey9756d752015-05-14 21:07:42 -07001939 enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);
Jeff Sharkey9756d752015-05-14 21:07:42 -07001940
1941 try {
Jeff Sharkeyb302c542017-09-15 12:57:59 -06001942 mVold.benchmark(volId, new IVoldTaskListener.Stub() {
1943 @Override
1944 public void onStatus(int status, PersistableBundle extras) {
Jeff Sharkey7e19f532017-11-06 13:54:11 -07001945 dispatchOnStatus(listener, status, extras);
Jeff Sharkeyb302c542017-09-15 12:57:59 -06001946 }
1947
1948 @Override
1949 public void onFinished(int status, PersistableBundle extras) {
Jeff Sharkey7e19f532017-11-06 13:54:11 -07001950 dispatchOnFinished(listener, status, extras);
Jeff Sharkeyb302c542017-09-15 12:57:59 -06001951
1952 final String path = extras.getString("path");
1953 final String ident = extras.getString("ident");
1954 final long create = extras.getLong("create");
1955 final long run = extras.getLong("run");
1956 final long destroy = extras.getLong("destroy");
1957
1958 final DropBoxManager dropBox = mContext.getSystemService(DropBoxManager.class);
1959 dropBox.addText(TAG_STORAGE_BENCHMARK, scrubPath(path)
1960 + " " + ident + " " + create + " " + run + " " + destroy);
1961
1962 synchronized (mLock) {
1963 final VolumeRecord rec = findRecordForPath(path);
1964 if (rec != null) {
1965 rec.lastBenchMillis = System.currentTimeMillis();
1966 writeSettingsLocked();
1967 }
1968 }
1969 }
1970 });
Jeff Sharkey7e19f532017-11-06 13:54:11 -07001971 } catch (RemoteException e) {
1972 throw e.rethrowAsRuntimeException();
Jeff Sharkey9756d752015-05-14 21:07:42 -07001973 }
1974 }
1975
1976 @Override
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001977 public void partitionPublic(String diskId) {
1978 enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001979
Jeff Sharkeyeba260d2015-04-19 14:35:16 -07001980 final CountDownLatch latch = findOrCreateDiskScanLatch(diskId);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001981 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06001982 mVold.partition(diskId, IVold.PARTITION_TYPE_PUBLIC, -1);
Jeff Sharkeyedcdaf62015-07-09 09:45:36 -07001983 waitForLatch(latch, "partitionPublic", 3 * DateUtils.MINUTE_IN_MILLIS);
Jeff Sharkeyace874b2017-09-07 15:27:33 -06001984 } catch (Exception e) {
1985 Slog.wtf(TAG, e);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001986 }
1987 }
1988
1989 @Override
1990 public void partitionPrivate(String diskId) {
1991 enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);
Amith Yamasani462ac3a2015-06-30 14:21:01 -07001992 enforceAdminUser();
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001993
Jeff Sharkeyeba260d2015-04-19 14:35:16 -07001994 final CountDownLatch latch = findOrCreateDiskScanLatch(diskId);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001995 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06001996 mVold.partition(diskId, IVold.PARTITION_TYPE_PRIVATE, -1);
Jeff Sharkeyedcdaf62015-07-09 09:45:36 -07001997 waitForLatch(latch, "partitionPrivate", 3 * DateUtils.MINUTE_IN_MILLIS);
Jeff Sharkeyace874b2017-09-07 15:27:33 -06001998 } catch (Exception e) {
1999 Slog.wtf(TAG, e);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07002000 }
2001 }
2002
2003 @Override
2004 public void partitionMixed(String diskId, int ratio) {
2005 enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);
Amith Yamasani462ac3a2015-06-30 14:21:01 -07002006 enforceAdminUser();
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07002007
Jeff Sharkeyeba260d2015-04-19 14:35:16 -07002008 final CountDownLatch latch = findOrCreateDiskScanLatch(diskId);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07002009 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002010 mVold.partition(diskId, IVold.PARTITION_TYPE_MIXED, ratio);
Jeff Sharkeyedcdaf62015-07-09 09:45:36 -07002011 waitForLatch(latch, "partitionMixed", 3 * DateUtils.MINUTE_IN_MILLIS);
Jeff Sharkeyace874b2017-09-07 15:27:33 -06002012 } catch (Exception e) {
2013 Slog.wtf(TAG, e);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07002014 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002015 }
2016
Jeff Sharkey48877892015-03-18 11:27:19 -07002017 @Override
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07002018 public void setVolumeNickname(String fsUuid, String nickname) {
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07002019 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07002020
Jeff Sharkey50a05452015-04-29 11:24:52 -07002021 Preconditions.checkNotNull(fsUuid);
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07002022 synchronized (mLock) {
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07002023 final VolumeRecord rec = mRecords.get(fsUuid);
2024 rec.nickname = nickname;
Jeff Sharkey50a05452015-04-29 11:24:52 -07002025 mCallbacks.notifyVolumeRecordChanged(rec);
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07002026 writeSettingsLocked();
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07002027 }
2028 }
2029
2030 @Override
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07002031 public void setVolumeUserFlags(String fsUuid, int flags, int mask) {
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07002032 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07002033
Jeff Sharkey50a05452015-04-29 11:24:52 -07002034 Preconditions.checkNotNull(fsUuid);
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07002035 synchronized (mLock) {
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07002036 final VolumeRecord rec = mRecords.get(fsUuid);
2037 rec.userFlags = (rec.userFlags & ~mask) | (flags & mask);
Jeff Sharkey50a05452015-04-29 11:24:52 -07002038 mCallbacks.notifyVolumeRecordChanged(rec);
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07002039 writeSettingsLocked();
2040 }
2041 }
2042
2043 @Override
2044 public void forgetVolume(String fsUuid) {
2045 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07002046
Jeff Sharkey50a05452015-04-29 11:24:52 -07002047 Preconditions.checkNotNull(fsUuid);
Jeff Sharkey5a9bb742015-11-03 10:15:57 -08002048
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07002049 synchronized (mLock) {
Jeff Sharkey5cc0df22015-06-17 19:44:05 -07002050 final VolumeRecord rec = mRecords.remove(fsUuid);
2051 if (rec != null && !TextUtils.isEmpty(rec.partGuid)) {
Jeff Sharkeydb4b6192017-10-24 11:08:50 -06002052 mHandler.obtainMessage(H_PARTITION_FORGET, rec).sendToTarget();
Jeff Sharkey5cc0df22015-06-17 19:44:05 -07002053 }
2054 mCallbacks.notifyVolumeForgotten(fsUuid);
Jeff Sharkey50a05452015-04-29 11:24:52 -07002055
2056 // If this had been primary storage, revert back to internal and
2057 // reset vold so we bind into new volume into place.
2058 if (Objects.equals(mPrimaryStorageUuid, fsUuid)) {
Jeff Sharkeyfced5342015-05-10 14:53:34 -07002059 mPrimaryStorageUuid = getDefaultPrimaryStorageUuid();
Jeff Sharkey5a9bb742015-11-03 10:15:57 -08002060 mHandler.obtainMessage(H_RESET).sendToTarget();
Jeff Sharkey50a05452015-04-29 11:24:52 -07002061 }
2062
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07002063 writeSettingsLocked();
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07002064 }
2065 }
2066
Jeff Sharkey7d2af542015-05-12 15:27:15 -07002067 @Override
2068 public void forgetAllVolumes() {
2069 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
Jeff Sharkey7d2af542015-05-12 15:27:15 -07002070
Jeff Sharkey50a05452015-04-29 11:24:52 -07002071 synchronized (mLock) {
2072 for (int i = 0; i < mRecords.size(); i++) {
2073 final String fsUuid = mRecords.keyAt(i);
Jeff Sharkey5cc0df22015-06-17 19:44:05 -07002074 final VolumeRecord rec = mRecords.valueAt(i);
2075 if (!TextUtils.isEmpty(rec.partGuid)) {
Jeff Sharkeydb4b6192017-10-24 11:08:50 -06002076 mHandler.obtainMessage(H_PARTITION_FORGET, rec).sendToTarget();
Jeff Sharkey5cc0df22015-06-17 19:44:05 -07002077 }
Jeff Sharkey50a05452015-04-29 11:24:52 -07002078 mCallbacks.notifyVolumeForgotten(fsUuid);
2079 }
Jeff Sharkey50a05452015-04-29 11:24:52 -07002080 mRecords.clear();
Jeff Sharkey50a05452015-04-29 11:24:52 -07002081
Jeff Sharkeyfced5342015-05-10 14:53:34 -07002082 if (!Objects.equals(StorageManager.UUID_PRIVATE_INTERNAL, mPrimaryStorageUuid)) {
2083 mPrimaryStorageUuid = getDefaultPrimaryStorageUuid();
2084 }
2085
2086 writeSettingsLocked();
Jeff Sharkey5a9bb742015-11-03 10:15:57 -08002087 mHandler.obtainMessage(H_RESET).sendToTarget();
Jeff Sharkey50a05452015-04-29 11:24:52 -07002088 }
2089 }
2090
Jeff Sharkeydb4b6192017-10-24 11:08:50 -06002091 private void forgetPartition(String partGuid, String fsUuid) {
Jeff Sharkey5cc0df22015-06-17 19:44:05 -07002092 try {
Jeff Sharkeydb4b6192017-10-24 11:08:50 -06002093 mVold.forgetPartition(partGuid, fsUuid);
Jeff Sharkeyace874b2017-09-07 15:27:33 -06002094 } catch (Exception e) {
2095 Slog.wtf(TAG, e);
Jeff Sharkey5cc0df22015-06-17 19:44:05 -07002096 }
2097 }
2098
Jeff Sharkey31d0b702016-11-21 14:16:53 -07002099 @Override
Jeff Sharkey7e19f532017-11-06 13:54:11 -07002100 public void fstrim(int flags, IVoldTaskListener listener) {
Jeff Sharkey31d0b702016-11-21 14:16:53 -07002101 enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);
Jeff Sharkey31d0b702016-11-21 14:16:53 -07002102
2103 try {
Jeff Sharkeyb302c542017-09-15 12:57:59 -06002104 mVold.fstrim(flags, new IVoldTaskListener.Stub() {
2105 @Override
2106 public void onStatus(int status, PersistableBundle extras) {
Jeff Sharkey7e19f532017-11-06 13:54:11 -07002107 dispatchOnStatus(listener, status, extras);
2108
Jeff Sharkeyb302c542017-09-15 12:57:59 -06002109 // Ignore trim failures
2110 if (status != 0) return;
2111
2112 final String path = extras.getString("path");
2113 final long bytes = extras.getLong("bytes");
2114 final long time = extras.getLong("time");
2115
2116 final DropBoxManager dropBox = mContext.getSystemService(DropBoxManager.class);
2117 dropBox.addText(TAG_STORAGE_TRIM, scrubPath(path) + " " + bytes + " " + time);
2118
2119 synchronized (mLock) {
2120 final VolumeRecord rec = findRecordForPath(path);
2121 if (rec != null) {
2122 rec.lastTrimMillis = System.currentTimeMillis();
2123 writeSettingsLocked();
2124 }
2125 }
2126 }
2127
2128 @Override
2129 public void onFinished(int status, PersistableBundle extras) {
Jeff Sharkey7e19f532017-11-06 13:54:11 -07002130 dispatchOnFinished(listener, status, extras);
2131
Jeff Sharkeyb302c542017-09-15 12:57:59 -06002132 // TODO: benchmark when desired
2133 }
2134 });
Jeff Sharkey7e19f532017-11-06 13:54:11 -07002135 } catch (RemoteException e) {
2136 throw e.rethrowAsRuntimeException();
Jeff Sharkey31d0b702016-11-21 14:16:53 -07002137 }
2138 }
2139
Jin Qiana85b9912017-10-17 15:48:18 -07002140 void runIdleMaint(Runnable callback) {
2141 enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);
2142
2143 try {
2144 mVold.runIdleMaint(new IVoldTaskListener.Stub() {
2145 @Override
2146 public void onStatus(int status, PersistableBundle extras) {
2147 // Not currently used
2148 }
2149 @Override
2150 public void onFinished(int status, PersistableBundle extras) {
2151 if (callback != null) {
2152 BackgroundThread.getHandler().post(callback);
2153 }
2154 }
2155 });
2156 } catch (Exception e) {
2157 Slog.wtf(TAG, e);
2158 }
2159 }
2160
2161 @Override
2162 public void runIdleMaintenance() {
2163 runIdleMaint(null);
2164 }
2165
2166 void abortIdleMaint(Runnable callback) {
2167 enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);
2168
2169 try {
2170 mVold.abortIdleMaint(new IVoldTaskListener.Stub() {
2171 @Override
2172 public void onStatus(int status, PersistableBundle extras) {
2173 // Not currently used
2174 }
2175 @Override
2176 public void onFinished(int status, PersistableBundle extras) {
2177 if (callback != null) {
2178 BackgroundThread.getHandler().post(callback);
2179 }
2180 }
2181 });
2182 } catch (Exception e) {
2183 Slog.wtf(TAG, e);
2184 }
2185 }
2186
2187 @Override
2188 public void abortIdleMaintenance() {
2189 abortIdleMaint(null);
2190 }
2191
Svet Ganov6ee871e2015-07-10 14:29:33 -07002192 private void remountUidExternalStorage(int uid, int mode) {
Jeff Sharkey9527b222015-06-24 15:24:48 -07002193 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002194 mVold.remountUid(uid, mode);
Jeff Sharkeyace874b2017-09-07 15:27:33 -06002195 } catch (Exception e) {
2196 Slog.wtf(TAG, e);
Jeff Sharkey9527b222015-06-24 15:24:48 -07002197 }
2198 }
2199
2200 @Override
Jeff Sharkey4c099d02015-05-15 13:45:00 -07002201 public void setDebugFlags(int flags, int mask) {
2202 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
Jeff Sharkey4c099d02015-05-15 13:45:00 -07002203
Jeff Sharkeyba512352015-11-12 20:17:45 -08002204 if ((mask & StorageManager.DEBUG_EMULATE_FBE) != 0) {
Jeff Sharkey00455bf2016-11-04 14:45:24 -06002205 if (!EMULATE_FBE_SUPPORTED) {
2206 throw new IllegalStateException(
2207 "Emulation not supported on this device");
2208 }
Paul Lawrence20be5d62016-02-26 13:51:17 -08002209 if (StorageManager.isFileEncryptedNativeOnly()) {
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07002210 throw new IllegalStateException(
Jeff Sharkey00455bf2016-11-04 14:45:24 -06002211 "Emulation not supported on device with native FBE");
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07002212 }
Jeff Sharkey5a785162016-03-21 13:02:06 -06002213 if (mLockPatternUtils.isCredentialRequiredToDecrypt(false)) {
2214 throw new IllegalStateException(
2215 "Emulation requires disabling 'Secure start-up' in Settings > Security");
2216 }
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07002217
Jeff Sharkey1176e512016-02-29 17:01:26 -07002218 final long token = Binder.clearCallingIdentity();
2219 try {
2220 final boolean emulateFbe = (flags & StorageManager.DEBUG_EMULATE_FBE) != 0;
2221 SystemProperties.set(StorageManager.PROP_EMULATE_FBE, Boolean.toString(emulateFbe));
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07002222
Jeff Sharkey1176e512016-02-29 17:01:26 -07002223 // Perform hard reboot to kick policy into place
2224 mContext.getSystemService(PowerManager.class).reboot(null);
2225 } finally {
2226 Binder.restoreCallingIdentity(token);
2227 }
Jeff Sharkeyba512352015-11-12 20:17:45 -08002228 }
Jeff Sharkey4c099d02015-05-15 13:45:00 -07002229
Jeff Sharkey901c0422018-04-20 13:11:20 -06002230 if ((mask & (StorageManager.DEBUG_ADOPTABLE_FORCE_ON
2231 | StorageManager.DEBUG_ADOPTABLE_FORCE_OFF)) != 0) {
2232 final String value;
2233 if ((flags & StorageManager.DEBUG_ADOPTABLE_FORCE_ON) != 0) {
2234 value = "force_on";
2235 } else if ((flags & StorageManager.DEBUG_ADOPTABLE_FORCE_OFF) != 0) {
2236 value = "force_off";
2237 } else {
2238 value = "";
2239 }
Jeff Sharkeyba512352015-11-12 20:17:45 -08002240
Jeff Sharkey901c0422018-04-20 13:11:20 -06002241 final long token = Binder.clearCallingIdentity();
2242 try {
2243 SystemProperties.set(StorageManager.PROP_ADOPTABLE, value);
2244
2245 // Reset storage to kick new setting into place
Jeff Sharkeyba512352015-11-12 20:17:45 -08002246 mHandler.obtainMessage(H_RESET).sendToTarget();
Jeff Sharkey901c0422018-04-20 13:11:20 -06002247 } finally {
2248 Binder.restoreCallingIdentity(token);
Jeff Sharkeyba512352015-11-12 20:17:45 -08002249 }
Jeff Sharkey4c099d02015-05-15 13:45:00 -07002250 }
Jeff Sharkey33dd1562016-04-07 11:05:33 -06002251
2252 if ((mask & (StorageManager.DEBUG_SDCARDFS_FORCE_ON
2253 | StorageManager.DEBUG_SDCARDFS_FORCE_OFF)) != 0) {
2254 final String value;
2255 if ((flags & StorageManager.DEBUG_SDCARDFS_FORCE_ON) != 0) {
2256 value = "force_on";
2257 } else if ((flags & StorageManager.DEBUG_SDCARDFS_FORCE_OFF) != 0) {
2258 value = "force_off";
2259 } else {
2260 value = "";
2261 }
2262
2263 final long token = Binder.clearCallingIdentity();
2264 try {
2265 SystemProperties.set(StorageManager.PROP_SDCARDFS, value);
2266
2267 // Reset storage to kick new setting into place
2268 mHandler.obtainMessage(H_RESET).sendToTarget();
2269 } finally {
2270 Binder.restoreCallingIdentity(token);
2271 }
2272 }
Jeff Sharkeye53e2d92017-03-25 23:14:06 -06002273
2274 if ((mask & StorageManager.DEBUG_VIRTUAL_DISK) != 0) {
2275 final boolean enabled = (flags & StorageManager.DEBUG_VIRTUAL_DISK) != 0;
2276
2277 final long token = Binder.clearCallingIdentity();
2278 try {
2279 SystemProperties.set(StorageManager.PROP_VIRTUAL_DISK, Boolean.toString(enabled));
2280
2281 // Reset storage to kick new setting into place
2282 mHandler.obtainMessage(H_RESET).sendToTarget();
2283 } finally {
2284 Binder.restoreCallingIdentity(token);
2285 }
2286 }
Sudheer Shankabe0febe2018-11-07 18:24:37 -08002287
Jeff Sharkeyb0c363b22018-12-15 11:53:03 -07002288 if ((mask & (StorageManager.DEBUG_ISOLATED_STORAGE_FORCE_ON
2289 | StorageManager.DEBUG_ISOLATED_STORAGE_FORCE_OFF)) != 0) {
2290 final int value;
2291 if ((flags & StorageManager.DEBUG_ISOLATED_STORAGE_FORCE_ON) != 0) {
2292 value = 1;
2293 } else if ((flags & StorageManager.DEBUG_ISOLATED_STORAGE_FORCE_OFF) != 0) {
2294 value = -1;
2295 } else {
2296 value = 0;
2297 }
Sudheer Shankabe0febe2018-11-07 18:24:37 -08002298
2299 final long token = Binder.clearCallingIdentity();
2300 try {
Jeff Sharkeyb0c363b22018-12-15 11:53:03 -07002301 Settings.Global.putInt(mContext.getContentResolver(),
2302 Settings.Global.ISOLATED_STORAGE_LOCAL, value);
2303 refreshIsolatedStorageSettings();
Sudheer Shankabe0febe2018-11-07 18:24:37 -08002304
2305 // Perform hard reboot to kick policy into place
2306 mContext.getSystemService(PowerManager.class).reboot(null);
2307 } finally {
2308 Binder.restoreCallingIdentity(token);
2309 }
2310 }
Jeff Sharkey4c099d02015-05-15 13:45:00 -07002311 }
2312
2313 @Override
Jeff Sharkey275e3e42015-04-24 16:10:32 -07002314 public String getPrimaryStorageUuid() {
Jeff Sharkey620b32b2015-04-23 19:36:02 -07002315 synchronized (mLock) {
2316 return mPrimaryStorageUuid;
2317 }
2318 }
2319
2320 @Override
Jeff Sharkey275e3e42015-04-24 16:10:32 -07002321 public void setPrimaryStorageUuid(String volumeUuid, IPackageMoveObserver callback) {
2322 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
Jeff Sharkey620b32b2015-04-23 19:36:02 -07002323
Jeff Sharkeya31460c2016-06-22 09:04:33 -06002324 final VolumeInfo from;
2325 final VolumeInfo to;
2326
Jeff Sharkey275e3e42015-04-24 16:10:32 -07002327 synchronized (mLock) {
Jeff Sharkeyfced5342015-05-10 14:53:34 -07002328 if (Objects.equals(mPrimaryStorageUuid, volumeUuid)) {
2329 throw new IllegalArgumentException("Primary storage already at " + volumeUuid);
Jeff Sharkey275e3e42015-04-24 16:10:32 -07002330 }
2331
2332 if (mMoveCallback != null) {
2333 throw new IllegalStateException("Move already in progress");
2334 }
2335 mMoveCallback = callback;
2336 mMoveTargetUuid = volumeUuid;
2337
Jeff Sharkeya65e6492017-06-21 13:45:11 -06002338 // We need all the users unlocked to move their primary storage
2339 final List<UserInfo> users = mContext.getSystemService(UserManager.class).getUsers();
2340 for (UserInfo user : users) {
2341 if (StorageManager.isFileEncryptedNativeOrEmulated()
2342 && !isUserKeyUnlocked(user.id)) {
2343 Slog.w(TAG, "Failing move due to locked user " + user.id);
2344 onMoveStatusLocked(PackageManager.MOVE_FAILED_LOCKED_USER);
2345 return;
2346 }
2347 }
2348
Jeff Sharkeyfced5342015-05-10 14:53:34 -07002349 // When moving to/from primary physical volume, we probably just nuked
2350 // the current storage location, so we have nothing to move.
2351 if (Objects.equals(StorageManager.UUID_PRIMARY_PHYSICAL, mPrimaryStorageUuid)
2352 || Objects.equals(StorageManager.UUID_PRIMARY_PHYSICAL, volumeUuid)) {
2353 Slog.d(TAG, "Skipping move to/from primary physical");
2354 onMoveStatusLocked(MOVE_STATUS_COPY_FINISHED);
2355 onMoveStatusLocked(PackageManager.MOVE_SUCCEEDED);
Jeff Sharkey5a9bb742015-11-03 10:15:57 -08002356 mHandler.obtainMessage(H_RESET).sendToTarget();
Jeff Sharkeya31460c2016-06-22 09:04:33 -06002357 return;
Jeff Sharkeyfced5342015-05-10 14:53:34 -07002358
2359 } else {
Jeff Sharkeya31460c2016-06-22 09:04:33 -06002360 from = findStorageForUuid(mPrimaryStorageUuid);
2361 to = findStorageForUuid(volumeUuid);
Jeff Sharkeyef10ee02015-07-05 14:17:27 -07002362
2363 if (from == null) {
2364 Slog.w(TAG, "Failing move due to missing from volume " + mPrimaryStorageUuid);
2365 onMoveStatusLocked(PackageManager.MOVE_FAILED_INTERNAL_ERROR);
2366 return;
2367 } else if (to == null) {
2368 Slog.w(TAG, "Failing move due to missing to volume " + volumeUuid);
2369 onMoveStatusLocked(PackageManager.MOVE_FAILED_INTERNAL_ERROR);
2370 return;
2371 }
Jeff Sharkey275e3e42015-04-24 16:10:32 -07002372 }
Jeff Sharkey620b32b2015-04-23 19:36:02 -07002373 }
Jeff Sharkeya31460c2016-06-22 09:04:33 -06002374
2375 try {
Jeff Sharkeyb302c542017-09-15 12:57:59 -06002376 mVold.moveStorage(from.id, to.id, new IVoldTaskListener.Stub() {
2377 @Override
2378 public void onStatus(int status, PersistableBundle extras) {
2379 synchronized (mLock) {
2380 onMoveStatusLocked(status);
2381 }
2382 }
2383
2384 @Override
2385 public void onFinished(int status, PersistableBundle extras) {
2386 // Not currently used
2387 }
2388 });
Jeff Sharkeyace874b2017-09-07 15:27:33 -06002389 } catch (Exception e) {
2390 Slog.wtf(TAG, e);
Jeff Sharkeya31460c2016-06-22 09:04:33 -06002391 }
Jeff Sharkey620b32b2015-04-23 19:36:02 -07002392 }
2393
San Mehatb1043402010-02-05 08:26:50 -08002394 private void warnOnNotMounted() {
Jeff Sharkey48877892015-03-18 11:27:19 -07002395 synchronized (mLock) {
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07002396 for (int i = 0; i < mVolumes.size(); i++) {
2397 final VolumeInfo vol = mVolumes.valueAt(i);
Jeff Sharkey27de30d2015-04-18 16:20:27 -07002398 if (vol.isPrimary() && vol.isMountedWritable()) {
Jeff Sharkey48877892015-03-18 11:27:19 -07002399 // Cool beans, we have a mounted primary volume
2400 return;
2401 }
Jeff Sharkey32ee8312012-09-30 13:21:31 -07002402 }
San Mehatb1043402010-02-05 08:26:50 -08002403 }
Jeff Sharkey48877892015-03-18 11:27:19 -07002404
2405 Slog.w(TAG, "No primary storage mounted!");
San Mehatb1043402010-02-05 08:26:50 -08002406 }
2407
Kenny Roota02b8b02010-08-05 16:14:17 -07002408 private boolean isUidOwnerOfPackageOrSystem(String packageName, int callerUid) {
2409 if (callerUid == android.os.Process.SYSTEM_UID) {
2410 return true;
2411 }
2412
Kenny Root02c87302010-07-01 08:10:18 -07002413 if (packageName == null) {
2414 return false;
2415 }
2416
Jeff Sharkey5790af02018-08-13 17:42:54 -06002417 final int packageUid = mPmInternal.getPackageUid(packageName,
Jeff Sharkeycd654482016-01-08 17:42:11 -07002418 PackageManager.MATCH_DEBUG_TRIAGED_MISSING, UserHandle.getUserId(callerUid));
Kenny Root02c87302010-07-01 08:10:18 -07002419
2420 if (DEBUG_OBB) {
2421 Slog.d(TAG, "packageName = " + packageName + ", packageUid = " +
2422 packageUid + ", callerUid = " + callerUid);
2423 }
2424
2425 return callerUid == packageUid;
2426 }
2427
Jeff Sharkey54402792017-09-15 16:05:19 -06002428 @Override
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002429 public String getMountedObbPath(String rawPath) {
2430 Preconditions.checkNotNull(rawPath, "rawPath cannot be null");
Kenny Rootaf9d6672010-10-08 09:21:39 -07002431
Kenny Root02c87302010-07-01 08:10:18 -07002432 warnOnNotMounted();
2433
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002434 final ObbState state;
Rubin Xucd7a0142015-04-17 23:45:27 +01002435 synchronized (mObbMounts) {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002436 state = mObbPathToStateMap.get(rawPath);
2437 }
2438 if (state == null) {
2439 Slog.w(TAG, "Failed to find OBB mounted at " + rawPath);
2440 return null;
2441 }
2442
Jeff Sharkey54402792017-09-15 16:05:19 -06002443 return findVolumeByIdOrThrow(state.volId).getPath().getAbsolutePath();
Kenny Root02c87302010-07-01 08:10:18 -07002444 }
2445
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002446 @Override
2447 public boolean isObbMounted(String rawPath) {
2448 Preconditions.checkNotNull(rawPath, "rawPath cannot be null");
Kenny Rootaf9d6672010-10-08 09:21:39 -07002449 synchronized (mObbMounts) {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002450 return mObbPathToStateMap.containsKey(rawPath);
Kenny Rootaf9d6672010-10-08 09:21:39 -07002451 }
Kenny Root02c87302010-07-01 08:10:18 -07002452 }
2453
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002454 @Override
Sudheer Shanka25469aa2018-08-27 15:50:23 -07002455 public void mountObb(String rawPath, String canonicalPath, String key,
2456 IObbActionListener token, int nonce, ObbInfo obbInfo) {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002457 Preconditions.checkNotNull(rawPath, "rawPath cannot be null");
2458 Preconditions.checkNotNull(canonicalPath, "canonicalPath cannot be null");
2459 Preconditions.checkNotNull(token, "token cannot be null");
Sudheer Shanka25469aa2018-08-27 15:50:23 -07002460 Preconditions.checkNotNull(obbInfo, "obbIfno cannot be null");
Kenny Rootaf9d6672010-10-08 09:21:39 -07002461
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002462 final int callingUid = Binder.getCallingUid();
Jeff Sharkey41cd6812017-09-11 10:32:17 -06002463 final ObbState obbState = new ObbState(rawPath, canonicalPath,
2464 callingUid, token, nonce, null);
Sudheer Shanka25469aa2018-08-27 15:50:23 -07002465 final ObbAction action = new MountObbAction(obbState, key, callingUid, obbInfo);
Kenny Roota02b8b02010-08-05 16:14:17 -07002466 mObbActionHandler.sendMessage(mObbActionHandler.obtainMessage(OBB_RUN_ACTION, action));
2467
2468 if (DEBUG_OBB)
2469 Slog.i(TAG, "Send to OBB handler: " + action.toString());
Kenny Root02c87302010-07-01 08:10:18 -07002470 }
2471
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002472 @Override
2473 public void unmountObb(String rawPath, boolean force, IObbActionListener token, int nonce) {
2474 Preconditions.checkNotNull(rawPath, "rawPath cannot be null");
2475
2476 final ObbState existingState;
Rubin Xucd7a0142015-04-17 23:45:27 +01002477 synchronized (mObbMounts) {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002478 existingState = mObbPathToStateMap.get(rawPath);
Kenny Rootf1121dc2010-09-29 07:30:53 -07002479 }
2480
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002481 if (existingState != null) {
2482 // TODO: separate state object from request data
2483 final int callingUid = Binder.getCallingUid();
Jeff Sharkey41cd6812017-09-11 10:32:17 -06002484 final ObbState newState = new ObbState(rawPath, existingState.canonicalPath,
2485 callingUid, token, nonce, existingState.volId);
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002486 final ObbAction action = new UnmountObbAction(newState, force);
2487 mObbActionHandler.sendMessage(mObbActionHandler.obtainMessage(OBB_RUN_ACTION, action));
Kenny Root02c87302010-07-01 08:10:18 -07002488
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002489 if (DEBUG_OBB)
2490 Slog.i(TAG, "Send to OBB handler: " + action.toString());
2491 } else {
2492 Slog.w(TAG, "Unknown OBB mount at " + rawPath);
2493 }
Kenny Roota02b8b02010-08-05 16:14:17 -07002494 }
2495
Ben Komalo444eca22011-09-01 15:17:44 -07002496 @Override
2497 public int getEncryptionState() {
2498 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
2499 "no permission to access the crypt keeper");
2500
Ben Komalo444eca22011-09-01 15:17:44 -07002501 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002502 return mVold.fdeComplete();
2503 } catch (Exception e) {
2504 Slog.wtf(TAG, e);
Sudheer Shankaf7341142016-10-18 17:15:18 -07002505 return StorageManager.ENCRYPTION_STATE_ERROR_UNKNOWN;
Ben Komalo444eca22011-09-01 15:17:44 -07002506 }
2507 }
2508
2509 @Override
Jason parks5af0b912010-11-29 09:05:25 -06002510 public int decryptStorage(String password) {
Jason parks8888c592011-01-20 22:46:41 -06002511 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
2512 "no permission to access the crypt keeper");
Jason parks5af0b912010-11-29 09:05:25 -06002513
Jeff Sharkey8058fe62017-09-13 11:50:33 -06002514 if (TextUtils.isEmpty(password)) {
2515 throw new IllegalArgumentException("password cannot be empty");
2516 }
2517
Jason parks5af0b912010-11-29 09:05:25 -06002518 if (DEBUG_EVENTS) {
2519 Slog.i(TAG, "decrypting storage...");
2520 }
2521
2522 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002523 mVold.fdeCheckPassword(password);
2524 mHandler.postDelayed(() -> {
2525 try {
2526 mVold.fdeRestart();
2527 } catch (Exception e) {
2528 Slog.wtf(TAG, e);
2529 }
2530 }, DateUtils.SECOND_IN_MILLIS);
2531 return 0;
Paul Crowleyfc0b5192018-07-02 13:58:10 -07002532 } catch (ServiceSpecificException e) {
2533 Slog.e(TAG, "fdeCheckPassword failed", e);
2534 return e.errorCode;
Jeff Sharkey54402792017-09-15 16:05:19 -06002535 } catch (Exception e) {
2536 Slog.wtf(TAG, e);
2537 return StorageManager.ENCRYPTION_STATE_ERROR_UNKNOWN;
Jason parks5af0b912010-11-29 09:05:25 -06002538 }
Jason parks5af0b912010-11-29 09:05:25 -06002539 }
2540
Jeff Sharkey54402792017-09-15 16:05:19 -06002541 @Override
Paul Lawrence46791e72014-04-03 09:10:26 -07002542 public int encryptStorage(int type, String password) {
Jason parks8888c592011-01-20 22:46:41 -06002543 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
2544 "no permission to access the crypt keeper");
Jason parks56aa5322011-01-07 09:01:15 -06002545
Jeff Sharkey8058fe62017-09-13 11:50:33 -06002546 if (type == StorageManager.CRYPT_TYPE_DEFAULT) {
2547 password = "";
2548 } else if (TextUtils.isEmpty(password)) {
2549 throw new IllegalArgumentException("password cannot be empty");
2550 }
2551
Jason parks56aa5322011-01-07 09:01:15 -06002552 if (DEBUG_EVENTS) {
Jason parks8888c592011-01-20 22:46:41 -06002553 Slog.i(TAG, "encrypting storage...");
Jason parks56aa5322011-01-07 09:01:15 -06002554 }
2555
2556 try {
Paul Lawrence89a0ae42017-12-22 10:11:10 -08002557 mVold.fdeEnable(type, password, 0);
Jeff Sharkey43e12112017-09-12 16:31:45 -06002558 } catch (Exception e) {
2559 Slog.wtf(TAG, e);
2560 return -1;
Jason parks56aa5322011-01-07 09:01:15 -06002561 }
2562
2563 return 0;
2564 }
2565
Paul Lawrence8e397362014-01-27 15:22:30 -08002566 /** Set the password for encrypting the master key.
2567 * @param type One of the CRYPTO_TYPE_XXX consts defined in StorageManager.
2568 * @param password The password to set.
2569 */
Jeff Sharkey54402792017-09-15 16:05:19 -06002570 @Override
Paul Lawrence8e397362014-01-27 15:22:30 -08002571 public int changeEncryptionPassword(int type, String password) {
Jason parksf7b3cd42011-01-27 09:28:25 -06002572 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
2573 "no permission to access the crypt keeper");
2574
Jeff Sharkeyae266462017-11-27 13:32:24 -07002575 if (StorageManager.isFileEncryptedNativeOnly()) {
2576 // Not supported on FBE devices
2577 return -1;
2578 }
2579
Jeff Sharkey8058fe62017-09-13 11:50:33 -06002580 if (type == StorageManager.CRYPT_TYPE_DEFAULT) {
2581 password = "";
2582 } else if (TextUtils.isEmpty(password)) {
2583 throw new IllegalArgumentException("password cannot be empty");
2584 }
2585
Jason parksf7b3cd42011-01-27 09:28:25 -06002586 if (DEBUG_EVENTS) {
2587 Slog.i(TAG, "changing encryption password...");
2588 }
2589
2590 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002591 mVold.fdeChangePassword(type, password);
2592 return 0;
2593 } catch (Exception e) {
2594 Slog.wtf(TAG, e);
2595 return -1;
Jason parksf7b3cd42011-01-27 09:28:25 -06002596 }
2597 }
2598
Christopher Tate32418be2011-10-10 13:51:12 -07002599 /**
2600 * Validate a user-supplied password string with cryptfs
2601 */
2602 @Override
2603 public int verifyEncryptionPassword(String password) throws RemoteException {
2604 // Only the system process is permitted to validate passwords
2605 if (Binder.getCallingUid() != android.os.Process.SYSTEM_UID) {
2606 throw new SecurityException("no permission to access the crypt keeper");
2607 }
2608
2609 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
2610 "no permission to access the crypt keeper");
2611
2612 if (TextUtils.isEmpty(password)) {
2613 throw new IllegalArgumentException("password cannot be empty");
2614 }
2615
Christopher Tate32418be2011-10-10 13:51:12 -07002616 if (DEBUG_EVENTS) {
2617 Slog.i(TAG, "validating encryption password...");
2618 }
2619
2620 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002621 mVold.fdeVerifyPassword(password);
2622 return 0;
2623 } catch (Exception e) {
2624 Slog.wtf(TAG, e);
2625 return -1;
Christopher Tate32418be2011-10-10 13:51:12 -07002626 }
2627 }
2628
Paul Lawrence8e397362014-01-27 15:22:30 -08002629 /**
2630 * Get the type of encryption used to encrypt the master key.
2631 * @return The type, one of the CRYPT_TYPE_XXX consts from StorageManager.
2632 */
2633 @Override
Svetoslav16e4a1a2014-09-29 18:16:20 -07002634 public int getPasswordType() {
Paul Lawrence76a40572017-03-15 11:08:04 -07002635 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
Paul Lawrence9de713d2016-05-02 22:45:33 +00002636 "no permission to access the crypt keeper");
2637
Paul Lawrence8e397362014-01-27 15:22:30 -08002638 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002639 return mVold.fdeGetPasswordType();
2640 } catch (Exception e) {
2641 Slog.wtf(TAG, e);
2642 return -1;
Paul Lawrence8e397362014-01-27 15:22:30 -08002643 }
2644 }
2645
Paul Lawrencee51dcf92014-03-18 10:56:00 -07002646 /**
2647 * Set a field in the crypto header.
2648 * @param field field to set
2649 * @param contents contents to set in field
2650 */
2651 @Override
2652 public void setField(String field, String contents) throws RemoteException {
Paul Lawrence76a40572017-03-15 11:08:04 -07002653 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
Paul Lawrence0bbd1082016-04-26 15:21:02 -07002654 "no permission to access the crypt keeper");
Paul Lawrencee51dcf92014-03-18 10:56:00 -07002655
Jeff Sharkeyae266462017-11-27 13:32:24 -07002656 if (StorageManager.isFileEncryptedNativeOnly()) {
2657 // Not supported on FBE devices
2658 return;
2659 }
2660
Paul Lawrencee51dcf92014-03-18 10:56:00 -07002661 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002662 mVold.fdeSetField(field, contents);
2663 return;
2664 } catch (Exception e) {
2665 Slog.wtf(TAG, e);
2666 return;
Paul Lawrencee51dcf92014-03-18 10:56:00 -07002667 }
2668 }
2669
2670 /**
2671 * Gets a field from the crypto header.
2672 * @param field field to get
2673 * @return contents of field
2674 */
2675 @Override
2676 public String getField(String field) throws RemoteException {
Paul Lawrence76a40572017-03-15 11:08:04 -07002677 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
Paul Lawrence0bbd1082016-04-26 15:21:02 -07002678 "no permission to access the crypt keeper");
Paul Lawrencee51dcf92014-03-18 10:56:00 -07002679
Jeff Sharkeyae266462017-11-27 13:32:24 -07002680 if (StorageManager.isFileEncryptedNativeOnly()) {
2681 // Not supported on FBE devices
2682 return null;
2683 }
2684
Paul Lawrencee51dcf92014-03-18 10:56:00 -07002685 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002686 return mVold.fdeGetField(field);
2687 } catch (Exception e) {
2688 Slog.wtf(TAG, e);
2689 return null;
Paul Lawrencee51dcf92014-03-18 10:56:00 -07002690 }
2691 }
2692
Paul Lawrence3806d9c2015-10-29 10:30:46 -07002693 /**
2694 * Is userdata convertible to file based encryption?
2695 * @return non zero for convertible
2696 */
2697 @Override
2698 public boolean isConvertibleToFBE() throws RemoteException {
Paul Lawrence76a40572017-03-15 11:08:04 -07002699 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
Paul Lawrence0bbd1082016-04-26 15:21:02 -07002700 "no permission to access the crypt keeper");
Paul Lawrence3806d9c2015-10-29 10:30:46 -07002701
Paul Lawrence3806d9c2015-10-29 10:30:46 -07002702 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002703 return mVold.isConvertibleToFbe();
2704 } catch (Exception e) {
2705 Slog.wtf(TAG, e);
2706 return false;
Paul Lawrence3806d9c2015-10-29 10:30:46 -07002707 }
2708 }
2709
Daniel Rosenberge129e5c2018-11-07 19:25:55 -08002710 /**
2711 * Signal that checkpointing partitions should commit changes
2712 */
2713 @Override
2714 public void commitChanges() throws RemoteException {
2715 // Only the system process is permitted to commit checkpoints
2716 if (Binder.getCallingUid() != android.os.Process.SYSTEM_UID) {
2717 throw new SecurityException("no permission to commit checkpoint changes");
2718 }
2719
2720 mVold.commitChanges();
2721 }
2722
Jeff Sharkeyb049e212012-09-07 23:16:01 -07002723 @Override
Paul Lawrence945490c2014-03-27 16:37:28 +00002724 public String getPassword() throws RemoteException {
Paul Lawrence76a40572017-03-15 11:08:04 -07002725 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
Rubin Xucd7a0142015-04-17 23:45:27 +01002726 "only keyguard can retrieve password");
Paul Lawrence0bbd1082016-04-26 15:21:02 -07002727
Paul Lawrence945490c2014-03-27 16:37:28 +00002728 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002729 return mVold.fdeGetPassword();
2730 } catch (Exception e) {
2731 Slog.wtf(TAG, e);
Paul Lawrence24063b52015-01-06 13:11:23 -08002732 return null;
Paul Lawrence945490c2014-03-27 16:37:28 +00002733 }
2734 }
2735
2736 @Override
2737 public void clearPassword() throws RemoteException {
Paul Lawrence76a40572017-03-15 11:08:04 -07002738 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
Paul Lawrence0bbd1082016-04-26 15:21:02 -07002739 "only keyguard can clear password");
2740
Paul Lawrence945490c2014-03-27 16:37:28 +00002741 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002742 mVold.fdeClearPassword();
2743 return;
2744 } catch (Exception e) {
2745 Slog.wtf(TAG, e);
2746 return;
Paul Lawrence945490c2014-03-27 16:37:28 +00002747 }
2748 }
2749
2750 @Override
Lenka Trochtovac4dd0212015-11-18 12:22:06 +01002751 public void createUserKey(int userId, int serialNumber, boolean ephemeral) {
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002752 enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
Paul Crowleybcf48ed2015-04-22 13:36:59 +01002753
Paul Crowleybcf48ed2015-04-22 13:36:59 +01002754 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002755 mVold.createUserKey(userId, serialNumber, ephemeral);
Jeff Sharkey43e12112017-09-12 16:31:45 -06002756 } catch (Exception e) {
2757 Slog.wtf(TAG, e);
Paul Crowleybcf48ed2015-04-22 13:36:59 +01002758 }
2759 }
2760
Paul Crowley7ec733f2015-05-19 12:42:00 +01002761 @Override
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002762 public void destroyUserKey(int userId) {
2763 enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
Paul Crowley7ec733f2015-05-19 12:42:00 +01002764
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002765 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002766 mVold.destroyUserKey(userId);
Jeff Sharkey43e12112017-09-12 16:31:45 -06002767 } catch (Exception e) {
2768 Slog.wtf(TAG, e);
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002769 }
2770 }
2771
Jeff Sharkey43e12112017-09-12 16:31:45 -06002772 private String encodeBytes(byte[] bytes) {
Paul Crowleyfaeb3eb2016-02-08 15:58:29 +00002773 if (ArrayUtils.isEmpty(bytes)) {
Jeff Sharkey43e12112017-09-12 16:31:45 -06002774 return "!";
Paul Crowleyfaeb3eb2016-02-08 15:58:29 +00002775 } else {
Jeff Sharkey43e12112017-09-12 16:31:45 -06002776 return HexDump.toHexString(bytes);
Paul Crowleyfaeb3eb2016-02-08 15:58:29 +00002777 }
2778 }
2779
Paul Crowleycc701552016-05-17 14:18:49 -07002780 /*
2781 * Add this token/secret pair to the set of ways we can recover a disk encryption key.
2782 * Changing the token/secret for a disk encryption key is done in two phases: first, adding
2783 * a new token/secret pair with this call, then delting all other pairs with
2784 * fixateNewestUserKeyAuth. This allows other places where a credential is used, such as
2785 * Gatekeeper, to be updated between the two calls.
2786 */
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002787 @Override
Paul Crowleycc701552016-05-17 14:18:49 -07002788 public void addUserKeyAuth(int userId, int serialNumber, byte[] token, byte[] secret) {
Paul Crowleyfaeb3eb2016-02-08 15:58:29 +00002789 enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
Paul Crowleyfaeb3eb2016-02-08 15:58:29 +00002790
2791 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002792 mVold.addUserKeyAuth(userId, serialNumber, encodeBytes(token), encodeBytes(secret));
Jeff Sharkey43e12112017-09-12 16:31:45 -06002793 } catch (Exception e) {
2794 Slog.wtf(TAG, e);
Paul Crowleycc701552016-05-17 14:18:49 -07002795 }
2796 }
2797
2798 /*
2799 * Delete all disk encryption token/secret pairs except the most recently added one
2800 */
2801 @Override
2802 public void fixateNewestUserKeyAuth(int userId) {
2803 enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
Paul Crowleycc701552016-05-17 14:18:49 -07002804
2805 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002806 mVold.fixateNewestUserKeyAuth(userId);
Jeff Sharkey43e12112017-09-12 16:31:45 -06002807 } catch (Exception e) {
2808 Slog.wtf(TAG, e);
Paul Crowleyfaeb3eb2016-02-08 15:58:29 +00002809 }
2810 }
2811
2812 @Override
2813 public void unlockUserKey(int userId, int serialNumber, byte[] token, byte[] secret) {
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002814 enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002815
Jeff Sharkeyce18c812016-04-27 16:00:41 -06002816 if (StorageManager.isFileEncryptedNativeOrEmulated()) {
Rubin Xu3bf722a2016-12-15 16:07:38 +00002817 // When a user has secure lock screen, require secret to actually unlock.
2818 // This check is mostly in place for emulation mode.
2819 if (mLockPatternUtils.isSecure(userId) && ArrayUtils.isEmpty(secret)) {
2820 throw new IllegalStateException("Secret required to unlock secure user " + userId);
Jeff Sharkeyce18c812016-04-27 16:00:41 -06002821 }
Jeff Sharkeyb9fe5372015-12-03 15:23:08 -07002822
Jeff Sharkeyce18c812016-04-27 16:00:41 -06002823 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002824 mVold.unlockUserKey(userId, serialNumber, encodeBytes(token),
2825 encodeBytes(secret));
Jeff Sharkey43e12112017-09-12 16:31:45 -06002826 } catch (Exception e) {
2827 Slog.wtf(TAG, e);
2828 return;
Jeff Sharkeyce18c812016-04-27 16:00:41 -06002829 }
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002830 }
2831
2832 synchronized (mLock) {
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07002833 mLocalUnlockedUsers = ArrayUtils.appendInt(mLocalUnlockedUsers, userId);
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002834 }
2835 }
2836
2837 @Override
2838 public void lockUserKey(int userId) {
2839 enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002840
2841 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002842 mVold.lockUserKey(userId);
Jeff Sharkey43e12112017-09-12 16:31:45 -06002843 } catch (Exception e) {
2844 Slog.wtf(TAG, e);
2845 return;
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002846 }
2847
2848 synchronized (mLock) {
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07002849 mLocalUnlockedUsers = ArrayUtils.removeInt(mLocalUnlockedUsers, userId);
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002850 }
2851 }
2852
2853 @Override
2854 public boolean isUserKeyUnlocked(int userId) {
Jeff Sharkeyce18c812016-04-27 16:00:41 -06002855 synchronized (mLock) {
2856 return ArrayUtils.contains(mLocalUnlockedUsers, userId);
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002857 }
2858 }
2859
2860 @Override
Jeff Sharkey47f71082016-02-01 17:03:54 -07002861 public void prepareUserStorage(String volumeUuid, int userId, int serialNumber, int flags) {
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002862 enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002863
2864 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002865 mVold.prepareUserStorage(volumeUuid, userId, serialNumber, flags);
Jeff Sharkey43e12112017-09-12 16:31:45 -06002866 } catch (Exception e) {
2867 Slog.wtf(TAG, e);
Paul Crowley7ec733f2015-05-19 12:42:00 +01002868 }
2869 }
2870
Paul Crowleybcf48ed2015-04-22 13:36:59 +01002871 @Override
Jeff Sharkeyfcf1e552016-04-14 20:44:58 -06002872 public void destroyUserStorage(String volumeUuid, int userId, int flags) {
2873 enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
Jeff Sharkeyfcf1e552016-04-14 20:44:58 -06002874
2875 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002876 mVold.destroyUserStorage(volumeUuid, userId, flags);
Jeff Sharkey43e12112017-09-12 16:31:45 -06002877 } catch (Exception e) {
2878 Slog.wtf(TAG, e);
Jeff Sharkeyfcf1e552016-04-14 20:44:58 -06002879 }
2880 }
2881
Daichi Hironoe56740d2017-02-02 13:56:45 +09002882 class AppFuseMountScope extends AppFuseBridge.MountScope {
Daichi Hirono812c95d2017-02-08 16:20:20 +09002883 boolean opened = false;
2884
Ryo Hashimoto38bcbf02018-05-16 18:20:37 +09002885 public AppFuseMountScope(int uid, int mountId) {
2886 super(uid, mountId);
Daichi Hirono812c95d2017-02-08 16:20:20 +09002887 }
2888
2889 @Override
2890 public ParcelFileDescriptor open() throws NativeDaemonConnectorException {
Jeff Sharkey54402792017-09-15 16:05:19 -06002891 try {
2892 return new ParcelFileDescriptor(
Ryo Hashimoto38bcbf02018-05-16 18:20:37 +09002893 mVold.mountAppFuse(uid, mountId));
Jeff Sharkey54402792017-09-15 16:05:19 -06002894 } catch (Exception e) {
2895 throw new NativeDaemonConnectorException("Failed to mount", e);
Daichi Hirono812c95d2017-02-08 16:20:20 +09002896 }
Daichi Hirono9fb00182016-11-08 14:12:17 +09002897 }
2898
2899 @Override
Ryo Hashimoto38bcbf02018-05-16 18:20:37 +09002900 public ParcelFileDescriptor openFile(int mountId, int fileId, int flags)
2901 throws NativeDaemonConnectorException {
2902 try {
2903 return new ParcelFileDescriptor(
2904 mVold.openAppFuseFile(uid, mountId, fileId, flags));
2905 } catch (Exception e) {
2906 throw new NativeDaemonConnectorException("Failed to open", e);
2907 }
2908 }
2909
2910 @Override
Daichi Hironoe56740d2017-02-02 13:56:45 +09002911 public void close() throws Exception {
Daichi Hirono812c95d2017-02-08 16:20:20 +09002912 if (opened) {
Ryo Hashimoto38bcbf02018-05-16 18:20:37 +09002913 mVold.unmountAppFuse(uid, mountId);
Daichi Hirono812c95d2017-02-08 16:20:20 +09002914 opened = false;
2915 }
Daichi Hirono9fb00182016-11-08 14:12:17 +09002916 }
2917 }
2918
2919 @Override
Daichi Hirono812c95d2017-02-08 16:20:20 +09002920 public @Nullable AppFuseMount mountProxyFileDescriptorBridge() {
Daichi Hironoe56740d2017-02-02 13:56:45 +09002921 Slog.v(TAG, "mountProxyFileDescriptorBridge");
Daichi Hirono9fb00182016-11-08 14:12:17 +09002922 final int uid = Binder.getCallingUid();
Daichi Hirono9fb00182016-11-08 14:12:17 +09002923
Daichi Hironoe56740d2017-02-02 13:56:45 +09002924 while (true) {
2925 synchronized (mAppFuseLock) {
2926 boolean newlyCreated = false;
2927 if (mAppFuseBridge == null) {
2928 mAppFuseBridge = new AppFuseBridge();
2929 new Thread(mAppFuseBridge, AppFuseBridge.TAG).start();
2930 newlyCreated = true;
Daichi Hirono9fb00182016-11-08 14:12:17 +09002931 }
Daichi Hironoe56740d2017-02-02 13:56:45 +09002932 try {
2933 final int name = mNextAppFuseName++;
2934 try {
2935 return new AppFuseMount(
Ryo Hashimoto38bcbf02018-05-16 18:20:37 +09002936 name, mAppFuseBridge.addBridge(new AppFuseMountScope(uid, name)));
Daichi Hirono812c95d2017-02-08 16:20:20 +09002937 } catch (FuseUnavailableMountException e) {
Daichi Hironoe56740d2017-02-02 13:56:45 +09002938 if (newlyCreated) {
2939 // If newly created bridge fails, it's a real error.
Daichi Hirono812c95d2017-02-08 16:20:20 +09002940 Slog.e(TAG, "", e);
2941 return null;
Daichi Hironoe56740d2017-02-02 13:56:45 +09002942 }
2943 // It seems the thread of mAppFuseBridge has already been terminated.
2944 mAppFuseBridge = null;
2945 }
2946 } catch (NativeDaemonConnectorException e) {
2947 throw e.rethrowAsParcelableException();
2948 }
Daichi Hirono9fb00182016-11-08 14:12:17 +09002949 }
Daichi Hirono9fb00182016-11-08 14:12:17 +09002950 }
2951 }
2952
2953 @Override
Daichi Hirono812c95d2017-02-08 16:20:20 +09002954 public @Nullable ParcelFileDescriptor openProxyFileDescriptor(
2955 int mountId, int fileId, int mode) {
2956 Slog.v(TAG, "mountProxyFileDescriptor");
Jeff Sharkey39466322018-12-05 19:19:52 -07002957
2958 // We only support a narrow set of incoming mode flags
Jeff Sharkey3b1c2542018-12-13 15:01:38 -07002959 mode &= MODE_READ_WRITE;
Jeff Sharkey39466322018-12-05 19:19:52 -07002960
Daichi Hirono9fb00182016-11-08 14:12:17 +09002961 try {
2962 synchronized (mAppFuseLock) {
Daichi Hironoe56740d2017-02-02 13:56:45 +09002963 if (mAppFuseBridge == null) {
Daichi Hirono812c95d2017-02-08 16:20:20 +09002964 Slog.e(TAG, "FuseBridge has not been created");
2965 return null;
Daichi Hirono9fb00182016-11-08 14:12:17 +09002966 }
Ryo Hashimoto38bcbf02018-05-16 18:20:37 +09002967 return mAppFuseBridge.openFile(mountId, fileId, mode);
Daichi Hirono9fb00182016-11-08 14:12:17 +09002968 }
Daichi Hirono812c95d2017-02-08 16:20:20 +09002969 } catch (FuseUnavailableMountException | InterruptedException error) {
2970 Slog.v(TAG, "The mount point has already been invalid", error);
2971 return null;
Daichi Hirono9fb00182016-11-08 14:12:17 +09002972 }
2973 }
2974
Daichi Hirono9e8d9e22015-11-13 14:37:00 +09002975 @Override
Jeff Sharkeyae266462017-11-27 13:32:24 -07002976 public void mkdirs(String callingPkg, String appPath) {
Jeff Sharkey2d8b4e82013-09-17 17:30:33 -07002977 final int userId = UserHandle.getUserId(Binder.getCallingUid());
2978 final UserEnvironment userEnv = new UserEnvironment(userId);
Farid Zare Seisanac094512018-04-02 15:06:13 -07002979 final String propertyName = "sys.user." + userId + ".ce_available";
Jeff Sharkey2d8b4e82013-09-17 17:30:33 -07002980
Jeff Sharkey196c7552018-03-26 15:56:50 -06002981 // Ignore requests to create directories while storage is locked
Farid Zare Seisanac094512018-04-02 15:06:13 -07002982 if (!isUserKeyUnlocked(userId)) {
2983 throw new IllegalStateException("Failed to prepare " + appPath);
2984 }
2985
2986 // Ignore requests to create directories if CE storage is not available
Farid Zare Seisan7f6b8122018-03-30 11:19:10 -07002987 if ((userId == UserHandle.USER_SYSTEM)
2988 && !SystemProperties.getBoolean(propertyName, false)) {
Farid Zare Seisanac094512018-04-02 15:06:13 -07002989 throw new IllegalStateException("Failed to prepare " + appPath);
2990 }
Jeff Sharkey196c7552018-03-26 15:56:50 -06002991
Jeff Sharkey2d8b4e82013-09-17 17:30:33 -07002992 // Validate that reported package name belongs to caller
2993 final AppOpsManager appOps = (AppOpsManager) mContext.getSystemService(
2994 Context.APP_OPS_SERVICE);
2995 appOps.checkPackage(Binder.getCallingUid(), callingPkg);
2996
Jeff Sharkey48877892015-03-18 11:27:19 -07002997 File appFile = null;
Jeff Sharkey2d8b4e82013-09-17 17:30:33 -07002998 try {
Jeff Sharkey48877892015-03-18 11:27:19 -07002999 appFile = new File(appPath).getCanonicalFile();
Jeff Sharkey2d8b4e82013-09-17 17:30:33 -07003000 } catch (IOException e) {
Jeff Sharkeyae266462017-11-27 13:32:24 -07003001 throw new IllegalStateException("Failed to resolve " + appPath + ": " + e);
Jeff Sharkey2d8b4e82013-09-17 17:30:33 -07003002 }
3003
3004 // Try translating the app path into a vold path, but require that it
3005 // belong to the calling package.
Jeff Sharkey48877892015-03-18 11:27:19 -07003006 if (FileUtils.contains(userEnv.buildExternalStorageAppDataDirs(callingPkg), appFile) ||
3007 FileUtils.contains(userEnv.buildExternalStorageAppObbDirs(callingPkg), appFile) ||
3008 FileUtils.contains(userEnv.buildExternalStorageAppMediaDirs(callingPkg), appFile)) {
3009 appPath = appFile.getAbsolutePath();
3010 if (!appPath.endsWith("/")) {
3011 appPath = appPath + "/";
3012 }
3013
Jeff Sharkey2d8b4e82013-09-17 17:30:33 -07003014 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06003015 mVold.mkdirs(appPath);
Jeff Sharkey27a108c2017-11-30 17:11:40 -07003016 return;
Jeff Sharkeyace874b2017-09-07 15:27:33 -06003017 } catch (Exception e) {
Jeff Sharkeyae266462017-11-27 13:32:24 -07003018 throw new IllegalStateException("Failed to prepare " + appPath + ": " + e);
Jeff Sharkey2d8b4e82013-09-17 17:30:33 -07003019 }
3020 }
3021
Jeff Sharkey48877892015-03-18 11:27:19 -07003022 throw new SecurityException("Invalid mkdirs path: " + appFile);
Jeff Sharkey2d8b4e82013-09-17 17:30:33 -07003023 }
3024
3025 @Override
Jeff Sharkey46349872015-07-28 10:49:47 -07003026 public StorageVolume[] getVolumeList(int uid, String packageName, int flags) {
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07003027 final int userId = UserHandle.getUserId(uid);
Jeff Sharkeyc02bfae2016-03-27 15:06:53 -06003028
Jeff Sharkey46349872015-07-28 10:49:47 -07003029 final boolean forWrite = (flags & StorageManager.FLAG_FOR_WRITE) != 0;
Jeff Sharkeyc02bfae2016-03-27 15:06:53 -06003030 final boolean realState = (flags & StorageManager.FLAG_REAL_STATE) != 0;
3031 final boolean includeInvisible = (flags & StorageManager.FLAG_INCLUDE_INVISIBLE) != 0;
Jeff Sharkey46349872015-07-28 10:49:47 -07003032
Jeff Sharkeyc02bfae2016-03-27 15:06:53 -06003033 final boolean userKeyUnlocked;
3034 final boolean storagePermission;
3035 final long token = Binder.clearCallingIdentity();
Svetoslav38c3dbb2015-07-14 11:27:06 -07003036 try {
Jeff Sharkeyc02bfae2016-03-27 15:06:53 -06003037 userKeyUnlocked = isUserKeyUnlocked(userId);
Sudheer Shanka2250d562016-11-07 15:41:02 -08003038 storagePermission = mStorageManagerInternal.hasExternalStorage(uid, packageName);
Svetoslav38c3dbb2015-07-14 11:27:06 -07003039 } finally {
Jeff Sharkeyc02bfae2016-03-27 15:06:53 -06003040 Binder.restoreCallingIdentity(token);
Svetoslav38c3dbb2015-07-14 11:27:06 -07003041 }
Svet Ganov6ee871e2015-07-10 14:29:33 -07003042
Jeff Sharkeyc02bfae2016-03-27 15:06:53 -06003043 boolean foundPrimary = false;
3044
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07003045 final ArrayList<StorageVolume> res = new ArrayList<>();
Jeff Sharkey48877892015-03-18 11:27:19 -07003046 synchronized (mLock) {
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07003047 for (int i = 0; i < mVolumes.size(); i++) {
3048 final VolumeInfo vol = mVolumes.valueAt(i);
Jeff Sharkeyc02bfae2016-03-27 15:06:53 -06003049 switch (vol.getType()) {
3050 case VolumeInfo.TYPE_PUBLIC:
Risan05c41e62018-10-29 08:57:43 +09003051 case VolumeInfo.TYPE_STUB:
Jeff Sharkeyc02bfae2016-03-27 15:06:53 -06003052 case VolumeInfo.TYPE_EMULATED:
3053 break;
3054 default:
3055 continue;
3056 }
3057
3058 boolean match = false;
3059 if (forWrite) {
3060 match = vol.isVisibleForWrite(userId);
3061 } else {
Felipe Leme123a0e72016-06-10 11:09:11 -07003062 match = vol.isVisibleForRead(userId)
3063 || (includeInvisible && vol.getPath() != null);
Jeff Sharkeyc02bfae2016-03-27 15:06:53 -06003064 }
3065 if (!match) continue;
3066
3067 boolean reportUnmounted = false;
3068 if ((vol.getType() == VolumeInfo.TYPE_EMULATED) && !userKeyUnlocked) {
3069 reportUnmounted = true;
3070 } else if (!storagePermission && !realState) {
3071 reportUnmounted = true;
3072 }
3073
3074 final StorageVolume userVol = vol.buildStorageVolume(mContext, userId,
3075 reportUnmounted);
3076 if (vol.isPrimary()) {
3077 res.add(0, userVol);
3078 foundPrimary = true;
3079 } else {
3080 res.add(userVol);
Jeff Sharkeyb049e212012-09-07 23:16:01 -07003081 }
Mike Lockwood8fa5f802011-03-24 08:12:30 -07003082 }
Mike Lockwood8fa5f802011-03-24 08:12:30 -07003083 }
Jeff Sharkey48877892015-03-18 11:27:19 -07003084
3085 if (!foundPrimary) {
Jeff Sharkey11697f52018-12-13 10:14:42 -07003086 Slog.w(TAG, "No primary storage defined yet; hacking together a stub");
Jeff Sharkey48877892015-03-18 11:27:19 -07003087
3088 final boolean primaryPhysical = SystemProperties.getBoolean(
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07003089 StorageManager.PROP_PRIMARY_PHYSICAL, false);
Jeff Sharkey48877892015-03-18 11:27:19 -07003090
3091 final String id = "stub_primary";
3092 final File path = Environment.getLegacyExternalStorageDirectory();
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07003093 final String description = mContext.getString(android.R.string.unknownName);
Jeff Sharkey48877892015-03-18 11:27:19 -07003094 final boolean primary = true;
3095 final boolean removable = primaryPhysical;
3096 final boolean emulated = !primaryPhysical;
Jeff Sharkey48877892015-03-18 11:27:19 -07003097 final boolean allowMassStorage = false;
3098 final long maxFileSize = 0L;
3099 final UserHandle owner = new UserHandle(userId);
3100 final String uuid = null;
Jeff Sharkey48877892015-03-18 11:27:19 -07003101 final String state = Environment.MEDIA_REMOVED;
3102
Jerry Zhang71938e12018-05-10 18:28:29 -07003103 res.add(0, new StorageVolume(id, path, path,
Jerry Zhangf9c5c252017-08-16 18:07:51 -07003104 description, primary, removable, emulated,
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07003105 allowMassStorage, maxFileSize, owner, uuid, state));
Jeff Sharkey48877892015-03-18 11:27:19 -07003106 }
3107
3108 return res.toArray(new StorageVolume[res.size()]);
Mike Lockwood8fa5f802011-03-24 08:12:30 -07003109 }
3110
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07003111 @Override
3112 public DiskInfo[] getDisks() {
3113 synchronized (mLock) {
3114 final DiskInfo[] res = new DiskInfo[mDisks.size()];
3115 for (int i = 0; i < mDisks.size(); i++) {
3116 res[i] = mDisks.valueAt(i);
3117 }
3118 return res;
3119 }
3120 }
3121
3122 @Override
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07003123 public VolumeInfo[] getVolumes(int flags) {
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07003124 synchronized (mLock) {
3125 final VolumeInfo[] res = new VolumeInfo[mVolumes.size()];
3126 for (int i = 0; i < mVolumes.size(); i++) {
3127 res[i] = mVolumes.valueAt(i);
3128 }
3129 return res;
3130 }
3131 }
3132
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07003133 @Override
3134 public VolumeRecord[] getVolumeRecords(int flags) {
3135 synchronized (mLock) {
3136 final VolumeRecord[] res = new VolumeRecord[mRecords.size()];
3137 for (int i = 0; i < mRecords.size(); i++) {
3138 res[i] = mRecords.valueAt(i);
3139 }
3140 return res;
3141 }
3142 }
3143
Jeff Sharkey9bed0702017-01-23 20:37:05 -07003144 @Override
3145 public long getCacheQuotaBytes(String volumeUuid, int uid) {
3146 if (uid != Binder.getCallingUid()) {
3147 mContext.enforceCallingPermission(android.Manifest.permission.STORAGE_INTERNAL, TAG);
3148 }
Daniel Nishi80fdb012017-03-09 14:30:07 -08003149 final long token = Binder.clearCallingIdentity();
3150 final StorageStatsManager stats = mContext.getSystemService(StorageStatsManager.class);
3151 try {
3152 return stats.getCacheQuotaBytes(volumeUuid, uid);
3153 } finally {
3154 Binder.restoreCallingIdentity(token);
3155 }
Jeff Sharkey9bed0702017-01-23 20:37:05 -07003156 }
3157
3158 @Override
3159 public long getCacheSizeBytes(String volumeUuid, int uid) {
3160 if (uid != Binder.getCallingUid()) {
3161 mContext.enforceCallingPermission(android.Manifest.permission.STORAGE_INTERNAL, TAG);
3162 }
3163 final long token = Binder.clearCallingIdentity();
3164 try {
3165 return mContext.getSystemService(StorageStatsManager.class)
3166 .queryStatsForUid(volumeUuid, uid).getCacheBytes();
Jeff Sharkey789a8fc2017-04-16 13:18:35 -06003167 } catch (IOException e) {
3168 throw new ParcelableException(e);
Jeff Sharkey9bed0702017-01-23 20:37:05 -07003169 } finally {
3170 Binder.restoreCallingIdentity(token);
3171 }
3172 }
3173
Jeff Sharkey35e46d22017-06-09 10:01:20 -06003174 private int adjustAllocateFlags(int flags, int callingUid, String callingPackage) {
3175 // Require permission to allocate aggressively
3176 if ((flags & StorageManager.FLAG_ALLOCATE_AGGRESSIVE) != 0) {
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07003177 mContext.enforceCallingOrSelfPermission(
3178 android.Manifest.permission.ALLOCATE_AGGRESSIVE, TAG);
3179 }
3180
Jeff Sharkey35e46d22017-06-09 10:01:20 -06003181 // Apps normally can't directly defy reserved space
3182 flags &= ~StorageManager.FLAG_ALLOCATE_DEFY_ALL_RESERVED;
3183 flags &= ~StorageManager.FLAG_ALLOCATE_DEFY_HALF_RESERVED;
3184
3185 // However, if app is actively using the camera, then we're willing to
3186 // clear up to half of the reserved cache space, since the user might be
3187 // trying to capture an important memory.
3188 final AppOpsManager appOps = mContext.getSystemService(AppOpsManager.class);
3189 final long token = Binder.clearCallingIdentity();
3190 try {
3191 if (appOps.isOperationActive(AppOpsManager.OP_CAMERA, callingUid, callingPackage)) {
3192 Slog.d(TAG, "UID " + callingUid + " is actively using camera;"
3193 + " letting them defy reserved cached data");
3194 flags |= StorageManager.FLAG_ALLOCATE_DEFY_HALF_RESERVED;
3195 }
3196 } finally {
3197 Binder.restoreCallingIdentity(token);
3198 }
3199
3200 return flags;
3201 }
3202
3203 @Override
3204 public long getAllocatableBytes(String volumeUuid, int flags, String callingPackage) {
3205 flags = adjustAllocateFlags(flags, Binder.getCallingUid(), callingPackage);
3206
3207 final StorageManager storage = mContext.getSystemService(StorageManager.class);
3208 final StorageStatsManager stats = mContext.getSystemService(StorageStatsManager.class);
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07003209 final long token = Binder.clearCallingIdentity();
3210 try {
3211 // In general, apps can allocate as much space as they want, except
3212 // we never let them eat into either the minimum cache space or into
Jeff Sharkeyddff8072017-05-26 13:10:46 -06003213 // the low disk warning space. To avoid user confusion, this logic
3214 // should be kept in sync with getFreeBytes().
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07003215 final File path = storage.findPathForUuid(volumeUuid);
Jeff Sharkeyddff8072017-05-26 13:10:46 -06003216
3217 final long usable = path.getUsableSpace();
3218 final long lowReserved = storage.getStorageLowBytes(path);
3219 final long fullReserved = storage.getStorageFullBytes(path);
3220
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07003221 if (stats.isQuotaSupported(volumeUuid)) {
Jeff Sharkeyddff8072017-05-26 13:10:46 -06003222 final long cacheTotal = stats.getCacheBytes(volumeUuid);
Jeff Sharkey35e46d22017-06-09 10:01:20 -06003223 final long cacheReserved = storage.getStorageCacheBytes(path, flags);
Jeff Sharkeyddff8072017-05-26 13:10:46 -06003224 final long cacheClearable = Math.max(0, cacheTotal - cacheReserved);
3225
Jeff Sharkey35e46d22017-06-09 10:01:20 -06003226 if ((flags & StorageManager.FLAG_ALLOCATE_AGGRESSIVE) != 0) {
3227 return Math.max(0, (usable + cacheClearable) - fullReserved);
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07003228 } else {
Jeff Sharkeyddff8072017-05-26 13:10:46 -06003229 return Math.max(0, (usable + cacheClearable) - lowReserved);
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07003230 }
3231 } else {
3232 // When we don't have fast quota information, we ignore cached
3233 // data and only consider unused bytes.
Jeff Sharkey35e46d22017-06-09 10:01:20 -06003234 if ((flags & StorageManager.FLAG_ALLOCATE_AGGRESSIVE) != 0) {
Jeff Sharkeyddff8072017-05-26 13:10:46 -06003235 return Math.max(0, usable - fullReserved);
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07003236 } else {
Jeff Sharkeyddff8072017-05-26 13:10:46 -06003237 return Math.max(0, usable - lowReserved);
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07003238 }
3239 }
Jeff Sharkey789a8fc2017-04-16 13:18:35 -06003240 } catch (IOException e) {
3241 throw new ParcelableException(e);
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07003242 } finally {
3243 Binder.restoreCallingIdentity(token);
3244 }
Jeff Sharkey500ce9e2017-02-12 02:39:24 -07003245 }
3246
3247 @Override
Jeff Sharkey35e46d22017-06-09 10:01:20 -06003248 public void allocateBytes(String volumeUuid, long bytes, int flags, String callingPackage) {
3249 flags = adjustAllocateFlags(flags, Binder.getCallingUid(), callingPackage);
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07003250
Jeff Sharkey35e46d22017-06-09 10:01:20 -06003251 final long allocatableBytes = getAllocatableBytes(volumeUuid, flags, callingPackage);
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07003252 if (bytes > allocatableBytes) {
3253 throw new ParcelableException(new IOException("Failed to allocate " + bytes
3254 + " because only " + allocatableBytes + " allocatable"));
3255 }
3256
Jeff Sharkey35e46d22017-06-09 10:01:20 -06003257 final StorageManager storage = mContext.getSystemService(StorageManager.class);
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07003258 final long token = Binder.clearCallingIdentity();
3259 try {
Jeff Sharkey789a8fc2017-04-16 13:18:35 -06003260 // Free up enough disk space to satisfy both the requested allocation
3261 // and our low disk warning space.
3262 final File path = storage.findPathForUuid(volumeUuid);
Jeff Sharkeyddff8072017-05-26 13:10:46 -06003263 if ((flags & StorageManager.FLAG_ALLOCATE_AGGRESSIVE) != 0) {
3264 bytes += storage.getStorageFullBytes(path);
3265 } else {
3266 bytes += storage.getStorageLowBytes(path);
3267 }
Jeff Sharkey789a8fc2017-04-16 13:18:35 -06003268
Jeff Sharkey5790af02018-08-13 17:42:54 -06003269 mPmInternal.freeStorage(volumeUuid, bytes, flags);
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07003270 } catch (IOException e) {
3271 throw new ParcelableException(e);
3272 } finally {
3273 Binder.restoreCallingIdentity(token);
Jeff Sharkey500ce9e2017-02-12 02:39:24 -07003274 }
3275 }
3276
Sudheer Shankaff971bc2018-12-13 17:39:59 -08003277 private IAppOpsCallback.Stub mAppOpsCallback = new IAppOpsCallback.Stub() {
3278 @Override
3279 public void opChanged(int op, int uid, String packageName) throws RemoteException {
3280 if (!ENABLE_ISOLATED_STORAGE) return;
3281
3282 remountUidExternalStorage(uid, getMountMode(uid, packageName));
3283 }
3284 };
3285
Jeff Sharkey5790af02018-08-13 17:42:54 -06003286 private static final Pattern PATTERN_TRANSLATE = Pattern.compile(
3287 "(?i)^(/storage/[^/]+/(?:[0-9]+/)?)(.*)");
3288
3289 @Override
Sudheer Shanka87915d62018-11-06 10:57:35 -08003290 public String translateAppToSystem(String path, int pid, int uid) {
3291 return translateInternal(path, pid, uid, true);
Jeff Sharkey5790af02018-08-13 17:42:54 -06003292 }
3293
3294 @Override
Sudheer Shanka87915d62018-11-06 10:57:35 -08003295 public String translateSystemToApp(String path, int pid, int uid) {
3296 return translateInternal(path, pid, uid, false);
Jeff Sharkey5790af02018-08-13 17:42:54 -06003297 }
3298
Sudheer Shanka87915d62018-11-06 10:57:35 -08003299 private String translateInternal(String path, int pid, int uid, boolean toSystem) {
Jeff Sharkey5790af02018-08-13 17:42:54 -06003300 if (!ENABLE_ISOLATED_STORAGE) return path;
3301
3302 if (path.contains("/../")) {
3303 throw new SecurityException("Shady looking path " + path);
3304 }
3305
Sudheer Shanka3a0df3b2018-12-12 12:43:43 -08003306 final int mountMode = mAmInternal.getStorageMountMode(pid, uid);
Sudheer Shanka0b6da532019-01-09 12:06:51 -08003307 if (mountMode == Zygote.MOUNT_EXTERNAL_FULL
3308 || mountMode == Zygote.MOUNT_EXTERNAL_LEGACY) {
Sudheer Shanka87915d62018-11-06 10:57:35 -08003309 return path;
3310 }
Jeff Sharkey5790af02018-08-13 17:42:54 -06003311
3312 final Matcher m = PATTERN_TRANSLATE.matcher(path);
3313 if (m.matches()) {
3314 final String device = m.group(1);
3315 final String devicePath = m.group(2);
3316
Sudheer Shanka3a0df3b2018-12-12 12:43:43 -08003317 if (mountMode == Zygote.MOUNT_EXTERNAL_INSTALLER
3318 && devicePath.startsWith("Android/obb/")) {
3319 return path;
3320 }
3321
Jeff Sharkey5790af02018-08-13 17:42:54 -06003322 // Does path belong to any packages belonging to this UID? If so,
3323 // they get to go straight through to legacy paths.
Sudheer Shanka87915d62018-11-06 10:57:35 -08003324 final String[] pkgs = mContext.getPackageManager().getPackagesForUid(uid);
Jeff Sharkey5790af02018-08-13 17:42:54 -06003325 for (String pkg : pkgs) {
3326 if (devicePath.startsWith("Android/data/" + pkg + "/") ||
3327 devicePath.startsWith("Android/media/" + pkg + "/") ||
3328 devicePath.startsWith("Android/obb/" + pkg + "/")) {
3329 return path;
3330 }
3331 }
3332
Sudheer Shanka87915d62018-11-06 10:57:35 -08003333 final String sharedUserId = mPmInternal.getSharedUserIdForPackage(pkgs[0]);
3334 final String sandboxId = getSandboxId(pkgs[0], sharedUserId);
3335
Jeff Sharkey5790af02018-08-13 17:42:54 -06003336 if (toSystem) {
3337 // Everything else goes into sandbox.
Sudheer Shanka31ad0a12018-10-20 20:59:00 -07003338 return device + "Android/sandbox/" + sandboxId + "/" + devicePath;
Jeff Sharkey5790af02018-08-13 17:42:54 -06003339 } else {
3340 // Does path belong to this sandbox? If so, leave sandbox.
Sudheer Shanka31ad0a12018-10-20 20:59:00 -07003341 final String sandboxPrefix = "Android/sandbox/" + sandboxId + "/";
Jeff Sharkey5790af02018-08-13 17:42:54 -06003342 if (devicePath.startsWith(sandboxPrefix)) {
3343 return device + devicePath.substring(sandboxPrefix.length());
3344 }
3345
3346 // Path isn't valid inside sandbox!
3347 throw new SecurityException(
3348 "Path " + path + " isn't valid inside sandbox " + sandboxId);
3349 }
3350 }
3351
3352 return path;
3353 }
3354
Kenny Rootaf9d6672010-10-08 09:21:39 -07003355 private void addObbStateLocked(ObbState obbState) throws RemoteException {
3356 final IBinder binder = obbState.getBinder();
3357 List<ObbState> obbStates = mObbMounts.get(binder);
Kenny Root5919ac62010-10-05 09:49:40 -07003358
Kenny Rootaf9d6672010-10-08 09:21:39 -07003359 if (obbStates == null) {
3360 obbStates = new ArrayList<ObbState>();
3361 mObbMounts.put(binder, obbStates);
3362 } else {
3363 for (final ObbState o : obbStates) {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003364 if (o.rawPath.equals(obbState.rawPath)) {
Kenny Rootaf9d6672010-10-08 09:21:39 -07003365 throw new IllegalStateException("Attempt to add ObbState twice. "
Sudheer Shanka2250d562016-11-07 15:41:02 -08003366 + "This indicates an error in the StorageManagerService logic.");
Kenny Root5919ac62010-10-05 09:49:40 -07003367 }
3368 }
Kenny Roota02b8b02010-08-05 16:14:17 -07003369 }
Kenny Rootaf9d6672010-10-08 09:21:39 -07003370
3371 obbStates.add(obbState);
3372 try {
3373 obbState.link();
3374 } catch (RemoteException e) {
3375 /*
3376 * The binder died before we could link it, so clean up our state
3377 * and return failure.
3378 */
3379 obbStates.remove(obbState);
3380 if (obbStates.isEmpty()) {
3381 mObbMounts.remove(binder);
3382 }
3383
3384 // Rethrow the error so mountObb can get it
3385 throw e;
3386 }
3387
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003388 mObbPathToStateMap.put(obbState.rawPath, obbState);
Kenny Roota02b8b02010-08-05 16:14:17 -07003389 }
3390
Kenny Rootaf9d6672010-10-08 09:21:39 -07003391 private void removeObbStateLocked(ObbState obbState) {
3392 final IBinder binder = obbState.getBinder();
3393 final List<ObbState> obbStates = mObbMounts.get(binder);
3394 if (obbStates != null) {
3395 if (obbStates.remove(obbState)) {
3396 obbState.unlink();
Kenny Root05105f72010-09-22 17:29:43 -07003397 }
Kenny Rootaf9d6672010-10-08 09:21:39 -07003398 if (obbStates.isEmpty()) {
3399 mObbMounts.remove(binder);
3400 }
Kenny Roota02b8b02010-08-05 16:14:17 -07003401 }
Kenny Roota02b8b02010-08-05 16:14:17 -07003402
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003403 mObbPathToStateMap.remove(obbState.rawPath);
Kenny Root38cf8862010-09-26 14:18:51 -07003404 }
3405
Kenny Roota02b8b02010-08-05 16:14:17 -07003406 private class ObbActionHandler extends Handler {
Kenny Roota02b8b02010-08-05 16:14:17 -07003407
3408 ObbActionHandler(Looper l) {
3409 super(l);
3410 }
3411
3412 @Override
3413 public void handleMessage(Message msg) {
3414 switch (msg.what) {
3415 case OBB_RUN_ACTION: {
Kenny Root480afe72010-10-07 10:17:50 -07003416 final ObbAction action = (ObbAction) msg.obj;
Kenny Roota02b8b02010-08-05 16:14:17 -07003417
3418 if (DEBUG_OBB)
3419 Slog.i(TAG, "OBB_RUN_ACTION: " + action.toString());
3420
Sudheer Shanka25469aa2018-08-27 15:50:23 -07003421 action.execute(this);
Kenny Roota02b8b02010-08-05 16:14:17 -07003422 break;
3423 }
Kenny Rootaf9d6672010-10-08 09:21:39 -07003424 case OBB_FLUSH_MOUNT_STATE: {
3425 final String path = (String) msg.obj;
3426
3427 if (DEBUG_OBB)
3428 Slog.i(TAG, "Flushing all OBB state for path " + path);
3429
3430 synchronized (mObbMounts) {
3431 final List<ObbState> obbStatesToRemove = new LinkedList<ObbState>();
3432
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003433 final Iterator<ObbState> i = mObbPathToStateMap.values().iterator();
Kenny Rootaf9d6672010-10-08 09:21:39 -07003434 while (i.hasNext()) {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003435 final ObbState state = i.next();
Kenny Rootaf9d6672010-10-08 09:21:39 -07003436
3437 /*
3438 * If this entry's source file is in the volume path
3439 * that got unmounted, remove it because it's no
3440 * longer valid.
3441 */
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003442 if (state.canonicalPath.startsWith(path)) {
3443 obbStatesToRemove.add(state);
Kenny Rootaf9d6672010-10-08 09:21:39 -07003444 }
3445 }
3446
3447 for (final ObbState obbState : obbStatesToRemove) {
3448 if (DEBUG_OBB)
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003449 Slog.i(TAG, "Removing state for " + obbState.rawPath);
Kenny Rootaf9d6672010-10-08 09:21:39 -07003450
3451 removeObbStateLocked(obbState);
3452
3453 try {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003454 obbState.token.onObbResult(obbState.rawPath, obbState.nonce,
Kenny Rootaf9d6672010-10-08 09:21:39 -07003455 OnObbStateChangeListener.UNMOUNTED);
3456 } catch (RemoteException e) {
3457 Slog.i(TAG, "Couldn't send unmount notification for OBB: "
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003458 + obbState.rawPath);
Kenny Rootaf9d6672010-10-08 09:21:39 -07003459 }
3460 }
3461 }
3462 break;
3463 }
Kenny Roota02b8b02010-08-05 16:14:17 -07003464 }
3465 }
Kenny Roota02b8b02010-08-05 16:14:17 -07003466 }
3467
Jeff Sharkey0095a822018-02-15 13:06:53 -07003468 private static class ObbException extends Exception {
3469 public final int status;
3470
3471 public ObbException(int status, String message) {
3472 super(message);
3473 this.status = status;
3474 }
3475
3476 public ObbException(int status, Throwable cause) {
3477 super(cause.getMessage(), cause);
3478 this.status = status;
3479 }
3480 }
3481
Kenny Roota02b8b02010-08-05 16:14:17 -07003482 abstract class ObbAction {
Kenny Roota02b8b02010-08-05 16:14:17 -07003483
3484 ObbState mObbState;
3485
3486 ObbAction(ObbState obbState) {
3487 mObbState = obbState;
3488 }
3489
3490 public void execute(ObbActionHandler handler) {
3491 try {
3492 if (DEBUG_OBB)
Ben Komalo444eca22011-09-01 15:17:44 -07003493 Slog.i(TAG, "Starting to execute action: " + toString());
Sudheer Shanka25469aa2018-08-27 15:50:23 -07003494 handleExecute();
Jeff Sharkey0095a822018-02-15 13:06:53 -07003495 } catch (ObbException e) {
3496 notifyObbStateChange(e);
Kenny Roota02b8b02010-08-05 16:14:17 -07003497 }
3498 }
3499
Jeff Sharkey0095a822018-02-15 13:06:53 -07003500 abstract void handleExecute() throws ObbException;
Kenny Root38cf8862010-09-26 14:18:51 -07003501
Jeff Sharkey0095a822018-02-15 13:06:53 -07003502 protected void notifyObbStateChange(ObbException e) {
3503 Slog.w(TAG, e);
3504 notifyObbStateChange(e.status);
3505 }
3506
3507 protected void notifyObbStateChange(int status) {
Kenny Rootaf9d6672010-10-08 09:21:39 -07003508 if (mObbState == null || mObbState.token == null) {
3509 return;
3510 }
3511
Kenny Root38cf8862010-09-26 14:18:51 -07003512 try {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003513 mObbState.token.onObbResult(mObbState.rawPath, mObbState.nonce, status);
Kenny Root38cf8862010-09-26 14:18:51 -07003514 } catch (RemoteException e) {
Sudheer Shanka2250d562016-11-07 15:41:02 -08003515 Slog.w(TAG, "StorageEventListener went away while calling onObbStateChanged");
Kenny Root38cf8862010-09-26 14:18:51 -07003516 }
3517 }
Kenny Roota02b8b02010-08-05 16:14:17 -07003518 }
3519
3520 class MountObbAction extends ObbAction {
Ben Komalo444eca22011-09-01 15:17:44 -07003521 private final String mKey;
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003522 private final int mCallingUid;
Sudheer Shanka25469aa2018-08-27 15:50:23 -07003523 private ObbInfo mObbInfo;
Kenny Roota02b8b02010-08-05 16:14:17 -07003524
Sudheer Shanka25469aa2018-08-27 15:50:23 -07003525 MountObbAction(ObbState obbState, String key, int callingUid, ObbInfo obbInfo) {
Kenny Roota02b8b02010-08-05 16:14:17 -07003526 super(obbState);
3527 mKey = key;
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003528 mCallingUid = callingUid;
Sudheer Shanka25469aa2018-08-27 15:50:23 -07003529 mObbInfo = obbInfo;
Kenny Roota02b8b02010-08-05 16:14:17 -07003530 }
3531
Jason parks5af0b912010-11-29 09:05:25 -06003532 @Override
Jeff Sharkey0095a822018-02-15 13:06:53 -07003533 public void handleExecute() throws ObbException {
Kenny Rootaf9d6672010-10-08 09:21:39 -07003534 warnOnNotMounted();
3535
Sudheer Shanka25469aa2018-08-27 15:50:23 -07003536 if (!isUidOwnerOfPackageOrSystem(mObbInfo.packageName, mCallingUid)) {
Jeff Sharkey0095a822018-02-15 13:06:53 -07003537 throw new ObbException(ERROR_PERMISSION_DENIED, "Denied attempt to mount OBB "
Sudheer Shanka25469aa2018-08-27 15:50:23 -07003538 + mObbInfo.filename + " which is owned by " + mObbInfo.packageName);
Kenny Roota02b8b02010-08-05 16:14:17 -07003539 }
3540
Kenny Rootaf9d6672010-10-08 09:21:39 -07003541 final boolean isMounted;
3542 synchronized (mObbMounts) {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003543 isMounted = mObbPathToStateMap.containsKey(mObbState.rawPath);
Kenny Rootaf9d6672010-10-08 09:21:39 -07003544 }
3545 if (isMounted) {
Jeff Sharkey0095a822018-02-15 13:06:53 -07003546 throw new ObbException(ERROR_ALREADY_MOUNTED,
Sudheer Shanka25469aa2018-08-27 15:50:23 -07003547 "Attempt to mount OBB which is already mounted: " + mObbInfo.filename);
Kenny Rootaf9d6672010-10-08 09:21:39 -07003548 }
3549
Kenny Rootaf9d6672010-10-08 09:21:39 -07003550 final String hashedKey;
Jeff Sharkey41cd6812017-09-11 10:32:17 -06003551 final String binderKey;
Kenny Rootaf9d6672010-10-08 09:21:39 -07003552 if (mKey == null) {
3553 hashedKey = "none";
Jeff Sharkey41cd6812017-09-11 10:32:17 -06003554 binderKey = "";
Kenny Rootaf9d6672010-10-08 09:21:39 -07003555 } else {
Kenny Rootaf9d6672010-10-08 09:21:39 -07003556 try {
Kenny Root3b1abba2010-10-13 15:00:07 -07003557 SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
3558
Sudheer Shanka25469aa2018-08-27 15:50:23 -07003559 KeySpec ks = new PBEKeySpec(mKey.toCharArray(), mObbInfo.salt,
Kenny Root3b1abba2010-10-13 15:00:07 -07003560 PBKDF2_HASH_ROUNDS, CRYPTO_ALGORITHM_KEY_SIZE);
3561 SecretKey key = factory.generateSecret(ks);
3562 BigInteger bi = new BigInteger(key.getEncoded());
3563 hashedKey = bi.toString(16);
Jeff Sharkey41cd6812017-09-11 10:32:17 -06003564 binderKey = hashedKey;
Jeff Sharkey0095a822018-02-15 13:06:53 -07003565 } catch (GeneralSecurityException e) {
3566 throw new ObbException(ERROR_INTERNAL, e);
Kenny Root38cf8862010-09-26 14:18:51 -07003567 }
Kenny Rootaf9d6672010-10-08 09:21:39 -07003568 }
Kenny Root38cf8862010-09-26 14:18:51 -07003569
Kenny Rootaf9d6672010-10-08 09:21:39 -07003570 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06003571 mObbState.volId = mVold.createObb(mObbState.canonicalPath, binderKey,
3572 mObbState.ownerGid);
3573 mVold.mount(mObbState.volId, 0, -1);
Kenny Roota02b8b02010-08-05 16:14:17 -07003574
Kenny Rootaf9d6672010-10-08 09:21:39 -07003575 if (DEBUG_OBB)
Xiaohui Chen621b3fc2015-10-02 14:41:42 -07003576 Slog.d(TAG, "Successfully mounted OBB " + mObbState.canonicalPath);
Kenny Rootaf9d6672010-10-08 09:21:39 -07003577
3578 synchronized (mObbMounts) {
3579 addObbStateLocked(mObbState);
3580 }
3581
Jeff Sharkey0095a822018-02-15 13:06:53 -07003582 notifyObbStateChange(MOUNTED);
3583 } catch (Exception e) {
3584 throw new ObbException(ERROR_COULD_NOT_MOUNT, e);
Kenny Root02c87302010-07-01 08:10:18 -07003585 }
3586 }
3587
Jason parks5af0b912010-11-29 09:05:25 -06003588 @Override
Kenny Roota02b8b02010-08-05 16:14:17 -07003589 public String toString() {
3590 StringBuilder sb = new StringBuilder();
3591 sb.append("MountObbAction{");
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003592 sb.append(mObbState);
Kenny Roota02b8b02010-08-05 16:14:17 -07003593 sb.append('}');
3594 return sb.toString();
3595 }
3596 }
3597
3598 class UnmountObbAction extends ObbAction {
Ben Komalo444eca22011-09-01 15:17:44 -07003599 private final boolean mForceUnmount;
Kenny Roota02b8b02010-08-05 16:14:17 -07003600
3601 UnmountObbAction(ObbState obbState, boolean force) {
3602 super(obbState);
3603 mForceUnmount = force;
3604 }
3605
Jason parks5af0b912010-11-29 09:05:25 -06003606 @Override
Jeff Sharkey0095a822018-02-15 13:06:53 -07003607 public void handleExecute() throws ObbException {
Kenny Rootaf9d6672010-10-08 09:21:39 -07003608 warnOnNotMounted();
3609
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003610 final ObbState existingState;
Kenny Root38cf8862010-09-26 14:18:51 -07003611 synchronized (mObbMounts) {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003612 existingState = mObbPathToStateMap.get(mObbState.rawPath);
Kenny Rootaf9d6672010-10-08 09:21:39 -07003613 }
Kenny Root38cf8862010-09-26 14:18:51 -07003614
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003615 if (existingState == null) {
Jeff Sharkey0095a822018-02-15 13:06:53 -07003616 throw new ObbException(ERROR_NOT_MOUNTED, "Missing existingState");
Kenny Rootaf9d6672010-10-08 09:21:39 -07003617 }
3618
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003619 if (existingState.ownerGid != mObbState.ownerGid) {
Jeff Sharkey0095a822018-02-15 13:06:53 -07003620 notifyObbStateChange(new ObbException(ERROR_PERMISSION_DENIED,
3621 "Permission denied to unmount OBB " + existingState.rawPath
3622 + " (owned by GID " + existingState.ownerGid + ")"));
Kenny Rootaf9d6672010-10-08 09:21:39 -07003623 return;
3624 }
3625
Kenny Rootaf9d6672010-10-08 09:21:39 -07003626 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06003627 mVold.unmount(mObbState.volId);
3628 mVold.destroyObb(mObbState.volId);
3629 mObbState.volId = null;
Kenny Roota02b8b02010-08-05 16:14:17 -07003630
Kenny Rootaf9d6672010-10-08 09:21:39 -07003631 synchronized (mObbMounts) {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003632 removeObbStateLocked(existingState);
Kenny Root38cf8862010-09-26 14:18:51 -07003633 }
3634
Jeff Sharkey0095a822018-02-15 13:06:53 -07003635 notifyObbStateChange(UNMOUNTED);
3636 } catch (Exception e) {
3637 throw new ObbException(ERROR_COULD_NOT_UNMOUNT, e);
Kenny Roota02b8b02010-08-05 16:14:17 -07003638 }
3639 }
3640
Jason parks5af0b912010-11-29 09:05:25 -06003641 @Override
Kenny Roota02b8b02010-08-05 16:14:17 -07003642 public String toString() {
3643 StringBuilder sb = new StringBuilder();
3644 sb.append("UnmountObbAction{");
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003645 sb.append(mObbState);
Kenny Roota02b8b02010-08-05 16:14:17 -07003646 sb.append(",force=");
3647 sb.append(mForceUnmount);
Kenny Roota02b8b02010-08-05 16:14:17 -07003648 sb.append('}');
3649 return sb.toString();
3650 }
Kenny Root02c87302010-07-01 08:10:18 -07003651 }
Kenny Root38cf8862010-09-26 14:18:51 -07003652
Jeff Sharkey7e19f532017-11-06 13:54:11 -07003653 private void dispatchOnStatus(IVoldTaskListener listener, int status,
3654 PersistableBundle extras) {
3655 if (listener != null) {
3656 try {
3657 listener.onStatus(status, extras);
3658 } catch (RemoteException ignored) {
3659 }
3660 }
3661 }
3662
3663 private void dispatchOnFinished(IVoldTaskListener listener, int status,
3664 PersistableBundle extras) {
3665 if (listener != null) {
3666 try {
3667 listener.onFinished(status, extras);
3668 } catch (RemoteException ignored) {
3669 }
3670 }
3671 }
3672
Sudheer Shanka3a0df3b2018-12-12 12:43:43 -08003673 private int getMountMode(int uid, String packageName) {
3674 try {
3675 if (Process.isIsolated(uid)) {
3676 return Zygote.MOUNT_EXTERNAL_NONE;
3677 }
3678 if (mIPackageManager.checkUidPermission(WRITE_MEDIA_STORAGE, uid)
3679 == PERMISSION_GRANTED) {
3680 return Zygote.MOUNT_EXTERNAL_FULL;
Jeff Sharkey11697f52018-12-13 10:14:42 -07003681 } else if (mIAppOpsService.checkOperation(OP_LEGACY_STORAGE, uid,
3682 packageName) == MODE_ALLOWED) {
Sudheer Shanka0b6da532019-01-09 12:06:51 -08003683 return Zygote.MOUNT_EXTERNAL_LEGACY;
Sudheer Shanka3a0df3b2018-12-12 12:43:43 -08003684 } else if (mIPackageManager.checkUidPermission(INSTALL_PACKAGES, uid)
3685 == PERMISSION_GRANTED || mIAppOpsService.checkOperation(
3686 OP_REQUEST_INSTALL_PACKAGES, uid, packageName) == MODE_ALLOWED) {
3687 return Zygote.MOUNT_EXTERNAL_INSTALLER;
Sudheer Shanka0f26cbd2019-01-18 18:25:38 -08003688 } else if (mPmInternal.isInstantApp(packageName, UserHandle.getUserId(uid))) {
3689 return Zygote.MOUNT_EXTERNAL_NONE;
Sudheer Shanka3a0df3b2018-12-12 12:43:43 -08003690 } else {
3691 return Zygote.MOUNT_EXTERNAL_WRITE;
3692 }
3693 } catch (RemoteException e) {
3694 // Should not happen
3695 }
3696 return Zygote.MOUNT_EXTERNAL_NONE;
3697 }
3698
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07003699 private static class Callbacks extends Handler {
3700 private static final int MSG_STORAGE_STATE_CHANGED = 1;
3701 private static final int MSG_VOLUME_STATE_CHANGED = 2;
Jeff Sharkey50a05452015-04-29 11:24:52 -07003702 private static final int MSG_VOLUME_RECORD_CHANGED = 3;
3703 private static final int MSG_VOLUME_FORGOTTEN = 4;
3704 private static final int MSG_DISK_SCANNED = 5;
Makoto Onuki9dc575d2015-06-12 16:10:25 -07003705 private static final int MSG_DISK_DESTROYED = 6;
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07003706
Sudheer Shanka2250d562016-11-07 15:41:02 -08003707 private final RemoteCallbackList<IStorageEventListener>
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07003708 mCallbacks = new RemoteCallbackList<>();
3709
3710 public Callbacks(Looper looper) {
3711 super(looper);
3712 }
3713
Sudheer Shanka2250d562016-11-07 15:41:02 -08003714 public void register(IStorageEventListener callback) {
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07003715 mCallbacks.register(callback);
3716 }
3717
Sudheer Shanka2250d562016-11-07 15:41:02 -08003718 public void unregister(IStorageEventListener callback) {
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07003719 mCallbacks.unregister(callback);
3720 }
3721
3722 @Override
3723 public void handleMessage(Message msg) {
3724 final SomeArgs args = (SomeArgs) msg.obj;
3725 final int n = mCallbacks.beginBroadcast();
3726 for (int i = 0; i < n; i++) {
Sudheer Shanka2250d562016-11-07 15:41:02 -08003727 final IStorageEventListener callback = mCallbacks.getBroadcastItem(i);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07003728 try {
3729 invokeCallback(callback, msg.what, args);
3730 } catch (RemoteException ignored) {
3731 }
3732 }
3733 mCallbacks.finishBroadcast();
3734 args.recycle();
3735 }
3736
Sudheer Shanka2250d562016-11-07 15:41:02 -08003737 private void invokeCallback(IStorageEventListener callback, int what, SomeArgs args)
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07003738 throws RemoteException {
3739 switch (what) {
3740 case MSG_STORAGE_STATE_CHANGED: {
3741 callback.onStorageStateChanged((String) args.arg1, (String) args.arg2,
3742 (String) args.arg3);
3743 break;
3744 }
3745 case MSG_VOLUME_STATE_CHANGED: {
3746 callback.onVolumeStateChanged((VolumeInfo) args.arg1, args.argi2, args.argi3);
3747 break;
3748 }
Jeff Sharkey50a05452015-04-29 11:24:52 -07003749 case MSG_VOLUME_RECORD_CHANGED: {
3750 callback.onVolumeRecordChanged((VolumeRecord) args.arg1);
3751 break;
3752 }
3753 case MSG_VOLUME_FORGOTTEN: {
3754 callback.onVolumeForgotten((String) args.arg1);
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07003755 break;
3756 }
Jeff Sharkey620b32b2015-04-23 19:36:02 -07003757 case MSG_DISK_SCANNED: {
3758 callback.onDiskScanned((DiskInfo) args.arg1, args.argi2);
Jeff Sharkey7e92ef32015-04-17 17:35:07 -07003759 break;
3760 }
Makoto Onuki9dc575d2015-06-12 16:10:25 -07003761 case MSG_DISK_DESTROYED: {
3762 callback.onDiskDestroyed((DiskInfo) args.arg1);
3763 break;
3764 }
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07003765 }
3766 }
3767
3768 private void notifyStorageStateChanged(String path, String oldState, String newState) {
3769 final SomeArgs args = SomeArgs.obtain();
3770 args.arg1 = path;
3771 args.arg2 = oldState;
3772 args.arg3 = newState;
3773 obtainMessage(MSG_STORAGE_STATE_CHANGED, args).sendToTarget();
3774 }
3775
3776 private void notifyVolumeStateChanged(VolumeInfo vol, int oldState, int newState) {
3777 final SomeArgs args = SomeArgs.obtain();
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07003778 args.arg1 = vol.clone();
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07003779 args.argi2 = oldState;
3780 args.argi3 = newState;
3781 obtainMessage(MSG_VOLUME_STATE_CHANGED, args).sendToTarget();
3782 }
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07003783
Jeff Sharkey50a05452015-04-29 11:24:52 -07003784 private void notifyVolumeRecordChanged(VolumeRecord rec) {
3785 final SomeArgs args = SomeArgs.obtain();
3786 args.arg1 = rec.clone();
3787 obtainMessage(MSG_VOLUME_RECORD_CHANGED, args).sendToTarget();
3788 }
3789
3790 private void notifyVolumeForgotten(String fsUuid) {
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07003791 final SomeArgs args = SomeArgs.obtain();
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07003792 args.arg1 = fsUuid;
Jeff Sharkey50a05452015-04-29 11:24:52 -07003793 obtainMessage(MSG_VOLUME_FORGOTTEN, args).sendToTarget();
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07003794 }
Jeff Sharkey7e92ef32015-04-17 17:35:07 -07003795
Jeff Sharkey620b32b2015-04-23 19:36:02 -07003796 private void notifyDiskScanned(DiskInfo disk, int volumeCount) {
Jeff Sharkey7e92ef32015-04-17 17:35:07 -07003797 final SomeArgs args = SomeArgs.obtain();
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07003798 args.arg1 = disk.clone();
Jeff Sharkey620b32b2015-04-23 19:36:02 -07003799 args.argi2 = volumeCount;
3800 obtainMessage(MSG_DISK_SCANNED, args).sendToTarget();
Jeff Sharkey7e92ef32015-04-17 17:35:07 -07003801 }
Makoto Onuki9dc575d2015-06-12 16:10:25 -07003802
3803 private void notifyDiskDestroyed(DiskInfo disk) {
3804 final SomeArgs args = SomeArgs.obtain();
3805 args.arg1 = disk.clone();
3806 obtainMessage(MSG_DISK_DESTROYED, args).sendToTarget();
3807 }
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07003808 }
3809
Kenny Root38cf8862010-09-26 14:18:51 -07003810 @Override
Jeff Sharkey5aca2b82013-10-16 16:21:54 -07003811 protected void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
Jeff Sharkeyfe9a53b2017-03-31 14:08:23 -06003812 if (!DumpUtils.checkDumpPermission(mContext, TAG, writer)) return;
Jeff Sharkey5aca2b82013-10-16 16:21:54 -07003813
3814 final IndentingPrintWriter pw = new IndentingPrintWriter(writer, " ", 160);
Jeff Sharkey27de30d2015-04-18 16:20:27 -07003815 synchronized (mLock) {
3816 pw.println("Disks:");
3817 pw.increaseIndent();
3818 for (int i = 0; i < mDisks.size(); i++) {
3819 final DiskInfo disk = mDisks.valueAt(i);
3820 disk.dump(pw);
3821 }
3822 pw.decreaseIndent();
3823
3824 pw.println();
3825 pw.println("Volumes:");
3826 pw.increaseIndent();
3827 for (int i = 0; i < mVolumes.size(); i++) {
3828 final VolumeInfo vol = mVolumes.valueAt(i);
3829 if (VolumeInfo.ID_PRIVATE_INTERNAL.equals(vol.id)) continue;
3830 vol.dump(pw);
3831 }
3832 pw.decreaseIndent();
3833
3834 pw.println();
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07003835 pw.println("Records:");
Jeff Sharkey27de30d2015-04-18 16:20:27 -07003836 pw.increaseIndent();
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07003837 for (int i = 0; i < mRecords.size(); i++) {
3838 final VolumeRecord note = mRecords.valueAt(i);
3839 note.dump(pw);
Jeff Sharkey27de30d2015-04-18 16:20:27 -07003840 }
3841 pw.decreaseIndent();
Jeff Sharkey275e3e42015-04-24 16:10:32 -07003842
3843 pw.println();
Sudheer Shanka3f0645b2018-09-18 13:07:59 -07003844 pw.println("mVisibleVols:");
3845 pw.increaseIndent();
3846 for (int i = 0; i < mVisibleVols.size(); i++) {
3847 mVisibleVols.get(i).dump(pw);
3848 }
3849 pw.decreaseIndent();
3850
3851 pw.println();
Jeff Sharkey275e3e42015-04-24 16:10:32 -07003852 pw.println("Primary storage UUID: " + mPrimaryStorageUuid);
Jeff Sharkeyb0c363b22018-12-15 11:53:03 -07003853
3854 pw.println();
Felipe Leme281389a2016-10-10 17:12:20 -07003855 final Pair<String, Long> pair = StorageManager.getPrimaryStoragePathAndSize();
3856 if (pair == null) {
3857 pw.println("Internal storage total size: N/A");
3858 } else {
3859 pw.print("Internal storage (");
3860 pw.print(pair.first);
3861 pw.print(") total size: ");
3862 pw.print(pair.second);
3863 pw.print(" (");
Jeff Sharkey9f2dc052018-01-07 16:47:31 -07003864 pw.print(DataUnit.MEBIBYTES.toBytes(pair.second));
3865 pw.println(" MiB)");
Felipe Leme281389a2016-10-10 17:12:20 -07003866 }
Jeff Sharkeyb0c363b22018-12-15 11:53:03 -07003867
3868 pw.println();
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07003869 pw.println("Local unlocked users: " + Arrays.toString(mLocalUnlockedUsers));
3870 pw.println("System unlocked users: " + Arrays.toString(mSystemUnlockedUsers));
Jeff Sharkeyb0c363b22018-12-15 11:53:03 -07003871
3872 final ContentResolver cr = mContext.getContentResolver();
3873 pw.println();
3874 pw.println("Isolated storage, local feature flag: "
3875 + Settings.Global.getInt(cr, Settings.Global.ISOLATED_STORAGE_LOCAL, 0));
3876 pw.println("Isolated storage, remote feature flag: "
3877 + Settings.Global.getInt(cr, Settings.Global.ISOLATED_STORAGE_REMOTE, 0));
3878 pw.println("Isolated storage, resolved: " + StorageManager.hasIsolatedStorage());
Jeff Sharkey27de30d2015-04-18 16:20:27 -07003879 }
Kenny Root38cf8862010-09-26 14:18:51 -07003880
Kenny Root38cf8862010-09-26 14:18:51 -07003881 synchronized (mObbMounts) {
Jeff Sharkey27de30d2015-04-18 16:20:27 -07003882 pw.println();
Jeff Sharkey5aca2b82013-10-16 16:21:54 -07003883 pw.println("mObbMounts:");
3884 pw.increaseIndent();
3885 final Iterator<Entry<IBinder, List<ObbState>>> binders = mObbMounts.entrySet()
3886 .iterator();
Kenny Rootaf9d6672010-10-08 09:21:39 -07003887 while (binders.hasNext()) {
3888 Entry<IBinder, List<ObbState>> e = binders.next();
Jeff Sharkey5aca2b82013-10-16 16:21:54 -07003889 pw.println(e.getKey() + ":");
3890 pw.increaseIndent();
Kenny Rootaf9d6672010-10-08 09:21:39 -07003891 final List<ObbState> obbStates = e.getValue();
Kenny Root38cf8862010-09-26 14:18:51 -07003892 for (final ObbState obbState : obbStates) {
Jeff Sharkey5aca2b82013-10-16 16:21:54 -07003893 pw.println(obbState);
Kenny Root38cf8862010-09-26 14:18:51 -07003894 }
Jeff Sharkey5aca2b82013-10-16 16:21:54 -07003895 pw.decreaseIndent();
Kenny Root38cf8862010-09-26 14:18:51 -07003896 }
Jeff Sharkey5aca2b82013-10-16 16:21:54 -07003897 pw.decreaseIndent();
Kenny Rootaf9d6672010-10-08 09:21:39 -07003898
Jeff Sharkey5aca2b82013-10-16 16:21:54 -07003899 pw.println();
3900 pw.println("mObbPathToStateMap:");
3901 pw.increaseIndent();
Kenny Rootaf9d6672010-10-08 09:21:39 -07003902 final Iterator<Entry<String, ObbState>> maps = mObbPathToStateMap.entrySet().iterator();
3903 while (maps.hasNext()) {
3904 final Entry<String, ObbState> e = maps.next();
Jeff Sharkey5aca2b82013-10-16 16:21:54 -07003905 pw.print(e.getKey());
3906 pw.print(" -> ");
3907 pw.println(e.getValue());
Kenny Rootaf9d6672010-10-08 09:21:39 -07003908 }
Jeff Sharkey5aca2b82013-10-16 16:21:54 -07003909 pw.decreaseIndent();
Kenny Root38cf8862010-09-26 14:18:51 -07003910 }
Kenny Root4161f9b2011-07-13 09:48:33 -07003911
Robert Greenwalt470fd722012-01-18 12:51:15 -08003912 pw.println();
Christopher Tate7265abe2014-11-21 13:54:45 -08003913 pw.print("Last maintenance: ");
Jeff Sharkeye8a4b662015-06-27 15:43:45 -07003914 pw.println(TimeUtils.formatForLogging(mLastMaintenance));
Kenny Root38cf8862010-09-26 14:18:51 -07003915 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003916
Jeff Sharkeyfa23c5a2011-08-09 21:44:24 -07003917 /** {@inheritDoc} */
Jeff Sharkey48877892015-03-18 11:27:19 -07003918 @Override
Jeff Sharkeyfa23c5a2011-08-09 21:44:24 -07003919 public void monitor() {
Jeff Sharkey54402792017-09-15 16:05:19 -06003920 try {
3921 mVold.monitor();
3922 } catch (Exception e) {
3923 Slog.wtf(TAG, e);
Paul Lawrence1c62cbb2015-06-03 14:14:52 -07003924 }
Jeff Sharkeyfa23c5a2011-08-09 21:44:24 -07003925 }
Svet Ganov6ee871e2015-07-10 14:29:33 -07003926
Sudheer Shanka2250d562016-11-07 15:41:02 -08003927 private final class StorageManagerInternalImpl extends StorageManagerInternal {
Svet Ganov6ee871e2015-07-10 14:29:33 -07003928 // Not guarded by a lock.
3929 private final CopyOnWriteArrayList<ExternalStorageMountPolicy> mPolicies =
3930 new CopyOnWriteArrayList<>();
3931
Risanaec0ee72018-10-31 10:10:12 +09003932 @GuardedBy("mResetListeners")
3933 private final List<StorageManagerInternal.ResetListener> mResetListeners =
3934 new ArrayList<>();
3935
Svet Ganov6ee871e2015-07-10 14:29:33 -07003936 @Override
3937 public void addExternalStoragePolicy(ExternalStorageMountPolicy policy) {
3938 // No locking - CopyOnWriteArrayList
3939 mPolicies.add(policy);
3940 }
3941
3942 @Override
3943 public void onExternalStoragePolicyChanged(int uid, String packageName) {
Sudheer Shanka0a541a52018-07-31 13:21:11 -07003944 // No runtime storage permissions in isolated storage world, so nothing to do here.
Jeff Sharkeyc58fdf32018-08-15 18:49:34 -06003945 if (ENABLE_ISOLATED_STORAGE) return;
Svet Ganov6ee871e2015-07-10 14:29:33 -07003946 final int mountMode = getExternalStorageMountMode(uid, packageName);
3947 remountUidExternalStorage(uid, mountMode);
3948 }
3949
3950 @Override
3951 public int getExternalStorageMountMode(int uid, String packageName) {
Sudheer Shanka3a0df3b2018-12-12 12:43:43 -08003952 if (ENABLE_ISOLATED_STORAGE) {
3953 return getMountMode(uid, packageName);
3954 }
Svet Ganov6ee871e2015-07-10 14:29:33 -07003955 // No locking - CopyOnWriteArrayList
3956 int mountMode = Integer.MAX_VALUE;
3957 for (ExternalStorageMountPolicy policy : mPolicies) {
3958 final int policyMode = policy.getMountMode(uid, packageName);
3959 if (policyMode == Zygote.MOUNT_EXTERNAL_NONE) {
3960 return Zygote.MOUNT_EXTERNAL_NONE;
3961 }
3962 mountMode = Math.min(mountMode, policyMode);
3963 }
3964 if (mountMode == Integer.MAX_VALUE) {
3965 return Zygote.MOUNT_EXTERNAL_NONE;
3966 }
3967 return mountMode;
3968 }
3969
Risanaec0ee72018-10-31 10:10:12 +09003970 @Override
3971 public void addResetListener(StorageManagerInternal.ResetListener listener) {
3972 synchronized (mResetListeners) {
3973 mResetListeners.add(listener);
3974 }
3975 }
3976
3977 public void onReset(IVold vold) {
3978 synchronized (mResetListeners) {
3979 for (StorageManagerInternal.ResetListener listener : mResetListeners) {
3980 listener.onReset(vold);
3981 }
3982 }
3983 }
3984
Svet Ganov6ee871e2015-07-10 14:29:33 -07003985 public boolean hasExternalStorage(int uid, String packageName) {
Amith Yamasani2bd5cff2015-07-22 14:42:31 -07003986 // No need to check for system uid. This avoids a deadlock between
3987 // PackageManagerService and AppOpsService.
3988 if (uid == Process.SYSTEM_UID) {
3989 return true;
3990 }
Sudheer Shanka3a0df3b2018-12-12 12:43:43 -08003991 if (ENABLE_ISOLATED_STORAGE) {
3992 return getMountMode(uid, packageName) != Zygote.MOUNT_EXTERNAL_NONE;
3993 }
Svet Ganov6ee871e2015-07-10 14:29:33 -07003994 // No locking - CopyOnWriteArrayList
3995 for (ExternalStorageMountPolicy policy : mPolicies) {
3996 final boolean policyHasStorage = policy.hasExternalStorage(uid, packageName);
3997 if (!policyHasStorage) {
3998 return false;
3999 }
4000 }
4001 return true;
4002 }
Sudheer Shanka8ff30b12018-08-06 17:29:44 -07004003
4004 @Override
Sudheer Shanka584b0682018-10-04 16:26:16 -07004005 public void prepareSandboxForApp(String packageName, int appId, String sharedUserId,
Sudheer Shanka8ff30b12018-08-06 17:29:44 -07004006 int userId) {
4007 final String sandboxId;
4008 synchronized (mPackagesLock) {
Sudheer Shanka2ac25a92018-10-25 10:59:32 -07004009 final ArraySet<String> userPackages = mPackages.get(userId);
Sudheer Shanka8ff30b12018-08-06 17:29:44 -07004010 // If userPackages is empty, it means the user is not started yet, so no need to
4011 // do anything now.
Sudheer Shanka2ac25a92018-10-25 10:59:32 -07004012 if (userPackages == null || userPackages.contains(packageName)) {
Sudheer Shanka8ff30b12018-08-06 17:29:44 -07004013 return;
4014 }
4015 userPackages.add(packageName);
Sudheer Shanka03fd40b2019-02-06 12:39:14 -08004016 sandboxId = StorageManagerService.this.getSandboxId(packageName, sharedUserId);
Sudheer Shanka8ff30b12018-08-06 17:29:44 -07004017 }
4018
4019 try {
Sudheer Shanka584b0682018-10-04 16:26:16 -07004020 mVold.prepareSandboxForApp(packageName, appId, sandboxId, userId);
4021 } catch (Exception e) {
4022 Slog.wtf(TAG, e);
4023 }
4024 }
4025
4026 @Override
Sudheer Shanka2ac25a92018-10-25 10:59:32 -07004027 public void destroySandboxForApp(String packageName, String sharedUserId, int userId) {
Sudheer Shanka584b0682018-10-04 16:26:16 -07004028 if (!ENABLE_ISOLATED_STORAGE) {
4029 return;
4030 }
Sudheer Shanka03fd40b2019-02-06 12:39:14 -08004031 final String sandboxId = StorageManagerService.this.getSandboxId(
4032 packageName, sharedUserId);
Sudheer Shanka584b0682018-10-04 16:26:16 -07004033 synchronized (mPackagesLock) {
Sudheer Shanka2ac25a92018-10-25 10:59:32 -07004034 final ArraySet<String> userPackages = mPackages.get(userId);
4035 // If the userPackages is null, it means the user is not started but we still
4036 // need to delete the sandbox data though.
4037 if (userPackages != null) {
4038 userPackages.remove(packageName);
Sudheer Shanka584b0682018-10-04 16:26:16 -07004039 }
4040 }
4041 try {
Sudheer Shanka2ac25a92018-10-25 10:59:32 -07004042 mVold.destroySandboxForApp(packageName, sandboxId, userId);
Sudheer Shanka8ff30b12018-08-06 17:29:44 -07004043 } catch (Exception e) {
4044 Slog.wtf(TAG, e);
4045 }
4046 }
Sudheer Shanka3f0645b2018-09-18 13:07:59 -07004047
4048 @Override
4049 public String[] getVisibleVolumesForUser(int userId) {
4050 final ArrayList<String> visibleVolsForUser = new ArrayList<>();
4051 for (int i = mVisibleVols.size() - 1; i >= 0; --i) {
4052 final VolumeInfo vol = mVisibleVols.get(i);
4053 if (vol.isVisibleForUser(userId)) {
4054 visibleVolsForUser.add(getVolumeLabel(vol));
4055 }
4056 }
4057 return visibleVolsForUser.toArray(new String[visibleVolsForUser.size()]);
4058 }
4059
Sudheer Shanka03fd40b2019-02-06 12:39:14 -08004060 @Override
4061 public String getSandboxId(String packageName) {
4062 return StorageManagerService.this.getSandboxId(packageName,
4063 mPmInternal.getSharedUserIdForPackage(packageName));
4064 }
4065
Sudheer Shanka3f0645b2018-09-18 13:07:59 -07004066 private String getVolumeLabel(VolumeInfo vol) {
4067 // STOPSHIP: Label needs to part of VolumeInfo and need to be passed on from vold
4068 switch (vol.getType()) {
4069 case VolumeInfo.TYPE_EMULATED:
4070 return "emulated";
4071 case VolumeInfo.TYPE_PUBLIC:
4072 return vol.fsUuid == null ? vol.id : vol.fsUuid;
4073 default:
4074 return null;
4075 }
4076 }
Svet Ganov6ee871e2015-07-10 14:29:33 -07004077 }
Jeff Sharkeyfa23c5a2011-08-09 21:44:24 -07004078}