blob: 9d810cd8f3ca00256f4c1b69958ce89ad41f1ca5 [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 Sharkey14cbe522015-07-08 14:06:37 -0700115import android.provider.MediaStore;
Jeff Sharkeye8a4b662015-06-27 15:43:45 -0700116import android.provider.Settings;
Inseob Kimc1246e62018-11-08 13:13:54 +0900117import android.sysprop.VoldProperties;
Jason parksf7b3cd42011-01-27 09:28:25 -0600118import android.text.TextUtils;
Jeff Sharkey1783f142015-04-17 10:52:51 -0700119import android.text.format.DateUtils;
Jeff Sharkey48877892015-03-18 11:27:19 -0700120import android.util.ArrayMap;
Sudheer Shanka0a541a52018-07-31 13:21:11 -0700121import android.util.ArraySet;
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700122import android.util.AtomicFile;
Jeff Sharkey9f2dc052018-01-07 16:47:31 -0700123import android.util.DataUnit;
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -0700124import android.util.Log;
Felipe Leme281389a2016-10-10 17:12:20 -0700125import android.util.Pair;
San Mehata5078592010-03-25 09:36:54 -0700126import android.util.Slog;
Sudheer Shanka0a541a52018-07-31 13:21:11 -0700127import android.util.SparseArray;
Jeff Sharkeye8a4b662015-06-27 15:43:45 -0700128import android.util.TimeUtils;
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700129import android.util.Xml;
Jeff Sharkey48877892015-03-18 11:27:19 -0700130
Jeff Sharkey8b2c3a142012-11-12 11:45:05 -0800131import com.android.internal.annotations.GuardedBy;
Sudheer Shankaff971bc2018-12-13 17:39:59 -0800132import com.android.internal.app.IAppOpsCallback;
Sudheer Shanka3a0df3b2018-12-12 12:43:43 -0800133import com.android.internal.app.IAppOpsService;
Daichi Hirono9fb00182016-11-08 14:12:17 +0900134import com.android.internal.os.AppFuseMount;
Jeff Sharkey1019de92017-09-06 13:47:03 -0600135import com.android.internal.os.BackgroundThread;
Daichi Hirono812c95d2017-02-08 16:20:20 +0900136import com.android.internal.os.FuseUnavailableMountException;
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700137import com.android.internal.os.SomeArgs;
Jeff Sharkey9527b222015-06-24 15:24:48 -0700138import com.android.internal.os.Zygote;
Jeff Sharkey48877892015-03-18 11:27:19 -0700139import com.android.internal.util.ArrayUtils;
Jeff Sharkey11697f52018-12-13 10:14:42 -0700140import com.android.internal.util.CollectionUtils;
Jeff Sharkeyfe9a53b2017-03-31 14:08:23 -0600141import com.android.internal.util.DumpUtils;
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700142import com.android.internal.util.FastXmlSerializer;
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -0800143import com.android.internal.util.HexDump;
Jeff Sharkey5aca2b82013-10-16 16:21:54 -0700144import com.android.internal.util.IndentingPrintWriter;
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700145import com.android.internal.util.Preconditions;
Jeff Sharkeyb9fe5372015-12-03 15:23:08 -0700146import com.android.internal.widget.LockPatternUtils;
Daichi Hirono9fb00182016-11-08 14:12:17 +0900147import com.android.server.storage.AppFuseBridge;
Wale Ogunwale9e4f3e02018-05-17 09:35:39 -0700148import com.android.server.wm.ActivityTaskManagerInternal;
149import com.android.server.wm.ActivityTaskManagerInternal.ScreenObserver;
Jeff Sharkey5217cac2015-12-20 15:34:01 -0700150
Jeff Sharkey5790af02018-08-13 17:42:54 -0600151import libcore.io.IoUtils;
152import libcore.util.EmptyArray;
153
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700154import org.xmlpull.v1.XmlPullParser;
155import org.xmlpull.v1.XmlPullParserException;
156import org.xmlpull.v1.XmlSerializer;
157
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700158import java.io.File;
Kenny Root38cf8862010-09-26 14:18:51 -0700159import java.io.FileDescriptor;
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700160import java.io.FileInputStream;
161import java.io.FileNotFoundException;
Christopher Tate7265abe2014-11-21 13:54:45 -0800162import java.io.FileOutputStream;
Kenny Root05105f72010-09-22 17:29:43 -0700163import java.io.IOException;
Kenny Root38cf8862010-09-26 14:18:51 -0700164import java.io.PrintWriter;
Kenny Root3b1abba2010-10-13 15:00:07 -0700165import java.math.BigInteger;
Paul Lawrence8e397362014-01-27 15:22:30 -0800166import java.nio.charset.StandardCharsets;
Jeff Sharkey0095a822018-02-15 13:06:53 -0700167import java.security.GeneralSecurityException;
Kenny Root3b1abba2010-10-13 15:00:07 -0700168import java.security.spec.KeySpec;
San Mehat22dd86e2010-01-12 12:21:18 -0800169import java.util.ArrayList;
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -0800170import java.util.Arrays;
Kenny Roota02b8b02010-08-05 16:14:17 -0700171import java.util.HashMap;
Kenny Root38cf8862010-09-26 14:18:51 -0700172import java.util.Iterator;
Kenny Roota02b8b02010-08-05 16:14:17 -0700173import java.util.LinkedList;
174import java.util.List;
Elliott Hughesf839b4f2014-09-26 12:30:47 -0700175import java.util.Locale;
Kenny Roota02b8b02010-08-05 16:14:17 -0700176import java.util.Map;
Kenny Root38cf8862010-09-26 14:18:51 -0700177import java.util.Map.Entry;
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700178import java.util.Objects;
Svet Ganov6ee871e2015-07-10 14:29:33 -0700179import java.util.concurrent.CopyOnWriteArrayList;
Kenny Root51a573c2012-05-17 13:30:28 -0700180import java.util.concurrent.CountDownLatch;
181import java.util.concurrent.TimeUnit;
Jeff Sharkeyedcdaf62015-07-09 09:45:36 -0700182import java.util.concurrent.TimeoutException;
Jeff Sharkey5790af02018-08-13 17:42:54 -0600183import java.util.regex.Matcher;
184import java.util.regex.Pattern;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800185
Kenny Root3b1abba2010-10-13 15:00:07 -0700186import javax.crypto.SecretKey;
187import javax.crypto.SecretKeyFactory;
188import javax.crypto.spec.PBEKeySpec;
189
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800190/**
Jeff Sharkey48877892015-03-18 11:27:19 -0700191 * Service responsible for various storage media. Connects to {@code vold} to
192 * watch for and manage dynamically added storage, such as SD cards and USB mass
193 * storage. Also decides how storage should be presented to users on the device.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800194 */
Jeff Sharkey9765e442017-12-14 22:15:14 -0700195class StorageManagerService extends IStorageManager.Stub
196 implements Watchdog.Monitor, ScreenObserver {
Jason parks5af0b912010-11-29 09:05:25 -0600197
Christopher Tated417d622013-08-19 16:14:25 -0700198 // Static direct instance pointer for the tightly-coupled idle service to use
Sudheer Shanka2250d562016-11-07 15:41:02 -0800199 static StorageManagerService sSelf = null;
Christopher Tated417d622013-08-19 16:14:25 -0700200
Daniel Colascione766b6322018-01-08 19:10:36 -0800201 /* Read during boot to decide whether to enable zram when available */
202 private static final String ZRAM_ENABLED_PROPERTY =
Sudheer Shanka0a541a52018-07-31 13:21:11 -0700203 "persist.sys.zram_enabled";
204
Jeff Sharkey10ec9d82018-11-28 14:52:45 -0700205 private static final boolean ENABLE_ISOLATED_STORAGE = StorageManager.hasIsolatedStorage();
Sudheer Shanka0a541a52018-07-31 13:21:11 -0700206
Jeff Sharkey56e62932015-03-21 20:41:00 -0700207 public static class Lifecycle extends SystemService {
Sudheer Shanka2250d562016-11-07 15:41:02 -0800208 private StorageManagerService mStorageManagerService;
Jeff Sharkey56e62932015-03-21 20:41:00 -0700209
210 public Lifecycle(Context context) {
211 super(context);
212 }
213
214 @Override
215 public void onStart() {
Sudheer Shanka2250d562016-11-07 15:41:02 -0800216 mStorageManagerService = new StorageManagerService(getContext());
217 publishBinderService("mount", mStorageManagerService);
218 mStorageManagerService.start();
Jeff Sharkey56e62932015-03-21 20:41:00 -0700219 }
220
221 @Override
222 public void onBootPhase(int phase) {
Jeff Sharkey11697f52018-12-13 10:14:42 -0700223 if (phase == SystemService.PHASE_SYSTEM_SERVICES_READY) {
224 mStorageManagerService.servicesReady();
225 } else if (phase == SystemService.PHASE_ACTIVITY_MANAGER_READY) {
Sudheer Shanka2250d562016-11-07 15:41:02 -0800226 mStorageManagerService.systemReady();
Yasuhiro Matsuda87a38b52015-07-24 22:10:16 +0900227 } else if (phase == SystemService.PHASE_BOOT_COMPLETED) {
Sudheer Shanka2250d562016-11-07 15:41:02 -0800228 mStorageManagerService.bootCompleted();
Jeff Sharkey56e62932015-03-21 20:41:00 -0700229 }
230 }
Jeff Sharkey48877892015-03-18 11:27:19 -0700231
232 @Override
Jeff Sharkeyab15c392016-05-05 11:45:01 -0600233 public void onSwitchUser(int userHandle) {
Sudheer Shanka2250d562016-11-07 15:41:02 -0800234 mStorageManagerService.mCurrentUserId = userHandle;
Jeff Sharkeyab15c392016-05-05 11:45:01 -0600235 }
236
237 @Override
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700238 public void onUnlockUser(int userHandle) {
Sudheer Shanka2250d562016-11-07 15:41:02 -0800239 mStorageManagerService.onUnlockUser(userHandle);
Jeff Sharkey48877892015-03-18 11:27:19 -0700240 }
241
242 @Override
243 public void onCleanupUser(int userHandle) {
Sudheer Shanka2250d562016-11-07 15:41:02 -0800244 mStorageManagerService.onCleanupUser(userHandle);
Jeff Sharkey48877892015-03-18 11:27:19 -0700245 }
Jeff Sharkey56e62932015-03-21 20:41:00 -0700246 }
247
Dianne Hackborn40e9f292012-11-27 19:12:23 -0800248 private static final boolean DEBUG_EVENTS = false;
Kenny Rootb7db2722011-01-25 16:39:35 -0800249 private static final boolean DEBUG_OBB = false;
Kenny Root02c87302010-07-01 08:10:18 -0700250
Jeff Sharkeyc3c72872018-06-06 15:35:53 -0600251 /**
252 * We now talk to vold over Binder, and it has its own internal lock to
253 * serialize certain calls. All long-running operations have been migrated
254 * to be async with callbacks, so we want watchdog to fire if vold wedges.
255 */
256 private static final boolean WATCHDOG_ENABLE = true;
Kenny Root07714d42011-08-17 17:49:28 -0700257
Jeff Sharkey00455bf2016-11-04 14:45:24 -0600258 /**
259 * Our goal is for all Android devices to be usable as development devices,
260 * which includes the new Direct Boot mode added in N. For devices that
261 * don't have native FBE support, we offer an emulation mode for developer
262 * testing purposes, but if it's prohibitively difficult to support this
263 * mode, it can be disabled for specific products using this flag.
264 */
265 private static final boolean EMULATE_FBE_SUPPORTED = true;
266
Sudheer Shanka2250d562016-11-07 15:41:02 -0800267 private static final String TAG = "StorageManagerService";
Jeff Sharkeye8a4b662015-06-27 15:43:45 -0700268
Jeff Sharkey9756d752015-05-14 21:07:42 -0700269 private static final String TAG_STORAGE_BENCHMARK = "storage_benchmark";
Jeff Sharkeye8a4b662015-06-27 15:43:45 -0700270 private static final String TAG_STORAGE_TRIM = "storage_trim";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800271
Jeff Sharkey275e3e42015-04-24 16:10:32 -0700272 /** Magic value sent by MoveTask.cpp */
273 private static final int MOVE_STATUS_COPY_FINISHED = 82;
274
Jeff Sharkey620b32b2015-04-23 19:36:02 -0700275 private static final int VERSION_INIT = 1;
276 private static final int VERSION_ADD_PRIMARY = 2;
Jeff Sharkeyfced5342015-05-10 14:53:34 -0700277 private static final int VERSION_FIX_PRIMARY = 3;
Jeff Sharkey620b32b2015-04-23 19:36:02 -0700278
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700279 private static final String TAG_VOLUMES = "volumes";
Jeff Sharkey620b32b2015-04-23 19:36:02 -0700280 private static final String ATTR_VERSION = "version";
281 private static final String ATTR_PRIMARY_STORAGE_UUID = "primaryStorageUuid";
Jeff Sharkey11697f52018-12-13 10:14:42 -0700282 private static final String ATTR_ISOLATED_STORAGE = "isolatedStorage";
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700283 private static final String TAG_VOLUME = "volume";
284 private static final String ATTR_TYPE = "type";
285 private static final String ATTR_FS_UUID = "fsUuid";
Jeff Sharkey5cc0df22015-06-17 19:44:05 -0700286 private static final String ATTR_PART_GUID = "partGuid";
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700287 private static final String ATTR_NICKNAME = "nickname";
288 private static final String ATTR_USER_FLAGS = "userFlags";
Jeff Sharkeye8a4b662015-06-27 15:43:45 -0700289 private static final String ATTR_CREATED_MILLIS = "createdMillis";
290 private static final String ATTR_LAST_TRIM_MILLIS = "lastTrimMillis";
291 private static final String ATTR_LAST_BENCH_MILLIS = "lastBenchMillis";
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700292
Jeff Sharkeyb36586a2015-04-27 08:42:28 -0700293 private final AtomicFile mSettingsFile;
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700294
Jeff Sharkey48877892015-03-18 11:27:19 -0700295 /**
296 * <em>Never</em> hold the lock while performing downcalls into vold, since
297 * unsolicited events can suddenly appear to update data structures.
298 */
Jeff Sharkey5f3e9342017-03-13 14:53:11 -0600299 private final Object mLock = LockGuard.installNewLock(LockGuard.INDEX_STORAGE);
Jeff Sharkey48877892015-03-18 11:27:19 -0700300
Sudheer Shanka0a541a52018-07-31 13:21:11 -0700301 /**
302 * Similar to {@link #mLock}, never hold this lock while performing downcalls into vold.
303 * Also, never hold this while calling into PackageManagerService since it is used in callbacks
304 * from PackageManagerService.
305 *
306 * If both {@link #mLock} and this lock need to be held, {@link #mLock} should be acquired
307 * before this.
308 *
309 * Use -PL suffix for methods that need to called with this lock held.
310 */
311 private final Object mPackagesLock = new Object();
312
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700313 /** Set of users that we know are unlocked. */
Jeff Sharkey48877892015-03-18 11:27:19 -0700314 @GuardedBy("mLock")
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700315 private int[] mLocalUnlockedUsers = EmptyArray.INT;
316 /** Set of users that system knows are unlocked. */
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -0800317 @GuardedBy("mLock")
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700318 private int[] mSystemUnlockedUsers = EmptyArray.INT;
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700319
320 /** Map from disk ID to disk */
Jeff Sharkey48877892015-03-18 11:27:19 -0700321 @GuardedBy("mLock")
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -0700322 private ArrayMap<String, DiskInfo> mDisks = new ArrayMap<>();
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700323 /** Map from volume ID to disk */
Jeff Sharkey48877892015-03-18 11:27:19 -0700324 @GuardedBy("mLock")
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700325 private final ArrayMap<String, VolumeInfo> mVolumes = new ArrayMap<>();
Jeff Sharkey48877892015-03-18 11:27:19 -0700326
Jeff Sharkeyb36586a2015-04-27 08:42:28 -0700327 /** Map from UUID to record */
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700328 @GuardedBy("mLock")
Jeff Sharkeyb36586a2015-04-27 08:42:28 -0700329 private ArrayMap<String, VolumeRecord> mRecords = new ArrayMap<>();
Jeff Sharkey620b32b2015-04-23 19:36:02 -0700330 @GuardedBy("mLock")
331 private String mPrimaryStorageUuid;
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700332
Jeff Sharkey11697f52018-12-13 10:14:42 -0700333 /** Flag indicating isolated storage state of last boot */
334 @GuardedBy("mLock")
335 private boolean mLastIsolatedStorage = false;
336
Jeff Sharkeyeba260d2015-04-19 14:35:16 -0700337 /** Map from disk ID to latches */
338 @GuardedBy("mLock")
339 private ArrayMap<String, CountDownLatch> mDiskScanLatches = new ArrayMap<>();
340
Jeff Sharkey275e3e42015-04-24 16:10:32 -0700341 @GuardedBy("mLock")
342 private IPackageMoveObserver mMoveCallback;
343 @GuardedBy("mLock")
344 private String mMoveTargetUuid;
345
Sudheer Shanka0a541a52018-07-31 13:21:11 -0700346 @GuardedBy("mPackagesLock")
347 private final SparseArray<ArraySet<String>> mPackages = new SparseArray<>();
348
Sudheer Shanka3f0645b2018-09-18 13:07:59 -0700349 /**
350 * List of volumes visible to any user.
351 * TODO: may be have a map of userId -> volumes?
352 */
353 private final CopyOnWriteArrayList<VolumeInfo> mVisibleVols = new CopyOnWriteArrayList<>();
354
Jeff Sharkeyab15c392016-05-05 11:45:01 -0600355 private volatile int mCurrentUserId = UserHandle.USER_SYSTEM;
356
Daichi Hirono9fb00182016-11-08 14:12:17 +0900357 /** Holding lock for AppFuse business */
358 private final Object mAppFuseLock = new Object();
359
360 @GuardedBy("mAppFuseLock")
361 private int mNextAppFuseName = 0;
362
363 @GuardedBy("mAppFuseLock")
Daichi Hironoe56740d2017-02-02 13:56:45 +0900364 private AppFuseBridge mAppFuseBridge = null;
Daichi Hirono9fb00182016-11-08 14:12:17 +0900365
Jeff Sharkeyef10ee02015-07-05 14:17:27 -0700366 private VolumeInfo findVolumeByIdOrThrow(String id) {
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700367 synchronized (mLock) {
368 final VolumeInfo vol = mVolumes.get(id);
369 if (vol != null) {
370 return vol;
371 }
372 }
373 throw new IllegalArgumentException("No volume found for ID " + id);
374 }
375
Jeff Sharkeyef10ee02015-07-05 14:17:27 -0700376 private String findVolumeIdForPathOrThrow(String path) {
Jeff Sharkey48877892015-03-18 11:27:19 -0700377 synchronized (mLock) {
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -0700378 for (int i = 0; i < mVolumes.size(); i++) {
379 final VolumeInfo vol = mVolumes.valueAt(i);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700380 if (vol.path != null && path.startsWith(vol.path)) {
381 return vol.id;
Jeff Sharkey48877892015-03-18 11:27:19 -0700382 }
383 }
384 }
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700385 throw new IllegalArgumentException("No volume found for path " + path);
Jeff Sharkey48877892015-03-18 11:27:19 -0700386 }
387
Jeff Sharkeye8a4b662015-06-27 15:43:45 -0700388 private VolumeRecord findRecordForPath(String path) {
389 synchronized (mLock) {
390 for (int i = 0; i < mVolumes.size(); i++) {
391 final VolumeInfo vol = mVolumes.valueAt(i);
392 if (vol.path != null && path.startsWith(vol.path)) {
393 return mRecords.get(vol.fsUuid);
394 }
395 }
396 }
397 return null;
398 }
399
400 private String scrubPath(String path) {
401 if (path.startsWith(Environment.getDataDirectory().getAbsolutePath())) {
402 return "internal";
403 }
404 final VolumeRecord rec = findRecordForPath(path);
405 if (rec == null || rec.createdMillis == 0) {
406 return "unknown";
407 } else {
408 return "ext:" + (int) ((System.currentTimeMillis() - rec.createdMillis)
409 / DateUtils.WEEK_IN_MILLIS) + "w";
410 }
411 }
412
Jeff Sharkeyef10ee02015-07-05 14:17:27 -0700413 private @Nullable VolumeInfo findStorageForUuid(String volumeUuid) {
Jeff Sharkey275e3e42015-04-24 16:10:32 -0700414 final StorageManager storage = mContext.getSystemService(StorageManager.class);
415 if (Objects.equals(StorageManager.UUID_PRIVATE_INTERNAL, volumeUuid)) {
Jeff Sharkeyef10ee02015-07-05 14:17:27 -0700416 return storage.findVolumeById(VolumeInfo.ID_EMULATED_INTERNAL);
Jeff Sharkey275e3e42015-04-24 16:10:32 -0700417 } else if (Objects.equals(StorageManager.UUID_PRIMARY_PHYSICAL, volumeUuid)) {
418 return storage.getPrimaryPhysicalVolume();
419 } else {
420 return storage.findEmulatedForPrivate(storage.findVolumeByUuid(volumeUuid));
421 }
422 }
423
Jeff Sharkeye8a4b662015-06-27 15:43:45 -0700424 private boolean shouldBenchmark() {
425 final long benchInterval = Settings.Global.getLong(mContext.getContentResolver(),
426 Settings.Global.STORAGE_BENCHMARK_INTERVAL, DateUtils.WEEK_IN_MILLIS);
Jeff Sharkeye83d8a92015-09-09 14:53:38 -0700427 if (benchInterval == -1) {
428 return false;
429 } else if (benchInterval == 0) {
430 return true;
431 }
432
Jeff Sharkeye8a4b662015-06-27 15:43:45 -0700433 synchronized (mLock) {
434 for (int i = 0; i < mVolumes.size(); i++) {
435 final VolumeInfo vol = mVolumes.valueAt(i);
436 final VolumeRecord rec = mRecords.get(vol.fsUuid);
Jeff Sharkeye83d8a92015-09-09 14:53:38 -0700437 if (vol.isMountedWritable() && rec != null) {
Jeff Sharkeye8a4b662015-06-27 15:43:45 -0700438 final long benchAge = System.currentTimeMillis() - rec.lastBenchMillis;
439 if (benchAge >= benchInterval) {
440 return true;
441 }
442 }
443 }
444 return false;
445 }
446 }
447
Jeff Sharkeyeba260d2015-04-19 14:35:16 -0700448 private CountDownLatch findOrCreateDiskScanLatch(String diskId) {
449 synchronized (mLock) {
450 CountDownLatch latch = mDiskScanLatches.get(diskId);
451 if (latch == null) {
452 latch = new CountDownLatch(1);
453 mDiskScanLatches.put(diskId, latch);
454 }
455 return latch;
456 }
457 }
458
Paul Lawrence8e397362014-01-27 15:22:30 -0800459 /** List of crypto types.
460 * These must match CRYPT_TYPE_XXX in cryptfs.h AND their
461 * corresponding commands in CommandListener.cpp */
462 public static final String[] CRYPTO_TYPES
463 = { "password", "default", "pattern", "pin" };
464
Brian Carlstrom7395a8a2014-04-28 22:11:01 -0700465 private final Context mContext;
Jeff Sharkeycd575992016-03-29 14:12:49 -0600466
Jeff Sharkey1019de92017-09-06 13:47:03 -0600467 private volatile IVold mVold;
Jin Qian12690d52017-10-13 18:17:04 -0700468 private volatile IStoraged mStoraged;
Jeff Sharkey1019de92017-09-06 13:47:03 -0600469
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700470 private volatile boolean mSystemReady = false;
Yasuhiro Matsuda87a38b52015-07-24 22:10:16 +0900471 private volatile boolean mBootCompleted = false;
Jeff Sharkey48877892015-03-18 11:27:19 -0700472 private volatile boolean mDaemonConnected = false;
Jeff Sharkey9765e442017-12-14 22:15:14 -0700473 private volatile boolean mSecureKeyguardShowing = true;
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700474
Sudheer Shanka0a541a52018-07-31 13:21:11 -0700475 private PackageManagerInternal mPmInternal;
Jeff Sharkey5790af02018-08-13 17:42:54 -0600476 private UserManagerInternal mUmInternal;
Sudheer Shanka87915d62018-11-06 10:57:35 -0800477 private ActivityManagerInternal mAmInternal;
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700478
Sudheer Shanka3a0df3b2018-12-12 12:43:43 -0800479 private IPackageManager mIPackageManager;
480 private IAppOpsService mIAppOpsService;
481
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700482 private final Callbacks mCallbacks;
Jeff Sharkeyb9fe5372015-12-03 15:23:08 -0700483 private final LockPatternUtils mLockPatternUtils;
Jeff Sharkey48877892015-03-18 11:27:19 -0700484
San Mehat6cdd9c02010-02-09 14:45:20 -0800485 /**
Kenny Root3b1abba2010-10-13 15:00:07 -0700486 * The size of the crypto algorithm key in bits for OBB files. Currently
487 * Twofish is used which takes 128-bit keys.
488 */
489 private static final int CRYPTO_ALGORITHM_KEY_SIZE = 128;
490
491 /**
492 * The number of times to run SHA1 in the PBKDF2 function for OBB files.
493 * 1024 is reasonably secure and not too slow.
494 */
495 private static final int PBKDF2_HASH_ROUNDS = 1024;
496
497 /**
Kenny Roota02b8b02010-08-05 16:14:17 -0700498 * Mounted OBB tracking information. Used to track the current state of all
499 * OBBs.
Kenny Root02c87302010-07-01 08:10:18 -0700500 */
Kenny Root735de3b2010-09-30 14:11:39 -0700501 final private Map<IBinder, List<ObbState>> mObbMounts = new HashMap<IBinder, List<ObbState>>();
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700502
503 /** Map from raw paths to {@link ObbState}. */
Kenny Roota02b8b02010-08-05 16:14:17 -0700504 final private Map<String, ObbState> mObbPathToStateMap = new HashMap<String, ObbState>();
505
Svet Ganov6ee871e2015-07-10 14:29:33 -0700506 // Not guarded by a lock.
Sudheer Shanka2250d562016-11-07 15:41:02 -0800507 private final StorageManagerInternalImpl mStorageManagerInternal
508 = new StorageManagerInternalImpl();
Svet Ganov6ee871e2015-07-10 14:29:33 -0700509
Kenny Roota02b8b02010-08-05 16:14:17 -0700510 class ObbState implements IBinder.DeathRecipient {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700511 public ObbState(String rawPath, String canonicalPath, int callingUid,
Jeff Sharkey41cd6812017-09-11 10:32:17 -0600512 IObbActionListener token, int nonce, String volId) {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700513 this.rawPath = rawPath;
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700514 this.canonicalPath = canonicalPath;
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700515 this.ownerGid = UserHandle.getSharedAppGid(callingUid);
Kenny Rootaf9d6672010-10-08 09:21:39 -0700516 this.token = token;
517 this.nonce = nonce;
Jeff Sharkey41cd6812017-09-11 10:32:17 -0600518 this.volId = volId;
Kenny Roota02b8b02010-08-05 16:14:17 -0700519 }
520
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700521 final String rawPath;
522 final String canonicalPath;
Kenny Roota02b8b02010-08-05 16:14:17 -0700523
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700524 final int ownerGid;
Kenny Roota02b8b02010-08-05 16:14:17 -0700525
Kenny Rootaf9d6672010-10-08 09:21:39 -0700526 // Token of remote Binder caller
527 final IObbActionListener token;
528
529 // Identifier to pass back to the token
530 final int nonce;
Kenny Roota02b8b02010-08-05 16:14:17 -0700531
Jeff Sharkey41cd6812017-09-11 10:32:17 -0600532 String volId;
533
Kenny Root735de3b2010-09-30 14:11:39 -0700534 public IBinder getBinder() {
535 return token.asBinder();
536 }
537
Kenny Roota02b8b02010-08-05 16:14:17 -0700538 @Override
539 public void binderDied() {
540 ObbAction action = new UnmountObbAction(this, true);
541 mObbActionHandler.sendMessage(mObbActionHandler.obtainMessage(OBB_RUN_ACTION, action));
Kenny Root735de3b2010-09-30 14:11:39 -0700542 }
Kenny Roota02b8b02010-08-05 16:14:17 -0700543
Kenny Root5919ac62010-10-05 09:49:40 -0700544 public void link() throws RemoteException {
545 getBinder().linkToDeath(this, 0);
546 }
547
548 public void unlink() {
Kenny Root735de3b2010-09-30 14:11:39 -0700549 getBinder().unlinkToDeath(this, 0);
Kenny Roota02b8b02010-08-05 16:14:17 -0700550 }
Kenny Root38cf8862010-09-26 14:18:51 -0700551
552 @Override
553 public String toString() {
554 StringBuilder sb = new StringBuilder("ObbState{");
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700555 sb.append("rawPath=").append(rawPath);
556 sb.append(",canonicalPath=").append(canonicalPath);
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700557 sb.append(",ownerGid=").append(ownerGid);
558 sb.append(",token=").append(token);
559 sb.append(",binder=").append(getBinder());
Jeff Sharkey41cd6812017-09-11 10:32:17 -0600560 sb.append(",volId=").append(volId);
Kenny Root38cf8862010-09-26 14:18:51 -0700561 sb.append('}');
562 return sb.toString();
563 }
Kenny Roota02b8b02010-08-05 16:14:17 -0700564 }
565
566 // OBB Action Handler
567 final private ObbActionHandler mObbActionHandler;
568
569 // OBB action handler messages
570 private static final int OBB_RUN_ACTION = 1;
Sudheer Shanka25469aa2018-08-27 15:50:23 -0700571 private static final int OBB_FLUSH_MOUNT_STATE = 2;
Kenny Root02c87302010-07-01 08:10:18 -0700572
Christopher Tate7265abe2014-11-21 13:54:45 -0800573 // Last fstrim operation tracking
574 private static final String LAST_FSTRIM_FILE = "last-fstrim";
575 private final File mLastMaintenanceFile;
576 private long mLastMaintenance;
577
Kenny Root02c87302010-07-01 08:10:18 -0700578 // Handler messages
Jeff Sharkey48877892015-03-18 11:27:19 -0700579 private static final int H_SYSTEM_READY = 1;
580 private static final int H_DAEMON_CONNECTED = 2;
581 private static final int H_SHUTDOWN = 3;
582 private static final int H_FSTRIM = 4;
583 private static final int H_VOLUME_MOUNT = 5;
584 private static final int H_VOLUME_BROADCAST = 6;
Jeff Sharkeyabc3e852015-08-03 14:41:13 -0700585 private static final int H_INTERNAL_BROADCAST = 7;
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700586 private static final int H_VOLUME_UNMOUNT = 8;
Jeff Sharkey5a9bb742015-11-03 10:15:57 -0800587 private static final int H_PARTITION_FORGET = 9;
588 private static final int H_RESET = 10;
Jin Qiana85b9912017-10-17 15:48:18 -0700589 private static final int H_RUN_IDLE_MAINT = 11;
590 private static final int H_ABORT_IDLE_MAINT = 12;
Suchi Amalapurapu6ffce2e2010-03-08 14:48:40 -0800591
Sudheer Shanka2250d562016-11-07 15:41:02 -0800592 class StorageManagerServiceHandler extends Handler {
593 public StorageManagerServiceHandler(Looper looper) {
Jeff Sharkey48877892015-03-18 11:27:19 -0700594 super(looper);
Daniel Sandler5f27ef42010-03-16 15:42:02 -0400595 }
596
Jason parks5af0b912010-11-29 09:05:25 -0600597 @Override
Suchi Amalapurapuc42e29e2010-02-22 16:03:53 -0800598 public void handleMessage(Message msg) {
599 switch (msg.what) {
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700600 case H_SYSTEM_READY: {
Jeff Sharkey48877892015-03-18 11:27:19 -0700601 handleSystemReady();
602 break;
603 }
604 case H_DAEMON_CONNECTED: {
605 handleDaemonConnected();
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700606 break;
607 }
Christopher Tated417d622013-08-19 16:14:25 -0700608 case H_FSTRIM: {
Christopher Tated417d622013-08-19 16:14:25 -0700609 Slog.i(TAG, "Running fstrim idle maintenance");
Christopher Tate7265abe2014-11-21 13:54:45 -0800610
611 // Remember when we kicked it off
612 try {
613 mLastMaintenance = System.currentTimeMillis();
614 mLastMaintenanceFile.setLastModified(mLastMaintenance);
615 } catch (Exception e) {
616 Slog.e(TAG, "Unable to record last fstrim!");
617 }
618
Jeff Sharkeyb302c542017-09-15 12:57:59 -0600619 // TODO: Reintroduce shouldBenchmark() test
Jeff Sharkey7e19f532017-11-06 13:54:11 -0700620 fstrim(0, null);
Christopher Tate7265abe2014-11-21 13:54:45 -0800621
Christopher Tated417d622013-08-19 16:14:25 -0700622 // invoke the completion callback, if any
Jeff Sharkeye8a4b662015-06-27 15:43:45 -0700623 // TODO: fstrim is non-blocking, so remove this useless callback
Christopher Tated417d622013-08-19 16:14:25 -0700624 Runnable callback = (Runnable) msg.obj;
625 if (callback != null) {
626 callback.run();
627 }
628 break;
629 }
Jeff Sharkey48877892015-03-18 11:27:19 -0700630 case H_SHUTDOWN: {
Sudheer Shanka2250d562016-11-07 15:41:02 -0800631 final IStorageShutdownObserver obs = (IStorageShutdownObserver) msg.obj;
Jeff Sharkey48877892015-03-18 11:27:19 -0700632 boolean success = false;
633 try {
Jeff Sharkey54402792017-09-15 16:05:19 -0600634 mVold.shutdown();
635 success = true;
Jeff Sharkeyace874b2017-09-07 15:27:33 -0600636 } catch (Exception e) {
637 Slog.wtf(TAG, e);
Jeff Sharkey48877892015-03-18 11:27:19 -0700638 }
639 if (obs != null) {
640 try {
641 obs.onShutDownComplete(success ? 0 : -1);
Jeff Sharkeyace874b2017-09-07 15:27:33 -0600642 } catch (Exception ignored) {
Jeff Sharkey48877892015-03-18 11:27:19 -0700643 }
644 }
645 break;
646 }
647 case H_VOLUME_MOUNT: {
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -0700648 final VolumeInfo vol = (VolumeInfo) msg.obj;
Jeff Sharkey2e606d72015-07-27 14:19:54 -0700649 if (isMountDisallowed(vol)) {
650 Slog.i(TAG, "Ignoring mount " + vol.getId() + " due to policy");
651 break;
652 }
Sudheer Shanka3f0645b2018-09-18 13:07:59 -0700653 mount(vol);
Jeff Sharkey48877892015-03-18 11:27:19 -0700654 break;
655 }
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700656 case H_VOLUME_UNMOUNT: {
657 final VolumeInfo vol = (VolumeInfo) msg.obj;
Sudheer Shanka3f0645b2018-09-18 13:07:59 -0700658 unmount(vol);
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700659 break;
660 }
Jeff Sharkey48877892015-03-18 11:27:19 -0700661 case H_VOLUME_BROADCAST: {
662 final StorageVolume userVol = (StorageVolume) msg.obj;
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700663 final String envState = userVol.getState();
664 Slog.d(TAG, "Volume " + userVol.getId() + " broadcasting " + envState + " to "
Jeff Sharkey48877892015-03-18 11:27:19 -0700665 + userVol.getOwner());
666
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700667 final String action = VolumeInfo.getBroadcastForEnvironment(envState);
Jeff Sharkey48877892015-03-18 11:27:19 -0700668 if (action != null) {
669 final Intent intent = new Intent(action,
670 Uri.fromFile(userVol.getPathFile()));
671 intent.putExtra(StorageVolume.EXTRA_STORAGE_VOLUME, userVol);
Jeff Sharkey082f83b2017-03-26 14:34:47 -0600672 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT
673 | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
Jeff Sharkey48877892015-03-18 11:27:19 -0700674 mContext.sendBroadcastAsUser(intent, userVol.getOwner());
675 }
676 break;
677 }
Jeff Sharkeyabc3e852015-08-03 14:41:13 -0700678 case H_INTERNAL_BROADCAST: {
679 // Internal broadcasts aimed at system components, not for
680 // third-party apps.
681 final Intent intent = (Intent) msg.obj;
682 mContext.sendBroadcastAsUser(intent, UserHandle.ALL,
683 android.Manifest.permission.WRITE_MEDIA_STORAGE);
Jeff Sharkey5a9bb742015-11-03 10:15:57 -0800684 break;
685 }
686 case H_PARTITION_FORGET: {
Jeff Sharkeydb4b6192017-10-24 11:08:50 -0600687 final VolumeRecord rec = (VolumeRecord) msg.obj;
688 forgetPartition(rec.partGuid, rec.fsUuid);
Jeff Sharkey5a9bb742015-11-03 10:15:57 -0800689 break;
690 }
691 case H_RESET: {
692 resetIfReadyAndConnected();
693 break;
Jeff Sharkeyabc3e852015-08-03 14:41:13 -0700694 }
Jin Qiana85b9912017-10-17 15:48:18 -0700695 case H_RUN_IDLE_MAINT: {
696 Slog.i(TAG, "Running idle maintenance");
697 runIdleMaint((Runnable)msg.obj);
698 break;
699 }
700 case H_ABORT_IDLE_MAINT: {
701 Slog.i(TAG, "Aborting idle maintenance");
702 abortIdleMaint((Runnable)msg.obj);
703 break;
704 }
705
Suchi Amalapurapuc42e29e2010-02-22 16:03:53 -0800706 }
707 }
Jeff Sharkey48877892015-03-18 11:27:19 -0700708 }
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700709
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700710 private final Handler mHandler;
Suchi Amalapurapuc42e29e2010-02-22 16:03:53 -0800711
Jeff Sharkeybcd262d2015-06-10 09:41:17 -0700712 private BroadcastReceiver mUserReceiver = new BroadcastReceiver() {
713 @Override
714 public void onReceive(Context context, Intent intent) {
715 final String action = intent.getAction();
716 final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700717 Preconditions.checkArgument(userId >= 0);
Jeff Sharkeybcd262d2015-06-10 09:41:17 -0700718
719 try {
720 if (Intent.ACTION_USER_ADDED.equals(action)) {
721 final UserManager um = mContext.getSystemService(UserManager.class);
722 final int userSerialNumber = um.getUserSerialNumber(userId);
Jeff Sharkey54402792017-09-15 16:05:19 -0600723 mVold.onUserAdded(userId, userSerialNumber);
Jeff Sharkeybcd262d2015-06-10 09:41:17 -0700724 } else if (Intent.ACTION_USER_REMOVED.equals(action)) {
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700725 synchronized (mVolumes) {
726 final int size = mVolumes.size();
727 for (int i = 0; i < size; i++) {
728 final VolumeInfo vol = mVolumes.valueAt(i);
729 if (vol.mountUserId == userId) {
730 vol.mountUserId = UserHandle.USER_NULL;
731 mHandler.obtainMessage(H_VOLUME_UNMOUNT, vol).sendToTarget();
732 }
733 }
734 }
Jeff Sharkey54402792017-09-15 16:05:19 -0600735 mVold.onUserRemoved(userId);
Jeff Sharkeybcd262d2015-06-10 09:41:17 -0700736 }
Jeff Sharkeyace874b2017-09-07 15:27:33 -0600737 } catch (Exception e) {
738 Slog.wtf(TAG, e);
Jeff Sharkeybcd262d2015-06-10 09:41:17 -0700739 }
740 }
741 };
742
Jeff Sharkeyedcdaf62015-07-09 09:45:36 -0700743 private void waitForLatch(CountDownLatch latch, String condition, long timeoutMillis)
744 throws TimeoutException {
745 final long startMillis = SystemClock.elapsedRealtime();
Jeff Sharkeyeba260d2015-04-19 14:35:16 -0700746 while (true) {
Kenny Root51a573c2012-05-17 13:30:28 -0700747 try {
748 if (latch.await(5000, TimeUnit.MILLISECONDS)) {
San Mehat207e5382010-02-04 20:46:54 -0800749 return;
Kenny Root51a573c2012-05-17 13:30:28 -0700750 } else {
751 Slog.w(TAG, "Thread " + Thread.currentThread().getName()
Jeff Sharkey48877892015-03-18 11:27:19 -0700752 + " still waiting for " + condition + "...");
San Mehat207e5382010-02-04 20:46:54 -0800753 }
Kenny Root51a573c2012-05-17 13:30:28 -0700754 } catch (InterruptedException e) {
Jeff Sharkeyeba260d2015-04-19 14:35:16 -0700755 Slog.w(TAG, "Interrupt while waiting for " + condition);
San Mehat207e5382010-02-04 20:46:54 -0800756 }
Jeff Sharkeyedcdaf62015-07-09 09:45:36 -0700757 if (timeoutMillis > 0 && SystemClock.elapsedRealtime() > startMillis + timeoutMillis) {
758 throw new TimeoutException("Thread " + Thread.currentThread().getName()
759 + " gave up waiting for " + condition + " after " + timeoutMillis + "ms");
760 }
San Mehat207e5382010-02-04 20:46:54 -0800761 }
San Mehat1f6301e2010-01-07 22:40:27 -0800762 }
Kenny Root02c87302010-07-01 08:10:18 -0700763
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700764 private void handleSystemReady() {
Jeff Sharkey8924e872015-11-30 12:52:10 -0700765 initIfReadyAndConnected();
Jeff Sharkey5a9bb742015-11-03 10:15:57 -0800766 resetIfReadyAndConnected();
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700767
Jeff Sharkey48877892015-03-18 11:27:19 -0700768 // Start scheduling nominally-daily fstrim operations
Christopher Tate115afda2014-06-06 19:06:26 -0700769 MountServiceIdler.scheduleIdlePass(mContext);
Daniel Colascione766b6322018-01-08 19:10:36 -0800770
771 // Toggle zram-enable system property in response to settings
772 mContext.getContentResolver().registerContentObserver(
773 Settings.Global.getUriFor(Settings.Global.ZRAM_ENABLED),
774 false /*notifyForDescendants*/,
775 new ContentObserver(null /* current thread */) {
776 @Override
777 public void onChange(boolean selfChange) {
778 refreshZramSettings();
779 }
780 });
781 refreshZramSettings();
Jeff Sharkeyb0c363b22018-12-15 11:53:03 -0700782
Srinivas Paladuguc8261752019-01-09 10:54:52 -0800783 // Schedule zram writeback unless zram is disabled by persist.sys.zram_enabled
784 String zramPropValue = SystemProperties.get(ZRAM_ENABLED_PROPERTY);
785 if (!zramPropValue.equals("0")
786 && mContext.getResources().getBoolean(
787 com.android.internal.R.bool.config_zramWriteback)) {
788 ZramWriteback.scheduleZramWriteback(mContext);
789 }
Jeff Sharkeyb0c363b22018-12-15 11:53:03 -0700790 // Toggle isolated-enable system property in response to settings
791 mContext.getContentResolver().registerContentObserver(
792 Settings.Global.getUriFor(Settings.Global.ISOLATED_STORAGE_REMOTE),
793 false /*notifyForDescendants*/,
794 new ContentObserver(null /* current thread */) {
795 @Override
796 public void onChange(boolean selfChange) {
797 refreshIsolatedStorageSettings();
798 }
799 });
800 refreshIsolatedStorageSettings();
Daniel Colascione766b6322018-01-08 19:10:36 -0800801 }
802
803 /**
804 * Update the zram_enabled system property (which init reads to
805 * decide whether to enable zram) to reflect the zram_enabled
806 * preference (which we can change for experimentation purposes).
807 */
808 private void refreshZramSettings() {
809 String propertyValue = SystemProperties.get(ZRAM_ENABLED_PROPERTY);
810 if ("".equals(propertyValue)) {
811 return; // System doesn't have zram toggling support
812 }
813 String desiredPropertyValue =
814 Settings.Global.getInt(mContext.getContentResolver(),
815 Settings.Global.ZRAM_ENABLED,
816 1) != 0
817 ? "1" : "0";
818 if (!desiredPropertyValue.equals(propertyValue)) {
819 // Avoid redundant disk writes by setting only if we're
820 // changing the property value. There's no race: we're the
821 // sole writer.
822 SystemProperties.set(ZRAM_ENABLED_PROPERTY, desiredPropertyValue);
Srinivas Paladuguc8261752019-01-09 10:54:52 -0800823 // Schedule writeback only if zram is being enabled.
824 if (desiredPropertyValue.equals("1")
825 && mContext.getResources().getBoolean(
826 com.android.internal.R.bool.config_zramWriteback)) {
827 ZramWriteback.scheduleZramWriteback(mContext);
828 }
Daniel Colascione766b6322018-01-08 19:10:36 -0800829 }
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700830 }
831
Jeff Sharkeyb0c363b22018-12-15 11:53:03 -0700832 private void refreshIsolatedStorageSettings() {
833 final int local = Settings.Global.getInt(mContext.getContentResolver(),
834 Settings.Global.ISOLATED_STORAGE_LOCAL, 0);
835 final int remote = Settings.Global.getInt(mContext.getContentResolver(),
836 Settings.Global.ISOLATED_STORAGE_REMOTE, 0);
837
838 // Walk down precedence chain; we prefer local settings first, then
839 // remote settings, before finally falling back to hard-coded default.
840 final boolean res;
841 if (local == -1) {
842 res = false;
843 } else if (local == 1) {
844 res = true;
845 } else if (remote == -1) {
846 res = false;
847 } else if (remote == 1) {
848 res = true;
849 } else {
850 res = false;
851 }
852
853 Slog.d(TAG, "Isolated storage local flag " + local + " and remote flag "
854 + remote + " resolved to " + res);
855 SystemProperties.set(StorageManager.PROP_ISOLATED_STORAGE, Boolean.toString(res));
856 }
857
Jeff Sharkey14cbe522015-07-08 14:06:37 -0700858 /**
859 * MediaProvider has a ton of code that makes assumptions about storage
860 * paths never changing, so we outright kill them to pick up new state.
861 */
862 @Deprecated
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700863 private void killMediaProvider(List<UserInfo> users) {
864 if (users == null) return;
865
Jeff Sharkeyb3cf9532015-07-17 15:12:39 -0700866 final long token = Binder.clearCallingIdentity();
867 try {
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700868 for (UserInfo user : users) {
869 // System user does not have media provider, so skip.
870 if (user.isSystemOnly()) continue;
871
Jeff Sharkey5790af02018-08-13 17:42:54 -0600872 final ProviderInfo provider = mPmInternal.resolveContentProvider(
873 MediaStore.AUTHORITY, PackageManager.MATCH_DIRECT_BOOT_AWARE
Jeff Sharkey8a372a02016-03-16 16:25:45 -0600874 | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
875 user.id);
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700876 if (provider != null) {
Sudheer Shankadc589ac2016-11-10 15:30:17 -0800877 final IActivityManager am = ActivityManager.getService();
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700878 try {
Jeff Sharkey85f449e2016-06-23 09:26:00 -0600879 am.killApplication(provider.applicationInfo.packageName,
880 UserHandle.getAppId(provider.applicationInfo.uid),
881 UserHandle.USER_ALL, "vold reset");
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700882 // We only need to run this once. It will kill all users' media processes.
883 break;
884 } catch (RemoteException e) {
885 }
Jeff Sharkeyb3cf9532015-07-17 15:12:39 -0700886 }
Jeff Sharkey14cbe522015-07-08 14:06:37 -0700887 }
Jeff Sharkeyb3cf9532015-07-17 15:12:39 -0700888 } finally {
889 Binder.restoreCallingIdentity(token);
Jeff Sharkey14cbe522015-07-08 14:06:37 -0700890 }
891 }
892
Andreas Gampea36dc622018-02-05 17:19:22 -0800893 @GuardedBy("mLock")
Jeff Sharkey5a9bb742015-11-03 10:15:57 -0800894 private void addInternalVolumeLocked() {
Amith Yamasania7892482015-08-07 11:09:05 -0700895 // Create a stub volume that represents internal storage
896 final VolumeInfo internal = new VolumeInfo(VolumeInfo.ID_PRIVATE_INTERNAL,
897 VolumeInfo.TYPE_PRIVATE, null, null);
898 internal.state = VolumeInfo.STATE_MOUNTED;
899 internal.path = Environment.getDataDirectory().getAbsolutePath();
900 mVolumes.put(internal.id, internal);
901 }
902
Jeff Sharkey8924e872015-11-30 12:52:10 -0700903 private void initIfReadyAndConnected() {
904 Slog.d(TAG, "Thinking about init, mSystemReady=" + mSystemReady
905 + ", mDaemonConnected=" + mDaemonConnected);
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700906 if (mSystemReady && mDaemonConnected
Paul Lawrence20be5d62016-02-26 13:51:17 -0800907 && !StorageManager.isFileEncryptedNativeOnly()) {
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700908 // When booting a device without native support, make sure that our
909 // user directories are locked or unlocked based on the current
910 // emulation status.
Paul Lawrence20be5d62016-02-26 13:51:17 -0800911 final boolean initLocked = StorageManager.isFileEncryptedEmulatedOnly();
Paul Crowleyd94ab732016-02-15 06:44:51 +0000912 Slog.d(TAG, "Setting up emulation state, initlocked=" + initLocked);
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700913 final List<UserInfo> users = mContext.getSystemService(UserManager.class).getUsers();
Jeff Sharkey8924e872015-11-30 12:52:10 -0700914 for (UserInfo user : users) {
915 try {
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700916 if (initLocked) {
Jeff Sharkey54402792017-09-15 16:05:19 -0600917 mVold.lockUserKey(user.id);
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700918 } else {
Jeff Sharkey54402792017-09-15 16:05:19 -0600919 mVold.unlockUserKey(user.id, user.serialNumber, encodeBytes(null),
920 encodeBytes(null));
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700921 }
Jeff Sharkey43e12112017-09-12 16:31:45 -0600922 } catch (Exception e) {
923 Slog.wtf(TAG, e);
Jeff Sharkey8924e872015-11-30 12:52:10 -0700924 }
925 }
926 }
927 }
928
Jeff Sharkey5a9bb742015-11-03 10:15:57 -0800929 private void resetIfReadyAndConnected() {
Jeff Sharkey48877892015-03-18 11:27:19 -0700930 Slog.d(TAG, "Thinking about reset, mSystemReady=" + mSystemReady
931 + ", mDaemonConnected=" + mDaemonConnected);
932 if (mSystemReady && mDaemonConnected) {
Jeff Sharkey5a9bb742015-11-03 10:15:57 -0800933 final List<UserInfo> users = mContext.getSystemService(UserManager.class).getUsers();
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700934 killMediaProvider(users);
Jeff Sharkey14cbe522015-07-08 14:06:37 -0700935
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700936 final int[] systemUnlockedUsers;
Jeff Sharkey5a9bb742015-11-03 10:15:57 -0800937 synchronized (mLock) {
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700938 systemUnlockedUsers = mSystemUnlockedUsers;
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700939
Jeff Sharkey5a9bb742015-11-03 10:15:57 -0800940 mDisks.clear();
941 mVolumes.clear();
942
943 addInternalVolumeLocked();
944 }
Jeff Sharkey59d577a2015-04-11 21:27:21 -0700945
Sudheer Shanka3f0645b2018-09-18 13:07:59 -0700946 mVisibleVols.clear();
947
Jeff Sharkey48877892015-03-18 11:27:19 -0700948 try {
Jeff Sharkey54402792017-09-15 16:05:19 -0600949 mVold.reset();
Jeff Sharkeybcd262d2015-06-10 09:41:17 -0700950
951 // Tell vold about all existing and started users
Jeff Sharkeybcd262d2015-06-10 09:41:17 -0700952 for (UserInfo user : users) {
Jeff Sharkey54402792017-09-15 16:05:19 -0600953 mVold.onUserAdded(user.id, user.serialNumber);
Jeff Sharkeybcd262d2015-06-10 09:41:17 -0700954 }
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700955 for (int userId : systemUnlockedUsers) {
Sudheer Shanka2ac25a92018-10-25 10:59:32 -0700956 sendUserStartedCallback(userId);
Jin Qian12690d52017-10-13 18:17:04 -0700957 mStoraged.onUserStarted(userId);
Jeff Sharkey50a05452015-04-29 11:24:52 -0700958 }
Jeff Sharkey9765e442017-12-14 22:15:14 -0700959 mVold.onSecureKeyguardStateChanged(mSecureKeyguardShowing);
Risanaec0ee72018-10-31 10:10:12 +0900960 mStorageManagerInternal.onReset(mVold);
Jeff Sharkeyace874b2017-09-07 15:27:33 -0600961 } catch (Exception e) {
962 Slog.wtf(TAG, e);
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700963 }
964 }
Jeff Sharkey48877892015-03-18 11:27:19 -0700965 }
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700966
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700967 private void onUnlockUser(int userId) {
968 Slog.d(TAG, "onUnlockUser " + userId);
Jeff Sharkey48877892015-03-18 11:27:19 -0700969
970 // We purposefully block here to make sure that user-specific
971 // staging area is ready so it's ready for zygote-forked apps to
972 // bind mount against.
973 try {
Sudheer Shanka2ac25a92018-10-25 10:59:32 -0700974 sendUserStartedCallback(userId);
Jin Qian12690d52017-10-13 18:17:04 -0700975 mStoraged.onUserStarted(userId);
Jeff Sharkeyace874b2017-09-07 15:27:33 -0600976 } catch (Exception e) {
977 Slog.wtf(TAG, e);
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700978 }
Jeff Sharkey48877892015-03-18 11:27:19 -0700979
980 // Record user as started so newly mounted volumes kick off events
981 // correctly, then synthesize events for any already-mounted volumes.
yuanhuihuiefd1f122016-07-13 21:21:03 +0800982 synchronized (mLock) {
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -0700983 for (int i = 0; i < mVolumes.size(); i++) {
984 final VolumeInfo vol = mVolumes.valueAt(i);
Jeff Sharkey46349872015-07-28 10:49:47 -0700985 if (vol.isVisibleForRead(userId) && vol.isMountedReadable()) {
Svet Ganov6ee871e2015-07-10 14:29:33 -0700986 final StorageVolume userVol = vol.buildStorageVolume(mContext, userId, false);
Jeff Sharkey48877892015-03-18 11:27:19 -0700987 mHandler.obtainMessage(H_VOLUME_BROADCAST, userVol).sendToTarget();
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700988
Jeff Sharkey27de30d2015-04-18 16:20:27 -0700989 final String envState = VolumeInfo.getEnvironmentForState(vol.getState());
990 mCallbacks.notifyStorageStateChanged(userVol.getPath(), envState, envState);
Jeff Sharkey48877892015-03-18 11:27:19 -0700991 }
992 }
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700993 mSystemUnlockedUsers = ArrayUtils.appendInt(mSystemUnlockedUsers, userId);
Jeff Sharkey48877892015-03-18 11:27:19 -0700994 }
995 }
996
997 private void onCleanupUser(int userId) {
998 Slog.d(TAG, "onCleanupUser " + userId);
999
1000 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06001001 mVold.onUserStopped(userId);
Jin Qian12690d52017-10-13 18:17:04 -07001002 mStoraged.onUserStopped(userId);
Jeff Sharkeyace874b2017-09-07 15:27:33 -06001003 } catch (Exception e) {
1004 Slog.wtf(TAG, e);
Jeff Sharkey48877892015-03-18 11:27:19 -07001005 }
1006
Sudheer Shanka2ac25a92018-10-25 10:59:32 -07001007 synchronized (mPackagesLock) {
1008 mPackages.delete(userId);
1009 }
1010
yuanhuihuiefd1f122016-07-13 21:21:03 +08001011 synchronized (mLock) {
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07001012 mSystemUnlockedUsers = ArrayUtils.removeInt(mSystemUnlockedUsers, userId);
Jeff Sharkey48877892015-03-18 11:27:19 -07001013 }
1014 }
Jeff Sharkeyb049e212012-09-07 23:16:01 -07001015
Sudheer Shanka2ac25a92018-10-25 10:59:32 -07001016 private void sendUserStartedCallback(int userId) throws Exception {
1017 if (!ENABLE_ISOLATED_STORAGE) {
1018 mVold.onUserStarted(userId, EmptyArray.STRING, EmptyArray.INT, EmptyArray.STRING);
1019 }
1020
1021 final String[] packages;
1022 final int[] appIds;
1023 final String[] sandboxIds;
1024 final SparseArray<String> sharedUserIds = mPmInternal.getAppsWithSharedUserIds();
1025 final List<ApplicationInfo> appInfos =
1026 mContext.getPackageManager().getInstalledApplicationsAsUser(
1027 PackageManager.MATCH_UNINSTALLED_PACKAGES, userId);
1028 synchronized (mPackagesLock) {
1029 final ArraySet<String> userPackages = new ArraySet<>();
1030 final ArrayMap<String, Integer> packageToAppId = new ArrayMap<>();
1031 for (int i = appInfos.size() - 1; i >= 0; --i) {
1032 final ApplicationInfo appInfo = appInfos.get(i);
1033 if (appInfo.isInstantApp()) {
1034 continue;
1035 }
1036 userPackages.add(appInfo.packageName);
1037 packageToAppId.put(appInfo.packageName, UserHandle.getAppId(appInfo.uid));
1038 }
1039 mPackages.put(userId, userPackages);
1040
1041 packages = new String[userPackages.size()];
1042 appIds = new int[userPackages.size()];
1043 sandboxIds = new String[userPackages.size()];
1044 for (int i = userPackages.size() - 1; i >= 0; --i) {
1045 packages[i] = userPackages.valueAt(i);
1046 appIds[i] = packageToAppId.get(packages[i]);
1047 sandboxIds[i] = getSandboxId(packages[i], sharedUserIds.get(appIds[i]));
1048 }
1049 }
1050 mVold.onUserStarted(userId, packages, appIds, sandboxIds);
1051 }
1052
Jeff Sharkey9765e442017-12-14 22:15:14 -07001053 @Override
1054 public void onAwakeStateChanged(boolean isAwake) {
1055 // Ignored
1056 }
1057
1058 @Override
1059 public void onKeyguardStateChanged(boolean isShowing) {
1060 // Push down current secure keyguard status so that we ignore malicious
1061 // USB devices while locked.
1062 mSecureKeyguardShowing = isShowing
1063 && mContext.getSystemService(KeyguardManager.class).isDeviceSecure();
1064 try {
1065 mVold.onSecureKeyguardStateChanged(mSecureKeyguardShowing);
1066 } catch (Exception e) {
1067 Slog.wtf(TAG, e);
1068 }
1069 }
1070
Christopher Tated417d622013-08-19 16:14:25 -07001071 void runIdleMaintenance(Runnable callback) {
1072 mHandler.sendMessage(mHandler.obtainMessage(H_FSTRIM, callback));
1073 }
1074
Christopher Tate7265abe2014-11-21 13:54:45 -08001075 // Binder entry point for kicking off an immediate fstrim
1076 @Override
1077 public void runMaintenance() {
Jeff Sharkey48877892015-03-18 11:27:19 -07001078 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
Christopher Tate7265abe2014-11-21 13:54:45 -08001079 runIdleMaintenance(null);
1080 }
1081
1082 @Override
1083 public long lastMaintenance() {
1084 return mLastMaintenance;
1085 }
1086
San Mehat4270e1e2010-01-29 05:32:19 -08001087 public void onDaemonConnected() {
Jeff Sharkey48877892015-03-18 11:27:19 -07001088 mDaemonConnected = true;
1089 mHandler.obtainMessage(H_DAEMON_CONNECTED).sendToTarget();
1090 }
1091
1092 private void handleDaemonConnected() {
Jeff Sharkey8924e872015-11-30 12:52:10 -07001093 initIfReadyAndConnected();
Jeff Sharkey5a9bb742015-11-03 10:15:57 -08001094 resetIfReadyAndConnected();
Jeff Sharkey48877892015-03-18 11:27:19 -07001095
Jeff Sharkey48877892015-03-18 11:27:19 -07001096 // On an encrypted device we can't see system properties yet, so pull
1097 // the system locale out of the mount service.
Inseob Kimc1246e62018-11-08 13:13:54 +09001098 if ("".equals(VoldProperties.encrypt_progress().orElse(""))) {
Jeff Sharkey48877892015-03-18 11:27:19 -07001099 copyLocaleFromMountService();
1100 }
San Mehat4270e1e2010-01-29 05:32:19 -08001101 }
1102
Elliott Hughesf839b4f2014-09-26 12:30:47 -07001103 private void copyLocaleFromMountService() {
1104 String systemLocale;
1105 try {
1106 systemLocale = getField(StorageManager.SYSTEM_LOCALE_KEY);
1107 } catch (RemoteException e) {
1108 return;
1109 }
1110 if (TextUtils.isEmpty(systemLocale)) {
1111 return;
1112 }
1113
1114 Slog.d(TAG, "Got locale " + systemLocale + " from mount service");
1115 Locale locale = Locale.forLanguageTag(systemLocale);
1116 Configuration config = new Configuration();
1117 config.setLocale(locale);
1118 try {
Sudheer Shankadc589ac2016-11-10 15:30:17 -08001119 ActivityManager.getService().updatePersistentConfiguration(config);
Elliott Hughesf839b4f2014-09-26 12:30:47 -07001120 } catch (RemoteException e) {
1121 Slog.e(TAG, "Error setting system locale from mount service", e);
1122 }
Elliott Hughes9c33f282014-10-13 12:39:56 -07001123
1124 // Temporary workaround for http://b/17945169.
1125 Slog.d(TAG, "Setting system properties to " + systemLocale + " from mount service");
Narayan Kamathd30dbb82015-01-15 14:48:15 +00001126 SystemProperties.set("persist.sys.locale", locale.toLanguageTag());
Elliott Hughesf839b4f2014-09-26 12:30:47 -07001127 }
1128
Jeff Sharkey8058fe62017-09-13 11:50:33 -06001129 private final IVoldListener mListener = new IVoldListener.Stub() {
1130 @Override
1131 public void onDiskCreated(String diskId, int flags) {
1132 synchronized (mLock) {
Jeff Sharkey901c0422018-04-20 13:11:20 -06001133 final String value = SystemProperties.get(StorageManager.PROP_ADOPTABLE);
1134 switch (value) {
1135 case "force_on":
1136 flags |= DiskInfo.FLAG_ADOPTABLE;
1137 break;
1138 case "force_off":
1139 flags &= ~DiskInfo.FLAG_ADOPTABLE;
1140 break;
Jeff Sharkey8058fe62017-09-13 11:50:33 -06001141 }
Jeff Sharkey8058fe62017-09-13 11:50:33 -06001142 mDisks.put(diskId, new DiskInfo(diskId, flags));
1143 }
1144 }
1145
1146 @Override
1147 public void onDiskScanned(String diskId) {
1148 synchronized (mLock) {
1149 final DiskInfo disk = mDisks.get(diskId);
1150 if (disk != null) {
1151 onDiskScannedLocked(disk);
1152 }
1153 }
1154 }
1155
1156 @Override
1157 public void onDiskMetadataChanged(String diskId, long sizeBytes, String label,
1158 String sysPath) {
1159 synchronized (mLock) {
1160 final DiskInfo disk = mDisks.get(diskId);
1161 if (disk != null) {
1162 disk.size = sizeBytes;
1163 disk.label = label;
1164 disk.sysPath = sysPath;
1165 }
1166 }
1167 }
1168
1169 @Override
1170 public void onDiskDestroyed(String diskId) {
1171 synchronized (mLock) {
1172 final DiskInfo disk = mDisks.remove(diskId);
1173 if (disk != null) {
1174 mCallbacks.notifyDiskDestroyed(disk);
1175 }
1176 }
1177 }
1178
1179 @Override
1180 public void onVolumeCreated(String volId, int type, String diskId, String partGuid) {
1181 synchronized (mLock) {
1182 final DiskInfo disk = mDisks.get(diskId);
1183 final VolumeInfo vol = new VolumeInfo(volId, type, disk, partGuid);
1184 mVolumes.put(volId, vol);
1185 onVolumeCreatedLocked(vol);
1186 }
1187 }
1188
1189 @Override
1190 public void onVolumeStateChanged(String volId, int state) {
1191 synchronized (mLock) {
1192 final VolumeInfo vol = mVolumes.get(volId);
1193 if (vol != null) {
1194 final int oldState = vol.state;
1195 final int newState = state;
1196 vol.state = newState;
1197 onVolumeStateChangedLocked(vol, oldState, newState);
1198 }
1199 }
1200 }
1201
1202 @Override
1203 public void onVolumeMetadataChanged(String volId, String fsType, String fsUuid,
1204 String fsLabel) {
1205 synchronized (mLock) {
1206 final VolumeInfo vol = mVolumes.get(volId);
1207 if (vol != null) {
1208 vol.fsType = fsType;
1209 vol.fsUuid = fsUuid;
1210 vol.fsLabel = fsLabel;
1211 }
1212 }
1213 }
1214
1215 @Override
1216 public void onVolumePathChanged(String volId, String path) {
1217 synchronized (mLock) {
1218 final VolumeInfo vol = mVolumes.get(volId);
1219 if (vol != null) {
1220 vol.path = path;
1221 }
1222 }
1223 }
1224
1225 @Override
1226 public void onVolumeInternalPathChanged(String volId, String internalPath) {
1227 synchronized (mLock) {
1228 final VolumeInfo vol = mVolumes.get(volId);
1229 if (vol != null) {
1230 vol.internalPath = internalPath;
1231 }
1232 }
1233 }
1234
1235 @Override
1236 public void onVolumeDestroyed(String volId) {
1237 synchronized (mLock) {
1238 mVolumes.remove(volId);
1239 }
1240 }
1241 };
1242
Andreas Gampea36dc622018-02-05 17:19:22 -08001243 @GuardedBy("mLock")
Jeff Sharkeyeba260d2015-04-19 14:35:16 -07001244 private void onDiskScannedLocked(DiskInfo disk) {
Jeff Sharkey620b32b2015-04-23 19:36:02 -07001245 int volumeCount = 0;
Jeff Sharkeyeba260d2015-04-19 14:35:16 -07001246 for (int i = 0; i < mVolumes.size(); i++) {
1247 final VolumeInfo vol = mVolumes.valueAt(i);
1248 if (Objects.equals(disk.id, vol.getDiskId())) {
Jeff Sharkey620b32b2015-04-23 19:36:02 -07001249 volumeCount++;
Jeff Sharkeyeba260d2015-04-19 14:35:16 -07001250 }
1251 }
1252
Jeff Sharkeyc7acac62015-06-12 16:16:56 -07001253 final Intent intent = new Intent(DiskInfo.ACTION_DISK_SCANNED);
Jeff Sharkey7732e1e2016-03-30 17:14:23 -06001254 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT
1255 | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
Jeff Sharkeyc7acac62015-06-12 16:16:56 -07001256 intent.putExtra(DiskInfo.EXTRA_DISK_ID, disk.id);
1257 intent.putExtra(DiskInfo.EXTRA_VOLUME_COUNT, volumeCount);
Jeff Sharkeyabc3e852015-08-03 14:41:13 -07001258 mHandler.obtainMessage(H_INTERNAL_BROADCAST, intent).sendToTarget();
Jeff Sharkeyc7acac62015-06-12 16:16:56 -07001259
1260 final CountDownLatch latch = mDiskScanLatches.remove(disk.id);
1261 if (latch != null) {
1262 latch.countDown();
1263 }
1264
Jeff Sharkeyf5a6bd72015-05-19 14:42:38 -07001265 disk.volumeCount = volumeCount;
Jeff Sharkey620b32b2015-04-23 19:36:02 -07001266 mCallbacks.notifyDiskScanned(disk, volumeCount);
Jeff Sharkeyeba260d2015-04-19 14:35:16 -07001267 }
1268
Andreas Gampea36dc622018-02-05 17:19:22 -08001269 @GuardedBy("mLock")
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07001270 private void onVolumeCreatedLocked(VolumeInfo vol) {
Jeff Sharkey5790af02018-08-13 17:42:54 -06001271 if (mPmInternal.isOnlyCoreApps()) {
Jeff Sharkey6855c482016-03-31 14:34:38 -06001272 Slog.d(TAG, "System booted in core-only mode; ignoring volume " + vol.getId());
1273 return;
1274 }
1275
Jeff Sharkey275e3e42015-04-24 16:10:32 -07001276 if (vol.type == VolumeInfo.TYPE_EMULATED) {
1277 final StorageManager storage = mContext.getSystemService(StorageManager.class);
1278 final VolumeInfo privateVol = storage.findPrivateForEmulated(vol);
1279
1280 if (Objects.equals(StorageManager.UUID_PRIVATE_INTERNAL, mPrimaryStorageUuid)
1281 && VolumeInfo.ID_PRIVATE_INTERNAL.equals(privateVol.id)) {
1282 Slog.v(TAG, "Found primary storage at " + vol);
1283 vol.mountFlags |= VolumeInfo.MOUNT_FLAG_PRIMARY;
1284 vol.mountFlags |= VolumeInfo.MOUNT_FLAG_VISIBLE;
1285 mHandler.obtainMessage(H_VOLUME_MOUNT, vol).sendToTarget();
1286
1287 } else if (Objects.equals(privateVol.fsUuid, mPrimaryStorageUuid)) {
1288 Slog.v(TAG, "Found primary storage at " + vol);
1289 vol.mountFlags |= VolumeInfo.MOUNT_FLAG_PRIMARY;
1290 vol.mountFlags |= VolumeInfo.MOUNT_FLAG_VISIBLE;
1291 mHandler.obtainMessage(H_VOLUME_MOUNT, vol).sendToTarget();
1292 }
Jeff Sharkeyb049e212012-09-07 23:16:01 -07001293
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07001294 } else if (vol.type == VolumeInfo.TYPE_PUBLIC) {
Jeff Sharkey275e3e42015-04-24 16:10:32 -07001295 // TODO: only look at first public partition
1296 if (Objects.equals(StorageManager.UUID_PRIMARY_PHYSICAL, mPrimaryStorageUuid)
1297 && vol.disk.isDefaultPrimary()) {
1298 Slog.v(TAG, "Found primary storage at " + vol);
Jeff Sharkey7e92ef32015-04-17 17:35:07 -07001299 vol.mountFlags |= VolumeInfo.MOUNT_FLAG_PRIMARY;
1300 vol.mountFlags |= VolumeInfo.MOUNT_FLAG_VISIBLE;
San Mehat4270e1e2010-01-29 05:32:19 -08001301 }
Jeff Sharkey7e92ef32015-04-17 17:35:07 -07001302
1303 // Adoptable public disks are visible to apps, since they meet
1304 // public API requirement of being in a stable location.
Jeff Sharkey275e3e42015-04-24 16:10:32 -07001305 if (vol.disk.isAdoptable()) {
Jeff Sharkey7e92ef32015-04-17 17:35:07 -07001306 vol.mountFlags |= VolumeInfo.MOUNT_FLAG_VISIBLE;
1307 }
1308
Jeff Sharkeyab15c392016-05-05 11:45:01 -06001309 vol.mountUserId = mCurrentUserId;
Jeff Sharkey48877892015-03-18 11:27:19 -07001310 mHandler.obtainMessage(H_VOLUME_MOUNT, vol).sendToTarget();
San Mehat4270e1e2010-01-29 05:32:19 -08001311
Jeff Sharkeyb2b9ab82015-04-05 21:10:42 -07001312 } else if (vol.type == VolumeInfo.TYPE_PRIVATE) {
1313 mHandler.obtainMessage(H_VOLUME_MOUNT, vol).sendToTarget();
1314
Risan05c41e62018-10-29 08:57:43 +09001315 } else if (vol.type == VolumeInfo.TYPE_STUB) {
1316 vol.mountUserId = mCurrentUserId;
1317 mHandler.obtainMessage(H_VOLUME_MOUNT, vol).sendToTarget();
San Mehat4270e1e2010-01-29 05:32:19 -08001318 } else {
Jeff Sharkey48877892015-03-18 11:27:19 -07001319 Slog.d(TAG, "Skipping automatic mounting of " + vol);
San Mehat4270e1e2010-01-29 05:32:19 -08001320 }
1321 }
1322
Jeff Sharkeye6c04f92015-04-18 21:38:05 -07001323 private boolean isBroadcastWorthy(VolumeInfo vol) {
1324 switch (vol.getType()) {
Jeff Sharkeyc7acac62015-06-12 16:16:56 -07001325 case VolumeInfo.TYPE_PRIVATE:
Jeff Sharkeye6c04f92015-04-18 21:38:05 -07001326 case VolumeInfo.TYPE_PUBLIC:
1327 case VolumeInfo.TYPE_EMULATED:
Risan05c41e62018-10-29 08:57:43 +09001328 case VolumeInfo.TYPE_STUB:
Jeff Sharkeye6c04f92015-04-18 21:38:05 -07001329 break;
1330 default:
1331 return false;
1332 }
1333
1334 switch (vol.getState()) {
1335 case VolumeInfo.STATE_MOUNTED:
1336 case VolumeInfo.STATE_MOUNTED_READ_ONLY:
1337 case VolumeInfo.STATE_EJECTING:
1338 case VolumeInfo.STATE_UNMOUNTED:
Jeff Sharkeyc7acac62015-06-12 16:16:56 -07001339 case VolumeInfo.STATE_UNMOUNTABLE:
Tony Mantlerf0d71052015-06-24 11:45:25 -07001340 case VolumeInfo.STATE_BAD_REMOVAL:
Jeff Sharkeye6c04f92015-04-18 21:38:05 -07001341 break;
1342 default:
1343 return false;
1344 }
1345
1346 return true;
1347 }
1348
Andreas Gampea36dc622018-02-05 17:19:22 -08001349 @GuardedBy("mLock")
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07001350 private void onVolumeStateChangedLocked(VolumeInfo vol, int oldState, int newState) {
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001351 // Remember that we saw this volume so we're ready to accept user
1352 // metadata, or so we can annoy them when a private volume is ejected
1353 if (vol.isMountedReadable() && !TextUtils.isEmpty(vol.fsUuid)) {
Jeff Sharkey5cc0df22015-06-17 19:44:05 -07001354 VolumeRecord rec = mRecords.get(vol.fsUuid);
1355 if (rec == null) {
1356 rec = new VolumeRecord(vol.type, vol.fsUuid);
1357 rec.partGuid = vol.partGuid;
Jeff Sharkeye8a4b662015-06-27 15:43:45 -07001358 rec.createdMillis = System.currentTimeMillis();
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001359 if (vol.type == VolumeInfo.TYPE_PRIVATE) {
1360 rec.nickname = vol.disk.getDescription();
1361 }
1362 mRecords.put(rec.fsUuid, rec);
1363 writeSettingsLocked();
Jeff Sharkey5cc0df22015-06-17 19:44:05 -07001364 } else {
1365 // Handle upgrade case where we didn't store partition GUID
1366 if (TextUtils.isEmpty(rec.partGuid)) {
1367 rec.partGuid = vol.partGuid;
1368 writeSettingsLocked();
1369 }
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001370 }
1371 }
1372
Jeff Sharkeye6c04f92015-04-18 21:38:05 -07001373 mCallbacks.notifyVolumeStateChanged(vol, oldState, newState);
1374
Yasuhiro Matsuda87a38b52015-07-24 22:10:16 +09001375 // Do not broadcast before boot has completed to avoid launching the
1376 // processes that receive the intent unnecessarily.
1377 if (mBootCompleted && isBroadcastWorthy(vol)) {
Jeff Sharkeye6c04f92015-04-18 21:38:05 -07001378 final Intent intent = new Intent(VolumeInfo.ACTION_VOLUME_STATE_CHANGED);
Jeff Sharkeyc7acac62015-06-12 16:16:56 -07001379 intent.putExtra(VolumeInfo.EXTRA_VOLUME_ID, vol.id);
1380 intent.putExtra(VolumeInfo.EXTRA_VOLUME_STATE, newState);
Tony Mantlerf0d71052015-06-24 11:45:25 -07001381 intent.putExtra(VolumeRecord.EXTRA_FS_UUID, vol.fsUuid);
Jeff Sharkey7732e1e2016-03-30 17:14:23 -06001382 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT
1383 | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
Jeff Sharkeyabc3e852015-08-03 14:41:13 -07001384 mHandler.obtainMessage(H_INTERNAL_BROADCAST, intent).sendToTarget();
Jeff Sharkeye6c04f92015-04-18 21:38:05 -07001385 }
Jeff Sharkeyb049e212012-09-07 23:16:01 -07001386
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001387 final String oldStateEnv = VolumeInfo.getEnvironmentForState(oldState);
1388 final String newStateEnv = VolumeInfo.getEnvironmentForState(newState);
Emily Bernier92aa5a22014-07-07 10:11:48 -04001389
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001390 if (!Objects.equals(oldStateEnv, newStateEnv)) {
1391 // Kick state changed event towards all started users. Any users
1392 // started after this point will trigger additional
1393 // user-specific broadcasts.
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07001394 for (int userId : mSystemUnlockedUsers) {
Jeff Sharkey46349872015-07-28 10:49:47 -07001395 if (vol.isVisibleForRead(userId)) {
Svet Ganov6ee871e2015-07-10 14:29:33 -07001396 final StorageVolume userVol = vol.buildStorageVolume(mContext, userId, false);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001397 mHandler.obtainMessage(H_VOLUME_BROADCAST, userVol).sendToTarget();
Jeff Sharkey48877892015-03-18 11:27:19 -07001398
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001399 mCallbacks.notifyStorageStateChanged(userVol.getPath(), oldStateEnv,
1400 newStateEnv);
San Mehat4270e1e2010-01-29 05:32:19 -08001401 }
1402 }
1403 }
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001404
Risan05c41e62018-10-29 08:57:43 +09001405 if ((vol.type == VolumeInfo.TYPE_PUBLIC || vol.type == VolumeInfo.TYPE_STUB)
1406 && vol.state == VolumeInfo.STATE_EJECTING) {
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001407 // TODO: this should eventually be handled by new ObbVolume state changes
1408 /*
1409 * Some OBBs might have been unmounted when this volume was
1410 * unmounted, so send a message to the handler to let it know to
1411 * remove those from the list of mounted OBBS.
1412 */
1413 mObbActionHandler.sendMessage(mObbActionHandler.obtainMessage(
1414 OBB_FLUSH_MOUNT_STATE, vol.path));
1415 }
Pavel Grafovce72ef02018-01-10 17:14:11 +00001416 maybeLogMediaMount(vol, newState);
1417 }
1418
1419 private void maybeLogMediaMount(VolumeInfo vol, int newState) {
1420 if (!SecurityLog.isLoggingEnabled()) {
1421 return;
1422 }
1423
1424 final DiskInfo disk = vol.getDisk();
1425 if (disk == null || (disk.flags & (DiskInfo.FLAG_SD | DiskInfo.FLAG_USB)) == 0) {
1426 return;
1427 }
1428
1429 // Sometimes there is a newline character.
1430 final String label = disk.label != null ? disk.label.trim() : "";
1431
1432 if (newState == VolumeInfo.STATE_MOUNTED
1433 || newState == VolumeInfo.STATE_MOUNTED_READ_ONLY) {
1434 SecurityLog.writeEvent(SecurityLog.TAG_MEDIA_MOUNT, vol.path, label);
1435 } else if (newState == VolumeInfo.STATE_UNMOUNTED
1436 || newState == VolumeInfo.STATE_BAD_REMOVAL) {
1437 SecurityLog.writeEvent(SecurityLog.TAG_MEDIA_UNMOUNT, vol.path, label);
1438 }
San Mehat4270e1e2010-01-29 05:32:19 -08001439 }
1440
Andreas Gampea36dc622018-02-05 17:19:22 -08001441 @GuardedBy("mLock")
Jeff Sharkey275e3e42015-04-24 16:10:32 -07001442 private void onMoveStatusLocked(int status) {
1443 if (mMoveCallback == null) {
1444 Slog.w(TAG, "Odd, status but no move requested");
1445 return;
1446 }
1447
1448 // TODO: estimate remaining time
1449 try {
Jeff Sharkey50a05452015-04-29 11:24:52 -07001450 mMoveCallback.onStatusChanged(-1, status, -1);
Jeff Sharkey275e3e42015-04-24 16:10:32 -07001451 } catch (RemoteException ignored) {
1452 }
1453
1454 // We've finished copying and we're about to clean up old data, so
1455 // remember that move was successful if we get rebooted
1456 if (status == MOVE_STATUS_COPY_FINISHED) {
1457 Slog.d(TAG, "Move to " + mMoveTargetUuid + " copy phase finshed; persisting");
1458
1459 mPrimaryStorageUuid = mMoveTargetUuid;
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001460 writeSettingsLocked();
Jeff Sharkey275e3e42015-04-24 16:10:32 -07001461 }
1462
1463 if (PackageManager.isMoveStatusFinished(status)) {
1464 Slog.d(TAG, "Move to " + mMoveTargetUuid + " finished with status " + status);
1465
1466 mMoveCallback = null;
1467 mMoveTargetUuid = null;
1468 }
1469 }
1470
Jeff Sharkey48877892015-03-18 11:27:19 -07001471 private void enforcePermission(String perm) {
1472 mContext.enforceCallingOrSelfPermission(perm, perm);
Mike Lockwooda5250c92011-05-23 13:44:04 -04001473 }
1474
Jeff Sharkey2e606d72015-07-27 14:19:54 -07001475 /**
1476 * Decide if volume is mountable per device policies.
1477 */
1478 private boolean isMountDisallowed(VolumeInfo vol) {
Philip P. Moltmannec3cbb22016-09-14 13:24:52 -07001479 UserManager userManager = mContext.getSystemService(UserManager.class);
1480
1481 boolean isUsbRestricted = false;
1482 if (vol.disk != null && vol.disk.isUsb()) {
1483 isUsbRestricted = userManager.hasUserRestriction(UserManager.DISALLOW_USB_FILE_TRANSFER,
Jeff Sharkey2e606d72015-07-27 14:19:54 -07001484 Binder.getCallingUserHandle());
Emily Bernier92aa5a22014-07-07 10:11:48 -04001485 }
Philip P. Moltmannec3cbb22016-09-14 13:24:52 -07001486
1487 boolean isTypeRestricted = false;
Risan05c41e62018-10-29 08:57:43 +09001488 if (vol.type == VolumeInfo.TYPE_PUBLIC || vol.type == VolumeInfo.TYPE_PRIVATE
1489 || vol.type == VolumeInfo.TYPE_STUB) {
Philip P. Moltmannec3cbb22016-09-14 13:24:52 -07001490 isTypeRestricted = userManager
1491 .hasUserRestriction(UserManager.DISALLOW_MOUNT_PHYSICAL_MEDIA,
1492 Binder.getCallingUserHandle());
1493 }
1494
1495 return isUsbRestricted || isTypeRestricted;
Emily Bernier92aa5a22014-07-07 10:11:48 -04001496 }
1497
Amith Yamasani462ac3a2015-06-30 14:21:01 -07001498 private void enforceAdminUser() {
1499 UserManager um = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
1500 final int callingUserId = UserHandle.getCallingUserId();
1501 boolean isAdmin;
1502 long token = Binder.clearCallingIdentity();
1503 try {
1504 isAdmin = um.getUserInfo(callingUserId).isAdmin();
1505 } finally {
1506 Binder.restoreCallingIdentity(token);
1507 }
1508 if (!isAdmin) {
1509 throw new SecurityException("Only admin users can adopt sd cards");
1510 }
1511 }
1512
Jeff Sharkeyb049e212012-09-07 23:16:01 -07001513 /**
Sudheer Shanka2250d562016-11-07 15:41:02 -08001514 * Constructs a new StorageManagerService instance
San Mehat207e5382010-02-04 20:46:54 -08001515 *
1516 * @param context Binder context for this service
1517 */
Sudheer Shanka2250d562016-11-07 15:41:02 -08001518 public StorageManagerService(Context context) {
Christopher Tated417d622013-08-19 16:14:25 -07001519 sSelf = this;
1520
Jeff Sharkey342b4bf2018-12-18 11:12:40 -07001521 // Snapshot feature flag used for this boot
1522 SystemProperties.set(StorageManager.PROP_ISOLATED_STORAGE_SNAPSHOT, Boolean.toString(
1523 SystemProperties.getBoolean(StorageManager.PROP_ISOLATED_STORAGE, false)));
1524
San Mehat207e5382010-02-04 20:46:54 -08001525 mContext = context;
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001526 mCallbacks = new Callbacks(FgThread.get().getLooper());
Jeff Sharkeyb9fe5372015-12-03 15:23:08 -07001527 mLockPatternUtils = new LockPatternUtils(mContext);
San Mehat207e5382010-02-04 20:46:54 -08001528
Sudheer Shanka0a541a52018-07-31 13:21:11 -07001529 mPmInternal = LocalServices.getService(PackageManagerInternal.class);
Jeff Sharkey5790af02018-08-13 17:42:54 -06001530 mUmInternal = LocalServices.getService(UserManagerInternal.class);
Sudheer Shanka87915d62018-11-06 10:57:35 -08001531 mAmInternal = LocalServices.getService(ActivityManagerInternal.class);
San Mehat207e5382010-02-04 20:46:54 -08001532
Dianne Hackbornefa92b22013-05-03 14:11:43 -07001533 HandlerThread hthread = new HandlerThread(TAG);
1534 hthread.start();
Sudheer Shanka2250d562016-11-07 15:41:02 -08001535 mHandler = new StorageManagerServiceHandler(hthread.getLooper());
Daniel Sandler5f27ef42010-03-16 15:42:02 -04001536
Sudheer Shanka2250d562016-11-07 15:41:02 -08001537 // Add OBB Action Handler to StorageManagerService thread.
Dianne Hackborn8d044e82013-04-30 17:24:15 -07001538 mObbActionHandler = new ObbActionHandler(IoThread.get().getLooper());
Kenny Roota02b8b02010-08-05 16:14:17 -07001539
Christopher Tate7265abe2014-11-21 13:54:45 -08001540 // Initialize the last-fstrim tracking if necessary
1541 File dataDir = Environment.getDataDirectory();
1542 File systemDir = new File(dataDir, "system");
1543 mLastMaintenanceFile = new File(systemDir, LAST_FSTRIM_FILE);
1544 if (!mLastMaintenanceFile.exists()) {
1545 // Not setting mLastMaintenance here means that we will force an
1546 // fstrim during reboot following the OTA that installs this code.
1547 try {
1548 (new FileOutputStream(mLastMaintenanceFile)).close();
1549 } catch (IOException e) {
1550 Slog.e(TAG, "Unable to create fstrim record " + mLastMaintenanceFile.getPath());
1551 }
1552 } else {
1553 mLastMaintenance = mLastMaintenanceFile.lastModified();
1554 }
1555
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001556 mSettingsFile = new AtomicFile(
Dianne Hackborne17b4452018-01-10 13:15:40 -08001557 new File(Environment.getDataSystemDirectory(), "storage.xml"), "storage-settings");
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001558
1559 synchronized (mLock) {
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001560 readSettingsLocked();
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001561 }
1562
Sudheer Shanka2250d562016-11-07 15:41:02 -08001563 LocalServices.addService(StorageManagerInternal.class, mStorageManagerInternal);
Svet Ganov6ee871e2015-07-10 14:29:33 -07001564
Jeff Sharkeybcd262d2015-06-10 09:41:17 -07001565 final IntentFilter userFilter = new IntentFilter();
1566 userFilter.addAction(Intent.ACTION_USER_ADDED);
1567 userFilter.addAction(Intent.ACTION_USER_REMOVED);
1568 mContext.registerReceiver(mUserReceiver, userFilter, null, mHandler);
1569
Jeff Sharkey5a9bb742015-11-03 10:15:57 -08001570 synchronized (mLock) {
1571 addInternalVolumeLocked();
1572 }
Amith Yamasania7892482015-08-07 11:09:05 -07001573
Kenny Root07714d42011-08-17 17:49:28 -07001574 // Add ourself to the Watchdog monitors if enabled.
1575 if (WATCHDOG_ENABLE) {
1576 Watchdog.getInstance().addMonitor(this);
1577 }
San Mehat207e5382010-02-04 20:46:54 -08001578 }
1579
Jeff Sharkeycd575992016-03-29 14:12:49 -06001580 private void start() {
Jeff Sharkey1019de92017-09-06 13:47:03 -06001581 connect();
Jeff Sharkeycd575992016-03-29 14:12:49 -06001582 }
1583
Sudheer Shanka0a541a52018-07-31 13:21:11 -07001584 private static String getSandboxId(String packageName, String sharedUserId) {
Sudheer Shankad68bd602018-11-13 17:43:39 -08001585 return sharedUserId == null
1586 ? packageName : StorageManager.SHARED_SANDBOX_PREFIX + sharedUserId;
Sudheer Shanka0a541a52018-07-31 13:21:11 -07001587 }
Sudheer Shanka0a541a52018-07-31 13:21:11 -07001588
Jeff Sharkey1019de92017-09-06 13:47:03 -06001589 private void connect() {
Jin Qian12690d52017-10-13 18:17:04 -07001590 IBinder binder = ServiceManager.getService("storaged");
1591 if (binder != null) {
1592 try {
1593 binder.linkToDeath(new DeathRecipient() {
1594 @Override
1595 public void binderDied() {
1596 Slog.w(TAG, "storaged died; reconnecting");
1597 mStoraged = null;
1598 connect();
1599 }
1600 }, 0);
1601 } catch (RemoteException e) {
1602 binder = null;
1603 }
1604 }
1605
1606 if (binder != null) {
1607 mStoraged = IStoraged.Stub.asInterface(binder);
1608 } else {
1609 Slog.w(TAG, "storaged not found; trying again");
1610 }
1611
1612 binder = ServiceManager.getService("vold");
Jeff Sharkey1019de92017-09-06 13:47:03 -06001613 if (binder != null) {
1614 try {
1615 binder.linkToDeath(new DeathRecipient() {
1616 @Override
1617 public void binderDied() {
1618 Slog.w(TAG, "vold died; reconnecting");
Jin Qian12690d52017-10-13 18:17:04 -07001619 mVold = null;
Jeff Sharkey1019de92017-09-06 13:47:03 -06001620 connect();
1621 }
1622 }, 0);
1623 } catch (RemoteException e) {
1624 binder = null;
1625 }
1626 }
1627
1628 if (binder != null) {
1629 mVold = IVold.Stub.asInterface(binder);
Jeff Sharkey8058fe62017-09-13 11:50:33 -06001630 try {
1631 mVold.setListener(mListener);
Jeff Sharkey8058fe62017-09-13 11:50:33 -06001632 } catch (RemoteException e) {
Jin Qian12690d52017-10-13 18:17:04 -07001633 mVold = null;
Jeff Sharkey8058fe62017-09-13 11:50:33 -06001634 Slog.w(TAG, "vold listener rejected; trying again", e);
1635 }
Jeff Sharkey1019de92017-09-06 13:47:03 -06001636 } else {
1637 Slog.w(TAG, "vold not found; trying again");
Jeff Sharkey1019de92017-09-06 13:47:03 -06001638 }
Jeff Sharkey8058fe62017-09-13 11:50:33 -06001639
Jin Qian12690d52017-10-13 18:17:04 -07001640 if (mStoraged == null || mVold == null) {
1641 BackgroundThread.getHandler().postDelayed(() -> {
1642 connect();
1643 }, DateUtils.SECOND_IN_MILLIS);
1644 } else {
1645 onDaemonConnected();
1646 }
Jeff Sharkey1019de92017-09-06 13:47:03 -06001647 }
1648
Jeff Sharkey11697f52018-12-13 10:14:42 -07001649 private void servicesReady() {
1650 synchronized (mLock) {
1651 final boolean thisIsolatedStorage = StorageManager.hasIsolatedStorage();
1652 if (mLastIsolatedStorage == thisIsolatedStorage) {
1653 // Nothing changed since last boot; keep rolling forward
1654 return;
1655 } else if (thisIsolatedStorage) {
1656 // This boot enables isolated storage; apply legacy behavior
1657 applyLegacyStorage();
1658 }
1659
1660 // Always remember the new state we just booted with
1661 writeSettingsLocked();
1662 }
1663 }
1664
1665 /**
1666 * If we're enabling isolated storage, we need to remember which existing
1667 * apps have already been using shared storage, and grant them legacy access
1668 * to keep them running smoothly.
1669 */
1670 private void applyLegacyStorage() {
1671 final AppOpsManager appOps = mContext.getSystemService(AppOpsManager.class);
1672 final UserManagerInternal um = LocalServices.getService(UserManagerInternal.class);
1673 for (int userId : um.getUserIds()) {
1674 final PackageManager pm;
1675 try {
1676 pm = mContext.createPackageContextAsUser(mContext.getPackageName(),
1677 0, UserHandle.of(userId)).getPackageManager();
1678 } catch (PackageManager.NameNotFoundException e) {
1679 throw new RuntimeException(e);
1680 }
1681
1682 final List<PackageInfo> pkgs = pm.getPackagesHoldingPermissions(new String[] {
1683 android.Manifest.permission.READ_EXTERNAL_STORAGE,
1684 android.Manifest.permission.WRITE_EXTERNAL_STORAGE
1685 }, MATCH_UNINSTALLED_PACKAGES | MATCH_DIRECT_BOOT_AWARE | MATCH_DIRECT_BOOT_UNAWARE);
1686 for (PackageInfo pkg : pkgs) {
1687 final int uid = pkg.applicationInfo.uid;
1688 final String packageName = pkg.applicationInfo.packageName;
1689
1690 final long lastAccess = getLastAccessTime(appOps, uid, packageName, new int[] {
1691 AppOpsManager.OP_READ_EXTERNAL_STORAGE,
1692 AppOpsManager.OP_WRITE_EXTERNAL_STORAGE,
1693 });
1694
1695 Log.d(TAG, "Found " + uid + " " + packageName
1696 + " with granted storage access, last accessed " + lastAccess);
1697 if (lastAccess > 0) {
1698 appOps.setMode(AppOpsManager.OP_LEGACY_STORAGE,
1699 uid, packageName, AppOpsManager.MODE_ALLOWED);
1700 }
1701 }
1702 }
1703 }
1704
1705 private static long getLastAccessTime(AppOpsManager manager,
1706 int uid, String packageName, int[] ops) {
1707 long maxTime = 0;
1708 final List<AppOpsManager.PackageOps> pkgs = manager.getOpsForPackage(uid, packageName, ops);
Eugene Susla04d021c2018-12-17 14:49:59 -08001709 for (AppOpsManager.PackageOps pkg : CollectionUtils.emptyIfNull(pkgs)) {
1710 for (AppOpsManager.OpEntry op : CollectionUtils.emptyIfNull(pkg.getOps())) {
Jeff Sharkey11697f52018-12-13 10:14:42 -07001711 maxTime = Math.max(maxTime, op.getLastAccessTime());
1712 }
1713 }
1714 return maxTime;
1715 }
1716
Jeff Sharkey56e62932015-03-21 20:41:00 -07001717 private void systemReady() {
Wale Ogunwale6767eae2018-05-03 15:52:51 -07001718 LocalServices.getService(ActivityTaskManagerInternal.class)
Jeff Sharkey9765e442017-12-14 22:15:14 -07001719 .registerScreenObserver(this);
1720
Jeff Sharkeyb049e212012-09-07 23:16:01 -07001721 mSystemReady = true;
Sudheer Shanka3a0df3b2018-12-12 12:43:43 -08001722 mIPackageManager = IPackageManager.Stub.asInterface(
1723 ServiceManager.getService("package"));
1724 mIAppOpsService = IAppOpsService.Stub.asInterface(
1725 ServiceManager.getService(Context.APP_OPS_SERVICE));
Sudheer Shankaff971bc2018-12-13 17:39:59 -08001726 try {
1727 mIAppOpsService.startWatchingMode(OP_REQUEST_INSTALL_PACKAGES, null, mAppOpsCallback);
1728 } catch (RemoteException e) {
1729 }
Jeff Sharkeyb049e212012-09-07 23:16:01 -07001730 mHandler.obtainMessage(H_SYSTEM_READY).sendToTarget();
1731 }
1732
Yasuhiro Matsuda87a38b52015-07-24 22:10:16 +09001733 private void bootCompleted() {
1734 mBootCompleted = true;
1735 }
1736
Jeff Sharkeyfced5342015-05-10 14:53:34 -07001737 private String getDefaultPrimaryStorageUuid() {
1738 if (SystemProperties.getBoolean(StorageManager.PROP_PRIMARY_PHYSICAL, false)) {
1739 return StorageManager.UUID_PRIMARY_PHYSICAL;
1740 } else {
1741 return StorageManager.UUID_PRIVATE_INTERNAL;
1742 }
1743 }
1744
Andreas Gampea36dc622018-02-05 17:19:22 -08001745 @GuardedBy("mLock")
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001746 private void readSettingsLocked() {
1747 mRecords.clear();
Jeff Sharkeyfced5342015-05-10 14:53:34 -07001748 mPrimaryStorageUuid = getDefaultPrimaryStorageUuid();
Jeff Sharkey11697f52018-12-13 10:14:42 -07001749 mLastIsolatedStorage = false;
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001750
1751 FileInputStream fis = null;
1752 try {
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001753 fis = mSettingsFile.openRead();
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001754 final XmlPullParser in = Xml.newPullParser();
Wojciech Staszkiewicz9e9e2e72015-05-08 14:58:46 +01001755 in.setInput(fis, StandardCharsets.UTF_8.name());
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001756
1757 int type;
1758 while ((type = in.next()) != END_DOCUMENT) {
1759 if (type == START_TAG) {
1760 final String tag = in.getName();
Jeff Sharkey620b32b2015-04-23 19:36:02 -07001761 if (TAG_VOLUMES.equals(tag)) {
1762 final int version = readIntAttribute(in, ATTR_VERSION, VERSION_INIT);
Jeff Sharkeyfced5342015-05-10 14:53:34 -07001763 final boolean primaryPhysical = SystemProperties.getBoolean(
1764 StorageManager.PROP_PRIMARY_PHYSICAL, false);
1765 final boolean validAttr = (version >= VERSION_FIX_PRIMARY)
1766 || (version >= VERSION_ADD_PRIMARY && !primaryPhysical);
1767 if (validAttr) {
Jeff Sharkey620b32b2015-04-23 19:36:02 -07001768 mPrimaryStorageUuid = readStringAttribute(in,
1769 ATTR_PRIMARY_STORAGE_UUID);
Jeff Sharkey620b32b2015-04-23 19:36:02 -07001770 }
Jeff Sharkey11697f52018-12-13 10:14:42 -07001771 mLastIsolatedStorage = readBooleanAttribute(in,
1772 ATTR_ISOLATED_STORAGE, false);
Jeff Sharkey620b32b2015-04-23 19:36:02 -07001773
1774 } else if (TAG_VOLUME.equals(tag)) {
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001775 final VolumeRecord rec = readVolumeRecord(in);
1776 mRecords.put(rec.fsUuid, rec);
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001777 }
1778 }
1779 }
1780 } catch (FileNotFoundException e) {
1781 // Missing metadata is okay, probably first boot
1782 } catch (IOException e) {
1783 Slog.wtf(TAG, "Failed reading metadata", e);
1784 } catch (XmlPullParserException e) {
1785 Slog.wtf(TAG, "Failed reading metadata", e);
1786 } finally {
1787 IoUtils.closeQuietly(fis);
1788 }
1789 }
1790
Andreas Gampea36dc622018-02-05 17:19:22 -08001791 @GuardedBy("mLock")
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001792 private void writeSettingsLocked() {
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001793 FileOutputStream fos = null;
1794 try {
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001795 fos = mSettingsFile.startWrite();
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001796
1797 XmlSerializer out = new FastXmlSerializer();
Wojciech Staszkiewicz9e9e2e72015-05-08 14:58:46 +01001798 out.setOutput(fos, StandardCharsets.UTF_8.name());
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001799 out.startDocument(null, true);
1800 out.startTag(null, TAG_VOLUMES);
Jeff Sharkeyfced5342015-05-10 14:53:34 -07001801 writeIntAttribute(out, ATTR_VERSION, VERSION_FIX_PRIMARY);
Jeff Sharkey620b32b2015-04-23 19:36:02 -07001802 writeStringAttribute(out, ATTR_PRIMARY_STORAGE_UUID, mPrimaryStorageUuid);
Jeff Sharkey11697f52018-12-13 10:14:42 -07001803 writeBooleanAttribute(out, ATTR_ISOLATED_STORAGE, StorageManager.hasIsolatedStorage());
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001804 final int size = mRecords.size();
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001805 for (int i = 0; i < size; i++) {
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001806 final VolumeRecord rec = mRecords.valueAt(i);
1807 writeVolumeRecord(out, rec);
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001808 }
1809 out.endTag(null, TAG_VOLUMES);
1810 out.endDocument();
1811
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001812 mSettingsFile.finishWrite(fos);
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001813 } catch (IOException e) {
1814 if (fos != null) {
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001815 mSettingsFile.failWrite(fos);
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001816 }
1817 }
1818 }
1819
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001820 public static VolumeRecord readVolumeRecord(XmlPullParser in) throws IOException {
1821 final int type = readIntAttribute(in, ATTR_TYPE);
1822 final String fsUuid = readStringAttribute(in, ATTR_FS_UUID);
1823 final VolumeRecord meta = new VolumeRecord(type, fsUuid);
Jeff Sharkey5cc0df22015-06-17 19:44:05 -07001824 meta.partGuid = readStringAttribute(in, ATTR_PART_GUID);
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001825 meta.nickname = readStringAttribute(in, ATTR_NICKNAME);
1826 meta.userFlags = readIntAttribute(in, ATTR_USER_FLAGS);
Jeff Sharkeye8a4b662015-06-27 15:43:45 -07001827 meta.createdMillis = readLongAttribute(in, ATTR_CREATED_MILLIS);
1828 meta.lastTrimMillis = readLongAttribute(in, ATTR_LAST_TRIM_MILLIS);
1829 meta.lastBenchMillis = readLongAttribute(in, ATTR_LAST_BENCH_MILLIS);
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001830 return meta;
1831 }
1832
1833 public static void writeVolumeRecord(XmlSerializer out, VolumeRecord rec) throws IOException {
1834 out.startTag(null, TAG_VOLUME);
1835 writeIntAttribute(out, ATTR_TYPE, rec.type);
1836 writeStringAttribute(out, ATTR_FS_UUID, rec.fsUuid);
Jeff Sharkey5cc0df22015-06-17 19:44:05 -07001837 writeStringAttribute(out, ATTR_PART_GUID, rec.partGuid);
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001838 writeStringAttribute(out, ATTR_NICKNAME, rec.nickname);
1839 writeIntAttribute(out, ATTR_USER_FLAGS, rec.userFlags);
Jeff Sharkeye8a4b662015-06-27 15:43:45 -07001840 writeLongAttribute(out, ATTR_CREATED_MILLIS, rec.createdMillis);
1841 writeLongAttribute(out, ATTR_LAST_TRIM_MILLIS, rec.lastTrimMillis);
1842 writeLongAttribute(out, ATTR_LAST_BENCH_MILLIS, rec.lastBenchMillis);
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001843 out.endTag(null, TAG_VOLUME);
1844 }
1845
San Mehat207e5382010-02-04 20:46:54 -08001846 /**
San Mehat4270e1e2010-01-29 05:32:19 -08001847 * Exposed API calls below here
1848 */
1849
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001850 @Override
Sudheer Shanka2250d562016-11-07 15:41:02 -08001851 public void registerListener(IStorageEventListener listener) {
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001852 mCallbacks.register(listener);
San Mehat4270e1e2010-01-29 05:32:19 -08001853 }
1854
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001855 @Override
Sudheer Shanka2250d562016-11-07 15:41:02 -08001856 public void unregisterListener(IStorageEventListener listener) {
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001857 mCallbacks.unregister(listener);
San Mehat4270e1e2010-01-29 05:32:19 -08001858 }
1859
Jeff Sharkey48877892015-03-18 11:27:19 -07001860 @Override
Sudheer Shanka2250d562016-11-07 15:41:02 -08001861 public void shutdown(final IStorageShutdownObserver observer) {
Jeff Sharkey48877892015-03-18 11:27:19 -07001862 enforcePermission(android.Manifest.permission.SHUTDOWN);
San Mehat4270e1e2010-01-29 05:32:19 -08001863
San Mehata5078592010-03-25 09:36:54 -07001864 Slog.i(TAG, "Shutting down");
Jeff Sharkey48877892015-03-18 11:27:19 -07001865 mHandler.obtainMessage(H_SHUTDOWN, observer).sendToTarget();
San Mehat4270e1e2010-01-29 05:32:19 -08001866 }
1867
Jeff Sharkey48877892015-03-18 11:27:19 -07001868 @Override
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001869 public void mount(String volId) {
1870 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001871
Jeff Sharkeyef10ee02015-07-05 14:17:27 -07001872 final VolumeInfo vol = findVolumeByIdOrThrow(volId);
Jeff Sharkey2e606d72015-07-27 14:19:54 -07001873 if (isMountDisallowed(vol)) {
1874 throw new SecurityException("Mounting " + volId + " restricted by policy");
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001875 }
Sudheer Shanka3f0645b2018-09-18 13:07:59 -07001876 mount(vol);
1877 }
1878
1879 private void mount(VolumeInfo vol) {
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001880 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06001881 mVold.mount(vol.id, vol.mountFlags, vol.mountUserId);
Sudheer Shanka3f0645b2018-09-18 13:07:59 -07001882 if ((vol.mountFlags & VolumeInfo.MOUNT_FLAG_VISIBLE) != 0) {
1883 mVisibleVols.add(vol);
1884 }
Jeff Sharkeyace874b2017-09-07 15:27:33 -06001885 } catch (Exception e) {
1886 Slog.wtf(TAG, e);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001887 }
1888 }
1889
1890 @Override
1891 public void unmount(String volId) {
1892 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001893
Jeff Sharkeyef10ee02015-07-05 14:17:27 -07001894 final VolumeInfo vol = findVolumeByIdOrThrow(volId);
Sudheer Shanka3f0645b2018-09-18 13:07:59 -07001895 unmount(vol);
1896 }
1897
1898 private void unmount(VolumeInfo vol) {
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001899 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06001900 mVold.unmount(vol.id);
Sudheer Shanka3f0645b2018-09-18 13:07:59 -07001901 if ((vol.mountFlags & VolumeInfo.MOUNT_FLAG_VISIBLE) != 0) {
1902 mVisibleVols.remove(vol);
1903 }
Jeff Sharkeyace874b2017-09-07 15:27:33 -06001904 } catch (Exception e) {
1905 Slog.wtf(TAG, e);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001906 }
1907 }
1908
1909 @Override
1910 public void format(String volId) {
Jeff Sharkey48877892015-03-18 11:27:19 -07001911 enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);
San Mehat5b77dab2010-01-26 13:28:50 -08001912
Jeff Sharkeyef10ee02015-07-05 14:17:27 -07001913 final VolumeInfo vol = findVolumeByIdOrThrow(volId);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001914 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06001915 mVold.format(vol.id, "auto");
Jeff Sharkeyace874b2017-09-07 15:27:33 -06001916 } catch (Exception e) {
1917 Slog.wtf(TAG, e);
Jeff Sharkey48877892015-03-18 11:27:19 -07001918 }
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001919 }
1920
1921 @Override
Jeff Sharkey7e19f532017-11-06 13:54:11 -07001922 public void benchmark(String volId, IVoldTaskListener listener) {
Jeff Sharkey9756d752015-05-14 21:07:42 -07001923 enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);
Jeff Sharkey9756d752015-05-14 21:07:42 -07001924
1925 try {
Jeff Sharkeyb302c542017-09-15 12:57:59 -06001926 mVold.benchmark(volId, new IVoldTaskListener.Stub() {
1927 @Override
1928 public void onStatus(int status, PersistableBundle extras) {
Jeff Sharkey7e19f532017-11-06 13:54:11 -07001929 dispatchOnStatus(listener, status, extras);
Jeff Sharkeyb302c542017-09-15 12:57:59 -06001930 }
1931
1932 @Override
1933 public void onFinished(int status, PersistableBundle extras) {
Jeff Sharkey7e19f532017-11-06 13:54:11 -07001934 dispatchOnFinished(listener, status, extras);
Jeff Sharkeyb302c542017-09-15 12:57:59 -06001935
1936 final String path = extras.getString("path");
1937 final String ident = extras.getString("ident");
1938 final long create = extras.getLong("create");
1939 final long run = extras.getLong("run");
1940 final long destroy = extras.getLong("destroy");
1941
1942 final DropBoxManager dropBox = mContext.getSystemService(DropBoxManager.class);
1943 dropBox.addText(TAG_STORAGE_BENCHMARK, scrubPath(path)
1944 + " " + ident + " " + create + " " + run + " " + destroy);
1945
1946 synchronized (mLock) {
1947 final VolumeRecord rec = findRecordForPath(path);
1948 if (rec != null) {
1949 rec.lastBenchMillis = System.currentTimeMillis();
1950 writeSettingsLocked();
1951 }
1952 }
1953 }
1954 });
Jeff Sharkey7e19f532017-11-06 13:54:11 -07001955 } catch (RemoteException e) {
1956 throw e.rethrowAsRuntimeException();
Jeff Sharkey9756d752015-05-14 21:07:42 -07001957 }
1958 }
1959
1960 @Override
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001961 public void partitionPublic(String diskId) {
1962 enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001963
Jeff Sharkeyeba260d2015-04-19 14:35:16 -07001964 final CountDownLatch latch = findOrCreateDiskScanLatch(diskId);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001965 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06001966 mVold.partition(diskId, IVold.PARTITION_TYPE_PUBLIC, -1);
Jeff Sharkeyedcdaf62015-07-09 09:45:36 -07001967 waitForLatch(latch, "partitionPublic", 3 * DateUtils.MINUTE_IN_MILLIS);
Jeff Sharkeyace874b2017-09-07 15:27:33 -06001968 } catch (Exception e) {
1969 Slog.wtf(TAG, e);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001970 }
1971 }
1972
1973 @Override
1974 public void partitionPrivate(String diskId) {
1975 enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);
Amith Yamasani462ac3a2015-06-30 14:21:01 -07001976 enforceAdminUser();
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001977
Jeff Sharkeyeba260d2015-04-19 14:35:16 -07001978 final CountDownLatch latch = findOrCreateDiskScanLatch(diskId);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001979 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06001980 mVold.partition(diskId, IVold.PARTITION_TYPE_PRIVATE, -1);
Jeff Sharkeyedcdaf62015-07-09 09:45:36 -07001981 waitForLatch(latch, "partitionPrivate", 3 * DateUtils.MINUTE_IN_MILLIS);
Jeff Sharkeyace874b2017-09-07 15:27:33 -06001982 } catch (Exception e) {
1983 Slog.wtf(TAG, e);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001984 }
1985 }
1986
1987 @Override
1988 public void partitionMixed(String diskId, int ratio) {
1989 enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);
Amith Yamasani462ac3a2015-06-30 14:21:01 -07001990 enforceAdminUser();
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001991
Jeff Sharkeyeba260d2015-04-19 14:35:16 -07001992 final CountDownLatch latch = findOrCreateDiskScanLatch(diskId);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001993 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06001994 mVold.partition(diskId, IVold.PARTITION_TYPE_MIXED, ratio);
Jeff Sharkeyedcdaf62015-07-09 09:45:36 -07001995 waitForLatch(latch, "partitionMixed", 3 * DateUtils.MINUTE_IN_MILLIS);
Jeff Sharkeyace874b2017-09-07 15:27:33 -06001996 } catch (Exception e) {
1997 Slog.wtf(TAG, e);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001998 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001999 }
2000
Jeff Sharkey48877892015-03-18 11:27:19 -07002001 @Override
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07002002 public void setVolumeNickname(String fsUuid, String nickname) {
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07002003 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07002004
Jeff Sharkey50a05452015-04-29 11:24:52 -07002005 Preconditions.checkNotNull(fsUuid);
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07002006 synchronized (mLock) {
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07002007 final VolumeRecord rec = mRecords.get(fsUuid);
2008 rec.nickname = nickname;
Jeff Sharkey50a05452015-04-29 11:24:52 -07002009 mCallbacks.notifyVolumeRecordChanged(rec);
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07002010 writeSettingsLocked();
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07002011 }
2012 }
2013
2014 @Override
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07002015 public void setVolumeUserFlags(String fsUuid, int flags, int mask) {
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07002016 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07002017
Jeff Sharkey50a05452015-04-29 11:24:52 -07002018 Preconditions.checkNotNull(fsUuid);
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07002019 synchronized (mLock) {
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07002020 final VolumeRecord rec = mRecords.get(fsUuid);
2021 rec.userFlags = (rec.userFlags & ~mask) | (flags & mask);
Jeff Sharkey50a05452015-04-29 11:24:52 -07002022 mCallbacks.notifyVolumeRecordChanged(rec);
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07002023 writeSettingsLocked();
2024 }
2025 }
2026
2027 @Override
2028 public void forgetVolume(String fsUuid) {
2029 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07002030
Jeff Sharkey50a05452015-04-29 11:24:52 -07002031 Preconditions.checkNotNull(fsUuid);
Jeff Sharkey5a9bb742015-11-03 10:15:57 -08002032
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07002033 synchronized (mLock) {
Jeff Sharkey5cc0df22015-06-17 19:44:05 -07002034 final VolumeRecord rec = mRecords.remove(fsUuid);
2035 if (rec != null && !TextUtils.isEmpty(rec.partGuid)) {
Jeff Sharkeydb4b6192017-10-24 11:08:50 -06002036 mHandler.obtainMessage(H_PARTITION_FORGET, rec).sendToTarget();
Jeff Sharkey5cc0df22015-06-17 19:44:05 -07002037 }
2038 mCallbacks.notifyVolumeForgotten(fsUuid);
Jeff Sharkey50a05452015-04-29 11:24:52 -07002039
2040 // If this had been primary storage, revert back to internal and
2041 // reset vold so we bind into new volume into place.
2042 if (Objects.equals(mPrimaryStorageUuid, fsUuid)) {
Jeff Sharkeyfced5342015-05-10 14:53:34 -07002043 mPrimaryStorageUuid = getDefaultPrimaryStorageUuid();
Jeff Sharkey5a9bb742015-11-03 10:15:57 -08002044 mHandler.obtainMessage(H_RESET).sendToTarget();
Jeff Sharkey50a05452015-04-29 11:24:52 -07002045 }
2046
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07002047 writeSettingsLocked();
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07002048 }
2049 }
2050
Jeff Sharkey7d2af542015-05-12 15:27:15 -07002051 @Override
2052 public void forgetAllVolumes() {
2053 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
Jeff Sharkey7d2af542015-05-12 15:27:15 -07002054
Jeff Sharkey50a05452015-04-29 11:24:52 -07002055 synchronized (mLock) {
2056 for (int i = 0; i < mRecords.size(); i++) {
2057 final String fsUuid = mRecords.keyAt(i);
Jeff Sharkey5cc0df22015-06-17 19:44:05 -07002058 final VolumeRecord rec = mRecords.valueAt(i);
2059 if (!TextUtils.isEmpty(rec.partGuid)) {
Jeff Sharkeydb4b6192017-10-24 11:08:50 -06002060 mHandler.obtainMessage(H_PARTITION_FORGET, rec).sendToTarget();
Jeff Sharkey5cc0df22015-06-17 19:44:05 -07002061 }
Jeff Sharkey50a05452015-04-29 11:24:52 -07002062 mCallbacks.notifyVolumeForgotten(fsUuid);
2063 }
Jeff Sharkey50a05452015-04-29 11:24:52 -07002064 mRecords.clear();
Jeff Sharkey50a05452015-04-29 11:24:52 -07002065
Jeff Sharkeyfced5342015-05-10 14:53:34 -07002066 if (!Objects.equals(StorageManager.UUID_PRIVATE_INTERNAL, mPrimaryStorageUuid)) {
2067 mPrimaryStorageUuid = getDefaultPrimaryStorageUuid();
2068 }
2069
2070 writeSettingsLocked();
Jeff Sharkey5a9bb742015-11-03 10:15:57 -08002071 mHandler.obtainMessage(H_RESET).sendToTarget();
Jeff Sharkey50a05452015-04-29 11:24:52 -07002072 }
2073 }
2074
Jeff Sharkeydb4b6192017-10-24 11:08:50 -06002075 private void forgetPartition(String partGuid, String fsUuid) {
Jeff Sharkey5cc0df22015-06-17 19:44:05 -07002076 try {
Jeff Sharkeydb4b6192017-10-24 11:08:50 -06002077 mVold.forgetPartition(partGuid, fsUuid);
Jeff Sharkeyace874b2017-09-07 15:27:33 -06002078 } catch (Exception e) {
2079 Slog.wtf(TAG, e);
Jeff Sharkey5cc0df22015-06-17 19:44:05 -07002080 }
2081 }
2082
Jeff Sharkey31d0b702016-11-21 14:16:53 -07002083 @Override
Jeff Sharkey7e19f532017-11-06 13:54:11 -07002084 public void fstrim(int flags, IVoldTaskListener listener) {
Jeff Sharkey31d0b702016-11-21 14:16:53 -07002085 enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);
Jeff Sharkey31d0b702016-11-21 14:16:53 -07002086
2087 try {
Jeff Sharkeyb302c542017-09-15 12:57:59 -06002088 mVold.fstrim(flags, new IVoldTaskListener.Stub() {
2089 @Override
2090 public void onStatus(int status, PersistableBundle extras) {
Jeff Sharkey7e19f532017-11-06 13:54:11 -07002091 dispatchOnStatus(listener, status, extras);
2092
Jeff Sharkeyb302c542017-09-15 12:57:59 -06002093 // Ignore trim failures
2094 if (status != 0) return;
2095
2096 final String path = extras.getString("path");
2097 final long bytes = extras.getLong("bytes");
2098 final long time = extras.getLong("time");
2099
2100 final DropBoxManager dropBox = mContext.getSystemService(DropBoxManager.class);
2101 dropBox.addText(TAG_STORAGE_TRIM, scrubPath(path) + " " + bytes + " " + time);
2102
2103 synchronized (mLock) {
2104 final VolumeRecord rec = findRecordForPath(path);
2105 if (rec != null) {
2106 rec.lastTrimMillis = System.currentTimeMillis();
2107 writeSettingsLocked();
2108 }
2109 }
2110 }
2111
2112 @Override
2113 public void onFinished(int status, PersistableBundle extras) {
Jeff Sharkey7e19f532017-11-06 13:54:11 -07002114 dispatchOnFinished(listener, status, extras);
2115
Jeff Sharkeyb302c542017-09-15 12:57:59 -06002116 // TODO: benchmark when desired
2117 }
2118 });
Jeff Sharkey7e19f532017-11-06 13:54:11 -07002119 } catch (RemoteException e) {
2120 throw e.rethrowAsRuntimeException();
Jeff Sharkey31d0b702016-11-21 14:16:53 -07002121 }
2122 }
2123
Jin Qiana85b9912017-10-17 15:48:18 -07002124 void runIdleMaint(Runnable callback) {
2125 enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);
2126
2127 try {
2128 mVold.runIdleMaint(new IVoldTaskListener.Stub() {
2129 @Override
2130 public void onStatus(int status, PersistableBundle extras) {
2131 // Not currently used
2132 }
2133 @Override
2134 public void onFinished(int status, PersistableBundle extras) {
2135 if (callback != null) {
2136 BackgroundThread.getHandler().post(callback);
2137 }
2138 }
2139 });
2140 } catch (Exception e) {
2141 Slog.wtf(TAG, e);
2142 }
2143 }
2144
2145 @Override
2146 public void runIdleMaintenance() {
2147 runIdleMaint(null);
2148 }
2149
2150 void abortIdleMaint(Runnable callback) {
2151 enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);
2152
2153 try {
2154 mVold.abortIdleMaint(new IVoldTaskListener.Stub() {
2155 @Override
2156 public void onStatus(int status, PersistableBundle extras) {
2157 // Not currently used
2158 }
2159 @Override
2160 public void onFinished(int status, PersistableBundle extras) {
2161 if (callback != null) {
2162 BackgroundThread.getHandler().post(callback);
2163 }
2164 }
2165 });
2166 } catch (Exception e) {
2167 Slog.wtf(TAG, e);
2168 }
2169 }
2170
2171 @Override
2172 public void abortIdleMaintenance() {
2173 abortIdleMaint(null);
2174 }
2175
Svet Ganov6ee871e2015-07-10 14:29:33 -07002176 private void remountUidExternalStorage(int uid, int mode) {
Jeff Sharkey9527b222015-06-24 15:24:48 -07002177 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002178 mVold.remountUid(uid, mode);
Jeff Sharkeyace874b2017-09-07 15:27:33 -06002179 } catch (Exception e) {
2180 Slog.wtf(TAG, e);
Jeff Sharkey9527b222015-06-24 15:24:48 -07002181 }
2182 }
2183
2184 @Override
Jeff Sharkey4c099d02015-05-15 13:45:00 -07002185 public void setDebugFlags(int flags, int mask) {
2186 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
Jeff Sharkey4c099d02015-05-15 13:45:00 -07002187
Jeff Sharkeyba512352015-11-12 20:17:45 -08002188 if ((mask & StorageManager.DEBUG_EMULATE_FBE) != 0) {
Jeff Sharkey00455bf2016-11-04 14:45:24 -06002189 if (!EMULATE_FBE_SUPPORTED) {
2190 throw new IllegalStateException(
2191 "Emulation not supported on this device");
2192 }
Paul Lawrence20be5d62016-02-26 13:51:17 -08002193 if (StorageManager.isFileEncryptedNativeOnly()) {
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07002194 throw new IllegalStateException(
Jeff Sharkey00455bf2016-11-04 14:45:24 -06002195 "Emulation not supported on device with native FBE");
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07002196 }
Jeff Sharkey5a785162016-03-21 13:02:06 -06002197 if (mLockPatternUtils.isCredentialRequiredToDecrypt(false)) {
2198 throw new IllegalStateException(
2199 "Emulation requires disabling 'Secure start-up' in Settings > Security");
2200 }
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07002201
Jeff Sharkey1176e512016-02-29 17:01:26 -07002202 final long token = Binder.clearCallingIdentity();
2203 try {
2204 final boolean emulateFbe = (flags & StorageManager.DEBUG_EMULATE_FBE) != 0;
2205 SystemProperties.set(StorageManager.PROP_EMULATE_FBE, Boolean.toString(emulateFbe));
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07002206
Jeff Sharkey1176e512016-02-29 17:01:26 -07002207 // Perform hard reboot to kick policy into place
2208 mContext.getSystemService(PowerManager.class).reboot(null);
2209 } finally {
2210 Binder.restoreCallingIdentity(token);
2211 }
Jeff Sharkeyba512352015-11-12 20:17:45 -08002212 }
Jeff Sharkey4c099d02015-05-15 13:45:00 -07002213
Jeff Sharkey901c0422018-04-20 13:11:20 -06002214 if ((mask & (StorageManager.DEBUG_ADOPTABLE_FORCE_ON
2215 | StorageManager.DEBUG_ADOPTABLE_FORCE_OFF)) != 0) {
2216 final String value;
2217 if ((flags & StorageManager.DEBUG_ADOPTABLE_FORCE_ON) != 0) {
2218 value = "force_on";
2219 } else if ((flags & StorageManager.DEBUG_ADOPTABLE_FORCE_OFF) != 0) {
2220 value = "force_off";
2221 } else {
2222 value = "";
2223 }
Jeff Sharkeyba512352015-11-12 20:17:45 -08002224
Jeff Sharkey901c0422018-04-20 13:11:20 -06002225 final long token = Binder.clearCallingIdentity();
2226 try {
2227 SystemProperties.set(StorageManager.PROP_ADOPTABLE, value);
2228
2229 // Reset storage to kick new setting into place
Jeff Sharkeyba512352015-11-12 20:17:45 -08002230 mHandler.obtainMessage(H_RESET).sendToTarget();
Jeff Sharkey901c0422018-04-20 13:11:20 -06002231 } finally {
2232 Binder.restoreCallingIdentity(token);
Jeff Sharkeyba512352015-11-12 20:17:45 -08002233 }
Jeff Sharkey4c099d02015-05-15 13:45:00 -07002234 }
Jeff Sharkey33dd1562016-04-07 11:05:33 -06002235
2236 if ((mask & (StorageManager.DEBUG_SDCARDFS_FORCE_ON
2237 | StorageManager.DEBUG_SDCARDFS_FORCE_OFF)) != 0) {
2238 final String value;
2239 if ((flags & StorageManager.DEBUG_SDCARDFS_FORCE_ON) != 0) {
2240 value = "force_on";
2241 } else if ((flags & StorageManager.DEBUG_SDCARDFS_FORCE_OFF) != 0) {
2242 value = "force_off";
2243 } else {
2244 value = "";
2245 }
2246
2247 final long token = Binder.clearCallingIdentity();
2248 try {
2249 SystemProperties.set(StorageManager.PROP_SDCARDFS, value);
2250
2251 // Reset storage to kick new setting into place
2252 mHandler.obtainMessage(H_RESET).sendToTarget();
2253 } finally {
2254 Binder.restoreCallingIdentity(token);
2255 }
2256 }
Jeff Sharkeye53e2d92017-03-25 23:14:06 -06002257
2258 if ((mask & StorageManager.DEBUG_VIRTUAL_DISK) != 0) {
2259 final boolean enabled = (flags & StorageManager.DEBUG_VIRTUAL_DISK) != 0;
2260
2261 final long token = Binder.clearCallingIdentity();
2262 try {
2263 SystemProperties.set(StorageManager.PROP_VIRTUAL_DISK, Boolean.toString(enabled));
2264
2265 // Reset storage to kick new setting into place
2266 mHandler.obtainMessage(H_RESET).sendToTarget();
2267 } finally {
2268 Binder.restoreCallingIdentity(token);
2269 }
2270 }
Sudheer Shankabe0febe2018-11-07 18:24:37 -08002271
Jeff Sharkeyb0c363b22018-12-15 11:53:03 -07002272 if ((mask & (StorageManager.DEBUG_ISOLATED_STORAGE_FORCE_ON
2273 | StorageManager.DEBUG_ISOLATED_STORAGE_FORCE_OFF)) != 0) {
2274 final int value;
2275 if ((flags & StorageManager.DEBUG_ISOLATED_STORAGE_FORCE_ON) != 0) {
2276 value = 1;
2277 } else if ((flags & StorageManager.DEBUG_ISOLATED_STORAGE_FORCE_OFF) != 0) {
2278 value = -1;
2279 } else {
2280 value = 0;
2281 }
Sudheer Shankabe0febe2018-11-07 18:24:37 -08002282
2283 final long token = Binder.clearCallingIdentity();
2284 try {
Jeff Sharkeyb0c363b22018-12-15 11:53:03 -07002285 Settings.Global.putInt(mContext.getContentResolver(),
2286 Settings.Global.ISOLATED_STORAGE_LOCAL, value);
2287 refreshIsolatedStorageSettings();
Sudheer Shankabe0febe2018-11-07 18:24:37 -08002288
2289 // Perform hard reboot to kick policy into place
2290 mContext.getSystemService(PowerManager.class).reboot(null);
2291 } finally {
2292 Binder.restoreCallingIdentity(token);
2293 }
2294 }
Jeff Sharkey4c099d02015-05-15 13:45:00 -07002295 }
2296
2297 @Override
Jeff Sharkey275e3e42015-04-24 16:10:32 -07002298 public String getPrimaryStorageUuid() {
Jeff Sharkey620b32b2015-04-23 19:36:02 -07002299 synchronized (mLock) {
2300 return mPrimaryStorageUuid;
2301 }
2302 }
2303
2304 @Override
Jeff Sharkey275e3e42015-04-24 16:10:32 -07002305 public void setPrimaryStorageUuid(String volumeUuid, IPackageMoveObserver callback) {
2306 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
Jeff Sharkey620b32b2015-04-23 19:36:02 -07002307
Jeff Sharkeya31460c2016-06-22 09:04:33 -06002308 final VolumeInfo from;
2309 final VolumeInfo to;
2310
Jeff Sharkey275e3e42015-04-24 16:10:32 -07002311 synchronized (mLock) {
Jeff Sharkeyfced5342015-05-10 14:53:34 -07002312 if (Objects.equals(mPrimaryStorageUuid, volumeUuid)) {
2313 throw new IllegalArgumentException("Primary storage already at " + volumeUuid);
Jeff Sharkey275e3e42015-04-24 16:10:32 -07002314 }
2315
2316 if (mMoveCallback != null) {
2317 throw new IllegalStateException("Move already in progress");
2318 }
2319 mMoveCallback = callback;
2320 mMoveTargetUuid = volumeUuid;
2321
Jeff Sharkeya65e6492017-06-21 13:45:11 -06002322 // We need all the users unlocked to move their primary storage
2323 final List<UserInfo> users = mContext.getSystemService(UserManager.class).getUsers();
2324 for (UserInfo user : users) {
2325 if (StorageManager.isFileEncryptedNativeOrEmulated()
2326 && !isUserKeyUnlocked(user.id)) {
2327 Slog.w(TAG, "Failing move due to locked user " + user.id);
2328 onMoveStatusLocked(PackageManager.MOVE_FAILED_LOCKED_USER);
2329 return;
2330 }
2331 }
2332
Jeff Sharkeyfced5342015-05-10 14:53:34 -07002333 // When moving to/from primary physical volume, we probably just nuked
2334 // the current storage location, so we have nothing to move.
2335 if (Objects.equals(StorageManager.UUID_PRIMARY_PHYSICAL, mPrimaryStorageUuid)
2336 || Objects.equals(StorageManager.UUID_PRIMARY_PHYSICAL, volumeUuid)) {
2337 Slog.d(TAG, "Skipping move to/from primary physical");
2338 onMoveStatusLocked(MOVE_STATUS_COPY_FINISHED);
2339 onMoveStatusLocked(PackageManager.MOVE_SUCCEEDED);
Jeff Sharkey5a9bb742015-11-03 10:15:57 -08002340 mHandler.obtainMessage(H_RESET).sendToTarget();
Jeff Sharkeya31460c2016-06-22 09:04:33 -06002341 return;
Jeff Sharkeyfced5342015-05-10 14:53:34 -07002342
2343 } else {
Jeff Sharkeya31460c2016-06-22 09:04:33 -06002344 from = findStorageForUuid(mPrimaryStorageUuid);
2345 to = findStorageForUuid(volumeUuid);
Jeff Sharkeyef10ee02015-07-05 14:17:27 -07002346
2347 if (from == null) {
2348 Slog.w(TAG, "Failing move due to missing from volume " + mPrimaryStorageUuid);
2349 onMoveStatusLocked(PackageManager.MOVE_FAILED_INTERNAL_ERROR);
2350 return;
2351 } else if (to == null) {
2352 Slog.w(TAG, "Failing move due to missing to volume " + volumeUuid);
2353 onMoveStatusLocked(PackageManager.MOVE_FAILED_INTERNAL_ERROR);
2354 return;
2355 }
Jeff Sharkey275e3e42015-04-24 16:10:32 -07002356 }
Jeff Sharkey620b32b2015-04-23 19:36:02 -07002357 }
Jeff Sharkeya31460c2016-06-22 09:04:33 -06002358
2359 try {
Jeff Sharkeyb302c542017-09-15 12:57:59 -06002360 mVold.moveStorage(from.id, to.id, new IVoldTaskListener.Stub() {
2361 @Override
2362 public void onStatus(int status, PersistableBundle extras) {
2363 synchronized (mLock) {
2364 onMoveStatusLocked(status);
2365 }
2366 }
2367
2368 @Override
2369 public void onFinished(int status, PersistableBundle extras) {
2370 // Not currently used
2371 }
2372 });
Jeff Sharkeyace874b2017-09-07 15:27:33 -06002373 } catch (Exception e) {
2374 Slog.wtf(TAG, e);
Jeff Sharkeya31460c2016-06-22 09:04:33 -06002375 }
Jeff Sharkey620b32b2015-04-23 19:36:02 -07002376 }
2377
San Mehatb1043402010-02-05 08:26:50 -08002378 private void warnOnNotMounted() {
Jeff Sharkey48877892015-03-18 11:27:19 -07002379 synchronized (mLock) {
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07002380 for (int i = 0; i < mVolumes.size(); i++) {
2381 final VolumeInfo vol = mVolumes.valueAt(i);
Jeff Sharkey27de30d2015-04-18 16:20:27 -07002382 if (vol.isPrimary() && vol.isMountedWritable()) {
Jeff Sharkey48877892015-03-18 11:27:19 -07002383 // Cool beans, we have a mounted primary volume
2384 return;
2385 }
Jeff Sharkey32ee8312012-09-30 13:21:31 -07002386 }
San Mehatb1043402010-02-05 08:26:50 -08002387 }
Jeff Sharkey48877892015-03-18 11:27:19 -07002388
2389 Slog.w(TAG, "No primary storage mounted!");
San Mehatb1043402010-02-05 08:26:50 -08002390 }
2391
Kenny Roota02b8b02010-08-05 16:14:17 -07002392 private boolean isUidOwnerOfPackageOrSystem(String packageName, int callerUid) {
2393 if (callerUid == android.os.Process.SYSTEM_UID) {
2394 return true;
2395 }
2396
Kenny Root02c87302010-07-01 08:10:18 -07002397 if (packageName == null) {
2398 return false;
2399 }
2400
Jeff Sharkey5790af02018-08-13 17:42:54 -06002401 final int packageUid = mPmInternal.getPackageUid(packageName,
Jeff Sharkeycd654482016-01-08 17:42:11 -07002402 PackageManager.MATCH_DEBUG_TRIAGED_MISSING, UserHandle.getUserId(callerUid));
Kenny Root02c87302010-07-01 08:10:18 -07002403
2404 if (DEBUG_OBB) {
2405 Slog.d(TAG, "packageName = " + packageName + ", packageUid = " +
2406 packageUid + ", callerUid = " + callerUid);
2407 }
2408
2409 return callerUid == packageUid;
2410 }
2411
Jeff Sharkey54402792017-09-15 16:05:19 -06002412 @Override
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002413 public String getMountedObbPath(String rawPath) {
2414 Preconditions.checkNotNull(rawPath, "rawPath cannot be null");
Kenny Rootaf9d6672010-10-08 09:21:39 -07002415
Kenny Root02c87302010-07-01 08:10:18 -07002416 warnOnNotMounted();
2417
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002418 final ObbState state;
Rubin Xucd7a0142015-04-17 23:45:27 +01002419 synchronized (mObbMounts) {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002420 state = mObbPathToStateMap.get(rawPath);
2421 }
2422 if (state == null) {
2423 Slog.w(TAG, "Failed to find OBB mounted at " + rawPath);
2424 return null;
2425 }
2426
Jeff Sharkey54402792017-09-15 16:05:19 -06002427 return findVolumeByIdOrThrow(state.volId).getPath().getAbsolutePath();
Kenny Root02c87302010-07-01 08:10:18 -07002428 }
2429
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002430 @Override
2431 public boolean isObbMounted(String rawPath) {
2432 Preconditions.checkNotNull(rawPath, "rawPath cannot be null");
Kenny Rootaf9d6672010-10-08 09:21:39 -07002433 synchronized (mObbMounts) {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002434 return mObbPathToStateMap.containsKey(rawPath);
Kenny Rootaf9d6672010-10-08 09:21:39 -07002435 }
Kenny Root02c87302010-07-01 08:10:18 -07002436 }
2437
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002438 @Override
Sudheer Shanka25469aa2018-08-27 15:50:23 -07002439 public void mountObb(String rawPath, String canonicalPath, String key,
2440 IObbActionListener token, int nonce, ObbInfo obbInfo) {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002441 Preconditions.checkNotNull(rawPath, "rawPath cannot be null");
2442 Preconditions.checkNotNull(canonicalPath, "canonicalPath cannot be null");
2443 Preconditions.checkNotNull(token, "token cannot be null");
Sudheer Shanka25469aa2018-08-27 15:50:23 -07002444 Preconditions.checkNotNull(obbInfo, "obbIfno cannot be null");
Kenny Rootaf9d6672010-10-08 09:21:39 -07002445
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002446 final int callingUid = Binder.getCallingUid();
Jeff Sharkey41cd6812017-09-11 10:32:17 -06002447 final ObbState obbState = new ObbState(rawPath, canonicalPath,
2448 callingUid, token, nonce, null);
Sudheer Shanka25469aa2018-08-27 15:50:23 -07002449 final ObbAction action = new MountObbAction(obbState, key, callingUid, obbInfo);
Kenny Roota02b8b02010-08-05 16:14:17 -07002450 mObbActionHandler.sendMessage(mObbActionHandler.obtainMessage(OBB_RUN_ACTION, action));
2451
2452 if (DEBUG_OBB)
2453 Slog.i(TAG, "Send to OBB handler: " + action.toString());
Kenny Root02c87302010-07-01 08:10:18 -07002454 }
2455
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002456 @Override
2457 public void unmountObb(String rawPath, boolean force, IObbActionListener token, int nonce) {
2458 Preconditions.checkNotNull(rawPath, "rawPath cannot be null");
2459
2460 final ObbState existingState;
Rubin Xucd7a0142015-04-17 23:45:27 +01002461 synchronized (mObbMounts) {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002462 existingState = mObbPathToStateMap.get(rawPath);
Kenny Rootf1121dc2010-09-29 07:30:53 -07002463 }
2464
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002465 if (existingState != null) {
2466 // TODO: separate state object from request data
2467 final int callingUid = Binder.getCallingUid();
Jeff Sharkey41cd6812017-09-11 10:32:17 -06002468 final ObbState newState = new ObbState(rawPath, existingState.canonicalPath,
2469 callingUid, token, nonce, existingState.volId);
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002470 final ObbAction action = new UnmountObbAction(newState, force);
2471 mObbActionHandler.sendMessage(mObbActionHandler.obtainMessage(OBB_RUN_ACTION, action));
Kenny Root02c87302010-07-01 08:10:18 -07002472
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002473 if (DEBUG_OBB)
2474 Slog.i(TAG, "Send to OBB handler: " + action.toString());
2475 } else {
2476 Slog.w(TAG, "Unknown OBB mount at " + rawPath);
2477 }
Kenny Roota02b8b02010-08-05 16:14:17 -07002478 }
2479
Ben Komalo444eca22011-09-01 15:17:44 -07002480 @Override
2481 public int getEncryptionState() {
2482 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
2483 "no permission to access the crypt keeper");
2484
Ben Komalo444eca22011-09-01 15:17:44 -07002485 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002486 return mVold.fdeComplete();
2487 } catch (Exception e) {
2488 Slog.wtf(TAG, e);
Sudheer Shankaf7341142016-10-18 17:15:18 -07002489 return StorageManager.ENCRYPTION_STATE_ERROR_UNKNOWN;
Ben Komalo444eca22011-09-01 15:17:44 -07002490 }
2491 }
2492
2493 @Override
Jason parks5af0b912010-11-29 09:05:25 -06002494 public int decryptStorage(String password) {
Jason parks8888c592011-01-20 22:46:41 -06002495 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
2496 "no permission to access the crypt keeper");
Jason parks5af0b912010-11-29 09:05:25 -06002497
Jeff Sharkey8058fe62017-09-13 11:50:33 -06002498 if (TextUtils.isEmpty(password)) {
2499 throw new IllegalArgumentException("password cannot be empty");
2500 }
2501
Jason parks5af0b912010-11-29 09:05:25 -06002502 if (DEBUG_EVENTS) {
2503 Slog.i(TAG, "decrypting storage...");
2504 }
2505
2506 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002507 mVold.fdeCheckPassword(password);
2508 mHandler.postDelayed(() -> {
2509 try {
2510 mVold.fdeRestart();
2511 } catch (Exception e) {
2512 Slog.wtf(TAG, e);
2513 }
2514 }, DateUtils.SECOND_IN_MILLIS);
2515 return 0;
Paul Crowleyfc0b5192018-07-02 13:58:10 -07002516 } catch (ServiceSpecificException e) {
2517 Slog.e(TAG, "fdeCheckPassword failed", e);
2518 return e.errorCode;
Jeff Sharkey54402792017-09-15 16:05:19 -06002519 } catch (Exception e) {
2520 Slog.wtf(TAG, e);
2521 return StorageManager.ENCRYPTION_STATE_ERROR_UNKNOWN;
Jason parks5af0b912010-11-29 09:05:25 -06002522 }
Jason parks5af0b912010-11-29 09:05:25 -06002523 }
2524
Jeff Sharkey54402792017-09-15 16:05:19 -06002525 @Override
Paul Lawrence46791e72014-04-03 09:10:26 -07002526 public int encryptStorage(int type, String password) {
Jason parks8888c592011-01-20 22:46:41 -06002527 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
2528 "no permission to access the crypt keeper");
Jason parks56aa5322011-01-07 09:01:15 -06002529
Jeff Sharkey8058fe62017-09-13 11:50:33 -06002530 if (type == StorageManager.CRYPT_TYPE_DEFAULT) {
2531 password = "";
2532 } else if (TextUtils.isEmpty(password)) {
2533 throw new IllegalArgumentException("password cannot be empty");
2534 }
2535
Jason parks56aa5322011-01-07 09:01:15 -06002536 if (DEBUG_EVENTS) {
Jason parks8888c592011-01-20 22:46:41 -06002537 Slog.i(TAG, "encrypting storage...");
Jason parks56aa5322011-01-07 09:01:15 -06002538 }
2539
2540 try {
Paul Lawrence89a0ae42017-12-22 10:11:10 -08002541 mVold.fdeEnable(type, password, 0);
Jeff Sharkey43e12112017-09-12 16:31:45 -06002542 } catch (Exception e) {
2543 Slog.wtf(TAG, e);
2544 return -1;
Jason parks56aa5322011-01-07 09:01:15 -06002545 }
2546
2547 return 0;
2548 }
2549
Paul Lawrence8e397362014-01-27 15:22:30 -08002550 /** Set the password for encrypting the master key.
2551 * @param type One of the CRYPTO_TYPE_XXX consts defined in StorageManager.
2552 * @param password The password to set.
2553 */
Jeff Sharkey54402792017-09-15 16:05:19 -06002554 @Override
Paul Lawrence8e397362014-01-27 15:22:30 -08002555 public int changeEncryptionPassword(int type, String password) {
Jason parksf7b3cd42011-01-27 09:28:25 -06002556 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
2557 "no permission to access the crypt keeper");
2558
Jeff Sharkeyae266462017-11-27 13:32:24 -07002559 if (StorageManager.isFileEncryptedNativeOnly()) {
2560 // Not supported on FBE devices
2561 return -1;
2562 }
2563
Jeff Sharkey8058fe62017-09-13 11:50:33 -06002564 if (type == StorageManager.CRYPT_TYPE_DEFAULT) {
2565 password = "";
2566 } else if (TextUtils.isEmpty(password)) {
2567 throw new IllegalArgumentException("password cannot be empty");
2568 }
2569
Jason parksf7b3cd42011-01-27 09:28:25 -06002570 if (DEBUG_EVENTS) {
2571 Slog.i(TAG, "changing encryption password...");
2572 }
2573
2574 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002575 mVold.fdeChangePassword(type, password);
2576 return 0;
2577 } catch (Exception e) {
2578 Slog.wtf(TAG, e);
2579 return -1;
Jason parksf7b3cd42011-01-27 09:28:25 -06002580 }
2581 }
2582
Christopher Tate32418be2011-10-10 13:51:12 -07002583 /**
2584 * Validate a user-supplied password string with cryptfs
2585 */
2586 @Override
2587 public int verifyEncryptionPassword(String password) throws RemoteException {
2588 // Only the system process is permitted to validate passwords
2589 if (Binder.getCallingUid() != android.os.Process.SYSTEM_UID) {
2590 throw new SecurityException("no permission to access the crypt keeper");
2591 }
2592
2593 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
2594 "no permission to access the crypt keeper");
2595
2596 if (TextUtils.isEmpty(password)) {
2597 throw new IllegalArgumentException("password cannot be empty");
2598 }
2599
Christopher Tate32418be2011-10-10 13:51:12 -07002600 if (DEBUG_EVENTS) {
2601 Slog.i(TAG, "validating encryption password...");
2602 }
2603
2604 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002605 mVold.fdeVerifyPassword(password);
2606 return 0;
2607 } catch (Exception e) {
2608 Slog.wtf(TAG, e);
2609 return -1;
Christopher Tate32418be2011-10-10 13:51:12 -07002610 }
2611 }
2612
Paul Lawrence8e397362014-01-27 15:22:30 -08002613 /**
2614 * Get the type of encryption used to encrypt the master key.
2615 * @return The type, one of the CRYPT_TYPE_XXX consts from StorageManager.
2616 */
2617 @Override
Svetoslav16e4a1a2014-09-29 18:16:20 -07002618 public int getPasswordType() {
Paul Lawrence76a40572017-03-15 11:08:04 -07002619 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
Paul Lawrence9de713d2016-05-02 22:45:33 +00002620 "no permission to access the crypt keeper");
2621
Paul Lawrence8e397362014-01-27 15:22:30 -08002622 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002623 return mVold.fdeGetPasswordType();
2624 } catch (Exception e) {
2625 Slog.wtf(TAG, e);
2626 return -1;
Paul Lawrence8e397362014-01-27 15:22:30 -08002627 }
2628 }
2629
Paul Lawrencee51dcf92014-03-18 10:56:00 -07002630 /**
2631 * Set a field in the crypto header.
2632 * @param field field to set
2633 * @param contents contents to set in field
2634 */
2635 @Override
2636 public void setField(String field, String contents) throws RemoteException {
Paul Lawrence76a40572017-03-15 11:08:04 -07002637 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
Paul Lawrence0bbd1082016-04-26 15:21:02 -07002638 "no permission to access the crypt keeper");
Paul Lawrencee51dcf92014-03-18 10:56:00 -07002639
Jeff Sharkeyae266462017-11-27 13:32:24 -07002640 if (StorageManager.isFileEncryptedNativeOnly()) {
2641 // Not supported on FBE devices
2642 return;
2643 }
2644
Paul Lawrencee51dcf92014-03-18 10:56:00 -07002645 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002646 mVold.fdeSetField(field, contents);
2647 return;
2648 } catch (Exception e) {
2649 Slog.wtf(TAG, e);
2650 return;
Paul Lawrencee51dcf92014-03-18 10:56:00 -07002651 }
2652 }
2653
2654 /**
2655 * Gets a field from the crypto header.
2656 * @param field field to get
2657 * @return contents of field
2658 */
2659 @Override
2660 public String getField(String field) throws RemoteException {
Paul Lawrence76a40572017-03-15 11:08:04 -07002661 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
Paul Lawrence0bbd1082016-04-26 15:21:02 -07002662 "no permission to access the crypt keeper");
Paul Lawrencee51dcf92014-03-18 10:56:00 -07002663
Jeff Sharkeyae266462017-11-27 13:32:24 -07002664 if (StorageManager.isFileEncryptedNativeOnly()) {
2665 // Not supported on FBE devices
2666 return null;
2667 }
2668
Paul Lawrencee51dcf92014-03-18 10:56:00 -07002669 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002670 return mVold.fdeGetField(field);
2671 } catch (Exception e) {
2672 Slog.wtf(TAG, e);
2673 return null;
Paul Lawrencee51dcf92014-03-18 10:56:00 -07002674 }
2675 }
2676
Paul Lawrence3806d9c2015-10-29 10:30:46 -07002677 /**
2678 * Is userdata convertible to file based encryption?
2679 * @return non zero for convertible
2680 */
2681 @Override
2682 public boolean isConvertibleToFBE() throws RemoteException {
Paul Lawrence76a40572017-03-15 11:08:04 -07002683 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
Paul Lawrence0bbd1082016-04-26 15:21:02 -07002684 "no permission to access the crypt keeper");
Paul Lawrence3806d9c2015-10-29 10:30:46 -07002685
Paul Lawrence3806d9c2015-10-29 10:30:46 -07002686 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002687 return mVold.isConvertibleToFbe();
2688 } catch (Exception e) {
2689 Slog.wtf(TAG, e);
2690 return false;
Paul Lawrence3806d9c2015-10-29 10:30:46 -07002691 }
2692 }
2693
Daniel Rosenberge129e5c2018-11-07 19:25:55 -08002694 /**
2695 * Signal that checkpointing partitions should commit changes
2696 */
2697 @Override
2698 public void commitChanges() throws RemoteException {
2699 // Only the system process is permitted to commit checkpoints
2700 if (Binder.getCallingUid() != android.os.Process.SYSTEM_UID) {
2701 throw new SecurityException("no permission to commit checkpoint changes");
2702 }
2703
2704 mVold.commitChanges();
2705 }
2706
Jeff Sharkeyb049e212012-09-07 23:16:01 -07002707 @Override
Paul Lawrence945490c2014-03-27 16:37:28 +00002708 public String getPassword() throws RemoteException {
Paul Lawrence76a40572017-03-15 11:08:04 -07002709 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
Rubin Xucd7a0142015-04-17 23:45:27 +01002710 "only keyguard can retrieve password");
Paul Lawrence0bbd1082016-04-26 15:21:02 -07002711
Paul Lawrence945490c2014-03-27 16:37:28 +00002712 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002713 return mVold.fdeGetPassword();
2714 } catch (Exception e) {
2715 Slog.wtf(TAG, e);
Paul Lawrence24063b52015-01-06 13:11:23 -08002716 return null;
Paul Lawrence945490c2014-03-27 16:37:28 +00002717 }
2718 }
2719
2720 @Override
2721 public void clearPassword() throws RemoteException {
Paul Lawrence76a40572017-03-15 11:08:04 -07002722 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
Paul Lawrence0bbd1082016-04-26 15:21:02 -07002723 "only keyguard can clear password");
2724
Paul Lawrence945490c2014-03-27 16:37:28 +00002725 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002726 mVold.fdeClearPassword();
2727 return;
2728 } catch (Exception e) {
2729 Slog.wtf(TAG, e);
2730 return;
Paul Lawrence945490c2014-03-27 16:37:28 +00002731 }
2732 }
2733
2734 @Override
Lenka Trochtovac4dd0212015-11-18 12:22:06 +01002735 public void createUserKey(int userId, int serialNumber, boolean ephemeral) {
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002736 enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
Paul Crowleybcf48ed2015-04-22 13:36:59 +01002737
Paul Crowleybcf48ed2015-04-22 13:36:59 +01002738 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002739 mVold.createUserKey(userId, serialNumber, ephemeral);
Jeff Sharkey43e12112017-09-12 16:31:45 -06002740 } catch (Exception e) {
2741 Slog.wtf(TAG, e);
Paul Crowleybcf48ed2015-04-22 13:36:59 +01002742 }
2743 }
2744
Paul Crowley7ec733f2015-05-19 12:42:00 +01002745 @Override
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002746 public void destroyUserKey(int userId) {
2747 enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
Paul Crowley7ec733f2015-05-19 12:42:00 +01002748
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002749 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002750 mVold.destroyUserKey(userId);
Jeff Sharkey43e12112017-09-12 16:31:45 -06002751 } catch (Exception e) {
2752 Slog.wtf(TAG, e);
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002753 }
2754 }
2755
Jeff Sharkey43e12112017-09-12 16:31:45 -06002756 private String encodeBytes(byte[] bytes) {
Paul Crowleyfaeb3eb2016-02-08 15:58:29 +00002757 if (ArrayUtils.isEmpty(bytes)) {
Jeff Sharkey43e12112017-09-12 16:31:45 -06002758 return "!";
Paul Crowleyfaeb3eb2016-02-08 15:58:29 +00002759 } else {
Jeff Sharkey43e12112017-09-12 16:31:45 -06002760 return HexDump.toHexString(bytes);
Paul Crowleyfaeb3eb2016-02-08 15:58:29 +00002761 }
2762 }
2763
Paul Crowleycc701552016-05-17 14:18:49 -07002764 /*
2765 * Add this token/secret pair to the set of ways we can recover a disk encryption key.
2766 * Changing the token/secret for a disk encryption key is done in two phases: first, adding
2767 * a new token/secret pair with this call, then delting all other pairs with
2768 * fixateNewestUserKeyAuth. This allows other places where a credential is used, such as
2769 * Gatekeeper, to be updated between the two calls.
2770 */
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002771 @Override
Paul Crowleycc701552016-05-17 14:18:49 -07002772 public void addUserKeyAuth(int userId, int serialNumber, byte[] token, byte[] secret) {
Paul Crowleyfaeb3eb2016-02-08 15:58:29 +00002773 enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
Paul Crowleyfaeb3eb2016-02-08 15:58:29 +00002774
2775 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002776 mVold.addUserKeyAuth(userId, serialNumber, encodeBytes(token), encodeBytes(secret));
Jeff Sharkey43e12112017-09-12 16:31:45 -06002777 } catch (Exception e) {
2778 Slog.wtf(TAG, e);
Paul Crowleycc701552016-05-17 14:18:49 -07002779 }
2780 }
2781
2782 /*
2783 * Delete all disk encryption token/secret pairs except the most recently added one
2784 */
2785 @Override
2786 public void fixateNewestUserKeyAuth(int userId) {
2787 enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
Paul Crowleycc701552016-05-17 14:18:49 -07002788
2789 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002790 mVold.fixateNewestUserKeyAuth(userId);
Jeff Sharkey43e12112017-09-12 16:31:45 -06002791 } catch (Exception e) {
2792 Slog.wtf(TAG, e);
Paul Crowleyfaeb3eb2016-02-08 15:58:29 +00002793 }
2794 }
2795
2796 @Override
2797 public void unlockUserKey(int userId, int serialNumber, byte[] token, byte[] secret) {
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002798 enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002799
Jeff Sharkeyce18c812016-04-27 16:00:41 -06002800 if (StorageManager.isFileEncryptedNativeOrEmulated()) {
Rubin Xu3bf722a2016-12-15 16:07:38 +00002801 // When a user has secure lock screen, require secret to actually unlock.
2802 // This check is mostly in place for emulation mode.
2803 if (mLockPatternUtils.isSecure(userId) && ArrayUtils.isEmpty(secret)) {
2804 throw new IllegalStateException("Secret required to unlock secure user " + userId);
Jeff Sharkeyce18c812016-04-27 16:00:41 -06002805 }
Jeff Sharkeyb9fe5372015-12-03 15:23:08 -07002806
Jeff Sharkeyce18c812016-04-27 16:00:41 -06002807 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002808 mVold.unlockUserKey(userId, serialNumber, encodeBytes(token),
2809 encodeBytes(secret));
Jeff Sharkey43e12112017-09-12 16:31:45 -06002810 } catch (Exception e) {
2811 Slog.wtf(TAG, e);
2812 return;
Jeff Sharkeyce18c812016-04-27 16:00:41 -06002813 }
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002814 }
2815
2816 synchronized (mLock) {
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07002817 mLocalUnlockedUsers = ArrayUtils.appendInt(mLocalUnlockedUsers, userId);
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002818 }
2819 }
2820
2821 @Override
2822 public void lockUserKey(int userId) {
2823 enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002824
2825 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002826 mVold.lockUserKey(userId);
Jeff Sharkey43e12112017-09-12 16:31:45 -06002827 } catch (Exception e) {
2828 Slog.wtf(TAG, e);
2829 return;
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002830 }
2831
2832 synchronized (mLock) {
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07002833 mLocalUnlockedUsers = ArrayUtils.removeInt(mLocalUnlockedUsers, userId);
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002834 }
2835 }
2836
2837 @Override
2838 public boolean isUserKeyUnlocked(int userId) {
Jeff Sharkeyce18c812016-04-27 16:00:41 -06002839 synchronized (mLock) {
2840 return ArrayUtils.contains(mLocalUnlockedUsers, userId);
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002841 }
2842 }
2843
2844 @Override
Jeff Sharkey47f71082016-02-01 17:03:54 -07002845 public void prepareUserStorage(String volumeUuid, int userId, int serialNumber, int flags) {
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002846 enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002847
2848 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002849 mVold.prepareUserStorage(volumeUuid, userId, serialNumber, flags);
Jeff Sharkey43e12112017-09-12 16:31:45 -06002850 } catch (Exception e) {
2851 Slog.wtf(TAG, e);
Paul Crowley7ec733f2015-05-19 12:42:00 +01002852 }
2853 }
2854
Paul Crowleybcf48ed2015-04-22 13:36:59 +01002855 @Override
Jeff Sharkeyfcf1e552016-04-14 20:44:58 -06002856 public void destroyUserStorage(String volumeUuid, int userId, int flags) {
2857 enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
Jeff Sharkeyfcf1e552016-04-14 20:44:58 -06002858
2859 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002860 mVold.destroyUserStorage(volumeUuid, userId, flags);
Jeff Sharkey43e12112017-09-12 16:31:45 -06002861 } catch (Exception e) {
2862 Slog.wtf(TAG, e);
Jeff Sharkeyfcf1e552016-04-14 20:44:58 -06002863 }
2864 }
2865
Daichi Hironoe56740d2017-02-02 13:56:45 +09002866 class AppFuseMountScope extends AppFuseBridge.MountScope {
Daichi Hirono812c95d2017-02-08 16:20:20 +09002867 boolean opened = false;
2868
Ryo Hashimoto38bcbf02018-05-16 18:20:37 +09002869 public AppFuseMountScope(int uid, int mountId) {
2870 super(uid, mountId);
Daichi Hirono812c95d2017-02-08 16:20:20 +09002871 }
2872
2873 @Override
2874 public ParcelFileDescriptor open() throws NativeDaemonConnectorException {
Jeff Sharkey54402792017-09-15 16:05:19 -06002875 try {
2876 return new ParcelFileDescriptor(
Ryo Hashimoto38bcbf02018-05-16 18:20:37 +09002877 mVold.mountAppFuse(uid, mountId));
Jeff Sharkey54402792017-09-15 16:05:19 -06002878 } catch (Exception e) {
2879 throw new NativeDaemonConnectorException("Failed to mount", e);
Daichi Hirono812c95d2017-02-08 16:20:20 +09002880 }
Daichi Hirono9fb00182016-11-08 14:12:17 +09002881 }
2882
2883 @Override
Ryo Hashimoto38bcbf02018-05-16 18:20:37 +09002884 public ParcelFileDescriptor openFile(int mountId, int fileId, int flags)
2885 throws NativeDaemonConnectorException {
2886 try {
2887 return new ParcelFileDescriptor(
2888 mVold.openAppFuseFile(uid, mountId, fileId, flags));
2889 } catch (Exception e) {
2890 throw new NativeDaemonConnectorException("Failed to open", e);
2891 }
2892 }
2893
2894 @Override
Daichi Hironoe56740d2017-02-02 13:56:45 +09002895 public void close() throws Exception {
Daichi Hirono812c95d2017-02-08 16:20:20 +09002896 if (opened) {
Ryo Hashimoto38bcbf02018-05-16 18:20:37 +09002897 mVold.unmountAppFuse(uid, mountId);
Daichi Hirono812c95d2017-02-08 16:20:20 +09002898 opened = false;
2899 }
Daichi Hirono9fb00182016-11-08 14:12:17 +09002900 }
2901 }
2902
2903 @Override
Daichi Hirono812c95d2017-02-08 16:20:20 +09002904 public @Nullable AppFuseMount mountProxyFileDescriptorBridge() {
Daichi Hironoe56740d2017-02-02 13:56:45 +09002905 Slog.v(TAG, "mountProxyFileDescriptorBridge");
Daichi Hirono9fb00182016-11-08 14:12:17 +09002906 final int uid = Binder.getCallingUid();
Daichi Hirono9fb00182016-11-08 14:12:17 +09002907
Daichi Hironoe56740d2017-02-02 13:56:45 +09002908 while (true) {
2909 synchronized (mAppFuseLock) {
2910 boolean newlyCreated = false;
2911 if (mAppFuseBridge == null) {
2912 mAppFuseBridge = new AppFuseBridge();
2913 new Thread(mAppFuseBridge, AppFuseBridge.TAG).start();
2914 newlyCreated = true;
Daichi Hirono9fb00182016-11-08 14:12:17 +09002915 }
Daichi Hironoe56740d2017-02-02 13:56:45 +09002916 try {
2917 final int name = mNextAppFuseName++;
2918 try {
2919 return new AppFuseMount(
Ryo Hashimoto38bcbf02018-05-16 18:20:37 +09002920 name, mAppFuseBridge.addBridge(new AppFuseMountScope(uid, name)));
Daichi Hirono812c95d2017-02-08 16:20:20 +09002921 } catch (FuseUnavailableMountException e) {
Daichi Hironoe56740d2017-02-02 13:56:45 +09002922 if (newlyCreated) {
2923 // If newly created bridge fails, it's a real error.
Daichi Hirono812c95d2017-02-08 16:20:20 +09002924 Slog.e(TAG, "", e);
2925 return null;
Daichi Hironoe56740d2017-02-02 13:56:45 +09002926 }
2927 // It seems the thread of mAppFuseBridge has already been terminated.
2928 mAppFuseBridge = null;
2929 }
2930 } catch (NativeDaemonConnectorException e) {
2931 throw e.rethrowAsParcelableException();
2932 }
Daichi Hirono9fb00182016-11-08 14:12:17 +09002933 }
Daichi Hirono9fb00182016-11-08 14:12:17 +09002934 }
2935 }
2936
2937 @Override
Daichi Hirono812c95d2017-02-08 16:20:20 +09002938 public @Nullable ParcelFileDescriptor openProxyFileDescriptor(
2939 int mountId, int fileId, int mode) {
2940 Slog.v(TAG, "mountProxyFileDescriptor");
Jeff Sharkey39466322018-12-05 19:19:52 -07002941
2942 // We only support a narrow set of incoming mode flags
Jeff Sharkey3b1c2542018-12-13 15:01:38 -07002943 mode &= MODE_READ_WRITE;
Jeff Sharkey39466322018-12-05 19:19:52 -07002944
Daichi Hirono9fb00182016-11-08 14:12:17 +09002945 try {
2946 synchronized (mAppFuseLock) {
Daichi Hironoe56740d2017-02-02 13:56:45 +09002947 if (mAppFuseBridge == null) {
Daichi Hirono812c95d2017-02-08 16:20:20 +09002948 Slog.e(TAG, "FuseBridge has not been created");
2949 return null;
Daichi Hirono9fb00182016-11-08 14:12:17 +09002950 }
Ryo Hashimoto38bcbf02018-05-16 18:20:37 +09002951 return mAppFuseBridge.openFile(mountId, fileId, mode);
Daichi Hirono9fb00182016-11-08 14:12:17 +09002952 }
Daichi Hirono812c95d2017-02-08 16:20:20 +09002953 } catch (FuseUnavailableMountException | InterruptedException error) {
2954 Slog.v(TAG, "The mount point has already been invalid", error);
2955 return null;
Daichi Hirono9fb00182016-11-08 14:12:17 +09002956 }
2957 }
2958
Daichi Hirono9e8d9e22015-11-13 14:37:00 +09002959 @Override
Jeff Sharkeyae266462017-11-27 13:32:24 -07002960 public void mkdirs(String callingPkg, String appPath) {
Jeff Sharkey2d8b4e82013-09-17 17:30:33 -07002961 final int userId = UserHandle.getUserId(Binder.getCallingUid());
2962 final UserEnvironment userEnv = new UserEnvironment(userId);
Farid Zare Seisanac094512018-04-02 15:06:13 -07002963 final String propertyName = "sys.user." + userId + ".ce_available";
Jeff Sharkey2d8b4e82013-09-17 17:30:33 -07002964
Jeff Sharkey196c7552018-03-26 15:56:50 -06002965 // Ignore requests to create directories while storage is locked
Farid Zare Seisanac094512018-04-02 15:06:13 -07002966 if (!isUserKeyUnlocked(userId)) {
2967 throw new IllegalStateException("Failed to prepare " + appPath);
2968 }
2969
2970 // Ignore requests to create directories if CE storage is not available
Farid Zare Seisan7f6b8122018-03-30 11:19:10 -07002971 if ((userId == UserHandle.USER_SYSTEM)
2972 && !SystemProperties.getBoolean(propertyName, false)) {
Farid Zare Seisanac094512018-04-02 15:06:13 -07002973 throw new IllegalStateException("Failed to prepare " + appPath);
2974 }
Jeff Sharkey196c7552018-03-26 15:56:50 -06002975
Jeff Sharkey2d8b4e82013-09-17 17:30:33 -07002976 // Validate that reported package name belongs to caller
2977 final AppOpsManager appOps = (AppOpsManager) mContext.getSystemService(
2978 Context.APP_OPS_SERVICE);
2979 appOps.checkPackage(Binder.getCallingUid(), callingPkg);
2980
Jeff Sharkey48877892015-03-18 11:27:19 -07002981 File appFile = null;
Jeff Sharkey2d8b4e82013-09-17 17:30:33 -07002982 try {
Jeff Sharkey48877892015-03-18 11:27:19 -07002983 appFile = new File(appPath).getCanonicalFile();
Jeff Sharkey2d8b4e82013-09-17 17:30:33 -07002984 } catch (IOException e) {
Jeff Sharkeyae266462017-11-27 13:32:24 -07002985 throw new IllegalStateException("Failed to resolve " + appPath + ": " + e);
Jeff Sharkey2d8b4e82013-09-17 17:30:33 -07002986 }
2987
2988 // Try translating the app path into a vold path, but require that it
2989 // belong to the calling package.
Jeff Sharkey48877892015-03-18 11:27:19 -07002990 if (FileUtils.contains(userEnv.buildExternalStorageAppDataDirs(callingPkg), appFile) ||
2991 FileUtils.contains(userEnv.buildExternalStorageAppObbDirs(callingPkg), appFile) ||
2992 FileUtils.contains(userEnv.buildExternalStorageAppMediaDirs(callingPkg), appFile)) {
2993 appPath = appFile.getAbsolutePath();
2994 if (!appPath.endsWith("/")) {
2995 appPath = appPath + "/";
2996 }
2997
Jeff Sharkey2d8b4e82013-09-17 17:30:33 -07002998 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002999 mVold.mkdirs(appPath);
Jeff Sharkey27a108c2017-11-30 17:11:40 -07003000 return;
Jeff Sharkeyace874b2017-09-07 15:27:33 -06003001 } catch (Exception e) {
Jeff Sharkeyae266462017-11-27 13:32:24 -07003002 throw new IllegalStateException("Failed to prepare " + appPath + ": " + e);
Jeff Sharkey2d8b4e82013-09-17 17:30:33 -07003003 }
3004 }
3005
Jeff Sharkey48877892015-03-18 11:27:19 -07003006 throw new SecurityException("Invalid mkdirs path: " + appFile);
Jeff Sharkey2d8b4e82013-09-17 17:30:33 -07003007 }
3008
3009 @Override
Jeff Sharkey46349872015-07-28 10:49:47 -07003010 public StorageVolume[] getVolumeList(int uid, String packageName, int flags) {
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07003011 final int userId = UserHandle.getUserId(uid);
Jeff Sharkeyc02bfae2016-03-27 15:06:53 -06003012
Jeff Sharkey46349872015-07-28 10:49:47 -07003013 final boolean forWrite = (flags & StorageManager.FLAG_FOR_WRITE) != 0;
Jeff Sharkeyc02bfae2016-03-27 15:06:53 -06003014 final boolean realState = (flags & StorageManager.FLAG_REAL_STATE) != 0;
3015 final boolean includeInvisible = (flags & StorageManager.FLAG_INCLUDE_INVISIBLE) != 0;
Jeff Sharkey46349872015-07-28 10:49:47 -07003016
Jeff Sharkeyc02bfae2016-03-27 15:06:53 -06003017 final boolean userKeyUnlocked;
3018 final boolean storagePermission;
3019 final long token = Binder.clearCallingIdentity();
Svetoslav38c3dbb2015-07-14 11:27:06 -07003020 try {
Jeff Sharkeyc02bfae2016-03-27 15:06:53 -06003021 userKeyUnlocked = isUserKeyUnlocked(userId);
Sudheer Shanka2250d562016-11-07 15:41:02 -08003022 storagePermission = mStorageManagerInternal.hasExternalStorage(uid, packageName);
Svetoslav38c3dbb2015-07-14 11:27:06 -07003023 } finally {
Jeff Sharkeyc02bfae2016-03-27 15:06:53 -06003024 Binder.restoreCallingIdentity(token);
Svetoslav38c3dbb2015-07-14 11:27:06 -07003025 }
Svet Ganov6ee871e2015-07-10 14:29:33 -07003026
Jeff Sharkeyc02bfae2016-03-27 15:06:53 -06003027 boolean foundPrimary = false;
3028
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07003029 final ArrayList<StorageVolume> res = new ArrayList<>();
Jeff Sharkey48877892015-03-18 11:27:19 -07003030 synchronized (mLock) {
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07003031 for (int i = 0; i < mVolumes.size(); i++) {
3032 final VolumeInfo vol = mVolumes.valueAt(i);
Jeff Sharkeyc02bfae2016-03-27 15:06:53 -06003033 switch (vol.getType()) {
3034 case VolumeInfo.TYPE_PUBLIC:
Risan05c41e62018-10-29 08:57:43 +09003035 case VolumeInfo.TYPE_STUB:
Jeff Sharkeyc02bfae2016-03-27 15:06:53 -06003036 case VolumeInfo.TYPE_EMULATED:
3037 break;
3038 default:
3039 continue;
3040 }
3041
3042 boolean match = false;
3043 if (forWrite) {
3044 match = vol.isVisibleForWrite(userId);
3045 } else {
Felipe Leme123a0e72016-06-10 11:09:11 -07003046 match = vol.isVisibleForRead(userId)
3047 || (includeInvisible && vol.getPath() != null);
Jeff Sharkeyc02bfae2016-03-27 15:06:53 -06003048 }
3049 if (!match) continue;
3050
3051 boolean reportUnmounted = false;
3052 if ((vol.getType() == VolumeInfo.TYPE_EMULATED) && !userKeyUnlocked) {
3053 reportUnmounted = true;
3054 } else if (!storagePermission && !realState) {
3055 reportUnmounted = true;
3056 }
3057
3058 final StorageVolume userVol = vol.buildStorageVolume(mContext, userId,
3059 reportUnmounted);
3060 if (vol.isPrimary()) {
3061 res.add(0, userVol);
3062 foundPrimary = true;
3063 } else {
3064 res.add(userVol);
Jeff Sharkeyb049e212012-09-07 23:16:01 -07003065 }
Mike Lockwood8fa5f802011-03-24 08:12:30 -07003066 }
Mike Lockwood8fa5f802011-03-24 08:12:30 -07003067 }
Jeff Sharkey48877892015-03-18 11:27:19 -07003068
3069 if (!foundPrimary) {
Jeff Sharkey11697f52018-12-13 10:14:42 -07003070 Slog.w(TAG, "No primary storage defined yet; hacking together a stub");
Jeff Sharkey48877892015-03-18 11:27:19 -07003071
3072 final boolean primaryPhysical = SystemProperties.getBoolean(
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07003073 StorageManager.PROP_PRIMARY_PHYSICAL, false);
Jeff Sharkey48877892015-03-18 11:27:19 -07003074
3075 final String id = "stub_primary";
3076 final File path = Environment.getLegacyExternalStorageDirectory();
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07003077 final String description = mContext.getString(android.R.string.unknownName);
Jeff Sharkey48877892015-03-18 11:27:19 -07003078 final boolean primary = true;
3079 final boolean removable = primaryPhysical;
3080 final boolean emulated = !primaryPhysical;
Jeff Sharkey48877892015-03-18 11:27:19 -07003081 final boolean allowMassStorage = false;
3082 final long maxFileSize = 0L;
3083 final UserHandle owner = new UserHandle(userId);
3084 final String uuid = null;
Jeff Sharkey48877892015-03-18 11:27:19 -07003085 final String state = Environment.MEDIA_REMOVED;
3086
Jerry Zhang71938e12018-05-10 18:28:29 -07003087 res.add(0, new StorageVolume(id, path, path,
Jerry Zhangf9c5c252017-08-16 18:07:51 -07003088 description, primary, removable, emulated,
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07003089 allowMassStorage, maxFileSize, owner, uuid, state));
Jeff Sharkey48877892015-03-18 11:27:19 -07003090 }
3091
3092 return res.toArray(new StorageVolume[res.size()]);
Mike Lockwood8fa5f802011-03-24 08:12:30 -07003093 }
3094
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07003095 @Override
3096 public DiskInfo[] getDisks() {
3097 synchronized (mLock) {
3098 final DiskInfo[] res = new DiskInfo[mDisks.size()];
3099 for (int i = 0; i < mDisks.size(); i++) {
3100 res[i] = mDisks.valueAt(i);
3101 }
3102 return res;
3103 }
3104 }
3105
3106 @Override
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07003107 public VolumeInfo[] getVolumes(int flags) {
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07003108 synchronized (mLock) {
3109 final VolumeInfo[] res = new VolumeInfo[mVolumes.size()];
3110 for (int i = 0; i < mVolumes.size(); i++) {
3111 res[i] = mVolumes.valueAt(i);
3112 }
3113 return res;
3114 }
3115 }
3116
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07003117 @Override
3118 public VolumeRecord[] getVolumeRecords(int flags) {
3119 synchronized (mLock) {
3120 final VolumeRecord[] res = new VolumeRecord[mRecords.size()];
3121 for (int i = 0; i < mRecords.size(); i++) {
3122 res[i] = mRecords.valueAt(i);
3123 }
3124 return res;
3125 }
3126 }
3127
Jeff Sharkey9bed0702017-01-23 20:37:05 -07003128 @Override
3129 public long getCacheQuotaBytes(String volumeUuid, int uid) {
3130 if (uid != Binder.getCallingUid()) {
3131 mContext.enforceCallingPermission(android.Manifest.permission.STORAGE_INTERNAL, TAG);
3132 }
Daniel Nishi80fdb012017-03-09 14:30:07 -08003133 final long token = Binder.clearCallingIdentity();
3134 final StorageStatsManager stats = mContext.getSystemService(StorageStatsManager.class);
3135 try {
3136 return stats.getCacheQuotaBytes(volumeUuid, uid);
3137 } finally {
3138 Binder.restoreCallingIdentity(token);
3139 }
Jeff Sharkey9bed0702017-01-23 20:37:05 -07003140 }
3141
3142 @Override
3143 public long getCacheSizeBytes(String volumeUuid, int uid) {
3144 if (uid != Binder.getCallingUid()) {
3145 mContext.enforceCallingPermission(android.Manifest.permission.STORAGE_INTERNAL, TAG);
3146 }
3147 final long token = Binder.clearCallingIdentity();
3148 try {
3149 return mContext.getSystemService(StorageStatsManager.class)
3150 .queryStatsForUid(volumeUuid, uid).getCacheBytes();
Jeff Sharkey789a8fc2017-04-16 13:18:35 -06003151 } catch (IOException e) {
3152 throw new ParcelableException(e);
Jeff Sharkey9bed0702017-01-23 20:37:05 -07003153 } finally {
3154 Binder.restoreCallingIdentity(token);
3155 }
3156 }
3157
Jeff Sharkey35e46d22017-06-09 10:01:20 -06003158 private int adjustAllocateFlags(int flags, int callingUid, String callingPackage) {
3159 // Require permission to allocate aggressively
3160 if ((flags & StorageManager.FLAG_ALLOCATE_AGGRESSIVE) != 0) {
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07003161 mContext.enforceCallingOrSelfPermission(
3162 android.Manifest.permission.ALLOCATE_AGGRESSIVE, TAG);
3163 }
3164
Jeff Sharkey35e46d22017-06-09 10:01:20 -06003165 // Apps normally can't directly defy reserved space
3166 flags &= ~StorageManager.FLAG_ALLOCATE_DEFY_ALL_RESERVED;
3167 flags &= ~StorageManager.FLAG_ALLOCATE_DEFY_HALF_RESERVED;
3168
3169 // However, if app is actively using the camera, then we're willing to
3170 // clear up to half of the reserved cache space, since the user might be
3171 // trying to capture an important memory.
3172 final AppOpsManager appOps = mContext.getSystemService(AppOpsManager.class);
3173 final long token = Binder.clearCallingIdentity();
3174 try {
3175 if (appOps.isOperationActive(AppOpsManager.OP_CAMERA, callingUid, callingPackage)) {
3176 Slog.d(TAG, "UID " + callingUid + " is actively using camera;"
3177 + " letting them defy reserved cached data");
3178 flags |= StorageManager.FLAG_ALLOCATE_DEFY_HALF_RESERVED;
3179 }
3180 } finally {
3181 Binder.restoreCallingIdentity(token);
3182 }
3183
3184 return flags;
3185 }
3186
3187 @Override
3188 public long getAllocatableBytes(String volumeUuid, int flags, String callingPackage) {
3189 flags = adjustAllocateFlags(flags, Binder.getCallingUid(), callingPackage);
3190
3191 final StorageManager storage = mContext.getSystemService(StorageManager.class);
3192 final StorageStatsManager stats = mContext.getSystemService(StorageStatsManager.class);
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07003193 final long token = Binder.clearCallingIdentity();
3194 try {
3195 // In general, apps can allocate as much space as they want, except
3196 // we never let them eat into either the minimum cache space or into
Jeff Sharkeyddff8072017-05-26 13:10:46 -06003197 // the low disk warning space. To avoid user confusion, this logic
3198 // should be kept in sync with getFreeBytes().
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07003199 final File path = storage.findPathForUuid(volumeUuid);
Jeff Sharkeyddff8072017-05-26 13:10:46 -06003200
3201 final long usable = path.getUsableSpace();
3202 final long lowReserved = storage.getStorageLowBytes(path);
3203 final long fullReserved = storage.getStorageFullBytes(path);
3204
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07003205 if (stats.isQuotaSupported(volumeUuid)) {
Jeff Sharkeyddff8072017-05-26 13:10:46 -06003206 final long cacheTotal = stats.getCacheBytes(volumeUuid);
Jeff Sharkey35e46d22017-06-09 10:01:20 -06003207 final long cacheReserved = storage.getStorageCacheBytes(path, flags);
Jeff Sharkeyddff8072017-05-26 13:10:46 -06003208 final long cacheClearable = Math.max(0, cacheTotal - cacheReserved);
3209
Jeff Sharkey35e46d22017-06-09 10:01:20 -06003210 if ((flags & StorageManager.FLAG_ALLOCATE_AGGRESSIVE) != 0) {
3211 return Math.max(0, (usable + cacheClearable) - fullReserved);
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07003212 } else {
Jeff Sharkeyddff8072017-05-26 13:10:46 -06003213 return Math.max(0, (usable + cacheClearable) - lowReserved);
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07003214 }
3215 } else {
3216 // When we don't have fast quota information, we ignore cached
3217 // data and only consider unused bytes.
Jeff Sharkey35e46d22017-06-09 10:01:20 -06003218 if ((flags & StorageManager.FLAG_ALLOCATE_AGGRESSIVE) != 0) {
Jeff Sharkeyddff8072017-05-26 13:10:46 -06003219 return Math.max(0, usable - fullReserved);
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07003220 } else {
Jeff Sharkeyddff8072017-05-26 13:10:46 -06003221 return Math.max(0, usable - lowReserved);
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07003222 }
3223 }
Jeff Sharkey789a8fc2017-04-16 13:18:35 -06003224 } catch (IOException e) {
3225 throw new ParcelableException(e);
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07003226 } finally {
3227 Binder.restoreCallingIdentity(token);
3228 }
Jeff Sharkey500ce9e2017-02-12 02:39:24 -07003229 }
3230
3231 @Override
Jeff Sharkey35e46d22017-06-09 10:01:20 -06003232 public void allocateBytes(String volumeUuid, long bytes, int flags, String callingPackage) {
3233 flags = adjustAllocateFlags(flags, Binder.getCallingUid(), callingPackage);
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07003234
Jeff Sharkey35e46d22017-06-09 10:01:20 -06003235 final long allocatableBytes = getAllocatableBytes(volumeUuid, flags, callingPackage);
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07003236 if (bytes > allocatableBytes) {
3237 throw new ParcelableException(new IOException("Failed to allocate " + bytes
3238 + " because only " + allocatableBytes + " allocatable"));
3239 }
3240
Jeff Sharkey35e46d22017-06-09 10:01:20 -06003241 final StorageManager storage = mContext.getSystemService(StorageManager.class);
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07003242 final long token = Binder.clearCallingIdentity();
3243 try {
Jeff Sharkey789a8fc2017-04-16 13:18:35 -06003244 // Free up enough disk space to satisfy both the requested allocation
3245 // and our low disk warning space.
3246 final File path = storage.findPathForUuid(volumeUuid);
Jeff Sharkeyddff8072017-05-26 13:10:46 -06003247 if ((flags & StorageManager.FLAG_ALLOCATE_AGGRESSIVE) != 0) {
3248 bytes += storage.getStorageFullBytes(path);
3249 } else {
3250 bytes += storage.getStorageLowBytes(path);
3251 }
Jeff Sharkey789a8fc2017-04-16 13:18:35 -06003252
Jeff Sharkey5790af02018-08-13 17:42:54 -06003253 mPmInternal.freeStorage(volumeUuid, bytes, flags);
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07003254 } catch (IOException e) {
3255 throw new ParcelableException(e);
3256 } finally {
3257 Binder.restoreCallingIdentity(token);
Jeff Sharkey500ce9e2017-02-12 02:39:24 -07003258 }
3259 }
3260
Sudheer Shankaff971bc2018-12-13 17:39:59 -08003261 private IAppOpsCallback.Stub mAppOpsCallback = new IAppOpsCallback.Stub() {
3262 @Override
3263 public void opChanged(int op, int uid, String packageName) throws RemoteException {
3264 if (!ENABLE_ISOLATED_STORAGE) return;
3265
3266 remountUidExternalStorage(uid, getMountMode(uid, packageName));
3267 }
3268 };
3269
Jeff Sharkey5790af02018-08-13 17:42:54 -06003270 private static final Pattern PATTERN_TRANSLATE = Pattern.compile(
3271 "(?i)^(/storage/[^/]+/(?:[0-9]+/)?)(.*)");
3272
3273 @Override
Sudheer Shanka87915d62018-11-06 10:57:35 -08003274 public String translateAppToSystem(String path, int pid, int uid) {
3275 return translateInternal(path, pid, uid, true);
Jeff Sharkey5790af02018-08-13 17:42:54 -06003276 }
3277
3278 @Override
Sudheer Shanka87915d62018-11-06 10:57:35 -08003279 public String translateSystemToApp(String path, int pid, int uid) {
3280 return translateInternal(path, pid, uid, false);
Jeff Sharkey5790af02018-08-13 17:42:54 -06003281 }
3282
Sudheer Shanka87915d62018-11-06 10:57:35 -08003283 private String translateInternal(String path, int pid, int uid, boolean toSystem) {
Jeff Sharkey5790af02018-08-13 17:42:54 -06003284 if (!ENABLE_ISOLATED_STORAGE) return path;
3285
3286 if (path.contains("/../")) {
3287 throw new SecurityException("Shady looking path " + path);
3288 }
3289
Sudheer Shanka3a0df3b2018-12-12 12:43:43 -08003290 final int mountMode = mAmInternal.getStorageMountMode(pid, uid);
Sudheer Shanka0b6da532019-01-09 12:06:51 -08003291 if (mountMode == Zygote.MOUNT_EXTERNAL_FULL
3292 || mountMode == Zygote.MOUNT_EXTERNAL_LEGACY) {
Sudheer Shanka87915d62018-11-06 10:57:35 -08003293 return path;
3294 }
Jeff Sharkey5790af02018-08-13 17:42:54 -06003295
3296 final Matcher m = PATTERN_TRANSLATE.matcher(path);
3297 if (m.matches()) {
3298 final String device = m.group(1);
3299 final String devicePath = m.group(2);
3300
Sudheer Shanka3a0df3b2018-12-12 12:43:43 -08003301 if (mountMode == Zygote.MOUNT_EXTERNAL_INSTALLER
3302 && devicePath.startsWith("Android/obb/")) {
3303 return path;
3304 }
3305
Jeff Sharkey5790af02018-08-13 17:42:54 -06003306 // Does path belong to any packages belonging to this UID? If so,
3307 // they get to go straight through to legacy paths.
Sudheer Shanka87915d62018-11-06 10:57:35 -08003308 final String[] pkgs = mContext.getPackageManager().getPackagesForUid(uid);
Jeff Sharkey5790af02018-08-13 17:42:54 -06003309 for (String pkg : pkgs) {
3310 if (devicePath.startsWith("Android/data/" + pkg + "/") ||
3311 devicePath.startsWith("Android/media/" + pkg + "/") ||
3312 devicePath.startsWith("Android/obb/" + pkg + "/")) {
3313 return path;
3314 }
3315 }
3316
Sudheer Shanka87915d62018-11-06 10:57:35 -08003317 final String sharedUserId = mPmInternal.getSharedUserIdForPackage(pkgs[0]);
3318 final String sandboxId = getSandboxId(pkgs[0], sharedUserId);
3319
Jeff Sharkey5790af02018-08-13 17:42:54 -06003320 if (toSystem) {
3321 // Everything else goes into sandbox.
Sudheer Shanka31ad0a12018-10-20 20:59:00 -07003322 return device + "Android/sandbox/" + sandboxId + "/" + devicePath;
Jeff Sharkey5790af02018-08-13 17:42:54 -06003323 } else {
3324 // Does path belong to this sandbox? If so, leave sandbox.
Sudheer Shanka31ad0a12018-10-20 20:59:00 -07003325 final String sandboxPrefix = "Android/sandbox/" + sandboxId + "/";
Jeff Sharkey5790af02018-08-13 17:42:54 -06003326 if (devicePath.startsWith(sandboxPrefix)) {
3327 return device + devicePath.substring(sandboxPrefix.length());
3328 }
3329
3330 // Path isn't valid inside sandbox!
3331 throw new SecurityException(
3332 "Path " + path + " isn't valid inside sandbox " + sandboxId);
3333 }
3334 }
3335
3336 return path;
3337 }
3338
Kenny Rootaf9d6672010-10-08 09:21:39 -07003339 private void addObbStateLocked(ObbState obbState) throws RemoteException {
3340 final IBinder binder = obbState.getBinder();
3341 List<ObbState> obbStates = mObbMounts.get(binder);
Kenny Root5919ac62010-10-05 09:49:40 -07003342
Kenny Rootaf9d6672010-10-08 09:21:39 -07003343 if (obbStates == null) {
3344 obbStates = new ArrayList<ObbState>();
3345 mObbMounts.put(binder, obbStates);
3346 } else {
3347 for (final ObbState o : obbStates) {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003348 if (o.rawPath.equals(obbState.rawPath)) {
Kenny Rootaf9d6672010-10-08 09:21:39 -07003349 throw new IllegalStateException("Attempt to add ObbState twice. "
Sudheer Shanka2250d562016-11-07 15:41:02 -08003350 + "This indicates an error in the StorageManagerService logic.");
Kenny Root5919ac62010-10-05 09:49:40 -07003351 }
3352 }
Kenny Roota02b8b02010-08-05 16:14:17 -07003353 }
Kenny Rootaf9d6672010-10-08 09:21:39 -07003354
3355 obbStates.add(obbState);
3356 try {
3357 obbState.link();
3358 } catch (RemoteException e) {
3359 /*
3360 * The binder died before we could link it, so clean up our state
3361 * and return failure.
3362 */
3363 obbStates.remove(obbState);
3364 if (obbStates.isEmpty()) {
3365 mObbMounts.remove(binder);
3366 }
3367
3368 // Rethrow the error so mountObb can get it
3369 throw e;
3370 }
3371
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003372 mObbPathToStateMap.put(obbState.rawPath, obbState);
Kenny Roota02b8b02010-08-05 16:14:17 -07003373 }
3374
Kenny Rootaf9d6672010-10-08 09:21:39 -07003375 private void removeObbStateLocked(ObbState obbState) {
3376 final IBinder binder = obbState.getBinder();
3377 final List<ObbState> obbStates = mObbMounts.get(binder);
3378 if (obbStates != null) {
3379 if (obbStates.remove(obbState)) {
3380 obbState.unlink();
Kenny Root05105f72010-09-22 17:29:43 -07003381 }
Kenny Rootaf9d6672010-10-08 09:21:39 -07003382 if (obbStates.isEmpty()) {
3383 mObbMounts.remove(binder);
3384 }
Kenny Roota02b8b02010-08-05 16:14:17 -07003385 }
Kenny Roota02b8b02010-08-05 16:14:17 -07003386
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003387 mObbPathToStateMap.remove(obbState.rawPath);
Kenny Root38cf8862010-09-26 14:18:51 -07003388 }
3389
Kenny Roota02b8b02010-08-05 16:14:17 -07003390 private class ObbActionHandler extends Handler {
Kenny Roota02b8b02010-08-05 16:14:17 -07003391
3392 ObbActionHandler(Looper l) {
3393 super(l);
3394 }
3395
3396 @Override
3397 public void handleMessage(Message msg) {
3398 switch (msg.what) {
3399 case OBB_RUN_ACTION: {
Kenny Root480afe72010-10-07 10:17:50 -07003400 final ObbAction action = (ObbAction) msg.obj;
Kenny Roota02b8b02010-08-05 16:14:17 -07003401
3402 if (DEBUG_OBB)
3403 Slog.i(TAG, "OBB_RUN_ACTION: " + action.toString());
3404
Sudheer Shanka25469aa2018-08-27 15:50:23 -07003405 action.execute(this);
Kenny Roota02b8b02010-08-05 16:14:17 -07003406 break;
3407 }
Kenny Rootaf9d6672010-10-08 09:21:39 -07003408 case OBB_FLUSH_MOUNT_STATE: {
3409 final String path = (String) msg.obj;
3410
3411 if (DEBUG_OBB)
3412 Slog.i(TAG, "Flushing all OBB state for path " + path);
3413
3414 synchronized (mObbMounts) {
3415 final List<ObbState> obbStatesToRemove = new LinkedList<ObbState>();
3416
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003417 final Iterator<ObbState> i = mObbPathToStateMap.values().iterator();
Kenny Rootaf9d6672010-10-08 09:21:39 -07003418 while (i.hasNext()) {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003419 final ObbState state = i.next();
Kenny Rootaf9d6672010-10-08 09:21:39 -07003420
3421 /*
3422 * If this entry's source file is in the volume path
3423 * that got unmounted, remove it because it's no
3424 * longer valid.
3425 */
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003426 if (state.canonicalPath.startsWith(path)) {
3427 obbStatesToRemove.add(state);
Kenny Rootaf9d6672010-10-08 09:21:39 -07003428 }
3429 }
3430
3431 for (final ObbState obbState : obbStatesToRemove) {
3432 if (DEBUG_OBB)
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003433 Slog.i(TAG, "Removing state for " + obbState.rawPath);
Kenny Rootaf9d6672010-10-08 09:21:39 -07003434
3435 removeObbStateLocked(obbState);
3436
3437 try {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003438 obbState.token.onObbResult(obbState.rawPath, obbState.nonce,
Kenny Rootaf9d6672010-10-08 09:21:39 -07003439 OnObbStateChangeListener.UNMOUNTED);
3440 } catch (RemoteException e) {
3441 Slog.i(TAG, "Couldn't send unmount notification for OBB: "
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003442 + obbState.rawPath);
Kenny Rootaf9d6672010-10-08 09:21:39 -07003443 }
3444 }
3445 }
3446 break;
3447 }
Kenny Roota02b8b02010-08-05 16:14:17 -07003448 }
3449 }
Kenny Roota02b8b02010-08-05 16:14:17 -07003450 }
3451
Jeff Sharkey0095a822018-02-15 13:06:53 -07003452 private static class ObbException extends Exception {
3453 public final int status;
3454
3455 public ObbException(int status, String message) {
3456 super(message);
3457 this.status = status;
3458 }
3459
3460 public ObbException(int status, Throwable cause) {
3461 super(cause.getMessage(), cause);
3462 this.status = status;
3463 }
3464 }
3465
Kenny Roota02b8b02010-08-05 16:14:17 -07003466 abstract class ObbAction {
Kenny Roota02b8b02010-08-05 16:14:17 -07003467
3468 ObbState mObbState;
3469
3470 ObbAction(ObbState obbState) {
3471 mObbState = obbState;
3472 }
3473
3474 public void execute(ObbActionHandler handler) {
3475 try {
3476 if (DEBUG_OBB)
Ben Komalo444eca22011-09-01 15:17:44 -07003477 Slog.i(TAG, "Starting to execute action: " + toString());
Sudheer Shanka25469aa2018-08-27 15:50:23 -07003478 handleExecute();
Jeff Sharkey0095a822018-02-15 13:06:53 -07003479 } catch (ObbException e) {
3480 notifyObbStateChange(e);
Kenny Roota02b8b02010-08-05 16:14:17 -07003481 }
3482 }
3483
Jeff Sharkey0095a822018-02-15 13:06:53 -07003484 abstract void handleExecute() throws ObbException;
Kenny Root38cf8862010-09-26 14:18:51 -07003485
Jeff Sharkey0095a822018-02-15 13:06:53 -07003486 protected void notifyObbStateChange(ObbException e) {
3487 Slog.w(TAG, e);
3488 notifyObbStateChange(e.status);
3489 }
3490
3491 protected void notifyObbStateChange(int status) {
Kenny Rootaf9d6672010-10-08 09:21:39 -07003492 if (mObbState == null || mObbState.token == null) {
3493 return;
3494 }
3495
Kenny Root38cf8862010-09-26 14:18:51 -07003496 try {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003497 mObbState.token.onObbResult(mObbState.rawPath, mObbState.nonce, status);
Kenny Root38cf8862010-09-26 14:18:51 -07003498 } catch (RemoteException e) {
Sudheer Shanka2250d562016-11-07 15:41:02 -08003499 Slog.w(TAG, "StorageEventListener went away while calling onObbStateChanged");
Kenny Root38cf8862010-09-26 14:18:51 -07003500 }
3501 }
Kenny Roota02b8b02010-08-05 16:14:17 -07003502 }
3503
3504 class MountObbAction extends ObbAction {
Ben Komalo444eca22011-09-01 15:17:44 -07003505 private final String mKey;
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003506 private final int mCallingUid;
Sudheer Shanka25469aa2018-08-27 15:50:23 -07003507 private ObbInfo mObbInfo;
Kenny Roota02b8b02010-08-05 16:14:17 -07003508
Sudheer Shanka25469aa2018-08-27 15:50:23 -07003509 MountObbAction(ObbState obbState, String key, int callingUid, ObbInfo obbInfo) {
Kenny Roota02b8b02010-08-05 16:14:17 -07003510 super(obbState);
3511 mKey = key;
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003512 mCallingUid = callingUid;
Sudheer Shanka25469aa2018-08-27 15:50:23 -07003513 mObbInfo = obbInfo;
Kenny Roota02b8b02010-08-05 16:14:17 -07003514 }
3515
Jason parks5af0b912010-11-29 09:05:25 -06003516 @Override
Jeff Sharkey0095a822018-02-15 13:06:53 -07003517 public void handleExecute() throws ObbException {
Kenny Rootaf9d6672010-10-08 09:21:39 -07003518 warnOnNotMounted();
3519
Sudheer Shanka25469aa2018-08-27 15:50:23 -07003520 if (!isUidOwnerOfPackageOrSystem(mObbInfo.packageName, mCallingUid)) {
Jeff Sharkey0095a822018-02-15 13:06:53 -07003521 throw new ObbException(ERROR_PERMISSION_DENIED, "Denied attempt to mount OBB "
Sudheer Shanka25469aa2018-08-27 15:50:23 -07003522 + mObbInfo.filename + " which is owned by " + mObbInfo.packageName);
Kenny Roota02b8b02010-08-05 16:14:17 -07003523 }
3524
Kenny Rootaf9d6672010-10-08 09:21:39 -07003525 final boolean isMounted;
3526 synchronized (mObbMounts) {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003527 isMounted = mObbPathToStateMap.containsKey(mObbState.rawPath);
Kenny Rootaf9d6672010-10-08 09:21:39 -07003528 }
3529 if (isMounted) {
Jeff Sharkey0095a822018-02-15 13:06:53 -07003530 throw new ObbException(ERROR_ALREADY_MOUNTED,
Sudheer Shanka25469aa2018-08-27 15:50:23 -07003531 "Attempt to mount OBB which is already mounted: " + mObbInfo.filename);
Kenny Rootaf9d6672010-10-08 09:21:39 -07003532 }
3533
Kenny Rootaf9d6672010-10-08 09:21:39 -07003534 final String hashedKey;
Jeff Sharkey41cd6812017-09-11 10:32:17 -06003535 final String binderKey;
Kenny Rootaf9d6672010-10-08 09:21:39 -07003536 if (mKey == null) {
3537 hashedKey = "none";
Jeff Sharkey41cd6812017-09-11 10:32:17 -06003538 binderKey = "";
Kenny Rootaf9d6672010-10-08 09:21:39 -07003539 } else {
Kenny Rootaf9d6672010-10-08 09:21:39 -07003540 try {
Kenny Root3b1abba2010-10-13 15:00:07 -07003541 SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
3542
Sudheer Shanka25469aa2018-08-27 15:50:23 -07003543 KeySpec ks = new PBEKeySpec(mKey.toCharArray(), mObbInfo.salt,
Kenny Root3b1abba2010-10-13 15:00:07 -07003544 PBKDF2_HASH_ROUNDS, CRYPTO_ALGORITHM_KEY_SIZE);
3545 SecretKey key = factory.generateSecret(ks);
3546 BigInteger bi = new BigInteger(key.getEncoded());
3547 hashedKey = bi.toString(16);
Jeff Sharkey41cd6812017-09-11 10:32:17 -06003548 binderKey = hashedKey;
Jeff Sharkey0095a822018-02-15 13:06:53 -07003549 } catch (GeneralSecurityException e) {
3550 throw new ObbException(ERROR_INTERNAL, e);
Kenny Root38cf8862010-09-26 14:18:51 -07003551 }
Kenny Rootaf9d6672010-10-08 09:21:39 -07003552 }
Kenny Root38cf8862010-09-26 14:18:51 -07003553
Kenny Rootaf9d6672010-10-08 09:21:39 -07003554 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06003555 mObbState.volId = mVold.createObb(mObbState.canonicalPath, binderKey,
3556 mObbState.ownerGid);
3557 mVold.mount(mObbState.volId, 0, -1);
Kenny Roota02b8b02010-08-05 16:14:17 -07003558
Kenny Rootaf9d6672010-10-08 09:21:39 -07003559 if (DEBUG_OBB)
Xiaohui Chen621b3fc2015-10-02 14:41:42 -07003560 Slog.d(TAG, "Successfully mounted OBB " + mObbState.canonicalPath);
Kenny Rootaf9d6672010-10-08 09:21:39 -07003561
3562 synchronized (mObbMounts) {
3563 addObbStateLocked(mObbState);
3564 }
3565
Jeff Sharkey0095a822018-02-15 13:06:53 -07003566 notifyObbStateChange(MOUNTED);
3567 } catch (Exception e) {
3568 throw new ObbException(ERROR_COULD_NOT_MOUNT, e);
Kenny Root02c87302010-07-01 08:10:18 -07003569 }
3570 }
3571
Jason parks5af0b912010-11-29 09:05:25 -06003572 @Override
Kenny Roota02b8b02010-08-05 16:14:17 -07003573 public String toString() {
3574 StringBuilder sb = new StringBuilder();
3575 sb.append("MountObbAction{");
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003576 sb.append(mObbState);
Kenny Roota02b8b02010-08-05 16:14:17 -07003577 sb.append('}');
3578 return sb.toString();
3579 }
3580 }
3581
3582 class UnmountObbAction extends ObbAction {
Ben Komalo444eca22011-09-01 15:17:44 -07003583 private final boolean mForceUnmount;
Kenny Roota02b8b02010-08-05 16:14:17 -07003584
3585 UnmountObbAction(ObbState obbState, boolean force) {
3586 super(obbState);
3587 mForceUnmount = force;
3588 }
3589
Jason parks5af0b912010-11-29 09:05:25 -06003590 @Override
Jeff Sharkey0095a822018-02-15 13:06:53 -07003591 public void handleExecute() throws ObbException {
Kenny Rootaf9d6672010-10-08 09:21:39 -07003592 warnOnNotMounted();
3593
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003594 final ObbState existingState;
Kenny Root38cf8862010-09-26 14:18:51 -07003595 synchronized (mObbMounts) {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003596 existingState = mObbPathToStateMap.get(mObbState.rawPath);
Kenny Rootaf9d6672010-10-08 09:21:39 -07003597 }
Kenny Root38cf8862010-09-26 14:18:51 -07003598
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003599 if (existingState == null) {
Jeff Sharkey0095a822018-02-15 13:06:53 -07003600 throw new ObbException(ERROR_NOT_MOUNTED, "Missing existingState");
Kenny Rootaf9d6672010-10-08 09:21:39 -07003601 }
3602
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003603 if (existingState.ownerGid != mObbState.ownerGid) {
Jeff Sharkey0095a822018-02-15 13:06:53 -07003604 notifyObbStateChange(new ObbException(ERROR_PERMISSION_DENIED,
3605 "Permission denied to unmount OBB " + existingState.rawPath
3606 + " (owned by GID " + existingState.ownerGid + ")"));
Kenny Rootaf9d6672010-10-08 09:21:39 -07003607 return;
3608 }
3609
Kenny Rootaf9d6672010-10-08 09:21:39 -07003610 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06003611 mVold.unmount(mObbState.volId);
3612 mVold.destroyObb(mObbState.volId);
3613 mObbState.volId = null;
Kenny Roota02b8b02010-08-05 16:14:17 -07003614
Kenny Rootaf9d6672010-10-08 09:21:39 -07003615 synchronized (mObbMounts) {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003616 removeObbStateLocked(existingState);
Kenny Root38cf8862010-09-26 14:18:51 -07003617 }
3618
Jeff Sharkey0095a822018-02-15 13:06:53 -07003619 notifyObbStateChange(UNMOUNTED);
3620 } catch (Exception e) {
3621 throw new ObbException(ERROR_COULD_NOT_UNMOUNT, e);
Kenny Roota02b8b02010-08-05 16:14:17 -07003622 }
3623 }
3624
Jason parks5af0b912010-11-29 09:05:25 -06003625 @Override
Kenny Roota02b8b02010-08-05 16:14:17 -07003626 public String toString() {
3627 StringBuilder sb = new StringBuilder();
3628 sb.append("UnmountObbAction{");
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003629 sb.append(mObbState);
Kenny Roota02b8b02010-08-05 16:14:17 -07003630 sb.append(",force=");
3631 sb.append(mForceUnmount);
Kenny Roota02b8b02010-08-05 16:14:17 -07003632 sb.append('}');
3633 return sb.toString();
3634 }
Kenny Root02c87302010-07-01 08:10:18 -07003635 }
Kenny Root38cf8862010-09-26 14:18:51 -07003636
Jeff Sharkey7e19f532017-11-06 13:54:11 -07003637 private void dispatchOnStatus(IVoldTaskListener listener, int status,
3638 PersistableBundle extras) {
3639 if (listener != null) {
3640 try {
3641 listener.onStatus(status, extras);
3642 } catch (RemoteException ignored) {
3643 }
3644 }
3645 }
3646
3647 private void dispatchOnFinished(IVoldTaskListener listener, int status,
3648 PersistableBundle extras) {
3649 if (listener != null) {
3650 try {
3651 listener.onFinished(status, extras);
3652 } catch (RemoteException ignored) {
3653 }
3654 }
3655 }
3656
Sudheer Shanka3a0df3b2018-12-12 12:43:43 -08003657 private int getMountMode(int uid, String packageName) {
3658 try {
3659 if (Process.isIsolated(uid)) {
3660 return Zygote.MOUNT_EXTERNAL_NONE;
3661 }
3662 if (mIPackageManager.checkUidPermission(WRITE_MEDIA_STORAGE, uid)
3663 == PERMISSION_GRANTED) {
3664 return Zygote.MOUNT_EXTERNAL_FULL;
Jeff Sharkey11697f52018-12-13 10:14:42 -07003665 } else if (mIAppOpsService.checkOperation(OP_LEGACY_STORAGE, uid,
3666 packageName) == MODE_ALLOWED) {
Sudheer Shanka0b6da532019-01-09 12:06:51 -08003667 return Zygote.MOUNT_EXTERNAL_LEGACY;
Sudheer Shanka3a0df3b2018-12-12 12:43:43 -08003668 } else if (mIPackageManager.checkUidPermission(INSTALL_PACKAGES, uid)
3669 == PERMISSION_GRANTED || mIAppOpsService.checkOperation(
3670 OP_REQUEST_INSTALL_PACKAGES, uid, packageName) == MODE_ALLOWED) {
3671 return Zygote.MOUNT_EXTERNAL_INSTALLER;
Sudheer Shanka0f26cbd2019-01-18 18:25:38 -08003672 } else if (mPmInternal.isInstantApp(packageName, UserHandle.getUserId(uid))) {
3673 return Zygote.MOUNT_EXTERNAL_NONE;
Sudheer Shanka3a0df3b2018-12-12 12:43:43 -08003674 } else {
3675 return Zygote.MOUNT_EXTERNAL_WRITE;
3676 }
3677 } catch (RemoteException e) {
3678 // Should not happen
3679 }
3680 return Zygote.MOUNT_EXTERNAL_NONE;
3681 }
3682
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07003683 private static class Callbacks extends Handler {
3684 private static final int MSG_STORAGE_STATE_CHANGED = 1;
3685 private static final int MSG_VOLUME_STATE_CHANGED = 2;
Jeff Sharkey50a05452015-04-29 11:24:52 -07003686 private static final int MSG_VOLUME_RECORD_CHANGED = 3;
3687 private static final int MSG_VOLUME_FORGOTTEN = 4;
3688 private static final int MSG_DISK_SCANNED = 5;
Makoto Onuki9dc575d2015-06-12 16:10:25 -07003689 private static final int MSG_DISK_DESTROYED = 6;
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07003690
Sudheer Shanka2250d562016-11-07 15:41:02 -08003691 private final RemoteCallbackList<IStorageEventListener>
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07003692 mCallbacks = new RemoteCallbackList<>();
3693
3694 public Callbacks(Looper looper) {
3695 super(looper);
3696 }
3697
Sudheer Shanka2250d562016-11-07 15:41:02 -08003698 public void register(IStorageEventListener callback) {
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07003699 mCallbacks.register(callback);
3700 }
3701
Sudheer Shanka2250d562016-11-07 15:41:02 -08003702 public void unregister(IStorageEventListener callback) {
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07003703 mCallbacks.unregister(callback);
3704 }
3705
3706 @Override
3707 public void handleMessage(Message msg) {
3708 final SomeArgs args = (SomeArgs) msg.obj;
3709 final int n = mCallbacks.beginBroadcast();
3710 for (int i = 0; i < n; i++) {
Sudheer Shanka2250d562016-11-07 15:41:02 -08003711 final IStorageEventListener callback = mCallbacks.getBroadcastItem(i);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07003712 try {
3713 invokeCallback(callback, msg.what, args);
3714 } catch (RemoteException ignored) {
3715 }
3716 }
3717 mCallbacks.finishBroadcast();
3718 args.recycle();
3719 }
3720
Sudheer Shanka2250d562016-11-07 15:41:02 -08003721 private void invokeCallback(IStorageEventListener callback, int what, SomeArgs args)
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07003722 throws RemoteException {
3723 switch (what) {
3724 case MSG_STORAGE_STATE_CHANGED: {
3725 callback.onStorageStateChanged((String) args.arg1, (String) args.arg2,
3726 (String) args.arg3);
3727 break;
3728 }
3729 case MSG_VOLUME_STATE_CHANGED: {
3730 callback.onVolumeStateChanged((VolumeInfo) args.arg1, args.argi2, args.argi3);
3731 break;
3732 }
Jeff Sharkey50a05452015-04-29 11:24:52 -07003733 case MSG_VOLUME_RECORD_CHANGED: {
3734 callback.onVolumeRecordChanged((VolumeRecord) args.arg1);
3735 break;
3736 }
3737 case MSG_VOLUME_FORGOTTEN: {
3738 callback.onVolumeForgotten((String) args.arg1);
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07003739 break;
3740 }
Jeff Sharkey620b32b2015-04-23 19:36:02 -07003741 case MSG_DISK_SCANNED: {
3742 callback.onDiskScanned((DiskInfo) args.arg1, args.argi2);
Jeff Sharkey7e92ef32015-04-17 17:35:07 -07003743 break;
3744 }
Makoto Onuki9dc575d2015-06-12 16:10:25 -07003745 case MSG_DISK_DESTROYED: {
3746 callback.onDiskDestroyed((DiskInfo) args.arg1);
3747 break;
3748 }
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07003749 }
3750 }
3751
3752 private void notifyStorageStateChanged(String path, String oldState, String newState) {
3753 final SomeArgs args = SomeArgs.obtain();
3754 args.arg1 = path;
3755 args.arg2 = oldState;
3756 args.arg3 = newState;
3757 obtainMessage(MSG_STORAGE_STATE_CHANGED, args).sendToTarget();
3758 }
3759
3760 private void notifyVolumeStateChanged(VolumeInfo vol, int oldState, int newState) {
3761 final SomeArgs args = SomeArgs.obtain();
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07003762 args.arg1 = vol.clone();
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07003763 args.argi2 = oldState;
3764 args.argi3 = newState;
3765 obtainMessage(MSG_VOLUME_STATE_CHANGED, args).sendToTarget();
3766 }
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07003767
Jeff Sharkey50a05452015-04-29 11:24:52 -07003768 private void notifyVolumeRecordChanged(VolumeRecord rec) {
3769 final SomeArgs args = SomeArgs.obtain();
3770 args.arg1 = rec.clone();
3771 obtainMessage(MSG_VOLUME_RECORD_CHANGED, args).sendToTarget();
3772 }
3773
3774 private void notifyVolumeForgotten(String fsUuid) {
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07003775 final SomeArgs args = SomeArgs.obtain();
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07003776 args.arg1 = fsUuid;
Jeff Sharkey50a05452015-04-29 11:24:52 -07003777 obtainMessage(MSG_VOLUME_FORGOTTEN, args).sendToTarget();
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07003778 }
Jeff Sharkey7e92ef32015-04-17 17:35:07 -07003779
Jeff Sharkey620b32b2015-04-23 19:36:02 -07003780 private void notifyDiskScanned(DiskInfo disk, int volumeCount) {
Jeff Sharkey7e92ef32015-04-17 17:35:07 -07003781 final SomeArgs args = SomeArgs.obtain();
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07003782 args.arg1 = disk.clone();
Jeff Sharkey620b32b2015-04-23 19:36:02 -07003783 args.argi2 = volumeCount;
3784 obtainMessage(MSG_DISK_SCANNED, args).sendToTarget();
Jeff Sharkey7e92ef32015-04-17 17:35:07 -07003785 }
Makoto Onuki9dc575d2015-06-12 16:10:25 -07003786
3787 private void notifyDiskDestroyed(DiskInfo disk) {
3788 final SomeArgs args = SomeArgs.obtain();
3789 args.arg1 = disk.clone();
3790 obtainMessage(MSG_DISK_DESTROYED, args).sendToTarget();
3791 }
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07003792 }
3793
Kenny Root38cf8862010-09-26 14:18:51 -07003794 @Override
Jeff Sharkey5aca2b82013-10-16 16:21:54 -07003795 protected void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
Jeff Sharkeyfe9a53b2017-03-31 14:08:23 -06003796 if (!DumpUtils.checkDumpPermission(mContext, TAG, writer)) return;
Jeff Sharkey5aca2b82013-10-16 16:21:54 -07003797
3798 final IndentingPrintWriter pw = new IndentingPrintWriter(writer, " ", 160);
Jeff Sharkey27de30d2015-04-18 16:20:27 -07003799 synchronized (mLock) {
3800 pw.println("Disks:");
3801 pw.increaseIndent();
3802 for (int i = 0; i < mDisks.size(); i++) {
3803 final DiskInfo disk = mDisks.valueAt(i);
3804 disk.dump(pw);
3805 }
3806 pw.decreaseIndent();
3807
3808 pw.println();
3809 pw.println("Volumes:");
3810 pw.increaseIndent();
3811 for (int i = 0; i < mVolumes.size(); i++) {
3812 final VolumeInfo vol = mVolumes.valueAt(i);
3813 if (VolumeInfo.ID_PRIVATE_INTERNAL.equals(vol.id)) continue;
3814 vol.dump(pw);
3815 }
3816 pw.decreaseIndent();
3817
3818 pw.println();
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07003819 pw.println("Records:");
Jeff Sharkey27de30d2015-04-18 16:20:27 -07003820 pw.increaseIndent();
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07003821 for (int i = 0; i < mRecords.size(); i++) {
3822 final VolumeRecord note = mRecords.valueAt(i);
3823 note.dump(pw);
Jeff Sharkey27de30d2015-04-18 16:20:27 -07003824 }
3825 pw.decreaseIndent();
Jeff Sharkey275e3e42015-04-24 16:10:32 -07003826
3827 pw.println();
Sudheer Shanka3f0645b2018-09-18 13:07:59 -07003828 pw.println("mVisibleVols:");
3829 pw.increaseIndent();
3830 for (int i = 0; i < mVisibleVols.size(); i++) {
3831 mVisibleVols.get(i).dump(pw);
3832 }
3833 pw.decreaseIndent();
3834
3835 pw.println();
Jeff Sharkey275e3e42015-04-24 16:10:32 -07003836 pw.println("Primary storage UUID: " + mPrimaryStorageUuid);
Jeff Sharkeyb0c363b22018-12-15 11:53:03 -07003837
3838 pw.println();
Felipe Leme281389a2016-10-10 17:12:20 -07003839 final Pair<String, Long> pair = StorageManager.getPrimaryStoragePathAndSize();
3840 if (pair == null) {
3841 pw.println("Internal storage total size: N/A");
3842 } else {
3843 pw.print("Internal storage (");
3844 pw.print(pair.first);
3845 pw.print(") total size: ");
3846 pw.print(pair.second);
3847 pw.print(" (");
Jeff Sharkey9f2dc052018-01-07 16:47:31 -07003848 pw.print(DataUnit.MEBIBYTES.toBytes(pair.second));
3849 pw.println(" MiB)");
Felipe Leme281389a2016-10-10 17:12:20 -07003850 }
Jeff Sharkeyb0c363b22018-12-15 11:53:03 -07003851
3852 pw.println();
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07003853 pw.println("Local unlocked users: " + Arrays.toString(mLocalUnlockedUsers));
3854 pw.println("System unlocked users: " + Arrays.toString(mSystemUnlockedUsers));
Jeff Sharkeyb0c363b22018-12-15 11:53:03 -07003855
3856 final ContentResolver cr = mContext.getContentResolver();
3857 pw.println();
3858 pw.println("Isolated storage, local feature flag: "
3859 + Settings.Global.getInt(cr, Settings.Global.ISOLATED_STORAGE_LOCAL, 0));
3860 pw.println("Isolated storage, remote feature flag: "
3861 + Settings.Global.getInt(cr, Settings.Global.ISOLATED_STORAGE_REMOTE, 0));
3862 pw.println("Isolated storage, resolved: " + StorageManager.hasIsolatedStorage());
Jeff Sharkey27de30d2015-04-18 16:20:27 -07003863 }
Kenny Root38cf8862010-09-26 14:18:51 -07003864
Kenny Root38cf8862010-09-26 14:18:51 -07003865 synchronized (mObbMounts) {
Jeff Sharkey27de30d2015-04-18 16:20:27 -07003866 pw.println();
Jeff Sharkey5aca2b82013-10-16 16:21:54 -07003867 pw.println("mObbMounts:");
3868 pw.increaseIndent();
3869 final Iterator<Entry<IBinder, List<ObbState>>> binders = mObbMounts.entrySet()
3870 .iterator();
Kenny Rootaf9d6672010-10-08 09:21:39 -07003871 while (binders.hasNext()) {
3872 Entry<IBinder, List<ObbState>> e = binders.next();
Jeff Sharkey5aca2b82013-10-16 16:21:54 -07003873 pw.println(e.getKey() + ":");
3874 pw.increaseIndent();
Kenny Rootaf9d6672010-10-08 09:21:39 -07003875 final List<ObbState> obbStates = e.getValue();
Kenny Root38cf8862010-09-26 14:18:51 -07003876 for (final ObbState obbState : obbStates) {
Jeff Sharkey5aca2b82013-10-16 16:21:54 -07003877 pw.println(obbState);
Kenny Root38cf8862010-09-26 14:18:51 -07003878 }
Jeff Sharkey5aca2b82013-10-16 16:21:54 -07003879 pw.decreaseIndent();
Kenny Root38cf8862010-09-26 14:18:51 -07003880 }
Jeff Sharkey5aca2b82013-10-16 16:21:54 -07003881 pw.decreaseIndent();
Kenny Rootaf9d6672010-10-08 09:21:39 -07003882
Jeff Sharkey5aca2b82013-10-16 16:21:54 -07003883 pw.println();
3884 pw.println("mObbPathToStateMap:");
3885 pw.increaseIndent();
Kenny Rootaf9d6672010-10-08 09:21:39 -07003886 final Iterator<Entry<String, ObbState>> maps = mObbPathToStateMap.entrySet().iterator();
3887 while (maps.hasNext()) {
3888 final Entry<String, ObbState> e = maps.next();
Jeff Sharkey5aca2b82013-10-16 16:21:54 -07003889 pw.print(e.getKey());
3890 pw.print(" -> ");
3891 pw.println(e.getValue());
Kenny Rootaf9d6672010-10-08 09:21:39 -07003892 }
Jeff Sharkey5aca2b82013-10-16 16:21:54 -07003893 pw.decreaseIndent();
Kenny Root38cf8862010-09-26 14:18:51 -07003894 }
Kenny Root4161f9b2011-07-13 09:48:33 -07003895
Robert Greenwalt470fd722012-01-18 12:51:15 -08003896 pw.println();
Christopher Tate7265abe2014-11-21 13:54:45 -08003897 pw.print("Last maintenance: ");
Jeff Sharkeye8a4b662015-06-27 15:43:45 -07003898 pw.println(TimeUtils.formatForLogging(mLastMaintenance));
Kenny Root38cf8862010-09-26 14:18:51 -07003899 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003900
Jeff Sharkeyfa23c5a2011-08-09 21:44:24 -07003901 /** {@inheritDoc} */
Jeff Sharkey48877892015-03-18 11:27:19 -07003902 @Override
Jeff Sharkeyfa23c5a2011-08-09 21:44:24 -07003903 public void monitor() {
Jeff Sharkey54402792017-09-15 16:05:19 -06003904 try {
3905 mVold.monitor();
3906 } catch (Exception e) {
3907 Slog.wtf(TAG, e);
Paul Lawrence1c62cbb2015-06-03 14:14:52 -07003908 }
Jeff Sharkeyfa23c5a2011-08-09 21:44:24 -07003909 }
Svet Ganov6ee871e2015-07-10 14:29:33 -07003910
Sudheer Shanka2250d562016-11-07 15:41:02 -08003911 private final class StorageManagerInternalImpl extends StorageManagerInternal {
Svet Ganov6ee871e2015-07-10 14:29:33 -07003912 // Not guarded by a lock.
3913 private final CopyOnWriteArrayList<ExternalStorageMountPolicy> mPolicies =
3914 new CopyOnWriteArrayList<>();
3915
Risanaec0ee72018-10-31 10:10:12 +09003916 @GuardedBy("mResetListeners")
3917 private final List<StorageManagerInternal.ResetListener> mResetListeners =
3918 new ArrayList<>();
3919
Svet Ganov6ee871e2015-07-10 14:29:33 -07003920 @Override
3921 public void addExternalStoragePolicy(ExternalStorageMountPolicy policy) {
3922 // No locking - CopyOnWriteArrayList
3923 mPolicies.add(policy);
3924 }
3925
3926 @Override
3927 public void onExternalStoragePolicyChanged(int uid, String packageName) {
Sudheer Shanka0a541a52018-07-31 13:21:11 -07003928 // No runtime storage permissions in isolated storage world, so nothing to do here.
Jeff Sharkeyc58fdf32018-08-15 18:49:34 -06003929 if (ENABLE_ISOLATED_STORAGE) return;
Svet Ganov6ee871e2015-07-10 14:29:33 -07003930 final int mountMode = getExternalStorageMountMode(uid, packageName);
3931 remountUidExternalStorage(uid, mountMode);
3932 }
3933
3934 @Override
3935 public int getExternalStorageMountMode(int uid, String packageName) {
Sudheer Shanka3a0df3b2018-12-12 12:43:43 -08003936 if (ENABLE_ISOLATED_STORAGE) {
3937 return getMountMode(uid, packageName);
3938 }
Svet Ganov6ee871e2015-07-10 14:29:33 -07003939 // No locking - CopyOnWriteArrayList
3940 int mountMode = Integer.MAX_VALUE;
3941 for (ExternalStorageMountPolicy policy : mPolicies) {
3942 final int policyMode = policy.getMountMode(uid, packageName);
3943 if (policyMode == Zygote.MOUNT_EXTERNAL_NONE) {
3944 return Zygote.MOUNT_EXTERNAL_NONE;
3945 }
3946 mountMode = Math.min(mountMode, policyMode);
3947 }
3948 if (mountMode == Integer.MAX_VALUE) {
3949 return Zygote.MOUNT_EXTERNAL_NONE;
3950 }
3951 return mountMode;
3952 }
3953
Risanaec0ee72018-10-31 10:10:12 +09003954 @Override
3955 public void addResetListener(StorageManagerInternal.ResetListener listener) {
3956 synchronized (mResetListeners) {
3957 mResetListeners.add(listener);
3958 }
3959 }
3960
3961 public void onReset(IVold vold) {
3962 synchronized (mResetListeners) {
3963 for (StorageManagerInternal.ResetListener listener : mResetListeners) {
3964 listener.onReset(vold);
3965 }
3966 }
3967 }
3968
Svet Ganov6ee871e2015-07-10 14:29:33 -07003969 public boolean hasExternalStorage(int uid, String packageName) {
Amith Yamasani2bd5cff2015-07-22 14:42:31 -07003970 // No need to check for system uid. This avoids a deadlock between
3971 // PackageManagerService and AppOpsService.
3972 if (uid == Process.SYSTEM_UID) {
3973 return true;
3974 }
Sudheer Shanka3a0df3b2018-12-12 12:43:43 -08003975 if (ENABLE_ISOLATED_STORAGE) {
3976 return getMountMode(uid, packageName) != Zygote.MOUNT_EXTERNAL_NONE;
3977 }
Svet Ganov6ee871e2015-07-10 14:29:33 -07003978 // No locking - CopyOnWriteArrayList
3979 for (ExternalStorageMountPolicy policy : mPolicies) {
3980 final boolean policyHasStorage = policy.hasExternalStorage(uid, packageName);
3981 if (!policyHasStorage) {
3982 return false;
3983 }
3984 }
3985 return true;
3986 }
Sudheer Shanka8ff30b12018-08-06 17:29:44 -07003987
3988 @Override
Sudheer Shanka584b0682018-10-04 16:26:16 -07003989 public void prepareSandboxForApp(String packageName, int appId, String sharedUserId,
Sudheer Shanka8ff30b12018-08-06 17:29:44 -07003990 int userId) {
3991 final String sandboxId;
3992 synchronized (mPackagesLock) {
Sudheer Shanka2ac25a92018-10-25 10:59:32 -07003993 final ArraySet<String> userPackages = mPackages.get(userId);
Sudheer Shanka8ff30b12018-08-06 17:29:44 -07003994 // If userPackages is empty, it means the user is not started yet, so no need to
3995 // do anything now.
Sudheer Shanka2ac25a92018-10-25 10:59:32 -07003996 if (userPackages == null || userPackages.contains(packageName)) {
Sudheer Shanka8ff30b12018-08-06 17:29:44 -07003997 return;
3998 }
3999 userPackages.add(packageName);
Sudheer Shanka8ff30b12018-08-06 17:29:44 -07004000 sandboxId = getSandboxId(packageName, sharedUserId);
Sudheer Shanka8ff30b12018-08-06 17:29:44 -07004001 }
4002
4003 try {
Sudheer Shanka584b0682018-10-04 16:26:16 -07004004 mVold.prepareSandboxForApp(packageName, appId, sandboxId, userId);
4005 } catch (Exception e) {
4006 Slog.wtf(TAG, e);
4007 }
4008 }
4009
4010 @Override
Sudheer Shanka2ac25a92018-10-25 10:59:32 -07004011 public void destroySandboxForApp(String packageName, String sharedUserId, int userId) {
Sudheer Shanka584b0682018-10-04 16:26:16 -07004012 if (!ENABLE_ISOLATED_STORAGE) {
4013 return;
4014 }
Sudheer Shanka2ac25a92018-10-25 10:59:32 -07004015 final String sandboxId = getSandboxId(packageName, sharedUserId);
Sudheer Shanka584b0682018-10-04 16:26:16 -07004016 synchronized (mPackagesLock) {
Sudheer Shanka2ac25a92018-10-25 10:59:32 -07004017 final ArraySet<String> userPackages = mPackages.get(userId);
4018 // If the userPackages is null, it means the user is not started but we still
4019 // need to delete the sandbox data though.
4020 if (userPackages != null) {
4021 userPackages.remove(packageName);
Sudheer Shanka584b0682018-10-04 16:26:16 -07004022 }
4023 }
4024 try {
Sudheer Shanka2ac25a92018-10-25 10:59:32 -07004025 mVold.destroySandboxForApp(packageName, sandboxId, userId);
Sudheer Shanka8ff30b12018-08-06 17:29:44 -07004026 } catch (Exception e) {
4027 Slog.wtf(TAG, e);
4028 }
4029 }
Sudheer Shanka3f0645b2018-09-18 13:07:59 -07004030
4031 @Override
4032 public String[] getVisibleVolumesForUser(int userId) {
4033 final ArrayList<String> visibleVolsForUser = new ArrayList<>();
4034 for (int i = mVisibleVols.size() - 1; i >= 0; --i) {
4035 final VolumeInfo vol = mVisibleVols.get(i);
4036 if (vol.isVisibleForUser(userId)) {
4037 visibleVolsForUser.add(getVolumeLabel(vol));
4038 }
4039 }
4040 return visibleVolsForUser.toArray(new String[visibleVolsForUser.size()]);
4041 }
4042
4043 private String getVolumeLabel(VolumeInfo vol) {
4044 // STOPSHIP: Label needs to part of VolumeInfo and need to be passed on from vold
4045 switch (vol.getType()) {
4046 case VolumeInfo.TYPE_EMULATED:
4047 return "emulated";
4048 case VolumeInfo.TYPE_PUBLIC:
4049 return vol.fsUuid == null ? vol.id : vol.fsUuid;
4050 default:
4051 return null;
4052 }
4053 }
Svet Ganov6ee871e2015-07-10 14:29:33 -07004054 }
Jeff Sharkeyfa23c5a2011-08-09 21:44:24 -07004055}