blob: 371e5177ede36cad8280f87c91d96e9b9e49d5af [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
Jeff Sharkey0095a822018-02-15 13:06:53 -070019import static android.os.storage.OnObbStateChangeListener.ERROR_ALREADY_MOUNTED;
20import static android.os.storage.OnObbStateChangeListener.ERROR_COULD_NOT_MOUNT;
21import static android.os.storage.OnObbStateChangeListener.ERROR_COULD_NOT_UNMOUNT;
22import static android.os.storage.OnObbStateChangeListener.ERROR_INTERNAL;
23import static android.os.storage.OnObbStateChangeListener.ERROR_NOT_MOUNTED;
24import static android.os.storage.OnObbStateChangeListener.ERROR_PERMISSION_DENIED;
25import static android.os.storage.OnObbStateChangeListener.MOUNTED;
26import static android.os.storage.OnObbStateChangeListener.UNMOUNTED;
27
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -070028import static com.android.internal.util.XmlUtils.readIntAttribute;
Jeff Sharkeye8a4b662015-06-27 15:43:45 -070029import static com.android.internal.util.XmlUtils.readLongAttribute;
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -070030import static com.android.internal.util.XmlUtils.readStringAttribute;
31import static com.android.internal.util.XmlUtils.writeIntAttribute;
Jeff Sharkeye8a4b662015-06-27 15:43:45 -070032import static com.android.internal.util.XmlUtils.writeLongAttribute;
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -070033import static com.android.internal.util.XmlUtils.writeStringAttribute;
Jeff Sharkey5217cac2015-12-20 15:34:01 -070034
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -070035import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT;
36import static org.xmlpull.v1.XmlPullParser.START_TAG;
37
Jason parks8888c592011-01-20 22:46:41 -060038import android.Manifest;
Jeff Sharkeyef10ee02015-07-05 14:17:27 -070039import android.annotation.Nullable;
Xiaohui Chen621b3fc2015-10-02 14:41:42 -070040import android.app.ActivityManager;
Jeff Sharkey9765e442017-12-14 22:15:14 -070041import android.app.ActivityManagerInternal;
42import android.app.ActivityManagerInternal.ScreenObserver;
Jeff Sharkey2d8b4e82013-09-17 17:30:33 -070043import android.app.AppOpsManager;
Jeff Sharkey14cbe522015-07-08 14:06:37 -070044import android.app.IActivityManager;
Jeff Sharkey9765e442017-12-14 22:15:14 -070045import android.app.KeyguardManager;
Pavel Grafovce72ef02018-01-10 17:14:11 +000046import android.app.admin.SecurityLog;
Jeff Sharkey9bed0702017-01-23 20:37:05 -070047import android.app.usage.StorageStatsManager;
Jeff Sharkeybcd262d2015-06-10 09:41:17 -070048import android.content.BroadcastReceiver;
Kenny Roota02b8b02010-08-05 16:14:17 -070049import android.content.ComponentName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080050import android.content.Context;
51import android.content.Intent;
Jeff Sharkeybcd262d2015-06-10 09:41:17 -070052import android.content.IntentFilter;
Kenny Roota02b8b02010-08-05 16:14:17 -070053import android.content.ServiceConnection;
Jeff Sharkey275e3e42015-04-24 16:10:32 -070054import android.content.pm.IPackageMoveObserver;
55import android.content.pm.PackageManager;
Jeff Sharkey14cbe522015-07-08 14:06:37 -070056import android.content.pm.ProviderInfo;
Jeff Sharkeybcd262d2015-06-10 09:41:17 -070057import android.content.pm.UserInfo;
Elliott Hughesf839b4f2014-09-26 12:30:47 -070058import android.content.res.Configuration;
Kenny Root02c87302010-07-01 08:10:18 -070059import android.content.res.ObbInfo;
Daniel Colascione766b6322018-01-08 19:10:36 -080060import android.database.ContentObserver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080061import android.net.Uri;
Kenny Root02c87302010-07-01 08:10:18 -070062import android.os.Binder;
Jeff Sharkey4c099d02015-05-15 13:45:00 -070063import android.os.DropBoxManager;
Kenny Roota02b8b02010-08-05 16:14:17 -070064import android.os.Environment;
Jeff Sharkeyb049e212012-09-07 23:16:01 -070065import android.os.Environment.UserEnvironment;
Jeff Sharkey48877892015-03-18 11:27:19 -070066import android.os.FileUtils;
Suchi Amalapurapuc42e29e2010-02-22 16:03:53 -080067import android.os.Handler;
Dianne Hackbornefa92b22013-05-03 14:11:43 -070068import android.os.HandlerThread;
Kenny Roota02b8b02010-08-05 16:14:17 -070069import android.os.IBinder;
Jin Qian12690d52017-10-13 18:17:04 -070070import android.os.IStoraged;
Jeff Sharkey1019de92017-09-06 13:47:03 -060071import android.os.IVold;
Jeff Sharkey8058fe62017-09-13 11:50:33 -060072import android.os.IVoldListener;
Jeff Sharkeyb302c542017-09-15 12:57:59 -060073import android.os.IVoldTaskListener;
Daniel Sandler5f27ef42010-03-16 15:42:02 -040074import android.os.Looper;
Suchi Amalapurapuc42e29e2010-02-22 16:03:53 -080075import android.os.Message;
Daichi Hirono9e8d9e22015-11-13 14:37:00 +090076import android.os.ParcelFileDescriptor;
Jeff Sharkey500ce9e2017-02-12 02:39:24 -070077import android.os.ParcelableException;
Jeff Sharkeyb302c542017-09-15 12:57:59 -060078import android.os.PersistableBundle;
Jeff Sharkeyce14cd02015-12-07 15:35:42 -070079import android.os.PowerManager;
Jeff Sharkey9527b222015-06-24 15:24:48 -070080import android.os.Process;
Jeff Sharkey7151a9a2015-04-04 15:22:37 -070081import android.os.RemoteCallbackList;
San Mehat4270e1e2010-01-29 05:32:19 -080082import android.os.RemoteException;
Suchi Amalapurapufd3530f2010-01-18 00:15:59 -080083import android.os.ServiceManager;
Paul Crowleyfc0b5192018-07-02 13:58:10 -070084import android.os.ServiceSpecificException;
Jeff Sharkeyedcdaf62015-07-09 09:45:36 -070085import android.os.SystemClock;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080086import android.os.SystemProperties;
Dianne Hackbornf02b60a2012-08-16 10:48:27 -070087import android.os.UserHandle;
Emily Bernier92aa5a22014-07-07 10:11:48 -040088import android.os.UserManager;
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -070089import android.os.storage.DiskInfo;
Kenny Roota02b8b02010-08-05 16:14:17 -070090import android.os.storage.IObbActionListener;
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -070091import android.os.storage.IStorageEventListener;
Sudheer Shanka2250d562016-11-07 15:41:02 -080092import android.os.storage.IStorageManager;
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -070093import android.os.storage.IStorageShutdownObserver;
Kenny Rootaf9d6672010-10-08 09:21:39 -070094import android.os.storage.OnObbStateChangeListener;
Paul Lawrence46791e72014-04-03 09:10:26 -070095import android.os.storage.StorageManager;
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -070096import android.os.storage.StorageManagerInternal;
Mike Lockwood2f6a3882011-05-09 19:08:06 -070097import android.os.storage.StorageVolume;
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -070098import android.os.storage.VolumeInfo;
Jeff Sharkeyb36586a2015-04-27 08:42:28 -070099import android.os.storage.VolumeRecord;
Jeff Sharkey14cbe522015-07-08 14:06:37 -0700100import android.provider.MediaStore;
Jeff Sharkeye8a4b662015-06-27 15:43:45 -0700101import android.provider.Settings;
Inseob Kim5b1cc272018-12-10 07:06:25 +0000102import android.sysprop.VoldProperties;
Jason parksf7b3cd42011-01-27 09:28:25 -0600103import android.text.TextUtils;
Jeff Sharkey1783f142015-04-17 10:52:51 -0700104import android.text.format.DateUtils;
Jeff Sharkey48877892015-03-18 11:27:19 -0700105import android.util.ArrayMap;
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700106import android.util.AtomicFile;
Jeff Sharkey9f2dc052018-01-07 16:47:31 -0700107import android.util.DataUnit;
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -0700108import android.util.Log;
Felipe Leme281389a2016-10-10 17:12:20 -0700109import android.util.Pair;
San Mehata5078592010-03-25 09:36:54 -0700110import android.util.Slog;
Jeff Sharkeye8a4b662015-06-27 15:43:45 -0700111import android.util.TimeUtils;
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700112import android.util.Xml;
Jeff Sharkey48877892015-03-18 11:27:19 -0700113
Jeff Sharkey8b2c3a142012-11-12 11:45:05 -0800114import com.android.internal.annotations.GuardedBy;
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700115import com.android.internal.app.IMediaContainerService;
Daichi Hirono9fb00182016-11-08 14:12:17 +0900116import com.android.internal.os.AppFuseMount;
Jeff Sharkey1019de92017-09-06 13:47:03 -0600117import com.android.internal.os.BackgroundThread;
Daichi Hirono812c95d2017-02-08 16:20:20 +0900118import com.android.internal.os.FuseUnavailableMountException;
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700119import com.android.internal.os.SomeArgs;
Jeff Sharkey9527b222015-06-24 15:24:48 -0700120import com.android.internal.os.Zygote;
Jeff Sharkey48877892015-03-18 11:27:19 -0700121import com.android.internal.util.ArrayUtils;
Jeff Sharkeyfe9a53b2017-03-31 14:08:23 -0600122import com.android.internal.util.DumpUtils;
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700123import com.android.internal.util.FastXmlSerializer;
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -0800124import com.android.internal.util.HexDump;
Jeff Sharkey5aca2b82013-10-16 16:21:54 -0700125import com.android.internal.util.IndentingPrintWriter;
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700126import com.android.internal.util.Preconditions;
Jeff Sharkeyb9fe5372015-12-03 15:23:08 -0700127import com.android.internal.widget.LockPatternUtils;
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700128import com.android.server.pm.PackageManagerService;
Daichi Hirono9fb00182016-11-08 14:12:17 +0900129import com.android.server.storage.AppFuseBridge;
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -0700130
Jeff Sharkey5217cac2015-12-20 15:34:01 -0700131import libcore.io.IoUtils;
132import libcore.util.EmptyArray;
133
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700134import org.xmlpull.v1.XmlPullParser;
135import org.xmlpull.v1.XmlPullParserException;
136import org.xmlpull.v1.XmlSerializer;
137
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700138import java.io.File;
Kenny Root38cf8862010-09-26 14:18:51 -0700139import java.io.FileDescriptor;
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700140import java.io.FileInputStream;
141import java.io.FileNotFoundException;
Christopher Tate7265abe2014-11-21 13:54:45 -0800142import java.io.FileOutputStream;
Kenny Root05105f72010-09-22 17:29:43 -0700143import java.io.IOException;
Kenny Root38cf8862010-09-26 14:18:51 -0700144import java.io.PrintWriter;
Kenny Root3b1abba2010-10-13 15:00:07 -0700145import java.math.BigInteger;
Paul Lawrence8e397362014-01-27 15:22:30 -0800146import java.nio.charset.StandardCharsets;
Jeff Sharkey0095a822018-02-15 13:06:53 -0700147import java.security.GeneralSecurityException;
Kenny Root3b1abba2010-10-13 15:00:07 -0700148import java.security.spec.KeySpec;
San Mehat22dd86e2010-01-12 12:21:18 -0800149import java.util.ArrayList;
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -0800150import java.util.Arrays;
Kenny Roota02b8b02010-08-05 16:14:17 -0700151import java.util.HashMap;
Kenny Root38cf8862010-09-26 14:18:51 -0700152import java.util.Iterator;
Kenny Roota02b8b02010-08-05 16:14:17 -0700153import java.util.LinkedList;
154import java.util.List;
Elliott Hughesf839b4f2014-09-26 12:30:47 -0700155import java.util.Locale;
Kenny Roota02b8b02010-08-05 16:14:17 -0700156import java.util.Map;
Kenny Root38cf8862010-09-26 14:18:51 -0700157import java.util.Map.Entry;
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700158import java.util.Objects;
Svet Ganov6ee871e2015-07-10 14:29:33 -0700159import java.util.concurrent.CopyOnWriteArrayList;
Kenny Root51a573c2012-05-17 13:30:28 -0700160import java.util.concurrent.CountDownLatch;
161import java.util.concurrent.TimeUnit;
Jeff Sharkeyedcdaf62015-07-09 09:45:36 -0700162import java.util.concurrent.TimeoutException;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800163
Kenny Root3b1abba2010-10-13 15:00:07 -0700164import javax.crypto.SecretKey;
165import javax.crypto.SecretKeyFactory;
166import javax.crypto.spec.PBEKeySpec;
167
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800168/**
Jeff Sharkey48877892015-03-18 11:27:19 -0700169 * Service responsible for various storage media. Connects to {@code vold} to
170 * watch for and manage dynamically added storage, such as SD cards and USB mass
171 * storage. Also decides how storage should be presented to users on the device.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800172 */
Jeff Sharkey9765e442017-12-14 22:15:14 -0700173class StorageManagerService extends IStorageManager.Stub
174 implements Watchdog.Monitor, ScreenObserver {
Jason parks5af0b912010-11-29 09:05:25 -0600175
Christopher Tated417d622013-08-19 16:14:25 -0700176 // Static direct instance pointer for the tightly-coupled idle service to use
Sudheer Shanka2250d562016-11-07 15:41:02 -0800177 static StorageManagerService sSelf = null;
Christopher Tated417d622013-08-19 16:14:25 -0700178
Daniel Colascione766b6322018-01-08 19:10:36 -0800179 /* Read during boot to decide whether to enable zram when available */
180 private static final String ZRAM_ENABLED_PROPERTY =
181 "persist.sys.zram_enabled";
182
Jeff Sharkey56e62932015-03-21 20:41:00 -0700183 public static class Lifecycle extends SystemService {
Sudheer Shanka2250d562016-11-07 15:41:02 -0800184 private StorageManagerService mStorageManagerService;
Jeff Sharkey56e62932015-03-21 20:41:00 -0700185
186 public Lifecycle(Context context) {
187 super(context);
188 }
189
190 @Override
191 public void onStart() {
Sudheer Shanka2250d562016-11-07 15:41:02 -0800192 mStorageManagerService = new StorageManagerService(getContext());
193 publishBinderService("mount", mStorageManagerService);
194 mStorageManagerService.start();
Jeff Sharkey56e62932015-03-21 20:41:00 -0700195 }
196
197 @Override
198 public void onBootPhase(int phase) {
199 if (phase == SystemService.PHASE_ACTIVITY_MANAGER_READY) {
Sudheer Shanka2250d562016-11-07 15:41:02 -0800200 mStorageManagerService.systemReady();
Yasuhiro Matsuda87a38b52015-07-24 22:10:16 +0900201 } else if (phase == SystemService.PHASE_BOOT_COMPLETED) {
Sudheer Shanka2250d562016-11-07 15:41:02 -0800202 mStorageManagerService.bootCompleted();
Jeff Sharkey56e62932015-03-21 20:41:00 -0700203 }
204 }
Jeff Sharkey48877892015-03-18 11:27:19 -0700205
206 @Override
Jeff Sharkeyab15c392016-05-05 11:45:01 -0600207 public void onSwitchUser(int userHandle) {
Sudheer Shanka2250d562016-11-07 15:41:02 -0800208 mStorageManagerService.mCurrentUserId = userHandle;
Jeff Sharkeyab15c392016-05-05 11:45:01 -0600209 }
210
211 @Override
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700212 public void onUnlockUser(int userHandle) {
Sudheer Shanka2250d562016-11-07 15:41:02 -0800213 mStorageManagerService.onUnlockUser(userHandle);
Jeff Sharkey48877892015-03-18 11:27:19 -0700214 }
215
216 @Override
217 public void onCleanupUser(int userHandle) {
Sudheer Shanka2250d562016-11-07 15:41:02 -0800218 mStorageManagerService.onCleanupUser(userHandle);
Jeff Sharkey48877892015-03-18 11:27:19 -0700219 }
Jeff Sharkey56e62932015-03-21 20:41:00 -0700220 }
221
Dianne Hackborn40e9f292012-11-27 19:12:23 -0800222 private static final boolean DEBUG_EVENTS = false;
Kenny Rootb7db2722011-01-25 16:39:35 -0800223 private static final boolean DEBUG_OBB = false;
Kenny Root02c87302010-07-01 08:10:18 -0700224
Kenny Root07714d42011-08-17 17:49:28 -0700225 // Disable this since it messes up long-running cryptfs operations.
226 private static final boolean WATCHDOG_ENABLE = false;
227
Jeff Sharkey00455bf2016-11-04 14:45:24 -0600228 /**
229 * Our goal is for all Android devices to be usable as development devices,
230 * which includes the new Direct Boot mode added in N. For devices that
231 * don't have native FBE support, we offer an emulation mode for developer
232 * testing purposes, but if it's prohibitively difficult to support this
233 * mode, it can be disabled for specific products using this flag.
234 */
235 private static final boolean EMULATE_FBE_SUPPORTED = true;
236
Sudheer Shanka2250d562016-11-07 15:41:02 -0800237 private static final String TAG = "StorageManagerService";
Jeff Sharkeye8a4b662015-06-27 15:43:45 -0700238
Jeff Sharkey9756d752015-05-14 21:07:42 -0700239 private static final String TAG_STORAGE_BENCHMARK = "storage_benchmark";
Jeff Sharkeye8a4b662015-06-27 15:43:45 -0700240 private static final String TAG_STORAGE_TRIM = "storage_trim";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800241
Jeff Sharkey275e3e42015-04-24 16:10:32 -0700242 /** Magic value sent by MoveTask.cpp */
243 private static final int MOVE_STATUS_COPY_FINISHED = 82;
244
Jeff Sharkey620b32b2015-04-23 19:36:02 -0700245 private static final int VERSION_INIT = 1;
246 private static final int VERSION_ADD_PRIMARY = 2;
Jeff Sharkeyfced5342015-05-10 14:53:34 -0700247 private static final int VERSION_FIX_PRIMARY = 3;
Jeff Sharkey620b32b2015-04-23 19:36:02 -0700248
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700249 private static final String TAG_VOLUMES = "volumes";
Jeff Sharkey620b32b2015-04-23 19:36:02 -0700250 private static final String ATTR_VERSION = "version";
251 private static final String ATTR_PRIMARY_STORAGE_UUID = "primaryStorageUuid";
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700252 private static final String TAG_VOLUME = "volume";
253 private static final String ATTR_TYPE = "type";
254 private static final String ATTR_FS_UUID = "fsUuid";
Jeff Sharkey5cc0df22015-06-17 19:44:05 -0700255 private static final String ATTR_PART_GUID = "partGuid";
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700256 private static final String ATTR_NICKNAME = "nickname";
257 private static final String ATTR_USER_FLAGS = "userFlags";
Jeff Sharkeye8a4b662015-06-27 15:43:45 -0700258 private static final String ATTR_CREATED_MILLIS = "createdMillis";
259 private static final String ATTR_LAST_TRIM_MILLIS = "lastTrimMillis";
260 private static final String ATTR_LAST_BENCH_MILLIS = "lastBenchMillis";
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700261
Jeff Sharkeyb36586a2015-04-27 08:42:28 -0700262 private final AtomicFile mSettingsFile;
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700263
Jeff Sharkey48877892015-03-18 11:27:19 -0700264 /**
265 * <em>Never</em> hold the lock while performing downcalls into vold, since
266 * unsolicited events can suddenly appear to update data structures.
267 */
Jeff Sharkey5f3e9342017-03-13 14:53:11 -0600268 private final Object mLock = LockGuard.installNewLock(LockGuard.INDEX_STORAGE);
Jeff Sharkey48877892015-03-18 11:27:19 -0700269
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700270 /** Set of users that we know are unlocked. */
Jeff Sharkey48877892015-03-18 11:27:19 -0700271 @GuardedBy("mLock")
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700272 private int[] mLocalUnlockedUsers = EmptyArray.INT;
273 /** Set of users that system knows are unlocked. */
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -0800274 @GuardedBy("mLock")
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700275 private int[] mSystemUnlockedUsers = EmptyArray.INT;
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700276
277 /** Map from disk ID to disk */
Jeff Sharkey48877892015-03-18 11:27:19 -0700278 @GuardedBy("mLock")
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -0700279 private ArrayMap<String, DiskInfo> mDisks = new ArrayMap<>();
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700280 /** Map from volume ID to disk */
Jeff Sharkey48877892015-03-18 11:27:19 -0700281 @GuardedBy("mLock")
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700282 private final ArrayMap<String, VolumeInfo> mVolumes = new ArrayMap<>();
Jeff Sharkey48877892015-03-18 11:27:19 -0700283
Jeff Sharkeyb36586a2015-04-27 08:42:28 -0700284 /** Map from UUID to record */
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700285 @GuardedBy("mLock")
Jeff Sharkeyb36586a2015-04-27 08:42:28 -0700286 private ArrayMap<String, VolumeRecord> mRecords = new ArrayMap<>();
Jeff Sharkey620b32b2015-04-23 19:36:02 -0700287 @GuardedBy("mLock")
288 private String mPrimaryStorageUuid;
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700289
Jeff Sharkeyeba260d2015-04-19 14:35:16 -0700290 /** Map from disk ID to latches */
291 @GuardedBy("mLock")
292 private ArrayMap<String, CountDownLatch> mDiskScanLatches = new ArrayMap<>();
293
Jeff Sharkey275e3e42015-04-24 16:10:32 -0700294 @GuardedBy("mLock")
295 private IPackageMoveObserver mMoveCallback;
296 @GuardedBy("mLock")
297 private String mMoveTargetUuid;
298
Jeff Sharkeyab15c392016-05-05 11:45:01 -0600299 private volatile int mCurrentUserId = UserHandle.USER_SYSTEM;
300
Daichi Hirono9fb00182016-11-08 14:12:17 +0900301 /** Holding lock for AppFuse business */
302 private final Object mAppFuseLock = new Object();
303
304 @GuardedBy("mAppFuseLock")
305 private int mNextAppFuseName = 0;
306
307 @GuardedBy("mAppFuseLock")
Daichi Hironoe56740d2017-02-02 13:56:45 +0900308 private AppFuseBridge mAppFuseBridge = null;
Daichi Hirono9fb00182016-11-08 14:12:17 +0900309
Jeff Sharkeyef10ee02015-07-05 14:17:27 -0700310 private VolumeInfo findVolumeByIdOrThrow(String id) {
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700311 synchronized (mLock) {
312 final VolumeInfo vol = mVolumes.get(id);
313 if (vol != null) {
314 return vol;
315 }
316 }
317 throw new IllegalArgumentException("No volume found for ID " + id);
318 }
319
Jeff Sharkeyef10ee02015-07-05 14:17:27 -0700320 private String findVolumeIdForPathOrThrow(String path) {
Jeff Sharkey48877892015-03-18 11:27:19 -0700321 synchronized (mLock) {
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -0700322 for (int i = 0; i < mVolumes.size(); i++) {
323 final VolumeInfo vol = mVolumes.valueAt(i);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700324 if (vol.path != null && path.startsWith(vol.path)) {
325 return vol.id;
Jeff Sharkey48877892015-03-18 11:27:19 -0700326 }
327 }
328 }
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700329 throw new IllegalArgumentException("No volume found for path " + path);
Jeff Sharkey48877892015-03-18 11:27:19 -0700330 }
331
Jeff Sharkeye8a4b662015-06-27 15:43:45 -0700332 private VolumeRecord findRecordForPath(String path) {
333 synchronized (mLock) {
334 for (int i = 0; i < mVolumes.size(); i++) {
335 final VolumeInfo vol = mVolumes.valueAt(i);
336 if (vol.path != null && path.startsWith(vol.path)) {
337 return mRecords.get(vol.fsUuid);
338 }
339 }
340 }
341 return null;
342 }
343
344 private String scrubPath(String path) {
345 if (path.startsWith(Environment.getDataDirectory().getAbsolutePath())) {
346 return "internal";
347 }
348 final VolumeRecord rec = findRecordForPath(path);
349 if (rec == null || rec.createdMillis == 0) {
350 return "unknown";
351 } else {
352 return "ext:" + (int) ((System.currentTimeMillis() - rec.createdMillis)
353 / DateUtils.WEEK_IN_MILLIS) + "w";
354 }
355 }
356
Jeff Sharkeyef10ee02015-07-05 14:17:27 -0700357 private @Nullable VolumeInfo findStorageForUuid(String volumeUuid) {
Jeff Sharkey275e3e42015-04-24 16:10:32 -0700358 final StorageManager storage = mContext.getSystemService(StorageManager.class);
359 if (Objects.equals(StorageManager.UUID_PRIVATE_INTERNAL, volumeUuid)) {
Jeff Sharkeyef10ee02015-07-05 14:17:27 -0700360 return storage.findVolumeById(VolumeInfo.ID_EMULATED_INTERNAL);
Jeff Sharkey275e3e42015-04-24 16:10:32 -0700361 } else if (Objects.equals(StorageManager.UUID_PRIMARY_PHYSICAL, volumeUuid)) {
362 return storage.getPrimaryPhysicalVolume();
363 } else {
364 return storage.findEmulatedForPrivate(storage.findVolumeByUuid(volumeUuid));
365 }
366 }
367
Jeff Sharkeye8a4b662015-06-27 15:43:45 -0700368 private boolean shouldBenchmark() {
369 final long benchInterval = Settings.Global.getLong(mContext.getContentResolver(),
370 Settings.Global.STORAGE_BENCHMARK_INTERVAL, DateUtils.WEEK_IN_MILLIS);
Jeff Sharkeye83d8a92015-09-09 14:53:38 -0700371 if (benchInterval == -1) {
372 return false;
373 } else if (benchInterval == 0) {
374 return true;
375 }
376
Jeff Sharkeye8a4b662015-06-27 15:43:45 -0700377 synchronized (mLock) {
378 for (int i = 0; i < mVolumes.size(); i++) {
379 final VolumeInfo vol = mVolumes.valueAt(i);
380 final VolumeRecord rec = mRecords.get(vol.fsUuid);
Jeff Sharkeye83d8a92015-09-09 14:53:38 -0700381 if (vol.isMountedWritable() && rec != null) {
Jeff Sharkeye8a4b662015-06-27 15:43:45 -0700382 final long benchAge = System.currentTimeMillis() - rec.lastBenchMillis;
383 if (benchAge >= benchInterval) {
384 return true;
385 }
386 }
387 }
388 return false;
389 }
390 }
391
Jeff Sharkeyeba260d2015-04-19 14:35:16 -0700392 private CountDownLatch findOrCreateDiskScanLatch(String diskId) {
393 synchronized (mLock) {
394 CountDownLatch latch = mDiskScanLatches.get(diskId);
395 if (latch == null) {
396 latch = new CountDownLatch(1);
397 mDiskScanLatches.put(diskId, latch);
398 }
399 return latch;
400 }
401 }
402
Paul Lawrence8e397362014-01-27 15:22:30 -0800403 /** List of crypto types.
404 * These must match CRYPT_TYPE_XXX in cryptfs.h AND their
405 * corresponding commands in CommandListener.cpp */
406 public static final String[] CRYPTO_TYPES
407 = { "password", "default", "pattern", "pin" };
408
Brian Carlstrom7395a8a2014-04-28 22:11:01 -0700409 private final Context mContext;
Jeff Sharkeycd575992016-03-29 14:12:49 -0600410
Jeff Sharkey1019de92017-09-06 13:47:03 -0600411 private volatile IVold mVold;
Jin Qian12690d52017-10-13 18:17:04 -0700412 private volatile IStoraged mStoraged;
Jeff Sharkey1019de92017-09-06 13:47:03 -0600413
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700414 private volatile boolean mSystemReady = false;
Yasuhiro Matsuda87a38b52015-07-24 22:10:16 +0900415 private volatile boolean mBootCompleted = false;
Jeff Sharkey48877892015-03-18 11:27:19 -0700416 private volatile boolean mDaemonConnected = false;
Jeff Sharkey9765e442017-12-14 22:15:14 -0700417 private volatile boolean mSecureKeyguardShowing = true;
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700418
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700419 private PackageManagerService mPms;
420
421 private final Callbacks mCallbacks;
Jeff Sharkeyb9fe5372015-12-03 15:23:08 -0700422 private final LockPatternUtils mLockPatternUtils;
Jeff Sharkey48877892015-03-18 11:27:19 -0700423
San Mehat6cdd9c02010-02-09 14:45:20 -0800424 /**
Kenny Root3b1abba2010-10-13 15:00:07 -0700425 * The size of the crypto algorithm key in bits for OBB files. Currently
426 * Twofish is used which takes 128-bit keys.
427 */
428 private static final int CRYPTO_ALGORITHM_KEY_SIZE = 128;
429
430 /**
431 * The number of times to run SHA1 in the PBKDF2 function for OBB files.
432 * 1024 is reasonably secure and not too slow.
433 */
434 private static final int PBKDF2_HASH_ROUNDS = 1024;
435
436 /**
Kenny Roota02b8b02010-08-05 16:14:17 -0700437 * Mounted OBB tracking information. Used to track the current state of all
438 * OBBs.
Kenny Root02c87302010-07-01 08:10:18 -0700439 */
Kenny Root735de3b2010-09-30 14:11:39 -0700440 final private Map<IBinder, List<ObbState>> mObbMounts = new HashMap<IBinder, List<ObbState>>();
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700441
442 /** Map from raw paths to {@link ObbState}. */
Kenny Roota02b8b02010-08-05 16:14:17 -0700443 final private Map<String, ObbState> mObbPathToStateMap = new HashMap<String, ObbState>();
444
Svet Ganov6ee871e2015-07-10 14:29:33 -0700445 // Not guarded by a lock.
Sudheer Shanka2250d562016-11-07 15:41:02 -0800446 private final StorageManagerInternalImpl mStorageManagerInternal
447 = new StorageManagerInternalImpl();
Svet Ganov6ee871e2015-07-10 14:29:33 -0700448
Kenny Roota02b8b02010-08-05 16:14:17 -0700449 class ObbState implements IBinder.DeathRecipient {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700450 public ObbState(String rawPath, String canonicalPath, int callingUid,
Jeff Sharkey41cd6812017-09-11 10:32:17 -0600451 IObbActionListener token, int nonce, String volId) {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700452 this.rawPath = rawPath;
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700453 this.canonicalPath = canonicalPath;
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700454 this.ownerGid = UserHandle.getSharedAppGid(callingUid);
Kenny Rootaf9d6672010-10-08 09:21:39 -0700455 this.token = token;
456 this.nonce = nonce;
Jeff Sharkey41cd6812017-09-11 10:32:17 -0600457 this.volId = volId;
Kenny Roota02b8b02010-08-05 16:14:17 -0700458 }
459
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700460 final String rawPath;
461 final String canonicalPath;
Kenny Roota02b8b02010-08-05 16:14:17 -0700462
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700463 final int ownerGid;
Kenny Roota02b8b02010-08-05 16:14:17 -0700464
Kenny Rootaf9d6672010-10-08 09:21:39 -0700465 // Token of remote Binder caller
466 final IObbActionListener token;
467
468 // Identifier to pass back to the token
469 final int nonce;
Kenny Roota02b8b02010-08-05 16:14:17 -0700470
Jeff Sharkey41cd6812017-09-11 10:32:17 -0600471 String volId;
472
Kenny Root735de3b2010-09-30 14:11:39 -0700473 public IBinder getBinder() {
474 return token.asBinder();
475 }
476
Kenny Roota02b8b02010-08-05 16:14:17 -0700477 @Override
478 public void binderDied() {
479 ObbAction action = new UnmountObbAction(this, true);
480 mObbActionHandler.sendMessage(mObbActionHandler.obtainMessage(OBB_RUN_ACTION, action));
Kenny Root735de3b2010-09-30 14:11:39 -0700481 }
Kenny Roota02b8b02010-08-05 16:14:17 -0700482
Kenny Root5919ac62010-10-05 09:49:40 -0700483 public void link() throws RemoteException {
484 getBinder().linkToDeath(this, 0);
485 }
486
487 public void unlink() {
Kenny Root735de3b2010-09-30 14:11:39 -0700488 getBinder().unlinkToDeath(this, 0);
Kenny Roota02b8b02010-08-05 16:14:17 -0700489 }
Kenny Root38cf8862010-09-26 14:18:51 -0700490
491 @Override
492 public String toString() {
493 StringBuilder sb = new StringBuilder("ObbState{");
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700494 sb.append("rawPath=").append(rawPath);
495 sb.append(",canonicalPath=").append(canonicalPath);
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700496 sb.append(",ownerGid=").append(ownerGid);
497 sb.append(",token=").append(token);
498 sb.append(",binder=").append(getBinder());
Jeff Sharkey41cd6812017-09-11 10:32:17 -0600499 sb.append(",volId=").append(volId);
Kenny Root38cf8862010-09-26 14:18:51 -0700500 sb.append('}');
501 return sb.toString();
502 }
Kenny Roota02b8b02010-08-05 16:14:17 -0700503 }
504
505 // OBB Action Handler
506 final private ObbActionHandler mObbActionHandler;
507
508 // OBB action handler messages
509 private static final int OBB_RUN_ACTION = 1;
510 private static final int OBB_MCS_BOUND = 2;
511 private static final int OBB_MCS_UNBIND = 3;
512 private static final int OBB_MCS_RECONNECT = 4;
Kenny Rootaf9d6672010-10-08 09:21:39 -0700513 private static final int OBB_FLUSH_MOUNT_STATE = 5;
Kenny Roota02b8b02010-08-05 16:14:17 -0700514
515 /*
516 * Default Container Service information
517 */
518 static final ComponentName DEFAULT_CONTAINER_COMPONENT = new ComponentName(
519 "com.android.defcontainer", "com.android.defcontainer.DefaultContainerService");
520
521 final private DefaultContainerConnection mDefContainerConn = new DefaultContainerConnection();
522
523 class DefaultContainerConnection implements ServiceConnection {
Jeff Sharkey48877892015-03-18 11:27:19 -0700524 @Override
Kenny Roota02b8b02010-08-05 16:14:17 -0700525 public void onServiceConnected(ComponentName name, IBinder service) {
526 if (DEBUG_OBB)
527 Slog.i(TAG, "onServiceConnected");
528 IMediaContainerService imcs = IMediaContainerService.Stub.asInterface(service);
529 mObbActionHandler.sendMessage(mObbActionHandler.obtainMessage(OBB_MCS_BOUND, imcs));
530 }
531
Jeff Sharkey48877892015-03-18 11:27:19 -0700532 @Override
Kenny Roota02b8b02010-08-05 16:14:17 -0700533 public void onServiceDisconnected(ComponentName name) {
534 if (DEBUG_OBB)
535 Slog.i(TAG, "onServiceDisconnected");
536 }
Jeff Sharkey54402792017-09-15 16:05:19 -0600537 }
Kenny Roota02b8b02010-08-05 16:14:17 -0700538
539 // Used in the ObbActionHandler
540 private IMediaContainerService mContainerService = null;
Kenny Root02c87302010-07-01 08:10:18 -0700541
Christopher Tate7265abe2014-11-21 13:54:45 -0800542 // Last fstrim operation tracking
543 private static final String LAST_FSTRIM_FILE = "last-fstrim";
544 private final File mLastMaintenanceFile;
545 private long mLastMaintenance;
546
Kenny Root02c87302010-07-01 08:10:18 -0700547 // Handler messages
Jeff Sharkey48877892015-03-18 11:27:19 -0700548 private static final int H_SYSTEM_READY = 1;
549 private static final int H_DAEMON_CONNECTED = 2;
550 private static final int H_SHUTDOWN = 3;
551 private static final int H_FSTRIM = 4;
552 private static final int H_VOLUME_MOUNT = 5;
553 private static final int H_VOLUME_BROADCAST = 6;
Jeff Sharkeyabc3e852015-08-03 14:41:13 -0700554 private static final int H_INTERNAL_BROADCAST = 7;
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700555 private static final int H_VOLUME_UNMOUNT = 8;
Jeff Sharkey5a9bb742015-11-03 10:15:57 -0800556 private static final int H_PARTITION_FORGET = 9;
557 private static final int H_RESET = 10;
Jin Qiana85b9912017-10-17 15:48:18 -0700558 private static final int H_RUN_IDLE_MAINT = 11;
559 private static final int H_ABORT_IDLE_MAINT = 12;
Suchi Amalapurapu6ffce2e2010-03-08 14:48:40 -0800560
Sudheer Shanka2250d562016-11-07 15:41:02 -0800561 class StorageManagerServiceHandler extends Handler {
562 public StorageManagerServiceHandler(Looper looper) {
Jeff Sharkey48877892015-03-18 11:27:19 -0700563 super(looper);
Daniel Sandler5f27ef42010-03-16 15:42:02 -0400564 }
565
Jason parks5af0b912010-11-29 09:05:25 -0600566 @Override
Suchi Amalapurapuc42e29e2010-02-22 16:03:53 -0800567 public void handleMessage(Message msg) {
568 switch (msg.what) {
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700569 case H_SYSTEM_READY: {
Jeff Sharkey48877892015-03-18 11:27:19 -0700570 handleSystemReady();
571 break;
572 }
573 case H_DAEMON_CONNECTED: {
574 handleDaemonConnected();
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700575 break;
576 }
Christopher Tated417d622013-08-19 16:14:25 -0700577 case H_FSTRIM: {
Christopher Tated417d622013-08-19 16:14:25 -0700578 Slog.i(TAG, "Running fstrim idle maintenance");
Christopher Tate7265abe2014-11-21 13:54:45 -0800579
580 // Remember when we kicked it off
581 try {
582 mLastMaintenance = System.currentTimeMillis();
583 mLastMaintenanceFile.setLastModified(mLastMaintenance);
584 } catch (Exception e) {
585 Slog.e(TAG, "Unable to record last fstrim!");
586 }
587
Jeff Sharkeyb302c542017-09-15 12:57:59 -0600588 // TODO: Reintroduce shouldBenchmark() test
Jeff Sharkey7e19f532017-11-06 13:54:11 -0700589 fstrim(0, null);
Christopher Tate7265abe2014-11-21 13:54:45 -0800590
Christopher Tated417d622013-08-19 16:14:25 -0700591 // invoke the completion callback, if any
Jeff Sharkeye8a4b662015-06-27 15:43:45 -0700592 // TODO: fstrim is non-blocking, so remove this useless callback
Christopher Tated417d622013-08-19 16:14:25 -0700593 Runnable callback = (Runnable) msg.obj;
594 if (callback != null) {
595 callback.run();
596 }
597 break;
598 }
Jeff Sharkey48877892015-03-18 11:27:19 -0700599 case H_SHUTDOWN: {
Sudheer Shanka2250d562016-11-07 15:41:02 -0800600 final IStorageShutdownObserver obs = (IStorageShutdownObserver) msg.obj;
Jeff Sharkey48877892015-03-18 11:27:19 -0700601 boolean success = false;
602 try {
Jeff Sharkey54402792017-09-15 16:05:19 -0600603 mVold.shutdown();
604 success = true;
Jeff Sharkeyace874b2017-09-07 15:27:33 -0600605 } catch (Exception e) {
606 Slog.wtf(TAG, e);
Jeff Sharkey48877892015-03-18 11:27:19 -0700607 }
608 if (obs != null) {
609 try {
610 obs.onShutDownComplete(success ? 0 : -1);
Jeff Sharkeyace874b2017-09-07 15:27:33 -0600611 } catch (Exception ignored) {
Jeff Sharkey48877892015-03-18 11:27:19 -0700612 }
613 }
614 break;
615 }
616 case H_VOLUME_MOUNT: {
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -0700617 final VolumeInfo vol = (VolumeInfo) msg.obj;
Jeff Sharkey2e606d72015-07-27 14:19:54 -0700618 if (isMountDisallowed(vol)) {
619 Slog.i(TAG, "Ignoring mount " + vol.getId() + " due to policy");
620 break;
621 }
Jeff Sharkey48877892015-03-18 11:27:19 -0700622 try {
Jeff Sharkey54402792017-09-15 16:05:19 -0600623 mVold.mount(vol.id, vol.mountFlags, vol.mountUserId);
Jeff Sharkeyace874b2017-09-07 15:27:33 -0600624 } catch (Exception e) {
625 Slog.wtf(TAG, e);
Jeff Sharkey48877892015-03-18 11:27:19 -0700626 }
627 break;
628 }
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700629 case H_VOLUME_UNMOUNT: {
630 final VolumeInfo vol = (VolumeInfo) msg.obj;
631 unmount(vol.getId());
632 break;
633 }
Jeff Sharkey48877892015-03-18 11:27:19 -0700634 case H_VOLUME_BROADCAST: {
635 final StorageVolume userVol = (StorageVolume) msg.obj;
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700636 final String envState = userVol.getState();
637 Slog.d(TAG, "Volume " + userVol.getId() + " broadcasting " + envState + " to "
Jeff Sharkey48877892015-03-18 11:27:19 -0700638 + userVol.getOwner());
639
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700640 final String action = VolumeInfo.getBroadcastForEnvironment(envState);
Jeff Sharkey48877892015-03-18 11:27:19 -0700641 if (action != null) {
642 final Intent intent = new Intent(action,
643 Uri.fromFile(userVol.getPathFile()));
644 intent.putExtra(StorageVolume.EXTRA_STORAGE_VOLUME, userVol);
Jeff Sharkey082f83b2017-03-26 14:34:47 -0600645 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT
646 | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
Jeff Sharkey48877892015-03-18 11:27:19 -0700647 mContext.sendBroadcastAsUser(intent, userVol.getOwner());
648 }
649 break;
650 }
Jeff Sharkeyabc3e852015-08-03 14:41:13 -0700651 case H_INTERNAL_BROADCAST: {
652 // Internal broadcasts aimed at system components, not for
653 // third-party apps.
654 final Intent intent = (Intent) msg.obj;
655 mContext.sendBroadcastAsUser(intent, UserHandle.ALL,
656 android.Manifest.permission.WRITE_MEDIA_STORAGE);
Jeff Sharkey5a9bb742015-11-03 10:15:57 -0800657 break;
658 }
659 case H_PARTITION_FORGET: {
Jeff Sharkeydb4b6192017-10-24 11:08:50 -0600660 final VolumeRecord rec = (VolumeRecord) msg.obj;
661 forgetPartition(rec.partGuid, rec.fsUuid);
Jeff Sharkey5a9bb742015-11-03 10:15:57 -0800662 break;
663 }
664 case H_RESET: {
665 resetIfReadyAndConnected();
666 break;
Jeff Sharkeyabc3e852015-08-03 14:41:13 -0700667 }
Jin Qiana85b9912017-10-17 15:48:18 -0700668 case H_RUN_IDLE_MAINT: {
669 Slog.i(TAG, "Running idle maintenance");
670 runIdleMaint((Runnable)msg.obj);
671 break;
672 }
673 case H_ABORT_IDLE_MAINT: {
674 Slog.i(TAG, "Aborting idle maintenance");
675 abortIdleMaint((Runnable)msg.obj);
676 break;
677 }
678
Suchi Amalapurapuc42e29e2010-02-22 16:03:53 -0800679 }
680 }
Jeff Sharkey48877892015-03-18 11:27:19 -0700681 }
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700682
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700683 private final Handler mHandler;
Suchi Amalapurapuc42e29e2010-02-22 16:03:53 -0800684
Jeff Sharkeybcd262d2015-06-10 09:41:17 -0700685 private BroadcastReceiver mUserReceiver = new BroadcastReceiver() {
686 @Override
687 public void onReceive(Context context, Intent intent) {
688 final String action = intent.getAction();
689 final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700690 Preconditions.checkArgument(userId >= 0);
Jeff Sharkeybcd262d2015-06-10 09:41:17 -0700691
692 try {
693 if (Intent.ACTION_USER_ADDED.equals(action)) {
694 final UserManager um = mContext.getSystemService(UserManager.class);
695 final int userSerialNumber = um.getUserSerialNumber(userId);
Jeff Sharkey54402792017-09-15 16:05:19 -0600696 mVold.onUserAdded(userId, userSerialNumber);
Jeff Sharkeybcd262d2015-06-10 09:41:17 -0700697 } else if (Intent.ACTION_USER_REMOVED.equals(action)) {
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700698 synchronized (mVolumes) {
699 final int size = mVolumes.size();
700 for (int i = 0; i < size; i++) {
701 final VolumeInfo vol = mVolumes.valueAt(i);
702 if (vol.mountUserId == userId) {
703 vol.mountUserId = UserHandle.USER_NULL;
704 mHandler.obtainMessage(H_VOLUME_UNMOUNT, vol).sendToTarget();
705 }
706 }
707 }
Jeff Sharkey54402792017-09-15 16:05:19 -0600708 mVold.onUserRemoved(userId);
Jeff Sharkeybcd262d2015-06-10 09:41:17 -0700709 }
Jeff Sharkeyace874b2017-09-07 15:27:33 -0600710 } catch (Exception e) {
711 Slog.wtf(TAG, e);
Jeff Sharkeybcd262d2015-06-10 09:41:17 -0700712 }
713 }
714 };
715
Jeff Sharkeyedcdaf62015-07-09 09:45:36 -0700716 private void waitForLatch(CountDownLatch latch, String condition, long timeoutMillis)
717 throws TimeoutException {
718 final long startMillis = SystemClock.elapsedRealtime();
Jeff Sharkeyeba260d2015-04-19 14:35:16 -0700719 while (true) {
Kenny Root51a573c2012-05-17 13:30:28 -0700720 try {
721 if (latch.await(5000, TimeUnit.MILLISECONDS)) {
San Mehat207e5382010-02-04 20:46:54 -0800722 return;
Kenny Root51a573c2012-05-17 13:30:28 -0700723 } else {
724 Slog.w(TAG, "Thread " + Thread.currentThread().getName()
Jeff Sharkey48877892015-03-18 11:27:19 -0700725 + " still waiting for " + condition + "...");
San Mehat207e5382010-02-04 20:46:54 -0800726 }
Kenny Root51a573c2012-05-17 13:30:28 -0700727 } catch (InterruptedException e) {
Jeff Sharkeyeba260d2015-04-19 14:35:16 -0700728 Slog.w(TAG, "Interrupt while waiting for " + condition);
San Mehat207e5382010-02-04 20:46:54 -0800729 }
Jeff Sharkeyedcdaf62015-07-09 09:45:36 -0700730 if (timeoutMillis > 0 && SystemClock.elapsedRealtime() > startMillis + timeoutMillis) {
731 throw new TimeoutException("Thread " + Thread.currentThread().getName()
732 + " gave up waiting for " + condition + " after " + timeoutMillis + "ms");
733 }
San Mehat207e5382010-02-04 20:46:54 -0800734 }
San Mehat1f6301e2010-01-07 22:40:27 -0800735 }
Kenny Root02c87302010-07-01 08:10:18 -0700736
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700737 private void handleSystemReady() {
Jeff Sharkey8924e872015-11-30 12:52:10 -0700738 initIfReadyAndConnected();
Jeff Sharkey5a9bb742015-11-03 10:15:57 -0800739 resetIfReadyAndConnected();
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700740
Jeff Sharkey48877892015-03-18 11:27:19 -0700741 // Start scheduling nominally-daily fstrim operations
Christopher Tate115afda2014-06-06 19:06:26 -0700742 MountServiceIdler.scheduleIdlePass(mContext);
Daniel Colascione766b6322018-01-08 19:10:36 -0800743
744 // Toggle zram-enable system property in response to settings
745 mContext.getContentResolver().registerContentObserver(
746 Settings.Global.getUriFor(Settings.Global.ZRAM_ENABLED),
747 false /*notifyForDescendants*/,
748 new ContentObserver(null /* current thread */) {
749 @Override
750 public void onChange(boolean selfChange) {
751 refreshZramSettings();
752 }
753 });
754 refreshZramSettings();
755 }
756
757 /**
758 * Update the zram_enabled system property (which init reads to
759 * decide whether to enable zram) to reflect the zram_enabled
760 * preference (which we can change for experimentation purposes).
761 */
762 private void refreshZramSettings() {
763 String propertyValue = SystemProperties.get(ZRAM_ENABLED_PROPERTY);
764 if ("".equals(propertyValue)) {
765 return; // System doesn't have zram toggling support
766 }
767 String desiredPropertyValue =
768 Settings.Global.getInt(mContext.getContentResolver(),
769 Settings.Global.ZRAM_ENABLED,
770 1) != 0
771 ? "1" : "0";
772 if (!desiredPropertyValue.equals(propertyValue)) {
773 // Avoid redundant disk writes by setting only if we're
774 // changing the property value. There's no race: we're the
775 // sole writer.
776 SystemProperties.set(ZRAM_ENABLED_PROPERTY, desiredPropertyValue);
777 }
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700778 }
779
Jeff Sharkey14cbe522015-07-08 14:06:37 -0700780 /**
781 * MediaProvider has a ton of code that makes assumptions about storage
782 * paths never changing, so we outright kill them to pick up new state.
783 */
784 @Deprecated
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700785 private void killMediaProvider(List<UserInfo> users) {
786 if (users == null) return;
787
Jeff Sharkeyb3cf9532015-07-17 15:12:39 -0700788 final long token = Binder.clearCallingIdentity();
789 try {
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700790 for (UserInfo user : users) {
791 // System user does not have media provider, so skip.
792 if (user.isSystemOnly()) continue;
793
Jeff Sharkey2a9e3f82015-12-18 10:57:58 -0700794 final ProviderInfo provider = mPms.resolveContentProvider(MediaStore.AUTHORITY,
Jeff Sharkey8a372a02016-03-16 16:25:45 -0600795 PackageManager.MATCH_DIRECT_BOOT_AWARE
796 | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
797 user.id);
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700798 if (provider != null) {
Sudheer Shankadc589ac2016-11-10 15:30:17 -0800799 final IActivityManager am = ActivityManager.getService();
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700800 try {
Jeff Sharkey85f449e2016-06-23 09:26:00 -0600801 am.killApplication(provider.applicationInfo.packageName,
802 UserHandle.getAppId(provider.applicationInfo.uid),
803 UserHandle.USER_ALL, "vold reset");
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700804 // We only need to run this once. It will kill all users' media processes.
805 break;
806 } catch (RemoteException e) {
807 }
Jeff Sharkeyb3cf9532015-07-17 15:12:39 -0700808 }
Jeff Sharkey14cbe522015-07-08 14:06:37 -0700809 }
Jeff Sharkeyb3cf9532015-07-17 15:12:39 -0700810 } finally {
811 Binder.restoreCallingIdentity(token);
Jeff Sharkey14cbe522015-07-08 14:06:37 -0700812 }
813 }
814
Andreas Gampea36dc622018-02-05 17:19:22 -0800815 @GuardedBy("mLock")
Jeff Sharkey5a9bb742015-11-03 10:15:57 -0800816 private void addInternalVolumeLocked() {
Amith Yamasania7892482015-08-07 11:09:05 -0700817 // Create a stub volume that represents internal storage
818 final VolumeInfo internal = new VolumeInfo(VolumeInfo.ID_PRIVATE_INTERNAL,
819 VolumeInfo.TYPE_PRIVATE, null, null);
820 internal.state = VolumeInfo.STATE_MOUNTED;
821 internal.path = Environment.getDataDirectory().getAbsolutePath();
822 mVolumes.put(internal.id, internal);
823 }
824
Jeff Sharkey8924e872015-11-30 12:52:10 -0700825 private void initIfReadyAndConnected() {
826 Slog.d(TAG, "Thinking about init, mSystemReady=" + mSystemReady
827 + ", mDaemonConnected=" + mDaemonConnected);
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700828 if (mSystemReady && mDaemonConnected
Paul Lawrence20be5d62016-02-26 13:51:17 -0800829 && !StorageManager.isFileEncryptedNativeOnly()) {
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700830 // When booting a device without native support, make sure that our
831 // user directories are locked or unlocked based on the current
832 // emulation status.
Paul Lawrence20be5d62016-02-26 13:51:17 -0800833 final boolean initLocked = StorageManager.isFileEncryptedEmulatedOnly();
Paul Crowleyd94ab732016-02-15 06:44:51 +0000834 Slog.d(TAG, "Setting up emulation state, initlocked=" + initLocked);
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700835 final List<UserInfo> users = mContext.getSystemService(UserManager.class).getUsers();
Jeff Sharkey8924e872015-11-30 12:52:10 -0700836 for (UserInfo user : users) {
837 try {
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700838 if (initLocked) {
Jeff Sharkey54402792017-09-15 16:05:19 -0600839 mVold.lockUserKey(user.id);
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700840 } else {
Jeff Sharkey54402792017-09-15 16:05:19 -0600841 mVold.unlockUserKey(user.id, user.serialNumber, encodeBytes(null),
842 encodeBytes(null));
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700843 }
Jeff Sharkey43e12112017-09-12 16:31:45 -0600844 } catch (Exception e) {
845 Slog.wtf(TAG, e);
Jeff Sharkey8924e872015-11-30 12:52:10 -0700846 }
847 }
848 }
849 }
850
Jeff Sharkey5a9bb742015-11-03 10:15:57 -0800851 private void resetIfReadyAndConnected() {
Jeff Sharkey48877892015-03-18 11:27:19 -0700852 Slog.d(TAG, "Thinking about reset, mSystemReady=" + mSystemReady
853 + ", mDaemonConnected=" + mDaemonConnected);
854 if (mSystemReady && mDaemonConnected) {
Jeff Sharkey5a9bb742015-11-03 10:15:57 -0800855 final List<UserInfo> users = mContext.getSystemService(UserManager.class).getUsers();
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700856 killMediaProvider(users);
Jeff Sharkey14cbe522015-07-08 14:06:37 -0700857
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700858 final int[] systemUnlockedUsers;
Jeff Sharkey5a9bb742015-11-03 10:15:57 -0800859 synchronized (mLock) {
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700860 systemUnlockedUsers = mSystemUnlockedUsers;
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700861
Jeff Sharkey5a9bb742015-11-03 10:15:57 -0800862 mDisks.clear();
863 mVolumes.clear();
864
865 addInternalVolumeLocked();
866 }
Jeff Sharkey59d577a2015-04-11 21:27:21 -0700867
Jeff Sharkey48877892015-03-18 11:27:19 -0700868 try {
Jeff Sharkey54402792017-09-15 16:05:19 -0600869 mVold.reset();
Jeff Sharkeybcd262d2015-06-10 09:41:17 -0700870
871 // Tell vold about all existing and started users
Jeff Sharkeybcd262d2015-06-10 09:41:17 -0700872 for (UserInfo user : users) {
Jeff Sharkey54402792017-09-15 16:05:19 -0600873 mVold.onUserAdded(user.id, user.serialNumber);
Jeff Sharkeybcd262d2015-06-10 09:41:17 -0700874 }
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700875 for (int userId : systemUnlockedUsers) {
Jeff Sharkey54402792017-09-15 16:05:19 -0600876 mVold.onUserStarted(userId);
Jin Qian12690d52017-10-13 18:17:04 -0700877 mStoraged.onUserStarted(userId);
Jeff Sharkey50a05452015-04-29 11:24:52 -0700878 }
Jeff Sharkey9765e442017-12-14 22:15:14 -0700879 mVold.onSecureKeyguardStateChanged(mSecureKeyguardShowing);
Risana354a272018-10-31 10:10:12 +0900880 mStorageManagerInternal.onReset(mVold);
Jeff Sharkeyace874b2017-09-07 15:27:33 -0600881 } catch (Exception e) {
882 Slog.wtf(TAG, e);
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700883 }
884 }
Jeff Sharkey48877892015-03-18 11:27:19 -0700885 }
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700886
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700887 private void onUnlockUser(int userId) {
888 Slog.d(TAG, "onUnlockUser " + userId);
Jeff Sharkey48877892015-03-18 11:27:19 -0700889
890 // We purposefully block here to make sure that user-specific
891 // staging area is ready so it's ready for zygote-forked apps to
892 // bind mount against.
893 try {
Jeff Sharkey54402792017-09-15 16:05:19 -0600894 mVold.onUserStarted(userId);
Jin Qian12690d52017-10-13 18:17:04 -0700895 mStoraged.onUserStarted(userId);
Jeff Sharkeyace874b2017-09-07 15:27:33 -0600896 } catch (Exception e) {
897 Slog.wtf(TAG, e);
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700898 }
Jeff Sharkey48877892015-03-18 11:27:19 -0700899
900 // Record user as started so newly mounted volumes kick off events
901 // correctly, then synthesize events for any already-mounted volumes.
yuanhuihuiefd1f122016-07-13 21:21:03 +0800902 synchronized (mLock) {
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -0700903 for (int i = 0; i < mVolumes.size(); i++) {
904 final VolumeInfo vol = mVolumes.valueAt(i);
Jeff Sharkey46349872015-07-28 10:49:47 -0700905 if (vol.isVisibleForRead(userId) && vol.isMountedReadable()) {
Svet Ganov6ee871e2015-07-10 14:29:33 -0700906 final StorageVolume userVol = vol.buildStorageVolume(mContext, userId, false);
Jeff Sharkey48877892015-03-18 11:27:19 -0700907 mHandler.obtainMessage(H_VOLUME_BROADCAST, userVol).sendToTarget();
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700908
Jeff Sharkey27de30d2015-04-18 16:20:27 -0700909 final String envState = VolumeInfo.getEnvironmentForState(vol.getState());
910 mCallbacks.notifyStorageStateChanged(userVol.getPath(), envState, envState);
Jeff Sharkey48877892015-03-18 11:27:19 -0700911 }
912 }
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700913 mSystemUnlockedUsers = ArrayUtils.appendInt(mSystemUnlockedUsers, userId);
Jeff Sharkey48877892015-03-18 11:27:19 -0700914 }
915 }
916
917 private void onCleanupUser(int userId) {
918 Slog.d(TAG, "onCleanupUser " + userId);
919
920 try {
Jeff Sharkey54402792017-09-15 16:05:19 -0600921 mVold.onUserStopped(userId);
Jin Qian12690d52017-10-13 18:17:04 -0700922 mStoraged.onUserStopped(userId);
Jeff Sharkeyace874b2017-09-07 15:27:33 -0600923 } catch (Exception e) {
924 Slog.wtf(TAG, e);
Jeff Sharkey48877892015-03-18 11:27:19 -0700925 }
926
yuanhuihuiefd1f122016-07-13 21:21:03 +0800927 synchronized (mLock) {
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700928 mSystemUnlockedUsers = ArrayUtils.removeInt(mSystemUnlockedUsers, userId);
Jeff Sharkey48877892015-03-18 11:27:19 -0700929 }
930 }
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700931
Jeff Sharkey9765e442017-12-14 22:15:14 -0700932 @Override
933 public void onAwakeStateChanged(boolean isAwake) {
934 // Ignored
935 }
936
937 @Override
938 public void onKeyguardStateChanged(boolean isShowing) {
939 // Push down current secure keyguard status so that we ignore malicious
940 // USB devices while locked.
941 mSecureKeyguardShowing = isShowing
942 && mContext.getSystemService(KeyguardManager.class).isDeviceSecure();
943 try {
944 mVold.onSecureKeyguardStateChanged(mSecureKeyguardShowing);
945 } catch (Exception e) {
946 Slog.wtf(TAG, e);
947 }
948 }
949
Christopher Tated417d622013-08-19 16:14:25 -0700950 void runIdleMaintenance(Runnable callback) {
951 mHandler.sendMessage(mHandler.obtainMessage(H_FSTRIM, callback));
952 }
953
Christopher Tate7265abe2014-11-21 13:54:45 -0800954 // Binder entry point for kicking off an immediate fstrim
955 @Override
956 public void runMaintenance() {
Jeff Sharkey48877892015-03-18 11:27:19 -0700957 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
Christopher Tate7265abe2014-11-21 13:54:45 -0800958 runIdleMaintenance(null);
959 }
960
961 @Override
962 public long lastMaintenance() {
963 return mLastMaintenance;
964 }
965
San Mehat4270e1e2010-01-29 05:32:19 -0800966 public void onDaemonConnected() {
Jeff Sharkey48877892015-03-18 11:27:19 -0700967 mDaemonConnected = true;
968 mHandler.obtainMessage(H_DAEMON_CONNECTED).sendToTarget();
969 }
970
971 private void handleDaemonConnected() {
Jeff Sharkey8924e872015-11-30 12:52:10 -0700972 initIfReadyAndConnected();
Jeff Sharkey5a9bb742015-11-03 10:15:57 -0800973 resetIfReadyAndConnected();
Jeff Sharkey48877892015-03-18 11:27:19 -0700974
Jeff Sharkey48877892015-03-18 11:27:19 -0700975 // On an encrypted device we can't see system properties yet, so pull
976 // the system locale out of the mount service.
Inseob Kim5b1cc272018-12-10 07:06:25 +0000977 if ("".equals(VoldProperties.encrypt_progress().orElse(""))) {
Jeff Sharkey48877892015-03-18 11:27:19 -0700978 copyLocaleFromMountService();
979 }
San Mehat4270e1e2010-01-29 05:32:19 -0800980 }
981
Elliott Hughesf839b4f2014-09-26 12:30:47 -0700982 private void copyLocaleFromMountService() {
983 String systemLocale;
984 try {
985 systemLocale = getField(StorageManager.SYSTEM_LOCALE_KEY);
986 } catch (RemoteException e) {
987 return;
988 }
989 if (TextUtils.isEmpty(systemLocale)) {
990 return;
991 }
992
993 Slog.d(TAG, "Got locale " + systemLocale + " from mount service");
994 Locale locale = Locale.forLanguageTag(systemLocale);
995 Configuration config = new Configuration();
996 config.setLocale(locale);
997 try {
Sudheer Shankadc589ac2016-11-10 15:30:17 -0800998 ActivityManager.getService().updatePersistentConfiguration(config);
Elliott Hughesf839b4f2014-09-26 12:30:47 -0700999 } catch (RemoteException e) {
1000 Slog.e(TAG, "Error setting system locale from mount service", e);
1001 }
Elliott Hughes9c33f282014-10-13 12:39:56 -07001002
1003 // Temporary workaround for http://b/17945169.
1004 Slog.d(TAG, "Setting system properties to " + systemLocale + " from mount service");
Narayan Kamathd30dbb82015-01-15 14:48:15 +00001005 SystemProperties.set("persist.sys.locale", locale.toLanguageTag());
Elliott Hughesf839b4f2014-09-26 12:30:47 -07001006 }
1007
Jeff Sharkey8058fe62017-09-13 11:50:33 -06001008 private final IVoldListener mListener = new IVoldListener.Stub() {
1009 @Override
1010 public void onDiskCreated(String diskId, int flags) {
1011 synchronized (mLock) {
Jeff Sharkey901c0422018-04-20 13:11:20 -06001012 final String value = SystemProperties.get(StorageManager.PROP_ADOPTABLE);
1013 switch (value) {
1014 case "force_on":
1015 flags |= DiskInfo.FLAG_ADOPTABLE;
1016 break;
1017 case "force_off":
1018 flags &= ~DiskInfo.FLAG_ADOPTABLE;
1019 break;
Jeff Sharkey8058fe62017-09-13 11:50:33 -06001020 }
Jeff Sharkey8058fe62017-09-13 11:50:33 -06001021 mDisks.put(diskId, new DiskInfo(diskId, flags));
1022 }
1023 }
1024
1025 @Override
1026 public void onDiskScanned(String diskId) {
1027 synchronized (mLock) {
1028 final DiskInfo disk = mDisks.get(diskId);
1029 if (disk != null) {
1030 onDiskScannedLocked(disk);
1031 }
1032 }
1033 }
1034
1035 @Override
1036 public void onDiskMetadataChanged(String diskId, long sizeBytes, String label,
1037 String sysPath) {
1038 synchronized (mLock) {
1039 final DiskInfo disk = mDisks.get(diskId);
1040 if (disk != null) {
1041 disk.size = sizeBytes;
1042 disk.label = label;
1043 disk.sysPath = sysPath;
1044 }
1045 }
1046 }
1047
1048 @Override
1049 public void onDiskDestroyed(String diskId) {
1050 synchronized (mLock) {
1051 final DiskInfo disk = mDisks.remove(diskId);
1052 if (disk != null) {
1053 mCallbacks.notifyDiskDestroyed(disk);
1054 }
1055 }
1056 }
1057
1058 @Override
1059 public void onVolumeCreated(String volId, int type, String diskId, String partGuid) {
1060 synchronized (mLock) {
1061 final DiskInfo disk = mDisks.get(diskId);
1062 final VolumeInfo vol = new VolumeInfo(volId, type, disk, partGuid);
1063 mVolumes.put(volId, vol);
1064 onVolumeCreatedLocked(vol);
1065 }
1066 }
1067
1068 @Override
1069 public void onVolumeStateChanged(String volId, int state) {
1070 synchronized (mLock) {
1071 final VolumeInfo vol = mVolumes.get(volId);
1072 if (vol != null) {
1073 final int oldState = vol.state;
1074 final int newState = state;
1075 vol.state = newState;
1076 onVolumeStateChangedLocked(vol, oldState, newState);
1077 }
1078 }
1079 }
1080
1081 @Override
1082 public void onVolumeMetadataChanged(String volId, String fsType, String fsUuid,
1083 String fsLabel) {
1084 synchronized (mLock) {
1085 final VolumeInfo vol = mVolumes.get(volId);
1086 if (vol != null) {
1087 vol.fsType = fsType;
1088 vol.fsUuid = fsUuid;
1089 vol.fsLabel = fsLabel;
1090 }
1091 }
1092 }
1093
1094 @Override
1095 public void onVolumePathChanged(String volId, String path) {
1096 synchronized (mLock) {
1097 final VolumeInfo vol = mVolumes.get(volId);
1098 if (vol != null) {
1099 vol.path = path;
1100 }
1101 }
1102 }
1103
1104 @Override
1105 public void onVolumeInternalPathChanged(String volId, String internalPath) {
1106 synchronized (mLock) {
1107 final VolumeInfo vol = mVolumes.get(volId);
1108 if (vol != null) {
1109 vol.internalPath = internalPath;
1110 }
1111 }
1112 }
1113
1114 @Override
1115 public void onVolumeDestroyed(String volId) {
1116 synchronized (mLock) {
1117 mVolumes.remove(volId);
1118 }
1119 }
1120 };
1121
Andreas Gampea36dc622018-02-05 17:19:22 -08001122 @GuardedBy("mLock")
Jeff Sharkeyeba260d2015-04-19 14:35:16 -07001123 private void onDiskScannedLocked(DiskInfo disk) {
Jeff Sharkey620b32b2015-04-23 19:36:02 -07001124 int volumeCount = 0;
Jeff Sharkeyeba260d2015-04-19 14:35:16 -07001125 for (int i = 0; i < mVolumes.size(); i++) {
1126 final VolumeInfo vol = mVolumes.valueAt(i);
1127 if (Objects.equals(disk.id, vol.getDiskId())) {
Jeff Sharkey620b32b2015-04-23 19:36:02 -07001128 volumeCount++;
Jeff Sharkeyeba260d2015-04-19 14:35:16 -07001129 }
1130 }
1131
Jeff Sharkeyc7acac62015-06-12 16:16:56 -07001132 final Intent intent = new Intent(DiskInfo.ACTION_DISK_SCANNED);
Jeff Sharkey7732e1e2016-03-30 17:14:23 -06001133 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT
1134 | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
Jeff Sharkeyc7acac62015-06-12 16:16:56 -07001135 intent.putExtra(DiskInfo.EXTRA_DISK_ID, disk.id);
1136 intent.putExtra(DiskInfo.EXTRA_VOLUME_COUNT, volumeCount);
Jeff Sharkeyabc3e852015-08-03 14:41:13 -07001137 mHandler.obtainMessage(H_INTERNAL_BROADCAST, intent).sendToTarget();
Jeff Sharkeyc7acac62015-06-12 16:16:56 -07001138
1139 final CountDownLatch latch = mDiskScanLatches.remove(disk.id);
1140 if (latch != null) {
1141 latch.countDown();
1142 }
1143
Jeff Sharkeyf5a6bd72015-05-19 14:42:38 -07001144 disk.volumeCount = volumeCount;
Jeff Sharkey620b32b2015-04-23 19:36:02 -07001145 mCallbacks.notifyDiskScanned(disk, volumeCount);
Jeff Sharkeyeba260d2015-04-19 14:35:16 -07001146 }
1147
Andreas Gampea36dc622018-02-05 17:19:22 -08001148 @GuardedBy("mLock")
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07001149 private void onVolumeCreatedLocked(VolumeInfo vol) {
Jeff Sharkey6855c482016-03-31 14:34:38 -06001150 if (mPms.isOnlyCoreApps()) {
1151 Slog.d(TAG, "System booted in core-only mode; ignoring volume " + vol.getId());
1152 return;
1153 }
1154
Jeff Sharkey275e3e42015-04-24 16:10:32 -07001155 if (vol.type == VolumeInfo.TYPE_EMULATED) {
1156 final StorageManager storage = mContext.getSystemService(StorageManager.class);
1157 final VolumeInfo privateVol = storage.findPrivateForEmulated(vol);
1158
1159 if (Objects.equals(StorageManager.UUID_PRIVATE_INTERNAL, mPrimaryStorageUuid)
1160 && VolumeInfo.ID_PRIVATE_INTERNAL.equals(privateVol.id)) {
1161 Slog.v(TAG, "Found primary storage at " + vol);
1162 vol.mountFlags |= VolumeInfo.MOUNT_FLAG_PRIMARY;
1163 vol.mountFlags |= VolumeInfo.MOUNT_FLAG_VISIBLE;
1164 mHandler.obtainMessage(H_VOLUME_MOUNT, vol).sendToTarget();
1165
1166 } else if (Objects.equals(privateVol.fsUuid, mPrimaryStorageUuid)) {
1167 Slog.v(TAG, "Found primary storage at " + vol);
1168 vol.mountFlags |= VolumeInfo.MOUNT_FLAG_PRIMARY;
1169 vol.mountFlags |= VolumeInfo.MOUNT_FLAG_VISIBLE;
1170 mHandler.obtainMessage(H_VOLUME_MOUNT, vol).sendToTarget();
1171 }
Jeff Sharkeyb049e212012-09-07 23:16:01 -07001172
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07001173 } else if (vol.type == VolumeInfo.TYPE_PUBLIC) {
Jeff Sharkey275e3e42015-04-24 16:10:32 -07001174 // TODO: only look at first public partition
1175 if (Objects.equals(StorageManager.UUID_PRIMARY_PHYSICAL, mPrimaryStorageUuid)
1176 && vol.disk.isDefaultPrimary()) {
1177 Slog.v(TAG, "Found primary storage at " + vol);
Jeff Sharkey7e92ef32015-04-17 17:35:07 -07001178 vol.mountFlags |= VolumeInfo.MOUNT_FLAG_PRIMARY;
1179 vol.mountFlags |= VolumeInfo.MOUNT_FLAG_VISIBLE;
San Mehat4270e1e2010-01-29 05:32:19 -08001180 }
Jeff Sharkey7e92ef32015-04-17 17:35:07 -07001181
1182 // Adoptable public disks are visible to apps, since they meet
1183 // public API requirement of being in a stable location.
Jeff Sharkey275e3e42015-04-24 16:10:32 -07001184 if (vol.disk.isAdoptable()) {
Jeff Sharkey7e92ef32015-04-17 17:35:07 -07001185 vol.mountFlags |= VolumeInfo.MOUNT_FLAG_VISIBLE;
1186 }
1187
Jeff Sharkeyab15c392016-05-05 11:45:01 -06001188 vol.mountUserId = mCurrentUserId;
Jeff Sharkey48877892015-03-18 11:27:19 -07001189 mHandler.obtainMessage(H_VOLUME_MOUNT, vol).sendToTarget();
San Mehat4270e1e2010-01-29 05:32:19 -08001190
Jeff Sharkeyb2b9ab82015-04-05 21:10:42 -07001191 } else if (vol.type == VolumeInfo.TYPE_PRIVATE) {
1192 mHandler.obtainMessage(H_VOLUME_MOUNT, vol).sendToTarget();
1193
Risan05c41e62018-10-29 08:57:43 +09001194 } else if (vol.type == VolumeInfo.TYPE_STUB) {
1195 vol.mountUserId = mCurrentUserId;
1196 mHandler.obtainMessage(H_VOLUME_MOUNT, vol).sendToTarget();
San Mehat4270e1e2010-01-29 05:32:19 -08001197 } else {
Jeff Sharkey48877892015-03-18 11:27:19 -07001198 Slog.d(TAG, "Skipping automatic mounting of " + vol);
San Mehat4270e1e2010-01-29 05:32:19 -08001199 }
1200 }
1201
Jeff Sharkeye6c04f92015-04-18 21:38:05 -07001202 private boolean isBroadcastWorthy(VolumeInfo vol) {
1203 switch (vol.getType()) {
Jeff Sharkeyc7acac62015-06-12 16:16:56 -07001204 case VolumeInfo.TYPE_PRIVATE:
Jeff Sharkeye6c04f92015-04-18 21:38:05 -07001205 case VolumeInfo.TYPE_PUBLIC:
1206 case VolumeInfo.TYPE_EMULATED:
Risan05c41e62018-10-29 08:57:43 +09001207 case VolumeInfo.TYPE_STUB:
Jeff Sharkeye6c04f92015-04-18 21:38:05 -07001208 break;
1209 default:
1210 return false;
1211 }
1212
1213 switch (vol.getState()) {
1214 case VolumeInfo.STATE_MOUNTED:
1215 case VolumeInfo.STATE_MOUNTED_READ_ONLY:
1216 case VolumeInfo.STATE_EJECTING:
1217 case VolumeInfo.STATE_UNMOUNTED:
Jeff Sharkeyc7acac62015-06-12 16:16:56 -07001218 case VolumeInfo.STATE_UNMOUNTABLE:
Tony Mantlerf0d71052015-06-24 11:45:25 -07001219 case VolumeInfo.STATE_BAD_REMOVAL:
Jeff Sharkeye6c04f92015-04-18 21:38:05 -07001220 break;
1221 default:
1222 return false;
1223 }
1224
1225 return true;
1226 }
1227
Andreas Gampea36dc622018-02-05 17:19:22 -08001228 @GuardedBy("mLock")
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07001229 private void onVolumeStateChangedLocked(VolumeInfo vol, int oldState, int newState) {
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001230 // Remember that we saw this volume so we're ready to accept user
1231 // metadata, or so we can annoy them when a private volume is ejected
1232 if (vol.isMountedReadable() && !TextUtils.isEmpty(vol.fsUuid)) {
Jeff Sharkey5cc0df22015-06-17 19:44:05 -07001233 VolumeRecord rec = mRecords.get(vol.fsUuid);
1234 if (rec == null) {
1235 rec = new VolumeRecord(vol.type, vol.fsUuid);
1236 rec.partGuid = vol.partGuid;
Jeff Sharkeye8a4b662015-06-27 15:43:45 -07001237 rec.createdMillis = System.currentTimeMillis();
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001238 if (vol.type == VolumeInfo.TYPE_PRIVATE) {
1239 rec.nickname = vol.disk.getDescription();
1240 }
1241 mRecords.put(rec.fsUuid, rec);
1242 writeSettingsLocked();
Jeff Sharkey5cc0df22015-06-17 19:44:05 -07001243 } else {
1244 // Handle upgrade case where we didn't store partition GUID
1245 if (TextUtils.isEmpty(rec.partGuid)) {
1246 rec.partGuid = vol.partGuid;
1247 writeSettingsLocked();
1248 }
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001249 }
1250 }
1251
Jeff Sharkeye6c04f92015-04-18 21:38:05 -07001252 mCallbacks.notifyVolumeStateChanged(vol, oldState, newState);
1253
Yasuhiro Matsuda87a38b52015-07-24 22:10:16 +09001254 // Do not broadcast before boot has completed to avoid launching the
1255 // processes that receive the intent unnecessarily.
1256 if (mBootCompleted && isBroadcastWorthy(vol)) {
Jeff Sharkeye6c04f92015-04-18 21:38:05 -07001257 final Intent intent = new Intent(VolumeInfo.ACTION_VOLUME_STATE_CHANGED);
Jeff Sharkeyc7acac62015-06-12 16:16:56 -07001258 intent.putExtra(VolumeInfo.EXTRA_VOLUME_ID, vol.id);
1259 intent.putExtra(VolumeInfo.EXTRA_VOLUME_STATE, newState);
Tony Mantlerf0d71052015-06-24 11:45:25 -07001260 intent.putExtra(VolumeRecord.EXTRA_FS_UUID, vol.fsUuid);
Jeff Sharkey7732e1e2016-03-30 17:14:23 -06001261 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT
1262 | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
Jeff Sharkeyabc3e852015-08-03 14:41:13 -07001263 mHandler.obtainMessage(H_INTERNAL_BROADCAST, intent).sendToTarget();
Jeff Sharkeye6c04f92015-04-18 21:38:05 -07001264 }
Jeff Sharkeyb049e212012-09-07 23:16:01 -07001265
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001266 final String oldStateEnv = VolumeInfo.getEnvironmentForState(oldState);
1267 final String newStateEnv = VolumeInfo.getEnvironmentForState(newState);
Emily Bernier92aa5a22014-07-07 10:11:48 -04001268
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001269 if (!Objects.equals(oldStateEnv, newStateEnv)) {
1270 // Kick state changed event towards all started users. Any users
1271 // started after this point will trigger additional
1272 // user-specific broadcasts.
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07001273 for (int userId : mSystemUnlockedUsers) {
Jeff Sharkey46349872015-07-28 10:49:47 -07001274 if (vol.isVisibleForRead(userId)) {
Svet Ganov6ee871e2015-07-10 14:29:33 -07001275 final StorageVolume userVol = vol.buildStorageVolume(mContext, userId, false);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001276 mHandler.obtainMessage(H_VOLUME_BROADCAST, userVol).sendToTarget();
Jeff Sharkey48877892015-03-18 11:27:19 -07001277
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001278 mCallbacks.notifyStorageStateChanged(userVol.getPath(), oldStateEnv,
1279 newStateEnv);
San Mehat4270e1e2010-01-29 05:32:19 -08001280 }
1281 }
1282 }
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001283
Risan05c41e62018-10-29 08:57:43 +09001284 if ((vol.type == VolumeInfo.TYPE_PUBLIC || vol.type == VolumeInfo.TYPE_STUB)
1285 && vol.state == VolumeInfo.STATE_EJECTING) {
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001286 // TODO: this should eventually be handled by new ObbVolume state changes
1287 /*
1288 * Some OBBs might have been unmounted when this volume was
1289 * unmounted, so send a message to the handler to let it know to
1290 * remove those from the list of mounted OBBS.
1291 */
1292 mObbActionHandler.sendMessage(mObbActionHandler.obtainMessage(
1293 OBB_FLUSH_MOUNT_STATE, vol.path));
1294 }
Pavel Grafovce72ef02018-01-10 17:14:11 +00001295 maybeLogMediaMount(vol, newState);
1296 }
1297
1298 private void maybeLogMediaMount(VolumeInfo vol, int newState) {
1299 if (!SecurityLog.isLoggingEnabled()) {
1300 return;
1301 }
1302
1303 final DiskInfo disk = vol.getDisk();
1304 if (disk == null || (disk.flags & (DiskInfo.FLAG_SD | DiskInfo.FLAG_USB)) == 0) {
1305 return;
1306 }
1307
1308 // Sometimes there is a newline character.
1309 final String label = disk.label != null ? disk.label.trim() : "";
1310
1311 if (newState == VolumeInfo.STATE_MOUNTED
1312 || newState == VolumeInfo.STATE_MOUNTED_READ_ONLY) {
1313 SecurityLog.writeEvent(SecurityLog.TAG_MEDIA_MOUNT, vol.path, label);
1314 } else if (newState == VolumeInfo.STATE_UNMOUNTED
1315 || newState == VolumeInfo.STATE_BAD_REMOVAL) {
1316 SecurityLog.writeEvent(SecurityLog.TAG_MEDIA_UNMOUNT, vol.path, label);
1317 }
San Mehat4270e1e2010-01-29 05:32:19 -08001318 }
1319
Andreas Gampea36dc622018-02-05 17:19:22 -08001320 @GuardedBy("mLock")
Jeff Sharkey275e3e42015-04-24 16:10:32 -07001321 private void onMoveStatusLocked(int status) {
1322 if (mMoveCallback == null) {
1323 Slog.w(TAG, "Odd, status but no move requested");
1324 return;
1325 }
1326
1327 // TODO: estimate remaining time
1328 try {
Jeff Sharkey50a05452015-04-29 11:24:52 -07001329 mMoveCallback.onStatusChanged(-1, status, -1);
Jeff Sharkey275e3e42015-04-24 16:10:32 -07001330 } catch (RemoteException ignored) {
1331 }
1332
1333 // We've finished copying and we're about to clean up old data, so
1334 // remember that move was successful if we get rebooted
1335 if (status == MOVE_STATUS_COPY_FINISHED) {
1336 Slog.d(TAG, "Move to " + mMoveTargetUuid + " copy phase finshed; persisting");
1337
1338 mPrimaryStorageUuid = mMoveTargetUuid;
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001339 writeSettingsLocked();
Jeff Sharkey275e3e42015-04-24 16:10:32 -07001340 }
1341
1342 if (PackageManager.isMoveStatusFinished(status)) {
1343 Slog.d(TAG, "Move to " + mMoveTargetUuid + " finished with status " + status);
1344
1345 mMoveCallback = null;
1346 mMoveTargetUuid = null;
1347 }
1348 }
1349
Jeff Sharkey48877892015-03-18 11:27:19 -07001350 private void enforcePermission(String perm) {
1351 mContext.enforceCallingOrSelfPermission(perm, perm);
Mike Lockwooda5250c92011-05-23 13:44:04 -04001352 }
1353
Jeff Sharkey2e606d72015-07-27 14:19:54 -07001354 /**
1355 * Decide if volume is mountable per device policies.
1356 */
1357 private boolean isMountDisallowed(VolumeInfo vol) {
Philip P. Moltmannec3cbb22016-09-14 13:24:52 -07001358 UserManager userManager = mContext.getSystemService(UserManager.class);
1359
1360 boolean isUsbRestricted = false;
1361 if (vol.disk != null && vol.disk.isUsb()) {
1362 isUsbRestricted = userManager.hasUserRestriction(UserManager.DISALLOW_USB_FILE_TRANSFER,
Jeff Sharkey2e606d72015-07-27 14:19:54 -07001363 Binder.getCallingUserHandle());
Emily Bernier92aa5a22014-07-07 10:11:48 -04001364 }
Philip P. Moltmannec3cbb22016-09-14 13:24:52 -07001365
1366 boolean isTypeRestricted = false;
Risan05c41e62018-10-29 08:57:43 +09001367 if (vol.type == VolumeInfo.TYPE_PUBLIC || vol.type == VolumeInfo.TYPE_PRIVATE
1368 || vol.type == VolumeInfo.TYPE_STUB) {
Philip P. Moltmannec3cbb22016-09-14 13:24:52 -07001369 isTypeRestricted = userManager
1370 .hasUserRestriction(UserManager.DISALLOW_MOUNT_PHYSICAL_MEDIA,
1371 Binder.getCallingUserHandle());
1372 }
1373
1374 return isUsbRestricted || isTypeRestricted;
Emily Bernier92aa5a22014-07-07 10:11:48 -04001375 }
1376
Amith Yamasani462ac3a2015-06-30 14:21:01 -07001377 private void enforceAdminUser() {
1378 UserManager um = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
1379 final int callingUserId = UserHandle.getCallingUserId();
1380 boolean isAdmin;
1381 long token = Binder.clearCallingIdentity();
1382 try {
1383 isAdmin = um.getUserInfo(callingUserId).isAdmin();
1384 } finally {
1385 Binder.restoreCallingIdentity(token);
1386 }
1387 if (!isAdmin) {
1388 throw new SecurityException("Only admin users can adopt sd cards");
1389 }
1390 }
1391
Jeff Sharkeyb049e212012-09-07 23:16:01 -07001392 /**
Sudheer Shanka2250d562016-11-07 15:41:02 -08001393 * Constructs a new StorageManagerService instance
San Mehat207e5382010-02-04 20:46:54 -08001394 *
1395 * @param context Binder context for this service
1396 */
Sudheer Shanka2250d562016-11-07 15:41:02 -08001397 public StorageManagerService(Context context) {
Christopher Tated417d622013-08-19 16:14:25 -07001398 sSelf = this;
1399
San Mehat207e5382010-02-04 20:46:54 -08001400 mContext = context;
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001401 mCallbacks = new Callbacks(FgThread.get().getLooper());
Jeff Sharkeyb9fe5372015-12-03 15:23:08 -07001402 mLockPatternUtils = new LockPatternUtils(mContext);
San Mehat207e5382010-02-04 20:46:54 -08001403
San Mehat207e5382010-02-04 20:46:54 -08001404 // XXX: This will go away soon in favor of IMountServiceObserver
1405 mPms = (PackageManagerService) ServiceManager.getService("package");
1406
Dianne Hackbornefa92b22013-05-03 14:11:43 -07001407 HandlerThread hthread = new HandlerThread(TAG);
1408 hthread.start();
Sudheer Shanka2250d562016-11-07 15:41:02 -08001409 mHandler = new StorageManagerServiceHandler(hthread.getLooper());
Daniel Sandler5f27ef42010-03-16 15:42:02 -04001410
Sudheer Shanka2250d562016-11-07 15:41:02 -08001411 // Add OBB Action Handler to StorageManagerService thread.
Dianne Hackborn8d044e82013-04-30 17:24:15 -07001412 mObbActionHandler = new ObbActionHandler(IoThread.get().getLooper());
Kenny Roota02b8b02010-08-05 16:14:17 -07001413
Christopher Tate7265abe2014-11-21 13:54:45 -08001414 // Initialize the last-fstrim tracking if necessary
1415 File dataDir = Environment.getDataDirectory();
1416 File systemDir = new File(dataDir, "system");
1417 mLastMaintenanceFile = new File(systemDir, LAST_FSTRIM_FILE);
1418 if (!mLastMaintenanceFile.exists()) {
1419 // Not setting mLastMaintenance here means that we will force an
1420 // fstrim during reboot following the OTA that installs this code.
1421 try {
1422 (new FileOutputStream(mLastMaintenanceFile)).close();
1423 } catch (IOException e) {
1424 Slog.e(TAG, "Unable to create fstrim record " + mLastMaintenanceFile.getPath());
1425 }
1426 } else {
1427 mLastMaintenance = mLastMaintenanceFile.lastModified();
1428 }
1429
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001430 mSettingsFile = new AtomicFile(
Dianne Hackborne17b4452018-01-10 13:15:40 -08001431 new File(Environment.getDataSystemDirectory(), "storage.xml"), "storage-settings");
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001432
1433 synchronized (mLock) {
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001434 readSettingsLocked();
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001435 }
1436
Sudheer Shanka2250d562016-11-07 15:41:02 -08001437 LocalServices.addService(StorageManagerInternal.class, mStorageManagerInternal);
Svet Ganov6ee871e2015-07-10 14:29:33 -07001438
Jeff Sharkeybcd262d2015-06-10 09:41:17 -07001439 final IntentFilter userFilter = new IntentFilter();
1440 userFilter.addAction(Intent.ACTION_USER_ADDED);
1441 userFilter.addAction(Intent.ACTION_USER_REMOVED);
1442 mContext.registerReceiver(mUserReceiver, userFilter, null, mHandler);
1443
Jeff Sharkey5a9bb742015-11-03 10:15:57 -08001444 synchronized (mLock) {
1445 addInternalVolumeLocked();
1446 }
Amith Yamasania7892482015-08-07 11:09:05 -07001447
Kenny Root07714d42011-08-17 17:49:28 -07001448 // Add ourself to the Watchdog monitors if enabled.
1449 if (WATCHDOG_ENABLE) {
1450 Watchdog.getInstance().addMonitor(this);
1451 }
San Mehat207e5382010-02-04 20:46:54 -08001452 }
1453
Jeff Sharkeycd575992016-03-29 14:12:49 -06001454 private void start() {
Jeff Sharkey1019de92017-09-06 13:47:03 -06001455 connect();
Jeff Sharkeycd575992016-03-29 14:12:49 -06001456 }
1457
Jeff Sharkey1019de92017-09-06 13:47:03 -06001458 private void connect() {
Jin Qian12690d52017-10-13 18:17:04 -07001459 IBinder binder = ServiceManager.getService("storaged");
1460 if (binder != null) {
1461 try {
1462 binder.linkToDeath(new DeathRecipient() {
1463 @Override
1464 public void binderDied() {
1465 Slog.w(TAG, "storaged died; reconnecting");
1466 mStoraged = null;
1467 connect();
1468 }
1469 }, 0);
1470 } catch (RemoteException e) {
1471 binder = null;
1472 }
1473 }
1474
1475 if (binder != null) {
1476 mStoraged = IStoraged.Stub.asInterface(binder);
1477 } else {
1478 Slog.w(TAG, "storaged not found; trying again");
1479 }
1480
1481 binder = ServiceManager.getService("vold");
Jeff Sharkey1019de92017-09-06 13:47:03 -06001482 if (binder != null) {
1483 try {
1484 binder.linkToDeath(new DeathRecipient() {
1485 @Override
1486 public void binderDied() {
1487 Slog.w(TAG, "vold died; reconnecting");
Jin Qian12690d52017-10-13 18:17:04 -07001488 mVold = null;
Jeff Sharkey1019de92017-09-06 13:47:03 -06001489 connect();
1490 }
1491 }, 0);
1492 } catch (RemoteException e) {
1493 binder = null;
1494 }
1495 }
1496
1497 if (binder != null) {
1498 mVold = IVold.Stub.asInterface(binder);
Jeff Sharkey8058fe62017-09-13 11:50:33 -06001499 try {
1500 mVold.setListener(mListener);
Jeff Sharkey8058fe62017-09-13 11:50:33 -06001501 } catch (RemoteException e) {
Jin Qian12690d52017-10-13 18:17:04 -07001502 mVold = null;
Jeff Sharkey8058fe62017-09-13 11:50:33 -06001503 Slog.w(TAG, "vold listener rejected; trying again", e);
1504 }
Jeff Sharkey1019de92017-09-06 13:47:03 -06001505 } else {
1506 Slog.w(TAG, "vold not found; trying again");
Jeff Sharkey1019de92017-09-06 13:47:03 -06001507 }
Jeff Sharkey8058fe62017-09-13 11:50:33 -06001508
Jin Qian12690d52017-10-13 18:17:04 -07001509 if (mStoraged == null || mVold == null) {
1510 BackgroundThread.getHandler().postDelayed(() -> {
1511 connect();
1512 }, DateUtils.SECOND_IN_MILLIS);
1513 } else {
1514 onDaemonConnected();
1515 }
Jeff Sharkey1019de92017-09-06 13:47:03 -06001516 }
1517
Jeff Sharkey56e62932015-03-21 20:41:00 -07001518 private void systemReady() {
Jeff Sharkey9765e442017-12-14 22:15:14 -07001519 LocalServices.getService(ActivityManagerInternal.class)
1520 .registerScreenObserver(this);
1521
Jeff Sharkeyb049e212012-09-07 23:16:01 -07001522 mSystemReady = true;
1523 mHandler.obtainMessage(H_SYSTEM_READY).sendToTarget();
1524 }
1525
Yasuhiro Matsuda87a38b52015-07-24 22:10:16 +09001526 private void bootCompleted() {
1527 mBootCompleted = true;
1528 }
1529
Jeff Sharkeyfced5342015-05-10 14:53:34 -07001530 private String getDefaultPrimaryStorageUuid() {
1531 if (SystemProperties.getBoolean(StorageManager.PROP_PRIMARY_PHYSICAL, false)) {
1532 return StorageManager.UUID_PRIMARY_PHYSICAL;
1533 } else {
1534 return StorageManager.UUID_PRIVATE_INTERNAL;
1535 }
1536 }
1537
Andreas Gampea36dc622018-02-05 17:19:22 -08001538 @GuardedBy("mLock")
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001539 private void readSettingsLocked() {
1540 mRecords.clear();
Jeff Sharkeyfced5342015-05-10 14:53:34 -07001541 mPrimaryStorageUuid = getDefaultPrimaryStorageUuid();
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001542
1543 FileInputStream fis = null;
1544 try {
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001545 fis = mSettingsFile.openRead();
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001546 final XmlPullParser in = Xml.newPullParser();
Wojciech Staszkiewicz9e9e2e72015-05-08 14:58:46 +01001547 in.setInput(fis, StandardCharsets.UTF_8.name());
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001548
1549 int type;
1550 while ((type = in.next()) != END_DOCUMENT) {
1551 if (type == START_TAG) {
1552 final String tag = in.getName();
Jeff Sharkey620b32b2015-04-23 19:36:02 -07001553 if (TAG_VOLUMES.equals(tag)) {
1554 final int version = readIntAttribute(in, ATTR_VERSION, VERSION_INIT);
Jeff Sharkeyfced5342015-05-10 14:53:34 -07001555 final boolean primaryPhysical = SystemProperties.getBoolean(
1556 StorageManager.PROP_PRIMARY_PHYSICAL, false);
1557 final boolean validAttr = (version >= VERSION_FIX_PRIMARY)
1558 || (version >= VERSION_ADD_PRIMARY && !primaryPhysical);
1559 if (validAttr) {
Jeff Sharkey620b32b2015-04-23 19:36:02 -07001560 mPrimaryStorageUuid = readStringAttribute(in,
1561 ATTR_PRIMARY_STORAGE_UUID);
Jeff Sharkey620b32b2015-04-23 19:36:02 -07001562 }
1563
1564 } else if (TAG_VOLUME.equals(tag)) {
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001565 final VolumeRecord rec = readVolumeRecord(in);
1566 mRecords.put(rec.fsUuid, rec);
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001567 }
1568 }
1569 }
1570 } catch (FileNotFoundException e) {
1571 // Missing metadata is okay, probably first boot
1572 } catch (IOException e) {
1573 Slog.wtf(TAG, "Failed reading metadata", e);
1574 } catch (XmlPullParserException e) {
1575 Slog.wtf(TAG, "Failed reading metadata", e);
1576 } finally {
1577 IoUtils.closeQuietly(fis);
1578 }
1579 }
1580
Andreas Gampea36dc622018-02-05 17:19:22 -08001581 @GuardedBy("mLock")
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001582 private void writeSettingsLocked() {
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001583 FileOutputStream fos = null;
1584 try {
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001585 fos = mSettingsFile.startWrite();
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001586
1587 XmlSerializer out = new FastXmlSerializer();
Wojciech Staszkiewicz9e9e2e72015-05-08 14:58:46 +01001588 out.setOutput(fos, StandardCharsets.UTF_8.name());
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001589 out.startDocument(null, true);
1590 out.startTag(null, TAG_VOLUMES);
Jeff Sharkeyfced5342015-05-10 14:53:34 -07001591 writeIntAttribute(out, ATTR_VERSION, VERSION_FIX_PRIMARY);
Jeff Sharkey620b32b2015-04-23 19:36:02 -07001592 writeStringAttribute(out, ATTR_PRIMARY_STORAGE_UUID, mPrimaryStorageUuid);
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001593 final int size = mRecords.size();
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001594 for (int i = 0; i < size; i++) {
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001595 final VolumeRecord rec = mRecords.valueAt(i);
1596 writeVolumeRecord(out, rec);
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001597 }
1598 out.endTag(null, TAG_VOLUMES);
1599 out.endDocument();
1600
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001601 mSettingsFile.finishWrite(fos);
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001602 } catch (IOException e) {
1603 if (fos != null) {
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001604 mSettingsFile.failWrite(fos);
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001605 }
1606 }
1607 }
1608
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001609 public static VolumeRecord readVolumeRecord(XmlPullParser in) throws IOException {
1610 final int type = readIntAttribute(in, ATTR_TYPE);
1611 final String fsUuid = readStringAttribute(in, ATTR_FS_UUID);
1612 final VolumeRecord meta = new VolumeRecord(type, fsUuid);
Jeff Sharkey5cc0df22015-06-17 19:44:05 -07001613 meta.partGuid = readStringAttribute(in, ATTR_PART_GUID);
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001614 meta.nickname = readStringAttribute(in, ATTR_NICKNAME);
1615 meta.userFlags = readIntAttribute(in, ATTR_USER_FLAGS);
Jeff Sharkeye8a4b662015-06-27 15:43:45 -07001616 meta.createdMillis = readLongAttribute(in, ATTR_CREATED_MILLIS);
1617 meta.lastTrimMillis = readLongAttribute(in, ATTR_LAST_TRIM_MILLIS);
1618 meta.lastBenchMillis = readLongAttribute(in, ATTR_LAST_BENCH_MILLIS);
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001619 return meta;
1620 }
1621
1622 public static void writeVolumeRecord(XmlSerializer out, VolumeRecord rec) throws IOException {
1623 out.startTag(null, TAG_VOLUME);
1624 writeIntAttribute(out, ATTR_TYPE, rec.type);
1625 writeStringAttribute(out, ATTR_FS_UUID, rec.fsUuid);
Jeff Sharkey5cc0df22015-06-17 19:44:05 -07001626 writeStringAttribute(out, ATTR_PART_GUID, rec.partGuid);
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001627 writeStringAttribute(out, ATTR_NICKNAME, rec.nickname);
1628 writeIntAttribute(out, ATTR_USER_FLAGS, rec.userFlags);
Jeff Sharkeye8a4b662015-06-27 15:43:45 -07001629 writeLongAttribute(out, ATTR_CREATED_MILLIS, rec.createdMillis);
1630 writeLongAttribute(out, ATTR_LAST_TRIM_MILLIS, rec.lastTrimMillis);
1631 writeLongAttribute(out, ATTR_LAST_BENCH_MILLIS, rec.lastBenchMillis);
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001632 out.endTag(null, TAG_VOLUME);
1633 }
1634
San Mehat207e5382010-02-04 20:46:54 -08001635 /**
San Mehat4270e1e2010-01-29 05:32:19 -08001636 * Exposed API calls below here
1637 */
1638
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001639 @Override
Sudheer Shanka2250d562016-11-07 15:41:02 -08001640 public void registerListener(IStorageEventListener listener) {
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001641 mCallbacks.register(listener);
San Mehat4270e1e2010-01-29 05:32:19 -08001642 }
1643
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001644 @Override
Sudheer Shanka2250d562016-11-07 15:41:02 -08001645 public void unregisterListener(IStorageEventListener listener) {
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001646 mCallbacks.unregister(listener);
San Mehat4270e1e2010-01-29 05:32:19 -08001647 }
1648
Jeff Sharkey48877892015-03-18 11:27:19 -07001649 @Override
Sudheer Shanka2250d562016-11-07 15:41:02 -08001650 public void shutdown(final IStorageShutdownObserver observer) {
Jeff Sharkey48877892015-03-18 11:27:19 -07001651 enforcePermission(android.Manifest.permission.SHUTDOWN);
San Mehat4270e1e2010-01-29 05:32:19 -08001652
San Mehata5078592010-03-25 09:36:54 -07001653 Slog.i(TAG, "Shutting down");
Jeff Sharkey48877892015-03-18 11:27:19 -07001654 mHandler.obtainMessage(H_SHUTDOWN, observer).sendToTarget();
San Mehat4270e1e2010-01-29 05:32:19 -08001655 }
1656
Jeff Sharkey48877892015-03-18 11:27:19 -07001657 @Override
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001658 public void mount(String volId) {
1659 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001660
Jeff Sharkeyef10ee02015-07-05 14:17:27 -07001661 final VolumeInfo vol = findVolumeByIdOrThrow(volId);
Jeff Sharkey2e606d72015-07-27 14:19:54 -07001662 if (isMountDisallowed(vol)) {
1663 throw new SecurityException("Mounting " + volId + " restricted by policy");
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001664 }
1665 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06001666 mVold.mount(vol.id, vol.mountFlags, vol.mountUserId);
Jeff Sharkeyace874b2017-09-07 15:27:33 -06001667 } catch (Exception e) {
1668 Slog.wtf(TAG, e);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001669 }
1670 }
1671
1672 @Override
1673 public void unmount(String volId) {
1674 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001675
Jeff Sharkeyef10ee02015-07-05 14:17:27 -07001676 final VolumeInfo vol = findVolumeByIdOrThrow(volId);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001677 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06001678 mVold.unmount(vol.id);
Jeff Sharkeyace874b2017-09-07 15:27:33 -06001679 } catch (Exception e) {
1680 Slog.wtf(TAG, e);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001681 }
1682 }
1683
1684 @Override
1685 public void format(String volId) {
Jeff Sharkey48877892015-03-18 11:27:19 -07001686 enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);
San Mehat5b77dab2010-01-26 13:28:50 -08001687
Jeff Sharkeyef10ee02015-07-05 14:17:27 -07001688 final VolumeInfo vol = findVolumeByIdOrThrow(volId);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001689 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06001690 mVold.format(vol.id, "auto");
Jeff Sharkeyace874b2017-09-07 15:27:33 -06001691 } catch (Exception e) {
1692 Slog.wtf(TAG, e);
Jeff Sharkey48877892015-03-18 11:27:19 -07001693 }
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001694 }
1695
1696 @Override
Jeff Sharkey7e19f532017-11-06 13:54:11 -07001697 public void benchmark(String volId, IVoldTaskListener listener) {
Jeff Sharkey9756d752015-05-14 21:07:42 -07001698 enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);
Jeff Sharkey9756d752015-05-14 21:07:42 -07001699
1700 try {
Jeff Sharkeyb302c542017-09-15 12:57:59 -06001701 mVold.benchmark(volId, new IVoldTaskListener.Stub() {
1702 @Override
1703 public void onStatus(int status, PersistableBundle extras) {
Jeff Sharkey7e19f532017-11-06 13:54:11 -07001704 dispatchOnStatus(listener, status, extras);
Jeff Sharkeyb302c542017-09-15 12:57:59 -06001705 }
1706
1707 @Override
1708 public void onFinished(int status, PersistableBundle extras) {
Jeff Sharkey7e19f532017-11-06 13:54:11 -07001709 dispatchOnFinished(listener, status, extras);
Jeff Sharkeyb302c542017-09-15 12:57:59 -06001710
1711 final String path = extras.getString("path");
1712 final String ident = extras.getString("ident");
1713 final long create = extras.getLong("create");
1714 final long run = extras.getLong("run");
1715 final long destroy = extras.getLong("destroy");
1716
1717 final DropBoxManager dropBox = mContext.getSystemService(DropBoxManager.class);
1718 dropBox.addText(TAG_STORAGE_BENCHMARK, scrubPath(path)
1719 + " " + ident + " " + create + " " + run + " " + destroy);
1720
1721 synchronized (mLock) {
1722 final VolumeRecord rec = findRecordForPath(path);
1723 if (rec != null) {
1724 rec.lastBenchMillis = System.currentTimeMillis();
1725 writeSettingsLocked();
1726 }
1727 }
1728 }
1729 });
Jeff Sharkey7e19f532017-11-06 13:54:11 -07001730 } catch (RemoteException e) {
1731 throw e.rethrowAsRuntimeException();
Jeff Sharkey9756d752015-05-14 21:07:42 -07001732 }
1733 }
1734
1735 @Override
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001736 public void partitionPublic(String diskId) {
1737 enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001738
Jeff Sharkeyeba260d2015-04-19 14:35:16 -07001739 final CountDownLatch latch = findOrCreateDiskScanLatch(diskId);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001740 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06001741 mVold.partition(diskId, IVold.PARTITION_TYPE_PUBLIC, -1);
Jeff Sharkeyedcdaf62015-07-09 09:45:36 -07001742 waitForLatch(latch, "partitionPublic", 3 * DateUtils.MINUTE_IN_MILLIS);
Jeff Sharkeyace874b2017-09-07 15:27:33 -06001743 } catch (Exception e) {
1744 Slog.wtf(TAG, e);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001745 }
1746 }
1747
1748 @Override
1749 public void partitionPrivate(String diskId) {
1750 enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);
Amith Yamasani462ac3a2015-06-30 14:21:01 -07001751 enforceAdminUser();
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001752
Jeff Sharkeyeba260d2015-04-19 14:35:16 -07001753 final CountDownLatch latch = findOrCreateDiskScanLatch(diskId);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001754 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06001755 mVold.partition(diskId, IVold.PARTITION_TYPE_PRIVATE, -1);
Jeff Sharkeyedcdaf62015-07-09 09:45:36 -07001756 waitForLatch(latch, "partitionPrivate", 3 * DateUtils.MINUTE_IN_MILLIS);
Jeff Sharkeyace874b2017-09-07 15:27:33 -06001757 } catch (Exception e) {
1758 Slog.wtf(TAG, e);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001759 }
1760 }
1761
1762 @Override
1763 public void partitionMixed(String diskId, int ratio) {
1764 enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);
Amith Yamasani462ac3a2015-06-30 14:21:01 -07001765 enforceAdminUser();
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001766
Jeff Sharkeyeba260d2015-04-19 14:35:16 -07001767 final CountDownLatch latch = findOrCreateDiskScanLatch(diskId);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001768 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06001769 mVold.partition(diskId, IVold.PARTITION_TYPE_MIXED, ratio);
Jeff Sharkeyedcdaf62015-07-09 09:45:36 -07001770 waitForLatch(latch, "partitionMixed", 3 * DateUtils.MINUTE_IN_MILLIS);
Jeff Sharkeyace874b2017-09-07 15:27:33 -06001771 } catch (Exception e) {
1772 Slog.wtf(TAG, e);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001773 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001774 }
1775
Jeff Sharkey48877892015-03-18 11:27:19 -07001776 @Override
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001777 public void setVolumeNickname(String fsUuid, String nickname) {
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001778 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001779
Jeff Sharkey50a05452015-04-29 11:24:52 -07001780 Preconditions.checkNotNull(fsUuid);
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001781 synchronized (mLock) {
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001782 final VolumeRecord rec = mRecords.get(fsUuid);
1783 rec.nickname = nickname;
Jeff Sharkey50a05452015-04-29 11:24:52 -07001784 mCallbacks.notifyVolumeRecordChanged(rec);
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001785 writeSettingsLocked();
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001786 }
1787 }
1788
1789 @Override
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001790 public void setVolumeUserFlags(String fsUuid, int flags, int mask) {
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001791 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001792
Jeff Sharkey50a05452015-04-29 11:24:52 -07001793 Preconditions.checkNotNull(fsUuid);
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001794 synchronized (mLock) {
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001795 final VolumeRecord rec = mRecords.get(fsUuid);
1796 rec.userFlags = (rec.userFlags & ~mask) | (flags & mask);
Jeff Sharkey50a05452015-04-29 11:24:52 -07001797 mCallbacks.notifyVolumeRecordChanged(rec);
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001798 writeSettingsLocked();
1799 }
1800 }
1801
1802 @Override
1803 public void forgetVolume(String fsUuid) {
1804 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001805
Jeff Sharkey50a05452015-04-29 11:24:52 -07001806 Preconditions.checkNotNull(fsUuid);
Jeff Sharkey5a9bb742015-11-03 10:15:57 -08001807
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001808 synchronized (mLock) {
Jeff Sharkey5cc0df22015-06-17 19:44:05 -07001809 final VolumeRecord rec = mRecords.remove(fsUuid);
1810 if (rec != null && !TextUtils.isEmpty(rec.partGuid)) {
Jeff Sharkeydb4b6192017-10-24 11:08:50 -06001811 mHandler.obtainMessage(H_PARTITION_FORGET, rec).sendToTarget();
Jeff Sharkey5cc0df22015-06-17 19:44:05 -07001812 }
1813 mCallbacks.notifyVolumeForgotten(fsUuid);
Jeff Sharkey50a05452015-04-29 11:24:52 -07001814
1815 // If this had been primary storage, revert back to internal and
1816 // reset vold so we bind into new volume into place.
1817 if (Objects.equals(mPrimaryStorageUuid, fsUuid)) {
Jeff Sharkeyfced5342015-05-10 14:53:34 -07001818 mPrimaryStorageUuid = getDefaultPrimaryStorageUuid();
Jeff Sharkey5a9bb742015-11-03 10:15:57 -08001819 mHandler.obtainMessage(H_RESET).sendToTarget();
Jeff Sharkey50a05452015-04-29 11:24:52 -07001820 }
1821
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001822 writeSettingsLocked();
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001823 }
1824 }
1825
Jeff Sharkey7d2af542015-05-12 15:27:15 -07001826 @Override
1827 public void forgetAllVolumes() {
1828 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
Jeff Sharkey7d2af542015-05-12 15:27:15 -07001829
Jeff Sharkey50a05452015-04-29 11:24:52 -07001830 synchronized (mLock) {
1831 for (int i = 0; i < mRecords.size(); i++) {
1832 final String fsUuid = mRecords.keyAt(i);
Jeff Sharkey5cc0df22015-06-17 19:44:05 -07001833 final VolumeRecord rec = mRecords.valueAt(i);
1834 if (!TextUtils.isEmpty(rec.partGuid)) {
Jeff Sharkeydb4b6192017-10-24 11:08:50 -06001835 mHandler.obtainMessage(H_PARTITION_FORGET, rec).sendToTarget();
Jeff Sharkey5cc0df22015-06-17 19:44:05 -07001836 }
Jeff Sharkey50a05452015-04-29 11:24:52 -07001837 mCallbacks.notifyVolumeForgotten(fsUuid);
1838 }
Jeff Sharkey50a05452015-04-29 11:24:52 -07001839 mRecords.clear();
Jeff Sharkey50a05452015-04-29 11:24:52 -07001840
Jeff Sharkeyfced5342015-05-10 14:53:34 -07001841 if (!Objects.equals(StorageManager.UUID_PRIVATE_INTERNAL, mPrimaryStorageUuid)) {
1842 mPrimaryStorageUuid = getDefaultPrimaryStorageUuid();
1843 }
1844
1845 writeSettingsLocked();
Jeff Sharkey5a9bb742015-11-03 10:15:57 -08001846 mHandler.obtainMessage(H_RESET).sendToTarget();
Jeff Sharkey50a05452015-04-29 11:24:52 -07001847 }
1848 }
1849
Jeff Sharkeydb4b6192017-10-24 11:08:50 -06001850 private void forgetPartition(String partGuid, String fsUuid) {
Jeff Sharkey5cc0df22015-06-17 19:44:05 -07001851 try {
Jeff Sharkeydb4b6192017-10-24 11:08:50 -06001852 mVold.forgetPartition(partGuid, fsUuid);
Jeff Sharkeyace874b2017-09-07 15:27:33 -06001853 } catch (Exception e) {
1854 Slog.wtf(TAG, e);
Jeff Sharkey5cc0df22015-06-17 19:44:05 -07001855 }
1856 }
1857
Jeff Sharkey31d0b702016-11-21 14:16:53 -07001858 @Override
Jeff Sharkey7e19f532017-11-06 13:54:11 -07001859 public void fstrim(int flags, IVoldTaskListener listener) {
Jeff Sharkey31d0b702016-11-21 14:16:53 -07001860 enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);
Jeff Sharkey31d0b702016-11-21 14:16:53 -07001861
1862 try {
Jeff Sharkeyb302c542017-09-15 12:57:59 -06001863 mVold.fstrim(flags, new IVoldTaskListener.Stub() {
1864 @Override
1865 public void onStatus(int status, PersistableBundle extras) {
Jeff Sharkey7e19f532017-11-06 13:54:11 -07001866 dispatchOnStatus(listener, status, extras);
1867
Jeff Sharkeyb302c542017-09-15 12:57:59 -06001868 // Ignore trim failures
1869 if (status != 0) return;
1870
1871 final String path = extras.getString("path");
1872 final long bytes = extras.getLong("bytes");
1873 final long time = extras.getLong("time");
1874
1875 final DropBoxManager dropBox = mContext.getSystemService(DropBoxManager.class);
1876 dropBox.addText(TAG_STORAGE_TRIM, scrubPath(path) + " " + bytes + " " + time);
1877
1878 synchronized (mLock) {
1879 final VolumeRecord rec = findRecordForPath(path);
1880 if (rec != null) {
1881 rec.lastTrimMillis = System.currentTimeMillis();
1882 writeSettingsLocked();
1883 }
1884 }
1885 }
1886
1887 @Override
1888 public void onFinished(int status, PersistableBundle extras) {
Jeff Sharkey7e19f532017-11-06 13:54:11 -07001889 dispatchOnFinished(listener, status, extras);
1890
Jeff Sharkeyb302c542017-09-15 12:57:59 -06001891 // TODO: benchmark when desired
1892 }
1893 });
Jeff Sharkey7e19f532017-11-06 13:54:11 -07001894 } catch (RemoteException e) {
1895 throw e.rethrowAsRuntimeException();
Jeff Sharkey31d0b702016-11-21 14:16:53 -07001896 }
1897 }
1898
Jin Qiana85b9912017-10-17 15:48:18 -07001899 void runIdleMaint(Runnable callback) {
1900 enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);
1901
1902 try {
1903 mVold.runIdleMaint(new IVoldTaskListener.Stub() {
1904 @Override
1905 public void onStatus(int status, PersistableBundle extras) {
1906 // Not currently used
1907 }
1908 @Override
1909 public void onFinished(int status, PersistableBundle extras) {
1910 if (callback != null) {
1911 BackgroundThread.getHandler().post(callback);
1912 }
1913 }
1914 });
1915 } catch (Exception e) {
1916 Slog.wtf(TAG, e);
1917 }
1918 }
1919
1920 @Override
1921 public void runIdleMaintenance() {
1922 runIdleMaint(null);
1923 }
1924
1925 void abortIdleMaint(Runnable callback) {
1926 enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);
1927
1928 try {
1929 mVold.abortIdleMaint(new IVoldTaskListener.Stub() {
1930 @Override
1931 public void onStatus(int status, PersistableBundle extras) {
1932 // Not currently used
1933 }
1934 @Override
1935 public void onFinished(int status, PersistableBundle extras) {
1936 if (callback != null) {
1937 BackgroundThread.getHandler().post(callback);
1938 }
1939 }
1940 });
1941 } catch (Exception e) {
1942 Slog.wtf(TAG, e);
1943 }
1944 }
1945
1946 @Override
1947 public void abortIdleMaintenance() {
1948 abortIdleMaint(null);
1949 }
1950
Svet Ganov6ee871e2015-07-10 14:29:33 -07001951 private void remountUidExternalStorage(int uid, int mode) {
Jeff Sharkey9527b222015-06-24 15:24:48 -07001952 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06001953 mVold.remountUid(uid, mode);
Jeff Sharkeyace874b2017-09-07 15:27:33 -06001954 } catch (Exception e) {
1955 Slog.wtf(TAG, e);
Jeff Sharkey9527b222015-06-24 15:24:48 -07001956 }
1957 }
1958
1959 @Override
Jeff Sharkey4c099d02015-05-15 13:45:00 -07001960 public void setDebugFlags(int flags, int mask) {
1961 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
Jeff Sharkey4c099d02015-05-15 13:45:00 -07001962
Jeff Sharkeyba512352015-11-12 20:17:45 -08001963 if ((mask & StorageManager.DEBUG_EMULATE_FBE) != 0) {
Jeff Sharkey00455bf2016-11-04 14:45:24 -06001964 if (!EMULATE_FBE_SUPPORTED) {
1965 throw new IllegalStateException(
1966 "Emulation not supported on this device");
1967 }
Paul Lawrence20be5d62016-02-26 13:51:17 -08001968 if (StorageManager.isFileEncryptedNativeOnly()) {
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07001969 throw new IllegalStateException(
Jeff Sharkey00455bf2016-11-04 14:45:24 -06001970 "Emulation not supported on device with native FBE");
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07001971 }
Jeff Sharkey5a785162016-03-21 13:02:06 -06001972 if (mLockPatternUtils.isCredentialRequiredToDecrypt(false)) {
1973 throw new IllegalStateException(
1974 "Emulation requires disabling 'Secure start-up' in Settings > Security");
1975 }
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07001976
Jeff Sharkey1176e512016-02-29 17:01:26 -07001977 final long token = Binder.clearCallingIdentity();
1978 try {
1979 final boolean emulateFbe = (flags & StorageManager.DEBUG_EMULATE_FBE) != 0;
1980 SystemProperties.set(StorageManager.PROP_EMULATE_FBE, Boolean.toString(emulateFbe));
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07001981
Jeff Sharkey1176e512016-02-29 17:01:26 -07001982 // Perform hard reboot to kick policy into place
1983 mContext.getSystemService(PowerManager.class).reboot(null);
1984 } finally {
1985 Binder.restoreCallingIdentity(token);
1986 }
Jeff Sharkeyba512352015-11-12 20:17:45 -08001987 }
Jeff Sharkey4c099d02015-05-15 13:45:00 -07001988
Jeff Sharkey901c0422018-04-20 13:11:20 -06001989 if ((mask & (StorageManager.DEBUG_ADOPTABLE_FORCE_ON
1990 | StorageManager.DEBUG_ADOPTABLE_FORCE_OFF)) != 0) {
1991 final String value;
1992 if ((flags & StorageManager.DEBUG_ADOPTABLE_FORCE_ON) != 0) {
1993 value = "force_on";
1994 } else if ((flags & StorageManager.DEBUG_ADOPTABLE_FORCE_OFF) != 0) {
1995 value = "force_off";
1996 } else {
1997 value = "";
1998 }
Jeff Sharkeyba512352015-11-12 20:17:45 -08001999
Jeff Sharkey901c0422018-04-20 13:11:20 -06002000 final long token = Binder.clearCallingIdentity();
2001 try {
2002 SystemProperties.set(StorageManager.PROP_ADOPTABLE, value);
2003
2004 // Reset storage to kick new setting into place
Jeff Sharkeyba512352015-11-12 20:17:45 -08002005 mHandler.obtainMessage(H_RESET).sendToTarget();
Jeff Sharkey901c0422018-04-20 13:11:20 -06002006 } finally {
2007 Binder.restoreCallingIdentity(token);
Jeff Sharkeyba512352015-11-12 20:17:45 -08002008 }
Jeff Sharkey4c099d02015-05-15 13:45:00 -07002009 }
Jeff Sharkey33dd1562016-04-07 11:05:33 -06002010
2011 if ((mask & (StorageManager.DEBUG_SDCARDFS_FORCE_ON
2012 | StorageManager.DEBUG_SDCARDFS_FORCE_OFF)) != 0) {
2013 final String value;
2014 if ((flags & StorageManager.DEBUG_SDCARDFS_FORCE_ON) != 0) {
2015 value = "force_on";
2016 } else if ((flags & StorageManager.DEBUG_SDCARDFS_FORCE_OFF) != 0) {
2017 value = "force_off";
2018 } else {
2019 value = "";
2020 }
2021
2022 final long token = Binder.clearCallingIdentity();
2023 try {
2024 SystemProperties.set(StorageManager.PROP_SDCARDFS, value);
2025
2026 // Reset storage to kick new setting into place
2027 mHandler.obtainMessage(H_RESET).sendToTarget();
2028 } finally {
2029 Binder.restoreCallingIdentity(token);
2030 }
2031 }
Jeff Sharkeye53e2d92017-03-25 23:14:06 -06002032
2033 if ((mask & StorageManager.DEBUG_VIRTUAL_DISK) != 0) {
2034 final boolean enabled = (flags & StorageManager.DEBUG_VIRTUAL_DISK) != 0;
2035
2036 final long token = Binder.clearCallingIdentity();
2037 try {
2038 SystemProperties.set(StorageManager.PROP_VIRTUAL_DISK, Boolean.toString(enabled));
2039
2040 // Reset storage to kick new setting into place
2041 mHandler.obtainMessage(H_RESET).sendToTarget();
2042 } finally {
2043 Binder.restoreCallingIdentity(token);
2044 }
2045 }
Jeff Sharkey4c099d02015-05-15 13:45:00 -07002046 }
2047
2048 @Override
Jeff Sharkey275e3e42015-04-24 16:10:32 -07002049 public String getPrimaryStorageUuid() {
Jeff Sharkey620b32b2015-04-23 19:36:02 -07002050 synchronized (mLock) {
2051 return mPrimaryStorageUuid;
2052 }
2053 }
2054
2055 @Override
Jeff Sharkey275e3e42015-04-24 16:10:32 -07002056 public void setPrimaryStorageUuid(String volumeUuid, IPackageMoveObserver callback) {
2057 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
Jeff Sharkey620b32b2015-04-23 19:36:02 -07002058
Jeff Sharkeya31460c2016-06-22 09:04:33 -06002059 final VolumeInfo from;
2060 final VolumeInfo to;
2061
Jeff Sharkey275e3e42015-04-24 16:10:32 -07002062 synchronized (mLock) {
Jeff Sharkeyfced5342015-05-10 14:53:34 -07002063 if (Objects.equals(mPrimaryStorageUuid, volumeUuid)) {
2064 throw new IllegalArgumentException("Primary storage already at " + volumeUuid);
Jeff Sharkey275e3e42015-04-24 16:10:32 -07002065 }
2066
2067 if (mMoveCallback != null) {
2068 throw new IllegalStateException("Move already in progress");
2069 }
2070 mMoveCallback = callback;
2071 mMoveTargetUuid = volumeUuid;
2072
Jeff Sharkeya65e6492017-06-21 13:45:11 -06002073 // We need all the users unlocked to move their primary storage
2074 final List<UserInfo> users = mContext.getSystemService(UserManager.class).getUsers();
2075 for (UserInfo user : users) {
2076 if (StorageManager.isFileEncryptedNativeOrEmulated()
2077 && !isUserKeyUnlocked(user.id)) {
2078 Slog.w(TAG, "Failing move due to locked user " + user.id);
2079 onMoveStatusLocked(PackageManager.MOVE_FAILED_LOCKED_USER);
2080 return;
2081 }
2082 }
2083
Jeff Sharkeyfced5342015-05-10 14:53:34 -07002084 // When moving to/from primary physical volume, we probably just nuked
2085 // the current storage location, so we have nothing to move.
2086 if (Objects.equals(StorageManager.UUID_PRIMARY_PHYSICAL, mPrimaryStorageUuid)
2087 || Objects.equals(StorageManager.UUID_PRIMARY_PHYSICAL, volumeUuid)) {
2088 Slog.d(TAG, "Skipping move to/from primary physical");
2089 onMoveStatusLocked(MOVE_STATUS_COPY_FINISHED);
2090 onMoveStatusLocked(PackageManager.MOVE_SUCCEEDED);
Jeff Sharkey5a9bb742015-11-03 10:15:57 -08002091 mHandler.obtainMessage(H_RESET).sendToTarget();
Jeff Sharkeya31460c2016-06-22 09:04:33 -06002092 return;
Jeff Sharkeyfced5342015-05-10 14:53:34 -07002093
2094 } else {
Jeff Sharkeya31460c2016-06-22 09:04:33 -06002095 from = findStorageForUuid(mPrimaryStorageUuid);
2096 to = findStorageForUuid(volumeUuid);
Jeff Sharkeyef10ee02015-07-05 14:17:27 -07002097
2098 if (from == null) {
2099 Slog.w(TAG, "Failing move due to missing from volume " + mPrimaryStorageUuid);
2100 onMoveStatusLocked(PackageManager.MOVE_FAILED_INTERNAL_ERROR);
2101 return;
2102 } else if (to == null) {
2103 Slog.w(TAG, "Failing move due to missing to volume " + volumeUuid);
2104 onMoveStatusLocked(PackageManager.MOVE_FAILED_INTERNAL_ERROR);
2105 return;
2106 }
Jeff Sharkey275e3e42015-04-24 16:10:32 -07002107 }
Jeff Sharkey620b32b2015-04-23 19:36:02 -07002108 }
Jeff Sharkeya31460c2016-06-22 09:04:33 -06002109
2110 try {
Jeff Sharkeyb302c542017-09-15 12:57:59 -06002111 mVold.moveStorage(from.id, to.id, new IVoldTaskListener.Stub() {
2112 @Override
2113 public void onStatus(int status, PersistableBundle extras) {
2114 synchronized (mLock) {
2115 onMoveStatusLocked(status);
2116 }
2117 }
2118
2119 @Override
2120 public void onFinished(int status, PersistableBundle extras) {
2121 // Not currently used
2122 }
2123 });
Jeff Sharkeyace874b2017-09-07 15:27:33 -06002124 } catch (Exception e) {
2125 Slog.wtf(TAG, e);
Jeff Sharkeya31460c2016-06-22 09:04:33 -06002126 }
Jeff Sharkey620b32b2015-04-23 19:36:02 -07002127 }
2128
San Mehatb1043402010-02-05 08:26:50 -08002129 private void warnOnNotMounted() {
Jeff Sharkey48877892015-03-18 11:27:19 -07002130 synchronized (mLock) {
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07002131 for (int i = 0; i < mVolumes.size(); i++) {
2132 final VolumeInfo vol = mVolumes.valueAt(i);
Jeff Sharkey27de30d2015-04-18 16:20:27 -07002133 if (vol.isPrimary() && vol.isMountedWritable()) {
Jeff Sharkey48877892015-03-18 11:27:19 -07002134 // Cool beans, we have a mounted primary volume
2135 return;
2136 }
Jeff Sharkey32ee8312012-09-30 13:21:31 -07002137 }
San Mehatb1043402010-02-05 08:26:50 -08002138 }
Jeff Sharkey48877892015-03-18 11:27:19 -07002139
2140 Slog.w(TAG, "No primary storage mounted!");
San Mehatb1043402010-02-05 08:26:50 -08002141 }
2142
Kenny Roota02b8b02010-08-05 16:14:17 -07002143 private boolean isUidOwnerOfPackageOrSystem(String packageName, int callerUid) {
2144 if (callerUid == android.os.Process.SYSTEM_UID) {
2145 return true;
2146 }
2147
Kenny Root02c87302010-07-01 08:10:18 -07002148 if (packageName == null) {
2149 return false;
2150 }
2151
Jeff Sharkeycd654482016-01-08 17:42:11 -07002152 final int packageUid = mPms.getPackageUid(packageName,
2153 PackageManager.MATCH_DEBUG_TRIAGED_MISSING, UserHandle.getUserId(callerUid));
Kenny Root02c87302010-07-01 08:10:18 -07002154
2155 if (DEBUG_OBB) {
2156 Slog.d(TAG, "packageName = " + packageName + ", packageUid = " +
2157 packageUid + ", callerUid = " + callerUid);
2158 }
2159
2160 return callerUid == packageUid;
2161 }
2162
Jeff Sharkey54402792017-09-15 16:05:19 -06002163 @Override
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002164 public String getMountedObbPath(String rawPath) {
2165 Preconditions.checkNotNull(rawPath, "rawPath cannot be null");
Kenny Rootaf9d6672010-10-08 09:21:39 -07002166
Kenny Root02c87302010-07-01 08:10:18 -07002167 warnOnNotMounted();
2168
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002169 final ObbState state;
Rubin Xucd7a0142015-04-17 23:45:27 +01002170 synchronized (mObbMounts) {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002171 state = mObbPathToStateMap.get(rawPath);
2172 }
2173 if (state == null) {
2174 Slog.w(TAG, "Failed to find OBB mounted at " + rawPath);
2175 return null;
2176 }
2177
Jeff Sharkey54402792017-09-15 16:05:19 -06002178 return findVolumeByIdOrThrow(state.volId).getPath().getAbsolutePath();
Kenny Root02c87302010-07-01 08:10:18 -07002179 }
2180
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002181 @Override
2182 public boolean isObbMounted(String rawPath) {
2183 Preconditions.checkNotNull(rawPath, "rawPath cannot be null");
Kenny Rootaf9d6672010-10-08 09:21:39 -07002184 synchronized (mObbMounts) {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002185 return mObbPathToStateMap.containsKey(rawPath);
Kenny Rootaf9d6672010-10-08 09:21:39 -07002186 }
Kenny Root02c87302010-07-01 08:10:18 -07002187 }
2188
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002189 @Override
2190 public void mountObb(
2191 String rawPath, String canonicalPath, String key, IObbActionListener token, int nonce) {
2192 Preconditions.checkNotNull(rawPath, "rawPath cannot be null");
2193 Preconditions.checkNotNull(canonicalPath, "canonicalPath cannot be null");
2194 Preconditions.checkNotNull(token, "token cannot be null");
Kenny Rootaf9d6672010-10-08 09:21:39 -07002195
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002196 final int callingUid = Binder.getCallingUid();
Jeff Sharkey41cd6812017-09-11 10:32:17 -06002197 final ObbState obbState = new ObbState(rawPath, canonicalPath,
2198 callingUid, token, nonce, null);
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002199 final ObbAction action = new MountObbAction(obbState, key, callingUid);
Kenny Roota02b8b02010-08-05 16:14:17 -07002200 mObbActionHandler.sendMessage(mObbActionHandler.obtainMessage(OBB_RUN_ACTION, action));
2201
2202 if (DEBUG_OBB)
2203 Slog.i(TAG, "Send to OBB handler: " + action.toString());
Kenny Root02c87302010-07-01 08:10:18 -07002204 }
2205
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002206 @Override
2207 public void unmountObb(String rawPath, boolean force, IObbActionListener token, int nonce) {
2208 Preconditions.checkNotNull(rawPath, "rawPath cannot be null");
2209
2210 final ObbState existingState;
Rubin Xucd7a0142015-04-17 23:45:27 +01002211 synchronized (mObbMounts) {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002212 existingState = mObbPathToStateMap.get(rawPath);
Kenny Rootf1121dc2010-09-29 07:30:53 -07002213 }
2214
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002215 if (existingState != null) {
2216 // TODO: separate state object from request data
2217 final int callingUid = Binder.getCallingUid();
Jeff Sharkey41cd6812017-09-11 10:32:17 -06002218 final ObbState newState = new ObbState(rawPath, existingState.canonicalPath,
2219 callingUid, token, nonce, existingState.volId);
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002220 final ObbAction action = new UnmountObbAction(newState, force);
2221 mObbActionHandler.sendMessage(mObbActionHandler.obtainMessage(OBB_RUN_ACTION, action));
Kenny Root02c87302010-07-01 08:10:18 -07002222
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002223 if (DEBUG_OBB)
2224 Slog.i(TAG, "Send to OBB handler: " + action.toString());
2225 } else {
2226 Slog.w(TAG, "Unknown OBB mount at " + rawPath);
2227 }
Kenny Roota02b8b02010-08-05 16:14:17 -07002228 }
2229
Ben Komalo444eca22011-09-01 15:17:44 -07002230 @Override
2231 public int getEncryptionState() {
2232 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
2233 "no permission to access the crypt keeper");
2234
Ben Komalo444eca22011-09-01 15:17:44 -07002235 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002236 return mVold.fdeComplete();
2237 } catch (Exception e) {
2238 Slog.wtf(TAG, e);
Sudheer Shankaf7341142016-10-18 17:15:18 -07002239 return StorageManager.ENCRYPTION_STATE_ERROR_UNKNOWN;
Ben Komalo444eca22011-09-01 15:17:44 -07002240 }
2241 }
2242
2243 @Override
Jason parks5af0b912010-11-29 09:05:25 -06002244 public int decryptStorage(String password) {
Jason parks8888c592011-01-20 22:46:41 -06002245 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
2246 "no permission to access the crypt keeper");
Jason parks5af0b912010-11-29 09:05:25 -06002247
Jeff Sharkey8058fe62017-09-13 11:50:33 -06002248 if (TextUtils.isEmpty(password)) {
2249 throw new IllegalArgumentException("password cannot be empty");
2250 }
2251
Jason parks5af0b912010-11-29 09:05:25 -06002252 if (DEBUG_EVENTS) {
2253 Slog.i(TAG, "decrypting storage...");
2254 }
2255
2256 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002257 mVold.fdeCheckPassword(password);
2258 mHandler.postDelayed(() -> {
2259 try {
2260 mVold.fdeRestart();
2261 } catch (Exception e) {
2262 Slog.wtf(TAG, e);
2263 }
2264 }, DateUtils.SECOND_IN_MILLIS);
2265 return 0;
Paul Crowleyfc0b5192018-07-02 13:58:10 -07002266 } catch (ServiceSpecificException e) {
2267 Slog.e(TAG, "fdeCheckPassword failed", e);
2268 return e.errorCode;
Jeff Sharkey54402792017-09-15 16:05:19 -06002269 } catch (Exception e) {
2270 Slog.wtf(TAG, e);
2271 return StorageManager.ENCRYPTION_STATE_ERROR_UNKNOWN;
Jason parks5af0b912010-11-29 09:05:25 -06002272 }
Jason parks5af0b912010-11-29 09:05:25 -06002273 }
2274
Jeff Sharkey54402792017-09-15 16:05:19 -06002275 @Override
Paul Lawrence46791e72014-04-03 09:10:26 -07002276 public int encryptStorage(int type, String password) {
Jason parks8888c592011-01-20 22:46:41 -06002277 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
2278 "no permission to access the crypt keeper");
Jason parks56aa5322011-01-07 09:01:15 -06002279
Jeff Sharkey8058fe62017-09-13 11:50:33 -06002280 if (type == StorageManager.CRYPT_TYPE_DEFAULT) {
2281 password = "";
2282 } else if (TextUtils.isEmpty(password)) {
2283 throw new IllegalArgumentException("password cannot be empty");
2284 }
2285
Jason parks56aa5322011-01-07 09:01:15 -06002286 if (DEBUG_EVENTS) {
Jason parks8888c592011-01-20 22:46:41 -06002287 Slog.i(TAG, "encrypting storage...");
Jason parks56aa5322011-01-07 09:01:15 -06002288 }
2289
2290 try {
Paul Lawrence89a0ae42017-12-22 10:11:10 -08002291 mVold.fdeEnable(type, password, 0);
Jeff Sharkey43e12112017-09-12 16:31:45 -06002292 } catch (Exception e) {
2293 Slog.wtf(TAG, e);
2294 return -1;
Jason parks56aa5322011-01-07 09:01:15 -06002295 }
2296
2297 return 0;
2298 }
2299
Paul Lawrence8e397362014-01-27 15:22:30 -08002300 /** Set the password for encrypting the master key.
2301 * @param type One of the CRYPTO_TYPE_XXX consts defined in StorageManager.
2302 * @param password The password to set.
2303 */
Jeff Sharkey54402792017-09-15 16:05:19 -06002304 @Override
Paul Lawrence8e397362014-01-27 15:22:30 -08002305 public int changeEncryptionPassword(int type, String password) {
Jason parksf7b3cd42011-01-27 09:28:25 -06002306 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
2307 "no permission to access the crypt keeper");
2308
Jeff Sharkeyae266462017-11-27 13:32:24 -07002309 if (StorageManager.isFileEncryptedNativeOnly()) {
2310 // Not supported on FBE devices
2311 return -1;
2312 }
2313
Jeff Sharkey8058fe62017-09-13 11:50:33 -06002314 if (type == StorageManager.CRYPT_TYPE_DEFAULT) {
2315 password = "";
2316 } else if (TextUtils.isEmpty(password)) {
2317 throw new IllegalArgumentException("password cannot be empty");
2318 }
2319
Jason parksf7b3cd42011-01-27 09:28:25 -06002320 if (DEBUG_EVENTS) {
2321 Slog.i(TAG, "changing encryption password...");
2322 }
2323
2324 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002325 mVold.fdeChangePassword(type, password);
2326 return 0;
2327 } catch (Exception e) {
2328 Slog.wtf(TAG, e);
2329 return -1;
Jason parksf7b3cd42011-01-27 09:28:25 -06002330 }
2331 }
2332
Christopher Tate32418be2011-10-10 13:51:12 -07002333 /**
2334 * Validate a user-supplied password string with cryptfs
2335 */
2336 @Override
2337 public int verifyEncryptionPassword(String password) throws RemoteException {
2338 // Only the system process is permitted to validate passwords
2339 if (Binder.getCallingUid() != android.os.Process.SYSTEM_UID) {
2340 throw new SecurityException("no permission to access the crypt keeper");
2341 }
2342
2343 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
2344 "no permission to access the crypt keeper");
2345
2346 if (TextUtils.isEmpty(password)) {
2347 throw new IllegalArgumentException("password cannot be empty");
2348 }
2349
Christopher Tate32418be2011-10-10 13:51:12 -07002350 if (DEBUG_EVENTS) {
2351 Slog.i(TAG, "validating encryption password...");
2352 }
2353
2354 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002355 mVold.fdeVerifyPassword(password);
2356 return 0;
2357 } catch (Exception e) {
2358 Slog.wtf(TAG, e);
2359 return -1;
Christopher Tate32418be2011-10-10 13:51:12 -07002360 }
2361 }
2362
Paul Lawrence8e397362014-01-27 15:22:30 -08002363 /**
2364 * Get the type of encryption used to encrypt the master key.
2365 * @return The type, one of the CRYPT_TYPE_XXX consts from StorageManager.
2366 */
2367 @Override
Svetoslav16e4a1a2014-09-29 18:16:20 -07002368 public int getPasswordType() {
Paul Lawrence76a40572017-03-15 11:08:04 -07002369 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
Paul Lawrence9de713d2016-05-02 22:45:33 +00002370 "no permission to access the crypt keeper");
2371
Paul Lawrence8e397362014-01-27 15:22:30 -08002372 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002373 return mVold.fdeGetPasswordType();
2374 } catch (Exception e) {
2375 Slog.wtf(TAG, e);
2376 return -1;
Paul Lawrence8e397362014-01-27 15:22:30 -08002377 }
2378 }
2379
Paul Lawrencee51dcf92014-03-18 10:56:00 -07002380 /**
2381 * Set a field in the crypto header.
2382 * @param field field to set
2383 * @param contents contents to set in field
2384 */
2385 @Override
2386 public void setField(String field, String contents) throws RemoteException {
Paul Lawrence76a40572017-03-15 11:08:04 -07002387 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
Paul Lawrence0bbd1082016-04-26 15:21:02 -07002388 "no permission to access the crypt keeper");
Paul Lawrencee51dcf92014-03-18 10:56:00 -07002389
Jeff Sharkeyae266462017-11-27 13:32:24 -07002390 if (StorageManager.isFileEncryptedNativeOnly()) {
2391 // Not supported on FBE devices
2392 return;
2393 }
2394
Paul Lawrencee51dcf92014-03-18 10:56:00 -07002395 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002396 mVold.fdeSetField(field, contents);
2397 return;
2398 } catch (Exception e) {
2399 Slog.wtf(TAG, e);
2400 return;
Paul Lawrencee51dcf92014-03-18 10:56:00 -07002401 }
2402 }
2403
2404 /**
2405 * Gets a field from the crypto header.
2406 * @param field field to get
2407 * @return contents of field
2408 */
2409 @Override
2410 public String getField(String field) throws RemoteException {
Paul Lawrence76a40572017-03-15 11:08:04 -07002411 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
Paul Lawrence0bbd1082016-04-26 15:21:02 -07002412 "no permission to access the crypt keeper");
Paul Lawrencee51dcf92014-03-18 10:56:00 -07002413
Jeff Sharkeyae266462017-11-27 13:32:24 -07002414 if (StorageManager.isFileEncryptedNativeOnly()) {
2415 // Not supported on FBE devices
2416 return null;
2417 }
2418
Paul Lawrencee51dcf92014-03-18 10:56:00 -07002419 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002420 return mVold.fdeGetField(field);
2421 } catch (Exception e) {
2422 Slog.wtf(TAG, e);
2423 return null;
Paul Lawrencee51dcf92014-03-18 10:56:00 -07002424 }
2425 }
2426
Paul Lawrence3806d9c2015-10-29 10:30:46 -07002427 /**
2428 * Is userdata convertible to file based encryption?
2429 * @return non zero for convertible
2430 */
2431 @Override
2432 public boolean isConvertibleToFBE() throws RemoteException {
Paul Lawrence76a40572017-03-15 11:08:04 -07002433 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
Paul Lawrence0bbd1082016-04-26 15:21:02 -07002434 "no permission to access the crypt keeper");
Paul Lawrence3806d9c2015-10-29 10:30:46 -07002435
Paul Lawrence3806d9c2015-10-29 10:30:46 -07002436 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002437 return mVold.isConvertibleToFbe();
2438 } catch (Exception e) {
2439 Slog.wtf(TAG, e);
2440 return false;
Paul Lawrence3806d9c2015-10-29 10:30:46 -07002441 }
2442 }
2443
Jeff Sharkeyb049e212012-09-07 23:16:01 -07002444 @Override
Paul Lawrence945490c2014-03-27 16:37:28 +00002445 public String getPassword() throws RemoteException {
Paul Lawrence76a40572017-03-15 11:08:04 -07002446 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
Rubin Xucd7a0142015-04-17 23:45:27 +01002447 "only keyguard can retrieve password");
Paul Lawrence0bbd1082016-04-26 15:21:02 -07002448
Paul Lawrence945490c2014-03-27 16:37:28 +00002449 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002450 return mVold.fdeGetPassword();
2451 } catch (Exception e) {
2452 Slog.wtf(TAG, e);
Paul Lawrence24063b52015-01-06 13:11:23 -08002453 return null;
Paul Lawrence945490c2014-03-27 16:37:28 +00002454 }
2455 }
2456
2457 @Override
2458 public void clearPassword() throws RemoteException {
Paul Lawrence76a40572017-03-15 11:08:04 -07002459 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
Paul Lawrence0bbd1082016-04-26 15:21:02 -07002460 "only keyguard can clear password");
2461
Paul Lawrence945490c2014-03-27 16:37:28 +00002462 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002463 mVold.fdeClearPassword();
2464 return;
2465 } catch (Exception e) {
2466 Slog.wtf(TAG, e);
2467 return;
Paul Lawrence945490c2014-03-27 16:37:28 +00002468 }
2469 }
2470
2471 @Override
Lenka Trochtovac4dd0212015-11-18 12:22:06 +01002472 public void createUserKey(int userId, int serialNumber, boolean ephemeral) {
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002473 enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
Paul Crowleybcf48ed2015-04-22 13:36:59 +01002474
Paul Crowleybcf48ed2015-04-22 13:36:59 +01002475 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002476 mVold.createUserKey(userId, serialNumber, ephemeral);
Jeff Sharkey43e12112017-09-12 16:31:45 -06002477 } catch (Exception e) {
2478 Slog.wtf(TAG, e);
Paul Crowleybcf48ed2015-04-22 13:36:59 +01002479 }
2480 }
2481
Paul Crowley7ec733f2015-05-19 12:42:00 +01002482 @Override
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002483 public void destroyUserKey(int userId) {
2484 enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
Paul Crowley7ec733f2015-05-19 12:42:00 +01002485
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002486 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002487 mVold.destroyUserKey(userId);
Jeff Sharkey43e12112017-09-12 16:31:45 -06002488 } catch (Exception e) {
2489 Slog.wtf(TAG, e);
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002490 }
2491 }
2492
Jeff Sharkey43e12112017-09-12 16:31:45 -06002493 private String encodeBytes(byte[] bytes) {
Paul Crowleyfaeb3eb2016-02-08 15:58:29 +00002494 if (ArrayUtils.isEmpty(bytes)) {
Jeff Sharkey43e12112017-09-12 16:31:45 -06002495 return "!";
Paul Crowleyfaeb3eb2016-02-08 15:58:29 +00002496 } else {
Jeff Sharkey43e12112017-09-12 16:31:45 -06002497 return HexDump.toHexString(bytes);
Paul Crowleyfaeb3eb2016-02-08 15:58:29 +00002498 }
2499 }
2500
Paul Crowleycc701552016-05-17 14:18:49 -07002501 /*
2502 * Add this token/secret pair to the set of ways we can recover a disk encryption key.
2503 * Changing the token/secret for a disk encryption key is done in two phases: first, adding
2504 * a new token/secret pair with this call, then delting all other pairs with
2505 * fixateNewestUserKeyAuth. This allows other places where a credential is used, such as
2506 * Gatekeeper, to be updated between the two calls.
2507 */
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002508 @Override
Paul Crowleycc701552016-05-17 14:18:49 -07002509 public void addUserKeyAuth(int userId, int serialNumber, byte[] token, byte[] secret) {
Paul Crowleyfaeb3eb2016-02-08 15:58:29 +00002510 enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
Paul Crowleyfaeb3eb2016-02-08 15:58:29 +00002511
2512 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002513 mVold.addUserKeyAuth(userId, serialNumber, encodeBytes(token), encodeBytes(secret));
Jeff Sharkey43e12112017-09-12 16:31:45 -06002514 } catch (Exception e) {
2515 Slog.wtf(TAG, e);
Paul Crowleycc701552016-05-17 14:18:49 -07002516 }
2517 }
2518
2519 /*
2520 * Delete all disk encryption token/secret pairs except the most recently added one
2521 */
2522 @Override
2523 public void fixateNewestUserKeyAuth(int userId) {
2524 enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
Paul Crowleycc701552016-05-17 14:18:49 -07002525
2526 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002527 mVold.fixateNewestUserKeyAuth(userId);
Jeff Sharkey43e12112017-09-12 16:31:45 -06002528 } catch (Exception e) {
2529 Slog.wtf(TAG, e);
Paul Crowleyfaeb3eb2016-02-08 15:58:29 +00002530 }
2531 }
2532
2533 @Override
2534 public void unlockUserKey(int userId, int serialNumber, byte[] token, byte[] secret) {
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002535 enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002536
Jeff Sharkeyce18c812016-04-27 16:00:41 -06002537 if (StorageManager.isFileEncryptedNativeOrEmulated()) {
Rubin Xu3bf722a2016-12-15 16:07:38 +00002538 // When a user has secure lock screen, require secret to actually unlock.
2539 // This check is mostly in place for emulation mode.
2540 if (mLockPatternUtils.isSecure(userId) && ArrayUtils.isEmpty(secret)) {
2541 throw new IllegalStateException("Secret required to unlock secure user " + userId);
Jeff Sharkeyce18c812016-04-27 16:00:41 -06002542 }
Jeff Sharkeyb9fe5372015-12-03 15:23:08 -07002543
Jeff Sharkeyce18c812016-04-27 16:00:41 -06002544 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002545 mVold.unlockUserKey(userId, serialNumber, encodeBytes(token),
2546 encodeBytes(secret));
Jeff Sharkey43e12112017-09-12 16:31:45 -06002547 } catch (Exception e) {
2548 Slog.wtf(TAG, e);
2549 return;
Jeff Sharkeyce18c812016-04-27 16:00:41 -06002550 }
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002551 }
2552
2553 synchronized (mLock) {
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07002554 mLocalUnlockedUsers = ArrayUtils.appendInt(mLocalUnlockedUsers, userId);
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002555 }
2556 }
2557
2558 @Override
2559 public void lockUserKey(int userId) {
2560 enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002561
2562 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002563 mVold.lockUserKey(userId);
Jeff Sharkey43e12112017-09-12 16:31:45 -06002564 } catch (Exception e) {
2565 Slog.wtf(TAG, e);
2566 return;
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002567 }
2568
2569 synchronized (mLock) {
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07002570 mLocalUnlockedUsers = ArrayUtils.removeInt(mLocalUnlockedUsers, userId);
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002571 }
2572 }
2573
2574 @Override
2575 public boolean isUserKeyUnlocked(int userId) {
Jeff Sharkeyce18c812016-04-27 16:00:41 -06002576 synchronized (mLock) {
2577 return ArrayUtils.contains(mLocalUnlockedUsers, userId);
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002578 }
2579 }
2580
2581 @Override
Jeff Sharkey47f71082016-02-01 17:03:54 -07002582 public void prepareUserStorage(String volumeUuid, int userId, int serialNumber, int flags) {
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002583 enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002584
2585 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002586 mVold.prepareUserStorage(volumeUuid, userId, serialNumber, flags);
Jeff Sharkey43e12112017-09-12 16:31:45 -06002587 } catch (Exception e) {
2588 Slog.wtf(TAG, e);
Paul Crowley7ec733f2015-05-19 12:42:00 +01002589 }
2590 }
2591
Paul Crowleybcf48ed2015-04-22 13:36:59 +01002592 @Override
Jeff Sharkeyfcf1e552016-04-14 20:44:58 -06002593 public void destroyUserStorage(String volumeUuid, int userId, int flags) {
2594 enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
Jeff Sharkeyfcf1e552016-04-14 20:44:58 -06002595
2596 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002597 mVold.destroyUserStorage(volumeUuid, userId, flags);
Jeff Sharkey43e12112017-09-12 16:31:45 -06002598 } catch (Exception e) {
2599 Slog.wtf(TAG, e);
Jeff Sharkeyfcf1e552016-04-14 20:44:58 -06002600 }
2601 }
2602
Daichi Hironoe56740d2017-02-02 13:56:45 +09002603 class AppFuseMountScope extends AppFuseBridge.MountScope {
Daichi Hirono812c95d2017-02-08 16:20:20 +09002604 boolean opened = false;
2605
Ryo Hashimoto70ee4322018-05-16 18:20:37 +09002606 public AppFuseMountScope(int uid, int mountId) {
2607 super(uid, mountId);
Daichi Hirono812c95d2017-02-08 16:20:20 +09002608 }
2609
2610 @Override
2611 public ParcelFileDescriptor open() throws NativeDaemonConnectorException {
Jeff Sharkey54402792017-09-15 16:05:19 -06002612 try {
2613 return new ParcelFileDescriptor(
Ryo Hashimoto70ee4322018-05-16 18:20:37 +09002614 mVold.mountAppFuse(uid, mountId));
Jeff Sharkey54402792017-09-15 16:05:19 -06002615 } catch (Exception e) {
2616 throw new NativeDaemonConnectorException("Failed to mount", e);
Daichi Hirono812c95d2017-02-08 16:20:20 +09002617 }
Daichi Hirono9fb00182016-11-08 14:12:17 +09002618 }
2619
2620 @Override
Ryo Hashimoto70ee4322018-05-16 18:20:37 +09002621 public ParcelFileDescriptor openFile(int mountId, int fileId, int flags)
2622 throws NativeDaemonConnectorException {
2623 try {
2624 return new ParcelFileDescriptor(
2625 mVold.openAppFuseFile(uid, mountId, fileId, flags));
2626 } catch (Exception e) {
2627 throw new NativeDaemonConnectorException("Failed to open", e);
2628 }
2629 }
2630
2631 @Override
Daichi Hironoe56740d2017-02-02 13:56:45 +09002632 public void close() throws Exception {
Daichi Hirono812c95d2017-02-08 16:20:20 +09002633 if (opened) {
Ryo Hashimoto70ee4322018-05-16 18:20:37 +09002634 mVold.unmountAppFuse(uid, mountId);
Daichi Hirono812c95d2017-02-08 16:20:20 +09002635 opened = false;
2636 }
Daichi Hirono9fb00182016-11-08 14:12:17 +09002637 }
2638 }
2639
2640 @Override
Daichi Hirono812c95d2017-02-08 16:20:20 +09002641 public @Nullable AppFuseMount mountProxyFileDescriptorBridge() {
Daichi Hironoe56740d2017-02-02 13:56:45 +09002642 Slog.v(TAG, "mountProxyFileDescriptorBridge");
Daichi Hirono9fb00182016-11-08 14:12:17 +09002643 final int uid = Binder.getCallingUid();
Daichi Hirono9fb00182016-11-08 14:12:17 +09002644
Daichi Hironoe56740d2017-02-02 13:56:45 +09002645 while (true) {
2646 synchronized (mAppFuseLock) {
2647 boolean newlyCreated = false;
2648 if (mAppFuseBridge == null) {
2649 mAppFuseBridge = new AppFuseBridge();
2650 new Thread(mAppFuseBridge, AppFuseBridge.TAG).start();
2651 newlyCreated = true;
Daichi Hirono9fb00182016-11-08 14:12:17 +09002652 }
Daichi Hironoe56740d2017-02-02 13:56:45 +09002653 try {
2654 final int name = mNextAppFuseName++;
2655 try {
2656 return new AppFuseMount(
Ryo Hashimoto70ee4322018-05-16 18:20:37 +09002657 name, mAppFuseBridge.addBridge(new AppFuseMountScope(uid, name)));
Daichi Hirono812c95d2017-02-08 16:20:20 +09002658 } catch (FuseUnavailableMountException e) {
Daichi Hironoe56740d2017-02-02 13:56:45 +09002659 if (newlyCreated) {
2660 // If newly created bridge fails, it's a real error.
Daichi Hirono812c95d2017-02-08 16:20:20 +09002661 Slog.e(TAG, "", e);
2662 return null;
Daichi Hironoe56740d2017-02-02 13:56:45 +09002663 }
2664 // It seems the thread of mAppFuseBridge has already been terminated.
2665 mAppFuseBridge = null;
2666 }
2667 } catch (NativeDaemonConnectorException e) {
2668 throw e.rethrowAsParcelableException();
2669 }
Daichi Hirono9fb00182016-11-08 14:12:17 +09002670 }
Daichi Hirono9fb00182016-11-08 14:12:17 +09002671 }
2672 }
2673
2674 @Override
Daichi Hirono812c95d2017-02-08 16:20:20 +09002675 public @Nullable ParcelFileDescriptor openProxyFileDescriptor(
2676 int mountId, int fileId, int mode) {
2677 Slog.v(TAG, "mountProxyFileDescriptor");
Daichi Hirono9fb00182016-11-08 14:12:17 +09002678 try {
2679 synchronized (mAppFuseLock) {
Daichi Hironoe56740d2017-02-02 13:56:45 +09002680 if (mAppFuseBridge == null) {
Daichi Hirono812c95d2017-02-08 16:20:20 +09002681 Slog.e(TAG, "FuseBridge has not been created");
2682 return null;
Daichi Hirono9fb00182016-11-08 14:12:17 +09002683 }
Ryo Hashimoto70ee4322018-05-16 18:20:37 +09002684 return mAppFuseBridge.openFile(mountId, fileId, mode);
Daichi Hirono9fb00182016-11-08 14:12:17 +09002685 }
Daichi Hirono812c95d2017-02-08 16:20:20 +09002686 } catch (FuseUnavailableMountException | InterruptedException error) {
2687 Slog.v(TAG, "The mount point has already been invalid", error);
2688 return null;
Daichi Hirono9fb00182016-11-08 14:12:17 +09002689 }
2690 }
2691
Daichi Hirono9e8d9e22015-11-13 14:37:00 +09002692 @Override
Jeff Sharkeyae266462017-11-27 13:32:24 -07002693 public void mkdirs(String callingPkg, String appPath) {
Jeff Sharkey2d8b4e82013-09-17 17:30:33 -07002694 final int userId = UserHandle.getUserId(Binder.getCallingUid());
2695 final UserEnvironment userEnv = new UserEnvironment(userId);
Farid Zare Seisanac094512018-04-02 15:06:13 -07002696 final String propertyName = "sys.user." + userId + ".ce_available";
Jeff Sharkey2d8b4e82013-09-17 17:30:33 -07002697
Jeff Sharkey196c7552018-03-26 15:56:50 -06002698 // Ignore requests to create directories while storage is locked
Farid Zare Seisanac094512018-04-02 15:06:13 -07002699 if (!isUserKeyUnlocked(userId)) {
2700 throw new IllegalStateException("Failed to prepare " + appPath);
2701 }
2702
2703 // Ignore requests to create directories if CE storage is not available
Farid Zare Seisan7f6b8122018-03-30 11:19:10 -07002704 if ((userId == UserHandle.USER_SYSTEM)
2705 && !SystemProperties.getBoolean(propertyName, false)) {
Farid Zare Seisanac094512018-04-02 15:06:13 -07002706 throw new IllegalStateException("Failed to prepare " + appPath);
2707 }
Jeff Sharkey196c7552018-03-26 15:56:50 -06002708
Jeff Sharkey2d8b4e82013-09-17 17:30:33 -07002709 // Validate that reported package name belongs to caller
2710 final AppOpsManager appOps = (AppOpsManager) mContext.getSystemService(
2711 Context.APP_OPS_SERVICE);
2712 appOps.checkPackage(Binder.getCallingUid(), callingPkg);
2713
Jeff Sharkey48877892015-03-18 11:27:19 -07002714 File appFile = null;
Jeff Sharkey2d8b4e82013-09-17 17:30:33 -07002715 try {
Jeff Sharkey48877892015-03-18 11:27:19 -07002716 appFile = new File(appPath).getCanonicalFile();
Jeff Sharkey2d8b4e82013-09-17 17:30:33 -07002717 } catch (IOException e) {
Jeff Sharkeyae266462017-11-27 13:32:24 -07002718 throw new IllegalStateException("Failed to resolve " + appPath + ": " + e);
Jeff Sharkey2d8b4e82013-09-17 17:30:33 -07002719 }
2720
2721 // Try translating the app path into a vold path, but require that it
2722 // belong to the calling package.
Jeff Sharkey48877892015-03-18 11:27:19 -07002723 if (FileUtils.contains(userEnv.buildExternalStorageAppDataDirs(callingPkg), appFile) ||
2724 FileUtils.contains(userEnv.buildExternalStorageAppObbDirs(callingPkg), appFile) ||
2725 FileUtils.contains(userEnv.buildExternalStorageAppMediaDirs(callingPkg), appFile)) {
2726 appPath = appFile.getAbsolutePath();
2727 if (!appPath.endsWith("/")) {
2728 appPath = appPath + "/";
2729 }
2730
Jeff Sharkey2d8b4e82013-09-17 17:30:33 -07002731 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002732 mVold.mkdirs(appPath);
Jeff Sharkey27a108c2017-11-30 17:11:40 -07002733 return;
Jeff Sharkeyace874b2017-09-07 15:27:33 -06002734 } catch (Exception e) {
Jeff Sharkeyae266462017-11-27 13:32:24 -07002735 throw new IllegalStateException("Failed to prepare " + appPath + ": " + e);
Jeff Sharkey2d8b4e82013-09-17 17:30:33 -07002736 }
2737 }
2738
Jeff Sharkey48877892015-03-18 11:27:19 -07002739 throw new SecurityException("Invalid mkdirs path: " + appFile);
Jeff Sharkey2d8b4e82013-09-17 17:30:33 -07002740 }
2741
2742 @Override
Jeff Sharkey46349872015-07-28 10:49:47 -07002743 public StorageVolume[] getVolumeList(int uid, String packageName, int flags) {
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07002744 final int userId = UserHandle.getUserId(uid);
Jeff Sharkeyc02bfae2016-03-27 15:06:53 -06002745
Jeff Sharkey46349872015-07-28 10:49:47 -07002746 final boolean forWrite = (flags & StorageManager.FLAG_FOR_WRITE) != 0;
Jeff Sharkeyc02bfae2016-03-27 15:06:53 -06002747 final boolean realState = (flags & StorageManager.FLAG_REAL_STATE) != 0;
2748 final boolean includeInvisible = (flags & StorageManager.FLAG_INCLUDE_INVISIBLE) != 0;
Jeff Sharkey46349872015-07-28 10:49:47 -07002749
Jeff Sharkeyc02bfae2016-03-27 15:06:53 -06002750 final boolean userKeyUnlocked;
2751 final boolean storagePermission;
2752 final long token = Binder.clearCallingIdentity();
Svetoslav38c3dbb2015-07-14 11:27:06 -07002753 try {
Jeff Sharkeyc02bfae2016-03-27 15:06:53 -06002754 userKeyUnlocked = isUserKeyUnlocked(userId);
Sudheer Shanka2250d562016-11-07 15:41:02 -08002755 storagePermission = mStorageManagerInternal.hasExternalStorage(uid, packageName);
Svetoslav38c3dbb2015-07-14 11:27:06 -07002756 } finally {
Jeff Sharkeyc02bfae2016-03-27 15:06:53 -06002757 Binder.restoreCallingIdentity(token);
Svetoslav38c3dbb2015-07-14 11:27:06 -07002758 }
Svet Ganov6ee871e2015-07-10 14:29:33 -07002759
Jeff Sharkeyc02bfae2016-03-27 15:06:53 -06002760 boolean foundPrimary = false;
2761
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07002762 final ArrayList<StorageVolume> res = new ArrayList<>();
Jeff Sharkey48877892015-03-18 11:27:19 -07002763 synchronized (mLock) {
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07002764 for (int i = 0; i < mVolumes.size(); i++) {
2765 final VolumeInfo vol = mVolumes.valueAt(i);
Jeff Sharkeyc02bfae2016-03-27 15:06:53 -06002766 switch (vol.getType()) {
2767 case VolumeInfo.TYPE_PUBLIC:
Risan05c41e62018-10-29 08:57:43 +09002768 case VolumeInfo.TYPE_STUB:
Jeff Sharkeyc02bfae2016-03-27 15:06:53 -06002769 case VolumeInfo.TYPE_EMULATED:
2770 break;
2771 default:
2772 continue;
2773 }
2774
2775 boolean match = false;
2776 if (forWrite) {
2777 match = vol.isVisibleForWrite(userId);
2778 } else {
Felipe Leme123a0e72016-06-10 11:09:11 -07002779 match = vol.isVisibleForRead(userId)
2780 || (includeInvisible && vol.getPath() != null);
Jeff Sharkeyc02bfae2016-03-27 15:06:53 -06002781 }
2782 if (!match) continue;
2783
2784 boolean reportUnmounted = false;
2785 if ((vol.getType() == VolumeInfo.TYPE_EMULATED) && !userKeyUnlocked) {
2786 reportUnmounted = true;
2787 } else if (!storagePermission && !realState) {
2788 reportUnmounted = true;
2789 }
2790
2791 final StorageVolume userVol = vol.buildStorageVolume(mContext, userId,
2792 reportUnmounted);
2793 if (vol.isPrimary()) {
2794 res.add(0, userVol);
2795 foundPrimary = true;
2796 } else {
2797 res.add(userVol);
Jeff Sharkeyb049e212012-09-07 23:16:01 -07002798 }
Mike Lockwood8fa5f802011-03-24 08:12:30 -07002799 }
Mike Lockwood8fa5f802011-03-24 08:12:30 -07002800 }
Jeff Sharkey48877892015-03-18 11:27:19 -07002801
2802 if (!foundPrimary) {
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07002803 Log.w(TAG, "No primary storage defined yet; hacking together a stub");
Jeff Sharkey48877892015-03-18 11:27:19 -07002804
2805 final boolean primaryPhysical = SystemProperties.getBoolean(
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07002806 StorageManager.PROP_PRIMARY_PHYSICAL, false);
Jeff Sharkey48877892015-03-18 11:27:19 -07002807
2808 final String id = "stub_primary";
2809 final File path = Environment.getLegacyExternalStorageDirectory();
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07002810 final String description = mContext.getString(android.R.string.unknownName);
Jeff Sharkey48877892015-03-18 11:27:19 -07002811 final boolean primary = true;
2812 final boolean removable = primaryPhysical;
2813 final boolean emulated = !primaryPhysical;
Jeff Sharkey48877892015-03-18 11:27:19 -07002814 final boolean allowMassStorage = false;
2815 final long maxFileSize = 0L;
2816 final UserHandle owner = new UserHandle(userId);
2817 final String uuid = null;
Jeff Sharkey48877892015-03-18 11:27:19 -07002818 final String state = Environment.MEDIA_REMOVED;
2819
Jerry Zhang71938e12018-05-10 18:28:29 -07002820 res.add(0, new StorageVolume(id, path, path,
Jerry Zhangf9c5c252017-08-16 18:07:51 -07002821 description, primary, removable, emulated,
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07002822 allowMassStorage, maxFileSize, owner, uuid, state));
Jeff Sharkey48877892015-03-18 11:27:19 -07002823 }
2824
2825 return res.toArray(new StorageVolume[res.size()]);
Mike Lockwood8fa5f802011-03-24 08:12:30 -07002826 }
2827
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07002828 @Override
2829 public DiskInfo[] getDisks() {
2830 synchronized (mLock) {
2831 final DiskInfo[] res = new DiskInfo[mDisks.size()];
2832 for (int i = 0; i < mDisks.size(); i++) {
2833 res[i] = mDisks.valueAt(i);
2834 }
2835 return res;
2836 }
2837 }
2838
2839 @Override
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07002840 public VolumeInfo[] getVolumes(int flags) {
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07002841 synchronized (mLock) {
2842 final VolumeInfo[] res = new VolumeInfo[mVolumes.size()];
2843 for (int i = 0; i < mVolumes.size(); i++) {
2844 res[i] = mVolumes.valueAt(i);
2845 }
2846 return res;
2847 }
2848 }
2849
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07002850 @Override
2851 public VolumeRecord[] getVolumeRecords(int flags) {
2852 synchronized (mLock) {
2853 final VolumeRecord[] res = new VolumeRecord[mRecords.size()];
2854 for (int i = 0; i < mRecords.size(); i++) {
2855 res[i] = mRecords.valueAt(i);
2856 }
2857 return res;
2858 }
2859 }
2860
Jeff Sharkey9bed0702017-01-23 20:37:05 -07002861 @Override
2862 public long getCacheQuotaBytes(String volumeUuid, int uid) {
2863 if (uid != Binder.getCallingUid()) {
2864 mContext.enforceCallingPermission(android.Manifest.permission.STORAGE_INTERNAL, TAG);
2865 }
Daniel Nishi80fdb012017-03-09 14:30:07 -08002866 final long token = Binder.clearCallingIdentity();
2867 final StorageStatsManager stats = mContext.getSystemService(StorageStatsManager.class);
2868 try {
2869 return stats.getCacheQuotaBytes(volumeUuid, uid);
2870 } finally {
2871 Binder.restoreCallingIdentity(token);
2872 }
Jeff Sharkey9bed0702017-01-23 20:37:05 -07002873 }
2874
2875 @Override
2876 public long getCacheSizeBytes(String volumeUuid, int uid) {
2877 if (uid != Binder.getCallingUid()) {
2878 mContext.enforceCallingPermission(android.Manifest.permission.STORAGE_INTERNAL, TAG);
2879 }
2880 final long token = Binder.clearCallingIdentity();
2881 try {
2882 return mContext.getSystemService(StorageStatsManager.class)
2883 .queryStatsForUid(volumeUuid, uid).getCacheBytes();
Jeff Sharkey789a8fc2017-04-16 13:18:35 -06002884 } catch (IOException e) {
2885 throw new ParcelableException(e);
Jeff Sharkey9bed0702017-01-23 20:37:05 -07002886 } finally {
2887 Binder.restoreCallingIdentity(token);
2888 }
2889 }
2890
Jeff Sharkey35e46d22017-06-09 10:01:20 -06002891 private int adjustAllocateFlags(int flags, int callingUid, String callingPackage) {
2892 // Require permission to allocate aggressively
2893 if ((flags & StorageManager.FLAG_ALLOCATE_AGGRESSIVE) != 0) {
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07002894 mContext.enforceCallingOrSelfPermission(
2895 android.Manifest.permission.ALLOCATE_AGGRESSIVE, TAG);
2896 }
2897
Jeff Sharkey35e46d22017-06-09 10:01:20 -06002898 // Apps normally can't directly defy reserved space
2899 flags &= ~StorageManager.FLAG_ALLOCATE_DEFY_ALL_RESERVED;
2900 flags &= ~StorageManager.FLAG_ALLOCATE_DEFY_HALF_RESERVED;
2901
2902 // However, if app is actively using the camera, then we're willing to
2903 // clear up to half of the reserved cache space, since the user might be
2904 // trying to capture an important memory.
2905 final AppOpsManager appOps = mContext.getSystemService(AppOpsManager.class);
2906 final long token = Binder.clearCallingIdentity();
2907 try {
2908 if (appOps.isOperationActive(AppOpsManager.OP_CAMERA, callingUid, callingPackage)) {
2909 Slog.d(TAG, "UID " + callingUid + " is actively using camera;"
2910 + " letting them defy reserved cached data");
2911 flags |= StorageManager.FLAG_ALLOCATE_DEFY_HALF_RESERVED;
2912 }
2913 } finally {
2914 Binder.restoreCallingIdentity(token);
2915 }
2916
2917 return flags;
2918 }
2919
2920 @Override
2921 public long getAllocatableBytes(String volumeUuid, int flags, String callingPackage) {
2922 flags = adjustAllocateFlags(flags, Binder.getCallingUid(), callingPackage);
2923
2924 final StorageManager storage = mContext.getSystemService(StorageManager.class);
2925 final StorageStatsManager stats = mContext.getSystemService(StorageStatsManager.class);
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07002926 final long token = Binder.clearCallingIdentity();
2927 try {
2928 // In general, apps can allocate as much space as they want, except
2929 // we never let them eat into either the minimum cache space or into
Jeff Sharkeyddff8072017-05-26 13:10:46 -06002930 // the low disk warning space. To avoid user confusion, this logic
2931 // should be kept in sync with getFreeBytes().
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07002932 final File path = storage.findPathForUuid(volumeUuid);
Jeff Sharkeyddff8072017-05-26 13:10:46 -06002933
2934 final long usable = path.getUsableSpace();
2935 final long lowReserved = storage.getStorageLowBytes(path);
2936 final long fullReserved = storage.getStorageFullBytes(path);
2937
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07002938 if (stats.isQuotaSupported(volumeUuid)) {
Jeff Sharkeyddff8072017-05-26 13:10:46 -06002939 final long cacheTotal = stats.getCacheBytes(volumeUuid);
Jeff Sharkey35e46d22017-06-09 10:01:20 -06002940 final long cacheReserved = storage.getStorageCacheBytes(path, flags);
Jeff Sharkeyddff8072017-05-26 13:10:46 -06002941 final long cacheClearable = Math.max(0, cacheTotal - cacheReserved);
2942
Jeff Sharkey35e46d22017-06-09 10:01:20 -06002943 if ((flags & StorageManager.FLAG_ALLOCATE_AGGRESSIVE) != 0) {
2944 return Math.max(0, (usable + cacheClearable) - fullReserved);
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07002945 } else {
Jeff Sharkeyddff8072017-05-26 13:10:46 -06002946 return Math.max(0, (usable + cacheClearable) - lowReserved);
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07002947 }
2948 } else {
2949 // When we don't have fast quota information, we ignore cached
2950 // data and only consider unused bytes.
Jeff Sharkey35e46d22017-06-09 10:01:20 -06002951 if ((flags & StorageManager.FLAG_ALLOCATE_AGGRESSIVE) != 0) {
Jeff Sharkeyddff8072017-05-26 13:10:46 -06002952 return Math.max(0, usable - fullReserved);
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07002953 } else {
Jeff Sharkeyddff8072017-05-26 13:10:46 -06002954 return Math.max(0, usable - lowReserved);
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07002955 }
2956 }
Jeff Sharkey789a8fc2017-04-16 13:18:35 -06002957 } catch (IOException e) {
2958 throw new ParcelableException(e);
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07002959 } finally {
2960 Binder.restoreCallingIdentity(token);
2961 }
Jeff Sharkey500ce9e2017-02-12 02:39:24 -07002962 }
2963
2964 @Override
Jeff Sharkey35e46d22017-06-09 10:01:20 -06002965 public void allocateBytes(String volumeUuid, long bytes, int flags, String callingPackage) {
2966 flags = adjustAllocateFlags(flags, Binder.getCallingUid(), callingPackage);
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07002967
Jeff Sharkey35e46d22017-06-09 10:01:20 -06002968 final long allocatableBytes = getAllocatableBytes(volumeUuid, flags, callingPackage);
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07002969 if (bytes > allocatableBytes) {
2970 throw new ParcelableException(new IOException("Failed to allocate " + bytes
2971 + " because only " + allocatableBytes + " allocatable"));
2972 }
2973
Jeff Sharkey35e46d22017-06-09 10:01:20 -06002974 final StorageManager storage = mContext.getSystemService(StorageManager.class);
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07002975 final long token = Binder.clearCallingIdentity();
2976 try {
Jeff Sharkey789a8fc2017-04-16 13:18:35 -06002977 // Free up enough disk space to satisfy both the requested allocation
2978 // and our low disk warning space.
2979 final File path = storage.findPathForUuid(volumeUuid);
Jeff Sharkeyddff8072017-05-26 13:10:46 -06002980 if ((flags & StorageManager.FLAG_ALLOCATE_AGGRESSIVE) != 0) {
2981 bytes += storage.getStorageFullBytes(path);
2982 } else {
2983 bytes += storage.getStorageLowBytes(path);
2984 }
Jeff Sharkey789a8fc2017-04-16 13:18:35 -06002985
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07002986 mPms.freeStorage(volumeUuid, bytes, flags);
2987 } catch (IOException e) {
2988 throw new ParcelableException(e);
2989 } finally {
2990 Binder.restoreCallingIdentity(token);
Jeff Sharkey500ce9e2017-02-12 02:39:24 -07002991 }
2992 }
2993
Kenny Rootaf9d6672010-10-08 09:21:39 -07002994 private void addObbStateLocked(ObbState obbState) throws RemoteException {
2995 final IBinder binder = obbState.getBinder();
2996 List<ObbState> obbStates = mObbMounts.get(binder);
Kenny Root5919ac62010-10-05 09:49:40 -07002997
Kenny Rootaf9d6672010-10-08 09:21:39 -07002998 if (obbStates == null) {
2999 obbStates = new ArrayList<ObbState>();
3000 mObbMounts.put(binder, obbStates);
3001 } else {
3002 for (final ObbState o : obbStates) {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003003 if (o.rawPath.equals(obbState.rawPath)) {
Kenny Rootaf9d6672010-10-08 09:21:39 -07003004 throw new IllegalStateException("Attempt to add ObbState twice. "
Sudheer Shanka2250d562016-11-07 15:41:02 -08003005 + "This indicates an error in the StorageManagerService logic.");
Kenny Root5919ac62010-10-05 09:49:40 -07003006 }
3007 }
Kenny Roota02b8b02010-08-05 16:14:17 -07003008 }
Kenny Rootaf9d6672010-10-08 09:21:39 -07003009
3010 obbStates.add(obbState);
3011 try {
3012 obbState.link();
3013 } catch (RemoteException e) {
3014 /*
3015 * The binder died before we could link it, so clean up our state
3016 * and return failure.
3017 */
3018 obbStates.remove(obbState);
3019 if (obbStates.isEmpty()) {
3020 mObbMounts.remove(binder);
3021 }
3022
3023 // Rethrow the error so mountObb can get it
3024 throw e;
3025 }
3026
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003027 mObbPathToStateMap.put(obbState.rawPath, obbState);
Kenny Roota02b8b02010-08-05 16:14:17 -07003028 }
3029
Kenny Rootaf9d6672010-10-08 09:21:39 -07003030 private void removeObbStateLocked(ObbState obbState) {
3031 final IBinder binder = obbState.getBinder();
3032 final List<ObbState> obbStates = mObbMounts.get(binder);
3033 if (obbStates != null) {
3034 if (obbStates.remove(obbState)) {
3035 obbState.unlink();
Kenny Root05105f72010-09-22 17:29:43 -07003036 }
Kenny Rootaf9d6672010-10-08 09:21:39 -07003037 if (obbStates.isEmpty()) {
3038 mObbMounts.remove(binder);
3039 }
Kenny Roota02b8b02010-08-05 16:14:17 -07003040 }
Kenny Roota02b8b02010-08-05 16:14:17 -07003041
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003042 mObbPathToStateMap.remove(obbState.rawPath);
Kenny Root38cf8862010-09-26 14:18:51 -07003043 }
3044
Kenny Roota02b8b02010-08-05 16:14:17 -07003045 private class ObbActionHandler extends Handler {
3046 private boolean mBound = false;
Kenny Root480afe72010-10-07 10:17:50 -07003047 private final List<ObbAction> mActions = new LinkedList<ObbAction>();
Kenny Roota02b8b02010-08-05 16:14:17 -07003048
3049 ObbActionHandler(Looper l) {
3050 super(l);
3051 }
3052
3053 @Override
3054 public void handleMessage(Message msg) {
3055 switch (msg.what) {
3056 case OBB_RUN_ACTION: {
Kenny Root480afe72010-10-07 10:17:50 -07003057 final ObbAction action = (ObbAction) msg.obj;
Kenny Roota02b8b02010-08-05 16:14:17 -07003058
3059 if (DEBUG_OBB)
3060 Slog.i(TAG, "OBB_RUN_ACTION: " + action.toString());
3061
3062 // If a bind was already initiated we don't really
3063 // need to do anything. The pending install
3064 // will be processed later on.
3065 if (!mBound) {
3066 // If this is the only one pending we might
3067 // have to bind to the service again.
3068 if (!connectToService()) {
Jeff Sharkey0095a822018-02-15 13:06:53 -07003069 action.notifyObbStateChange(new ObbException(ERROR_INTERNAL,
3070 "Failed to bind to media container service"));
Kenny Roota02b8b02010-08-05 16:14:17 -07003071 return;
Kenny Roota02b8b02010-08-05 16:14:17 -07003072 }
Kenny Roota02b8b02010-08-05 16:14:17 -07003073 }
Kenny Root735de3b2010-09-30 14:11:39 -07003074
Kenny Root735de3b2010-09-30 14:11:39 -07003075 mActions.add(action);
Kenny Roota02b8b02010-08-05 16:14:17 -07003076 break;
3077 }
3078 case OBB_MCS_BOUND: {
3079 if (DEBUG_OBB)
3080 Slog.i(TAG, "OBB_MCS_BOUND");
3081 if (msg.obj != null) {
3082 mContainerService = (IMediaContainerService) msg.obj;
3083 }
3084 if (mContainerService == null) {
3085 // Something seriously wrong. Bail out
Kenny Roota02b8b02010-08-05 16:14:17 -07003086 for (ObbAction action : mActions) {
3087 // Indicate service bind error
Jeff Sharkey0095a822018-02-15 13:06:53 -07003088 action.notifyObbStateChange(new ObbException(ERROR_INTERNAL,
3089 "Failed to bind to media container service"));
Kenny Roota02b8b02010-08-05 16:14:17 -07003090 }
3091 mActions.clear();
3092 } else if (mActions.size() > 0) {
Kenny Root480afe72010-10-07 10:17:50 -07003093 final ObbAction action = mActions.get(0);
Kenny Roota02b8b02010-08-05 16:14:17 -07003094 if (action != null) {
3095 action.execute(this);
3096 }
3097 } else {
3098 // Should never happen ideally.
3099 Slog.w(TAG, "Empty queue");
3100 }
3101 break;
3102 }
3103 case OBB_MCS_RECONNECT: {
3104 if (DEBUG_OBB)
3105 Slog.i(TAG, "OBB_MCS_RECONNECT");
3106 if (mActions.size() > 0) {
3107 if (mBound) {
3108 disconnectService();
3109 }
3110 if (!connectToService()) {
Kenny Roota02b8b02010-08-05 16:14:17 -07003111 for (ObbAction action : mActions) {
3112 // Indicate service bind error
Jeff Sharkey0095a822018-02-15 13:06:53 -07003113 action.notifyObbStateChange(new ObbException(ERROR_INTERNAL,
3114 "Failed to bind to media container service"));
Kenny Roota02b8b02010-08-05 16:14:17 -07003115 }
3116 mActions.clear();
3117 }
3118 }
3119 break;
3120 }
3121 case OBB_MCS_UNBIND: {
3122 if (DEBUG_OBB)
3123 Slog.i(TAG, "OBB_MCS_UNBIND");
3124
3125 // Delete pending install
3126 if (mActions.size() > 0) {
3127 mActions.remove(0);
3128 }
3129 if (mActions.size() == 0) {
3130 if (mBound) {
3131 disconnectService();
3132 }
3133 } else {
3134 // There are more pending requests in queue.
3135 // Just post MCS_BOUND message to trigger processing
3136 // of next pending install.
3137 mObbActionHandler.sendEmptyMessage(OBB_MCS_BOUND);
3138 }
3139 break;
3140 }
Kenny Rootaf9d6672010-10-08 09:21:39 -07003141 case OBB_FLUSH_MOUNT_STATE: {
3142 final String path = (String) msg.obj;
3143
3144 if (DEBUG_OBB)
3145 Slog.i(TAG, "Flushing all OBB state for path " + path);
3146
3147 synchronized (mObbMounts) {
3148 final List<ObbState> obbStatesToRemove = new LinkedList<ObbState>();
3149
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003150 final Iterator<ObbState> i = mObbPathToStateMap.values().iterator();
Kenny Rootaf9d6672010-10-08 09:21:39 -07003151 while (i.hasNext()) {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003152 final ObbState state = i.next();
Kenny Rootaf9d6672010-10-08 09:21:39 -07003153
3154 /*
3155 * If this entry's source file is in the volume path
3156 * that got unmounted, remove it because it's no
3157 * longer valid.
3158 */
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003159 if (state.canonicalPath.startsWith(path)) {
3160 obbStatesToRemove.add(state);
Kenny Rootaf9d6672010-10-08 09:21:39 -07003161 }
3162 }
3163
3164 for (final ObbState obbState : obbStatesToRemove) {
3165 if (DEBUG_OBB)
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003166 Slog.i(TAG, "Removing state for " + obbState.rawPath);
Kenny Rootaf9d6672010-10-08 09:21:39 -07003167
3168 removeObbStateLocked(obbState);
3169
3170 try {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003171 obbState.token.onObbResult(obbState.rawPath, obbState.nonce,
Kenny Rootaf9d6672010-10-08 09:21:39 -07003172 OnObbStateChangeListener.UNMOUNTED);
3173 } catch (RemoteException e) {
3174 Slog.i(TAG, "Couldn't send unmount notification for OBB: "
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003175 + obbState.rawPath);
Kenny Rootaf9d6672010-10-08 09:21:39 -07003176 }
3177 }
3178 }
3179 break;
3180 }
Kenny Roota02b8b02010-08-05 16:14:17 -07003181 }
3182 }
3183
3184 private boolean connectToService() {
3185 if (DEBUG_OBB)
3186 Slog.i(TAG, "Trying to bind to DefaultContainerService");
3187
3188 Intent service = new Intent().setComponent(DEFAULT_CONTAINER_COMPONENT);
Jeff Sharkey6dce4962015-07-03 18:08:41 -07003189 if (mContext.bindServiceAsUser(service, mDefContainerConn, Context.BIND_AUTO_CREATE,
Xiaohui Chene4de5a02015-09-22 15:33:31 -07003190 UserHandle.SYSTEM)) {
Kenny Roota02b8b02010-08-05 16:14:17 -07003191 mBound = true;
3192 return true;
3193 }
3194 return false;
3195 }
3196
3197 private void disconnectService() {
3198 mContainerService = null;
3199 mBound = false;
3200 mContext.unbindService(mDefContainerConn);
3201 }
3202 }
3203
Jeff Sharkey0095a822018-02-15 13:06:53 -07003204 private static class ObbException extends Exception {
3205 public final int status;
3206
3207 public ObbException(int status, String message) {
3208 super(message);
3209 this.status = status;
3210 }
3211
3212 public ObbException(int status, Throwable cause) {
3213 super(cause.getMessage(), cause);
3214 this.status = status;
3215 }
3216 }
3217
Kenny Roota02b8b02010-08-05 16:14:17 -07003218 abstract class ObbAction {
3219 private static final int MAX_RETRIES = 3;
3220 private int mRetries;
3221
3222 ObbState mObbState;
3223
3224 ObbAction(ObbState obbState) {
3225 mObbState = obbState;
3226 }
3227
3228 public void execute(ObbActionHandler handler) {
3229 try {
3230 if (DEBUG_OBB)
Ben Komalo444eca22011-09-01 15:17:44 -07003231 Slog.i(TAG, "Starting to execute action: " + toString());
Kenny Roota02b8b02010-08-05 16:14:17 -07003232 mRetries++;
3233 if (mRetries > MAX_RETRIES) {
Kenny Root480afe72010-10-07 10:17:50 -07003234 mObbActionHandler.sendEmptyMessage(OBB_MCS_UNBIND);
Jeff Sharkey0095a822018-02-15 13:06:53 -07003235 notifyObbStateChange(new ObbException(ERROR_INTERNAL,
3236 "Failed to bind to media container service"));
Kenny Roota02b8b02010-08-05 16:14:17 -07003237 } else {
3238 handleExecute();
3239 if (DEBUG_OBB)
3240 Slog.i(TAG, "Posting install MCS_UNBIND");
3241 mObbActionHandler.sendEmptyMessage(OBB_MCS_UNBIND);
3242 }
Jeff Sharkey0095a822018-02-15 13:06:53 -07003243 } catch (ObbException e) {
3244 notifyObbStateChange(e);
Kenny Root17eb6fb2010-10-06 15:02:52 -07003245 mObbActionHandler.sendEmptyMessage(OBB_MCS_UNBIND);
Kenny Roota02b8b02010-08-05 16:14:17 -07003246 }
3247 }
3248
Jeff Sharkey0095a822018-02-15 13:06:53 -07003249 abstract void handleExecute() throws ObbException;
Kenny Root38cf8862010-09-26 14:18:51 -07003250
Jeff Sharkey0095a822018-02-15 13:06:53 -07003251 protected ObbInfo getObbInfo() throws ObbException {
3252 final ObbInfo obbInfo;
Kenny Root38cf8862010-09-26 14:18:51 -07003253 try {
Xiaohui Chen621b3fc2015-10-02 14:41:42 -07003254 obbInfo = mContainerService.getObbInfo(mObbState.canonicalPath);
Jeff Sharkey0095a822018-02-15 13:06:53 -07003255 } catch (Exception e) {
3256 throw new ObbException(ERROR_PERMISSION_DENIED, e);
Kenny Root38cf8862010-09-26 14:18:51 -07003257 }
Jeff Sharkey0095a822018-02-15 13:06:53 -07003258 if (obbInfo != null) {
3259 return obbInfo;
3260 } else {
3261 throw new ObbException(ERROR_INTERNAL,
3262 "Missing OBB info for: " + mObbState.canonicalPath);
Kenny Root38cf8862010-09-26 14:18:51 -07003263 }
Kenny Root38cf8862010-09-26 14:18:51 -07003264 }
3265
Jeff Sharkey0095a822018-02-15 13:06:53 -07003266 protected void notifyObbStateChange(ObbException e) {
3267 Slog.w(TAG, e);
3268 notifyObbStateChange(e.status);
3269 }
3270
3271 protected void notifyObbStateChange(int status) {
Kenny Rootaf9d6672010-10-08 09:21:39 -07003272 if (mObbState == null || mObbState.token == null) {
3273 return;
3274 }
3275
Kenny Root38cf8862010-09-26 14:18:51 -07003276 try {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003277 mObbState.token.onObbResult(mObbState.rawPath, mObbState.nonce, status);
Kenny Root38cf8862010-09-26 14:18:51 -07003278 } catch (RemoteException e) {
Sudheer Shanka2250d562016-11-07 15:41:02 -08003279 Slog.w(TAG, "StorageEventListener went away while calling onObbStateChanged");
Kenny Root38cf8862010-09-26 14:18:51 -07003280 }
3281 }
Kenny Roota02b8b02010-08-05 16:14:17 -07003282 }
3283
3284 class MountObbAction extends ObbAction {
Ben Komalo444eca22011-09-01 15:17:44 -07003285 private final String mKey;
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003286 private final int mCallingUid;
Kenny Roota02b8b02010-08-05 16:14:17 -07003287
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003288 MountObbAction(ObbState obbState, String key, int callingUid) {
Kenny Roota02b8b02010-08-05 16:14:17 -07003289 super(obbState);
3290 mKey = key;
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003291 mCallingUid = callingUid;
Kenny Roota02b8b02010-08-05 16:14:17 -07003292 }
3293
Jason parks5af0b912010-11-29 09:05:25 -06003294 @Override
Jeff Sharkey0095a822018-02-15 13:06:53 -07003295 public void handleExecute() throws ObbException {
Kenny Rootaf9d6672010-10-08 09:21:39 -07003296 warnOnNotMounted();
3297
Kenny Root38cf8862010-09-26 14:18:51 -07003298 final ObbInfo obbInfo = getObbInfo();
3299
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003300 if (!isUidOwnerOfPackageOrSystem(obbInfo.packageName, mCallingUid)) {
Jeff Sharkey0095a822018-02-15 13:06:53 -07003301 throw new ObbException(ERROR_PERMISSION_DENIED, "Denied attempt to mount OBB "
3302 + obbInfo.filename + " which is owned by " + obbInfo.packageName);
Kenny Roota02b8b02010-08-05 16:14:17 -07003303 }
3304
Kenny Rootaf9d6672010-10-08 09:21:39 -07003305 final boolean isMounted;
3306 synchronized (mObbMounts) {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003307 isMounted = mObbPathToStateMap.containsKey(mObbState.rawPath);
Kenny Rootaf9d6672010-10-08 09:21:39 -07003308 }
3309 if (isMounted) {
Jeff Sharkey0095a822018-02-15 13:06:53 -07003310 throw new ObbException(ERROR_ALREADY_MOUNTED,
3311 "Attempt to mount OBB which is already mounted: " + obbInfo.filename);
Kenny Rootaf9d6672010-10-08 09:21:39 -07003312 }
3313
Kenny Rootaf9d6672010-10-08 09:21:39 -07003314 final String hashedKey;
Jeff Sharkey41cd6812017-09-11 10:32:17 -06003315 final String binderKey;
Kenny Rootaf9d6672010-10-08 09:21:39 -07003316 if (mKey == null) {
3317 hashedKey = "none";
Jeff Sharkey41cd6812017-09-11 10:32:17 -06003318 binderKey = "";
Kenny Rootaf9d6672010-10-08 09:21:39 -07003319 } else {
Kenny Rootaf9d6672010-10-08 09:21:39 -07003320 try {
Kenny Root3b1abba2010-10-13 15:00:07 -07003321 SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
3322
3323 KeySpec ks = new PBEKeySpec(mKey.toCharArray(), obbInfo.salt,
3324 PBKDF2_HASH_ROUNDS, CRYPTO_ALGORITHM_KEY_SIZE);
3325 SecretKey key = factory.generateSecret(ks);
3326 BigInteger bi = new BigInteger(key.getEncoded());
3327 hashedKey = bi.toString(16);
Jeff Sharkey41cd6812017-09-11 10:32:17 -06003328 binderKey = hashedKey;
Jeff Sharkey0095a822018-02-15 13:06:53 -07003329 } catch (GeneralSecurityException e) {
3330 throw new ObbException(ERROR_INTERNAL, e);
Kenny Root38cf8862010-09-26 14:18:51 -07003331 }
Kenny Rootaf9d6672010-10-08 09:21:39 -07003332 }
Kenny Root38cf8862010-09-26 14:18:51 -07003333
Kenny Rootaf9d6672010-10-08 09:21:39 -07003334 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06003335 mObbState.volId = mVold.createObb(mObbState.canonicalPath, binderKey,
3336 mObbState.ownerGid);
3337 mVold.mount(mObbState.volId, 0, -1);
Kenny Roota02b8b02010-08-05 16:14:17 -07003338
Kenny Rootaf9d6672010-10-08 09:21:39 -07003339 if (DEBUG_OBB)
Xiaohui Chen621b3fc2015-10-02 14:41:42 -07003340 Slog.d(TAG, "Successfully mounted OBB " + mObbState.canonicalPath);
Kenny Rootaf9d6672010-10-08 09:21:39 -07003341
3342 synchronized (mObbMounts) {
3343 addObbStateLocked(mObbState);
3344 }
3345
Jeff Sharkey0095a822018-02-15 13:06:53 -07003346 notifyObbStateChange(MOUNTED);
3347 } catch (Exception e) {
3348 throw new ObbException(ERROR_COULD_NOT_MOUNT, e);
Kenny Root02c87302010-07-01 08:10:18 -07003349 }
3350 }
3351
Jason parks5af0b912010-11-29 09:05:25 -06003352 @Override
Kenny Roota02b8b02010-08-05 16:14:17 -07003353 public String toString() {
3354 StringBuilder sb = new StringBuilder();
3355 sb.append("MountObbAction{");
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003356 sb.append(mObbState);
Kenny Roota02b8b02010-08-05 16:14:17 -07003357 sb.append('}');
3358 return sb.toString();
3359 }
3360 }
3361
3362 class UnmountObbAction extends ObbAction {
Ben Komalo444eca22011-09-01 15:17:44 -07003363 private final boolean mForceUnmount;
Kenny Roota02b8b02010-08-05 16:14:17 -07003364
3365 UnmountObbAction(ObbState obbState, boolean force) {
3366 super(obbState);
3367 mForceUnmount = force;
3368 }
3369
Jason parks5af0b912010-11-29 09:05:25 -06003370 @Override
Jeff Sharkey0095a822018-02-15 13:06:53 -07003371 public void handleExecute() throws ObbException {
Kenny Rootaf9d6672010-10-08 09:21:39 -07003372 warnOnNotMounted();
3373
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003374 final ObbState existingState;
Kenny Root38cf8862010-09-26 14:18:51 -07003375 synchronized (mObbMounts) {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003376 existingState = mObbPathToStateMap.get(mObbState.rawPath);
Kenny Rootaf9d6672010-10-08 09:21:39 -07003377 }
Kenny Root38cf8862010-09-26 14:18:51 -07003378
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003379 if (existingState == null) {
Jeff Sharkey0095a822018-02-15 13:06:53 -07003380 throw new ObbException(ERROR_NOT_MOUNTED, "Missing existingState");
Kenny Rootaf9d6672010-10-08 09:21:39 -07003381 }
3382
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003383 if (existingState.ownerGid != mObbState.ownerGid) {
Jeff Sharkey0095a822018-02-15 13:06:53 -07003384 notifyObbStateChange(new ObbException(ERROR_PERMISSION_DENIED,
3385 "Permission denied to unmount OBB " + existingState.rawPath
3386 + " (owned by GID " + existingState.ownerGid + ")"));
Kenny Rootaf9d6672010-10-08 09:21:39 -07003387 return;
3388 }
3389
Kenny Rootaf9d6672010-10-08 09:21:39 -07003390 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06003391 mVold.unmount(mObbState.volId);
3392 mVold.destroyObb(mObbState.volId);
3393 mObbState.volId = null;
Kenny Roota02b8b02010-08-05 16:14:17 -07003394
Kenny Rootaf9d6672010-10-08 09:21:39 -07003395 synchronized (mObbMounts) {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003396 removeObbStateLocked(existingState);
Kenny Root38cf8862010-09-26 14:18:51 -07003397 }
3398
Jeff Sharkey0095a822018-02-15 13:06:53 -07003399 notifyObbStateChange(UNMOUNTED);
3400 } catch (Exception e) {
3401 throw new ObbException(ERROR_COULD_NOT_UNMOUNT, e);
Kenny Roota02b8b02010-08-05 16:14:17 -07003402 }
3403 }
3404
Jason parks5af0b912010-11-29 09:05:25 -06003405 @Override
Kenny Roota02b8b02010-08-05 16:14:17 -07003406 public String toString() {
3407 StringBuilder sb = new StringBuilder();
3408 sb.append("UnmountObbAction{");
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003409 sb.append(mObbState);
Kenny Roota02b8b02010-08-05 16:14:17 -07003410 sb.append(",force=");
3411 sb.append(mForceUnmount);
Kenny Roota02b8b02010-08-05 16:14:17 -07003412 sb.append('}');
3413 return sb.toString();
3414 }
Kenny Root02c87302010-07-01 08:10:18 -07003415 }
Kenny Root38cf8862010-09-26 14:18:51 -07003416
Jeff Sharkey7e19f532017-11-06 13:54:11 -07003417 private void dispatchOnStatus(IVoldTaskListener listener, int status,
3418 PersistableBundle extras) {
3419 if (listener != null) {
3420 try {
3421 listener.onStatus(status, extras);
3422 } catch (RemoteException ignored) {
3423 }
3424 }
3425 }
3426
3427 private void dispatchOnFinished(IVoldTaskListener listener, int status,
3428 PersistableBundle extras) {
3429 if (listener != null) {
3430 try {
3431 listener.onFinished(status, extras);
3432 } catch (RemoteException ignored) {
3433 }
3434 }
3435 }
3436
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07003437 private static class Callbacks extends Handler {
3438 private static final int MSG_STORAGE_STATE_CHANGED = 1;
3439 private static final int MSG_VOLUME_STATE_CHANGED = 2;
Jeff Sharkey50a05452015-04-29 11:24:52 -07003440 private static final int MSG_VOLUME_RECORD_CHANGED = 3;
3441 private static final int MSG_VOLUME_FORGOTTEN = 4;
3442 private static final int MSG_DISK_SCANNED = 5;
Makoto Onuki9dc575d2015-06-12 16:10:25 -07003443 private static final int MSG_DISK_DESTROYED = 6;
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07003444
Sudheer Shanka2250d562016-11-07 15:41:02 -08003445 private final RemoteCallbackList<IStorageEventListener>
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07003446 mCallbacks = new RemoteCallbackList<>();
3447
3448 public Callbacks(Looper looper) {
3449 super(looper);
3450 }
3451
Sudheer Shanka2250d562016-11-07 15:41:02 -08003452 public void register(IStorageEventListener callback) {
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07003453 mCallbacks.register(callback);
3454 }
3455
Sudheer Shanka2250d562016-11-07 15:41:02 -08003456 public void unregister(IStorageEventListener callback) {
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07003457 mCallbacks.unregister(callback);
3458 }
3459
3460 @Override
3461 public void handleMessage(Message msg) {
3462 final SomeArgs args = (SomeArgs) msg.obj;
3463 final int n = mCallbacks.beginBroadcast();
3464 for (int i = 0; i < n; i++) {
Sudheer Shanka2250d562016-11-07 15:41:02 -08003465 final IStorageEventListener callback = mCallbacks.getBroadcastItem(i);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07003466 try {
3467 invokeCallback(callback, msg.what, args);
3468 } catch (RemoteException ignored) {
3469 }
3470 }
3471 mCallbacks.finishBroadcast();
3472 args.recycle();
3473 }
3474
Sudheer Shanka2250d562016-11-07 15:41:02 -08003475 private void invokeCallback(IStorageEventListener callback, int what, SomeArgs args)
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07003476 throws RemoteException {
3477 switch (what) {
3478 case MSG_STORAGE_STATE_CHANGED: {
3479 callback.onStorageStateChanged((String) args.arg1, (String) args.arg2,
3480 (String) args.arg3);
3481 break;
3482 }
3483 case MSG_VOLUME_STATE_CHANGED: {
3484 callback.onVolumeStateChanged((VolumeInfo) args.arg1, args.argi2, args.argi3);
3485 break;
3486 }
Jeff Sharkey50a05452015-04-29 11:24:52 -07003487 case MSG_VOLUME_RECORD_CHANGED: {
3488 callback.onVolumeRecordChanged((VolumeRecord) args.arg1);
3489 break;
3490 }
3491 case MSG_VOLUME_FORGOTTEN: {
3492 callback.onVolumeForgotten((String) args.arg1);
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07003493 break;
3494 }
Jeff Sharkey620b32b2015-04-23 19:36:02 -07003495 case MSG_DISK_SCANNED: {
3496 callback.onDiskScanned((DiskInfo) args.arg1, args.argi2);
Jeff Sharkey7e92ef32015-04-17 17:35:07 -07003497 break;
3498 }
Makoto Onuki9dc575d2015-06-12 16:10:25 -07003499 case MSG_DISK_DESTROYED: {
3500 callback.onDiskDestroyed((DiskInfo) args.arg1);
3501 break;
3502 }
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07003503 }
3504 }
3505
3506 private void notifyStorageStateChanged(String path, String oldState, String newState) {
3507 final SomeArgs args = SomeArgs.obtain();
3508 args.arg1 = path;
3509 args.arg2 = oldState;
3510 args.arg3 = newState;
3511 obtainMessage(MSG_STORAGE_STATE_CHANGED, args).sendToTarget();
3512 }
3513
3514 private void notifyVolumeStateChanged(VolumeInfo vol, int oldState, int newState) {
3515 final SomeArgs args = SomeArgs.obtain();
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07003516 args.arg1 = vol.clone();
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07003517 args.argi2 = oldState;
3518 args.argi3 = newState;
3519 obtainMessage(MSG_VOLUME_STATE_CHANGED, args).sendToTarget();
3520 }
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07003521
Jeff Sharkey50a05452015-04-29 11:24:52 -07003522 private void notifyVolumeRecordChanged(VolumeRecord rec) {
3523 final SomeArgs args = SomeArgs.obtain();
3524 args.arg1 = rec.clone();
3525 obtainMessage(MSG_VOLUME_RECORD_CHANGED, args).sendToTarget();
3526 }
3527
3528 private void notifyVolumeForgotten(String fsUuid) {
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07003529 final SomeArgs args = SomeArgs.obtain();
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07003530 args.arg1 = fsUuid;
Jeff Sharkey50a05452015-04-29 11:24:52 -07003531 obtainMessage(MSG_VOLUME_FORGOTTEN, args).sendToTarget();
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07003532 }
Jeff Sharkey7e92ef32015-04-17 17:35:07 -07003533
Jeff Sharkey620b32b2015-04-23 19:36:02 -07003534 private void notifyDiskScanned(DiskInfo disk, int volumeCount) {
Jeff Sharkey7e92ef32015-04-17 17:35:07 -07003535 final SomeArgs args = SomeArgs.obtain();
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07003536 args.arg1 = disk.clone();
Jeff Sharkey620b32b2015-04-23 19:36:02 -07003537 args.argi2 = volumeCount;
3538 obtainMessage(MSG_DISK_SCANNED, args).sendToTarget();
Jeff Sharkey7e92ef32015-04-17 17:35:07 -07003539 }
Makoto Onuki9dc575d2015-06-12 16:10:25 -07003540
3541 private void notifyDiskDestroyed(DiskInfo disk) {
3542 final SomeArgs args = SomeArgs.obtain();
3543 args.arg1 = disk.clone();
3544 obtainMessage(MSG_DISK_DESTROYED, args).sendToTarget();
3545 }
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07003546 }
3547
Kenny Root38cf8862010-09-26 14:18:51 -07003548 @Override
Jeff Sharkey5aca2b82013-10-16 16:21:54 -07003549 protected void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
Jeff Sharkeyfe9a53b2017-03-31 14:08:23 -06003550 if (!DumpUtils.checkDumpPermission(mContext, TAG, writer)) return;
Jeff Sharkey5aca2b82013-10-16 16:21:54 -07003551
3552 final IndentingPrintWriter pw = new IndentingPrintWriter(writer, " ", 160);
Jeff Sharkey27de30d2015-04-18 16:20:27 -07003553 synchronized (mLock) {
3554 pw.println("Disks:");
3555 pw.increaseIndent();
3556 for (int i = 0; i < mDisks.size(); i++) {
3557 final DiskInfo disk = mDisks.valueAt(i);
3558 disk.dump(pw);
3559 }
3560 pw.decreaseIndent();
3561
3562 pw.println();
3563 pw.println("Volumes:");
3564 pw.increaseIndent();
3565 for (int i = 0; i < mVolumes.size(); i++) {
3566 final VolumeInfo vol = mVolumes.valueAt(i);
3567 if (VolumeInfo.ID_PRIVATE_INTERNAL.equals(vol.id)) continue;
3568 vol.dump(pw);
3569 }
3570 pw.decreaseIndent();
3571
3572 pw.println();
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07003573 pw.println("Records:");
Jeff Sharkey27de30d2015-04-18 16:20:27 -07003574 pw.increaseIndent();
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07003575 for (int i = 0; i < mRecords.size(); i++) {
3576 final VolumeRecord note = mRecords.valueAt(i);
3577 note.dump(pw);
Jeff Sharkey27de30d2015-04-18 16:20:27 -07003578 }
3579 pw.decreaseIndent();
Jeff Sharkey275e3e42015-04-24 16:10:32 -07003580
3581 pw.println();
3582 pw.println("Primary storage UUID: " + mPrimaryStorageUuid);
Felipe Leme281389a2016-10-10 17:12:20 -07003583 final Pair<String, Long> pair = StorageManager.getPrimaryStoragePathAndSize();
3584 if (pair == null) {
3585 pw.println("Internal storage total size: N/A");
3586 } else {
3587 pw.print("Internal storage (");
3588 pw.print(pair.first);
3589 pw.print(") total size: ");
3590 pw.print(pair.second);
3591 pw.print(" (");
Jeff Sharkey9f2dc052018-01-07 16:47:31 -07003592 pw.print(DataUnit.MEBIBYTES.toBytes(pair.second));
3593 pw.println(" MiB)");
Felipe Leme281389a2016-10-10 17:12:20 -07003594 }
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07003595 pw.println("Local unlocked users: " + Arrays.toString(mLocalUnlockedUsers));
3596 pw.println("System unlocked users: " + Arrays.toString(mSystemUnlockedUsers));
Jeff Sharkey27de30d2015-04-18 16:20:27 -07003597 }
Kenny Root38cf8862010-09-26 14:18:51 -07003598
Kenny Root38cf8862010-09-26 14:18:51 -07003599 synchronized (mObbMounts) {
Jeff Sharkey27de30d2015-04-18 16:20:27 -07003600 pw.println();
Jeff Sharkey5aca2b82013-10-16 16:21:54 -07003601 pw.println("mObbMounts:");
3602 pw.increaseIndent();
3603 final Iterator<Entry<IBinder, List<ObbState>>> binders = mObbMounts.entrySet()
3604 .iterator();
Kenny Rootaf9d6672010-10-08 09:21:39 -07003605 while (binders.hasNext()) {
3606 Entry<IBinder, List<ObbState>> e = binders.next();
Jeff Sharkey5aca2b82013-10-16 16:21:54 -07003607 pw.println(e.getKey() + ":");
3608 pw.increaseIndent();
Kenny Rootaf9d6672010-10-08 09:21:39 -07003609 final List<ObbState> obbStates = e.getValue();
Kenny Root38cf8862010-09-26 14:18:51 -07003610 for (final ObbState obbState : obbStates) {
Jeff Sharkey5aca2b82013-10-16 16:21:54 -07003611 pw.println(obbState);
Kenny Root38cf8862010-09-26 14:18:51 -07003612 }
Jeff Sharkey5aca2b82013-10-16 16:21:54 -07003613 pw.decreaseIndent();
Kenny Root38cf8862010-09-26 14:18:51 -07003614 }
Jeff Sharkey5aca2b82013-10-16 16:21:54 -07003615 pw.decreaseIndent();
Kenny Rootaf9d6672010-10-08 09:21:39 -07003616
Jeff Sharkey5aca2b82013-10-16 16:21:54 -07003617 pw.println();
3618 pw.println("mObbPathToStateMap:");
3619 pw.increaseIndent();
Kenny Rootaf9d6672010-10-08 09:21:39 -07003620 final Iterator<Entry<String, ObbState>> maps = mObbPathToStateMap.entrySet().iterator();
3621 while (maps.hasNext()) {
3622 final Entry<String, ObbState> e = maps.next();
Jeff Sharkey5aca2b82013-10-16 16:21:54 -07003623 pw.print(e.getKey());
3624 pw.print(" -> ");
3625 pw.println(e.getValue());
Kenny Rootaf9d6672010-10-08 09:21:39 -07003626 }
Jeff Sharkey5aca2b82013-10-16 16:21:54 -07003627 pw.decreaseIndent();
Kenny Root38cf8862010-09-26 14:18:51 -07003628 }
Kenny Root4161f9b2011-07-13 09:48:33 -07003629
Robert Greenwalt470fd722012-01-18 12:51:15 -08003630 pw.println();
Christopher Tate7265abe2014-11-21 13:54:45 -08003631 pw.print("Last maintenance: ");
Jeff Sharkeye8a4b662015-06-27 15:43:45 -07003632 pw.println(TimeUtils.formatForLogging(mLastMaintenance));
Kenny Root38cf8862010-09-26 14:18:51 -07003633 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003634
Jeff Sharkeyfa23c5a2011-08-09 21:44:24 -07003635 /** {@inheritDoc} */
Jeff Sharkey48877892015-03-18 11:27:19 -07003636 @Override
Jeff Sharkeyfa23c5a2011-08-09 21:44:24 -07003637 public void monitor() {
Jeff Sharkey54402792017-09-15 16:05:19 -06003638 try {
3639 mVold.monitor();
3640 } catch (Exception e) {
3641 Slog.wtf(TAG, e);
Paul Lawrence1c62cbb2015-06-03 14:14:52 -07003642 }
Jeff Sharkeyfa23c5a2011-08-09 21:44:24 -07003643 }
Svet Ganov6ee871e2015-07-10 14:29:33 -07003644
Sudheer Shanka2250d562016-11-07 15:41:02 -08003645 private final class StorageManagerInternalImpl extends StorageManagerInternal {
Svet Ganov6ee871e2015-07-10 14:29:33 -07003646 // Not guarded by a lock.
3647 private final CopyOnWriteArrayList<ExternalStorageMountPolicy> mPolicies =
3648 new CopyOnWriteArrayList<>();
3649
Risana354a272018-10-31 10:10:12 +09003650 @GuardedBy("mResetListeners")
3651 private final List<StorageManagerInternal.ResetListener> mResetListeners =
3652 new ArrayList<>();
3653
Svet Ganov6ee871e2015-07-10 14:29:33 -07003654 @Override
3655 public void addExternalStoragePolicy(ExternalStorageMountPolicy policy) {
3656 // No locking - CopyOnWriteArrayList
3657 mPolicies.add(policy);
3658 }
3659
3660 @Override
3661 public void onExternalStoragePolicyChanged(int uid, String packageName) {
3662 final int mountMode = getExternalStorageMountMode(uid, packageName);
3663 remountUidExternalStorage(uid, mountMode);
3664 }
3665
3666 @Override
3667 public int getExternalStorageMountMode(int uid, String packageName) {
3668 // No locking - CopyOnWriteArrayList
3669 int mountMode = Integer.MAX_VALUE;
3670 for (ExternalStorageMountPolicy policy : mPolicies) {
3671 final int policyMode = policy.getMountMode(uid, packageName);
3672 if (policyMode == Zygote.MOUNT_EXTERNAL_NONE) {
3673 return Zygote.MOUNT_EXTERNAL_NONE;
3674 }
3675 mountMode = Math.min(mountMode, policyMode);
3676 }
3677 if (mountMode == Integer.MAX_VALUE) {
3678 return Zygote.MOUNT_EXTERNAL_NONE;
3679 }
3680 return mountMode;
3681 }
3682
Risana354a272018-10-31 10:10:12 +09003683 @Override
3684 public void addResetListener(StorageManagerInternal.ResetListener listener) {
3685 synchronized (mResetListeners) {
3686 mResetListeners.add(listener);
3687 }
3688 }
3689
3690 public void onReset(IVold vold) {
3691 synchronized (mResetListeners) {
3692 for (StorageManagerInternal.ResetListener listener : mResetListeners) {
3693 listener.onReset(vold);
3694 }
3695 }
3696 }
3697
Svet Ganov6ee871e2015-07-10 14:29:33 -07003698 public boolean hasExternalStorage(int uid, String packageName) {
Amith Yamasani2bd5cff2015-07-22 14:42:31 -07003699 // No need to check for system uid. This avoids a deadlock between
3700 // PackageManagerService and AppOpsService.
3701 if (uid == Process.SYSTEM_UID) {
3702 return true;
3703 }
Svet Ganov6ee871e2015-07-10 14:29:33 -07003704 // No locking - CopyOnWriteArrayList
3705 for (ExternalStorageMountPolicy policy : mPolicies) {
3706 final boolean policyHasStorage = policy.hasExternalStorage(uid, packageName);
3707 if (!policyHasStorage) {
3708 return false;
3709 }
3710 }
3711 return true;
3712 }
3713 }
Jeff Sharkeyfa23c5a2011-08-09 21:44:24 -07003714}