blob: ada3947477de69b413473710c38bc0d52b4f1e2f [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
Jeff Sharkeyab15c392016-05-05 11:45:01 -0600350 private volatile int mCurrentUserId = UserHandle.USER_SYSTEM;
351
Daichi Hirono9fb00182016-11-08 14:12:17 +0900352 /** Holding lock for AppFuse business */
353 private final Object mAppFuseLock = new Object();
354
355 @GuardedBy("mAppFuseLock")
356 private int mNextAppFuseName = 0;
357
358 @GuardedBy("mAppFuseLock")
Daichi Hironoe56740d2017-02-02 13:56:45 +0900359 private AppFuseBridge mAppFuseBridge = null;
Daichi Hirono9fb00182016-11-08 14:12:17 +0900360
Jeff Sharkeyef10ee02015-07-05 14:17:27 -0700361 private VolumeInfo findVolumeByIdOrThrow(String id) {
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700362 synchronized (mLock) {
363 final VolumeInfo vol = mVolumes.get(id);
364 if (vol != null) {
365 return vol;
366 }
367 }
368 throw new IllegalArgumentException("No volume found for ID " + id);
369 }
370
Jeff Sharkeyef10ee02015-07-05 14:17:27 -0700371 private String findVolumeIdForPathOrThrow(String path) {
Jeff Sharkey48877892015-03-18 11:27:19 -0700372 synchronized (mLock) {
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -0700373 for (int i = 0; i < mVolumes.size(); i++) {
374 final VolumeInfo vol = mVolumes.valueAt(i);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700375 if (vol.path != null && path.startsWith(vol.path)) {
376 return vol.id;
Jeff Sharkey48877892015-03-18 11:27:19 -0700377 }
378 }
379 }
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700380 throw new IllegalArgumentException("No volume found for path " + path);
Jeff Sharkey48877892015-03-18 11:27:19 -0700381 }
382
Jeff Sharkeye8a4b662015-06-27 15:43:45 -0700383 private VolumeRecord findRecordForPath(String path) {
384 synchronized (mLock) {
385 for (int i = 0; i < mVolumes.size(); i++) {
386 final VolumeInfo vol = mVolumes.valueAt(i);
387 if (vol.path != null && path.startsWith(vol.path)) {
388 return mRecords.get(vol.fsUuid);
389 }
390 }
391 }
392 return null;
393 }
394
395 private String scrubPath(String path) {
396 if (path.startsWith(Environment.getDataDirectory().getAbsolutePath())) {
397 return "internal";
398 }
399 final VolumeRecord rec = findRecordForPath(path);
400 if (rec == null || rec.createdMillis == 0) {
401 return "unknown";
402 } else {
403 return "ext:" + (int) ((System.currentTimeMillis() - rec.createdMillis)
404 / DateUtils.WEEK_IN_MILLIS) + "w";
405 }
406 }
407
Jeff Sharkeyef10ee02015-07-05 14:17:27 -0700408 private @Nullable VolumeInfo findStorageForUuid(String volumeUuid) {
Jeff Sharkey275e3e42015-04-24 16:10:32 -0700409 final StorageManager storage = mContext.getSystemService(StorageManager.class);
410 if (Objects.equals(StorageManager.UUID_PRIVATE_INTERNAL, volumeUuid)) {
Jeff Sharkeyef10ee02015-07-05 14:17:27 -0700411 return storage.findVolumeById(VolumeInfo.ID_EMULATED_INTERNAL);
Jeff Sharkey275e3e42015-04-24 16:10:32 -0700412 } else if (Objects.equals(StorageManager.UUID_PRIMARY_PHYSICAL, volumeUuid)) {
413 return storage.getPrimaryPhysicalVolume();
414 } else {
415 return storage.findEmulatedForPrivate(storage.findVolumeByUuid(volumeUuid));
416 }
417 }
418
Jeff Sharkeye8a4b662015-06-27 15:43:45 -0700419 private boolean shouldBenchmark() {
420 final long benchInterval = Settings.Global.getLong(mContext.getContentResolver(),
421 Settings.Global.STORAGE_BENCHMARK_INTERVAL, DateUtils.WEEK_IN_MILLIS);
Jeff Sharkeye83d8a92015-09-09 14:53:38 -0700422 if (benchInterval == -1) {
423 return false;
424 } else if (benchInterval == 0) {
425 return true;
426 }
427
Jeff Sharkeye8a4b662015-06-27 15:43:45 -0700428 synchronized (mLock) {
429 for (int i = 0; i < mVolumes.size(); i++) {
430 final VolumeInfo vol = mVolumes.valueAt(i);
431 final VolumeRecord rec = mRecords.get(vol.fsUuid);
Jeff Sharkeye83d8a92015-09-09 14:53:38 -0700432 if (vol.isMountedWritable() && rec != null) {
Jeff Sharkeye8a4b662015-06-27 15:43:45 -0700433 final long benchAge = System.currentTimeMillis() - rec.lastBenchMillis;
434 if (benchAge >= benchInterval) {
435 return true;
436 }
437 }
438 }
439 return false;
440 }
441 }
442
Jeff Sharkeyeba260d2015-04-19 14:35:16 -0700443 private CountDownLatch findOrCreateDiskScanLatch(String diskId) {
444 synchronized (mLock) {
445 CountDownLatch latch = mDiskScanLatches.get(diskId);
446 if (latch == null) {
447 latch = new CountDownLatch(1);
448 mDiskScanLatches.put(diskId, latch);
449 }
450 return latch;
451 }
452 }
453
Paul Lawrence8e397362014-01-27 15:22:30 -0800454 /** List of crypto types.
455 * These must match CRYPT_TYPE_XXX in cryptfs.h AND their
456 * corresponding commands in CommandListener.cpp */
457 public static final String[] CRYPTO_TYPES
458 = { "password", "default", "pattern", "pin" };
459
Brian Carlstrom7395a8a2014-04-28 22:11:01 -0700460 private final Context mContext;
Jeff Sharkey5d0c55c2019-01-24 14:32:31 -0700461 private final ContentResolver mResolver;
Jeff Sharkeycd575992016-03-29 14:12:49 -0600462
Jeff Sharkey1019de92017-09-06 13:47:03 -0600463 private volatile IVold mVold;
Jin Qian12690d52017-10-13 18:17:04 -0700464 private volatile IStoraged mStoraged;
Jeff Sharkey1019de92017-09-06 13:47:03 -0600465
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700466 private volatile boolean mSystemReady = false;
Yasuhiro Matsuda87a38b52015-07-24 22:10:16 +0900467 private volatile boolean mBootCompleted = false;
Jeff Sharkey48877892015-03-18 11:27:19 -0700468 private volatile boolean mDaemonConnected = false;
Jeff Sharkey9765e442017-12-14 22:15:14 -0700469 private volatile boolean mSecureKeyguardShowing = true;
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700470
Sudheer Shanka0a541a52018-07-31 13:21:11 -0700471 private PackageManagerInternal mPmInternal;
Jeff Sharkey5790af02018-08-13 17:42:54 -0600472 private UserManagerInternal mUmInternal;
Sudheer Shanka87915d62018-11-06 10:57:35 -0800473 private ActivityManagerInternal mAmInternal;
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700474
Sudheer Shanka3a0df3b2018-12-12 12:43:43 -0800475 private IPackageManager mIPackageManager;
476 private IAppOpsService mIAppOpsService;
477
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700478 private final Callbacks mCallbacks;
Jeff Sharkeyb9fe5372015-12-03 15:23:08 -0700479 private final LockPatternUtils mLockPatternUtils;
Jeff Sharkey48877892015-03-18 11:27:19 -0700480
San Mehat6cdd9c02010-02-09 14:45:20 -0800481 /**
Kenny Root3b1abba2010-10-13 15:00:07 -0700482 * The size of the crypto algorithm key in bits for OBB files. Currently
483 * Twofish is used which takes 128-bit keys.
484 */
485 private static final int CRYPTO_ALGORITHM_KEY_SIZE = 128;
486
487 /**
488 * The number of times to run SHA1 in the PBKDF2 function for OBB files.
489 * 1024 is reasonably secure and not too slow.
490 */
491 private static final int PBKDF2_HASH_ROUNDS = 1024;
492
493 /**
Kenny Roota02b8b02010-08-05 16:14:17 -0700494 * Mounted OBB tracking information. Used to track the current state of all
495 * OBBs.
Kenny Root02c87302010-07-01 08:10:18 -0700496 */
Kenny Root735de3b2010-09-30 14:11:39 -0700497 final private Map<IBinder, List<ObbState>> mObbMounts = new HashMap<IBinder, List<ObbState>>();
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700498
499 /** Map from raw paths to {@link ObbState}. */
Kenny Roota02b8b02010-08-05 16:14:17 -0700500 final private Map<String, ObbState> mObbPathToStateMap = new HashMap<String, ObbState>();
501
Svet Ganov6ee871e2015-07-10 14:29:33 -0700502 // Not guarded by a lock.
Sudheer Shanka2250d562016-11-07 15:41:02 -0800503 private final StorageManagerInternalImpl mStorageManagerInternal
504 = new StorageManagerInternalImpl();
Svet Ganov6ee871e2015-07-10 14:29:33 -0700505
Kenny Roota02b8b02010-08-05 16:14:17 -0700506 class ObbState implements IBinder.DeathRecipient {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700507 public ObbState(String rawPath, String canonicalPath, int callingUid,
Jeff Sharkey41cd6812017-09-11 10:32:17 -0600508 IObbActionListener token, int nonce, String volId) {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700509 this.rawPath = rawPath;
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700510 this.canonicalPath = canonicalPath;
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700511 this.ownerGid = UserHandle.getSharedAppGid(callingUid);
Kenny Rootaf9d6672010-10-08 09:21:39 -0700512 this.token = token;
513 this.nonce = nonce;
Jeff Sharkey41cd6812017-09-11 10:32:17 -0600514 this.volId = volId;
Kenny Roota02b8b02010-08-05 16:14:17 -0700515 }
516
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700517 final String rawPath;
518 final String canonicalPath;
Kenny Roota02b8b02010-08-05 16:14:17 -0700519
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700520 final int ownerGid;
Kenny Roota02b8b02010-08-05 16:14:17 -0700521
Kenny Rootaf9d6672010-10-08 09:21:39 -0700522 // Token of remote Binder caller
523 final IObbActionListener token;
524
525 // Identifier to pass back to the token
526 final int nonce;
Kenny Roota02b8b02010-08-05 16:14:17 -0700527
Jeff Sharkey41cd6812017-09-11 10:32:17 -0600528 String volId;
529
Kenny Root735de3b2010-09-30 14:11:39 -0700530 public IBinder getBinder() {
531 return token.asBinder();
532 }
533
Kenny Roota02b8b02010-08-05 16:14:17 -0700534 @Override
535 public void binderDied() {
536 ObbAction action = new UnmountObbAction(this, true);
537 mObbActionHandler.sendMessage(mObbActionHandler.obtainMessage(OBB_RUN_ACTION, action));
Kenny Root735de3b2010-09-30 14:11:39 -0700538 }
Kenny Roota02b8b02010-08-05 16:14:17 -0700539
Kenny Root5919ac62010-10-05 09:49:40 -0700540 public void link() throws RemoteException {
541 getBinder().linkToDeath(this, 0);
542 }
543
544 public void unlink() {
Kenny Root735de3b2010-09-30 14:11:39 -0700545 getBinder().unlinkToDeath(this, 0);
Kenny Roota02b8b02010-08-05 16:14:17 -0700546 }
Kenny Root38cf8862010-09-26 14:18:51 -0700547
548 @Override
549 public String toString() {
550 StringBuilder sb = new StringBuilder("ObbState{");
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700551 sb.append("rawPath=").append(rawPath);
552 sb.append(",canonicalPath=").append(canonicalPath);
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700553 sb.append(",ownerGid=").append(ownerGid);
554 sb.append(",token=").append(token);
555 sb.append(",binder=").append(getBinder());
Jeff Sharkey41cd6812017-09-11 10:32:17 -0600556 sb.append(",volId=").append(volId);
Kenny Root38cf8862010-09-26 14:18:51 -0700557 sb.append('}');
558 return sb.toString();
559 }
Kenny Roota02b8b02010-08-05 16:14:17 -0700560 }
561
562 // OBB Action Handler
563 final private ObbActionHandler mObbActionHandler;
564
565 // OBB action handler messages
566 private static final int OBB_RUN_ACTION = 1;
Sudheer Shanka25469aa2018-08-27 15:50:23 -0700567 private static final int OBB_FLUSH_MOUNT_STATE = 2;
Kenny Root02c87302010-07-01 08:10:18 -0700568
Christopher Tate7265abe2014-11-21 13:54:45 -0800569 // Last fstrim operation tracking
570 private static final String LAST_FSTRIM_FILE = "last-fstrim";
571 private final File mLastMaintenanceFile;
572 private long mLastMaintenance;
573
Kenny Root02c87302010-07-01 08:10:18 -0700574 // Handler messages
Jeff Sharkey48877892015-03-18 11:27:19 -0700575 private static final int H_SYSTEM_READY = 1;
576 private static final int H_DAEMON_CONNECTED = 2;
577 private static final int H_SHUTDOWN = 3;
578 private static final int H_FSTRIM = 4;
579 private static final int H_VOLUME_MOUNT = 5;
580 private static final int H_VOLUME_BROADCAST = 6;
Jeff Sharkeyabc3e852015-08-03 14:41:13 -0700581 private static final int H_INTERNAL_BROADCAST = 7;
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700582 private static final int H_VOLUME_UNMOUNT = 8;
Jeff Sharkey5a9bb742015-11-03 10:15:57 -0800583 private static final int H_PARTITION_FORGET = 9;
584 private static final int H_RESET = 10;
Jin Qiana85b9912017-10-17 15:48:18 -0700585 private static final int H_RUN_IDLE_MAINT = 11;
586 private static final int H_ABORT_IDLE_MAINT = 12;
Suchi Amalapurapu6ffce2e2010-03-08 14:48:40 -0800587
Sudheer Shanka2250d562016-11-07 15:41:02 -0800588 class StorageManagerServiceHandler extends Handler {
589 public StorageManagerServiceHandler(Looper looper) {
Jeff Sharkey48877892015-03-18 11:27:19 -0700590 super(looper);
Daniel Sandler5f27ef42010-03-16 15:42:02 -0400591 }
592
Jason parks5af0b912010-11-29 09:05:25 -0600593 @Override
Suchi Amalapurapuc42e29e2010-02-22 16:03:53 -0800594 public void handleMessage(Message msg) {
595 switch (msg.what) {
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700596 case H_SYSTEM_READY: {
Jeff Sharkey48877892015-03-18 11:27:19 -0700597 handleSystemReady();
598 break;
599 }
600 case H_DAEMON_CONNECTED: {
601 handleDaemonConnected();
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700602 break;
603 }
Christopher Tated417d622013-08-19 16:14:25 -0700604 case H_FSTRIM: {
Christopher Tated417d622013-08-19 16:14:25 -0700605 Slog.i(TAG, "Running fstrim idle maintenance");
Christopher Tate7265abe2014-11-21 13:54:45 -0800606
607 // Remember when we kicked it off
608 try {
609 mLastMaintenance = System.currentTimeMillis();
610 mLastMaintenanceFile.setLastModified(mLastMaintenance);
611 } catch (Exception e) {
612 Slog.e(TAG, "Unable to record last fstrim!");
613 }
614
Jeff Sharkeyb302c542017-09-15 12:57:59 -0600615 // TODO: Reintroduce shouldBenchmark() test
Jeff Sharkey7e19f532017-11-06 13:54:11 -0700616 fstrim(0, null);
Christopher Tate7265abe2014-11-21 13:54:45 -0800617
Christopher Tated417d622013-08-19 16:14:25 -0700618 // invoke the completion callback, if any
Jeff Sharkeye8a4b662015-06-27 15:43:45 -0700619 // TODO: fstrim is non-blocking, so remove this useless callback
Christopher Tated417d622013-08-19 16:14:25 -0700620 Runnable callback = (Runnable) msg.obj;
621 if (callback != null) {
622 callback.run();
623 }
624 break;
625 }
Jeff Sharkey48877892015-03-18 11:27:19 -0700626 case H_SHUTDOWN: {
Sudheer Shanka2250d562016-11-07 15:41:02 -0800627 final IStorageShutdownObserver obs = (IStorageShutdownObserver) msg.obj;
Jeff Sharkey48877892015-03-18 11:27:19 -0700628 boolean success = false;
629 try {
Jeff Sharkey54402792017-09-15 16:05:19 -0600630 mVold.shutdown();
631 success = true;
Jeff Sharkeyace874b2017-09-07 15:27:33 -0600632 } catch (Exception e) {
633 Slog.wtf(TAG, e);
Jeff Sharkey48877892015-03-18 11:27:19 -0700634 }
635 if (obs != null) {
636 try {
637 obs.onShutDownComplete(success ? 0 : -1);
Jeff Sharkeyace874b2017-09-07 15:27:33 -0600638 } catch (Exception ignored) {
Jeff Sharkey48877892015-03-18 11:27:19 -0700639 }
640 }
641 break;
642 }
643 case H_VOLUME_MOUNT: {
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -0700644 final VolumeInfo vol = (VolumeInfo) msg.obj;
Jeff Sharkey2e606d72015-07-27 14:19:54 -0700645 if (isMountDisallowed(vol)) {
646 Slog.i(TAG, "Ignoring mount " + vol.getId() + " due to policy");
647 break;
648 }
Sudheer Shanka3f0645b2018-09-18 13:07:59 -0700649 mount(vol);
Jeff Sharkey48877892015-03-18 11:27:19 -0700650 break;
651 }
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700652 case H_VOLUME_UNMOUNT: {
653 final VolumeInfo vol = (VolumeInfo) msg.obj;
Sudheer Shanka3f0645b2018-09-18 13:07:59 -0700654 unmount(vol);
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700655 break;
656 }
Jeff Sharkey48877892015-03-18 11:27:19 -0700657 case H_VOLUME_BROADCAST: {
658 final StorageVolume userVol = (StorageVolume) msg.obj;
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700659 final String envState = userVol.getState();
660 Slog.d(TAG, "Volume " + userVol.getId() + " broadcasting " + envState + " to "
Jeff Sharkey48877892015-03-18 11:27:19 -0700661 + userVol.getOwner());
662
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700663 final String action = VolumeInfo.getBroadcastForEnvironment(envState);
Jeff Sharkey48877892015-03-18 11:27:19 -0700664 if (action != null) {
665 final Intent intent = new Intent(action,
666 Uri.fromFile(userVol.getPathFile()));
667 intent.putExtra(StorageVolume.EXTRA_STORAGE_VOLUME, userVol);
Jeff Sharkey082f83b2017-03-26 14:34:47 -0600668 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT
669 | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
Jeff Sharkey48877892015-03-18 11:27:19 -0700670 mContext.sendBroadcastAsUser(intent, userVol.getOwner());
671 }
672 break;
673 }
Jeff Sharkeyabc3e852015-08-03 14:41:13 -0700674 case H_INTERNAL_BROADCAST: {
675 // Internal broadcasts aimed at system components, not for
676 // third-party apps.
677 final Intent intent = (Intent) msg.obj;
678 mContext.sendBroadcastAsUser(intent, UserHandle.ALL,
679 android.Manifest.permission.WRITE_MEDIA_STORAGE);
Jeff Sharkey5a9bb742015-11-03 10:15:57 -0800680 break;
681 }
682 case H_PARTITION_FORGET: {
Jeff Sharkeydb4b6192017-10-24 11:08:50 -0600683 final VolumeRecord rec = (VolumeRecord) msg.obj;
684 forgetPartition(rec.partGuid, rec.fsUuid);
Jeff Sharkey5a9bb742015-11-03 10:15:57 -0800685 break;
686 }
687 case H_RESET: {
688 resetIfReadyAndConnected();
689 break;
Jeff Sharkeyabc3e852015-08-03 14:41:13 -0700690 }
Jin Qiana85b9912017-10-17 15:48:18 -0700691 case H_RUN_IDLE_MAINT: {
692 Slog.i(TAG, "Running idle maintenance");
693 runIdleMaint((Runnable)msg.obj);
694 break;
695 }
696 case H_ABORT_IDLE_MAINT: {
697 Slog.i(TAG, "Aborting idle maintenance");
698 abortIdleMaint((Runnable)msg.obj);
699 break;
700 }
701
Suchi Amalapurapuc42e29e2010-02-22 16:03:53 -0800702 }
703 }
Jeff Sharkey48877892015-03-18 11:27:19 -0700704 }
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700705
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700706 private final Handler mHandler;
Suchi Amalapurapuc42e29e2010-02-22 16:03:53 -0800707
Jeff Sharkeybcd262d2015-06-10 09:41:17 -0700708 private BroadcastReceiver mUserReceiver = new BroadcastReceiver() {
709 @Override
710 public void onReceive(Context context, Intent intent) {
711 final String action = intent.getAction();
712 final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700713 Preconditions.checkArgument(userId >= 0);
Jeff Sharkeybcd262d2015-06-10 09:41:17 -0700714
715 try {
716 if (Intent.ACTION_USER_ADDED.equals(action)) {
717 final UserManager um = mContext.getSystemService(UserManager.class);
718 final int userSerialNumber = um.getUserSerialNumber(userId);
Jeff Sharkey54402792017-09-15 16:05:19 -0600719 mVold.onUserAdded(userId, userSerialNumber);
Jeff Sharkeybcd262d2015-06-10 09:41:17 -0700720 } else if (Intent.ACTION_USER_REMOVED.equals(action)) {
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700721 synchronized (mVolumes) {
722 final int size = mVolumes.size();
723 for (int i = 0; i < size; i++) {
724 final VolumeInfo vol = mVolumes.valueAt(i);
725 if (vol.mountUserId == userId) {
726 vol.mountUserId = UserHandle.USER_NULL;
727 mHandler.obtainMessage(H_VOLUME_UNMOUNT, vol).sendToTarget();
728 }
729 }
730 }
Jeff Sharkey54402792017-09-15 16:05:19 -0600731 mVold.onUserRemoved(userId);
Jeff Sharkeybcd262d2015-06-10 09:41:17 -0700732 }
Jeff Sharkeyace874b2017-09-07 15:27:33 -0600733 } catch (Exception e) {
734 Slog.wtf(TAG, e);
Jeff Sharkeybcd262d2015-06-10 09:41:17 -0700735 }
736 }
737 };
738
Jeff Sharkeyedcdaf62015-07-09 09:45:36 -0700739 private void waitForLatch(CountDownLatch latch, String condition, long timeoutMillis)
740 throws TimeoutException {
741 final long startMillis = SystemClock.elapsedRealtime();
Jeff Sharkeyeba260d2015-04-19 14:35:16 -0700742 while (true) {
Kenny Root51a573c2012-05-17 13:30:28 -0700743 try {
744 if (latch.await(5000, TimeUnit.MILLISECONDS)) {
San Mehat207e5382010-02-04 20:46:54 -0800745 return;
Kenny Root51a573c2012-05-17 13:30:28 -0700746 } else {
747 Slog.w(TAG, "Thread " + Thread.currentThread().getName()
Jeff Sharkey48877892015-03-18 11:27:19 -0700748 + " still waiting for " + condition + "...");
San Mehat207e5382010-02-04 20:46:54 -0800749 }
Kenny Root51a573c2012-05-17 13:30:28 -0700750 } catch (InterruptedException e) {
Jeff Sharkeyeba260d2015-04-19 14:35:16 -0700751 Slog.w(TAG, "Interrupt while waiting for " + condition);
San Mehat207e5382010-02-04 20:46:54 -0800752 }
Jeff Sharkeyedcdaf62015-07-09 09:45:36 -0700753 if (timeoutMillis > 0 && SystemClock.elapsedRealtime() > startMillis + timeoutMillis) {
754 throw new TimeoutException("Thread " + Thread.currentThread().getName()
755 + " gave up waiting for " + condition + " after " + timeoutMillis + "ms");
756 }
San Mehat207e5382010-02-04 20:46:54 -0800757 }
San Mehat1f6301e2010-01-07 22:40:27 -0800758 }
Kenny Root02c87302010-07-01 08:10:18 -0700759
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700760 private void handleSystemReady() {
Jeff Sharkey8924e872015-11-30 12:52:10 -0700761 initIfReadyAndConnected();
Jeff Sharkey5a9bb742015-11-03 10:15:57 -0800762 resetIfReadyAndConnected();
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700763
Jeff Sharkey48877892015-03-18 11:27:19 -0700764 // Start scheduling nominally-daily fstrim operations
Christopher Tate115afda2014-06-06 19:06:26 -0700765 MountServiceIdler.scheduleIdlePass(mContext);
Daniel Colascione766b6322018-01-08 19:10:36 -0800766
767 // Toggle zram-enable system property in response to settings
768 mContext.getContentResolver().registerContentObserver(
769 Settings.Global.getUriFor(Settings.Global.ZRAM_ENABLED),
770 false /*notifyForDescendants*/,
771 new ContentObserver(null /* current thread */) {
772 @Override
773 public void onChange(boolean selfChange) {
774 refreshZramSettings();
775 }
776 });
777 refreshZramSettings();
Jeff Sharkeyb0c363b22018-12-15 11:53:03 -0700778
Srinivas Paladuguc8261752019-01-09 10:54:52 -0800779 // Schedule zram writeback unless zram is disabled by persist.sys.zram_enabled
780 String zramPropValue = SystemProperties.get(ZRAM_ENABLED_PROPERTY);
781 if (!zramPropValue.equals("0")
782 && mContext.getResources().getBoolean(
783 com.android.internal.R.bool.config_zramWriteback)) {
784 ZramWriteback.scheduleZramWriteback(mContext);
785 }
Jeff Sharkeyb0c363b22018-12-15 11:53:03 -0700786 // Toggle isolated-enable system property in response to settings
787 mContext.getContentResolver().registerContentObserver(
788 Settings.Global.getUriFor(Settings.Global.ISOLATED_STORAGE_REMOTE),
789 false /*notifyForDescendants*/,
790 new ContentObserver(null /* current thread */) {
791 @Override
792 public void onChange(boolean selfChange) {
793 refreshIsolatedStorageSettings();
794 }
795 });
Jeff Sharkey5d0c55c2019-01-24 14:32:31 -0700796 // For now, simply clone property when it changes
797 DeviceConfig.addOnPropertyChangedListener(DeviceConfig.Storage.NAMESPACE,
798 mContext.getMainExecutor(), (namespace, name, value) -> {
Jeff Sharkey8b499a02019-01-28 13:31:50 -0700799 refreshIsolatedStorageSettings();
Jeff Sharkey5d0c55c2019-01-24 14:32:31 -0700800 });
Jeff Sharkeyb0c363b22018-12-15 11:53:03 -0700801 refreshIsolatedStorageSettings();
Daniel Colascione766b6322018-01-08 19:10:36 -0800802 }
803
804 /**
805 * Update the zram_enabled system property (which init reads to
806 * decide whether to enable zram) to reflect the zram_enabled
807 * preference (which we can change for experimentation purposes).
808 */
809 private void refreshZramSettings() {
810 String propertyValue = SystemProperties.get(ZRAM_ENABLED_PROPERTY);
811 if ("".equals(propertyValue)) {
812 return; // System doesn't have zram toggling support
813 }
814 String desiredPropertyValue =
815 Settings.Global.getInt(mContext.getContentResolver(),
816 Settings.Global.ZRAM_ENABLED,
817 1) != 0
818 ? "1" : "0";
819 if (!desiredPropertyValue.equals(propertyValue)) {
820 // Avoid redundant disk writes by setting only if we're
821 // changing the property value. There's no race: we're the
822 // sole writer.
823 SystemProperties.set(ZRAM_ENABLED_PROPERTY, desiredPropertyValue);
Srinivas Paladuguc8261752019-01-09 10:54:52 -0800824 // Schedule writeback only if zram is being enabled.
825 if (desiredPropertyValue.equals("1")
826 && mContext.getResources().getBoolean(
827 com.android.internal.R.bool.config_zramWriteback)) {
828 ZramWriteback.scheduleZramWriteback(mContext);
829 }
Daniel Colascione766b6322018-01-08 19:10:36 -0800830 }
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700831 }
832
Jeff Sharkeyb0c363b22018-12-15 11:53:03 -0700833 private void refreshIsolatedStorageSettings() {
Jeff Sharkey8b499a02019-01-28 13:31:50 -0700834 // Always copy value from newer DeviceConfig location
835 Settings.Global.putString(mResolver,
836 Settings.Global.ISOLATED_STORAGE_REMOTE,
837 DeviceConfig.getProperty(DeviceConfig.Storage.NAMESPACE,
838 DeviceConfig.Storage.ISOLATED_STORAGE_ENABLED));
839
Jeff Sharkeyb0c363b22018-12-15 11:53:03 -0700840 final int local = Settings.Global.getInt(mContext.getContentResolver(),
841 Settings.Global.ISOLATED_STORAGE_LOCAL, 0);
842 final int remote = Settings.Global.getInt(mContext.getContentResolver(),
843 Settings.Global.ISOLATED_STORAGE_REMOTE, 0);
844
845 // Walk down precedence chain; we prefer local settings first, then
846 // remote settings, before finally falling back to hard-coded default.
847 final boolean res;
848 if (local == -1) {
849 res = false;
850 } else if (local == 1) {
851 res = true;
852 } else if (remote == -1) {
853 res = false;
854 } else if (remote == 1) {
855 res = true;
856 } else {
Jeff Sharkey06376802019-02-11 12:20:02 -0700857 res = true;
Jeff Sharkeyb0c363b22018-12-15 11:53:03 -0700858 }
859
860 Slog.d(TAG, "Isolated storage local flag " + local + " and remote flag "
861 + remote + " resolved to " + res);
862 SystemProperties.set(StorageManager.PROP_ISOLATED_STORAGE, Boolean.toString(res));
863 }
864
Jeff Sharkey14cbe522015-07-08 14:06:37 -0700865 /**
866 * MediaProvider has a ton of code that makes assumptions about storage
867 * paths never changing, so we outright kill them to pick up new state.
868 */
869 @Deprecated
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700870 private void killMediaProvider(List<UserInfo> users) {
871 if (users == null) return;
872
Jeff Sharkeyb3cf9532015-07-17 15:12:39 -0700873 final long token = Binder.clearCallingIdentity();
874 try {
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700875 for (UserInfo user : users) {
876 // System user does not have media provider, so skip.
877 if (user.isSystemOnly()) continue;
878
Jeff Sharkey5790af02018-08-13 17:42:54 -0600879 final ProviderInfo provider = mPmInternal.resolveContentProvider(
880 MediaStore.AUTHORITY, PackageManager.MATCH_DIRECT_BOOT_AWARE
Jeff Sharkey8a372a02016-03-16 16:25:45 -0600881 | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
882 user.id);
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700883 if (provider != null) {
Sudheer Shankadc589ac2016-11-10 15:30:17 -0800884 final IActivityManager am = ActivityManager.getService();
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700885 try {
Jeff Sharkey85f449e2016-06-23 09:26:00 -0600886 am.killApplication(provider.applicationInfo.packageName,
887 UserHandle.getAppId(provider.applicationInfo.uid),
888 UserHandle.USER_ALL, "vold reset");
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700889 // We only need to run this once. It will kill all users' media processes.
890 break;
891 } catch (RemoteException e) {
892 }
Jeff Sharkeyb3cf9532015-07-17 15:12:39 -0700893 }
Jeff Sharkey14cbe522015-07-08 14:06:37 -0700894 }
Jeff Sharkeyb3cf9532015-07-17 15:12:39 -0700895 } finally {
896 Binder.restoreCallingIdentity(token);
Jeff Sharkey14cbe522015-07-08 14:06:37 -0700897 }
898 }
899
Andreas Gampea36dc622018-02-05 17:19:22 -0800900 @GuardedBy("mLock")
Jeff Sharkey5a9bb742015-11-03 10:15:57 -0800901 private void addInternalVolumeLocked() {
Amith Yamasania7892482015-08-07 11:09:05 -0700902 // Create a stub volume that represents internal storage
903 final VolumeInfo internal = new VolumeInfo(VolumeInfo.ID_PRIVATE_INTERNAL,
904 VolumeInfo.TYPE_PRIVATE, null, null);
905 internal.state = VolumeInfo.STATE_MOUNTED;
906 internal.path = Environment.getDataDirectory().getAbsolutePath();
907 mVolumes.put(internal.id, internal);
908 }
909
Jeff Sharkey8924e872015-11-30 12:52:10 -0700910 private void initIfReadyAndConnected() {
911 Slog.d(TAG, "Thinking about init, mSystemReady=" + mSystemReady
912 + ", mDaemonConnected=" + mDaemonConnected);
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700913 if (mSystemReady && mDaemonConnected
Paul Lawrence20be5d62016-02-26 13:51:17 -0800914 && !StorageManager.isFileEncryptedNativeOnly()) {
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700915 // When booting a device without native support, make sure that our
916 // user directories are locked or unlocked based on the current
917 // emulation status.
Paul Lawrence20be5d62016-02-26 13:51:17 -0800918 final boolean initLocked = StorageManager.isFileEncryptedEmulatedOnly();
Paul Crowleyd94ab732016-02-15 06:44:51 +0000919 Slog.d(TAG, "Setting up emulation state, initlocked=" + initLocked);
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700920 final List<UserInfo> users = mContext.getSystemService(UserManager.class).getUsers();
Jeff Sharkey8924e872015-11-30 12:52:10 -0700921 for (UserInfo user : users) {
922 try {
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700923 if (initLocked) {
Jeff Sharkey54402792017-09-15 16:05:19 -0600924 mVold.lockUserKey(user.id);
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700925 } else {
Jeff Sharkey54402792017-09-15 16:05:19 -0600926 mVold.unlockUserKey(user.id, user.serialNumber, encodeBytes(null),
927 encodeBytes(null));
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700928 }
Jeff Sharkey43e12112017-09-12 16:31:45 -0600929 } catch (Exception e) {
930 Slog.wtf(TAG, e);
Jeff Sharkey8924e872015-11-30 12:52:10 -0700931 }
932 }
933 }
934 }
935
Jeff Sharkey5a9bb742015-11-03 10:15:57 -0800936 private void resetIfReadyAndConnected() {
Jeff Sharkey48877892015-03-18 11:27:19 -0700937 Slog.d(TAG, "Thinking about reset, mSystemReady=" + mSystemReady
938 + ", mDaemonConnected=" + mDaemonConnected);
939 if (mSystemReady && mDaemonConnected) {
Jeff Sharkey5a9bb742015-11-03 10:15:57 -0800940 final List<UserInfo> users = mContext.getSystemService(UserManager.class).getUsers();
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700941 killMediaProvider(users);
Jeff Sharkey14cbe522015-07-08 14:06:37 -0700942
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700943 final int[] systemUnlockedUsers;
Jeff Sharkey5a9bb742015-11-03 10:15:57 -0800944 synchronized (mLock) {
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700945 systemUnlockedUsers = mSystemUnlockedUsers;
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700946
Jeff Sharkey5a9bb742015-11-03 10:15:57 -0800947 mDisks.clear();
948 mVolumes.clear();
949
950 addInternalVolumeLocked();
951 }
Jeff Sharkey59d577a2015-04-11 21:27:21 -0700952
Jeff Sharkey48877892015-03-18 11:27:19 -0700953 try {
Jeff Sharkey54402792017-09-15 16:05:19 -0600954 mVold.reset();
Jeff Sharkeybcd262d2015-06-10 09:41:17 -0700955
956 // Tell vold about all existing and started users
Jeff Sharkeybcd262d2015-06-10 09:41:17 -0700957 for (UserInfo user : users) {
Jeff Sharkey54402792017-09-15 16:05:19 -0600958 mVold.onUserAdded(user.id, user.serialNumber);
Jeff Sharkeybcd262d2015-06-10 09:41:17 -0700959 }
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700960 for (int userId : systemUnlockedUsers) {
Sudheer Shanka2ac25a92018-10-25 10:59:32 -0700961 sendUserStartedCallback(userId);
Jin Qian12690d52017-10-13 18:17:04 -0700962 mStoraged.onUserStarted(userId);
Jeff Sharkey50a05452015-04-29 11:24:52 -0700963 }
Jeff Sharkey9765e442017-12-14 22:15:14 -0700964 mVold.onSecureKeyguardStateChanged(mSecureKeyguardShowing);
Risanaec0ee72018-10-31 10:10:12 +0900965 mStorageManagerInternal.onReset(mVold);
Jeff Sharkeyace874b2017-09-07 15:27:33 -0600966 } catch (Exception e) {
967 Slog.wtf(TAG, e);
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700968 }
969 }
Jeff Sharkey48877892015-03-18 11:27:19 -0700970 }
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700971
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700972 private void onUnlockUser(int userId) {
973 Slog.d(TAG, "onUnlockUser " + userId);
Jeff Sharkey48877892015-03-18 11:27:19 -0700974
975 // We purposefully block here to make sure that user-specific
976 // staging area is ready so it's ready for zygote-forked apps to
977 // bind mount against.
978 try {
Sudheer Shanka2ac25a92018-10-25 10:59:32 -0700979 sendUserStartedCallback(userId);
Jin Qian12690d52017-10-13 18:17:04 -0700980 mStoraged.onUserStarted(userId);
Jeff Sharkeyace874b2017-09-07 15:27:33 -0600981 } catch (Exception e) {
982 Slog.wtf(TAG, e);
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700983 }
Jeff Sharkey48877892015-03-18 11:27:19 -0700984
985 // Record user as started so newly mounted volumes kick off events
986 // correctly, then synthesize events for any already-mounted volumes.
yuanhuihuiefd1f122016-07-13 21:21:03 +0800987 synchronized (mLock) {
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -0700988 for (int i = 0; i < mVolumes.size(); i++) {
989 final VolumeInfo vol = mVolumes.valueAt(i);
Jeff Sharkey46349872015-07-28 10:49:47 -0700990 if (vol.isVisibleForRead(userId) && vol.isMountedReadable()) {
Svet Ganov6ee871e2015-07-10 14:29:33 -0700991 final StorageVolume userVol = vol.buildStorageVolume(mContext, userId, false);
Jeff Sharkey48877892015-03-18 11:27:19 -0700992 mHandler.obtainMessage(H_VOLUME_BROADCAST, userVol).sendToTarget();
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700993
Jeff Sharkey27de30d2015-04-18 16:20:27 -0700994 final String envState = VolumeInfo.getEnvironmentForState(vol.getState());
995 mCallbacks.notifyStorageStateChanged(userVol.getPath(), envState, envState);
Jeff Sharkey48877892015-03-18 11:27:19 -0700996 }
997 }
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700998 mSystemUnlockedUsers = ArrayUtils.appendInt(mSystemUnlockedUsers, userId);
Jeff Sharkey48877892015-03-18 11:27:19 -0700999 }
1000 }
1001
1002 private void onCleanupUser(int userId) {
1003 Slog.d(TAG, "onCleanupUser " + userId);
1004
1005 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06001006 mVold.onUserStopped(userId);
Jin Qian12690d52017-10-13 18:17:04 -07001007 mStoraged.onUserStopped(userId);
Jeff Sharkeyace874b2017-09-07 15:27:33 -06001008 } catch (Exception e) {
1009 Slog.wtf(TAG, e);
Jeff Sharkey48877892015-03-18 11:27:19 -07001010 }
1011
Sudheer Shanka2ac25a92018-10-25 10:59:32 -07001012 synchronized (mPackagesLock) {
1013 mPackages.delete(userId);
1014 }
1015
yuanhuihuiefd1f122016-07-13 21:21:03 +08001016 synchronized (mLock) {
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07001017 mSystemUnlockedUsers = ArrayUtils.removeInt(mSystemUnlockedUsers, userId);
Jeff Sharkey48877892015-03-18 11:27:19 -07001018 }
1019 }
Jeff Sharkeyb049e212012-09-07 23:16:01 -07001020
Sudheer Shanka2ac25a92018-10-25 10:59:32 -07001021 private void sendUserStartedCallback(int userId) throws Exception {
1022 if (!ENABLE_ISOLATED_STORAGE) {
1023 mVold.onUserStarted(userId, EmptyArray.STRING, EmptyArray.INT, EmptyArray.STRING);
1024 }
1025
1026 final String[] packages;
1027 final int[] appIds;
1028 final String[] sandboxIds;
1029 final SparseArray<String> sharedUserIds = mPmInternal.getAppsWithSharedUserIds();
1030 final List<ApplicationInfo> appInfos =
1031 mContext.getPackageManager().getInstalledApplicationsAsUser(
1032 PackageManager.MATCH_UNINSTALLED_PACKAGES, userId);
1033 synchronized (mPackagesLock) {
1034 final ArraySet<String> userPackages = new ArraySet<>();
1035 final ArrayMap<String, Integer> packageToAppId = new ArrayMap<>();
1036 for (int i = appInfos.size() - 1; i >= 0; --i) {
1037 final ApplicationInfo appInfo = appInfos.get(i);
1038 if (appInfo.isInstantApp()) {
1039 continue;
1040 }
1041 userPackages.add(appInfo.packageName);
1042 packageToAppId.put(appInfo.packageName, UserHandle.getAppId(appInfo.uid));
1043 }
1044 mPackages.put(userId, userPackages);
1045
1046 packages = new String[userPackages.size()];
1047 appIds = new int[userPackages.size()];
1048 sandboxIds = new String[userPackages.size()];
1049 for (int i = userPackages.size() - 1; i >= 0; --i) {
1050 packages[i] = userPackages.valueAt(i);
1051 appIds[i] = packageToAppId.get(packages[i]);
1052 sandboxIds[i] = getSandboxId(packages[i], sharedUserIds.get(appIds[i]));
1053 }
1054 }
1055 mVold.onUserStarted(userId, packages, appIds, sandboxIds);
1056 }
1057
Jeff Sharkey9765e442017-12-14 22:15:14 -07001058 @Override
1059 public void onAwakeStateChanged(boolean isAwake) {
1060 // Ignored
1061 }
1062
1063 @Override
1064 public void onKeyguardStateChanged(boolean isShowing) {
1065 // Push down current secure keyguard status so that we ignore malicious
1066 // USB devices while locked.
1067 mSecureKeyguardShowing = isShowing
1068 && mContext.getSystemService(KeyguardManager.class).isDeviceSecure();
1069 try {
1070 mVold.onSecureKeyguardStateChanged(mSecureKeyguardShowing);
1071 } catch (Exception e) {
1072 Slog.wtf(TAG, e);
1073 }
1074 }
1075
Christopher Tated417d622013-08-19 16:14:25 -07001076 void runIdleMaintenance(Runnable callback) {
1077 mHandler.sendMessage(mHandler.obtainMessage(H_FSTRIM, callback));
1078 }
1079
Christopher Tate7265abe2014-11-21 13:54:45 -08001080 // Binder entry point for kicking off an immediate fstrim
1081 @Override
1082 public void runMaintenance() {
Jeff Sharkey48877892015-03-18 11:27:19 -07001083 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
Christopher Tate7265abe2014-11-21 13:54:45 -08001084 runIdleMaintenance(null);
1085 }
1086
1087 @Override
1088 public long lastMaintenance() {
1089 return mLastMaintenance;
1090 }
1091
San Mehat4270e1e2010-01-29 05:32:19 -08001092 public void onDaemonConnected() {
Jeff Sharkey48877892015-03-18 11:27:19 -07001093 mDaemonConnected = true;
1094 mHandler.obtainMessage(H_DAEMON_CONNECTED).sendToTarget();
1095 }
1096
1097 private void handleDaemonConnected() {
Jeff Sharkey8924e872015-11-30 12:52:10 -07001098 initIfReadyAndConnected();
Jeff Sharkey5a9bb742015-11-03 10:15:57 -08001099 resetIfReadyAndConnected();
Jeff Sharkey48877892015-03-18 11:27:19 -07001100
Jeff Sharkey48877892015-03-18 11:27:19 -07001101 // On an encrypted device we can't see system properties yet, so pull
1102 // the system locale out of the mount service.
Inseob Kimc1246e62018-11-08 13:13:54 +09001103 if ("".equals(VoldProperties.encrypt_progress().orElse(""))) {
Jeff Sharkey48877892015-03-18 11:27:19 -07001104 copyLocaleFromMountService();
1105 }
San Mehat4270e1e2010-01-29 05:32:19 -08001106 }
1107
Elliott Hughesf839b4f2014-09-26 12:30:47 -07001108 private void copyLocaleFromMountService() {
1109 String systemLocale;
1110 try {
1111 systemLocale = getField(StorageManager.SYSTEM_LOCALE_KEY);
1112 } catch (RemoteException e) {
1113 return;
1114 }
1115 if (TextUtils.isEmpty(systemLocale)) {
1116 return;
1117 }
1118
1119 Slog.d(TAG, "Got locale " + systemLocale + " from mount service");
1120 Locale locale = Locale.forLanguageTag(systemLocale);
1121 Configuration config = new Configuration();
1122 config.setLocale(locale);
1123 try {
Sudheer Shankadc589ac2016-11-10 15:30:17 -08001124 ActivityManager.getService().updatePersistentConfiguration(config);
Elliott Hughesf839b4f2014-09-26 12:30:47 -07001125 } catch (RemoteException e) {
1126 Slog.e(TAG, "Error setting system locale from mount service", e);
1127 }
Elliott Hughes9c33f282014-10-13 12:39:56 -07001128
1129 // Temporary workaround for http://b/17945169.
1130 Slog.d(TAG, "Setting system properties to " + systemLocale + " from mount service");
Narayan Kamathd30dbb82015-01-15 14:48:15 +00001131 SystemProperties.set("persist.sys.locale", locale.toLanguageTag());
Elliott Hughesf839b4f2014-09-26 12:30:47 -07001132 }
1133
Jeff Sharkey8058fe62017-09-13 11:50:33 -06001134 private final IVoldListener mListener = new IVoldListener.Stub() {
1135 @Override
1136 public void onDiskCreated(String diskId, int flags) {
1137 synchronized (mLock) {
Jeff Sharkey901c0422018-04-20 13:11:20 -06001138 final String value = SystemProperties.get(StorageManager.PROP_ADOPTABLE);
1139 switch (value) {
1140 case "force_on":
1141 flags |= DiskInfo.FLAG_ADOPTABLE;
1142 break;
1143 case "force_off":
1144 flags &= ~DiskInfo.FLAG_ADOPTABLE;
1145 break;
Jeff Sharkey8058fe62017-09-13 11:50:33 -06001146 }
Jeff Sharkey8058fe62017-09-13 11:50:33 -06001147 mDisks.put(diskId, new DiskInfo(diskId, flags));
1148 }
1149 }
1150
1151 @Override
1152 public void onDiskScanned(String diskId) {
1153 synchronized (mLock) {
1154 final DiskInfo disk = mDisks.get(diskId);
1155 if (disk != null) {
1156 onDiskScannedLocked(disk);
1157 }
1158 }
1159 }
1160
1161 @Override
1162 public void onDiskMetadataChanged(String diskId, long sizeBytes, String label,
1163 String sysPath) {
1164 synchronized (mLock) {
1165 final DiskInfo disk = mDisks.get(diskId);
1166 if (disk != null) {
1167 disk.size = sizeBytes;
1168 disk.label = label;
1169 disk.sysPath = sysPath;
1170 }
1171 }
1172 }
1173
1174 @Override
1175 public void onDiskDestroyed(String diskId) {
1176 synchronized (mLock) {
1177 final DiskInfo disk = mDisks.remove(diskId);
1178 if (disk != null) {
1179 mCallbacks.notifyDiskDestroyed(disk);
1180 }
1181 }
1182 }
1183
1184 @Override
1185 public void onVolumeCreated(String volId, int type, String diskId, String partGuid) {
1186 synchronized (mLock) {
1187 final DiskInfo disk = mDisks.get(diskId);
1188 final VolumeInfo vol = new VolumeInfo(volId, type, disk, partGuid);
1189 mVolumes.put(volId, vol);
1190 onVolumeCreatedLocked(vol);
1191 }
1192 }
1193
1194 @Override
1195 public void onVolumeStateChanged(String volId, int state) {
1196 synchronized (mLock) {
1197 final VolumeInfo vol = mVolumes.get(volId);
1198 if (vol != null) {
1199 final int oldState = vol.state;
1200 final int newState = state;
1201 vol.state = newState;
1202 onVolumeStateChangedLocked(vol, oldState, newState);
1203 }
1204 }
1205 }
1206
1207 @Override
1208 public void onVolumeMetadataChanged(String volId, String fsType, String fsUuid,
1209 String fsLabel) {
1210 synchronized (mLock) {
1211 final VolumeInfo vol = mVolumes.get(volId);
1212 if (vol != null) {
1213 vol.fsType = fsType;
1214 vol.fsUuid = fsUuid;
1215 vol.fsLabel = fsLabel;
1216 }
1217 }
1218 }
1219
1220 @Override
1221 public void onVolumePathChanged(String volId, String path) {
1222 synchronized (mLock) {
1223 final VolumeInfo vol = mVolumes.get(volId);
1224 if (vol != null) {
1225 vol.path = path;
1226 }
1227 }
1228 }
1229
1230 @Override
1231 public void onVolumeInternalPathChanged(String volId, String internalPath) {
1232 synchronized (mLock) {
1233 final VolumeInfo vol = mVolumes.get(volId);
1234 if (vol != null) {
1235 vol.internalPath = internalPath;
1236 }
1237 }
1238 }
1239
1240 @Override
1241 public void onVolumeDestroyed(String volId) {
1242 synchronized (mLock) {
1243 mVolumes.remove(volId);
1244 }
1245 }
1246 };
1247
Andreas Gampea36dc622018-02-05 17:19:22 -08001248 @GuardedBy("mLock")
Jeff Sharkeyeba260d2015-04-19 14:35:16 -07001249 private void onDiskScannedLocked(DiskInfo disk) {
Jeff Sharkey620b32b2015-04-23 19:36:02 -07001250 int volumeCount = 0;
Jeff Sharkeyeba260d2015-04-19 14:35:16 -07001251 for (int i = 0; i < mVolumes.size(); i++) {
1252 final VolumeInfo vol = mVolumes.valueAt(i);
1253 if (Objects.equals(disk.id, vol.getDiskId())) {
Jeff Sharkey620b32b2015-04-23 19:36:02 -07001254 volumeCount++;
Jeff Sharkeyeba260d2015-04-19 14:35:16 -07001255 }
1256 }
1257
Jeff Sharkeyc7acac62015-06-12 16:16:56 -07001258 final Intent intent = new Intent(DiskInfo.ACTION_DISK_SCANNED);
Jeff Sharkey7732e1e2016-03-30 17:14:23 -06001259 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT
1260 | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
Jeff Sharkeyc7acac62015-06-12 16:16:56 -07001261 intent.putExtra(DiskInfo.EXTRA_DISK_ID, disk.id);
1262 intent.putExtra(DiskInfo.EXTRA_VOLUME_COUNT, volumeCount);
Jeff Sharkeyabc3e852015-08-03 14:41:13 -07001263 mHandler.obtainMessage(H_INTERNAL_BROADCAST, intent).sendToTarget();
Jeff Sharkeyc7acac62015-06-12 16:16:56 -07001264
1265 final CountDownLatch latch = mDiskScanLatches.remove(disk.id);
1266 if (latch != null) {
1267 latch.countDown();
1268 }
1269
Jeff Sharkeyf5a6bd72015-05-19 14:42:38 -07001270 disk.volumeCount = volumeCount;
Jeff Sharkey620b32b2015-04-23 19:36:02 -07001271 mCallbacks.notifyDiskScanned(disk, volumeCount);
Jeff Sharkeyeba260d2015-04-19 14:35:16 -07001272 }
1273
Andreas Gampea36dc622018-02-05 17:19:22 -08001274 @GuardedBy("mLock")
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07001275 private void onVolumeCreatedLocked(VolumeInfo vol) {
Jeff Sharkey5790af02018-08-13 17:42:54 -06001276 if (mPmInternal.isOnlyCoreApps()) {
Jeff Sharkey6855c482016-03-31 14:34:38 -06001277 Slog.d(TAG, "System booted in core-only mode; ignoring volume " + vol.getId());
1278 return;
1279 }
1280
Jeff Sharkey275e3e42015-04-24 16:10:32 -07001281 if (vol.type == VolumeInfo.TYPE_EMULATED) {
1282 final StorageManager storage = mContext.getSystemService(StorageManager.class);
1283 final VolumeInfo privateVol = storage.findPrivateForEmulated(vol);
1284
1285 if (Objects.equals(StorageManager.UUID_PRIVATE_INTERNAL, mPrimaryStorageUuid)
1286 && VolumeInfo.ID_PRIVATE_INTERNAL.equals(privateVol.id)) {
1287 Slog.v(TAG, "Found primary storage at " + vol);
1288 vol.mountFlags |= VolumeInfo.MOUNT_FLAG_PRIMARY;
1289 vol.mountFlags |= VolumeInfo.MOUNT_FLAG_VISIBLE;
1290 mHandler.obtainMessage(H_VOLUME_MOUNT, vol).sendToTarget();
1291
1292 } else if (Objects.equals(privateVol.fsUuid, mPrimaryStorageUuid)) {
1293 Slog.v(TAG, "Found primary storage at " + vol);
1294 vol.mountFlags |= VolumeInfo.MOUNT_FLAG_PRIMARY;
1295 vol.mountFlags |= VolumeInfo.MOUNT_FLAG_VISIBLE;
1296 mHandler.obtainMessage(H_VOLUME_MOUNT, vol).sendToTarget();
1297 }
Jeff Sharkeyb049e212012-09-07 23:16:01 -07001298
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07001299 } else if (vol.type == VolumeInfo.TYPE_PUBLIC) {
Jeff Sharkey275e3e42015-04-24 16:10:32 -07001300 // TODO: only look at first public partition
1301 if (Objects.equals(StorageManager.UUID_PRIMARY_PHYSICAL, mPrimaryStorageUuid)
1302 && vol.disk.isDefaultPrimary()) {
1303 Slog.v(TAG, "Found primary storage at " + vol);
Jeff Sharkey7e92ef32015-04-17 17:35:07 -07001304 vol.mountFlags |= VolumeInfo.MOUNT_FLAG_PRIMARY;
1305 vol.mountFlags |= VolumeInfo.MOUNT_FLAG_VISIBLE;
San Mehat4270e1e2010-01-29 05:32:19 -08001306 }
Jeff Sharkey7e92ef32015-04-17 17:35:07 -07001307
1308 // Adoptable public disks are visible to apps, since they meet
1309 // public API requirement of being in a stable location.
Jeff Sharkey275e3e42015-04-24 16:10:32 -07001310 if (vol.disk.isAdoptable()) {
Jeff Sharkey7e92ef32015-04-17 17:35:07 -07001311 vol.mountFlags |= VolumeInfo.MOUNT_FLAG_VISIBLE;
1312 }
1313
Jeff Sharkeyab15c392016-05-05 11:45:01 -06001314 vol.mountUserId = mCurrentUserId;
Jeff Sharkey48877892015-03-18 11:27:19 -07001315 mHandler.obtainMessage(H_VOLUME_MOUNT, vol).sendToTarget();
San Mehat4270e1e2010-01-29 05:32:19 -08001316
Jeff Sharkeyb2b9ab82015-04-05 21:10:42 -07001317 } else if (vol.type == VolumeInfo.TYPE_PRIVATE) {
1318 mHandler.obtainMessage(H_VOLUME_MOUNT, vol).sendToTarget();
1319
Risan05c41e62018-10-29 08:57:43 +09001320 } else if (vol.type == VolumeInfo.TYPE_STUB) {
1321 vol.mountUserId = mCurrentUserId;
1322 mHandler.obtainMessage(H_VOLUME_MOUNT, vol).sendToTarget();
San Mehat4270e1e2010-01-29 05:32:19 -08001323 } else {
Jeff Sharkey48877892015-03-18 11:27:19 -07001324 Slog.d(TAG, "Skipping automatic mounting of " + vol);
San Mehat4270e1e2010-01-29 05:32:19 -08001325 }
1326 }
1327
Jeff Sharkeye6c04f92015-04-18 21:38:05 -07001328 private boolean isBroadcastWorthy(VolumeInfo vol) {
1329 switch (vol.getType()) {
Jeff Sharkeyc7acac62015-06-12 16:16:56 -07001330 case VolumeInfo.TYPE_PRIVATE:
Jeff Sharkeye6c04f92015-04-18 21:38:05 -07001331 case VolumeInfo.TYPE_PUBLIC:
1332 case VolumeInfo.TYPE_EMULATED:
Risan05c41e62018-10-29 08:57:43 +09001333 case VolumeInfo.TYPE_STUB:
Jeff Sharkeye6c04f92015-04-18 21:38:05 -07001334 break;
1335 default:
1336 return false;
1337 }
1338
1339 switch (vol.getState()) {
1340 case VolumeInfo.STATE_MOUNTED:
1341 case VolumeInfo.STATE_MOUNTED_READ_ONLY:
1342 case VolumeInfo.STATE_EJECTING:
1343 case VolumeInfo.STATE_UNMOUNTED:
Jeff Sharkeyc7acac62015-06-12 16:16:56 -07001344 case VolumeInfo.STATE_UNMOUNTABLE:
Tony Mantlerf0d71052015-06-24 11:45:25 -07001345 case VolumeInfo.STATE_BAD_REMOVAL:
Jeff Sharkeye6c04f92015-04-18 21:38:05 -07001346 break;
1347 default:
1348 return false;
1349 }
1350
1351 return true;
1352 }
1353
Andreas Gampea36dc622018-02-05 17:19:22 -08001354 @GuardedBy("mLock")
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07001355 private void onVolumeStateChangedLocked(VolumeInfo vol, int oldState, int newState) {
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001356 // Remember that we saw this volume so we're ready to accept user
1357 // metadata, or so we can annoy them when a private volume is ejected
1358 if (vol.isMountedReadable() && !TextUtils.isEmpty(vol.fsUuid)) {
Jeff Sharkey5cc0df22015-06-17 19:44:05 -07001359 VolumeRecord rec = mRecords.get(vol.fsUuid);
1360 if (rec == null) {
1361 rec = new VolumeRecord(vol.type, vol.fsUuid);
1362 rec.partGuid = vol.partGuid;
Jeff Sharkeye8a4b662015-06-27 15:43:45 -07001363 rec.createdMillis = System.currentTimeMillis();
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001364 if (vol.type == VolumeInfo.TYPE_PRIVATE) {
1365 rec.nickname = vol.disk.getDescription();
1366 }
1367 mRecords.put(rec.fsUuid, rec);
1368 writeSettingsLocked();
Jeff Sharkey5cc0df22015-06-17 19:44:05 -07001369 } else {
1370 // Handle upgrade case where we didn't store partition GUID
1371 if (TextUtils.isEmpty(rec.partGuid)) {
1372 rec.partGuid = vol.partGuid;
1373 writeSettingsLocked();
1374 }
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001375 }
1376 }
1377
Jeff Sharkeye6c04f92015-04-18 21:38:05 -07001378 mCallbacks.notifyVolumeStateChanged(vol, oldState, newState);
1379
Yasuhiro Matsuda87a38b52015-07-24 22:10:16 +09001380 // Do not broadcast before boot has completed to avoid launching the
1381 // processes that receive the intent unnecessarily.
1382 if (mBootCompleted && isBroadcastWorthy(vol)) {
Jeff Sharkeye6c04f92015-04-18 21:38:05 -07001383 final Intent intent = new Intent(VolumeInfo.ACTION_VOLUME_STATE_CHANGED);
Jeff Sharkeyc7acac62015-06-12 16:16:56 -07001384 intent.putExtra(VolumeInfo.EXTRA_VOLUME_ID, vol.id);
1385 intent.putExtra(VolumeInfo.EXTRA_VOLUME_STATE, newState);
Tony Mantlerf0d71052015-06-24 11:45:25 -07001386 intent.putExtra(VolumeRecord.EXTRA_FS_UUID, vol.fsUuid);
Jeff Sharkey7732e1e2016-03-30 17:14:23 -06001387 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT
1388 | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
Jeff Sharkeyabc3e852015-08-03 14:41:13 -07001389 mHandler.obtainMessage(H_INTERNAL_BROADCAST, intent).sendToTarget();
Jeff Sharkeye6c04f92015-04-18 21:38:05 -07001390 }
Jeff Sharkeyb049e212012-09-07 23:16:01 -07001391
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001392 final String oldStateEnv = VolumeInfo.getEnvironmentForState(oldState);
1393 final String newStateEnv = VolumeInfo.getEnvironmentForState(newState);
Emily Bernier92aa5a22014-07-07 10:11:48 -04001394
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001395 if (!Objects.equals(oldStateEnv, newStateEnv)) {
1396 // Kick state changed event towards all started users. Any users
1397 // started after this point will trigger additional
1398 // user-specific broadcasts.
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07001399 for (int userId : mSystemUnlockedUsers) {
Jeff Sharkey46349872015-07-28 10:49:47 -07001400 if (vol.isVisibleForRead(userId)) {
Svet Ganov6ee871e2015-07-10 14:29:33 -07001401 final StorageVolume userVol = vol.buildStorageVolume(mContext, userId, false);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001402 mHandler.obtainMessage(H_VOLUME_BROADCAST, userVol).sendToTarget();
Jeff Sharkey48877892015-03-18 11:27:19 -07001403
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001404 mCallbacks.notifyStorageStateChanged(userVol.getPath(), oldStateEnv,
1405 newStateEnv);
San Mehat4270e1e2010-01-29 05:32:19 -08001406 }
1407 }
1408 }
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001409
Risan05c41e62018-10-29 08:57:43 +09001410 if ((vol.type == VolumeInfo.TYPE_PUBLIC || vol.type == VolumeInfo.TYPE_STUB)
1411 && vol.state == VolumeInfo.STATE_EJECTING) {
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001412 // TODO: this should eventually be handled by new ObbVolume state changes
1413 /*
1414 * Some OBBs might have been unmounted when this volume was
1415 * unmounted, so send a message to the handler to let it know to
1416 * remove those from the list of mounted OBBS.
1417 */
1418 mObbActionHandler.sendMessage(mObbActionHandler.obtainMessage(
1419 OBB_FLUSH_MOUNT_STATE, vol.path));
1420 }
Pavel Grafovce72ef02018-01-10 17:14:11 +00001421 maybeLogMediaMount(vol, newState);
1422 }
1423
1424 private void maybeLogMediaMount(VolumeInfo vol, int newState) {
1425 if (!SecurityLog.isLoggingEnabled()) {
1426 return;
1427 }
1428
1429 final DiskInfo disk = vol.getDisk();
1430 if (disk == null || (disk.flags & (DiskInfo.FLAG_SD | DiskInfo.FLAG_USB)) == 0) {
1431 return;
1432 }
1433
1434 // Sometimes there is a newline character.
1435 final String label = disk.label != null ? disk.label.trim() : "";
1436
1437 if (newState == VolumeInfo.STATE_MOUNTED
1438 || newState == VolumeInfo.STATE_MOUNTED_READ_ONLY) {
1439 SecurityLog.writeEvent(SecurityLog.TAG_MEDIA_MOUNT, vol.path, label);
1440 } else if (newState == VolumeInfo.STATE_UNMOUNTED
1441 || newState == VolumeInfo.STATE_BAD_REMOVAL) {
1442 SecurityLog.writeEvent(SecurityLog.TAG_MEDIA_UNMOUNT, vol.path, label);
1443 }
San Mehat4270e1e2010-01-29 05:32:19 -08001444 }
1445
Andreas Gampea36dc622018-02-05 17:19:22 -08001446 @GuardedBy("mLock")
Jeff Sharkey275e3e42015-04-24 16:10:32 -07001447 private void onMoveStatusLocked(int status) {
1448 if (mMoveCallback == null) {
1449 Slog.w(TAG, "Odd, status but no move requested");
1450 return;
1451 }
1452
1453 // TODO: estimate remaining time
1454 try {
Jeff Sharkey50a05452015-04-29 11:24:52 -07001455 mMoveCallback.onStatusChanged(-1, status, -1);
Jeff Sharkey275e3e42015-04-24 16:10:32 -07001456 } catch (RemoteException ignored) {
1457 }
1458
1459 // We've finished copying and we're about to clean up old data, so
1460 // remember that move was successful if we get rebooted
1461 if (status == MOVE_STATUS_COPY_FINISHED) {
1462 Slog.d(TAG, "Move to " + mMoveTargetUuid + " copy phase finshed; persisting");
1463
1464 mPrimaryStorageUuid = mMoveTargetUuid;
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001465 writeSettingsLocked();
Jeff Sharkey275e3e42015-04-24 16:10:32 -07001466 }
1467
1468 if (PackageManager.isMoveStatusFinished(status)) {
1469 Slog.d(TAG, "Move to " + mMoveTargetUuid + " finished with status " + status);
1470
1471 mMoveCallback = null;
1472 mMoveTargetUuid = null;
1473 }
1474 }
1475
Jeff Sharkey48877892015-03-18 11:27:19 -07001476 private void enforcePermission(String perm) {
1477 mContext.enforceCallingOrSelfPermission(perm, perm);
Mike Lockwooda5250c92011-05-23 13:44:04 -04001478 }
1479
Jeff Sharkey2e606d72015-07-27 14:19:54 -07001480 /**
1481 * Decide if volume is mountable per device policies.
1482 */
1483 private boolean isMountDisallowed(VolumeInfo vol) {
Philip P. Moltmannec3cbb22016-09-14 13:24:52 -07001484 UserManager userManager = mContext.getSystemService(UserManager.class);
1485
1486 boolean isUsbRestricted = false;
1487 if (vol.disk != null && vol.disk.isUsb()) {
1488 isUsbRestricted = userManager.hasUserRestriction(UserManager.DISALLOW_USB_FILE_TRANSFER,
Jeff Sharkey2e606d72015-07-27 14:19:54 -07001489 Binder.getCallingUserHandle());
Emily Bernier92aa5a22014-07-07 10:11:48 -04001490 }
Philip P. Moltmannec3cbb22016-09-14 13:24:52 -07001491
1492 boolean isTypeRestricted = false;
Risan05c41e62018-10-29 08:57:43 +09001493 if (vol.type == VolumeInfo.TYPE_PUBLIC || vol.type == VolumeInfo.TYPE_PRIVATE
1494 || vol.type == VolumeInfo.TYPE_STUB) {
Philip P. Moltmannec3cbb22016-09-14 13:24:52 -07001495 isTypeRestricted = userManager
1496 .hasUserRestriction(UserManager.DISALLOW_MOUNT_PHYSICAL_MEDIA,
1497 Binder.getCallingUserHandle());
1498 }
1499
1500 return isUsbRestricted || isTypeRestricted;
Emily Bernier92aa5a22014-07-07 10:11:48 -04001501 }
1502
Amith Yamasani462ac3a2015-06-30 14:21:01 -07001503 private void enforceAdminUser() {
1504 UserManager um = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
1505 final int callingUserId = UserHandle.getCallingUserId();
1506 boolean isAdmin;
1507 long token = Binder.clearCallingIdentity();
1508 try {
1509 isAdmin = um.getUserInfo(callingUserId).isAdmin();
1510 } finally {
1511 Binder.restoreCallingIdentity(token);
1512 }
1513 if (!isAdmin) {
1514 throw new SecurityException("Only admin users can adopt sd cards");
1515 }
1516 }
1517
Jeff Sharkeyb049e212012-09-07 23:16:01 -07001518 /**
Sudheer Shanka2250d562016-11-07 15:41:02 -08001519 * Constructs a new StorageManagerService instance
San Mehat207e5382010-02-04 20:46:54 -08001520 *
1521 * @param context Binder context for this service
1522 */
Sudheer Shanka2250d562016-11-07 15:41:02 -08001523 public StorageManagerService(Context context) {
Christopher Tated417d622013-08-19 16:14:25 -07001524 sSelf = this;
1525
Jeff Sharkey342b4bf2018-12-18 11:12:40 -07001526 // Snapshot feature flag used for this boot
1527 SystemProperties.set(StorageManager.PROP_ISOLATED_STORAGE_SNAPSHOT, Boolean.toString(
Jeff Sharkey06376802019-02-11 12:20:02 -07001528 SystemProperties.getBoolean(StorageManager.PROP_ISOLATED_STORAGE, true)));
Jeff Sharkey342b4bf2018-12-18 11:12:40 -07001529
San Mehat207e5382010-02-04 20:46:54 -08001530 mContext = context;
Jeff Sharkey5d0c55c2019-01-24 14:32:31 -07001531 mResolver = mContext.getContentResolver();
1532
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001533 mCallbacks = new Callbacks(FgThread.get().getLooper());
Jeff Sharkeyb9fe5372015-12-03 15:23:08 -07001534 mLockPatternUtils = new LockPatternUtils(mContext);
San Mehat207e5382010-02-04 20:46:54 -08001535
Dianne Hackbornefa92b22013-05-03 14:11:43 -07001536 HandlerThread hthread = new HandlerThread(TAG);
1537 hthread.start();
Sudheer Shanka2250d562016-11-07 15:41:02 -08001538 mHandler = new StorageManagerServiceHandler(hthread.getLooper());
Daniel Sandler5f27ef42010-03-16 15:42:02 -04001539
Sudheer Shanka2250d562016-11-07 15:41:02 -08001540 // Add OBB Action Handler to StorageManagerService thread.
Dianne Hackborn8d044e82013-04-30 17:24:15 -07001541 mObbActionHandler = new ObbActionHandler(IoThread.get().getLooper());
Kenny Roota02b8b02010-08-05 16:14:17 -07001542
Christopher Tate7265abe2014-11-21 13:54:45 -08001543 // Initialize the last-fstrim tracking if necessary
1544 File dataDir = Environment.getDataDirectory();
1545 File systemDir = new File(dataDir, "system");
1546 mLastMaintenanceFile = new File(systemDir, LAST_FSTRIM_FILE);
1547 if (!mLastMaintenanceFile.exists()) {
1548 // Not setting mLastMaintenance here means that we will force an
1549 // fstrim during reboot following the OTA that installs this code.
1550 try {
1551 (new FileOutputStream(mLastMaintenanceFile)).close();
1552 } catch (IOException e) {
1553 Slog.e(TAG, "Unable to create fstrim record " + mLastMaintenanceFile.getPath());
1554 }
1555 } else {
1556 mLastMaintenance = mLastMaintenanceFile.lastModified();
1557 }
1558
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001559 mSettingsFile = new AtomicFile(
Dianne Hackborne17b4452018-01-10 13:15:40 -08001560 new File(Environment.getDataSystemDirectory(), "storage.xml"), "storage-settings");
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001561
1562 synchronized (mLock) {
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001563 readSettingsLocked();
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001564 }
1565
Sudheer Shanka2250d562016-11-07 15:41:02 -08001566 LocalServices.addService(StorageManagerInternal.class, mStorageManagerInternal);
Svet Ganov6ee871e2015-07-10 14:29:33 -07001567
Jeff Sharkeybcd262d2015-06-10 09:41:17 -07001568 final IntentFilter userFilter = new IntentFilter();
1569 userFilter.addAction(Intent.ACTION_USER_ADDED);
1570 userFilter.addAction(Intent.ACTION_USER_REMOVED);
1571 mContext.registerReceiver(mUserReceiver, userFilter, null, mHandler);
1572
Jeff Sharkey5a9bb742015-11-03 10:15:57 -08001573 synchronized (mLock) {
1574 addInternalVolumeLocked();
1575 }
Amith Yamasania7892482015-08-07 11:09:05 -07001576
Kenny Root07714d42011-08-17 17:49:28 -07001577 // Add ourself to the Watchdog monitors if enabled.
1578 if (WATCHDOG_ENABLE) {
1579 Watchdog.getInstance().addMonitor(this);
1580 }
San Mehat207e5382010-02-04 20:46:54 -08001581 }
1582
Jeff Sharkeycd575992016-03-29 14:12:49 -06001583 private void start() {
Jeff Sharkey1019de92017-09-06 13:47:03 -06001584 connect();
Jeff Sharkeycd575992016-03-29 14:12:49 -06001585 }
1586
Sudheer Shanka0a541a52018-07-31 13:21:11 -07001587 private static String getSandboxId(String packageName, String sharedUserId) {
Sudheer Shankad68bd602018-11-13 17:43:39 -08001588 return sharedUserId == null
1589 ? packageName : StorageManager.SHARED_SANDBOX_PREFIX + sharedUserId;
Sudheer Shanka0a541a52018-07-31 13:21:11 -07001590 }
Sudheer Shanka0a541a52018-07-31 13:21:11 -07001591
Jeff Sharkey1019de92017-09-06 13:47:03 -06001592 private void connect() {
Jin Qian12690d52017-10-13 18:17:04 -07001593 IBinder binder = ServiceManager.getService("storaged");
1594 if (binder != null) {
1595 try {
1596 binder.linkToDeath(new DeathRecipient() {
1597 @Override
1598 public void binderDied() {
1599 Slog.w(TAG, "storaged died; reconnecting");
1600 mStoraged = null;
1601 connect();
1602 }
1603 }, 0);
1604 } catch (RemoteException e) {
1605 binder = null;
1606 }
1607 }
1608
1609 if (binder != null) {
1610 mStoraged = IStoraged.Stub.asInterface(binder);
1611 } else {
1612 Slog.w(TAG, "storaged not found; trying again");
1613 }
1614
1615 binder = ServiceManager.getService("vold");
Jeff Sharkey1019de92017-09-06 13:47:03 -06001616 if (binder != null) {
1617 try {
1618 binder.linkToDeath(new DeathRecipient() {
1619 @Override
1620 public void binderDied() {
1621 Slog.w(TAG, "vold died; reconnecting");
Jin Qian12690d52017-10-13 18:17:04 -07001622 mVold = null;
Jeff Sharkey1019de92017-09-06 13:47:03 -06001623 connect();
1624 }
1625 }, 0);
1626 } catch (RemoteException e) {
1627 binder = null;
1628 }
1629 }
1630
1631 if (binder != null) {
1632 mVold = IVold.Stub.asInterface(binder);
Jeff Sharkey8058fe62017-09-13 11:50:33 -06001633 try {
1634 mVold.setListener(mListener);
Jeff Sharkey8058fe62017-09-13 11:50:33 -06001635 } catch (RemoteException e) {
Jin Qian12690d52017-10-13 18:17:04 -07001636 mVold = null;
Jeff Sharkey8058fe62017-09-13 11:50:33 -06001637 Slog.w(TAG, "vold listener rejected; trying again", e);
1638 }
Jeff Sharkey1019de92017-09-06 13:47:03 -06001639 } else {
1640 Slog.w(TAG, "vold not found; trying again");
Jeff Sharkey1019de92017-09-06 13:47:03 -06001641 }
Jeff Sharkey8058fe62017-09-13 11:50:33 -06001642
Jin Qian12690d52017-10-13 18:17:04 -07001643 if (mStoraged == null || mVold == null) {
1644 BackgroundThread.getHandler().postDelayed(() -> {
1645 connect();
1646 }, DateUtils.SECOND_IN_MILLIS);
1647 } else {
1648 onDaemonConnected();
1649 }
Jeff Sharkey1019de92017-09-06 13:47:03 -06001650 }
1651
Jeff Sharkey11697f52018-12-13 10:14:42 -07001652 private void servicesReady() {
Sudheer Shankaff585072019-01-29 23:19:45 -08001653 mPmInternal = LocalServices.getService(PackageManagerInternal.class);
1654 mUmInternal = LocalServices.getService(UserManagerInternal.class);
1655 mAmInternal = LocalServices.getService(ActivityManagerInternal.class);
1656
1657 mIPackageManager = IPackageManager.Stub.asInterface(
1658 ServiceManager.getService("package"));
1659 mIAppOpsService = IAppOpsService.Stub.asInterface(
1660 ServiceManager.getService(Context.APP_OPS_SERVICE));
1661 try {
1662 mIAppOpsService.startWatchingMode(OP_REQUEST_INSTALL_PACKAGES, null, mAppOpsCallback);
1663 } catch (RemoteException e) {
1664 }
1665
Jeff Sharkey11697f52018-12-13 10:14:42 -07001666 synchronized (mLock) {
1667 final boolean thisIsolatedStorage = StorageManager.hasIsolatedStorage();
1668 if (mLastIsolatedStorage == thisIsolatedStorage) {
1669 // Nothing changed since last boot; keep rolling forward
1670 return;
1671 } else if (thisIsolatedStorage) {
1672 // This boot enables isolated storage; apply legacy behavior
1673 applyLegacyStorage();
1674 }
1675
1676 // Always remember the new state we just booted with
1677 writeSettingsLocked();
1678 }
1679 }
1680
1681 /**
1682 * If we're enabling isolated storage, we need to remember which existing
1683 * apps have already been using shared storage, and grant them legacy access
1684 * to keep them running smoothly.
1685 */
1686 private void applyLegacyStorage() {
1687 final AppOpsManager appOps = mContext.getSystemService(AppOpsManager.class);
1688 final UserManagerInternal um = LocalServices.getService(UserManagerInternal.class);
1689 for (int userId : um.getUserIds()) {
1690 final PackageManager pm;
1691 try {
1692 pm = mContext.createPackageContextAsUser(mContext.getPackageName(),
1693 0, UserHandle.of(userId)).getPackageManager();
1694 } catch (PackageManager.NameNotFoundException e) {
1695 throw new RuntimeException(e);
1696 }
1697
1698 final List<PackageInfo> pkgs = pm.getPackagesHoldingPermissions(new String[] {
1699 android.Manifest.permission.READ_EXTERNAL_STORAGE,
1700 android.Manifest.permission.WRITE_EXTERNAL_STORAGE
1701 }, MATCH_UNINSTALLED_PACKAGES | MATCH_DIRECT_BOOT_AWARE | MATCH_DIRECT_BOOT_UNAWARE);
1702 for (PackageInfo pkg : pkgs) {
1703 final int uid = pkg.applicationInfo.uid;
1704 final String packageName = pkg.applicationInfo.packageName;
1705
1706 final long lastAccess = getLastAccessTime(appOps, uid, packageName, new int[] {
1707 AppOpsManager.OP_READ_EXTERNAL_STORAGE,
1708 AppOpsManager.OP_WRITE_EXTERNAL_STORAGE,
1709 });
1710
1711 Log.d(TAG, "Found " + uid + " " + packageName
1712 + " with granted storage access, last accessed " + lastAccess);
1713 if (lastAccess > 0) {
1714 appOps.setMode(AppOpsManager.OP_LEGACY_STORAGE,
1715 uid, packageName, AppOpsManager.MODE_ALLOWED);
1716 }
1717 }
1718 }
1719 }
1720
1721 private static long getLastAccessTime(AppOpsManager manager,
1722 int uid, String packageName, int[] ops) {
1723 long maxTime = 0;
1724 final List<AppOpsManager.PackageOps> pkgs = manager.getOpsForPackage(uid, packageName, ops);
Eugene Susla04d021c2018-12-17 14:49:59 -08001725 for (AppOpsManager.PackageOps pkg : CollectionUtils.emptyIfNull(pkgs)) {
1726 for (AppOpsManager.OpEntry op : CollectionUtils.emptyIfNull(pkg.getOps())) {
Jeff Sharkey11697f52018-12-13 10:14:42 -07001727 maxTime = Math.max(maxTime, op.getLastAccessTime());
1728 }
1729 }
1730 return maxTime;
1731 }
1732
Jeff Sharkey56e62932015-03-21 20:41:00 -07001733 private void systemReady() {
Wale Ogunwale6767eae2018-05-03 15:52:51 -07001734 LocalServices.getService(ActivityTaskManagerInternal.class)
Jeff Sharkey9765e442017-12-14 22:15:14 -07001735 .registerScreenObserver(this);
1736
Jeff Sharkeyb049e212012-09-07 23:16:01 -07001737 mSystemReady = true;
1738 mHandler.obtainMessage(H_SYSTEM_READY).sendToTarget();
1739 }
1740
Yasuhiro Matsuda87a38b52015-07-24 22:10:16 +09001741 private void bootCompleted() {
1742 mBootCompleted = true;
1743 }
1744
Jeff Sharkeyfced5342015-05-10 14:53:34 -07001745 private String getDefaultPrimaryStorageUuid() {
1746 if (SystemProperties.getBoolean(StorageManager.PROP_PRIMARY_PHYSICAL, false)) {
1747 return StorageManager.UUID_PRIMARY_PHYSICAL;
1748 } else {
1749 return StorageManager.UUID_PRIVATE_INTERNAL;
1750 }
1751 }
1752
Andreas Gampea36dc622018-02-05 17:19:22 -08001753 @GuardedBy("mLock")
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001754 private void readSettingsLocked() {
1755 mRecords.clear();
Jeff Sharkeyfced5342015-05-10 14:53:34 -07001756 mPrimaryStorageUuid = getDefaultPrimaryStorageUuid();
Jeff Sharkey11697f52018-12-13 10:14:42 -07001757 mLastIsolatedStorage = false;
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001758
1759 FileInputStream fis = null;
1760 try {
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001761 fis = mSettingsFile.openRead();
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001762 final XmlPullParser in = Xml.newPullParser();
Wojciech Staszkiewicz9e9e2e72015-05-08 14:58:46 +01001763 in.setInput(fis, StandardCharsets.UTF_8.name());
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001764
1765 int type;
1766 while ((type = in.next()) != END_DOCUMENT) {
1767 if (type == START_TAG) {
1768 final String tag = in.getName();
Jeff Sharkey620b32b2015-04-23 19:36:02 -07001769 if (TAG_VOLUMES.equals(tag)) {
1770 final int version = readIntAttribute(in, ATTR_VERSION, VERSION_INIT);
Jeff Sharkeyfced5342015-05-10 14:53:34 -07001771 final boolean primaryPhysical = SystemProperties.getBoolean(
1772 StorageManager.PROP_PRIMARY_PHYSICAL, false);
1773 final boolean validAttr = (version >= VERSION_FIX_PRIMARY)
1774 || (version >= VERSION_ADD_PRIMARY && !primaryPhysical);
1775 if (validAttr) {
Jeff Sharkey620b32b2015-04-23 19:36:02 -07001776 mPrimaryStorageUuid = readStringAttribute(in,
1777 ATTR_PRIMARY_STORAGE_UUID);
Jeff Sharkey620b32b2015-04-23 19:36:02 -07001778 }
Jeff Sharkey11697f52018-12-13 10:14:42 -07001779 mLastIsolatedStorage = readBooleanAttribute(in,
1780 ATTR_ISOLATED_STORAGE, false);
Jeff Sharkey620b32b2015-04-23 19:36:02 -07001781
1782 } else if (TAG_VOLUME.equals(tag)) {
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001783 final VolumeRecord rec = readVolumeRecord(in);
1784 mRecords.put(rec.fsUuid, rec);
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001785 }
1786 }
1787 }
1788 } catch (FileNotFoundException e) {
1789 // Missing metadata is okay, probably first boot
1790 } catch (IOException e) {
1791 Slog.wtf(TAG, "Failed reading metadata", e);
1792 } catch (XmlPullParserException e) {
1793 Slog.wtf(TAG, "Failed reading metadata", e);
1794 } finally {
1795 IoUtils.closeQuietly(fis);
1796 }
1797 }
1798
Andreas Gampea36dc622018-02-05 17:19:22 -08001799 @GuardedBy("mLock")
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001800 private void writeSettingsLocked() {
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001801 FileOutputStream fos = null;
1802 try {
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001803 fos = mSettingsFile.startWrite();
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001804
1805 XmlSerializer out = new FastXmlSerializer();
Wojciech Staszkiewicz9e9e2e72015-05-08 14:58:46 +01001806 out.setOutput(fos, StandardCharsets.UTF_8.name());
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001807 out.startDocument(null, true);
1808 out.startTag(null, TAG_VOLUMES);
Jeff Sharkeyfced5342015-05-10 14:53:34 -07001809 writeIntAttribute(out, ATTR_VERSION, VERSION_FIX_PRIMARY);
Jeff Sharkey620b32b2015-04-23 19:36:02 -07001810 writeStringAttribute(out, ATTR_PRIMARY_STORAGE_UUID, mPrimaryStorageUuid);
Jeff Sharkey11697f52018-12-13 10:14:42 -07001811 writeBooleanAttribute(out, ATTR_ISOLATED_STORAGE, StorageManager.hasIsolatedStorage());
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001812 final int size = mRecords.size();
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001813 for (int i = 0; i < size; i++) {
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001814 final VolumeRecord rec = mRecords.valueAt(i);
1815 writeVolumeRecord(out, rec);
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001816 }
1817 out.endTag(null, TAG_VOLUMES);
1818 out.endDocument();
1819
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001820 mSettingsFile.finishWrite(fos);
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001821 } catch (IOException e) {
1822 if (fos != null) {
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001823 mSettingsFile.failWrite(fos);
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001824 }
1825 }
1826 }
1827
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001828 public static VolumeRecord readVolumeRecord(XmlPullParser in) throws IOException {
1829 final int type = readIntAttribute(in, ATTR_TYPE);
1830 final String fsUuid = readStringAttribute(in, ATTR_FS_UUID);
1831 final VolumeRecord meta = new VolumeRecord(type, fsUuid);
Jeff Sharkey5cc0df22015-06-17 19:44:05 -07001832 meta.partGuid = readStringAttribute(in, ATTR_PART_GUID);
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001833 meta.nickname = readStringAttribute(in, ATTR_NICKNAME);
1834 meta.userFlags = readIntAttribute(in, ATTR_USER_FLAGS);
Jeff Sharkeye8a4b662015-06-27 15:43:45 -07001835 meta.createdMillis = readLongAttribute(in, ATTR_CREATED_MILLIS);
1836 meta.lastTrimMillis = readLongAttribute(in, ATTR_LAST_TRIM_MILLIS);
1837 meta.lastBenchMillis = readLongAttribute(in, ATTR_LAST_BENCH_MILLIS);
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001838 return meta;
1839 }
1840
1841 public static void writeVolumeRecord(XmlSerializer out, VolumeRecord rec) throws IOException {
1842 out.startTag(null, TAG_VOLUME);
1843 writeIntAttribute(out, ATTR_TYPE, rec.type);
1844 writeStringAttribute(out, ATTR_FS_UUID, rec.fsUuid);
Jeff Sharkey5cc0df22015-06-17 19:44:05 -07001845 writeStringAttribute(out, ATTR_PART_GUID, rec.partGuid);
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001846 writeStringAttribute(out, ATTR_NICKNAME, rec.nickname);
1847 writeIntAttribute(out, ATTR_USER_FLAGS, rec.userFlags);
Jeff Sharkeye8a4b662015-06-27 15:43:45 -07001848 writeLongAttribute(out, ATTR_CREATED_MILLIS, rec.createdMillis);
1849 writeLongAttribute(out, ATTR_LAST_TRIM_MILLIS, rec.lastTrimMillis);
1850 writeLongAttribute(out, ATTR_LAST_BENCH_MILLIS, rec.lastBenchMillis);
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001851 out.endTag(null, TAG_VOLUME);
1852 }
1853
San Mehat207e5382010-02-04 20:46:54 -08001854 /**
San Mehat4270e1e2010-01-29 05:32:19 -08001855 * Exposed API calls below here
1856 */
1857
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001858 @Override
Sudheer Shanka2250d562016-11-07 15:41:02 -08001859 public void registerListener(IStorageEventListener listener) {
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001860 mCallbacks.register(listener);
San Mehat4270e1e2010-01-29 05:32:19 -08001861 }
1862
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001863 @Override
Sudheer Shanka2250d562016-11-07 15:41:02 -08001864 public void unregisterListener(IStorageEventListener listener) {
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001865 mCallbacks.unregister(listener);
San Mehat4270e1e2010-01-29 05:32:19 -08001866 }
1867
Jeff Sharkey48877892015-03-18 11:27:19 -07001868 @Override
Sudheer Shanka2250d562016-11-07 15:41:02 -08001869 public void shutdown(final IStorageShutdownObserver observer) {
Jeff Sharkey48877892015-03-18 11:27:19 -07001870 enforcePermission(android.Manifest.permission.SHUTDOWN);
San Mehat4270e1e2010-01-29 05:32:19 -08001871
San Mehata5078592010-03-25 09:36:54 -07001872 Slog.i(TAG, "Shutting down");
Jeff Sharkey48877892015-03-18 11:27:19 -07001873 mHandler.obtainMessage(H_SHUTDOWN, observer).sendToTarget();
San Mehat4270e1e2010-01-29 05:32:19 -08001874 }
1875
Jeff Sharkey48877892015-03-18 11:27:19 -07001876 @Override
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001877 public void mount(String volId) {
1878 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001879
Jeff Sharkeyef10ee02015-07-05 14:17:27 -07001880 final VolumeInfo vol = findVolumeByIdOrThrow(volId);
Jeff Sharkey2e606d72015-07-27 14:19:54 -07001881 if (isMountDisallowed(vol)) {
1882 throw new SecurityException("Mounting " + volId + " restricted by policy");
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001883 }
Sudheer Shanka3f0645b2018-09-18 13:07:59 -07001884 mount(vol);
1885 }
1886
1887 private void mount(VolumeInfo vol) {
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001888 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06001889 mVold.mount(vol.id, vol.mountFlags, vol.mountUserId);
Jeff Sharkeyace874b2017-09-07 15:27:33 -06001890 } catch (Exception e) {
1891 Slog.wtf(TAG, e);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001892 }
1893 }
1894
1895 @Override
1896 public void unmount(String volId) {
1897 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001898
Jeff Sharkeyef10ee02015-07-05 14:17:27 -07001899 final VolumeInfo vol = findVolumeByIdOrThrow(volId);
Sudheer Shanka3f0645b2018-09-18 13:07:59 -07001900 unmount(vol);
1901 }
1902
1903 private void unmount(VolumeInfo vol) {
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001904 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06001905 mVold.unmount(vol.id);
Jeff Sharkeyace874b2017-09-07 15:27:33 -06001906 } catch (Exception e) {
1907 Slog.wtf(TAG, e);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001908 }
1909 }
1910
1911 @Override
1912 public void format(String volId) {
Jeff Sharkey48877892015-03-18 11:27:19 -07001913 enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);
San Mehat5b77dab2010-01-26 13:28:50 -08001914
Jeff Sharkeyef10ee02015-07-05 14:17:27 -07001915 final VolumeInfo vol = findVolumeByIdOrThrow(volId);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001916 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06001917 mVold.format(vol.id, "auto");
Jeff Sharkeyace874b2017-09-07 15:27:33 -06001918 } catch (Exception e) {
1919 Slog.wtf(TAG, e);
Jeff Sharkey48877892015-03-18 11:27:19 -07001920 }
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001921 }
1922
1923 @Override
Jeff Sharkey7e19f532017-11-06 13:54:11 -07001924 public void benchmark(String volId, IVoldTaskListener listener) {
Jeff Sharkey9756d752015-05-14 21:07:42 -07001925 enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);
Jeff Sharkey9756d752015-05-14 21:07:42 -07001926
1927 try {
Jeff Sharkeyb302c542017-09-15 12:57:59 -06001928 mVold.benchmark(volId, new IVoldTaskListener.Stub() {
1929 @Override
1930 public void onStatus(int status, PersistableBundle extras) {
Jeff Sharkey7e19f532017-11-06 13:54:11 -07001931 dispatchOnStatus(listener, status, extras);
Jeff Sharkeyb302c542017-09-15 12:57:59 -06001932 }
1933
1934 @Override
1935 public void onFinished(int status, PersistableBundle extras) {
Jeff Sharkey7e19f532017-11-06 13:54:11 -07001936 dispatchOnFinished(listener, status, extras);
Jeff Sharkeyb302c542017-09-15 12:57:59 -06001937
1938 final String path = extras.getString("path");
1939 final String ident = extras.getString("ident");
1940 final long create = extras.getLong("create");
1941 final long run = extras.getLong("run");
1942 final long destroy = extras.getLong("destroy");
1943
1944 final DropBoxManager dropBox = mContext.getSystemService(DropBoxManager.class);
1945 dropBox.addText(TAG_STORAGE_BENCHMARK, scrubPath(path)
1946 + " " + ident + " " + create + " " + run + " " + destroy);
1947
1948 synchronized (mLock) {
1949 final VolumeRecord rec = findRecordForPath(path);
1950 if (rec != null) {
1951 rec.lastBenchMillis = System.currentTimeMillis();
1952 writeSettingsLocked();
1953 }
1954 }
1955 }
1956 });
Jeff Sharkey7e19f532017-11-06 13:54:11 -07001957 } catch (RemoteException e) {
1958 throw e.rethrowAsRuntimeException();
Jeff Sharkey9756d752015-05-14 21:07:42 -07001959 }
1960 }
1961
1962 @Override
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001963 public void partitionPublic(String diskId) {
1964 enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001965
Jeff Sharkeyeba260d2015-04-19 14:35:16 -07001966 final CountDownLatch latch = findOrCreateDiskScanLatch(diskId);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001967 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06001968 mVold.partition(diskId, IVold.PARTITION_TYPE_PUBLIC, -1);
Jeff Sharkeyedcdaf62015-07-09 09:45:36 -07001969 waitForLatch(latch, "partitionPublic", 3 * DateUtils.MINUTE_IN_MILLIS);
Jeff Sharkeyace874b2017-09-07 15:27:33 -06001970 } catch (Exception e) {
1971 Slog.wtf(TAG, e);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001972 }
1973 }
1974
1975 @Override
1976 public void partitionPrivate(String diskId) {
1977 enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);
Amith Yamasani462ac3a2015-06-30 14:21:01 -07001978 enforceAdminUser();
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_PRIVATE, -1);
Jeff Sharkeyedcdaf62015-07-09 09:45:36 -07001983 waitForLatch(latch, "partitionPrivate", 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 partitionMixed(String diskId, int ratio) {
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_MIXED, ratio);
Jeff Sharkeyedcdaf62015-07-09 09:45:36 -07001997 waitForLatch(latch, "partitionMixed", 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 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002001 }
2002
Jeff Sharkey48877892015-03-18 11:27:19 -07002003 @Override
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07002004 public void setVolumeNickname(String fsUuid, String nickname) {
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07002005 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07002006
Jeff Sharkey50a05452015-04-29 11:24:52 -07002007 Preconditions.checkNotNull(fsUuid);
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07002008 synchronized (mLock) {
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07002009 final VolumeRecord rec = mRecords.get(fsUuid);
2010 rec.nickname = nickname;
Jeff Sharkey50a05452015-04-29 11:24:52 -07002011 mCallbacks.notifyVolumeRecordChanged(rec);
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07002012 writeSettingsLocked();
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07002013 }
2014 }
2015
2016 @Override
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07002017 public void setVolumeUserFlags(String fsUuid, int flags, int mask) {
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07002018 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07002019
Jeff Sharkey50a05452015-04-29 11:24:52 -07002020 Preconditions.checkNotNull(fsUuid);
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07002021 synchronized (mLock) {
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07002022 final VolumeRecord rec = mRecords.get(fsUuid);
2023 rec.userFlags = (rec.userFlags & ~mask) | (flags & mask);
Jeff Sharkey50a05452015-04-29 11:24:52 -07002024 mCallbacks.notifyVolumeRecordChanged(rec);
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07002025 writeSettingsLocked();
2026 }
2027 }
2028
2029 @Override
2030 public void forgetVolume(String fsUuid) {
2031 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07002032
Jeff Sharkey50a05452015-04-29 11:24:52 -07002033 Preconditions.checkNotNull(fsUuid);
Jeff Sharkey5a9bb742015-11-03 10:15:57 -08002034
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07002035 synchronized (mLock) {
Jeff Sharkey5cc0df22015-06-17 19:44:05 -07002036 final VolumeRecord rec = mRecords.remove(fsUuid);
2037 if (rec != null && !TextUtils.isEmpty(rec.partGuid)) {
Jeff Sharkeydb4b6192017-10-24 11:08:50 -06002038 mHandler.obtainMessage(H_PARTITION_FORGET, rec).sendToTarget();
Jeff Sharkey5cc0df22015-06-17 19:44:05 -07002039 }
2040 mCallbacks.notifyVolumeForgotten(fsUuid);
Jeff Sharkey50a05452015-04-29 11:24:52 -07002041
2042 // If this had been primary storage, revert back to internal and
2043 // reset vold so we bind into new volume into place.
2044 if (Objects.equals(mPrimaryStorageUuid, fsUuid)) {
Jeff Sharkeyfced5342015-05-10 14:53:34 -07002045 mPrimaryStorageUuid = getDefaultPrimaryStorageUuid();
Jeff Sharkey5a9bb742015-11-03 10:15:57 -08002046 mHandler.obtainMessage(H_RESET).sendToTarget();
Jeff Sharkey50a05452015-04-29 11:24:52 -07002047 }
2048
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07002049 writeSettingsLocked();
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07002050 }
2051 }
2052
Jeff Sharkey7d2af542015-05-12 15:27:15 -07002053 @Override
2054 public void forgetAllVolumes() {
2055 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
Jeff Sharkey7d2af542015-05-12 15:27:15 -07002056
Jeff Sharkey50a05452015-04-29 11:24:52 -07002057 synchronized (mLock) {
2058 for (int i = 0; i < mRecords.size(); i++) {
2059 final String fsUuid = mRecords.keyAt(i);
Jeff Sharkey5cc0df22015-06-17 19:44:05 -07002060 final VolumeRecord rec = mRecords.valueAt(i);
2061 if (!TextUtils.isEmpty(rec.partGuid)) {
Jeff Sharkeydb4b6192017-10-24 11:08:50 -06002062 mHandler.obtainMessage(H_PARTITION_FORGET, rec).sendToTarget();
Jeff Sharkey5cc0df22015-06-17 19:44:05 -07002063 }
Jeff Sharkey50a05452015-04-29 11:24:52 -07002064 mCallbacks.notifyVolumeForgotten(fsUuid);
2065 }
Jeff Sharkey50a05452015-04-29 11:24:52 -07002066 mRecords.clear();
Jeff Sharkey50a05452015-04-29 11:24:52 -07002067
Jeff Sharkeyfced5342015-05-10 14:53:34 -07002068 if (!Objects.equals(StorageManager.UUID_PRIVATE_INTERNAL, mPrimaryStorageUuid)) {
2069 mPrimaryStorageUuid = getDefaultPrimaryStorageUuid();
2070 }
2071
2072 writeSettingsLocked();
Jeff Sharkey5a9bb742015-11-03 10:15:57 -08002073 mHandler.obtainMessage(H_RESET).sendToTarget();
Jeff Sharkey50a05452015-04-29 11:24:52 -07002074 }
2075 }
2076
Jeff Sharkeydb4b6192017-10-24 11:08:50 -06002077 private void forgetPartition(String partGuid, String fsUuid) {
Jeff Sharkey5cc0df22015-06-17 19:44:05 -07002078 try {
Jeff Sharkeydb4b6192017-10-24 11:08:50 -06002079 mVold.forgetPartition(partGuid, fsUuid);
Jeff Sharkeyace874b2017-09-07 15:27:33 -06002080 } catch (Exception e) {
2081 Slog.wtf(TAG, e);
Jeff Sharkey5cc0df22015-06-17 19:44:05 -07002082 }
2083 }
2084
Jeff Sharkey31d0b702016-11-21 14:16:53 -07002085 @Override
Jeff Sharkey7e19f532017-11-06 13:54:11 -07002086 public void fstrim(int flags, IVoldTaskListener listener) {
Jeff Sharkey31d0b702016-11-21 14:16:53 -07002087 enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);
Jeff Sharkey31d0b702016-11-21 14:16:53 -07002088
2089 try {
Jeff Sharkeyb302c542017-09-15 12:57:59 -06002090 mVold.fstrim(flags, new IVoldTaskListener.Stub() {
2091 @Override
2092 public void onStatus(int status, PersistableBundle extras) {
Jeff Sharkey7e19f532017-11-06 13:54:11 -07002093 dispatchOnStatus(listener, status, extras);
2094
Jeff Sharkeyb302c542017-09-15 12:57:59 -06002095 // Ignore trim failures
2096 if (status != 0) return;
2097
2098 final String path = extras.getString("path");
2099 final long bytes = extras.getLong("bytes");
2100 final long time = extras.getLong("time");
2101
2102 final DropBoxManager dropBox = mContext.getSystemService(DropBoxManager.class);
2103 dropBox.addText(TAG_STORAGE_TRIM, scrubPath(path) + " " + bytes + " " + time);
2104
2105 synchronized (mLock) {
2106 final VolumeRecord rec = findRecordForPath(path);
2107 if (rec != null) {
2108 rec.lastTrimMillis = System.currentTimeMillis();
2109 writeSettingsLocked();
2110 }
2111 }
2112 }
2113
2114 @Override
2115 public void onFinished(int status, PersistableBundle extras) {
Jeff Sharkey7e19f532017-11-06 13:54:11 -07002116 dispatchOnFinished(listener, status, extras);
2117
Jeff Sharkeyb302c542017-09-15 12:57:59 -06002118 // TODO: benchmark when desired
2119 }
2120 });
Jeff Sharkey7e19f532017-11-06 13:54:11 -07002121 } catch (RemoteException e) {
2122 throw e.rethrowAsRuntimeException();
Jeff Sharkey31d0b702016-11-21 14:16:53 -07002123 }
2124 }
2125
Jin Qiana85b9912017-10-17 15:48:18 -07002126 void runIdleMaint(Runnable callback) {
2127 enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);
2128
2129 try {
2130 mVold.runIdleMaint(new IVoldTaskListener.Stub() {
2131 @Override
2132 public void onStatus(int status, PersistableBundle extras) {
2133 // Not currently used
2134 }
2135 @Override
2136 public void onFinished(int status, PersistableBundle extras) {
2137 if (callback != null) {
2138 BackgroundThread.getHandler().post(callback);
2139 }
2140 }
2141 });
2142 } catch (Exception e) {
2143 Slog.wtf(TAG, e);
2144 }
2145 }
2146
2147 @Override
2148 public void runIdleMaintenance() {
2149 runIdleMaint(null);
2150 }
2151
2152 void abortIdleMaint(Runnable callback) {
2153 enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);
2154
2155 try {
2156 mVold.abortIdleMaint(new IVoldTaskListener.Stub() {
2157 @Override
2158 public void onStatus(int status, PersistableBundle extras) {
2159 // Not currently used
2160 }
2161 @Override
2162 public void onFinished(int status, PersistableBundle extras) {
2163 if (callback != null) {
2164 BackgroundThread.getHandler().post(callback);
2165 }
2166 }
2167 });
2168 } catch (Exception e) {
2169 Slog.wtf(TAG, e);
2170 }
2171 }
2172
2173 @Override
2174 public void abortIdleMaintenance() {
2175 abortIdleMaint(null);
2176 }
2177
Svet Ganov6ee871e2015-07-10 14:29:33 -07002178 private void remountUidExternalStorage(int uid, int mode) {
Jeff Sharkey9527b222015-06-24 15:24:48 -07002179 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002180 mVold.remountUid(uid, mode);
Jeff Sharkeyace874b2017-09-07 15:27:33 -06002181 } catch (Exception e) {
2182 Slog.wtf(TAG, e);
Jeff Sharkey9527b222015-06-24 15:24:48 -07002183 }
2184 }
2185
2186 @Override
Jeff Sharkey4c099d02015-05-15 13:45:00 -07002187 public void setDebugFlags(int flags, int mask) {
2188 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
Jeff Sharkey4c099d02015-05-15 13:45:00 -07002189
Jeff Sharkeyba512352015-11-12 20:17:45 -08002190 if ((mask & StorageManager.DEBUG_EMULATE_FBE) != 0) {
Jeff Sharkey00455bf2016-11-04 14:45:24 -06002191 if (!EMULATE_FBE_SUPPORTED) {
2192 throw new IllegalStateException(
2193 "Emulation not supported on this device");
2194 }
Paul Lawrence20be5d62016-02-26 13:51:17 -08002195 if (StorageManager.isFileEncryptedNativeOnly()) {
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07002196 throw new IllegalStateException(
Jeff Sharkey00455bf2016-11-04 14:45:24 -06002197 "Emulation not supported on device with native FBE");
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07002198 }
Jeff Sharkey5a785162016-03-21 13:02:06 -06002199 if (mLockPatternUtils.isCredentialRequiredToDecrypt(false)) {
2200 throw new IllegalStateException(
2201 "Emulation requires disabling 'Secure start-up' in Settings > Security");
2202 }
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07002203
Jeff Sharkey1176e512016-02-29 17:01:26 -07002204 final long token = Binder.clearCallingIdentity();
2205 try {
2206 final boolean emulateFbe = (flags & StorageManager.DEBUG_EMULATE_FBE) != 0;
2207 SystemProperties.set(StorageManager.PROP_EMULATE_FBE, Boolean.toString(emulateFbe));
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07002208
Jeff Sharkey1176e512016-02-29 17:01:26 -07002209 // Perform hard reboot to kick policy into place
2210 mContext.getSystemService(PowerManager.class).reboot(null);
2211 } finally {
2212 Binder.restoreCallingIdentity(token);
2213 }
Jeff Sharkeyba512352015-11-12 20:17:45 -08002214 }
Jeff Sharkey4c099d02015-05-15 13:45:00 -07002215
Jeff Sharkey901c0422018-04-20 13:11:20 -06002216 if ((mask & (StorageManager.DEBUG_ADOPTABLE_FORCE_ON
2217 | StorageManager.DEBUG_ADOPTABLE_FORCE_OFF)) != 0) {
2218 final String value;
2219 if ((flags & StorageManager.DEBUG_ADOPTABLE_FORCE_ON) != 0) {
2220 value = "force_on";
2221 } else if ((flags & StorageManager.DEBUG_ADOPTABLE_FORCE_OFF) != 0) {
2222 value = "force_off";
2223 } else {
2224 value = "";
2225 }
Jeff Sharkeyba512352015-11-12 20:17:45 -08002226
Jeff Sharkey901c0422018-04-20 13:11:20 -06002227 final long token = Binder.clearCallingIdentity();
2228 try {
2229 SystemProperties.set(StorageManager.PROP_ADOPTABLE, value);
2230
2231 // Reset storage to kick new setting into place
Jeff Sharkeyba512352015-11-12 20:17:45 -08002232 mHandler.obtainMessage(H_RESET).sendToTarget();
Jeff Sharkey901c0422018-04-20 13:11:20 -06002233 } finally {
2234 Binder.restoreCallingIdentity(token);
Jeff Sharkeyba512352015-11-12 20:17:45 -08002235 }
Jeff Sharkey4c099d02015-05-15 13:45:00 -07002236 }
Jeff Sharkey33dd1562016-04-07 11:05:33 -06002237
2238 if ((mask & (StorageManager.DEBUG_SDCARDFS_FORCE_ON
2239 | StorageManager.DEBUG_SDCARDFS_FORCE_OFF)) != 0) {
2240 final String value;
2241 if ((flags & StorageManager.DEBUG_SDCARDFS_FORCE_ON) != 0) {
2242 value = "force_on";
2243 } else if ((flags & StorageManager.DEBUG_SDCARDFS_FORCE_OFF) != 0) {
2244 value = "force_off";
2245 } else {
2246 value = "";
2247 }
2248
2249 final long token = Binder.clearCallingIdentity();
2250 try {
2251 SystemProperties.set(StorageManager.PROP_SDCARDFS, value);
2252
2253 // Reset storage to kick new setting into place
2254 mHandler.obtainMessage(H_RESET).sendToTarget();
2255 } finally {
2256 Binder.restoreCallingIdentity(token);
2257 }
2258 }
Jeff Sharkeye53e2d92017-03-25 23:14:06 -06002259
2260 if ((mask & StorageManager.DEBUG_VIRTUAL_DISK) != 0) {
2261 final boolean enabled = (flags & StorageManager.DEBUG_VIRTUAL_DISK) != 0;
2262
2263 final long token = Binder.clearCallingIdentity();
2264 try {
2265 SystemProperties.set(StorageManager.PROP_VIRTUAL_DISK, Boolean.toString(enabled));
2266
2267 // Reset storage to kick new setting into place
2268 mHandler.obtainMessage(H_RESET).sendToTarget();
2269 } finally {
2270 Binder.restoreCallingIdentity(token);
2271 }
2272 }
Sudheer Shankabe0febe2018-11-07 18:24:37 -08002273
Jeff Sharkeyb0c363b22018-12-15 11:53:03 -07002274 if ((mask & (StorageManager.DEBUG_ISOLATED_STORAGE_FORCE_ON
2275 | StorageManager.DEBUG_ISOLATED_STORAGE_FORCE_OFF)) != 0) {
2276 final int value;
2277 if ((flags & StorageManager.DEBUG_ISOLATED_STORAGE_FORCE_ON) != 0) {
2278 value = 1;
2279 } else if ((flags & StorageManager.DEBUG_ISOLATED_STORAGE_FORCE_OFF) != 0) {
2280 value = -1;
2281 } else {
2282 value = 0;
2283 }
Sudheer Shankabe0febe2018-11-07 18:24:37 -08002284
2285 final long token = Binder.clearCallingIdentity();
2286 try {
Jeff Sharkeyb0c363b22018-12-15 11:53:03 -07002287 Settings.Global.putInt(mContext.getContentResolver(),
2288 Settings.Global.ISOLATED_STORAGE_LOCAL, value);
2289 refreshIsolatedStorageSettings();
Sudheer Shankabe0febe2018-11-07 18:24:37 -08002290
2291 // Perform hard reboot to kick policy into place
2292 mContext.getSystemService(PowerManager.class).reboot(null);
2293 } finally {
2294 Binder.restoreCallingIdentity(token);
2295 }
2296 }
Jeff Sharkey4c099d02015-05-15 13:45:00 -07002297 }
2298
2299 @Override
Jeff Sharkey275e3e42015-04-24 16:10:32 -07002300 public String getPrimaryStorageUuid() {
Jeff Sharkey620b32b2015-04-23 19:36:02 -07002301 synchronized (mLock) {
2302 return mPrimaryStorageUuid;
2303 }
2304 }
2305
2306 @Override
Jeff Sharkey275e3e42015-04-24 16:10:32 -07002307 public void setPrimaryStorageUuid(String volumeUuid, IPackageMoveObserver callback) {
2308 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
Jeff Sharkey620b32b2015-04-23 19:36:02 -07002309
Jeff Sharkeya31460c2016-06-22 09:04:33 -06002310 final VolumeInfo from;
2311 final VolumeInfo to;
2312
Jeff Sharkey275e3e42015-04-24 16:10:32 -07002313 synchronized (mLock) {
Jeff Sharkeyfced5342015-05-10 14:53:34 -07002314 if (Objects.equals(mPrimaryStorageUuid, volumeUuid)) {
2315 throw new IllegalArgumentException("Primary storage already at " + volumeUuid);
Jeff Sharkey275e3e42015-04-24 16:10:32 -07002316 }
2317
2318 if (mMoveCallback != null) {
2319 throw new IllegalStateException("Move already in progress");
2320 }
2321 mMoveCallback = callback;
2322 mMoveTargetUuid = volumeUuid;
2323
Jeff Sharkeya65e6492017-06-21 13:45:11 -06002324 // We need all the users unlocked to move their primary storage
2325 final List<UserInfo> users = mContext.getSystemService(UserManager.class).getUsers();
2326 for (UserInfo user : users) {
2327 if (StorageManager.isFileEncryptedNativeOrEmulated()
2328 && !isUserKeyUnlocked(user.id)) {
2329 Slog.w(TAG, "Failing move due to locked user " + user.id);
2330 onMoveStatusLocked(PackageManager.MOVE_FAILED_LOCKED_USER);
2331 return;
2332 }
2333 }
2334
Jeff Sharkeyfced5342015-05-10 14:53:34 -07002335 // When moving to/from primary physical volume, we probably just nuked
2336 // the current storage location, so we have nothing to move.
2337 if (Objects.equals(StorageManager.UUID_PRIMARY_PHYSICAL, mPrimaryStorageUuid)
2338 || Objects.equals(StorageManager.UUID_PRIMARY_PHYSICAL, volumeUuid)) {
2339 Slog.d(TAG, "Skipping move to/from primary physical");
2340 onMoveStatusLocked(MOVE_STATUS_COPY_FINISHED);
2341 onMoveStatusLocked(PackageManager.MOVE_SUCCEEDED);
Jeff Sharkey5a9bb742015-11-03 10:15:57 -08002342 mHandler.obtainMessage(H_RESET).sendToTarget();
Jeff Sharkeya31460c2016-06-22 09:04:33 -06002343 return;
Jeff Sharkeyfced5342015-05-10 14:53:34 -07002344
2345 } else {
Jeff Sharkeya31460c2016-06-22 09:04:33 -06002346 from = findStorageForUuid(mPrimaryStorageUuid);
2347 to = findStorageForUuid(volumeUuid);
Jeff Sharkeyef10ee02015-07-05 14:17:27 -07002348
2349 if (from == null) {
2350 Slog.w(TAG, "Failing move due to missing from volume " + mPrimaryStorageUuid);
2351 onMoveStatusLocked(PackageManager.MOVE_FAILED_INTERNAL_ERROR);
2352 return;
2353 } else if (to == null) {
2354 Slog.w(TAG, "Failing move due to missing to volume " + volumeUuid);
2355 onMoveStatusLocked(PackageManager.MOVE_FAILED_INTERNAL_ERROR);
2356 return;
2357 }
Jeff Sharkey275e3e42015-04-24 16:10:32 -07002358 }
Jeff Sharkey620b32b2015-04-23 19:36:02 -07002359 }
Jeff Sharkeya31460c2016-06-22 09:04:33 -06002360
2361 try {
Jeff Sharkeyb302c542017-09-15 12:57:59 -06002362 mVold.moveStorage(from.id, to.id, new IVoldTaskListener.Stub() {
2363 @Override
2364 public void onStatus(int status, PersistableBundle extras) {
2365 synchronized (mLock) {
2366 onMoveStatusLocked(status);
2367 }
2368 }
2369
2370 @Override
2371 public void onFinished(int status, PersistableBundle extras) {
2372 // Not currently used
2373 }
2374 });
Jeff Sharkeyace874b2017-09-07 15:27:33 -06002375 } catch (Exception e) {
2376 Slog.wtf(TAG, e);
Jeff Sharkeya31460c2016-06-22 09:04:33 -06002377 }
Jeff Sharkey620b32b2015-04-23 19:36:02 -07002378 }
2379
San Mehatb1043402010-02-05 08:26:50 -08002380 private void warnOnNotMounted() {
Jeff Sharkey48877892015-03-18 11:27:19 -07002381 synchronized (mLock) {
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07002382 for (int i = 0; i < mVolumes.size(); i++) {
2383 final VolumeInfo vol = mVolumes.valueAt(i);
Jeff Sharkey27de30d2015-04-18 16:20:27 -07002384 if (vol.isPrimary() && vol.isMountedWritable()) {
Jeff Sharkey48877892015-03-18 11:27:19 -07002385 // Cool beans, we have a mounted primary volume
2386 return;
2387 }
Jeff Sharkey32ee8312012-09-30 13:21:31 -07002388 }
San Mehatb1043402010-02-05 08:26:50 -08002389 }
Jeff Sharkey48877892015-03-18 11:27:19 -07002390
2391 Slog.w(TAG, "No primary storage mounted!");
San Mehatb1043402010-02-05 08:26:50 -08002392 }
2393
Kenny Roota02b8b02010-08-05 16:14:17 -07002394 private boolean isUidOwnerOfPackageOrSystem(String packageName, int callerUid) {
2395 if (callerUid == android.os.Process.SYSTEM_UID) {
2396 return true;
2397 }
2398
Kenny Root02c87302010-07-01 08:10:18 -07002399 if (packageName == null) {
2400 return false;
2401 }
2402
Jeff Sharkey5790af02018-08-13 17:42:54 -06002403 final int packageUid = mPmInternal.getPackageUid(packageName,
Jeff Sharkeycd654482016-01-08 17:42:11 -07002404 PackageManager.MATCH_DEBUG_TRIAGED_MISSING, UserHandle.getUserId(callerUid));
Kenny Root02c87302010-07-01 08:10:18 -07002405
2406 if (DEBUG_OBB) {
2407 Slog.d(TAG, "packageName = " + packageName + ", packageUid = " +
2408 packageUid + ", callerUid = " + callerUid);
2409 }
2410
2411 return callerUid == packageUid;
2412 }
2413
Jeff Sharkey54402792017-09-15 16:05:19 -06002414 @Override
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002415 public String getMountedObbPath(String rawPath) {
2416 Preconditions.checkNotNull(rawPath, "rawPath cannot be null");
Kenny Rootaf9d6672010-10-08 09:21:39 -07002417
Kenny Root02c87302010-07-01 08:10:18 -07002418 warnOnNotMounted();
2419
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002420 final ObbState state;
Rubin Xucd7a0142015-04-17 23:45:27 +01002421 synchronized (mObbMounts) {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002422 state = mObbPathToStateMap.get(rawPath);
2423 }
2424 if (state == null) {
2425 Slog.w(TAG, "Failed to find OBB mounted at " + rawPath);
2426 return null;
2427 }
2428
Jeff Sharkey54402792017-09-15 16:05:19 -06002429 return findVolumeByIdOrThrow(state.volId).getPath().getAbsolutePath();
Kenny Root02c87302010-07-01 08:10:18 -07002430 }
2431
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002432 @Override
2433 public boolean isObbMounted(String rawPath) {
2434 Preconditions.checkNotNull(rawPath, "rawPath cannot be null");
Kenny Rootaf9d6672010-10-08 09:21:39 -07002435 synchronized (mObbMounts) {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002436 return mObbPathToStateMap.containsKey(rawPath);
Kenny Rootaf9d6672010-10-08 09:21:39 -07002437 }
Kenny Root02c87302010-07-01 08:10:18 -07002438 }
2439
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002440 @Override
Sudheer Shanka25469aa2018-08-27 15:50:23 -07002441 public void mountObb(String rawPath, String canonicalPath, String key,
2442 IObbActionListener token, int nonce, ObbInfo obbInfo) {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002443 Preconditions.checkNotNull(rawPath, "rawPath cannot be null");
2444 Preconditions.checkNotNull(canonicalPath, "canonicalPath cannot be null");
2445 Preconditions.checkNotNull(token, "token cannot be null");
Sudheer Shanka25469aa2018-08-27 15:50:23 -07002446 Preconditions.checkNotNull(obbInfo, "obbIfno cannot be null");
Kenny Rootaf9d6672010-10-08 09:21:39 -07002447
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002448 final int callingUid = Binder.getCallingUid();
Jeff Sharkey41cd6812017-09-11 10:32:17 -06002449 final ObbState obbState = new ObbState(rawPath, canonicalPath,
2450 callingUid, token, nonce, null);
Sudheer Shanka25469aa2018-08-27 15:50:23 -07002451 final ObbAction action = new MountObbAction(obbState, key, callingUid, obbInfo);
Kenny Roota02b8b02010-08-05 16:14:17 -07002452 mObbActionHandler.sendMessage(mObbActionHandler.obtainMessage(OBB_RUN_ACTION, action));
2453
2454 if (DEBUG_OBB)
2455 Slog.i(TAG, "Send to OBB handler: " + action.toString());
Kenny Root02c87302010-07-01 08:10:18 -07002456 }
2457
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002458 @Override
2459 public void unmountObb(String rawPath, boolean force, IObbActionListener token, int nonce) {
2460 Preconditions.checkNotNull(rawPath, "rawPath cannot be null");
2461
2462 final ObbState existingState;
Rubin Xucd7a0142015-04-17 23:45:27 +01002463 synchronized (mObbMounts) {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002464 existingState = mObbPathToStateMap.get(rawPath);
Kenny Rootf1121dc2010-09-29 07:30:53 -07002465 }
2466
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002467 if (existingState != null) {
2468 // TODO: separate state object from request data
2469 final int callingUid = Binder.getCallingUid();
Jeff Sharkey41cd6812017-09-11 10:32:17 -06002470 final ObbState newState = new ObbState(rawPath, existingState.canonicalPath,
2471 callingUid, token, nonce, existingState.volId);
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002472 final ObbAction action = new UnmountObbAction(newState, force);
2473 mObbActionHandler.sendMessage(mObbActionHandler.obtainMessage(OBB_RUN_ACTION, action));
Kenny Root02c87302010-07-01 08:10:18 -07002474
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002475 if (DEBUG_OBB)
2476 Slog.i(TAG, "Send to OBB handler: " + action.toString());
2477 } else {
2478 Slog.w(TAG, "Unknown OBB mount at " + rawPath);
2479 }
Kenny Roota02b8b02010-08-05 16:14:17 -07002480 }
2481
Ben Komalo444eca22011-09-01 15:17:44 -07002482 @Override
2483 public int getEncryptionState() {
2484 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
2485 "no permission to access the crypt keeper");
2486
Ben Komalo444eca22011-09-01 15:17:44 -07002487 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002488 return mVold.fdeComplete();
2489 } catch (Exception e) {
2490 Slog.wtf(TAG, e);
Sudheer Shankaf7341142016-10-18 17:15:18 -07002491 return StorageManager.ENCRYPTION_STATE_ERROR_UNKNOWN;
Ben Komalo444eca22011-09-01 15:17:44 -07002492 }
2493 }
2494
2495 @Override
Jason parks5af0b912010-11-29 09:05:25 -06002496 public int decryptStorage(String password) {
Jason parks8888c592011-01-20 22:46:41 -06002497 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
2498 "no permission to access the crypt keeper");
Jason parks5af0b912010-11-29 09:05:25 -06002499
Jeff Sharkey8058fe62017-09-13 11:50:33 -06002500 if (TextUtils.isEmpty(password)) {
2501 throw new IllegalArgumentException("password cannot be empty");
2502 }
2503
Jason parks5af0b912010-11-29 09:05:25 -06002504 if (DEBUG_EVENTS) {
2505 Slog.i(TAG, "decrypting storage...");
2506 }
2507
2508 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002509 mVold.fdeCheckPassword(password);
2510 mHandler.postDelayed(() -> {
2511 try {
2512 mVold.fdeRestart();
2513 } catch (Exception e) {
2514 Slog.wtf(TAG, e);
2515 }
2516 }, DateUtils.SECOND_IN_MILLIS);
2517 return 0;
Paul Crowleyfc0b5192018-07-02 13:58:10 -07002518 } catch (ServiceSpecificException e) {
2519 Slog.e(TAG, "fdeCheckPassword failed", e);
2520 return e.errorCode;
Jeff Sharkey54402792017-09-15 16:05:19 -06002521 } catch (Exception e) {
2522 Slog.wtf(TAG, e);
2523 return StorageManager.ENCRYPTION_STATE_ERROR_UNKNOWN;
Jason parks5af0b912010-11-29 09:05:25 -06002524 }
Jason parks5af0b912010-11-29 09:05:25 -06002525 }
2526
Jeff Sharkey54402792017-09-15 16:05:19 -06002527 @Override
Paul Lawrence46791e72014-04-03 09:10:26 -07002528 public int encryptStorage(int type, String password) {
Jason parks8888c592011-01-20 22:46:41 -06002529 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
2530 "no permission to access the crypt keeper");
Jason parks56aa5322011-01-07 09:01:15 -06002531
Jeff Sharkey8058fe62017-09-13 11:50:33 -06002532 if (type == StorageManager.CRYPT_TYPE_DEFAULT) {
2533 password = "";
2534 } else if (TextUtils.isEmpty(password)) {
2535 throw new IllegalArgumentException("password cannot be empty");
2536 }
2537
Jason parks56aa5322011-01-07 09:01:15 -06002538 if (DEBUG_EVENTS) {
Jason parks8888c592011-01-20 22:46:41 -06002539 Slog.i(TAG, "encrypting storage...");
Jason parks56aa5322011-01-07 09:01:15 -06002540 }
2541
2542 try {
Paul Lawrence89a0ae42017-12-22 10:11:10 -08002543 mVold.fdeEnable(type, password, 0);
Jeff Sharkey43e12112017-09-12 16:31:45 -06002544 } catch (Exception e) {
2545 Slog.wtf(TAG, e);
2546 return -1;
Jason parks56aa5322011-01-07 09:01:15 -06002547 }
2548
2549 return 0;
2550 }
2551
Paul Lawrence8e397362014-01-27 15:22:30 -08002552 /** Set the password for encrypting the master key.
2553 * @param type One of the CRYPTO_TYPE_XXX consts defined in StorageManager.
2554 * @param password The password to set.
2555 */
Jeff Sharkey54402792017-09-15 16:05:19 -06002556 @Override
Paul Lawrence8e397362014-01-27 15:22:30 -08002557 public int changeEncryptionPassword(int type, String password) {
Jason parksf7b3cd42011-01-27 09:28:25 -06002558 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
2559 "no permission to access the crypt keeper");
2560
Jeff Sharkeyae266462017-11-27 13:32:24 -07002561 if (StorageManager.isFileEncryptedNativeOnly()) {
2562 // Not supported on FBE devices
2563 return -1;
2564 }
2565
Jeff Sharkey8058fe62017-09-13 11:50:33 -06002566 if (type == StorageManager.CRYPT_TYPE_DEFAULT) {
2567 password = "";
2568 } else if (TextUtils.isEmpty(password)) {
2569 throw new IllegalArgumentException("password cannot be empty");
2570 }
2571
Jason parksf7b3cd42011-01-27 09:28:25 -06002572 if (DEBUG_EVENTS) {
2573 Slog.i(TAG, "changing encryption password...");
2574 }
2575
2576 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002577 mVold.fdeChangePassword(type, password);
2578 return 0;
2579 } catch (Exception e) {
2580 Slog.wtf(TAG, e);
2581 return -1;
Jason parksf7b3cd42011-01-27 09:28:25 -06002582 }
2583 }
2584
Christopher Tate32418be2011-10-10 13:51:12 -07002585 /**
2586 * Validate a user-supplied password string with cryptfs
2587 */
2588 @Override
2589 public int verifyEncryptionPassword(String password) throws RemoteException {
2590 // Only the system process is permitted to validate passwords
2591 if (Binder.getCallingUid() != android.os.Process.SYSTEM_UID) {
2592 throw new SecurityException("no permission to access the crypt keeper");
2593 }
2594
2595 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
2596 "no permission to access the crypt keeper");
2597
2598 if (TextUtils.isEmpty(password)) {
2599 throw new IllegalArgumentException("password cannot be empty");
2600 }
2601
Christopher Tate32418be2011-10-10 13:51:12 -07002602 if (DEBUG_EVENTS) {
2603 Slog.i(TAG, "validating encryption password...");
2604 }
2605
2606 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002607 mVold.fdeVerifyPassword(password);
2608 return 0;
2609 } catch (Exception e) {
2610 Slog.wtf(TAG, e);
2611 return -1;
Christopher Tate32418be2011-10-10 13:51:12 -07002612 }
2613 }
2614
Paul Lawrence8e397362014-01-27 15:22:30 -08002615 /**
2616 * Get the type of encryption used to encrypt the master key.
2617 * @return The type, one of the CRYPT_TYPE_XXX consts from StorageManager.
2618 */
2619 @Override
Svetoslav16e4a1a2014-09-29 18:16:20 -07002620 public int getPasswordType() {
Paul Lawrence76a40572017-03-15 11:08:04 -07002621 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
Paul Lawrence9de713d2016-05-02 22:45:33 +00002622 "no permission to access the crypt keeper");
2623
Paul Lawrence8e397362014-01-27 15:22:30 -08002624 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002625 return mVold.fdeGetPasswordType();
2626 } catch (Exception e) {
2627 Slog.wtf(TAG, e);
2628 return -1;
Paul Lawrence8e397362014-01-27 15:22:30 -08002629 }
2630 }
2631
Paul Lawrencee51dcf92014-03-18 10:56:00 -07002632 /**
2633 * Set a field in the crypto header.
2634 * @param field field to set
2635 * @param contents contents to set in field
2636 */
2637 @Override
2638 public void setField(String field, String contents) throws RemoteException {
Paul Lawrence76a40572017-03-15 11:08:04 -07002639 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
Paul Lawrence0bbd1082016-04-26 15:21:02 -07002640 "no permission to access the crypt keeper");
Paul Lawrencee51dcf92014-03-18 10:56:00 -07002641
Jeff Sharkeyae266462017-11-27 13:32:24 -07002642 if (StorageManager.isFileEncryptedNativeOnly()) {
2643 // Not supported on FBE devices
2644 return;
2645 }
2646
Paul Lawrencee51dcf92014-03-18 10:56:00 -07002647 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002648 mVold.fdeSetField(field, contents);
2649 return;
2650 } catch (Exception e) {
2651 Slog.wtf(TAG, e);
2652 return;
Paul Lawrencee51dcf92014-03-18 10:56:00 -07002653 }
2654 }
2655
2656 /**
2657 * Gets a field from the crypto header.
2658 * @param field field to get
2659 * @return contents of field
2660 */
2661 @Override
2662 public String getField(String field) throws RemoteException {
Paul Lawrence76a40572017-03-15 11:08:04 -07002663 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
Paul Lawrence0bbd1082016-04-26 15:21:02 -07002664 "no permission to access the crypt keeper");
Paul Lawrencee51dcf92014-03-18 10:56:00 -07002665
Jeff Sharkeyae266462017-11-27 13:32:24 -07002666 if (StorageManager.isFileEncryptedNativeOnly()) {
2667 // Not supported on FBE devices
2668 return null;
2669 }
2670
Paul Lawrencee51dcf92014-03-18 10:56:00 -07002671 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002672 return mVold.fdeGetField(field);
2673 } catch (Exception e) {
2674 Slog.wtf(TAG, e);
2675 return null;
Paul Lawrencee51dcf92014-03-18 10:56:00 -07002676 }
2677 }
2678
Paul Lawrence3806d9c2015-10-29 10:30:46 -07002679 /**
2680 * Is userdata convertible to file based encryption?
2681 * @return non zero for convertible
2682 */
2683 @Override
2684 public boolean isConvertibleToFBE() throws RemoteException {
Paul Lawrence76a40572017-03-15 11:08:04 -07002685 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
Paul Lawrence0bbd1082016-04-26 15:21:02 -07002686 "no permission to access the crypt keeper");
Paul Lawrence3806d9c2015-10-29 10:30:46 -07002687
Paul Lawrence3806d9c2015-10-29 10:30:46 -07002688 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002689 return mVold.isConvertibleToFbe();
2690 } catch (Exception e) {
2691 Slog.wtf(TAG, e);
2692 return false;
Paul Lawrence3806d9c2015-10-29 10:30:46 -07002693 }
2694 }
2695
Daniel Rosenberge129e5c2018-11-07 19:25:55 -08002696 /**
2697 * Signal that checkpointing partitions should commit changes
2698 */
2699 @Override
2700 public void commitChanges() throws RemoteException {
2701 // Only the system process is permitted to commit checkpoints
2702 if (Binder.getCallingUid() != android.os.Process.SYSTEM_UID) {
2703 throw new SecurityException("no permission to commit checkpoint changes");
2704 }
2705
2706 mVold.commitChanges();
2707 }
2708
Jeff Sharkeyb049e212012-09-07 23:16:01 -07002709 @Override
Paul Lawrence945490c2014-03-27 16:37:28 +00002710 public String getPassword() throws RemoteException {
Paul Lawrence76a40572017-03-15 11:08:04 -07002711 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
Rubin Xucd7a0142015-04-17 23:45:27 +01002712 "only keyguard can retrieve password");
Paul Lawrence0bbd1082016-04-26 15:21:02 -07002713
Paul Lawrence945490c2014-03-27 16:37:28 +00002714 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002715 return mVold.fdeGetPassword();
2716 } catch (Exception e) {
2717 Slog.wtf(TAG, e);
Paul Lawrence24063b52015-01-06 13:11:23 -08002718 return null;
Paul Lawrence945490c2014-03-27 16:37:28 +00002719 }
2720 }
2721
2722 @Override
2723 public void clearPassword() throws RemoteException {
Paul Lawrence76a40572017-03-15 11:08:04 -07002724 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
Paul Lawrence0bbd1082016-04-26 15:21:02 -07002725 "only keyguard can clear password");
2726
Paul Lawrence945490c2014-03-27 16:37:28 +00002727 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002728 mVold.fdeClearPassword();
2729 return;
2730 } catch (Exception e) {
2731 Slog.wtf(TAG, e);
2732 return;
Paul Lawrence945490c2014-03-27 16:37:28 +00002733 }
2734 }
2735
2736 @Override
Lenka Trochtovac4dd0212015-11-18 12:22:06 +01002737 public void createUserKey(int userId, int serialNumber, boolean ephemeral) {
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002738 enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
Paul Crowleybcf48ed2015-04-22 13:36:59 +01002739
Paul Crowleybcf48ed2015-04-22 13:36:59 +01002740 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002741 mVold.createUserKey(userId, serialNumber, ephemeral);
Jeff Sharkey43e12112017-09-12 16:31:45 -06002742 } catch (Exception e) {
2743 Slog.wtf(TAG, e);
Paul Crowleybcf48ed2015-04-22 13:36:59 +01002744 }
2745 }
2746
Paul Crowley7ec733f2015-05-19 12:42:00 +01002747 @Override
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002748 public void destroyUserKey(int userId) {
2749 enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
Paul Crowley7ec733f2015-05-19 12:42:00 +01002750
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002751 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002752 mVold.destroyUserKey(userId);
Jeff Sharkey43e12112017-09-12 16:31:45 -06002753 } catch (Exception e) {
2754 Slog.wtf(TAG, e);
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002755 }
2756 }
2757
Jeff Sharkey43e12112017-09-12 16:31:45 -06002758 private String encodeBytes(byte[] bytes) {
Paul Crowleyfaeb3eb2016-02-08 15:58:29 +00002759 if (ArrayUtils.isEmpty(bytes)) {
Jeff Sharkey43e12112017-09-12 16:31:45 -06002760 return "!";
Paul Crowleyfaeb3eb2016-02-08 15:58:29 +00002761 } else {
Jeff Sharkey43e12112017-09-12 16:31:45 -06002762 return HexDump.toHexString(bytes);
Paul Crowleyfaeb3eb2016-02-08 15:58:29 +00002763 }
2764 }
2765
Paul Crowleycc701552016-05-17 14:18:49 -07002766 /*
2767 * Add this token/secret pair to the set of ways we can recover a disk encryption key.
2768 * Changing the token/secret for a disk encryption key is done in two phases: first, adding
2769 * a new token/secret pair with this call, then delting all other pairs with
2770 * fixateNewestUserKeyAuth. This allows other places where a credential is used, such as
2771 * Gatekeeper, to be updated between the two calls.
2772 */
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002773 @Override
Paul Crowleycc701552016-05-17 14:18:49 -07002774 public void addUserKeyAuth(int userId, int serialNumber, byte[] token, byte[] secret) {
Paul Crowleyfaeb3eb2016-02-08 15:58:29 +00002775 enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
Paul Crowleyfaeb3eb2016-02-08 15:58:29 +00002776
2777 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002778 mVold.addUserKeyAuth(userId, serialNumber, encodeBytes(token), encodeBytes(secret));
Jeff Sharkey43e12112017-09-12 16:31:45 -06002779 } catch (Exception e) {
2780 Slog.wtf(TAG, e);
Paul Crowleycc701552016-05-17 14:18:49 -07002781 }
2782 }
2783
2784 /*
2785 * Delete all disk encryption token/secret pairs except the most recently added one
2786 */
2787 @Override
2788 public void fixateNewestUserKeyAuth(int userId) {
2789 enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
Paul Crowleycc701552016-05-17 14:18:49 -07002790
2791 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002792 mVold.fixateNewestUserKeyAuth(userId);
Jeff Sharkey43e12112017-09-12 16:31:45 -06002793 } catch (Exception e) {
2794 Slog.wtf(TAG, e);
Paul Crowleyfaeb3eb2016-02-08 15:58:29 +00002795 }
2796 }
2797
2798 @Override
2799 public void unlockUserKey(int userId, int serialNumber, byte[] token, byte[] secret) {
Sudheer Shanka03b20ec2019-02-21 15:11:00 -08002800 Slog.d(TAG, "unlockUserKey: " + userId);
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002801 enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002802
Jeff Sharkeyce18c812016-04-27 16:00:41 -06002803 if (StorageManager.isFileEncryptedNativeOrEmulated()) {
Rubin Xu3bf722a2016-12-15 16:07:38 +00002804 // When a user has secure lock screen, require secret to actually unlock.
2805 // This check is mostly in place for emulation mode.
2806 if (mLockPatternUtils.isSecure(userId) && ArrayUtils.isEmpty(secret)) {
2807 throw new IllegalStateException("Secret required to unlock secure user " + userId);
Jeff Sharkeyce18c812016-04-27 16:00:41 -06002808 }
Jeff Sharkeyb9fe5372015-12-03 15:23:08 -07002809
Jeff Sharkeyce18c812016-04-27 16:00:41 -06002810 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002811 mVold.unlockUserKey(userId, serialNumber, encodeBytes(token),
2812 encodeBytes(secret));
Jeff Sharkey43e12112017-09-12 16:31:45 -06002813 } catch (Exception e) {
2814 Slog.wtf(TAG, e);
2815 return;
Jeff Sharkeyce18c812016-04-27 16:00:41 -06002816 }
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002817 }
2818
2819 synchronized (mLock) {
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07002820 mLocalUnlockedUsers = ArrayUtils.appendInt(mLocalUnlockedUsers, userId);
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002821 }
2822 }
2823
2824 @Override
2825 public void lockUserKey(int userId) {
2826 enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002827
2828 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002829 mVold.lockUserKey(userId);
Jeff Sharkey43e12112017-09-12 16:31:45 -06002830 } catch (Exception e) {
2831 Slog.wtf(TAG, e);
2832 return;
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002833 }
2834
2835 synchronized (mLock) {
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07002836 mLocalUnlockedUsers = ArrayUtils.removeInt(mLocalUnlockedUsers, userId);
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002837 }
2838 }
2839
2840 @Override
2841 public boolean isUserKeyUnlocked(int userId) {
Jeff Sharkeyce18c812016-04-27 16:00:41 -06002842 synchronized (mLock) {
2843 return ArrayUtils.contains(mLocalUnlockedUsers, userId);
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002844 }
2845 }
2846
2847 @Override
Jeff Sharkey47f71082016-02-01 17:03:54 -07002848 public void prepareUserStorage(String volumeUuid, int userId, int serialNumber, int flags) {
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002849 enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002850
2851 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002852 mVold.prepareUserStorage(volumeUuid, userId, serialNumber, flags);
Jeff Sharkey43e12112017-09-12 16:31:45 -06002853 } catch (Exception e) {
2854 Slog.wtf(TAG, e);
Paul Crowley7ec733f2015-05-19 12:42:00 +01002855 }
2856 }
2857
Paul Crowleybcf48ed2015-04-22 13:36:59 +01002858 @Override
Jeff Sharkeyfcf1e552016-04-14 20:44:58 -06002859 public void destroyUserStorage(String volumeUuid, int userId, int flags) {
2860 enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
Jeff Sharkeyfcf1e552016-04-14 20:44:58 -06002861
2862 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002863 mVold.destroyUserStorage(volumeUuid, userId, flags);
Jeff Sharkey43e12112017-09-12 16:31:45 -06002864 } catch (Exception e) {
2865 Slog.wtf(TAG, e);
Jeff Sharkeyfcf1e552016-04-14 20:44:58 -06002866 }
2867 }
2868
Daichi Hironoe56740d2017-02-02 13:56:45 +09002869 class AppFuseMountScope extends AppFuseBridge.MountScope {
Daichi Hirono812c95d2017-02-08 16:20:20 +09002870 boolean opened = false;
2871
Ryo Hashimoto38bcbf02018-05-16 18:20:37 +09002872 public AppFuseMountScope(int uid, int mountId) {
2873 super(uid, mountId);
Daichi Hirono812c95d2017-02-08 16:20:20 +09002874 }
2875
2876 @Override
2877 public ParcelFileDescriptor open() throws NativeDaemonConnectorException {
Jeff Sharkey54402792017-09-15 16:05:19 -06002878 try {
2879 return new ParcelFileDescriptor(
Ryo Hashimoto38bcbf02018-05-16 18:20:37 +09002880 mVold.mountAppFuse(uid, mountId));
Jeff Sharkey54402792017-09-15 16:05:19 -06002881 } catch (Exception e) {
2882 throw new NativeDaemonConnectorException("Failed to mount", e);
Daichi Hirono812c95d2017-02-08 16:20:20 +09002883 }
Daichi Hirono9fb00182016-11-08 14:12:17 +09002884 }
2885
2886 @Override
Ryo Hashimoto38bcbf02018-05-16 18:20:37 +09002887 public ParcelFileDescriptor openFile(int mountId, int fileId, int flags)
2888 throws NativeDaemonConnectorException {
2889 try {
2890 return new ParcelFileDescriptor(
2891 mVold.openAppFuseFile(uid, mountId, fileId, flags));
2892 } catch (Exception e) {
2893 throw new NativeDaemonConnectorException("Failed to open", e);
2894 }
2895 }
2896
2897 @Override
Daichi Hironoe56740d2017-02-02 13:56:45 +09002898 public void close() throws Exception {
Daichi Hirono812c95d2017-02-08 16:20:20 +09002899 if (opened) {
Ryo Hashimoto38bcbf02018-05-16 18:20:37 +09002900 mVold.unmountAppFuse(uid, mountId);
Daichi Hirono812c95d2017-02-08 16:20:20 +09002901 opened = false;
2902 }
Daichi Hirono9fb00182016-11-08 14:12:17 +09002903 }
2904 }
2905
2906 @Override
Daichi Hirono812c95d2017-02-08 16:20:20 +09002907 public @Nullable AppFuseMount mountProxyFileDescriptorBridge() {
Daichi Hironoe56740d2017-02-02 13:56:45 +09002908 Slog.v(TAG, "mountProxyFileDescriptorBridge");
Daichi Hirono9fb00182016-11-08 14:12:17 +09002909 final int uid = Binder.getCallingUid();
Daichi Hirono9fb00182016-11-08 14:12:17 +09002910
Daichi Hironoe56740d2017-02-02 13:56:45 +09002911 while (true) {
2912 synchronized (mAppFuseLock) {
2913 boolean newlyCreated = false;
2914 if (mAppFuseBridge == null) {
2915 mAppFuseBridge = new AppFuseBridge();
2916 new Thread(mAppFuseBridge, AppFuseBridge.TAG).start();
2917 newlyCreated = true;
Daichi Hirono9fb00182016-11-08 14:12:17 +09002918 }
Daichi Hironoe56740d2017-02-02 13:56:45 +09002919 try {
2920 final int name = mNextAppFuseName++;
2921 try {
2922 return new AppFuseMount(
Ryo Hashimoto38bcbf02018-05-16 18:20:37 +09002923 name, mAppFuseBridge.addBridge(new AppFuseMountScope(uid, name)));
Daichi Hirono812c95d2017-02-08 16:20:20 +09002924 } catch (FuseUnavailableMountException e) {
Daichi Hironoe56740d2017-02-02 13:56:45 +09002925 if (newlyCreated) {
2926 // If newly created bridge fails, it's a real error.
Daichi Hirono812c95d2017-02-08 16:20:20 +09002927 Slog.e(TAG, "", e);
2928 return null;
Daichi Hironoe56740d2017-02-02 13:56:45 +09002929 }
2930 // It seems the thread of mAppFuseBridge has already been terminated.
2931 mAppFuseBridge = null;
2932 }
2933 } catch (NativeDaemonConnectorException e) {
2934 throw e.rethrowAsParcelableException();
2935 }
Daichi Hirono9fb00182016-11-08 14:12:17 +09002936 }
Daichi Hirono9fb00182016-11-08 14:12:17 +09002937 }
2938 }
2939
2940 @Override
Daichi Hirono812c95d2017-02-08 16:20:20 +09002941 public @Nullable ParcelFileDescriptor openProxyFileDescriptor(
2942 int mountId, int fileId, int mode) {
2943 Slog.v(TAG, "mountProxyFileDescriptor");
Jeff Sharkey39466322018-12-05 19:19:52 -07002944
2945 // We only support a narrow set of incoming mode flags
Jeff Sharkey3b1c2542018-12-13 15:01:38 -07002946 mode &= MODE_READ_WRITE;
Jeff Sharkey39466322018-12-05 19:19:52 -07002947
Daichi Hirono9fb00182016-11-08 14:12:17 +09002948 try {
2949 synchronized (mAppFuseLock) {
Daichi Hironoe56740d2017-02-02 13:56:45 +09002950 if (mAppFuseBridge == null) {
Daichi Hirono812c95d2017-02-08 16:20:20 +09002951 Slog.e(TAG, "FuseBridge has not been created");
2952 return null;
Daichi Hirono9fb00182016-11-08 14:12:17 +09002953 }
Ryo Hashimoto38bcbf02018-05-16 18:20:37 +09002954 return mAppFuseBridge.openFile(mountId, fileId, mode);
Daichi Hirono9fb00182016-11-08 14:12:17 +09002955 }
Daichi Hirono812c95d2017-02-08 16:20:20 +09002956 } catch (FuseUnavailableMountException | InterruptedException error) {
2957 Slog.v(TAG, "The mount point has already been invalid", error);
2958 return null;
Daichi Hirono9fb00182016-11-08 14:12:17 +09002959 }
2960 }
2961
Daichi Hirono9e8d9e22015-11-13 14:37:00 +09002962 @Override
Jeff Sharkeyae266462017-11-27 13:32:24 -07002963 public void mkdirs(String callingPkg, String appPath) {
Jeff Sharkey2d8b4e82013-09-17 17:30:33 -07002964 final int userId = UserHandle.getUserId(Binder.getCallingUid());
2965 final UserEnvironment userEnv = new UserEnvironment(userId);
Farid Zare Seisanac094512018-04-02 15:06:13 -07002966 final String propertyName = "sys.user." + userId + ".ce_available";
Jeff Sharkey2d8b4e82013-09-17 17:30:33 -07002967
Jeff Sharkey196c7552018-03-26 15:56:50 -06002968 // Ignore requests to create directories while storage is locked
Farid Zare Seisanac094512018-04-02 15:06:13 -07002969 if (!isUserKeyUnlocked(userId)) {
2970 throw new IllegalStateException("Failed to prepare " + appPath);
2971 }
2972
2973 // Ignore requests to create directories if CE storage is not available
Farid Zare Seisan7f6b8122018-03-30 11:19:10 -07002974 if ((userId == UserHandle.USER_SYSTEM)
2975 && !SystemProperties.getBoolean(propertyName, false)) {
Farid Zare Seisanac094512018-04-02 15:06:13 -07002976 throw new IllegalStateException("Failed to prepare " + appPath);
2977 }
Jeff Sharkey196c7552018-03-26 15:56:50 -06002978
Jeff Sharkey2d8b4e82013-09-17 17:30:33 -07002979 // Validate that reported package name belongs to caller
2980 final AppOpsManager appOps = (AppOpsManager) mContext.getSystemService(
2981 Context.APP_OPS_SERVICE);
2982 appOps.checkPackage(Binder.getCallingUid(), callingPkg);
2983
Jeff Sharkey48877892015-03-18 11:27:19 -07002984 File appFile = null;
Jeff Sharkey2d8b4e82013-09-17 17:30:33 -07002985 try {
Jeff Sharkey48877892015-03-18 11:27:19 -07002986 appFile = new File(appPath).getCanonicalFile();
Jeff Sharkey2d8b4e82013-09-17 17:30:33 -07002987 } catch (IOException e) {
Jeff Sharkeyae266462017-11-27 13:32:24 -07002988 throw new IllegalStateException("Failed to resolve " + appPath + ": " + e);
Jeff Sharkey2d8b4e82013-09-17 17:30:33 -07002989 }
2990
2991 // Try translating the app path into a vold path, but require that it
2992 // belong to the calling package.
Jeff Sharkey48877892015-03-18 11:27:19 -07002993 if (FileUtils.contains(userEnv.buildExternalStorageAppDataDirs(callingPkg), appFile) ||
2994 FileUtils.contains(userEnv.buildExternalStorageAppObbDirs(callingPkg), appFile) ||
2995 FileUtils.contains(userEnv.buildExternalStorageAppMediaDirs(callingPkg), appFile)) {
2996 appPath = appFile.getAbsolutePath();
2997 if (!appPath.endsWith("/")) {
2998 appPath = appPath + "/";
2999 }
3000
Jeff Sharkey2d8b4e82013-09-17 17:30:33 -07003001 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06003002 mVold.mkdirs(appPath);
Jeff Sharkey27a108c2017-11-30 17:11:40 -07003003 return;
Jeff Sharkeyace874b2017-09-07 15:27:33 -06003004 } catch (Exception e) {
Jeff Sharkeyae266462017-11-27 13:32:24 -07003005 throw new IllegalStateException("Failed to prepare " + appPath + ": " + e);
Jeff Sharkey2d8b4e82013-09-17 17:30:33 -07003006 }
3007 }
3008
Jeff Sharkey48877892015-03-18 11:27:19 -07003009 throw new SecurityException("Invalid mkdirs path: " + appFile);
Jeff Sharkey2d8b4e82013-09-17 17:30:33 -07003010 }
3011
3012 @Override
Jeff Sharkey46349872015-07-28 10:49:47 -07003013 public StorageVolume[] getVolumeList(int uid, String packageName, int flags) {
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07003014 final int userId = UserHandle.getUserId(uid);
Jeff Sharkeyc02bfae2016-03-27 15:06:53 -06003015
Jeff Sharkey46349872015-07-28 10:49:47 -07003016 final boolean forWrite = (flags & StorageManager.FLAG_FOR_WRITE) != 0;
Jeff Sharkeyc02bfae2016-03-27 15:06:53 -06003017 final boolean realState = (flags & StorageManager.FLAG_REAL_STATE) != 0;
3018 final boolean includeInvisible = (flags & StorageManager.FLAG_INCLUDE_INVISIBLE) != 0;
Jeff Sharkey46349872015-07-28 10:49:47 -07003019
Jeff Sharkeyc02bfae2016-03-27 15:06:53 -06003020 final boolean userKeyUnlocked;
3021 final boolean storagePermission;
3022 final long token = Binder.clearCallingIdentity();
Svetoslav38c3dbb2015-07-14 11:27:06 -07003023 try {
Jeff Sharkeyc02bfae2016-03-27 15:06:53 -06003024 userKeyUnlocked = isUserKeyUnlocked(userId);
Sudheer Shanka2250d562016-11-07 15:41:02 -08003025 storagePermission = mStorageManagerInternal.hasExternalStorage(uid, packageName);
Svetoslav38c3dbb2015-07-14 11:27:06 -07003026 } finally {
Jeff Sharkeyc02bfae2016-03-27 15:06:53 -06003027 Binder.restoreCallingIdentity(token);
Svetoslav38c3dbb2015-07-14 11:27:06 -07003028 }
Svet Ganov6ee871e2015-07-10 14:29:33 -07003029
Jeff Sharkeyc02bfae2016-03-27 15:06:53 -06003030 boolean foundPrimary = false;
3031
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07003032 final ArrayList<StorageVolume> res = new ArrayList<>();
Jeff Sharkey48877892015-03-18 11:27:19 -07003033 synchronized (mLock) {
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07003034 for (int i = 0; i < mVolumes.size(); i++) {
3035 final VolumeInfo vol = mVolumes.valueAt(i);
Jeff Sharkeyc02bfae2016-03-27 15:06:53 -06003036 switch (vol.getType()) {
3037 case VolumeInfo.TYPE_PUBLIC:
Risan05c41e62018-10-29 08:57:43 +09003038 case VolumeInfo.TYPE_STUB:
Jeff Sharkeyc02bfae2016-03-27 15:06:53 -06003039 case VolumeInfo.TYPE_EMULATED:
3040 break;
3041 default:
3042 continue;
3043 }
3044
3045 boolean match = false;
3046 if (forWrite) {
3047 match = vol.isVisibleForWrite(userId);
3048 } else {
Felipe Leme123a0e72016-06-10 11:09:11 -07003049 match = vol.isVisibleForRead(userId)
3050 || (includeInvisible && vol.getPath() != null);
Jeff Sharkeyc02bfae2016-03-27 15:06:53 -06003051 }
3052 if (!match) continue;
3053
3054 boolean reportUnmounted = false;
3055 if ((vol.getType() == VolumeInfo.TYPE_EMULATED) && !userKeyUnlocked) {
3056 reportUnmounted = true;
3057 } else if (!storagePermission && !realState) {
3058 reportUnmounted = true;
3059 }
3060
3061 final StorageVolume userVol = vol.buildStorageVolume(mContext, userId,
3062 reportUnmounted);
3063 if (vol.isPrimary()) {
3064 res.add(0, userVol);
3065 foundPrimary = true;
3066 } else {
3067 res.add(userVol);
Jeff Sharkeyb049e212012-09-07 23:16:01 -07003068 }
Mike Lockwood8fa5f802011-03-24 08:12:30 -07003069 }
Mike Lockwood8fa5f802011-03-24 08:12:30 -07003070 }
Jeff Sharkey48877892015-03-18 11:27:19 -07003071
3072 if (!foundPrimary) {
Jeff Sharkey11697f52018-12-13 10:14:42 -07003073 Slog.w(TAG, "No primary storage defined yet; hacking together a stub");
Jeff Sharkey48877892015-03-18 11:27:19 -07003074
3075 final boolean primaryPhysical = SystemProperties.getBoolean(
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07003076 StorageManager.PROP_PRIMARY_PHYSICAL, false);
Jeff Sharkey48877892015-03-18 11:27:19 -07003077
3078 final String id = "stub_primary";
3079 final File path = Environment.getLegacyExternalStorageDirectory();
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07003080 final String description = mContext.getString(android.R.string.unknownName);
Jeff Sharkey48877892015-03-18 11:27:19 -07003081 final boolean primary = true;
3082 final boolean removable = primaryPhysical;
3083 final boolean emulated = !primaryPhysical;
Jeff Sharkey48877892015-03-18 11:27:19 -07003084 final boolean allowMassStorage = false;
3085 final long maxFileSize = 0L;
3086 final UserHandle owner = new UserHandle(userId);
3087 final String uuid = null;
Jeff Sharkey48877892015-03-18 11:27:19 -07003088 final String state = Environment.MEDIA_REMOVED;
3089
Jerry Zhang71938e12018-05-10 18:28:29 -07003090 res.add(0, new StorageVolume(id, path, path,
Jerry Zhangf9c5c252017-08-16 18:07:51 -07003091 description, primary, removable, emulated,
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07003092 allowMassStorage, maxFileSize, owner, uuid, state));
Jeff Sharkey48877892015-03-18 11:27:19 -07003093 }
3094
3095 return res.toArray(new StorageVolume[res.size()]);
Mike Lockwood8fa5f802011-03-24 08:12:30 -07003096 }
3097
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07003098 @Override
3099 public DiskInfo[] getDisks() {
3100 synchronized (mLock) {
3101 final DiskInfo[] res = new DiskInfo[mDisks.size()];
3102 for (int i = 0; i < mDisks.size(); i++) {
3103 res[i] = mDisks.valueAt(i);
3104 }
3105 return res;
3106 }
3107 }
3108
3109 @Override
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07003110 public VolumeInfo[] getVolumes(int flags) {
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07003111 synchronized (mLock) {
3112 final VolumeInfo[] res = new VolumeInfo[mVolumes.size()];
3113 for (int i = 0; i < mVolumes.size(); i++) {
3114 res[i] = mVolumes.valueAt(i);
3115 }
3116 return res;
3117 }
3118 }
3119
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07003120 @Override
3121 public VolumeRecord[] getVolumeRecords(int flags) {
3122 synchronized (mLock) {
3123 final VolumeRecord[] res = new VolumeRecord[mRecords.size()];
3124 for (int i = 0; i < mRecords.size(); i++) {
3125 res[i] = mRecords.valueAt(i);
3126 }
3127 return res;
3128 }
3129 }
3130
Jeff Sharkey9bed0702017-01-23 20:37:05 -07003131 @Override
3132 public long getCacheQuotaBytes(String volumeUuid, int uid) {
3133 if (uid != Binder.getCallingUid()) {
3134 mContext.enforceCallingPermission(android.Manifest.permission.STORAGE_INTERNAL, TAG);
3135 }
Daniel Nishi80fdb012017-03-09 14:30:07 -08003136 final long token = Binder.clearCallingIdentity();
3137 final StorageStatsManager stats = mContext.getSystemService(StorageStatsManager.class);
3138 try {
3139 return stats.getCacheQuotaBytes(volumeUuid, uid);
3140 } finally {
3141 Binder.restoreCallingIdentity(token);
3142 }
Jeff Sharkey9bed0702017-01-23 20:37:05 -07003143 }
3144
3145 @Override
3146 public long getCacheSizeBytes(String volumeUuid, int uid) {
3147 if (uid != Binder.getCallingUid()) {
3148 mContext.enforceCallingPermission(android.Manifest.permission.STORAGE_INTERNAL, TAG);
3149 }
3150 final long token = Binder.clearCallingIdentity();
3151 try {
3152 return mContext.getSystemService(StorageStatsManager.class)
3153 .queryStatsForUid(volumeUuid, uid).getCacheBytes();
Jeff Sharkey789a8fc2017-04-16 13:18:35 -06003154 } catch (IOException e) {
3155 throw new ParcelableException(e);
Jeff Sharkey9bed0702017-01-23 20:37:05 -07003156 } finally {
3157 Binder.restoreCallingIdentity(token);
3158 }
3159 }
3160
Jeff Sharkey35e46d22017-06-09 10:01:20 -06003161 private int adjustAllocateFlags(int flags, int callingUid, String callingPackage) {
3162 // Require permission to allocate aggressively
3163 if ((flags & StorageManager.FLAG_ALLOCATE_AGGRESSIVE) != 0) {
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07003164 mContext.enforceCallingOrSelfPermission(
3165 android.Manifest.permission.ALLOCATE_AGGRESSIVE, TAG);
3166 }
3167
Jeff Sharkey35e46d22017-06-09 10:01:20 -06003168 // Apps normally can't directly defy reserved space
3169 flags &= ~StorageManager.FLAG_ALLOCATE_DEFY_ALL_RESERVED;
3170 flags &= ~StorageManager.FLAG_ALLOCATE_DEFY_HALF_RESERVED;
3171
3172 // However, if app is actively using the camera, then we're willing to
3173 // clear up to half of the reserved cache space, since the user might be
3174 // trying to capture an important memory.
3175 final AppOpsManager appOps = mContext.getSystemService(AppOpsManager.class);
3176 final long token = Binder.clearCallingIdentity();
3177 try {
3178 if (appOps.isOperationActive(AppOpsManager.OP_CAMERA, callingUid, callingPackage)) {
3179 Slog.d(TAG, "UID " + callingUid + " is actively using camera;"
3180 + " letting them defy reserved cached data");
3181 flags |= StorageManager.FLAG_ALLOCATE_DEFY_HALF_RESERVED;
3182 }
3183 } finally {
3184 Binder.restoreCallingIdentity(token);
3185 }
3186
3187 return flags;
3188 }
3189
3190 @Override
3191 public long getAllocatableBytes(String volumeUuid, int flags, String callingPackage) {
3192 flags = adjustAllocateFlags(flags, Binder.getCallingUid(), callingPackage);
3193
3194 final StorageManager storage = mContext.getSystemService(StorageManager.class);
3195 final StorageStatsManager stats = mContext.getSystemService(StorageStatsManager.class);
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07003196 final long token = Binder.clearCallingIdentity();
3197 try {
3198 // In general, apps can allocate as much space as they want, except
3199 // we never let them eat into either the minimum cache space or into
Jeff Sharkeyddff8072017-05-26 13:10:46 -06003200 // the low disk warning space. To avoid user confusion, this logic
3201 // should be kept in sync with getFreeBytes().
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07003202 final File path = storage.findPathForUuid(volumeUuid);
Jeff Sharkeyddff8072017-05-26 13:10:46 -06003203
3204 final long usable = path.getUsableSpace();
3205 final long lowReserved = storage.getStorageLowBytes(path);
3206 final long fullReserved = storage.getStorageFullBytes(path);
3207
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07003208 if (stats.isQuotaSupported(volumeUuid)) {
Jeff Sharkeyddff8072017-05-26 13:10:46 -06003209 final long cacheTotal = stats.getCacheBytes(volumeUuid);
Jeff Sharkey35e46d22017-06-09 10:01:20 -06003210 final long cacheReserved = storage.getStorageCacheBytes(path, flags);
Jeff Sharkeyddff8072017-05-26 13:10:46 -06003211 final long cacheClearable = Math.max(0, cacheTotal - cacheReserved);
3212
Jeff Sharkey35e46d22017-06-09 10:01:20 -06003213 if ((flags & StorageManager.FLAG_ALLOCATE_AGGRESSIVE) != 0) {
3214 return Math.max(0, (usable + cacheClearable) - fullReserved);
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07003215 } else {
Jeff Sharkeyddff8072017-05-26 13:10:46 -06003216 return Math.max(0, (usable + cacheClearable) - lowReserved);
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07003217 }
3218 } else {
3219 // When we don't have fast quota information, we ignore cached
3220 // data and only consider unused bytes.
Jeff Sharkey35e46d22017-06-09 10:01:20 -06003221 if ((flags & StorageManager.FLAG_ALLOCATE_AGGRESSIVE) != 0) {
Jeff Sharkeyddff8072017-05-26 13:10:46 -06003222 return Math.max(0, usable - fullReserved);
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07003223 } else {
Jeff Sharkeyddff8072017-05-26 13:10:46 -06003224 return Math.max(0, usable - lowReserved);
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07003225 }
3226 }
Jeff Sharkey789a8fc2017-04-16 13:18:35 -06003227 } catch (IOException e) {
3228 throw new ParcelableException(e);
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07003229 } finally {
3230 Binder.restoreCallingIdentity(token);
3231 }
Jeff Sharkey500ce9e2017-02-12 02:39:24 -07003232 }
3233
3234 @Override
Jeff Sharkey35e46d22017-06-09 10:01:20 -06003235 public void allocateBytes(String volumeUuid, long bytes, int flags, String callingPackage) {
3236 flags = adjustAllocateFlags(flags, Binder.getCallingUid(), callingPackage);
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07003237
Jeff Sharkey35e46d22017-06-09 10:01:20 -06003238 final long allocatableBytes = getAllocatableBytes(volumeUuid, flags, callingPackage);
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07003239 if (bytes > allocatableBytes) {
3240 throw new ParcelableException(new IOException("Failed to allocate " + bytes
3241 + " because only " + allocatableBytes + " allocatable"));
3242 }
3243
Jeff Sharkey35e46d22017-06-09 10:01:20 -06003244 final StorageManager storage = mContext.getSystemService(StorageManager.class);
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07003245 final long token = Binder.clearCallingIdentity();
3246 try {
Jeff Sharkey789a8fc2017-04-16 13:18:35 -06003247 // Free up enough disk space to satisfy both the requested allocation
3248 // and our low disk warning space.
3249 final File path = storage.findPathForUuid(volumeUuid);
Jeff Sharkeyddff8072017-05-26 13:10:46 -06003250 if ((flags & StorageManager.FLAG_ALLOCATE_AGGRESSIVE) != 0) {
3251 bytes += storage.getStorageFullBytes(path);
3252 } else {
3253 bytes += storage.getStorageLowBytes(path);
3254 }
Jeff Sharkey789a8fc2017-04-16 13:18:35 -06003255
Jeff Sharkey5790af02018-08-13 17:42:54 -06003256 mPmInternal.freeStorage(volumeUuid, bytes, flags);
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07003257 } catch (IOException e) {
3258 throw new ParcelableException(e);
3259 } finally {
3260 Binder.restoreCallingIdentity(token);
Jeff Sharkey500ce9e2017-02-12 02:39:24 -07003261 }
3262 }
3263
Sudheer Shankaff971bc2018-12-13 17:39:59 -08003264 private IAppOpsCallback.Stub mAppOpsCallback = new IAppOpsCallback.Stub() {
3265 @Override
3266 public void opChanged(int op, int uid, String packageName) throws RemoteException {
3267 if (!ENABLE_ISOLATED_STORAGE) return;
3268
3269 remountUidExternalStorage(uid, getMountMode(uid, packageName));
3270 }
3271 };
3272
Jeff Sharkey5790af02018-08-13 17:42:54 -06003273 private static final Pattern PATTERN_TRANSLATE = Pattern.compile(
3274 "(?i)^(/storage/[^/]+/(?:[0-9]+/)?)(.*)");
3275
3276 @Override
Sudheer Shanka87915d62018-11-06 10:57:35 -08003277 public String translateAppToSystem(String path, int pid, int uid) {
3278 return translateInternal(path, pid, uid, true);
Jeff Sharkey5790af02018-08-13 17:42:54 -06003279 }
3280
3281 @Override
Sudheer Shanka87915d62018-11-06 10:57:35 -08003282 public String translateSystemToApp(String path, int pid, int uid) {
3283 return translateInternal(path, pid, uid, false);
Jeff Sharkey5790af02018-08-13 17:42:54 -06003284 }
3285
Sudheer Shanka87915d62018-11-06 10:57:35 -08003286 private String translateInternal(String path, int pid, int uid, boolean toSystem) {
Jeff Sharkey5790af02018-08-13 17:42:54 -06003287 if (!ENABLE_ISOLATED_STORAGE) return path;
3288
3289 if (path.contains("/../")) {
3290 throw new SecurityException("Shady looking path " + path);
3291 }
3292
Sudheer Shanka3a0df3b2018-12-12 12:43:43 -08003293 final int mountMode = mAmInternal.getStorageMountMode(pid, uid);
Sudheer Shanka0b6da532019-01-09 12:06:51 -08003294 if (mountMode == Zygote.MOUNT_EXTERNAL_FULL
3295 || mountMode == Zygote.MOUNT_EXTERNAL_LEGACY) {
Sudheer Shanka87915d62018-11-06 10:57:35 -08003296 return path;
3297 }
Jeff Sharkey5790af02018-08-13 17:42:54 -06003298
3299 final Matcher m = PATTERN_TRANSLATE.matcher(path);
3300 if (m.matches()) {
3301 final String device = m.group(1);
3302 final String devicePath = m.group(2);
3303
Sudheer Shanka3a0df3b2018-12-12 12:43:43 -08003304 if (mountMode == Zygote.MOUNT_EXTERNAL_INSTALLER
3305 && devicePath.startsWith("Android/obb/")) {
3306 return path;
3307 }
3308
Jeff Sharkey5790af02018-08-13 17:42:54 -06003309 // Does path belong to any packages belonging to this UID? If so,
3310 // they get to go straight through to legacy paths.
Sudheer Shanka87915d62018-11-06 10:57:35 -08003311 final String[] pkgs = mContext.getPackageManager().getPackagesForUid(uid);
Jeff Sharkey5790af02018-08-13 17:42:54 -06003312 for (String pkg : pkgs) {
3313 if (devicePath.startsWith("Android/data/" + pkg + "/") ||
3314 devicePath.startsWith("Android/media/" + pkg + "/") ||
3315 devicePath.startsWith("Android/obb/" + pkg + "/")) {
3316 return path;
3317 }
3318 }
3319
Sudheer Shanka87915d62018-11-06 10:57:35 -08003320 final String sharedUserId = mPmInternal.getSharedUserIdForPackage(pkgs[0]);
3321 final String sandboxId = getSandboxId(pkgs[0], sharedUserId);
3322
Jeff Sharkey5790af02018-08-13 17:42:54 -06003323 if (toSystem) {
3324 // Everything else goes into sandbox.
Sudheer Shanka31ad0a12018-10-20 20:59:00 -07003325 return device + "Android/sandbox/" + sandboxId + "/" + devicePath;
Jeff Sharkey5790af02018-08-13 17:42:54 -06003326 } else {
3327 // Does path belong to this sandbox? If so, leave sandbox.
Sudheer Shanka31ad0a12018-10-20 20:59:00 -07003328 final String sandboxPrefix = "Android/sandbox/" + sandboxId + "/";
Jeff Sharkey5790af02018-08-13 17:42:54 -06003329 if (devicePath.startsWith(sandboxPrefix)) {
3330 return device + devicePath.substring(sandboxPrefix.length());
3331 }
3332
3333 // Path isn't valid inside sandbox!
3334 throw new SecurityException(
3335 "Path " + path + " isn't valid inside sandbox " + sandboxId);
3336 }
3337 }
3338
3339 return path;
3340 }
3341
Kenny Rootaf9d6672010-10-08 09:21:39 -07003342 private void addObbStateLocked(ObbState obbState) throws RemoteException {
3343 final IBinder binder = obbState.getBinder();
3344 List<ObbState> obbStates = mObbMounts.get(binder);
Kenny Root5919ac62010-10-05 09:49:40 -07003345
Kenny Rootaf9d6672010-10-08 09:21:39 -07003346 if (obbStates == null) {
3347 obbStates = new ArrayList<ObbState>();
3348 mObbMounts.put(binder, obbStates);
3349 } else {
3350 for (final ObbState o : obbStates) {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003351 if (o.rawPath.equals(obbState.rawPath)) {
Kenny Rootaf9d6672010-10-08 09:21:39 -07003352 throw new IllegalStateException("Attempt to add ObbState twice. "
Sudheer Shanka2250d562016-11-07 15:41:02 -08003353 + "This indicates an error in the StorageManagerService logic.");
Kenny Root5919ac62010-10-05 09:49:40 -07003354 }
3355 }
Kenny Roota02b8b02010-08-05 16:14:17 -07003356 }
Kenny Rootaf9d6672010-10-08 09:21:39 -07003357
3358 obbStates.add(obbState);
3359 try {
3360 obbState.link();
3361 } catch (RemoteException e) {
3362 /*
3363 * The binder died before we could link it, so clean up our state
3364 * and return failure.
3365 */
3366 obbStates.remove(obbState);
3367 if (obbStates.isEmpty()) {
3368 mObbMounts.remove(binder);
3369 }
3370
3371 // Rethrow the error so mountObb can get it
3372 throw e;
3373 }
3374
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003375 mObbPathToStateMap.put(obbState.rawPath, obbState);
Kenny Roota02b8b02010-08-05 16:14:17 -07003376 }
3377
Kenny Rootaf9d6672010-10-08 09:21:39 -07003378 private void removeObbStateLocked(ObbState obbState) {
3379 final IBinder binder = obbState.getBinder();
3380 final List<ObbState> obbStates = mObbMounts.get(binder);
3381 if (obbStates != null) {
3382 if (obbStates.remove(obbState)) {
3383 obbState.unlink();
Kenny Root05105f72010-09-22 17:29:43 -07003384 }
Kenny Rootaf9d6672010-10-08 09:21:39 -07003385 if (obbStates.isEmpty()) {
3386 mObbMounts.remove(binder);
3387 }
Kenny Roota02b8b02010-08-05 16:14:17 -07003388 }
Kenny Roota02b8b02010-08-05 16:14:17 -07003389
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003390 mObbPathToStateMap.remove(obbState.rawPath);
Kenny Root38cf8862010-09-26 14:18:51 -07003391 }
3392
Kenny Roota02b8b02010-08-05 16:14:17 -07003393 private class ObbActionHandler extends Handler {
Kenny Roota02b8b02010-08-05 16:14:17 -07003394
3395 ObbActionHandler(Looper l) {
3396 super(l);
3397 }
3398
3399 @Override
3400 public void handleMessage(Message msg) {
3401 switch (msg.what) {
3402 case OBB_RUN_ACTION: {
Kenny Root480afe72010-10-07 10:17:50 -07003403 final ObbAction action = (ObbAction) msg.obj;
Kenny Roota02b8b02010-08-05 16:14:17 -07003404
3405 if (DEBUG_OBB)
3406 Slog.i(TAG, "OBB_RUN_ACTION: " + action.toString());
3407
Sudheer Shanka25469aa2018-08-27 15:50:23 -07003408 action.execute(this);
Kenny Roota02b8b02010-08-05 16:14:17 -07003409 break;
3410 }
Kenny Rootaf9d6672010-10-08 09:21:39 -07003411 case OBB_FLUSH_MOUNT_STATE: {
3412 final String path = (String) msg.obj;
3413
3414 if (DEBUG_OBB)
3415 Slog.i(TAG, "Flushing all OBB state for path " + path);
3416
3417 synchronized (mObbMounts) {
3418 final List<ObbState> obbStatesToRemove = new LinkedList<ObbState>();
3419
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003420 final Iterator<ObbState> i = mObbPathToStateMap.values().iterator();
Kenny Rootaf9d6672010-10-08 09:21:39 -07003421 while (i.hasNext()) {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003422 final ObbState state = i.next();
Kenny Rootaf9d6672010-10-08 09:21:39 -07003423
3424 /*
3425 * If this entry's source file is in the volume path
3426 * that got unmounted, remove it because it's no
3427 * longer valid.
3428 */
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003429 if (state.canonicalPath.startsWith(path)) {
3430 obbStatesToRemove.add(state);
Kenny Rootaf9d6672010-10-08 09:21:39 -07003431 }
3432 }
3433
3434 for (final ObbState obbState : obbStatesToRemove) {
3435 if (DEBUG_OBB)
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003436 Slog.i(TAG, "Removing state for " + obbState.rawPath);
Kenny Rootaf9d6672010-10-08 09:21:39 -07003437
3438 removeObbStateLocked(obbState);
3439
3440 try {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003441 obbState.token.onObbResult(obbState.rawPath, obbState.nonce,
Kenny Rootaf9d6672010-10-08 09:21:39 -07003442 OnObbStateChangeListener.UNMOUNTED);
3443 } catch (RemoteException e) {
3444 Slog.i(TAG, "Couldn't send unmount notification for OBB: "
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003445 + obbState.rawPath);
Kenny Rootaf9d6672010-10-08 09:21:39 -07003446 }
3447 }
3448 }
3449 break;
3450 }
Kenny Roota02b8b02010-08-05 16:14:17 -07003451 }
3452 }
Kenny Roota02b8b02010-08-05 16:14:17 -07003453 }
3454
Jeff Sharkey0095a822018-02-15 13:06:53 -07003455 private static class ObbException extends Exception {
3456 public final int status;
3457
3458 public ObbException(int status, String message) {
3459 super(message);
3460 this.status = status;
3461 }
3462
3463 public ObbException(int status, Throwable cause) {
3464 super(cause.getMessage(), cause);
3465 this.status = status;
3466 }
3467 }
3468
Kenny Roota02b8b02010-08-05 16:14:17 -07003469 abstract class ObbAction {
Kenny Roota02b8b02010-08-05 16:14:17 -07003470
3471 ObbState mObbState;
3472
3473 ObbAction(ObbState obbState) {
3474 mObbState = obbState;
3475 }
3476
3477 public void execute(ObbActionHandler handler) {
3478 try {
3479 if (DEBUG_OBB)
Ben Komalo444eca22011-09-01 15:17:44 -07003480 Slog.i(TAG, "Starting to execute action: " + toString());
Sudheer Shanka25469aa2018-08-27 15:50:23 -07003481 handleExecute();
Jeff Sharkey0095a822018-02-15 13:06:53 -07003482 } catch (ObbException e) {
3483 notifyObbStateChange(e);
Kenny Roota02b8b02010-08-05 16:14:17 -07003484 }
3485 }
3486
Jeff Sharkey0095a822018-02-15 13:06:53 -07003487 abstract void handleExecute() throws ObbException;
Kenny Root38cf8862010-09-26 14:18:51 -07003488
Jeff Sharkey0095a822018-02-15 13:06:53 -07003489 protected void notifyObbStateChange(ObbException e) {
3490 Slog.w(TAG, e);
3491 notifyObbStateChange(e.status);
3492 }
3493
3494 protected void notifyObbStateChange(int status) {
Kenny Rootaf9d6672010-10-08 09:21:39 -07003495 if (mObbState == null || mObbState.token == null) {
3496 return;
3497 }
3498
Kenny Root38cf8862010-09-26 14:18:51 -07003499 try {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003500 mObbState.token.onObbResult(mObbState.rawPath, mObbState.nonce, status);
Kenny Root38cf8862010-09-26 14:18:51 -07003501 } catch (RemoteException e) {
Sudheer Shanka2250d562016-11-07 15:41:02 -08003502 Slog.w(TAG, "StorageEventListener went away while calling onObbStateChanged");
Kenny Root38cf8862010-09-26 14:18:51 -07003503 }
3504 }
Kenny Roota02b8b02010-08-05 16:14:17 -07003505 }
3506
3507 class MountObbAction extends ObbAction {
Ben Komalo444eca22011-09-01 15:17:44 -07003508 private final String mKey;
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003509 private final int mCallingUid;
Sudheer Shanka25469aa2018-08-27 15:50:23 -07003510 private ObbInfo mObbInfo;
Kenny Roota02b8b02010-08-05 16:14:17 -07003511
Sudheer Shanka25469aa2018-08-27 15:50:23 -07003512 MountObbAction(ObbState obbState, String key, int callingUid, ObbInfo obbInfo) {
Kenny Roota02b8b02010-08-05 16:14:17 -07003513 super(obbState);
3514 mKey = key;
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003515 mCallingUid = callingUid;
Sudheer Shanka25469aa2018-08-27 15:50:23 -07003516 mObbInfo = obbInfo;
Kenny Roota02b8b02010-08-05 16:14:17 -07003517 }
3518
Jason parks5af0b912010-11-29 09:05:25 -06003519 @Override
Jeff Sharkey0095a822018-02-15 13:06:53 -07003520 public void handleExecute() throws ObbException {
Kenny Rootaf9d6672010-10-08 09:21:39 -07003521 warnOnNotMounted();
3522
Sudheer Shanka25469aa2018-08-27 15:50:23 -07003523 if (!isUidOwnerOfPackageOrSystem(mObbInfo.packageName, mCallingUid)) {
Jeff Sharkey0095a822018-02-15 13:06:53 -07003524 throw new ObbException(ERROR_PERMISSION_DENIED, "Denied attempt to mount OBB "
Sudheer Shanka25469aa2018-08-27 15:50:23 -07003525 + mObbInfo.filename + " which is owned by " + mObbInfo.packageName);
Kenny Roota02b8b02010-08-05 16:14:17 -07003526 }
3527
Kenny Rootaf9d6672010-10-08 09:21:39 -07003528 final boolean isMounted;
3529 synchronized (mObbMounts) {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003530 isMounted = mObbPathToStateMap.containsKey(mObbState.rawPath);
Kenny Rootaf9d6672010-10-08 09:21:39 -07003531 }
3532 if (isMounted) {
Jeff Sharkey0095a822018-02-15 13:06:53 -07003533 throw new ObbException(ERROR_ALREADY_MOUNTED,
Sudheer Shanka25469aa2018-08-27 15:50:23 -07003534 "Attempt to mount OBB which is already mounted: " + mObbInfo.filename);
Kenny Rootaf9d6672010-10-08 09:21:39 -07003535 }
3536
Kenny Rootaf9d6672010-10-08 09:21:39 -07003537 final String hashedKey;
Jeff Sharkey41cd6812017-09-11 10:32:17 -06003538 final String binderKey;
Kenny Rootaf9d6672010-10-08 09:21:39 -07003539 if (mKey == null) {
3540 hashedKey = "none";
Jeff Sharkey41cd6812017-09-11 10:32:17 -06003541 binderKey = "";
Kenny Rootaf9d6672010-10-08 09:21:39 -07003542 } else {
Kenny Rootaf9d6672010-10-08 09:21:39 -07003543 try {
Kenny Root3b1abba2010-10-13 15:00:07 -07003544 SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
3545
Sudheer Shanka25469aa2018-08-27 15:50:23 -07003546 KeySpec ks = new PBEKeySpec(mKey.toCharArray(), mObbInfo.salt,
Kenny Root3b1abba2010-10-13 15:00:07 -07003547 PBKDF2_HASH_ROUNDS, CRYPTO_ALGORITHM_KEY_SIZE);
3548 SecretKey key = factory.generateSecret(ks);
3549 BigInteger bi = new BigInteger(key.getEncoded());
3550 hashedKey = bi.toString(16);
Jeff Sharkey41cd6812017-09-11 10:32:17 -06003551 binderKey = hashedKey;
Jeff Sharkey0095a822018-02-15 13:06:53 -07003552 } catch (GeneralSecurityException e) {
3553 throw new ObbException(ERROR_INTERNAL, e);
Kenny Root38cf8862010-09-26 14:18:51 -07003554 }
Kenny Rootaf9d6672010-10-08 09:21:39 -07003555 }
Kenny Root38cf8862010-09-26 14:18:51 -07003556
Kenny Rootaf9d6672010-10-08 09:21:39 -07003557 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06003558 mObbState.volId = mVold.createObb(mObbState.canonicalPath, binderKey,
3559 mObbState.ownerGid);
3560 mVold.mount(mObbState.volId, 0, -1);
Kenny Roota02b8b02010-08-05 16:14:17 -07003561
Kenny Rootaf9d6672010-10-08 09:21:39 -07003562 if (DEBUG_OBB)
Xiaohui Chen621b3fc2015-10-02 14:41:42 -07003563 Slog.d(TAG, "Successfully mounted OBB " + mObbState.canonicalPath);
Kenny Rootaf9d6672010-10-08 09:21:39 -07003564
3565 synchronized (mObbMounts) {
3566 addObbStateLocked(mObbState);
3567 }
3568
Jeff Sharkey0095a822018-02-15 13:06:53 -07003569 notifyObbStateChange(MOUNTED);
3570 } catch (Exception e) {
3571 throw new ObbException(ERROR_COULD_NOT_MOUNT, e);
Kenny Root02c87302010-07-01 08:10:18 -07003572 }
3573 }
3574
Jason parks5af0b912010-11-29 09:05:25 -06003575 @Override
Kenny Roota02b8b02010-08-05 16:14:17 -07003576 public String toString() {
3577 StringBuilder sb = new StringBuilder();
3578 sb.append("MountObbAction{");
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003579 sb.append(mObbState);
Kenny Roota02b8b02010-08-05 16:14:17 -07003580 sb.append('}');
3581 return sb.toString();
3582 }
3583 }
3584
3585 class UnmountObbAction extends ObbAction {
Ben Komalo444eca22011-09-01 15:17:44 -07003586 private final boolean mForceUnmount;
Kenny Roota02b8b02010-08-05 16:14:17 -07003587
3588 UnmountObbAction(ObbState obbState, boolean force) {
3589 super(obbState);
3590 mForceUnmount = force;
3591 }
3592
Jason parks5af0b912010-11-29 09:05:25 -06003593 @Override
Jeff Sharkey0095a822018-02-15 13:06:53 -07003594 public void handleExecute() throws ObbException {
Kenny Rootaf9d6672010-10-08 09:21:39 -07003595 warnOnNotMounted();
3596
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003597 final ObbState existingState;
Kenny Root38cf8862010-09-26 14:18:51 -07003598 synchronized (mObbMounts) {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003599 existingState = mObbPathToStateMap.get(mObbState.rawPath);
Kenny Rootaf9d6672010-10-08 09:21:39 -07003600 }
Kenny Root38cf8862010-09-26 14:18:51 -07003601
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003602 if (existingState == null) {
Jeff Sharkey0095a822018-02-15 13:06:53 -07003603 throw new ObbException(ERROR_NOT_MOUNTED, "Missing existingState");
Kenny Rootaf9d6672010-10-08 09:21:39 -07003604 }
3605
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003606 if (existingState.ownerGid != mObbState.ownerGid) {
Jeff Sharkey0095a822018-02-15 13:06:53 -07003607 notifyObbStateChange(new ObbException(ERROR_PERMISSION_DENIED,
3608 "Permission denied to unmount OBB " + existingState.rawPath
3609 + " (owned by GID " + existingState.ownerGid + ")"));
Kenny Rootaf9d6672010-10-08 09:21:39 -07003610 return;
3611 }
3612
Kenny Rootaf9d6672010-10-08 09:21:39 -07003613 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06003614 mVold.unmount(mObbState.volId);
3615 mVold.destroyObb(mObbState.volId);
3616 mObbState.volId = null;
Kenny Roota02b8b02010-08-05 16:14:17 -07003617
Kenny Rootaf9d6672010-10-08 09:21:39 -07003618 synchronized (mObbMounts) {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003619 removeObbStateLocked(existingState);
Kenny Root38cf8862010-09-26 14:18:51 -07003620 }
3621
Jeff Sharkey0095a822018-02-15 13:06:53 -07003622 notifyObbStateChange(UNMOUNTED);
3623 } catch (Exception e) {
3624 throw new ObbException(ERROR_COULD_NOT_UNMOUNT, e);
Kenny Roota02b8b02010-08-05 16:14:17 -07003625 }
3626 }
3627
Jason parks5af0b912010-11-29 09:05:25 -06003628 @Override
Kenny Roota02b8b02010-08-05 16:14:17 -07003629 public String toString() {
3630 StringBuilder sb = new StringBuilder();
3631 sb.append("UnmountObbAction{");
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003632 sb.append(mObbState);
Kenny Roota02b8b02010-08-05 16:14:17 -07003633 sb.append(",force=");
3634 sb.append(mForceUnmount);
Kenny Roota02b8b02010-08-05 16:14:17 -07003635 sb.append('}');
3636 return sb.toString();
3637 }
Kenny Root02c87302010-07-01 08:10:18 -07003638 }
Kenny Root38cf8862010-09-26 14:18:51 -07003639
Jeff Sharkey7e19f532017-11-06 13:54:11 -07003640 private void dispatchOnStatus(IVoldTaskListener listener, int status,
3641 PersistableBundle extras) {
3642 if (listener != null) {
3643 try {
3644 listener.onStatus(status, extras);
3645 } catch (RemoteException ignored) {
3646 }
3647 }
3648 }
3649
3650 private void dispatchOnFinished(IVoldTaskListener listener, int status,
3651 PersistableBundle extras) {
3652 if (listener != null) {
3653 try {
3654 listener.onFinished(status, extras);
3655 } catch (RemoteException ignored) {
3656 }
3657 }
3658 }
3659
Sudheer Shanka3a0df3b2018-12-12 12:43:43 -08003660 private int getMountMode(int uid, String packageName) {
3661 try {
3662 if (Process.isIsolated(uid)) {
3663 return Zygote.MOUNT_EXTERNAL_NONE;
3664 }
3665 if (mIPackageManager.checkUidPermission(WRITE_MEDIA_STORAGE, uid)
3666 == PERMISSION_GRANTED) {
3667 return Zygote.MOUNT_EXTERNAL_FULL;
Jeff Sharkey11697f52018-12-13 10:14:42 -07003668 } else if (mIAppOpsService.checkOperation(OP_LEGACY_STORAGE, uid,
3669 packageName) == MODE_ALLOWED) {
Sudheer Shanka0b6da532019-01-09 12:06:51 -08003670 return Zygote.MOUNT_EXTERNAL_LEGACY;
Sudheer Shanka3a0df3b2018-12-12 12:43:43 -08003671 } else if (mIPackageManager.checkUidPermission(INSTALL_PACKAGES, uid)
3672 == PERMISSION_GRANTED || mIAppOpsService.checkOperation(
3673 OP_REQUEST_INSTALL_PACKAGES, uid, packageName) == MODE_ALLOWED) {
3674 return Zygote.MOUNT_EXTERNAL_INSTALLER;
Sudheer Shanka0f26cbd2019-01-18 18:25:38 -08003675 } else if (mPmInternal.isInstantApp(packageName, UserHandle.getUserId(uid))) {
3676 return Zygote.MOUNT_EXTERNAL_NONE;
Sudheer Shanka3a0df3b2018-12-12 12:43:43 -08003677 } else {
Jeff Sharkey0ebbd462019-02-19 23:45:57 -07003678 // STOPSHIP: remove this temporary workaround once developers
3679 // fix bugs where they're opening _data paths in native code
3680 switch (packageName) {
3681 case "com.facebook.katana": // b/123996076
3682 case "jp.naver.line.android": // b/124767356
3683 case "com.mxtech.videoplayer.ad": // b/124531483
3684 return Zygote.MOUNT_EXTERNAL_LEGACY;
3685 default:
3686 return Zygote.MOUNT_EXTERNAL_WRITE;
3687 }
Sudheer Shanka3a0df3b2018-12-12 12:43:43 -08003688 }
3689 } catch (RemoteException e) {
3690 // Should not happen
3691 }
3692 return Zygote.MOUNT_EXTERNAL_NONE;
3693 }
3694
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07003695 private static class Callbacks extends Handler {
3696 private static final int MSG_STORAGE_STATE_CHANGED = 1;
3697 private static final int MSG_VOLUME_STATE_CHANGED = 2;
Jeff Sharkey50a05452015-04-29 11:24:52 -07003698 private static final int MSG_VOLUME_RECORD_CHANGED = 3;
3699 private static final int MSG_VOLUME_FORGOTTEN = 4;
3700 private static final int MSG_DISK_SCANNED = 5;
Makoto Onuki9dc575d2015-06-12 16:10:25 -07003701 private static final int MSG_DISK_DESTROYED = 6;
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07003702
Sudheer Shanka2250d562016-11-07 15:41:02 -08003703 private final RemoteCallbackList<IStorageEventListener>
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07003704 mCallbacks = new RemoteCallbackList<>();
3705
3706 public Callbacks(Looper looper) {
3707 super(looper);
3708 }
3709
Sudheer Shanka2250d562016-11-07 15:41:02 -08003710 public void register(IStorageEventListener callback) {
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07003711 mCallbacks.register(callback);
3712 }
3713
Sudheer Shanka2250d562016-11-07 15:41:02 -08003714 public void unregister(IStorageEventListener callback) {
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07003715 mCallbacks.unregister(callback);
3716 }
3717
3718 @Override
3719 public void handleMessage(Message msg) {
3720 final SomeArgs args = (SomeArgs) msg.obj;
3721 final int n = mCallbacks.beginBroadcast();
3722 for (int i = 0; i < n; i++) {
Sudheer Shanka2250d562016-11-07 15:41:02 -08003723 final IStorageEventListener callback = mCallbacks.getBroadcastItem(i);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07003724 try {
3725 invokeCallback(callback, msg.what, args);
3726 } catch (RemoteException ignored) {
3727 }
3728 }
3729 mCallbacks.finishBroadcast();
3730 args.recycle();
3731 }
3732
Sudheer Shanka2250d562016-11-07 15:41:02 -08003733 private void invokeCallback(IStorageEventListener callback, int what, SomeArgs args)
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07003734 throws RemoteException {
3735 switch (what) {
3736 case MSG_STORAGE_STATE_CHANGED: {
3737 callback.onStorageStateChanged((String) args.arg1, (String) args.arg2,
3738 (String) args.arg3);
3739 break;
3740 }
3741 case MSG_VOLUME_STATE_CHANGED: {
3742 callback.onVolumeStateChanged((VolumeInfo) args.arg1, args.argi2, args.argi3);
3743 break;
3744 }
Jeff Sharkey50a05452015-04-29 11:24:52 -07003745 case MSG_VOLUME_RECORD_CHANGED: {
3746 callback.onVolumeRecordChanged((VolumeRecord) args.arg1);
3747 break;
3748 }
3749 case MSG_VOLUME_FORGOTTEN: {
3750 callback.onVolumeForgotten((String) args.arg1);
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07003751 break;
3752 }
Jeff Sharkey620b32b2015-04-23 19:36:02 -07003753 case MSG_DISK_SCANNED: {
3754 callback.onDiskScanned((DiskInfo) args.arg1, args.argi2);
Jeff Sharkey7e92ef32015-04-17 17:35:07 -07003755 break;
3756 }
Makoto Onuki9dc575d2015-06-12 16:10:25 -07003757 case MSG_DISK_DESTROYED: {
3758 callback.onDiskDestroyed((DiskInfo) args.arg1);
3759 break;
3760 }
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07003761 }
3762 }
3763
3764 private void notifyStorageStateChanged(String path, String oldState, String newState) {
3765 final SomeArgs args = SomeArgs.obtain();
3766 args.arg1 = path;
3767 args.arg2 = oldState;
3768 args.arg3 = newState;
3769 obtainMessage(MSG_STORAGE_STATE_CHANGED, args).sendToTarget();
3770 }
3771
3772 private void notifyVolumeStateChanged(VolumeInfo vol, int oldState, int newState) {
3773 final SomeArgs args = SomeArgs.obtain();
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07003774 args.arg1 = vol.clone();
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07003775 args.argi2 = oldState;
3776 args.argi3 = newState;
3777 obtainMessage(MSG_VOLUME_STATE_CHANGED, args).sendToTarget();
3778 }
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07003779
Jeff Sharkey50a05452015-04-29 11:24:52 -07003780 private void notifyVolumeRecordChanged(VolumeRecord rec) {
3781 final SomeArgs args = SomeArgs.obtain();
3782 args.arg1 = rec.clone();
3783 obtainMessage(MSG_VOLUME_RECORD_CHANGED, args).sendToTarget();
3784 }
3785
3786 private void notifyVolumeForgotten(String fsUuid) {
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07003787 final SomeArgs args = SomeArgs.obtain();
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07003788 args.arg1 = fsUuid;
Jeff Sharkey50a05452015-04-29 11:24:52 -07003789 obtainMessage(MSG_VOLUME_FORGOTTEN, args).sendToTarget();
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07003790 }
Jeff Sharkey7e92ef32015-04-17 17:35:07 -07003791
Jeff Sharkey620b32b2015-04-23 19:36:02 -07003792 private void notifyDiskScanned(DiskInfo disk, int volumeCount) {
Jeff Sharkey7e92ef32015-04-17 17:35:07 -07003793 final SomeArgs args = SomeArgs.obtain();
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07003794 args.arg1 = disk.clone();
Jeff Sharkey620b32b2015-04-23 19:36:02 -07003795 args.argi2 = volumeCount;
3796 obtainMessage(MSG_DISK_SCANNED, args).sendToTarget();
Jeff Sharkey7e92ef32015-04-17 17:35:07 -07003797 }
Makoto Onuki9dc575d2015-06-12 16:10:25 -07003798
3799 private void notifyDiskDestroyed(DiskInfo disk) {
3800 final SomeArgs args = SomeArgs.obtain();
3801 args.arg1 = disk.clone();
3802 obtainMessage(MSG_DISK_DESTROYED, args).sendToTarget();
3803 }
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07003804 }
3805
Kenny Root38cf8862010-09-26 14:18:51 -07003806 @Override
Jeff Sharkey5aca2b82013-10-16 16:21:54 -07003807 protected void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
Jeff Sharkeyfe9a53b2017-03-31 14:08:23 -06003808 if (!DumpUtils.checkDumpPermission(mContext, TAG, writer)) return;
Jeff Sharkey5aca2b82013-10-16 16:21:54 -07003809
3810 final IndentingPrintWriter pw = new IndentingPrintWriter(writer, " ", 160);
Jeff Sharkey27de30d2015-04-18 16:20:27 -07003811 synchronized (mLock) {
3812 pw.println("Disks:");
3813 pw.increaseIndent();
3814 for (int i = 0; i < mDisks.size(); i++) {
3815 final DiskInfo disk = mDisks.valueAt(i);
3816 disk.dump(pw);
3817 }
3818 pw.decreaseIndent();
3819
3820 pw.println();
3821 pw.println("Volumes:");
3822 pw.increaseIndent();
3823 for (int i = 0; i < mVolumes.size(); i++) {
3824 final VolumeInfo vol = mVolumes.valueAt(i);
3825 if (VolumeInfo.ID_PRIVATE_INTERNAL.equals(vol.id)) continue;
3826 vol.dump(pw);
3827 }
3828 pw.decreaseIndent();
3829
3830 pw.println();
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07003831 pw.println("Records:");
Jeff Sharkey27de30d2015-04-18 16:20:27 -07003832 pw.increaseIndent();
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07003833 for (int i = 0; i < mRecords.size(); i++) {
3834 final VolumeRecord note = mRecords.valueAt(i);
3835 note.dump(pw);
Jeff Sharkey27de30d2015-04-18 16:20:27 -07003836 }
3837 pw.decreaseIndent();
Jeff Sharkey275e3e42015-04-24 16:10:32 -07003838
3839 pw.println();
3840 pw.println("Primary storage UUID: " + mPrimaryStorageUuid);
Jeff Sharkeyb0c363b22018-12-15 11:53:03 -07003841
3842 pw.println();
Felipe Leme281389a2016-10-10 17:12:20 -07003843 final Pair<String, Long> pair = StorageManager.getPrimaryStoragePathAndSize();
3844 if (pair == null) {
3845 pw.println("Internal storage total size: N/A");
3846 } else {
3847 pw.print("Internal storage (");
3848 pw.print(pair.first);
3849 pw.print(") total size: ");
3850 pw.print(pair.second);
3851 pw.print(" (");
Jeff Sharkey9f2dc052018-01-07 16:47:31 -07003852 pw.print(DataUnit.MEBIBYTES.toBytes(pair.second));
3853 pw.println(" MiB)");
Felipe Leme281389a2016-10-10 17:12:20 -07003854 }
Jeff Sharkeyb0c363b22018-12-15 11:53:03 -07003855
3856 pw.println();
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07003857 pw.println("Local unlocked users: " + Arrays.toString(mLocalUnlockedUsers));
3858 pw.println("System unlocked users: " + Arrays.toString(mSystemUnlockedUsers));
Jeff Sharkeyb0c363b22018-12-15 11:53:03 -07003859
3860 final ContentResolver cr = mContext.getContentResolver();
3861 pw.println();
3862 pw.println("Isolated storage, local feature flag: "
3863 + Settings.Global.getInt(cr, Settings.Global.ISOLATED_STORAGE_LOCAL, 0));
3864 pw.println("Isolated storage, remote feature flag: "
3865 + Settings.Global.getInt(cr, Settings.Global.ISOLATED_STORAGE_REMOTE, 0));
3866 pw.println("Isolated storage, resolved: " + StorageManager.hasIsolatedStorage());
Jeff Sharkey27de30d2015-04-18 16:20:27 -07003867 }
Kenny Root38cf8862010-09-26 14:18:51 -07003868
Kenny Root38cf8862010-09-26 14:18:51 -07003869 synchronized (mObbMounts) {
Jeff Sharkey27de30d2015-04-18 16:20:27 -07003870 pw.println();
Jeff Sharkey5aca2b82013-10-16 16:21:54 -07003871 pw.println("mObbMounts:");
3872 pw.increaseIndent();
3873 final Iterator<Entry<IBinder, List<ObbState>>> binders = mObbMounts.entrySet()
3874 .iterator();
Kenny Rootaf9d6672010-10-08 09:21:39 -07003875 while (binders.hasNext()) {
3876 Entry<IBinder, List<ObbState>> e = binders.next();
Jeff Sharkey5aca2b82013-10-16 16:21:54 -07003877 pw.println(e.getKey() + ":");
3878 pw.increaseIndent();
Kenny Rootaf9d6672010-10-08 09:21:39 -07003879 final List<ObbState> obbStates = e.getValue();
Kenny Root38cf8862010-09-26 14:18:51 -07003880 for (final ObbState obbState : obbStates) {
Jeff Sharkey5aca2b82013-10-16 16:21:54 -07003881 pw.println(obbState);
Kenny Root38cf8862010-09-26 14:18:51 -07003882 }
Jeff Sharkey5aca2b82013-10-16 16:21:54 -07003883 pw.decreaseIndent();
Kenny Root38cf8862010-09-26 14:18:51 -07003884 }
Jeff Sharkey5aca2b82013-10-16 16:21:54 -07003885 pw.decreaseIndent();
Kenny Rootaf9d6672010-10-08 09:21:39 -07003886
Jeff Sharkey5aca2b82013-10-16 16:21:54 -07003887 pw.println();
3888 pw.println("mObbPathToStateMap:");
3889 pw.increaseIndent();
Kenny Rootaf9d6672010-10-08 09:21:39 -07003890 final Iterator<Entry<String, ObbState>> maps = mObbPathToStateMap.entrySet().iterator();
3891 while (maps.hasNext()) {
3892 final Entry<String, ObbState> e = maps.next();
Jeff Sharkey5aca2b82013-10-16 16:21:54 -07003893 pw.print(e.getKey());
3894 pw.print(" -> ");
3895 pw.println(e.getValue());
Kenny Rootaf9d6672010-10-08 09:21:39 -07003896 }
Jeff Sharkey5aca2b82013-10-16 16:21:54 -07003897 pw.decreaseIndent();
Kenny Root38cf8862010-09-26 14:18:51 -07003898 }
Kenny Root4161f9b2011-07-13 09:48:33 -07003899
Robert Greenwalt470fd722012-01-18 12:51:15 -08003900 pw.println();
Christopher Tate7265abe2014-11-21 13:54:45 -08003901 pw.print("Last maintenance: ");
Jeff Sharkeye8a4b662015-06-27 15:43:45 -07003902 pw.println(TimeUtils.formatForLogging(mLastMaintenance));
Kenny Root38cf8862010-09-26 14:18:51 -07003903 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003904
Jeff Sharkeyfa23c5a2011-08-09 21:44:24 -07003905 /** {@inheritDoc} */
Jeff Sharkey48877892015-03-18 11:27:19 -07003906 @Override
Jeff Sharkeyfa23c5a2011-08-09 21:44:24 -07003907 public void monitor() {
Jeff Sharkey54402792017-09-15 16:05:19 -06003908 try {
3909 mVold.monitor();
3910 } catch (Exception e) {
3911 Slog.wtf(TAG, e);
Paul Lawrence1c62cbb2015-06-03 14:14:52 -07003912 }
Jeff Sharkeyfa23c5a2011-08-09 21:44:24 -07003913 }
Svet Ganov6ee871e2015-07-10 14:29:33 -07003914
Sudheer Shanka2250d562016-11-07 15:41:02 -08003915 private final class StorageManagerInternalImpl extends StorageManagerInternal {
Svet Ganov6ee871e2015-07-10 14:29:33 -07003916 // Not guarded by a lock.
3917 private final CopyOnWriteArrayList<ExternalStorageMountPolicy> mPolicies =
3918 new CopyOnWriteArrayList<>();
3919
Risanaec0ee72018-10-31 10:10:12 +09003920 @GuardedBy("mResetListeners")
3921 private final List<StorageManagerInternal.ResetListener> mResetListeners =
3922 new ArrayList<>();
3923
Svet Ganov6ee871e2015-07-10 14:29:33 -07003924 @Override
3925 public void addExternalStoragePolicy(ExternalStorageMountPolicy policy) {
3926 // No locking - CopyOnWriteArrayList
3927 mPolicies.add(policy);
3928 }
3929
3930 @Override
3931 public void onExternalStoragePolicyChanged(int uid, String packageName) {
Sudheer Shanka0a541a52018-07-31 13:21:11 -07003932 // No runtime storage permissions in isolated storage world, so nothing to do here.
Jeff Sharkeyc58fdf32018-08-15 18:49:34 -06003933 if (ENABLE_ISOLATED_STORAGE) return;
Svet Ganov6ee871e2015-07-10 14:29:33 -07003934 final int mountMode = getExternalStorageMountMode(uid, packageName);
3935 remountUidExternalStorage(uid, mountMode);
3936 }
3937
3938 @Override
3939 public int getExternalStorageMountMode(int uid, String packageName) {
Sudheer Shanka3a0df3b2018-12-12 12:43:43 -08003940 if (ENABLE_ISOLATED_STORAGE) {
3941 return getMountMode(uid, packageName);
3942 }
Svet Ganov6ee871e2015-07-10 14:29:33 -07003943 // No locking - CopyOnWriteArrayList
3944 int mountMode = Integer.MAX_VALUE;
3945 for (ExternalStorageMountPolicy policy : mPolicies) {
3946 final int policyMode = policy.getMountMode(uid, packageName);
3947 if (policyMode == Zygote.MOUNT_EXTERNAL_NONE) {
3948 return Zygote.MOUNT_EXTERNAL_NONE;
3949 }
3950 mountMode = Math.min(mountMode, policyMode);
3951 }
3952 if (mountMode == Integer.MAX_VALUE) {
3953 return Zygote.MOUNT_EXTERNAL_NONE;
3954 }
3955 return mountMode;
3956 }
3957
Risanaec0ee72018-10-31 10:10:12 +09003958 @Override
3959 public void addResetListener(StorageManagerInternal.ResetListener listener) {
3960 synchronized (mResetListeners) {
3961 mResetListeners.add(listener);
3962 }
3963 }
3964
3965 public void onReset(IVold vold) {
3966 synchronized (mResetListeners) {
3967 for (StorageManagerInternal.ResetListener listener : mResetListeners) {
3968 listener.onReset(vold);
3969 }
3970 }
3971 }
3972
Svet Ganov6ee871e2015-07-10 14:29:33 -07003973 public boolean hasExternalStorage(int uid, String packageName) {
Amith Yamasani2bd5cff2015-07-22 14:42:31 -07003974 // No need to check for system uid. This avoids a deadlock between
3975 // PackageManagerService and AppOpsService.
3976 if (uid == Process.SYSTEM_UID) {
3977 return true;
3978 }
Sudheer Shanka3a0df3b2018-12-12 12:43:43 -08003979 if (ENABLE_ISOLATED_STORAGE) {
3980 return getMountMode(uid, packageName) != Zygote.MOUNT_EXTERNAL_NONE;
3981 }
Svet Ganov6ee871e2015-07-10 14:29:33 -07003982 // No locking - CopyOnWriteArrayList
3983 for (ExternalStorageMountPolicy policy : mPolicies) {
3984 final boolean policyHasStorage = policy.hasExternalStorage(uid, packageName);
3985 if (!policyHasStorage) {
3986 return false;
3987 }
3988 }
3989 return true;
3990 }
Sudheer Shanka8ff30b12018-08-06 17:29:44 -07003991
3992 @Override
Sudheer Shanka584b0682018-10-04 16:26:16 -07003993 public void prepareSandboxForApp(String packageName, int appId, String sharedUserId,
Sudheer Shanka8ff30b12018-08-06 17:29:44 -07003994 int userId) {
3995 final String sandboxId;
3996 synchronized (mPackagesLock) {
Sudheer Shanka2ac25a92018-10-25 10:59:32 -07003997 final ArraySet<String> userPackages = mPackages.get(userId);
Sudheer Shanka8ff30b12018-08-06 17:29:44 -07003998 // If userPackages is empty, it means the user is not started yet, so no need to
3999 // do anything now.
Sudheer Shanka2ac25a92018-10-25 10:59:32 -07004000 if (userPackages == null || userPackages.contains(packageName)) {
Sudheer Shanka8ff30b12018-08-06 17:29:44 -07004001 return;
4002 }
4003 userPackages.add(packageName);
Sudheer Shanka03fd40b2019-02-06 12:39:14 -08004004 sandboxId = StorageManagerService.this.getSandboxId(packageName, sharedUserId);
Sudheer Shanka8ff30b12018-08-06 17:29:44 -07004005 }
4006
4007 try {
Sudheer Shanka584b0682018-10-04 16:26:16 -07004008 mVold.prepareSandboxForApp(packageName, appId, sandboxId, userId);
4009 } catch (Exception e) {
4010 Slog.wtf(TAG, e);
4011 }
4012 }
4013
4014 @Override
Sudheer Shanka2ac25a92018-10-25 10:59:32 -07004015 public void destroySandboxForApp(String packageName, String sharedUserId, int userId) {
Sudheer Shanka584b0682018-10-04 16:26:16 -07004016 if (!ENABLE_ISOLATED_STORAGE) {
4017 return;
4018 }
Sudheer Shanka03fd40b2019-02-06 12:39:14 -08004019 final String sandboxId = StorageManagerService.this.getSandboxId(
4020 packageName, sharedUserId);
Sudheer Shanka584b0682018-10-04 16:26:16 -07004021 synchronized (mPackagesLock) {
Sudheer Shanka2ac25a92018-10-25 10:59:32 -07004022 final ArraySet<String> userPackages = mPackages.get(userId);
4023 // If the userPackages is null, it means the user is not started but we still
4024 // need to delete the sandbox data though.
4025 if (userPackages != null) {
4026 userPackages.remove(packageName);
Sudheer Shanka584b0682018-10-04 16:26:16 -07004027 }
4028 }
4029 try {
Sudheer Shanka2ac25a92018-10-25 10:59:32 -07004030 mVold.destroySandboxForApp(packageName, sandboxId, userId);
Sudheer Shanka8ff30b12018-08-06 17:29:44 -07004031 } catch (Exception e) {
4032 Slog.wtf(TAG, e);
4033 }
4034 }
Sudheer Shanka3f0645b2018-09-18 13:07:59 -07004035
4036 @Override
Sudheer Shanka03fd40b2019-02-06 12:39:14 -08004037 public String getSandboxId(String packageName) {
4038 return StorageManagerService.this.getSandboxId(packageName,
4039 mPmInternal.getSharedUserIdForPackage(packageName));
4040 }
Svet Ganov6ee871e2015-07-10 14:29:33 -07004041 }
Jeff Sharkeyfa23c5a2011-08-09 21:44:24 -07004042}