blob: 379658f6302f944ea70f16254f4493adb2585a56 [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 Sharkey4c099d02015-05-15 13:45:00 -070028import static com.android.internal.util.XmlUtils.readBooleanAttribute;
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -070029import static com.android.internal.util.XmlUtils.readIntAttribute;
Jeff Sharkeye8a4b662015-06-27 15:43:45 -070030import static com.android.internal.util.XmlUtils.readLongAttribute;
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -070031import static com.android.internal.util.XmlUtils.readStringAttribute;
Jeff Sharkey4c099d02015-05-15 13:45:00 -070032import static com.android.internal.util.XmlUtils.writeBooleanAttribute;
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -070033import static com.android.internal.util.XmlUtils.writeIntAttribute;
Jeff Sharkeye8a4b662015-06-27 15:43:45 -070034import static com.android.internal.util.XmlUtils.writeLongAttribute;
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -070035import static com.android.internal.util.XmlUtils.writeStringAttribute;
Jeff Sharkey5217cac2015-12-20 15:34:01 -070036
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -070037import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT;
38import static org.xmlpull.v1.XmlPullParser.START_TAG;
39
Jason parks8888c592011-01-20 22:46:41 -060040import android.Manifest;
Jeff Sharkeyef10ee02015-07-05 14:17:27 -070041import android.annotation.Nullable;
Xiaohui Chen621b3fc2015-10-02 14:41:42 -070042import android.app.ActivityManager;
Jeff Sharkey9765e442017-12-14 22:15:14 -070043import android.app.ActivityManagerInternal;
44import android.app.ActivityManagerInternal.ScreenObserver;
Jeff Sharkey2d8b4e82013-09-17 17:30:33 -070045import android.app.AppOpsManager;
Jeff Sharkey14cbe522015-07-08 14:06:37 -070046import android.app.IActivityManager;
Jeff Sharkey9765e442017-12-14 22:15:14 -070047import android.app.KeyguardManager;
Pavel Grafovce72ef02018-01-10 17:14:11 +000048import android.app.admin.SecurityLog;
Jeff Sharkey9bed0702017-01-23 20:37:05 -070049import android.app.usage.StorageStatsManager;
Jeff Sharkeybcd262d2015-06-10 09:41:17 -070050import android.content.BroadcastReceiver;
Kenny Roota02b8b02010-08-05 16:14:17 -070051import android.content.ComponentName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080052import android.content.Context;
53import android.content.Intent;
Jeff Sharkeybcd262d2015-06-10 09:41:17 -070054import android.content.IntentFilter;
Kenny Roota02b8b02010-08-05 16:14:17 -070055import android.content.ServiceConnection;
Jeff Sharkey275e3e42015-04-24 16:10:32 -070056import android.content.pm.IPackageMoveObserver;
57import android.content.pm.PackageManager;
Jeff Sharkey14cbe522015-07-08 14:06:37 -070058import android.content.pm.ProviderInfo;
Jeff Sharkeybcd262d2015-06-10 09:41:17 -070059import android.content.pm.UserInfo;
Elliott Hughesf839b4f2014-09-26 12:30:47 -070060import android.content.res.Configuration;
Kenny Root02c87302010-07-01 08:10:18 -070061import android.content.res.ObbInfo;
Daniel Colascione766b6322018-01-08 19:10:36 -080062import android.database.ContentObserver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080063import android.net.Uri;
Kenny Root02c87302010-07-01 08:10:18 -070064import android.os.Binder;
Jeff Sharkey4c099d02015-05-15 13:45:00 -070065import android.os.DropBoxManager;
Kenny Roota02b8b02010-08-05 16:14:17 -070066import android.os.Environment;
Jeff Sharkeyb049e212012-09-07 23:16:01 -070067import android.os.Environment.UserEnvironment;
Jeff Sharkey48877892015-03-18 11:27:19 -070068import android.os.FileUtils;
Suchi Amalapurapuc42e29e2010-02-22 16:03:53 -080069import android.os.Handler;
Dianne Hackbornefa92b22013-05-03 14:11:43 -070070import android.os.HandlerThread;
Kenny Roota02b8b02010-08-05 16:14:17 -070071import android.os.IBinder;
Jin Qian12690d52017-10-13 18:17:04 -070072import android.os.IStoraged;
Jeff Sharkey1019de92017-09-06 13:47:03 -060073import android.os.IVold;
Jeff Sharkey8058fe62017-09-13 11:50:33 -060074import android.os.IVoldListener;
Jeff Sharkeyb302c542017-09-15 12:57:59 -060075import android.os.IVoldTaskListener;
Daniel Sandler5f27ef42010-03-16 15:42:02 -040076import android.os.Looper;
Suchi Amalapurapuc42e29e2010-02-22 16:03:53 -080077import android.os.Message;
Daichi Hirono9e8d9e22015-11-13 14:37:00 +090078import android.os.ParcelFileDescriptor;
Jeff Sharkey500ce9e2017-02-12 02:39:24 -070079import android.os.ParcelableException;
Jeff Sharkeyb302c542017-09-15 12:57:59 -060080import android.os.PersistableBundle;
Jeff Sharkeyce14cd02015-12-07 15:35:42 -070081import android.os.PowerManager;
Jeff Sharkey9527b222015-06-24 15:24:48 -070082import android.os.Process;
Jeff Sharkey7151a9a2015-04-04 15:22:37 -070083import android.os.RemoteCallbackList;
San Mehat4270e1e2010-01-29 05:32:19 -080084import android.os.RemoteException;
Suchi Amalapurapufd3530f2010-01-18 00:15:59 -080085import android.os.ServiceManager;
Jeff Sharkeyedcdaf62015-07-09 09:45:36 -070086import android.os.SystemClock;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080087import android.os.SystemProperties;
Dianne Hackbornf02b60a2012-08-16 10:48:27 -070088import android.os.UserHandle;
Emily Bernier92aa5a22014-07-07 10:11:48 -040089import android.os.UserManager;
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -070090import android.os.storage.DiskInfo;
Kenny Roota02b8b02010-08-05 16:14:17 -070091import android.os.storage.IObbActionListener;
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -070092import android.os.storage.IStorageEventListener;
Sudheer Shanka2250d562016-11-07 15:41:02 -080093import android.os.storage.IStorageManager;
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -070094import android.os.storage.IStorageShutdownObserver;
Kenny Rootaf9d6672010-10-08 09:21:39 -070095import android.os.storage.OnObbStateChangeListener;
Paul Lawrence46791e72014-04-03 09:10:26 -070096import android.os.storage.StorageManager;
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -070097import android.os.storage.StorageManagerInternal;
Mike Lockwood2f6a3882011-05-09 19:08:06 -070098import android.os.storage.StorageVolume;
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -070099import android.os.storage.VolumeInfo;
Jeff Sharkeyb36586a2015-04-27 08:42:28 -0700100import android.os.storage.VolumeRecord;
Jeff Sharkey14cbe522015-07-08 14:06:37 -0700101import android.provider.MediaStore;
Jeff Sharkeye8a4b662015-06-27 15:43:45 -0700102import android.provider.Settings;
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 Sharkey4c099d02015-05-15 13:45:00 -0700252 private static final String ATTR_FORCE_ADOPTABLE = "forceAdoptable";
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700253 private static final String TAG_VOLUME = "volume";
254 private static final String ATTR_TYPE = "type";
255 private static final String ATTR_FS_UUID = "fsUuid";
Jeff Sharkey5cc0df22015-06-17 19:44:05 -0700256 private static final String ATTR_PART_GUID = "partGuid";
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700257 private static final String ATTR_NICKNAME = "nickname";
258 private static final String ATTR_USER_FLAGS = "userFlags";
Jeff Sharkeye8a4b662015-06-27 15:43:45 -0700259 private static final String ATTR_CREATED_MILLIS = "createdMillis";
260 private static final String ATTR_LAST_TRIM_MILLIS = "lastTrimMillis";
261 private static final String ATTR_LAST_BENCH_MILLIS = "lastBenchMillis";
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700262
Jeff Sharkeyb36586a2015-04-27 08:42:28 -0700263 private final AtomicFile mSettingsFile;
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700264
Jeff Sharkey48877892015-03-18 11:27:19 -0700265 /**
266 * <em>Never</em> hold the lock while performing downcalls into vold, since
267 * unsolicited events can suddenly appear to update data structures.
268 */
Jeff Sharkey5f3e9342017-03-13 14:53:11 -0600269 private final Object mLock = LockGuard.installNewLock(LockGuard.INDEX_STORAGE);
Jeff Sharkey48877892015-03-18 11:27:19 -0700270
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700271 /** Set of users that we know are unlocked. */
Jeff Sharkey48877892015-03-18 11:27:19 -0700272 @GuardedBy("mLock")
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700273 private int[] mLocalUnlockedUsers = EmptyArray.INT;
274 /** Set of users that system knows are unlocked. */
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -0800275 @GuardedBy("mLock")
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700276 private int[] mSystemUnlockedUsers = EmptyArray.INT;
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700277
278 /** Map from disk ID to disk */
Jeff Sharkey48877892015-03-18 11:27:19 -0700279 @GuardedBy("mLock")
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -0700280 private ArrayMap<String, DiskInfo> mDisks = new ArrayMap<>();
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700281 /** Map from volume ID to disk */
Jeff Sharkey48877892015-03-18 11:27:19 -0700282 @GuardedBy("mLock")
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700283 private final ArrayMap<String, VolumeInfo> mVolumes = new ArrayMap<>();
Jeff Sharkey48877892015-03-18 11:27:19 -0700284
Jeff Sharkeyb36586a2015-04-27 08:42:28 -0700285 /** Map from UUID to record */
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700286 @GuardedBy("mLock")
Jeff Sharkeyb36586a2015-04-27 08:42:28 -0700287 private ArrayMap<String, VolumeRecord> mRecords = new ArrayMap<>();
Jeff Sharkey620b32b2015-04-23 19:36:02 -0700288 @GuardedBy("mLock")
289 private String mPrimaryStorageUuid;
Jeff Sharkey4c099d02015-05-15 13:45:00 -0700290 @GuardedBy("mLock")
291 private boolean mForceAdoptable;
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700292
Jeff Sharkeyeba260d2015-04-19 14:35:16 -0700293 /** Map from disk ID to latches */
294 @GuardedBy("mLock")
295 private ArrayMap<String, CountDownLatch> mDiskScanLatches = new ArrayMap<>();
296
Jeff Sharkey275e3e42015-04-24 16:10:32 -0700297 @GuardedBy("mLock")
298 private IPackageMoveObserver mMoveCallback;
299 @GuardedBy("mLock")
300 private String mMoveTargetUuid;
301
Jeff Sharkeyab15c392016-05-05 11:45:01 -0600302 private volatile int mCurrentUserId = UserHandle.USER_SYSTEM;
303
Daichi Hirono9fb00182016-11-08 14:12:17 +0900304 /** Holding lock for AppFuse business */
305 private final Object mAppFuseLock = new Object();
306
307 @GuardedBy("mAppFuseLock")
308 private int mNextAppFuseName = 0;
309
310 @GuardedBy("mAppFuseLock")
Daichi Hironoe56740d2017-02-02 13:56:45 +0900311 private AppFuseBridge mAppFuseBridge = null;
Daichi Hirono9fb00182016-11-08 14:12:17 +0900312
Jeff Sharkeyef10ee02015-07-05 14:17:27 -0700313 private VolumeInfo findVolumeByIdOrThrow(String id) {
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700314 synchronized (mLock) {
315 final VolumeInfo vol = mVolumes.get(id);
316 if (vol != null) {
317 return vol;
318 }
319 }
320 throw new IllegalArgumentException("No volume found for ID " + id);
321 }
322
Jeff Sharkeyef10ee02015-07-05 14:17:27 -0700323 private String findVolumeIdForPathOrThrow(String path) {
Jeff Sharkey48877892015-03-18 11:27:19 -0700324 synchronized (mLock) {
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -0700325 for (int i = 0; i < mVolumes.size(); i++) {
326 final VolumeInfo vol = mVolumes.valueAt(i);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700327 if (vol.path != null && path.startsWith(vol.path)) {
328 return vol.id;
Jeff Sharkey48877892015-03-18 11:27:19 -0700329 }
330 }
331 }
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700332 throw new IllegalArgumentException("No volume found for path " + path);
Jeff Sharkey48877892015-03-18 11:27:19 -0700333 }
334
Jeff Sharkeye8a4b662015-06-27 15:43:45 -0700335 private VolumeRecord findRecordForPath(String path) {
336 synchronized (mLock) {
337 for (int i = 0; i < mVolumes.size(); i++) {
338 final VolumeInfo vol = mVolumes.valueAt(i);
339 if (vol.path != null && path.startsWith(vol.path)) {
340 return mRecords.get(vol.fsUuid);
341 }
342 }
343 }
344 return null;
345 }
346
347 private String scrubPath(String path) {
348 if (path.startsWith(Environment.getDataDirectory().getAbsolutePath())) {
349 return "internal";
350 }
351 final VolumeRecord rec = findRecordForPath(path);
352 if (rec == null || rec.createdMillis == 0) {
353 return "unknown";
354 } else {
355 return "ext:" + (int) ((System.currentTimeMillis() - rec.createdMillis)
356 / DateUtils.WEEK_IN_MILLIS) + "w";
357 }
358 }
359
Jeff Sharkeyef10ee02015-07-05 14:17:27 -0700360 private @Nullable VolumeInfo findStorageForUuid(String volumeUuid) {
Jeff Sharkey275e3e42015-04-24 16:10:32 -0700361 final StorageManager storage = mContext.getSystemService(StorageManager.class);
362 if (Objects.equals(StorageManager.UUID_PRIVATE_INTERNAL, volumeUuid)) {
Jeff Sharkeyef10ee02015-07-05 14:17:27 -0700363 return storage.findVolumeById(VolumeInfo.ID_EMULATED_INTERNAL);
Jeff Sharkey275e3e42015-04-24 16:10:32 -0700364 } else if (Objects.equals(StorageManager.UUID_PRIMARY_PHYSICAL, volumeUuid)) {
365 return storage.getPrimaryPhysicalVolume();
366 } else {
367 return storage.findEmulatedForPrivate(storage.findVolumeByUuid(volumeUuid));
368 }
369 }
370
Jeff Sharkeye8a4b662015-06-27 15:43:45 -0700371 private boolean shouldBenchmark() {
372 final long benchInterval = Settings.Global.getLong(mContext.getContentResolver(),
373 Settings.Global.STORAGE_BENCHMARK_INTERVAL, DateUtils.WEEK_IN_MILLIS);
Jeff Sharkeye83d8a92015-09-09 14:53:38 -0700374 if (benchInterval == -1) {
375 return false;
376 } else if (benchInterval == 0) {
377 return true;
378 }
379
Jeff Sharkeye8a4b662015-06-27 15:43:45 -0700380 synchronized (mLock) {
381 for (int i = 0; i < mVolumes.size(); i++) {
382 final VolumeInfo vol = mVolumes.valueAt(i);
383 final VolumeRecord rec = mRecords.get(vol.fsUuid);
Jeff Sharkeye83d8a92015-09-09 14:53:38 -0700384 if (vol.isMountedWritable() && rec != null) {
Jeff Sharkeye8a4b662015-06-27 15:43:45 -0700385 final long benchAge = System.currentTimeMillis() - rec.lastBenchMillis;
386 if (benchAge >= benchInterval) {
387 return true;
388 }
389 }
390 }
391 return false;
392 }
393 }
394
Jeff Sharkeyeba260d2015-04-19 14:35:16 -0700395 private CountDownLatch findOrCreateDiskScanLatch(String diskId) {
396 synchronized (mLock) {
397 CountDownLatch latch = mDiskScanLatches.get(diskId);
398 if (latch == null) {
399 latch = new CountDownLatch(1);
400 mDiskScanLatches.put(diskId, latch);
401 }
402 return latch;
403 }
404 }
405
Paul Lawrence8e397362014-01-27 15:22:30 -0800406 /** List of crypto types.
407 * These must match CRYPT_TYPE_XXX in cryptfs.h AND their
408 * corresponding commands in CommandListener.cpp */
409 public static final String[] CRYPTO_TYPES
410 = { "password", "default", "pattern", "pin" };
411
Brian Carlstrom7395a8a2014-04-28 22:11:01 -0700412 private final Context mContext;
Jeff Sharkeycd575992016-03-29 14:12:49 -0600413
Jeff Sharkey1019de92017-09-06 13:47:03 -0600414 private volatile IVold mVold;
Jin Qian12690d52017-10-13 18:17:04 -0700415 private volatile IStoraged mStoraged;
Jeff Sharkey1019de92017-09-06 13:47:03 -0600416
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700417 private volatile boolean mSystemReady = false;
Yasuhiro Matsuda87a38b52015-07-24 22:10:16 +0900418 private volatile boolean mBootCompleted = false;
Jeff Sharkey48877892015-03-18 11:27:19 -0700419 private volatile boolean mDaemonConnected = false;
Jeff Sharkey9765e442017-12-14 22:15:14 -0700420 private volatile boolean mSecureKeyguardShowing = true;
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700421
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700422 private PackageManagerService mPms;
423
424 private final Callbacks mCallbacks;
Jeff Sharkeyb9fe5372015-12-03 15:23:08 -0700425 private final LockPatternUtils mLockPatternUtils;
Jeff Sharkey48877892015-03-18 11:27:19 -0700426
San Mehat6cdd9c02010-02-09 14:45:20 -0800427 /**
Kenny Root3b1abba2010-10-13 15:00:07 -0700428 * The size of the crypto algorithm key in bits for OBB files. Currently
429 * Twofish is used which takes 128-bit keys.
430 */
431 private static final int CRYPTO_ALGORITHM_KEY_SIZE = 128;
432
433 /**
434 * The number of times to run SHA1 in the PBKDF2 function for OBB files.
435 * 1024 is reasonably secure and not too slow.
436 */
437 private static final int PBKDF2_HASH_ROUNDS = 1024;
438
439 /**
Kenny Roota02b8b02010-08-05 16:14:17 -0700440 * Mounted OBB tracking information. Used to track the current state of all
441 * OBBs.
Kenny Root02c87302010-07-01 08:10:18 -0700442 */
Kenny Root735de3b2010-09-30 14:11:39 -0700443 final private Map<IBinder, List<ObbState>> mObbMounts = new HashMap<IBinder, List<ObbState>>();
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700444
445 /** Map from raw paths to {@link ObbState}. */
Kenny Roota02b8b02010-08-05 16:14:17 -0700446 final private Map<String, ObbState> mObbPathToStateMap = new HashMap<String, ObbState>();
447
Svet Ganov6ee871e2015-07-10 14:29:33 -0700448 // Not guarded by a lock.
Sudheer Shanka2250d562016-11-07 15:41:02 -0800449 private final StorageManagerInternalImpl mStorageManagerInternal
450 = new StorageManagerInternalImpl();
Svet Ganov6ee871e2015-07-10 14:29:33 -0700451
Kenny Roota02b8b02010-08-05 16:14:17 -0700452 class ObbState implements IBinder.DeathRecipient {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700453 public ObbState(String rawPath, String canonicalPath, int callingUid,
Jeff Sharkey41cd6812017-09-11 10:32:17 -0600454 IObbActionListener token, int nonce, String volId) {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700455 this.rawPath = rawPath;
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700456 this.canonicalPath = canonicalPath;
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700457 this.ownerGid = UserHandle.getSharedAppGid(callingUid);
Kenny Rootaf9d6672010-10-08 09:21:39 -0700458 this.token = token;
459 this.nonce = nonce;
Jeff Sharkey41cd6812017-09-11 10:32:17 -0600460 this.volId = volId;
Kenny Roota02b8b02010-08-05 16:14:17 -0700461 }
462
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700463 final String rawPath;
464 final String canonicalPath;
Kenny Roota02b8b02010-08-05 16:14:17 -0700465
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700466 final int ownerGid;
Kenny Roota02b8b02010-08-05 16:14:17 -0700467
Kenny Rootaf9d6672010-10-08 09:21:39 -0700468 // Token of remote Binder caller
469 final IObbActionListener token;
470
471 // Identifier to pass back to the token
472 final int nonce;
Kenny Roota02b8b02010-08-05 16:14:17 -0700473
Jeff Sharkey41cd6812017-09-11 10:32:17 -0600474 String volId;
475
Kenny Root735de3b2010-09-30 14:11:39 -0700476 public IBinder getBinder() {
477 return token.asBinder();
478 }
479
Kenny Roota02b8b02010-08-05 16:14:17 -0700480 @Override
481 public void binderDied() {
482 ObbAction action = new UnmountObbAction(this, true);
483 mObbActionHandler.sendMessage(mObbActionHandler.obtainMessage(OBB_RUN_ACTION, action));
Kenny Root735de3b2010-09-30 14:11:39 -0700484 }
Kenny Roota02b8b02010-08-05 16:14:17 -0700485
Kenny Root5919ac62010-10-05 09:49:40 -0700486 public void link() throws RemoteException {
487 getBinder().linkToDeath(this, 0);
488 }
489
490 public void unlink() {
Kenny Root735de3b2010-09-30 14:11:39 -0700491 getBinder().unlinkToDeath(this, 0);
Kenny Roota02b8b02010-08-05 16:14:17 -0700492 }
Kenny Root38cf8862010-09-26 14:18:51 -0700493
494 @Override
495 public String toString() {
496 StringBuilder sb = new StringBuilder("ObbState{");
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700497 sb.append("rawPath=").append(rawPath);
498 sb.append(",canonicalPath=").append(canonicalPath);
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700499 sb.append(",ownerGid=").append(ownerGid);
500 sb.append(",token=").append(token);
501 sb.append(",binder=").append(getBinder());
Jeff Sharkey41cd6812017-09-11 10:32:17 -0600502 sb.append(",volId=").append(volId);
Kenny Root38cf8862010-09-26 14:18:51 -0700503 sb.append('}');
504 return sb.toString();
505 }
Kenny Roota02b8b02010-08-05 16:14:17 -0700506 }
507
508 // OBB Action Handler
509 final private ObbActionHandler mObbActionHandler;
510
511 // OBB action handler messages
512 private static final int OBB_RUN_ACTION = 1;
513 private static final int OBB_MCS_BOUND = 2;
514 private static final int OBB_MCS_UNBIND = 3;
515 private static final int OBB_MCS_RECONNECT = 4;
Kenny Rootaf9d6672010-10-08 09:21:39 -0700516 private static final int OBB_FLUSH_MOUNT_STATE = 5;
Kenny Roota02b8b02010-08-05 16:14:17 -0700517
518 /*
519 * Default Container Service information
520 */
521 static final ComponentName DEFAULT_CONTAINER_COMPONENT = new ComponentName(
522 "com.android.defcontainer", "com.android.defcontainer.DefaultContainerService");
523
524 final private DefaultContainerConnection mDefContainerConn = new DefaultContainerConnection();
525
526 class DefaultContainerConnection implements ServiceConnection {
Jeff Sharkey48877892015-03-18 11:27:19 -0700527 @Override
Kenny Roota02b8b02010-08-05 16:14:17 -0700528 public void onServiceConnected(ComponentName name, IBinder service) {
529 if (DEBUG_OBB)
530 Slog.i(TAG, "onServiceConnected");
531 IMediaContainerService imcs = IMediaContainerService.Stub.asInterface(service);
532 mObbActionHandler.sendMessage(mObbActionHandler.obtainMessage(OBB_MCS_BOUND, imcs));
533 }
534
Jeff Sharkey48877892015-03-18 11:27:19 -0700535 @Override
Kenny Roota02b8b02010-08-05 16:14:17 -0700536 public void onServiceDisconnected(ComponentName name) {
537 if (DEBUG_OBB)
538 Slog.i(TAG, "onServiceDisconnected");
539 }
Jeff Sharkey54402792017-09-15 16:05:19 -0600540 }
Kenny Roota02b8b02010-08-05 16:14:17 -0700541
542 // Used in the ObbActionHandler
543 private IMediaContainerService mContainerService = null;
Kenny Root02c87302010-07-01 08:10:18 -0700544
Christopher Tate7265abe2014-11-21 13:54:45 -0800545 // Last fstrim operation tracking
546 private static final String LAST_FSTRIM_FILE = "last-fstrim";
547 private final File mLastMaintenanceFile;
548 private long mLastMaintenance;
549
Kenny Root02c87302010-07-01 08:10:18 -0700550 // Handler messages
Jeff Sharkey48877892015-03-18 11:27:19 -0700551 private static final int H_SYSTEM_READY = 1;
552 private static final int H_DAEMON_CONNECTED = 2;
553 private static final int H_SHUTDOWN = 3;
554 private static final int H_FSTRIM = 4;
555 private static final int H_VOLUME_MOUNT = 5;
556 private static final int H_VOLUME_BROADCAST = 6;
Jeff Sharkeyabc3e852015-08-03 14:41:13 -0700557 private static final int H_INTERNAL_BROADCAST = 7;
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700558 private static final int H_VOLUME_UNMOUNT = 8;
Jeff Sharkey5a9bb742015-11-03 10:15:57 -0800559 private static final int H_PARTITION_FORGET = 9;
560 private static final int H_RESET = 10;
Jin Qiana85b9912017-10-17 15:48:18 -0700561 private static final int H_RUN_IDLE_MAINT = 11;
562 private static final int H_ABORT_IDLE_MAINT = 12;
Suchi Amalapurapu6ffce2e2010-03-08 14:48:40 -0800563
Sudheer Shanka2250d562016-11-07 15:41:02 -0800564 class StorageManagerServiceHandler extends Handler {
565 public StorageManagerServiceHandler(Looper looper) {
Jeff Sharkey48877892015-03-18 11:27:19 -0700566 super(looper);
Daniel Sandler5f27ef42010-03-16 15:42:02 -0400567 }
568
Jason parks5af0b912010-11-29 09:05:25 -0600569 @Override
Suchi Amalapurapuc42e29e2010-02-22 16:03:53 -0800570 public void handleMessage(Message msg) {
571 switch (msg.what) {
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700572 case H_SYSTEM_READY: {
Jeff Sharkey48877892015-03-18 11:27:19 -0700573 handleSystemReady();
574 break;
575 }
576 case H_DAEMON_CONNECTED: {
577 handleDaemonConnected();
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700578 break;
579 }
Christopher Tated417d622013-08-19 16:14:25 -0700580 case H_FSTRIM: {
Christopher Tated417d622013-08-19 16:14:25 -0700581 Slog.i(TAG, "Running fstrim idle maintenance");
Christopher Tate7265abe2014-11-21 13:54:45 -0800582
583 // Remember when we kicked it off
584 try {
585 mLastMaintenance = System.currentTimeMillis();
586 mLastMaintenanceFile.setLastModified(mLastMaintenance);
587 } catch (Exception e) {
588 Slog.e(TAG, "Unable to record last fstrim!");
589 }
590
Jeff Sharkeyb302c542017-09-15 12:57:59 -0600591 // TODO: Reintroduce shouldBenchmark() test
Jeff Sharkey7e19f532017-11-06 13:54:11 -0700592 fstrim(0, null);
Christopher Tate7265abe2014-11-21 13:54:45 -0800593
Christopher Tated417d622013-08-19 16:14:25 -0700594 // invoke the completion callback, if any
Jeff Sharkeye8a4b662015-06-27 15:43:45 -0700595 // TODO: fstrim is non-blocking, so remove this useless callback
Christopher Tated417d622013-08-19 16:14:25 -0700596 Runnable callback = (Runnable) msg.obj;
597 if (callback != null) {
598 callback.run();
599 }
600 break;
601 }
Jeff Sharkey48877892015-03-18 11:27:19 -0700602 case H_SHUTDOWN: {
Sudheer Shanka2250d562016-11-07 15:41:02 -0800603 final IStorageShutdownObserver obs = (IStorageShutdownObserver) msg.obj;
Jeff Sharkey48877892015-03-18 11:27:19 -0700604 boolean success = false;
605 try {
Jeff Sharkey54402792017-09-15 16:05:19 -0600606 mVold.shutdown();
607 success = true;
Jeff Sharkeyace874b2017-09-07 15:27:33 -0600608 } catch (Exception e) {
609 Slog.wtf(TAG, e);
Jeff Sharkey48877892015-03-18 11:27:19 -0700610 }
611 if (obs != null) {
612 try {
613 obs.onShutDownComplete(success ? 0 : -1);
Jeff Sharkeyace874b2017-09-07 15:27:33 -0600614 } catch (Exception ignored) {
Jeff Sharkey48877892015-03-18 11:27:19 -0700615 }
616 }
617 break;
618 }
619 case H_VOLUME_MOUNT: {
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -0700620 final VolumeInfo vol = (VolumeInfo) msg.obj;
Jeff Sharkey2e606d72015-07-27 14:19:54 -0700621 if (isMountDisallowed(vol)) {
622 Slog.i(TAG, "Ignoring mount " + vol.getId() + " due to policy");
623 break;
624 }
Jeff Sharkey48877892015-03-18 11:27:19 -0700625 try {
Jeff Sharkey54402792017-09-15 16:05:19 -0600626 mVold.mount(vol.id, vol.mountFlags, vol.mountUserId);
Jeff Sharkeyace874b2017-09-07 15:27:33 -0600627 } catch (Exception e) {
628 Slog.wtf(TAG, e);
Jeff Sharkey48877892015-03-18 11:27:19 -0700629 }
630 break;
631 }
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700632 case H_VOLUME_UNMOUNT: {
633 final VolumeInfo vol = (VolumeInfo) msg.obj;
634 unmount(vol.getId());
635 break;
636 }
Jeff Sharkey48877892015-03-18 11:27:19 -0700637 case H_VOLUME_BROADCAST: {
638 final StorageVolume userVol = (StorageVolume) msg.obj;
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700639 final String envState = userVol.getState();
640 Slog.d(TAG, "Volume " + userVol.getId() + " broadcasting " + envState + " to "
Jeff Sharkey48877892015-03-18 11:27:19 -0700641 + userVol.getOwner());
642
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700643 final String action = VolumeInfo.getBroadcastForEnvironment(envState);
Jeff Sharkey48877892015-03-18 11:27:19 -0700644 if (action != null) {
645 final Intent intent = new Intent(action,
646 Uri.fromFile(userVol.getPathFile()));
647 intent.putExtra(StorageVolume.EXTRA_STORAGE_VOLUME, userVol);
Jeff Sharkey082f83b2017-03-26 14:34:47 -0600648 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT
649 | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
Jeff Sharkey48877892015-03-18 11:27:19 -0700650 mContext.sendBroadcastAsUser(intent, userVol.getOwner());
651 }
652 break;
653 }
Jeff Sharkeyabc3e852015-08-03 14:41:13 -0700654 case H_INTERNAL_BROADCAST: {
655 // Internal broadcasts aimed at system components, not for
656 // third-party apps.
657 final Intent intent = (Intent) msg.obj;
658 mContext.sendBroadcastAsUser(intent, UserHandle.ALL,
659 android.Manifest.permission.WRITE_MEDIA_STORAGE);
Jeff Sharkey5a9bb742015-11-03 10:15:57 -0800660 break;
661 }
662 case H_PARTITION_FORGET: {
Jeff Sharkeydb4b6192017-10-24 11:08:50 -0600663 final VolumeRecord rec = (VolumeRecord) msg.obj;
664 forgetPartition(rec.partGuid, rec.fsUuid);
Jeff Sharkey5a9bb742015-11-03 10:15:57 -0800665 break;
666 }
667 case H_RESET: {
668 resetIfReadyAndConnected();
669 break;
Jeff Sharkeyabc3e852015-08-03 14:41:13 -0700670 }
Jin Qiana85b9912017-10-17 15:48:18 -0700671 case H_RUN_IDLE_MAINT: {
672 Slog.i(TAG, "Running idle maintenance");
673 runIdleMaint((Runnable)msg.obj);
674 break;
675 }
676 case H_ABORT_IDLE_MAINT: {
677 Slog.i(TAG, "Aborting idle maintenance");
678 abortIdleMaint((Runnable)msg.obj);
679 break;
680 }
681
Suchi Amalapurapuc42e29e2010-02-22 16:03:53 -0800682 }
683 }
Jeff Sharkey48877892015-03-18 11:27:19 -0700684 }
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700685
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700686 private final Handler mHandler;
Suchi Amalapurapuc42e29e2010-02-22 16:03:53 -0800687
Jeff Sharkeybcd262d2015-06-10 09:41:17 -0700688 private BroadcastReceiver mUserReceiver = new BroadcastReceiver() {
689 @Override
690 public void onReceive(Context context, Intent intent) {
691 final String action = intent.getAction();
692 final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700693 Preconditions.checkArgument(userId >= 0);
Jeff Sharkeybcd262d2015-06-10 09:41:17 -0700694
695 try {
696 if (Intent.ACTION_USER_ADDED.equals(action)) {
697 final UserManager um = mContext.getSystemService(UserManager.class);
698 final int userSerialNumber = um.getUserSerialNumber(userId);
Jeff Sharkey54402792017-09-15 16:05:19 -0600699 mVold.onUserAdded(userId, userSerialNumber);
Jeff Sharkeybcd262d2015-06-10 09:41:17 -0700700 } else if (Intent.ACTION_USER_REMOVED.equals(action)) {
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700701 synchronized (mVolumes) {
702 final int size = mVolumes.size();
703 for (int i = 0; i < size; i++) {
704 final VolumeInfo vol = mVolumes.valueAt(i);
705 if (vol.mountUserId == userId) {
706 vol.mountUserId = UserHandle.USER_NULL;
707 mHandler.obtainMessage(H_VOLUME_UNMOUNT, vol).sendToTarget();
708 }
709 }
710 }
Jeff Sharkey54402792017-09-15 16:05:19 -0600711 mVold.onUserRemoved(userId);
Jeff Sharkeybcd262d2015-06-10 09:41:17 -0700712 }
Jeff Sharkeyace874b2017-09-07 15:27:33 -0600713 } catch (Exception e) {
714 Slog.wtf(TAG, e);
Jeff Sharkeybcd262d2015-06-10 09:41:17 -0700715 }
716 }
717 };
718
Jeff Sharkeyedcdaf62015-07-09 09:45:36 -0700719 private void waitForLatch(CountDownLatch latch, String condition, long timeoutMillis)
720 throws TimeoutException {
721 final long startMillis = SystemClock.elapsedRealtime();
Jeff Sharkeyeba260d2015-04-19 14:35:16 -0700722 while (true) {
Kenny Root51a573c2012-05-17 13:30:28 -0700723 try {
724 if (latch.await(5000, TimeUnit.MILLISECONDS)) {
San Mehat207e5382010-02-04 20:46:54 -0800725 return;
Kenny Root51a573c2012-05-17 13:30:28 -0700726 } else {
727 Slog.w(TAG, "Thread " + Thread.currentThread().getName()
Jeff Sharkey48877892015-03-18 11:27:19 -0700728 + " still waiting for " + condition + "...");
San Mehat207e5382010-02-04 20:46:54 -0800729 }
Kenny Root51a573c2012-05-17 13:30:28 -0700730 } catch (InterruptedException e) {
Jeff Sharkeyeba260d2015-04-19 14:35:16 -0700731 Slog.w(TAG, "Interrupt while waiting for " + condition);
San Mehat207e5382010-02-04 20:46:54 -0800732 }
Jeff Sharkeyedcdaf62015-07-09 09:45:36 -0700733 if (timeoutMillis > 0 && SystemClock.elapsedRealtime() > startMillis + timeoutMillis) {
734 throw new TimeoutException("Thread " + Thread.currentThread().getName()
735 + " gave up waiting for " + condition + " after " + timeoutMillis + "ms");
736 }
San Mehat207e5382010-02-04 20:46:54 -0800737 }
San Mehat1f6301e2010-01-07 22:40:27 -0800738 }
Kenny Root02c87302010-07-01 08:10:18 -0700739
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700740 private void handleSystemReady() {
Jeff Sharkey8924e872015-11-30 12:52:10 -0700741 initIfReadyAndConnected();
Jeff Sharkey5a9bb742015-11-03 10:15:57 -0800742 resetIfReadyAndConnected();
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700743
Jeff Sharkey48877892015-03-18 11:27:19 -0700744 // Start scheduling nominally-daily fstrim operations
Christopher Tate115afda2014-06-06 19:06:26 -0700745 MountServiceIdler.scheduleIdlePass(mContext);
Daniel Colascione766b6322018-01-08 19:10:36 -0800746
747 // Toggle zram-enable system property in response to settings
748 mContext.getContentResolver().registerContentObserver(
749 Settings.Global.getUriFor(Settings.Global.ZRAM_ENABLED),
750 false /*notifyForDescendants*/,
751 new ContentObserver(null /* current thread */) {
752 @Override
753 public void onChange(boolean selfChange) {
754 refreshZramSettings();
755 }
756 });
757 refreshZramSettings();
758 }
759
760 /**
761 * Update the zram_enabled system property (which init reads to
762 * decide whether to enable zram) to reflect the zram_enabled
763 * preference (which we can change for experimentation purposes).
764 */
765 private void refreshZramSettings() {
766 String propertyValue = SystemProperties.get(ZRAM_ENABLED_PROPERTY);
767 if ("".equals(propertyValue)) {
768 return; // System doesn't have zram toggling support
769 }
770 String desiredPropertyValue =
771 Settings.Global.getInt(mContext.getContentResolver(),
772 Settings.Global.ZRAM_ENABLED,
773 1) != 0
774 ? "1" : "0";
775 if (!desiredPropertyValue.equals(propertyValue)) {
776 // Avoid redundant disk writes by setting only if we're
777 // changing the property value. There's no race: we're the
778 // sole writer.
779 SystemProperties.set(ZRAM_ENABLED_PROPERTY, desiredPropertyValue);
780 }
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700781 }
782
Jeff Sharkey14cbe522015-07-08 14:06:37 -0700783 /**
784 * MediaProvider has a ton of code that makes assumptions about storage
785 * paths never changing, so we outright kill them to pick up new state.
786 */
787 @Deprecated
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700788 private void killMediaProvider(List<UserInfo> users) {
789 if (users == null) return;
790
Jeff Sharkeyb3cf9532015-07-17 15:12:39 -0700791 final long token = Binder.clearCallingIdentity();
792 try {
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700793 for (UserInfo user : users) {
794 // System user does not have media provider, so skip.
795 if (user.isSystemOnly()) continue;
796
Jeff Sharkey2a9e3f82015-12-18 10:57:58 -0700797 final ProviderInfo provider = mPms.resolveContentProvider(MediaStore.AUTHORITY,
Jeff Sharkey8a372a02016-03-16 16:25:45 -0600798 PackageManager.MATCH_DIRECT_BOOT_AWARE
799 | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
800 user.id);
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700801 if (provider != null) {
Sudheer Shankadc589ac2016-11-10 15:30:17 -0800802 final IActivityManager am = ActivityManager.getService();
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700803 try {
Jeff Sharkey85f449e2016-06-23 09:26:00 -0600804 am.killApplication(provider.applicationInfo.packageName,
805 UserHandle.getAppId(provider.applicationInfo.uid),
806 UserHandle.USER_ALL, "vold reset");
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700807 // We only need to run this once. It will kill all users' media processes.
808 break;
809 } catch (RemoteException e) {
810 }
Jeff Sharkeyb3cf9532015-07-17 15:12:39 -0700811 }
Jeff Sharkey14cbe522015-07-08 14:06:37 -0700812 }
Jeff Sharkeyb3cf9532015-07-17 15:12:39 -0700813 } finally {
814 Binder.restoreCallingIdentity(token);
Jeff Sharkey14cbe522015-07-08 14:06:37 -0700815 }
816 }
817
Andreas Gampea36dc622018-02-05 17:19:22 -0800818 @GuardedBy("mLock")
Jeff Sharkey5a9bb742015-11-03 10:15:57 -0800819 private void addInternalVolumeLocked() {
Amith Yamasania7892482015-08-07 11:09:05 -0700820 // Create a stub volume that represents internal storage
821 final VolumeInfo internal = new VolumeInfo(VolumeInfo.ID_PRIVATE_INTERNAL,
822 VolumeInfo.TYPE_PRIVATE, null, null);
823 internal.state = VolumeInfo.STATE_MOUNTED;
824 internal.path = Environment.getDataDirectory().getAbsolutePath();
825 mVolumes.put(internal.id, internal);
826 }
827
Jeff Sharkey8924e872015-11-30 12:52:10 -0700828 private void initIfReadyAndConnected() {
829 Slog.d(TAG, "Thinking about init, mSystemReady=" + mSystemReady
830 + ", mDaemonConnected=" + mDaemonConnected);
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700831 if (mSystemReady && mDaemonConnected
Paul Lawrence20be5d62016-02-26 13:51:17 -0800832 && !StorageManager.isFileEncryptedNativeOnly()) {
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700833 // When booting a device without native support, make sure that our
834 // user directories are locked or unlocked based on the current
835 // emulation status.
Paul Lawrence20be5d62016-02-26 13:51:17 -0800836 final boolean initLocked = StorageManager.isFileEncryptedEmulatedOnly();
Paul Crowleyd94ab732016-02-15 06:44:51 +0000837 Slog.d(TAG, "Setting up emulation state, initlocked=" + initLocked);
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700838 final List<UserInfo> users = mContext.getSystemService(UserManager.class).getUsers();
Jeff Sharkey8924e872015-11-30 12:52:10 -0700839 for (UserInfo user : users) {
840 try {
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700841 if (initLocked) {
Jeff Sharkey54402792017-09-15 16:05:19 -0600842 mVold.lockUserKey(user.id);
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700843 } else {
Jeff Sharkey54402792017-09-15 16:05:19 -0600844 mVold.unlockUserKey(user.id, user.serialNumber, encodeBytes(null),
845 encodeBytes(null));
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700846 }
Jeff Sharkey43e12112017-09-12 16:31:45 -0600847 } catch (Exception e) {
848 Slog.wtf(TAG, e);
Jeff Sharkey8924e872015-11-30 12:52:10 -0700849 }
850 }
851 }
852 }
853
Jeff Sharkey5a9bb742015-11-03 10:15:57 -0800854 private void resetIfReadyAndConnected() {
Jeff Sharkey48877892015-03-18 11:27:19 -0700855 Slog.d(TAG, "Thinking about reset, mSystemReady=" + mSystemReady
856 + ", mDaemonConnected=" + mDaemonConnected);
857 if (mSystemReady && mDaemonConnected) {
Jeff Sharkey5a9bb742015-11-03 10:15:57 -0800858 final List<UserInfo> users = mContext.getSystemService(UserManager.class).getUsers();
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700859 killMediaProvider(users);
Jeff Sharkey14cbe522015-07-08 14:06:37 -0700860
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700861 final int[] systemUnlockedUsers;
Jeff Sharkey5a9bb742015-11-03 10:15:57 -0800862 synchronized (mLock) {
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700863 systemUnlockedUsers = mSystemUnlockedUsers;
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700864
Jeff Sharkey5a9bb742015-11-03 10:15:57 -0800865 mDisks.clear();
866 mVolumes.clear();
867
868 addInternalVolumeLocked();
869 }
Jeff Sharkey59d577a2015-04-11 21:27:21 -0700870
Jeff Sharkey48877892015-03-18 11:27:19 -0700871 try {
Jeff Sharkey54402792017-09-15 16:05:19 -0600872 mVold.reset();
Jeff Sharkeybcd262d2015-06-10 09:41:17 -0700873
874 // Tell vold about all existing and started users
Jeff Sharkeybcd262d2015-06-10 09:41:17 -0700875 for (UserInfo user : users) {
Jeff Sharkey54402792017-09-15 16:05:19 -0600876 mVold.onUserAdded(user.id, user.serialNumber);
Jeff Sharkeybcd262d2015-06-10 09:41:17 -0700877 }
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700878 for (int userId : systemUnlockedUsers) {
Jeff Sharkey54402792017-09-15 16:05:19 -0600879 mVold.onUserStarted(userId);
Jin Qian12690d52017-10-13 18:17:04 -0700880 mStoraged.onUserStarted(userId);
Jeff Sharkey50a05452015-04-29 11:24:52 -0700881 }
Jeff Sharkey9765e442017-12-14 22:15:14 -0700882 mVold.onSecureKeyguardStateChanged(mSecureKeyguardShowing);
Jeff Sharkeyace874b2017-09-07 15:27:33 -0600883 } catch (Exception e) {
884 Slog.wtf(TAG, e);
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700885 }
886 }
Jeff Sharkey48877892015-03-18 11:27:19 -0700887 }
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700888
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700889 private void onUnlockUser(int userId) {
890 Slog.d(TAG, "onUnlockUser " + userId);
Jeff Sharkey48877892015-03-18 11:27:19 -0700891
892 // We purposefully block here to make sure that user-specific
893 // staging area is ready so it's ready for zygote-forked apps to
894 // bind mount against.
895 try {
Jeff Sharkey54402792017-09-15 16:05:19 -0600896 mVold.onUserStarted(userId);
Jin Qian12690d52017-10-13 18:17:04 -0700897 mStoraged.onUserStarted(userId);
Jeff Sharkeyace874b2017-09-07 15:27:33 -0600898 } catch (Exception e) {
899 Slog.wtf(TAG, e);
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700900 }
Jeff Sharkey48877892015-03-18 11:27:19 -0700901
902 // Record user as started so newly mounted volumes kick off events
903 // correctly, then synthesize events for any already-mounted volumes.
yuanhuihuiefd1f122016-07-13 21:21:03 +0800904 synchronized (mLock) {
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -0700905 for (int i = 0; i < mVolumes.size(); i++) {
906 final VolumeInfo vol = mVolumes.valueAt(i);
Jeff Sharkey46349872015-07-28 10:49:47 -0700907 if (vol.isVisibleForRead(userId) && vol.isMountedReadable()) {
Svet Ganov6ee871e2015-07-10 14:29:33 -0700908 final StorageVolume userVol = vol.buildStorageVolume(mContext, userId, false);
Jeff Sharkey48877892015-03-18 11:27:19 -0700909 mHandler.obtainMessage(H_VOLUME_BROADCAST, userVol).sendToTarget();
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700910
Jeff Sharkey27de30d2015-04-18 16:20:27 -0700911 final String envState = VolumeInfo.getEnvironmentForState(vol.getState());
912 mCallbacks.notifyStorageStateChanged(userVol.getPath(), envState, envState);
Jeff Sharkey48877892015-03-18 11:27:19 -0700913 }
914 }
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700915 mSystemUnlockedUsers = ArrayUtils.appendInt(mSystemUnlockedUsers, userId);
Jeff Sharkey48877892015-03-18 11:27:19 -0700916 }
917 }
918
919 private void onCleanupUser(int userId) {
920 Slog.d(TAG, "onCleanupUser " + userId);
921
922 try {
Jeff Sharkey54402792017-09-15 16:05:19 -0600923 mVold.onUserStopped(userId);
Jin Qian12690d52017-10-13 18:17:04 -0700924 mStoraged.onUserStopped(userId);
Jeff Sharkeyace874b2017-09-07 15:27:33 -0600925 } catch (Exception e) {
926 Slog.wtf(TAG, e);
Jeff Sharkey48877892015-03-18 11:27:19 -0700927 }
928
yuanhuihuiefd1f122016-07-13 21:21:03 +0800929 synchronized (mLock) {
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700930 mSystemUnlockedUsers = ArrayUtils.removeInt(mSystemUnlockedUsers, userId);
Jeff Sharkey48877892015-03-18 11:27:19 -0700931 }
932 }
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700933
Jeff Sharkey9765e442017-12-14 22:15:14 -0700934 @Override
935 public void onAwakeStateChanged(boolean isAwake) {
936 // Ignored
937 }
938
939 @Override
940 public void onKeyguardStateChanged(boolean isShowing) {
941 // Push down current secure keyguard status so that we ignore malicious
942 // USB devices while locked.
943 mSecureKeyguardShowing = isShowing
944 && mContext.getSystemService(KeyguardManager.class).isDeviceSecure();
945 try {
946 mVold.onSecureKeyguardStateChanged(mSecureKeyguardShowing);
947 } catch (Exception e) {
948 Slog.wtf(TAG, e);
949 }
950 }
951
Christopher Tated417d622013-08-19 16:14:25 -0700952 void runIdleMaintenance(Runnable callback) {
953 mHandler.sendMessage(mHandler.obtainMessage(H_FSTRIM, callback));
954 }
955
Christopher Tate7265abe2014-11-21 13:54:45 -0800956 // Binder entry point for kicking off an immediate fstrim
957 @Override
958 public void runMaintenance() {
Jeff Sharkey48877892015-03-18 11:27:19 -0700959 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
Christopher Tate7265abe2014-11-21 13:54:45 -0800960 runIdleMaintenance(null);
961 }
962
963 @Override
964 public long lastMaintenance() {
965 return mLastMaintenance;
966 }
967
San Mehat4270e1e2010-01-29 05:32:19 -0800968 public void onDaemonConnected() {
Jeff Sharkey48877892015-03-18 11:27:19 -0700969 mDaemonConnected = true;
970 mHandler.obtainMessage(H_DAEMON_CONNECTED).sendToTarget();
971 }
972
973 private void handleDaemonConnected() {
Jeff Sharkey8924e872015-11-30 12:52:10 -0700974 initIfReadyAndConnected();
Jeff Sharkey5a9bb742015-11-03 10:15:57 -0800975 resetIfReadyAndConnected();
Jeff Sharkey48877892015-03-18 11:27:19 -0700976
Jeff Sharkey48877892015-03-18 11:27:19 -0700977 // On an encrypted device we can't see system properties yet, so pull
978 // the system locale out of the mount service.
979 if ("".equals(SystemProperties.get("vold.encrypt_progress"))) {
980 copyLocaleFromMountService();
981 }
San Mehat4270e1e2010-01-29 05:32:19 -0800982 }
983
Elliott Hughesf839b4f2014-09-26 12:30:47 -0700984 private void copyLocaleFromMountService() {
985 String systemLocale;
986 try {
987 systemLocale = getField(StorageManager.SYSTEM_LOCALE_KEY);
988 } catch (RemoteException e) {
989 return;
990 }
991 if (TextUtils.isEmpty(systemLocale)) {
992 return;
993 }
994
995 Slog.d(TAG, "Got locale " + systemLocale + " from mount service");
996 Locale locale = Locale.forLanguageTag(systemLocale);
997 Configuration config = new Configuration();
998 config.setLocale(locale);
999 try {
Sudheer Shankadc589ac2016-11-10 15:30:17 -08001000 ActivityManager.getService().updatePersistentConfiguration(config);
Elliott Hughesf839b4f2014-09-26 12:30:47 -07001001 } catch (RemoteException e) {
1002 Slog.e(TAG, "Error setting system locale from mount service", e);
1003 }
Elliott Hughes9c33f282014-10-13 12:39:56 -07001004
1005 // Temporary workaround for http://b/17945169.
1006 Slog.d(TAG, "Setting system properties to " + systemLocale + " from mount service");
Narayan Kamathd30dbb82015-01-15 14:48:15 +00001007 SystemProperties.set("persist.sys.locale", locale.toLanguageTag());
Elliott Hughesf839b4f2014-09-26 12:30:47 -07001008 }
1009
Jeff Sharkey8058fe62017-09-13 11:50:33 -06001010 private final IVoldListener mListener = new IVoldListener.Stub() {
1011 @Override
1012 public void onDiskCreated(String diskId, int flags) {
1013 synchronized (mLock) {
1014 if (SystemProperties.getBoolean(StorageManager.PROP_FORCE_ADOPTABLE, false)
1015 || mForceAdoptable) {
1016 flags |= DiskInfo.FLAG_ADOPTABLE;
1017 }
Jeff Sharkey8058fe62017-09-13 11:50:33 -06001018 mDisks.put(diskId, new DiskInfo(diskId, flags));
1019 }
1020 }
1021
1022 @Override
1023 public void onDiskScanned(String diskId) {
1024 synchronized (mLock) {
1025 final DiskInfo disk = mDisks.get(diskId);
1026 if (disk != null) {
1027 onDiskScannedLocked(disk);
1028 }
1029 }
1030 }
1031
1032 @Override
1033 public void onDiskMetadataChanged(String diskId, long sizeBytes, String label,
1034 String sysPath) {
1035 synchronized (mLock) {
1036 final DiskInfo disk = mDisks.get(diskId);
1037 if (disk != null) {
1038 disk.size = sizeBytes;
1039 disk.label = label;
1040 disk.sysPath = sysPath;
1041 }
1042 }
1043 }
1044
1045 @Override
1046 public void onDiskDestroyed(String diskId) {
1047 synchronized (mLock) {
1048 final DiskInfo disk = mDisks.remove(diskId);
1049 if (disk != null) {
1050 mCallbacks.notifyDiskDestroyed(disk);
1051 }
1052 }
1053 }
1054
1055 @Override
1056 public void onVolumeCreated(String volId, int type, String diskId, String partGuid) {
1057 synchronized (mLock) {
1058 final DiskInfo disk = mDisks.get(diskId);
1059 final VolumeInfo vol = new VolumeInfo(volId, type, disk, partGuid);
1060 mVolumes.put(volId, vol);
1061 onVolumeCreatedLocked(vol);
1062 }
1063 }
1064
1065 @Override
1066 public void onVolumeStateChanged(String volId, int state) {
1067 synchronized (mLock) {
1068 final VolumeInfo vol = mVolumes.get(volId);
1069 if (vol != null) {
1070 final int oldState = vol.state;
1071 final int newState = state;
1072 vol.state = newState;
1073 onVolumeStateChangedLocked(vol, oldState, newState);
1074 }
1075 }
1076 }
1077
1078 @Override
1079 public void onVolumeMetadataChanged(String volId, String fsType, String fsUuid,
1080 String fsLabel) {
1081 synchronized (mLock) {
1082 final VolumeInfo vol = mVolumes.get(volId);
1083 if (vol != null) {
1084 vol.fsType = fsType;
1085 vol.fsUuid = fsUuid;
1086 vol.fsLabel = fsLabel;
1087 }
1088 }
1089 }
1090
1091 @Override
1092 public void onVolumePathChanged(String volId, String path) {
1093 synchronized (mLock) {
1094 final VolumeInfo vol = mVolumes.get(volId);
1095 if (vol != null) {
1096 vol.path = path;
1097 }
1098 }
1099 }
1100
1101 @Override
1102 public void onVolumeInternalPathChanged(String volId, String internalPath) {
1103 synchronized (mLock) {
1104 final VolumeInfo vol = mVolumes.get(volId);
1105 if (vol != null) {
1106 vol.internalPath = internalPath;
1107 }
1108 }
1109 }
1110
1111 @Override
1112 public void onVolumeDestroyed(String volId) {
1113 synchronized (mLock) {
1114 mVolumes.remove(volId);
1115 }
1116 }
1117 };
1118
Andreas Gampea36dc622018-02-05 17:19:22 -08001119 @GuardedBy("mLock")
Jeff Sharkeyeba260d2015-04-19 14:35:16 -07001120 private void onDiskScannedLocked(DiskInfo disk) {
Jeff Sharkey620b32b2015-04-23 19:36:02 -07001121 int volumeCount = 0;
Jeff Sharkeyeba260d2015-04-19 14:35:16 -07001122 for (int i = 0; i < mVolumes.size(); i++) {
1123 final VolumeInfo vol = mVolumes.valueAt(i);
1124 if (Objects.equals(disk.id, vol.getDiskId())) {
Jeff Sharkey620b32b2015-04-23 19:36:02 -07001125 volumeCount++;
Jeff Sharkeyeba260d2015-04-19 14:35:16 -07001126 }
1127 }
1128
Jeff Sharkeyc7acac62015-06-12 16:16:56 -07001129 final Intent intent = new Intent(DiskInfo.ACTION_DISK_SCANNED);
Jeff Sharkey7732e1e2016-03-30 17:14:23 -06001130 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT
1131 | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
Jeff Sharkeyc7acac62015-06-12 16:16:56 -07001132 intent.putExtra(DiskInfo.EXTRA_DISK_ID, disk.id);
1133 intent.putExtra(DiskInfo.EXTRA_VOLUME_COUNT, volumeCount);
Jeff Sharkeyabc3e852015-08-03 14:41:13 -07001134 mHandler.obtainMessage(H_INTERNAL_BROADCAST, intent).sendToTarget();
Jeff Sharkeyc7acac62015-06-12 16:16:56 -07001135
1136 final CountDownLatch latch = mDiskScanLatches.remove(disk.id);
1137 if (latch != null) {
1138 latch.countDown();
1139 }
1140
Jeff Sharkeyf5a6bd72015-05-19 14:42:38 -07001141 disk.volumeCount = volumeCount;
Jeff Sharkey620b32b2015-04-23 19:36:02 -07001142 mCallbacks.notifyDiskScanned(disk, volumeCount);
Jeff Sharkeyeba260d2015-04-19 14:35:16 -07001143 }
1144
Andreas Gampea36dc622018-02-05 17:19:22 -08001145 @GuardedBy("mLock")
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07001146 private void onVolumeCreatedLocked(VolumeInfo vol) {
Jeff Sharkey6855c482016-03-31 14:34:38 -06001147 if (mPms.isOnlyCoreApps()) {
1148 Slog.d(TAG, "System booted in core-only mode; ignoring volume " + vol.getId());
1149 return;
1150 }
1151
Jeff Sharkey275e3e42015-04-24 16:10:32 -07001152 if (vol.type == VolumeInfo.TYPE_EMULATED) {
1153 final StorageManager storage = mContext.getSystemService(StorageManager.class);
1154 final VolumeInfo privateVol = storage.findPrivateForEmulated(vol);
1155
1156 if (Objects.equals(StorageManager.UUID_PRIVATE_INTERNAL, mPrimaryStorageUuid)
1157 && VolumeInfo.ID_PRIVATE_INTERNAL.equals(privateVol.id)) {
1158 Slog.v(TAG, "Found primary storage at " + vol);
1159 vol.mountFlags |= VolumeInfo.MOUNT_FLAG_PRIMARY;
1160 vol.mountFlags |= VolumeInfo.MOUNT_FLAG_VISIBLE;
1161 mHandler.obtainMessage(H_VOLUME_MOUNT, vol).sendToTarget();
1162
1163 } else if (Objects.equals(privateVol.fsUuid, mPrimaryStorageUuid)) {
1164 Slog.v(TAG, "Found primary storage at " + vol);
1165 vol.mountFlags |= VolumeInfo.MOUNT_FLAG_PRIMARY;
1166 vol.mountFlags |= VolumeInfo.MOUNT_FLAG_VISIBLE;
1167 mHandler.obtainMessage(H_VOLUME_MOUNT, vol).sendToTarget();
1168 }
Jeff Sharkeyb049e212012-09-07 23:16:01 -07001169
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07001170 } else if (vol.type == VolumeInfo.TYPE_PUBLIC) {
Jeff Sharkey275e3e42015-04-24 16:10:32 -07001171 // TODO: only look at first public partition
1172 if (Objects.equals(StorageManager.UUID_PRIMARY_PHYSICAL, mPrimaryStorageUuid)
1173 && vol.disk.isDefaultPrimary()) {
1174 Slog.v(TAG, "Found primary storage at " + vol);
Jeff Sharkey7e92ef32015-04-17 17:35:07 -07001175 vol.mountFlags |= VolumeInfo.MOUNT_FLAG_PRIMARY;
1176 vol.mountFlags |= VolumeInfo.MOUNT_FLAG_VISIBLE;
San Mehat4270e1e2010-01-29 05:32:19 -08001177 }
Jeff Sharkey7e92ef32015-04-17 17:35:07 -07001178
1179 // Adoptable public disks are visible to apps, since they meet
1180 // public API requirement of being in a stable location.
Jeff Sharkey275e3e42015-04-24 16:10:32 -07001181 if (vol.disk.isAdoptable()) {
Jeff Sharkey7e92ef32015-04-17 17:35:07 -07001182 vol.mountFlags |= VolumeInfo.MOUNT_FLAG_VISIBLE;
1183 }
1184
Jeff Sharkeyab15c392016-05-05 11:45:01 -06001185 vol.mountUserId = mCurrentUserId;
Jeff Sharkey48877892015-03-18 11:27:19 -07001186 mHandler.obtainMessage(H_VOLUME_MOUNT, vol).sendToTarget();
San Mehat4270e1e2010-01-29 05:32:19 -08001187
Jeff Sharkeyb2b9ab82015-04-05 21:10:42 -07001188 } else if (vol.type == VolumeInfo.TYPE_PRIVATE) {
1189 mHandler.obtainMessage(H_VOLUME_MOUNT, vol).sendToTarget();
1190
San Mehat4270e1e2010-01-29 05:32:19 -08001191 } else {
Jeff Sharkey48877892015-03-18 11:27:19 -07001192 Slog.d(TAG, "Skipping automatic mounting of " + vol);
San Mehat4270e1e2010-01-29 05:32:19 -08001193 }
1194 }
1195
Jeff Sharkeye6c04f92015-04-18 21:38:05 -07001196 private boolean isBroadcastWorthy(VolumeInfo vol) {
1197 switch (vol.getType()) {
Jeff Sharkeyc7acac62015-06-12 16:16:56 -07001198 case VolumeInfo.TYPE_PRIVATE:
Jeff Sharkeye6c04f92015-04-18 21:38:05 -07001199 case VolumeInfo.TYPE_PUBLIC:
1200 case VolumeInfo.TYPE_EMULATED:
1201 break;
1202 default:
1203 return false;
1204 }
1205
1206 switch (vol.getState()) {
1207 case VolumeInfo.STATE_MOUNTED:
1208 case VolumeInfo.STATE_MOUNTED_READ_ONLY:
1209 case VolumeInfo.STATE_EJECTING:
1210 case VolumeInfo.STATE_UNMOUNTED:
Jeff Sharkeyc7acac62015-06-12 16:16:56 -07001211 case VolumeInfo.STATE_UNMOUNTABLE:
Tony Mantlerf0d71052015-06-24 11:45:25 -07001212 case VolumeInfo.STATE_BAD_REMOVAL:
Jeff Sharkeye6c04f92015-04-18 21:38:05 -07001213 break;
1214 default:
1215 return false;
1216 }
1217
1218 return true;
1219 }
1220
Andreas Gampea36dc622018-02-05 17:19:22 -08001221 @GuardedBy("mLock")
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07001222 private void onVolumeStateChangedLocked(VolumeInfo vol, int oldState, int newState) {
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001223 // Remember that we saw this volume so we're ready to accept user
1224 // metadata, or so we can annoy them when a private volume is ejected
1225 if (vol.isMountedReadable() && !TextUtils.isEmpty(vol.fsUuid)) {
Jeff Sharkey5cc0df22015-06-17 19:44:05 -07001226 VolumeRecord rec = mRecords.get(vol.fsUuid);
1227 if (rec == null) {
1228 rec = new VolumeRecord(vol.type, vol.fsUuid);
1229 rec.partGuid = vol.partGuid;
Jeff Sharkeye8a4b662015-06-27 15:43:45 -07001230 rec.createdMillis = System.currentTimeMillis();
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001231 if (vol.type == VolumeInfo.TYPE_PRIVATE) {
1232 rec.nickname = vol.disk.getDescription();
1233 }
1234 mRecords.put(rec.fsUuid, rec);
1235 writeSettingsLocked();
Jeff Sharkey5cc0df22015-06-17 19:44:05 -07001236 } else {
1237 // Handle upgrade case where we didn't store partition GUID
1238 if (TextUtils.isEmpty(rec.partGuid)) {
1239 rec.partGuid = vol.partGuid;
1240 writeSettingsLocked();
1241 }
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001242 }
1243 }
1244
Jeff Sharkeye6c04f92015-04-18 21:38:05 -07001245 mCallbacks.notifyVolumeStateChanged(vol, oldState, newState);
1246
Yasuhiro Matsuda87a38b52015-07-24 22:10:16 +09001247 // Do not broadcast before boot has completed to avoid launching the
1248 // processes that receive the intent unnecessarily.
1249 if (mBootCompleted && isBroadcastWorthy(vol)) {
Jeff Sharkeye6c04f92015-04-18 21:38:05 -07001250 final Intent intent = new Intent(VolumeInfo.ACTION_VOLUME_STATE_CHANGED);
Jeff Sharkeyc7acac62015-06-12 16:16:56 -07001251 intent.putExtra(VolumeInfo.EXTRA_VOLUME_ID, vol.id);
1252 intent.putExtra(VolumeInfo.EXTRA_VOLUME_STATE, newState);
Tony Mantlerf0d71052015-06-24 11:45:25 -07001253 intent.putExtra(VolumeRecord.EXTRA_FS_UUID, vol.fsUuid);
Jeff Sharkey7732e1e2016-03-30 17:14:23 -06001254 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT
1255 | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
Jeff Sharkeyabc3e852015-08-03 14:41:13 -07001256 mHandler.obtainMessage(H_INTERNAL_BROADCAST, intent).sendToTarget();
Jeff Sharkeye6c04f92015-04-18 21:38:05 -07001257 }
Jeff Sharkeyb049e212012-09-07 23:16:01 -07001258
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001259 final String oldStateEnv = VolumeInfo.getEnvironmentForState(oldState);
1260 final String newStateEnv = VolumeInfo.getEnvironmentForState(newState);
Emily Bernier92aa5a22014-07-07 10:11:48 -04001261
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001262 if (!Objects.equals(oldStateEnv, newStateEnv)) {
1263 // Kick state changed event towards all started users. Any users
1264 // started after this point will trigger additional
1265 // user-specific broadcasts.
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07001266 for (int userId : mSystemUnlockedUsers) {
Jeff Sharkey46349872015-07-28 10:49:47 -07001267 if (vol.isVisibleForRead(userId)) {
Svet Ganov6ee871e2015-07-10 14:29:33 -07001268 final StorageVolume userVol = vol.buildStorageVolume(mContext, userId, false);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001269 mHandler.obtainMessage(H_VOLUME_BROADCAST, userVol).sendToTarget();
Jeff Sharkey48877892015-03-18 11:27:19 -07001270
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001271 mCallbacks.notifyStorageStateChanged(userVol.getPath(), oldStateEnv,
1272 newStateEnv);
San Mehat4270e1e2010-01-29 05:32:19 -08001273 }
1274 }
1275 }
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001276
Jeff Sharkey7e92ef32015-04-17 17:35:07 -07001277 if (vol.type == VolumeInfo.TYPE_PUBLIC && vol.state == VolumeInfo.STATE_EJECTING) {
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001278 // TODO: this should eventually be handled by new ObbVolume state changes
1279 /*
1280 * Some OBBs might have been unmounted when this volume was
1281 * unmounted, so send a message to the handler to let it know to
1282 * remove those from the list of mounted OBBS.
1283 */
1284 mObbActionHandler.sendMessage(mObbActionHandler.obtainMessage(
1285 OBB_FLUSH_MOUNT_STATE, vol.path));
1286 }
Pavel Grafovce72ef02018-01-10 17:14:11 +00001287 maybeLogMediaMount(vol, newState);
1288 }
1289
1290 private void maybeLogMediaMount(VolumeInfo vol, int newState) {
1291 if (!SecurityLog.isLoggingEnabled()) {
1292 return;
1293 }
1294
1295 final DiskInfo disk = vol.getDisk();
1296 if (disk == null || (disk.flags & (DiskInfo.FLAG_SD | DiskInfo.FLAG_USB)) == 0) {
1297 return;
1298 }
1299
1300 // Sometimes there is a newline character.
1301 final String label = disk.label != null ? disk.label.trim() : "";
1302
1303 if (newState == VolumeInfo.STATE_MOUNTED
1304 || newState == VolumeInfo.STATE_MOUNTED_READ_ONLY) {
1305 SecurityLog.writeEvent(SecurityLog.TAG_MEDIA_MOUNT, vol.path, label);
1306 } else if (newState == VolumeInfo.STATE_UNMOUNTED
1307 || newState == VolumeInfo.STATE_BAD_REMOVAL) {
1308 SecurityLog.writeEvent(SecurityLog.TAG_MEDIA_UNMOUNT, vol.path, label);
1309 }
San Mehat4270e1e2010-01-29 05:32:19 -08001310 }
1311
Andreas Gampea36dc622018-02-05 17:19:22 -08001312 @GuardedBy("mLock")
Jeff Sharkey275e3e42015-04-24 16:10:32 -07001313 private void onMoveStatusLocked(int status) {
1314 if (mMoveCallback == null) {
1315 Slog.w(TAG, "Odd, status but no move requested");
1316 return;
1317 }
1318
1319 // TODO: estimate remaining time
1320 try {
Jeff Sharkey50a05452015-04-29 11:24:52 -07001321 mMoveCallback.onStatusChanged(-1, status, -1);
Jeff Sharkey275e3e42015-04-24 16:10:32 -07001322 } catch (RemoteException ignored) {
1323 }
1324
1325 // We've finished copying and we're about to clean up old data, so
1326 // remember that move was successful if we get rebooted
1327 if (status == MOVE_STATUS_COPY_FINISHED) {
1328 Slog.d(TAG, "Move to " + mMoveTargetUuid + " copy phase finshed; persisting");
1329
1330 mPrimaryStorageUuid = mMoveTargetUuid;
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001331 writeSettingsLocked();
Jeff Sharkey275e3e42015-04-24 16:10:32 -07001332 }
1333
1334 if (PackageManager.isMoveStatusFinished(status)) {
1335 Slog.d(TAG, "Move to " + mMoveTargetUuid + " finished with status " + status);
1336
1337 mMoveCallback = null;
1338 mMoveTargetUuid = null;
1339 }
1340 }
1341
Jeff Sharkey48877892015-03-18 11:27:19 -07001342 private void enforcePermission(String perm) {
1343 mContext.enforceCallingOrSelfPermission(perm, perm);
Mike Lockwooda5250c92011-05-23 13:44:04 -04001344 }
1345
Jeff Sharkey2e606d72015-07-27 14:19:54 -07001346 /**
1347 * Decide if volume is mountable per device policies.
1348 */
1349 private boolean isMountDisallowed(VolumeInfo vol) {
Philip P. Moltmannec3cbb22016-09-14 13:24:52 -07001350 UserManager userManager = mContext.getSystemService(UserManager.class);
1351
1352 boolean isUsbRestricted = false;
1353 if (vol.disk != null && vol.disk.isUsb()) {
1354 isUsbRestricted = userManager.hasUserRestriction(UserManager.DISALLOW_USB_FILE_TRANSFER,
Jeff Sharkey2e606d72015-07-27 14:19:54 -07001355 Binder.getCallingUserHandle());
Emily Bernier92aa5a22014-07-07 10:11:48 -04001356 }
Philip P. Moltmannec3cbb22016-09-14 13:24:52 -07001357
1358 boolean isTypeRestricted = false;
1359 if (vol.type == VolumeInfo.TYPE_PUBLIC || vol.type == VolumeInfo.TYPE_PRIVATE) {
1360 isTypeRestricted = userManager
1361 .hasUserRestriction(UserManager.DISALLOW_MOUNT_PHYSICAL_MEDIA,
1362 Binder.getCallingUserHandle());
1363 }
1364
1365 return isUsbRestricted || isTypeRestricted;
Emily Bernier92aa5a22014-07-07 10:11:48 -04001366 }
1367
Amith Yamasani462ac3a2015-06-30 14:21:01 -07001368 private void enforceAdminUser() {
1369 UserManager um = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
1370 final int callingUserId = UserHandle.getCallingUserId();
1371 boolean isAdmin;
1372 long token = Binder.clearCallingIdentity();
1373 try {
1374 isAdmin = um.getUserInfo(callingUserId).isAdmin();
1375 } finally {
1376 Binder.restoreCallingIdentity(token);
1377 }
1378 if (!isAdmin) {
1379 throw new SecurityException("Only admin users can adopt sd cards");
1380 }
1381 }
1382
Jeff Sharkeyb049e212012-09-07 23:16:01 -07001383 /**
Sudheer Shanka2250d562016-11-07 15:41:02 -08001384 * Constructs a new StorageManagerService instance
San Mehat207e5382010-02-04 20:46:54 -08001385 *
1386 * @param context Binder context for this service
1387 */
Sudheer Shanka2250d562016-11-07 15:41:02 -08001388 public StorageManagerService(Context context) {
Christopher Tated417d622013-08-19 16:14:25 -07001389 sSelf = this;
1390
San Mehat207e5382010-02-04 20:46:54 -08001391 mContext = context;
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001392 mCallbacks = new Callbacks(FgThread.get().getLooper());
Jeff Sharkeyb9fe5372015-12-03 15:23:08 -07001393 mLockPatternUtils = new LockPatternUtils(mContext);
San Mehat207e5382010-02-04 20:46:54 -08001394
San Mehat207e5382010-02-04 20:46:54 -08001395 // XXX: This will go away soon in favor of IMountServiceObserver
1396 mPms = (PackageManagerService) ServiceManager.getService("package");
1397
Dianne Hackbornefa92b22013-05-03 14:11:43 -07001398 HandlerThread hthread = new HandlerThread(TAG);
1399 hthread.start();
Sudheer Shanka2250d562016-11-07 15:41:02 -08001400 mHandler = new StorageManagerServiceHandler(hthread.getLooper());
Daniel Sandler5f27ef42010-03-16 15:42:02 -04001401
Sudheer Shanka2250d562016-11-07 15:41:02 -08001402 // Add OBB Action Handler to StorageManagerService thread.
Dianne Hackborn8d044e82013-04-30 17:24:15 -07001403 mObbActionHandler = new ObbActionHandler(IoThread.get().getLooper());
Kenny Roota02b8b02010-08-05 16:14:17 -07001404
Christopher Tate7265abe2014-11-21 13:54:45 -08001405 // Initialize the last-fstrim tracking if necessary
1406 File dataDir = Environment.getDataDirectory();
1407 File systemDir = new File(dataDir, "system");
1408 mLastMaintenanceFile = new File(systemDir, LAST_FSTRIM_FILE);
1409 if (!mLastMaintenanceFile.exists()) {
1410 // Not setting mLastMaintenance here means that we will force an
1411 // fstrim during reboot following the OTA that installs this code.
1412 try {
1413 (new FileOutputStream(mLastMaintenanceFile)).close();
1414 } catch (IOException e) {
1415 Slog.e(TAG, "Unable to create fstrim record " + mLastMaintenanceFile.getPath());
1416 }
1417 } else {
1418 mLastMaintenance = mLastMaintenanceFile.lastModified();
1419 }
1420
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001421 mSettingsFile = new AtomicFile(
Dianne Hackborne17b4452018-01-10 13:15:40 -08001422 new File(Environment.getDataSystemDirectory(), "storage.xml"), "storage-settings");
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001423
1424 synchronized (mLock) {
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001425 readSettingsLocked();
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001426 }
1427
Sudheer Shanka2250d562016-11-07 15:41:02 -08001428 LocalServices.addService(StorageManagerInternal.class, mStorageManagerInternal);
Svet Ganov6ee871e2015-07-10 14:29:33 -07001429
Jeff Sharkeybcd262d2015-06-10 09:41:17 -07001430 final IntentFilter userFilter = new IntentFilter();
1431 userFilter.addAction(Intent.ACTION_USER_ADDED);
1432 userFilter.addAction(Intent.ACTION_USER_REMOVED);
1433 mContext.registerReceiver(mUserReceiver, userFilter, null, mHandler);
1434
Jeff Sharkey5a9bb742015-11-03 10:15:57 -08001435 synchronized (mLock) {
1436 addInternalVolumeLocked();
1437 }
Amith Yamasania7892482015-08-07 11:09:05 -07001438
Kenny Root07714d42011-08-17 17:49:28 -07001439 // Add ourself to the Watchdog monitors if enabled.
1440 if (WATCHDOG_ENABLE) {
1441 Watchdog.getInstance().addMonitor(this);
1442 }
San Mehat207e5382010-02-04 20:46:54 -08001443 }
1444
Jeff Sharkeycd575992016-03-29 14:12:49 -06001445 private void start() {
Jeff Sharkey1019de92017-09-06 13:47:03 -06001446 connect();
Jeff Sharkeycd575992016-03-29 14:12:49 -06001447 }
1448
Jeff Sharkey1019de92017-09-06 13:47:03 -06001449 private void connect() {
Jin Qian12690d52017-10-13 18:17:04 -07001450 IBinder binder = ServiceManager.getService("storaged");
1451 if (binder != null) {
1452 try {
1453 binder.linkToDeath(new DeathRecipient() {
1454 @Override
1455 public void binderDied() {
1456 Slog.w(TAG, "storaged died; reconnecting");
1457 mStoraged = null;
1458 connect();
1459 }
1460 }, 0);
1461 } catch (RemoteException e) {
1462 binder = null;
1463 }
1464 }
1465
1466 if (binder != null) {
1467 mStoraged = IStoraged.Stub.asInterface(binder);
1468 } else {
1469 Slog.w(TAG, "storaged not found; trying again");
1470 }
1471
1472 binder = ServiceManager.getService("vold");
Jeff Sharkey1019de92017-09-06 13:47:03 -06001473 if (binder != null) {
1474 try {
1475 binder.linkToDeath(new DeathRecipient() {
1476 @Override
1477 public void binderDied() {
1478 Slog.w(TAG, "vold died; reconnecting");
Jin Qian12690d52017-10-13 18:17:04 -07001479 mVold = null;
Jeff Sharkey1019de92017-09-06 13:47:03 -06001480 connect();
1481 }
1482 }, 0);
1483 } catch (RemoteException e) {
1484 binder = null;
1485 }
1486 }
1487
1488 if (binder != null) {
1489 mVold = IVold.Stub.asInterface(binder);
Jeff Sharkey8058fe62017-09-13 11:50:33 -06001490 try {
1491 mVold.setListener(mListener);
Jeff Sharkey8058fe62017-09-13 11:50:33 -06001492 } catch (RemoteException e) {
Jin Qian12690d52017-10-13 18:17:04 -07001493 mVold = null;
Jeff Sharkey8058fe62017-09-13 11:50:33 -06001494 Slog.w(TAG, "vold listener rejected; trying again", e);
1495 }
Jeff Sharkey1019de92017-09-06 13:47:03 -06001496 } else {
1497 Slog.w(TAG, "vold not found; trying again");
Jeff Sharkey1019de92017-09-06 13:47:03 -06001498 }
Jeff Sharkey8058fe62017-09-13 11:50:33 -06001499
Jin Qian12690d52017-10-13 18:17:04 -07001500 if (mStoraged == null || mVold == null) {
1501 BackgroundThread.getHandler().postDelayed(() -> {
1502 connect();
1503 }, DateUtils.SECOND_IN_MILLIS);
1504 } else {
1505 onDaemonConnected();
1506 }
Jeff Sharkey1019de92017-09-06 13:47:03 -06001507 }
1508
Jeff Sharkey56e62932015-03-21 20:41:00 -07001509 private void systemReady() {
Jeff Sharkey9765e442017-12-14 22:15:14 -07001510 LocalServices.getService(ActivityManagerInternal.class)
1511 .registerScreenObserver(this);
1512
Jeff Sharkeyb049e212012-09-07 23:16:01 -07001513 mSystemReady = true;
1514 mHandler.obtainMessage(H_SYSTEM_READY).sendToTarget();
1515 }
1516
Yasuhiro Matsuda87a38b52015-07-24 22:10:16 +09001517 private void bootCompleted() {
1518 mBootCompleted = true;
1519 }
1520
Jeff Sharkeyfced5342015-05-10 14:53:34 -07001521 private String getDefaultPrimaryStorageUuid() {
1522 if (SystemProperties.getBoolean(StorageManager.PROP_PRIMARY_PHYSICAL, false)) {
1523 return StorageManager.UUID_PRIMARY_PHYSICAL;
1524 } else {
1525 return StorageManager.UUID_PRIVATE_INTERNAL;
1526 }
1527 }
1528
Andreas Gampea36dc622018-02-05 17:19:22 -08001529 @GuardedBy("mLock")
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001530 private void readSettingsLocked() {
1531 mRecords.clear();
Jeff Sharkeyfced5342015-05-10 14:53:34 -07001532 mPrimaryStorageUuid = getDefaultPrimaryStorageUuid();
Jeff Sharkey4c099d02015-05-15 13:45:00 -07001533 mForceAdoptable = false;
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001534
1535 FileInputStream fis = null;
1536 try {
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001537 fis = mSettingsFile.openRead();
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001538 final XmlPullParser in = Xml.newPullParser();
Wojciech Staszkiewicz9e9e2e72015-05-08 14:58:46 +01001539 in.setInput(fis, StandardCharsets.UTF_8.name());
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001540
1541 int type;
1542 while ((type = in.next()) != END_DOCUMENT) {
1543 if (type == START_TAG) {
1544 final String tag = in.getName();
Jeff Sharkey620b32b2015-04-23 19:36:02 -07001545 if (TAG_VOLUMES.equals(tag)) {
1546 final int version = readIntAttribute(in, ATTR_VERSION, VERSION_INIT);
Jeff Sharkeyfced5342015-05-10 14:53:34 -07001547 final boolean primaryPhysical = SystemProperties.getBoolean(
1548 StorageManager.PROP_PRIMARY_PHYSICAL, false);
1549 final boolean validAttr = (version >= VERSION_FIX_PRIMARY)
1550 || (version >= VERSION_ADD_PRIMARY && !primaryPhysical);
1551 if (validAttr) {
Jeff Sharkey620b32b2015-04-23 19:36:02 -07001552 mPrimaryStorageUuid = readStringAttribute(in,
1553 ATTR_PRIMARY_STORAGE_UUID);
Jeff Sharkey620b32b2015-04-23 19:36:02 -07001554 }
Jeff Sharkey4c099d02015-05-15 13:45:00 -07001555 mForceAdoptable = readBooleanAttribute(in, ATTR_FORCE_ADOPTABLE, false);
Jeff Sharkey620b32b2015-04-23 19:36:02 -07001556
1557 } else if (TAG_VOLUME.equals(tag)) {
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001558 final VolumeRecord rec = readVolumeRecord(in);
1559 mRecords.put(rec.fsUuid, rec);
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001560 }
1561 }
1562 }
1563 } catch (FileNotFoundException e) {
1564 // Missing metadata is okay, probably first boot
1565 } catch (IOException e) {
1566 Slog.wtf(TAG, "Failed reading metadata", e);
1567 } catch (XmlPullParserException e) {
1568 Slog.wtf(TAG, "Failed reading metadata", e);
1569 } finally {
1570 IoUtils.closeQuietly(fis);
1571 }
1572 }
1573
Andreas Gampea36dc622018-02-05 17:19:22 -08001574 @GuardedBy("mLock")
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001575 private void writeSettingsLocked() {
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001576 FileOutputStream fos = null;
1577 try {
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001578 fos = mSettingsFile.startWrite();
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001579
1580 XmlSerializer out = new FastXmlSerializer();
Wojciech Staszkiewicz9e9e2e72015-05-08 14:58:46 +01001581 out.setOutput(fos, StandardCharsets.UTF_8.name());
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001582 out.startDocument(null, true);
1583 out.startTag(null, TAG_VOLUMES);
Jeff Sharkeyfced5342015-05-10 14:53:34 -07001584 writeIntAttribute(out, ATTR_VERSION, VERSION_FIX_PRIMARY);
Jeff Sharkey620b32b2015-04-23 19:36:02 -07001585 writeStringAttribute(out, ATTR_PRIMARY_STORAGE_UUID, mPrimaryStorageUuid);
Jeff Sharkey4c099d02015-05-15 13:45:00 -07001586 writeBooleanAttribute(out, ATTR_FORCE_ADOPTABLE, mForceAdoptable);
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001587 final int size = mRecords.size();
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001588 for (int i = 0; i < size; i++) {
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001589 final VolumeRecord rec = mRecords.valueAt(i);
1590 writeVolumeRecord(out, rec);
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001591 }
1592 out.endTag(null, TAG_VOLUMES);
1593 out.endDocument();
1594
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001595 mSettingsFile.finishWrite(fos);
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001596 } catch (IOException e) {
1597 if (fos != null) {
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001598 mSettingsFile.failWrite(fos);
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001599 }
1600 }
1601 }
1602
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001603 public static VolumeRecord readVolumeRecord(XmlPullParser in) throws IOException {
1604 final int type = readIntAttribute(in, ATTR_TYPE);
1605 final String fsUuid = readStringAttribute(in, ATTR_FS_UUID);
1606 final VolumeRecord meta = new VolumeRecord(type, fsUuid);
Jeff Sharkey5cc0df22015-06-17 19:44:05 -07001607 meta.partGuid = readStringAttribute(in, ATTR_PART_GUID);
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001608 meta.nickname = readStringAttribute(in, ATTR_NICKNAME);
1609 meta.userFlags = readIntAttribute(in, ATTR_USER_FLAGS);
Jeff Sharkeye8a4b662015-06-27 15:43:45 -07001610 meta.createdMillis = readLongAttribute(in, ATTR_CREATED_MILLIS);
1611 meta.lastTrimMillis = readLongAttribute(in, ATTR_LAST_TRIM_MILLIS);
1612 meta.lastBenchMillis = readLongAttribute(in, ATTR_LAST_BENCH_MILLIS);
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001613 return meta;
1614 }
1615
1616 public static void writeVolumeRecord(XmlSerializer out, VolumeRecord rec) throws IOException {
1617 out.startTag(null, TAG_VOLUME);
1618 writeIntAttribute(out, ATTR_TYPE, rec.type);
1619 writeStringAttribute(out, ATTR_FS_UUID, rec.fsUuid);
Jeff Sharkey5cc0df22015-06-17 19:44:05 -07001620 writeStringAttribute(out, ATTR_PART_GUID, rec.partGuid);
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001621 writeStringAttribute(out, ATTR_NICKNAME, rec.nickname);
1622 writeIntAttribute(out, ATTR_USER_FLAGS, rec.userFlags);
Jeff Sharkeye8a4b662015-06-27 15:43:45 -07001623 writeLongAttribute(out, ATTR_CREATED_MILLIS, rec.createdMillis);
1624 writeLongAttribute(out, ATTR_LAST_TRIM_MILLIS, rec.lastTrimMillis);
1625 writeLongAttribute(out, ATTR_LAST_BENCH_MILLIS, rec.lastBenchMillis);
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001626 out.endTag(null, TAG_VOLUME);
1627 }
1628
San Mehat207e5382010-02-04 20:46:54 -08001629 /**
San Mehat4270e1e2010-01-29 05:32:19 -08001630 * Exposed API calls below here
1631 */
1632
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001633 @Override
Sudheer Shanka2250d562016-11-07 15:41:02 -08001634 public void registerListener(IStorageEventListener listener) {
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001635 mCallbacks.register(listener);
San Mehat4270e1e2010-01-29 05:32:19 -08001636 }
1637
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001638 @Override
Sudheer Shanka2250d562016-11-07 15:41:02 -08001639 public void unregisterListener(IStorageEventListener listener) {
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001640 mCallbacks.unregister(listener);
San Mehat4270e1e2010-01-29 05:32:19 -08001641 }
1642
Jeff Sharkey48877892015-03-18 11:27:19 -07001643 @Override
Sudheer Shanka2250d562016-11-07 15:41:02 -08001644 public void shutdown(final IStorageShutdownObserver observer) {
Jeff Sharkey48877892015-03-18 11:27:19 -07001645 enforcePermission(android.Manifest.permission.SHUTDOWN);
San Mehat4270e1e2010-01-29 05:32:19 -08001646
San Mehata5078592010-03-25 09:36:54 -07001647 Slog.i(TAG, "Shutting down");
Jeff Sharkey48877892015-03-18 11:27:19 -07001648 mHandler.obtainMessage(H_SHUTDOWN, observer).sendToTarget();
San Mehat4270e1e2010-01-29 05:32:19 -08001649 }
1650
Jeff Sharkey48877892015-03-18 11:27:19 -07001651 @Override
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001652 public void mount(String volId) {
1653 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001654
Jeff Sharkeyef10ee02015-07-05 14:17:27 -07001655 final VolumeInfo vol = findVolumeByIdOrThrow(volId);
Jeff Sharkey2e606d72015-07-27 14:19:54 -07001656 if (isMountDisallowed(vol)) {
1657 throw new SecurityException("Mounting " + volId + " restricted by policy");
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001658 }
1659 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06001660 mVold.mount(vol.id, vol.mountFlags, vol.mountUserId);
Jeff Sharkeyace874b2017-09-07 15:27:33 -06001661 } catch (Exception e) {
1662 Slog.wtf(TAG, e);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001663 }
1664 }
1665
1666 @Override
1667 public void unmount(String volId) {
1668 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001669
Jeff Sharkeyef10ee02015-07-05 14:17:27 -07001670 final VolumeInfo vol = findVolumeByIdOrThrow(volId);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001671 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06001672 mVold.unmount(vol.id);
Jeff Sharkeyace874b2017-09-07 15:27:33 -06001673 } catch (Exception e) {
1674 Slog.wtf(TAG, e);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001675 }
1676 }
1677
1678 @Override
1679 public void format(String volId) {
Jeff Sharkey48877892015-03-18 11:27:19 -07001680 enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);
San Mehat5b77dab2010-01-26 13:28:50 -08001681
Jeff Sharkeyef10ee02015-07-05 14:17:27 -07001682 final VolumeInfo vol = findVolumeByIdOrThrow(volId);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001683 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06001684 mVold.format(vol.id, "auto");
Jeff Sharkeyace874b2017-09-07 15:27:33 -06001685 } catch (Exception e) {
1686 Slog.wtf(TAG, e);
Jeff Sharkey48877892015-03-18 11:27:19 -07001687 }
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001688 }
1689
1690 @Override
Jeff Sharkey7e19f532017-11-06 13:54:11 -07001691 public void benchmark(String volId, IVoldTaskListener listener) {
Jeff Sharkey9756d752015-05-14 21:07:42 -07001692 enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);
Jeff Sharkey9756d752015-05-14 21:07:42 -07001693
1694 try {
Jeff Sharkeyb302c542017-09-15 12:57:59 -06001695 mVold.benchmark(volId, new IVoldTaskListener.Stub() {
1696 @Override
1697 public void onStatus(int status, PersistableBundle extras) {
Jeff Sharkey7e19f532017-11-06 13:54:11 -07001698 dispatchOnStatus(listener, status, extras);
Jeff Sharkeyb302c542017-09-15 12:57:59 -06001699 }
1700
1701 @Override
1702 public void onFinished(int status, PersistableBundle extras) {
Jeff Sharkey7e19f532017-11-06 13:54:11 -07001703 dispatchOnFinished(listener, status, extras);
Jeff Sharkeyb302c542017-09-15 12:57:59 -06001704
1705 final String path = extras.getString("path");
1706 final String ident = extras.getString("ident");
1707 final long create = extras.getLong("create");
1708 final long run = extras.getLong("run");
1709 final long destroy = extras.getLong("destroy");
1710
1711 final DropBoxManager dropBox = mContext.getSystemService(DropBoxManager.class);
1712 dropBox.addText(TAG_STORAGE_BENCHMARK, scrubPath(path)
1713 + " " + ident + " " + create + " " + run + " " + destroy);
1714
1715 synchronized (mLock) {
1716 final VolumeRecord rec = findRecordForPath(path);
1717 if (rec != null) {
1718 rec.lastBenchMillis = System.currentTimeMillis();
1719 writeSettingsLocked();
1720 }
1721 }
1722 }
1723 });
Jeff Sharkey7e19f532017-11-06 13:54:11 -07001724 } catch (RemoteException e) {
1725 throw e.rethrowAsRuntimeException();
Jeff Sharkey9756d752015-05-14 21:07:42 -07001726 }
1727 }
1728
1729 @Override
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001730 public void partitionPublic(String diskId) {
1731 enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001732
Jeff Sharkeyeba260d2015-04-19 14:35:16 -07001733 final CountDownLatch latch = findOrCreateDiskScanLatch(diskId);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001734 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06001735 mVold.partition(diskId, IVold.PARTITION_TYPE_PUBLIC, -1);
Jeff Sharkeyedcdaf62015-07-09 09:45:36 -07001736 waitForLatch(latch, "partitionPublic", 3 * DateUtils.MINUTE_IN_MILLIS);
Jeff Sharkeyace874b2017-09-07 15:27:33 -06001737 } catch (Exception e) {
1738 Slog.wtf(TAG, e);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001739 }
1740 }
1741
1742 @Override
1743 public void partitionPrivate(String diskId) {
1744 enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);
Amith Yamasani462ac3a2015-06-30 14:21:01 -07001745 enforceAdminUser();
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001746
Jeff Sharkeyeba260d2015-04-19 14:35:16 -07001747 final CountDownLatch latch = findOrCreateDiskScanLatch(diskId);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001748 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06001749 mVold.partition(diskId, IVold.PARTITION_TYPE_PRIVATE, -1);
Jeff Sharkeyedcdaf62015-07-09 09:45:36 -07001750 waitForLatch(latch, "partitionPrivate", 3 * DateUtils.MINUTE_IN_MILLIS);
Jeff Sharkeyace874b2017-09-07 15:27:33 -06001751 } catch (Exception e) {
1752 Slog.wtf(TAG, e);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001753 }
1754 }
1755
1756 @Override
1757 public void partitionMixed(String diskId, int ratio) {
1758 enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);
Amith Yamasani462ac3a2015-06-30 14:21:01 -07001759 enforceAdminUser();
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001760
Jeff Sharkeyeba260d2015-04-19 14:35:16 -07001761 final CountDownLatch latch = findOrCreateDiskScanLatch(diskId);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001762 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06001763 mVold.partition(diskId, IVold.PARTITION_TYPE_MIXED, ratio);
Jeff Sharkeyedcdaf62015-07-09 09:45:36 -07001764 waitForLatch(latch, "partitionMixed", 3 * DateUtils.MINUTE_IN_MILLIS);
Jeff Sharkeyace874b2017-09-07 15:27:33 -06001765 } catch (Exception e) {
1766 Slog.wtf(TAG, e);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001767 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001768 }
1769
Jeff Sharkey48877892015-03-18 11:27:19 -07001770 @Override
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001771 public void setVolumeNickname(String fsUuid, String nickname) {
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001772 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001773
Jeff Sharkey50a05452015-04-29 11:24:52 -07001774 Preconditions.checkNotNull(fsUuid);
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001775 synchronized (mLock) {
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001776 final VolumeRecord rec = mRecords.get(fsUuid);
1777 rec.nickname = nickname;
Jeff Sharkey50a05452015-04-29 11:24:52 -07001778 mCallbacks.notifyVolumeRecordChanged(rec);
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001779 writeSettingsLocked();
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001780 }
1781 }
1782
1783 @Override
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001784 public void setVolumeUserFlags(String fsUuid, int flags, int mask) {
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001785 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001786
Jeff Sharkey50a05452015-04-29 11:24:52 -07001787 Preconditions.checkNotNull(fsUuid);
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001788 synchronized (mLock) {
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001789 final VolumeRecord rec = mRecords.get(fsUuid);
1790 rec.userFlags = (rec.userFlags & ~mask) | (flags & mask);
Jeff Sharkey50a05452015-04-29 11:24:52 -07001791 mCallbacks.notifyVolumeRecordChanged(rec);
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001792 writeSettingsLocked();
1793 }
1794 }
1795
1796 @Override
1797 public void forgetVolume(String fsUuid) {
1798 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001799
Jeff Sharkey50a05452015-04-29 11:24:52 -07001800 Preconditions.checkNotNull(fsUuid);
Jeff Sharkey5a9bb742015-11-03 10:15:57 -08001801
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001802 synchronized (mLock) {
Jeff Sharkey5cc0df22015-06-17 19:44:05 -07001803 final VolumeRecord rec = mRecords.remove(fsUuid);
1804 if (rec != null && !TextUtils.isEmpty(rec.partGuid)) {
Jeff Sharkeydb4b6192017-10-24 11:08:50 -06001805 mHandler.obtainMessage(H_PARTITION_FORGET, rec).sendToTarget();
Jeff Sharkey5cc0df22015-06-17 19:44:05 -07001806 }
1807 mCallbacks.notifyVolumeForgotten(fsUuid);
Jeff Sharkey50a05452015-04-29 11:24:52 -07001808
1809 // If this had been primary storage, revert back to internal and
1810 // reset vold so we bind into new volume into place.
1811 if (Objects.equals(mPrimaryStorageUuid, fsUuid)) {
Jeff Sharkeyfced5342015-05-10 14:53:34 -07001812 mPrimaryStorageUuid = getDefaultPrimaryStorageUuid();
Jeff Sharkey5a9bb742015-11-03 10:15:57 -08001813 mHandler.obtainMessage(H_RESET).sendToTarget();
Jeff Sharkey50a05452015-04-29 11:24:52 -07001814 }
1815
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001816 writeSettingsLocked();
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001817 }
1818 }
1819
Jeff Sharkey7d2af542015-05-12 15:27:15 -07001820 @Override
1821 public void forgetAllVolumes() {
1822 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
Jeff Sharkey7d2af542015-05-12 15:27:15 -07001823
Jeff Sharkey50a05452015-04-29 11:24:52 -07001824 synchronized (mLock) {
1825 for (int i = 0; i < mRecords.size(); i++) {
1826 final String fsUuid = mRecords.keyAt(i);
Jeff Sharkey5cc0df22015-06-17 19:44:05 -07001827 final VolumeRecord rec = mRecords.valueAt(i);
1828 if (!TextUtils.isEmpty(rec.partGuid)) {
Jeff Sharkeydb4b6192017-10-24 11:08:50 -06001829 mHandler.obtainMessage(H_PARTITION_FORGET, rec).sendToTarget();
Jeff Sharkey5cc0df22015-06-17 19:44:05 -07001830 }
Jeff Sharkey50a05452015-04-29 11:24:52 -07001831 mCallbacks.notifyVolumeForgotten(fsUuid);
1832 }
Jeff Sharkey50a05452015-04-29 11:24:52 -07001833 mRecords.clear();
Jeff Sharkey50a05452015-04-29 11:24:52 -07001834
Jeff Sharkeyfced5342015-05-10 14:53:34 -07001835 if (!Objects.equals(StorageManager.UUID_PRIVATE_INTERNAL, mPrimaryStorageUuid)) {
1836 mPrimaryStorageUuid = getDefaultPrimaryStorageUuid();
1837 }
1838
1839 writeSettingsLocked();
Jeff Sharkey5a9bb742015-11-03 10:15:57 -08001840 mHandler.obtainMessage(H_RESET).sendToTarget();
Jeff Sharkey50a05452015-04-29 11:24:52 -07001841 }
1842 }
1843
Jeff Sharkeydb4b6192017-10-24 11:08:50 -06001844 private void forgetPartition(String partGuid, String fsUuid) {
Jeff Sharkey5cc0df22015-06-17 19:44:05 -07001845 try {
Jeff Sharkeydb4b6192017-10-24 11:08:50 -06001846 mVold.forgetPartition(partGuid, fsUuid);
Jeff Sharkeyace874b2017-09-07 15:27:33 -06001847 } catch (Exception e) {
1848 Slog.wtf(TAG, e);
Jeff Sharkey5cc0df22015-06-17 19:44:05 -07001849 }
1850 }
1851
Jeff Sharkey31d0b702016-11-21 14:16:53 -07001852 @Override
Jeff Sharkey7e19f532017-11-06 13:54:11 -07001853 public void fstrim(int flags, IVoldTaskListener listener) {
Jeff Sharkey31d0b702016-11-21 14:16:53 -07001854 enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);
Jeff Sharkey31d0b702016-11-21 14:16:53 -07001855
1856 try {
Jeff Sharkeyb302c542017-09-15 12:57:59 -06001857 mVold.fstrim(flags, new IVoldTaskListener.Stub() {
1858 @Override
1859 public void onStatus(int status, PersistableBundle extras) {
Jeff Sharkey7e19f532017-11-06 13:54:11 -07001860 dispatchOnStatus(listener, status, extras);
1861
Jeff Sharkeyb302c542017-09-15 12:57:59 -06001862 // Ignore trim failures
1863 if (status != 0) return;
1864
1865 final String path = extras.getString("path");
1866 final long bytes = extras.getLong("bytes");
1867 final long time = extras.getLong("time");
1868
1869 final DropBoxManager dropBox = mContext.getSystemService(DropBoxManager.class);
1870 dropBox.addText(TAG_STORAGE_TRIM, scrubPath(path) + " " + bytes + " " + time);
1871
1872 synchronized (mLock) {
1873 final VolumeRecord rec = findRecordForPath(path);
1874 if (rec != null) {
1875 rec.lastTrimMillis = System.currentTimeMillis();
1876 writeSettingsLocked();
1877 }
1878 }
1879 }
1880
1881 @Override
1882 public void onFinished(int status, PersistableBundle extras) {
Jeff Sharkey7e19f532017-11-06 13:54:11 -07001883 dispatchOnFinished(listener, status, extras);
1884
Jeff Sharkeyb302c542017-09-15 12:57:59 -06001885 // TODO: benchmark when desired
1886 }
1887 });
Jeff Sharkey7e19f532017-11-06 13:54:11 -07001888 } catch (RemoteException e) {
1889 throw e.rethrowAsRuntimeException();
Jeff Sharkey31d0b702016-11-21 14:16:53 -07001890 }
1891 }
1892
Jin Qiana85b9912017-10-17 15:48:18 -07001893 void runIdleMaint(Runnable callback) {
1894 enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);
1895
1896 try {
1897 mVold.runIdleMaint(new IVoldTaskListener.Stub() {
1898 @Override
1899 public void onStatus(int status, PersistableBundle extras) {
1900 // Not currently used
1901 }
1902 @Override
1903 public void onFinished(int status, PersistableBundle extras) {
1904 if (callback != null) {
1905 BackgroundThread.getHandler().post(callback);
1906 }
1907 }
1908 });
1909 } catch (Exception e) {
1910 Slog.wtf(TAG, e);
1911 }
1912 }
1913
1914 @Override
1915 public void runIdleMaintenance() {
1916 runIdleMaint(null);
1917 }
1918
1919 void abortIdleMaint(Runnable callback) {
1920 enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);
1921
1922 try {
1923 mVold.abortIdleMaint(new IVoldTaskListener.Stub() {
1924 @Override
1925 public void onStatus(int status, PersistableBundle extras) {
1926 // Not currently used
1927 }
1928 @Override
1929 public void onFinished(int status, PersistableBundle extras) {
1930 if (callback != null) {
1931 BackgroundThread.getHandler().post(callback);
1932 }
1933 }
1934 });
1935 } catch (Exception e) {
1936 Slog.wtf(TAG, e);
1937 }
1938 }
1939
1940 @Override
1941 public void abortIdleMaintenance() {
1942 abortIdleMaint(null);
1943 }
1944
Svet Ganov6ee871e2015-07-10 14:29:33 -07001945 private void remountUidExternalStorage(int uid, int mode) {
Jeff Sharkey9527b222015-06-24 15:24:48 -07001946 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06001947 mVold.remountUid(uid, mode);
Jeff Sharkeyace874b2017-09-07 15:27:33 -06001948 } catch (Exception e) {
1949 Slog.wtf(TAG, e);
Jeff Sharkey9527b222015-06-24 15:24:48 -07001950 }
1951 }
1952
1953 @Override
Jeff Sharkey4c099d02015-05-15 13:45:00 -07001954 public void setDebugFlags(int flags, int mask) {
1955 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
Jeff Sharkey4c099d02015-05-15 13:45:00 -07001956
Jeff Sharkeyba512352015-11-12 20:17:45 -08001957 if ((mask & StorageManager.DEBUG_EMULATE_FBE) != 0) {
Jeff Sharkey00455bf2016-11-04 14:45:24 -06001958 if (!EMULATE_FBE_SUPPORTED) {
1959 throw new IllegalStateException(
1960 "Emulation not supported on this device");
1961 }
Paul Lawrence20be5d62016-02-26 13:51:17 -08001962 if (StorageManager.isFileEncryptedNativeOnly()) {
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07001963 throw new IllegalStateException(
Jeff Sharkey00455bf2016-11-04 14:45:24 -06001964 "Emulation not supported on device with native FBE");
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07001965 }
Jeff Sharkey5a785162016-03-21 13:02:06 -06001966 if (mLockPatternUtils.isCredentialRequiredToDecrypt(false)) {
1967 throw new IllegalStateException(
1968 "Emulation requires disabling 'Secure start-up' in Settings > Security");
1969 }
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07001970
Jeff Sharkey1176e512016-02-29 17:01:26 -07001971 final long token = Binder.clearCallingIdentity();
1972 try {
1973 final boolean emulateFbe = (flags & StorageManager.DEBUG_EMULATE_FBE) != 0;
1974 SystemProperties.set(StorageManager.PROP_EMULATE_FBE, Boolean.toString(emulateFbe));
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07001975
Jeff Sharkey1176e512016-02-29 17:01:26 -07001976 // Perform hard reboot to kick policy into place
1977 mContext.getSystemService(PowerManager.class).reboot(null);
1978 } finally {
1979 Binder.restoreCallingIdentity(token);
1980 }
Jeff Sharkeyba512352015-11-12 20:17:45 -08001981 }
Jeff Sharkey4c099d02015-05-15 13:45:00 -07001982
Jeff Sharkeyba512352015-11-12 20:17:45 -08001983 if ((mask & StorageManager.DEBUG_FORCE_ADOPTABLE) != 0) {
1984 synchronized (mLock) {
1985 mForceAdoptable = (flags & StorageManager.DEBUG_FORCE_ADOPTABLE) != 0;
1986
1987 writeSettingsLocked();
1988 mHandler.obtainMessage(H_RESET).sendToTarget();
1989 }
Jeff Sharkey4c099d02015-05-15 13:45:00 -07001990 }
Jeff Sharkey33dd1562016-04-07 11:05:33 -06001991
1992 if ((mask & (StorageManager.DEBUG_SDCARDFS_FORCE_ON
1993 | StorageManager.DEBUG_SDCARDFS_FORCE_OFF)) != 0) {
1994 final String value;
1995 if ((flags & StorageManager.DEBUG_SDCARDFS_FORCE_ON) != 0) {
1996 value = "force_on";
1997 } else if ((flags & StorageManager.DEBUG_SDCARDFS_FORCE_OFF) != 0) {
1998 value = "force_off";
1999 } else {
2000 value = "";
2001 }
2002
2003 final long token = Binder.clearCallingIdentity();
2004 try {
2005 SystemProperties.set(StorageManager.PROP_SDCARDFS, value);
2006
2007 // Reset storage to kick new setting into place
2008 mHandler.obtainMessage(H_RESET).sendToTarget();
2009 } finally {
2010 Binder.restoreCallingIdentity(token);
2011 }
2012 }
Jeff Sharkeye53e2d92017-03-25 23:14:06 -06002013
2014 if ((mask & StorageManager.DEBUG_VIRTUAL_DISK) != 0) {
2015 final boolean enabled = (flags & StorageManager.DEBUG_VIRTUAL_DISK) != 0;
2016
2017 final long token = Binder.clearCallingIdentity();
2018 try {
2019 SystemProperties.set(StorageManager.PROP_VIRTUAL_DISK, Boolean.toString(enabled));
2020
2021 // Reset storage to kick new setting into place
2022 mHandler.obtainMessage(H_RESET).sendToTarget();
2023 } finally {
2024 Binder.restoreCallingIdentity(token);
2025 }
2026 }
Jeff Sharkey4c099d02015-05-15 13:45:00 -07002027 }
2028
2029 @Override
Jeff Sharkey275e3e42015-04-24 16:10:32 -07002030 public String getPrimaryStorageUuid() {
Jeff Sharkey620b32b2015-04-23 19:36:02 -07002031 synchronized (mLock) {
2032 return mPrimaryStorageUuid;
2033 }
2034 }
2035
2036 @Override
Jeff Sharkey275e3e42015-04-24 16:10:32 -07002037 public void setPrimaryStorageUuid(String volumeUuid, IPackageMoveObserver callback) {
2038 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
Jeff Sharkey620b32b2015-04-23 19:36:02 -07002039
Jeff Sharkeya31460c2016-06-22 09:04:33 -06002040 final VolumeInfo from;
2041 final VolumeInfo to;
2042
Jeff Sharkey275e3e42015-04-24 16:10:32 -07002043 synchronized (mLock) {
Jeff Sharkeyfced5342015-05-10 14:53:34 -07002044 if (Objects.equals(mPrimaryStorageUuid, volumeUuid)) {
2045 throw new IllegalArgumentException("Primary storage already at " + volumeUuid);
Jeff Sharkey275e3e42015-04-24 16:10:32 -07002046 }
2047
2048 if (mMoveCallback != null) {
2049 throw new IllegalStateException("Move already in progress");
2050 }
2051 mMoveCallback = callback;
2052 mMoveTargetUuid = volumeUuid;
2053
Jeff Sharkeya65e6492017-06-21 13:45:11 -06002054 // We need all the users unlocked to move their primary storage
2055 final List<UserInfo> users = mContext.getSystemService(UserManager.class).getUsers();
2056 for (UserInfo user : users) {
2057 if (StorageManager.isFileEncryptedNativeOrEmulated()
2058 && !isUserKeyUnlocked(user.id)) {
2059 Slog.w(TAG, "Failing move due to locked user " + user.id);
2060 onMoveStatusLocked(PackageManager.MOVE_FAILED_LOCKED_USER);
2061 return;
2062 }
2063 }
2064
Jeff Sharkeyfced5342015-05-10 14:53:34 -07002065 // When moving to/from primary physical volume, we probably just nuked
2066 // the current storage location, so we have nothing to move.
2067 if (Objects.equals(StorageManager.UUID_PRIMARY_PHYSICAL, mPrimaryStorageUuid)
2068 || Objects.equals(StorageManager.UUID_PRIMARY_PHYSICAL, volumeUuid)) {
2069 Slog.d(TAG, "Skipping move to/from primary physical");
2070 onMoveStatusLocked(MOVE_STATUS_COPY_FINISHED);
2071 onMoveStatusLocked(PackageManager.MOVE_SUCCEEDED);
Jeff Sharkey5a9bb742015-11-03 10:15:57 -08002072 mHandler.obtainMessage(H_RESET).sendToTarget();
Jeff Sharkeya31460c2016-06-22 09:04:33 -06002073 return;
Jeff Sharkeyfced5342015-05-10 14:53:34 -07002074
2075 } else {
Jeff Sharkeya31460c2016-06-22 09:04:33 -06002076 from = findStorageForUuid(mPrimaryStorageUuid);
2077 to = findStorageForUuid(volumeUuid);
Jeff Sharkeyef10ee02015-07-05 14:17:27 -07002078
2079 if (from == null) {
2080 Slog.w(TAG, "Failing move due to missing from volume " + mPrimaryStorageUuid);
2081 onMoveStatusLocked(PackageManager.MOVE_FAILED_INTERNAL_ERROR);
2082 return;
2083 } else if (to == null) {
2084 Slog.w(TAG, "Failing move due to missing to volume " + volumeUuid);
2085 onMoveStatusLocked(PackageManager.MOVE_FAILED_INTERNAL_ERROR);
2086 return;
2087 }
Jeff Sharkey275e3e42015-04-24 16:10:32 -07002088 }
Jeff Sharkey620b32b2015-04-23 19:36:02 -07002089 }
Jeff Sharkeya31460c2016-06-22 09:04:33 -06002090
2091 try {
Jeff Sharkeyb302c542017-09-15 12:57:59 -06002092 mVold.moveStorage(from.id, to.id, new IVoldTaskListener.Stub() {
2093 @Override
2094 public void onStatus(int status, PersistableBundle extras) {
2095 synchronized (mLock) {
2096 onMoveStatusLocked(status);
2097 }
2098 }
2099
2100 @Override
2101 public void onFinished(int status, PersistableBundle extras) {
2102 // Not currently used
2103 }
2104 });
Jeff Sharkeyace874b2017-09-07 15:27:33 -06002105 } catch (Exception e) {
2106 Slog.wtf(TAG, e);
Jeff Sharkeya31460c2016-06-22 09:04:33 -06002107 }
Jeff Sharkey620b32b2015-04-23 19:36:02 -07002108 }
2109
San Mehatb1043402010-02-05 08:26:50 -08002110 private void warnOnNotMounted() {
Jeff Sharkey48877892015-03-18 11:27:19 -07002111 synchronized (mLock) {
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07002112 for (int i = 0; i < mVolumes.size(); i++) {
2113 final VolumeInfo vol = mVolumes.valueAt(i);
Jeff Sharkey27de30d2015-04-18 16:20:27 -07002114 if (vol.isPrimary() && vol.isMountedWritable()) {
Jeff Sharkey48877892015-03-18 11:27:19 -07002115 // Cool beans, we have a mounted primary volume
2116 return;
2117 }
Jeff Sharkey32ee8312012-09-30 13:21:31 -07002118 }
San Mehatb1043402010-02-05 08:26:50 -08002119 }
Jeff Sharkey48877892015-03-18 11:27:19 -07002120
2121 Slog.w(TAG, "No primary storage mounted!");
San Mehatb1043402010-02-05 08:26:50 -08002122 }
2123
Kenny Roota02b8b02010-08-05 16:14:17 -07002124 private boolean isUidOwnerOfPackageOrSystem(String packageName, int callerUid) {
2125 if (callerUid == android.os.Process.SYSTEM_UID) {
2126 return true;
2127 }
2128
Kenny Root02c87302010-07-01 08:10:18 -07002129 if (packageName == null) {
2130 return false;
2131 }
2132
Jeff Sharkeycd654482016-01-08 17:42:11 -07002133 final int packageUid = mPms.getPackageUid(packageName,
2134 PackageManager.MATCH_DEBUG_TRIAGED_MISSING, UserHandle.getUserId(callerUid));
Kenny Root02c87302010-07-01 08:10:18 -07002135
2136 if (DEBUG_OBB) {
2137 Slog.d(TAG, "packageName = " + packageName + ", packageUid = " +
2138 packageUid + ", callerUid = " + callerUid);
2139 }
2140
2141 return callerUid == packageUid;
2142 }
2143
Jeff Sharkey54402792017-09-15 16:05:19 -06002144 @Override
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002145 public String getMountedObbPath(String rawPath) {
2146 Preconditions.checkNotNull(rawPath, "rawPath cannot be null");
Kenny Rootaf9d6672010-10-08 09:21:39 -07002147
Kenny Root02c87302010-07-01 08:10:18 -07002148 warnOnNotMounted();
2149
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002150 final ObbState state;
Rubin Xucd7a0142015-04-17 23:45:27 +01002151 synchronized (mObbMounts) {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002152 state = mObbPathToStateMap.get(rawPath);
2153 }
2154 if (state == null) {
2155 Slog.w(TAG, "Failed to find OBB mounted at " + rawPath);
2156 return null;
2157 }
2158
Jeff Sharkey54402792017-09-15 16:05:19 -06002159 return findVolumeByIdOrThrow(state.volId).getPath().getAbsolutePath();
Kenny Root02c87302010-07-01 08:10:18 -07002160 }
2161
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002162 @Override
2163 public boolean isObbMounted(String rawPath) {
2164 Preconditions.checkNotNull(rawPath, "rawPath cannot be null");
Kenny Rootaf9d6672010-10-08 09:21:39 -07002165 synchronized (mObbMounts) {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002166 return mObbPathToStateMap.containsKey(rawPath);
Kenny Rootaf9d6672010-10-08 09:21:39 -07002167 }
Kenny Root02c87302010-07-01 08:10:18 -07002168 }
2169
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002170 @Override
2171 public void mountObb(
2172 String rawPath, String canonicalPath, String key, IObbActionListener token, int nonce) {
2173 Preconditions.checkNotNull(rawPath, "rawPath cannot be null");
2174 Preconditions.checkNotNull(canonicalPath, "canonicalPath cannot be null");
2175 Preconditions.checkNotNull(token, "token cannot be null");
Kenny Rootaf9d6672010-10-08 09:21:39 -07002176
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002177 final int callingUid = Binder.getCallingUid();
Jeff Sharkey41cd6812017-09-11 10:32:17 -06002178 final ObbState obbState = new ObbState(rawPath, canonicalPath,
2179 callingUid, token, nonce, null);
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002180 final ObbAction action = new MountObbAction(obbState, key, callingUid);
Kenny Roota02b8b02010-08-05 16:14:17 -07002181 mObbActionHandler.sendMessage(mObbActionHandler.obtainMessage(OBB_RUN_ACTION, action));
2182
2183 if (DEBUG_OBB)
2184 Slog.i(TAG, "Send to OBB handler: " + action.toString());
Kenny Root02c87302010-07-01 08:10:18 -07002185 }
2186
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002187 @Override
2188 public void unmountObb(String rawPath, boolean force, IObbActionListener token, int nonce) {
2189 Preconditions.checkNotNull(rawPath, "rawPath cannot be null");
2190
2191 final ObbState existingState;
Rubin Xucd7a0142015-04-17 23:45:27 +01002192 synchronized (mObbMounts) {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002193 existingState = mObbPathToStateMap.get(rawPath);
Kenny Rootf1121dc2010-09-29 07:30:53 -07002194 }
2195
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002196 if (existingState != null) {
2197 // TODO: separate state object from request data
2198 final int callingUid = Binder.getCallingUid();
Jeff Sharkey41cd6812017-09-11 10:32:17 -06002199 final ObbState newState = new ObbState(rawPath, existingState.canonicalPath,
2200 callingUid, token, nonce, existingState.volId);
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002201 final ObbAction action = new UnmountObbAction(newState, force);
2202 mObbActionHandler.sendMessage(mObbActionHandler.obtainMessage(OBB_RUN_ACTION, action));
Kenny Root02c87302010-07-01 08:10:18 -07002203
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002204 if (DEBUG_OBB)
2205 Slog.i(TAG, "Send to OBB handler: " + action.toString());
2206 } else {
2207 Slog.w(TAG, "Unknown OBB mount at " + rawPath);
2208 }
Kenny Roota02b8b02010-08-05 16:14:17 -07002209 }
2210
Ben Komalo444eca22011-09-01 15:17:44 -07002211 @Override
2212 public int getEncryptionState() {
2213 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
2214 "no permission to access the crypt keeper");
2215
Ben Komalo444eca22011-09-01 15:17:44 -07002216 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002217 return mVold.fdeComplete();
2218 } catch (Exception e) {
2219 Slog.wtf(TAG, e);
Sudheer Shankaf7341142016-10-18 17:15:18 -07002220 return StorageManager.ENCRYPTION_STATE_ERROR_UNKNOWN;
Ben Komalo444eca22011-09-01 15:17:44 -07002221 }
2222 }
2223
2224 @Override
Jason parks5af0b912010-11-29 09:05:25 -06002225 public int decryptStorage(String password) {
Jason parks8888c592011-01-20 22:46:41 -06002226 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
2227 "no permission to access the crypt keeper");
Jason parks5af0b912010-11-29 09:05:25 -06002228
Jeff Sharkey8058fe62017-09-13 11:50:33 -06002229 if (TextUtils.isEmpty(password)) {
2230 throw new IllegalArgumentException("password cannot be empty");
2231 }
2232
Jason parks5af0b912010-11-29 09:05:25 -06002233 if (DEBUG_EVENTS) {
2234 Slog.i(TAG, "decrypting storage...");
2235 }
2236
2237 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002238 mVold.fdeCheckPassword(password);
2239 mHandler.postDelayed(() -> {
2240 try {
2241 mVold.fdeRestart();
2242 } catch (Exception e) {
2243 Slog.wtf(TAG, e);
2244 }
2245 }, DateUtils.SECOND_IN_MILLIS);
2246 return 0;
2247 } catch (Exception e) {
2248 Slog.wtf(TAG, e);
2249 return StorageManager.ENCRYPTION_STATE_ERROR_UNKNOWN;
Jason parks5af0b912010-11-29 09:05:25 -06002250 }
Jason parks5af0b912010-11-29 09:05:25 -06002251 }
2252
Jeff Sharkey54402792017-09-15 16:05:19 -06002253 @Override
Paul Lawrence46791e72014-04-03 09:10:26 -07002254 public int encryptStorage(int type, String password) {
Jason parks8888c592011-01-20 22:46:41 -06002255 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
2256 "no permission to access the crypt keeper");
Jason parks56aa5322011-01-07 09:01:15 -06002257
Jeff Sharkey8058fe62017-09-13 11:50:33 -06002258 if (type == StorageManager.CRYPT_TYPE_DEFAULT) {
2259 password = "";
2260 } else if (TextUtils.isEmpty(password)) {
2261 throw new IllegalArgumentException("password cannot be empty");
2262 }
2263
Jason parks56aa5322011-01-07 09:01:15 -06002264 if (DEBUG_EVENTS) {
Jason parks8888c592011-01-20 22:46:41 -06002265 Slog.i(TAG, "encrypting storage...");
Jason parks56aa5322011-01-07 09:01:15 -06002266 }
2267
2268 try {
Paul Lawrence89a0ae42017-12-22 10:11:10 -08002269 mVold.fdeEnable(type, password, 0);
Jeff Sharkey43e12112017-09-12 16:31:45 -06002270 } catch (Exception e) {
2271 Slog.wtf(TAG, e);
2272 return -1;
Jason parks56aa5322011-01-07 09:01:15 -06002273 }
2274
2275 return 0;
2276 }
2277
Paul Lawrence8e397362014-01-27 15:22:30 -08002278 /** Set the password for encrypting the master key.
2279 * @param type One of the CRYPTO_TYPE_XXX consts defined in StorageManager.
2280 * @param password The password to set.
2281 */
Jeff Sharkey54402792017-09-15 16:05:19 -06002282 @Override
Paul Lawrence8e397362014-01-27 15:22:30 -08002283 public int changeEncryptionPassword(int type, String password) {
Jason parksf7b3cd42011-01-27 09:28:25 -06002284 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
2285 "no permission to access the crypt keeper");
2286
Jeff Sharkeyae266462017-11-27 13:32:24 -07002287 if (StorageManager.isFileEncryptedNativeOnly()) {
2288 // Not supported on FBE devices
2289 return -1;
2290 }
2291
Jeff Sharkey8058fe62017-09-13 11:50:33 -06002292 if (type == StorageManager.CRYPT_TYPE_DEFAULT) {
2293 password = "";
2294 } else if (TextUtils.isEmpty(password)) {
2295 throw new IllegalArgumentException("password cannot be empty");
2296 }
2297
Jason parksf7b3cd42011-01-27 09:28:25 -06002298 if (DEBUG_EVENTS) {
2299 Slog.i(TAG, "changing encryption password...");
2300 }
2301
2302 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002303 mVold.fdeChangePassword(type, password);
2304 return 0;
2305 } catch (Exception e) {
2306 Slog.wtf(TAG, e);
2307 return -1;
Jason parksf7b3cd42011-01-27 09:28:25 -06002308 }
2309 }
2310
Christopher Tate32418be2011-10-10 13:51:12 -07002311 /**
2312 * Validate a user-supplied password string with cryptfs
2313 */
2314 @Override
2315 public int verifyEncryptionPassword(String password) throws RemoteException {
2316 // Only the system process is permitted to validate passwords
2317 if (Binder.getCallingUid() != android.os.Process.SYSTEM_UID) {
2318 throw new SecurityException("no permission to access the crypt keeper");
2319 }
2320
2321 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
2322 "no permission to access the crypt keeper");
2323
2324 if (TextUtils.isEmpty(password)) {
2325 throw new IllegalArgumentException("password cannot be empty");
2326 }
2327
Christopher Tate32418be2011-10-10 13:51:12 -07002328 if (DEBUG_EVENTS) {
2329 Slog.i(TAG, "validating encryption password...");
2330 }
2331
2332 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002333 mVold.fdeVerifyPassword(password);
2334 return 0;
2335 } catch (Exception e) {
2336 Slog.wtf(TAG, e);
2337 return -1;
Christopher Tate32418be2011-10-10 13:51:12 -07002338 }
2339 }
2340
Paul Lawrence8e397362014-01-27 15:22:30 -08002341 /**
2342 * Get the type of encryption used to encrypt the master key.
2343 * @return The type, one of the CRYPT_TYPE_XXX consts from StorageManager.
2344 */
2345 @Override
Svetoslav16e4a1a2014-09-29 18:16:20 -07002346 public int getPasswordType() {
Paul Lawrence76a40572017-03-15 11:08:04 -07002347 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
Paul Lawrence9de713d2016-05-02 22:45:33 +00002348 "no permission to access the crypt keeper");
2349
Paul Lawrence8e397362014-01-27 15:22:30 -08002350 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002351 return mVold.fdeGetPasswordType();
2352 } catch (Exception e) {
2353 Slog.wtf(TAG, e);
2354 return -1;
Paul Lawrence8e397362014-01-27 15:22:30 -08002355 }
2356 }
2357
Paul Lawrencee51dcf92014-03-18 10:56:00 -07002358 /**
2359 * Set a field in the crypto header.
2360 * @param field field to set
2361 * @param contents contents to set in field
2362 */
2363 @Override
2364 public void setField(String field, String contents) throws RemoteException {
Paul Lawrence76a40572017-03-15 11:08:04 -07002365 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
Paul Lawrence0bbd1082016-04-26 15:21:02 -07002366 "no permission to access the crypt keeper");
Paul Lawrencee51dcf92014-03-18 10:56:00 -07002367
Jeff Sharkeyae266462017-11-27 13:32:24 -07002368 if (StorageManager.isFileEncryptedNativeOnly()) {
2369 // Not supported on FBE devices
2370 return;
2371 }
2372
Paul Lawrencee51dcf92014-03-18 10:56:00 -07002373 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002374 mVold.fdeSetField(field, contents);
2375 return;
2376 } catch (Exception e) {
2377 Slog.wtf(TAG, e);
2378 return;
Paul Lawrencee51dcf92014-03-18 10:56:00 -07002379 }
2380 }
2381
2382 /**
2383 * Gets a field from the crypto header.
2384 * @param field field to get
2385 * @return contents of field
2386 */
2387 @Override
2388 public String getField(String field) throws RemoteException {
Paul Lawrence76a40572017-03-15 11:08:04 -07002389 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
Paul Lawrence0bbd1082016-04-26 15:21:02 -07002390 "no permission to access the crypt keeper");
Paul Lawrencee51dcf92014-03-18 10:56:00 -07002391
Jeff Sharkeyae266462017-11-27 13:32:24 -07002392 if (StorageManager.isFileEncryptedNativeOnly()) {
2393 // Not supported on FBE devices
2394 return null;
2395 }
2396
Paul Lawrencee51dcf92014-03-18 10:56:00 -07002397 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002398 return mVold.fdeGetField(field);
2399 } catch (Exception e) {
2400 Slog.wtf(TAG, e);
2401 return null;
Paul Lawrencee51dcf92014-03-18 10:56:00 -07002402 }
2403 }
2404
Paul Lawrence3806d9c2015-10-29 10:30:46 -07002405 /**
2406 * Is userdata convertible to file based encryption?
2407 * @return non zero for convertible
2408 */
2409 @Override
2410 public boolean isConvertibleToFBE() 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 Lawrence3806d9c2015-10-29 10:30:46 -07002413
Paul Lawrence3806d9c2015-10-29 10:30:46 -07002414 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002415 return mVold.isConvertibleToFbe();
2416 } catch (Exception e) {
2417 Slog.wtf(TAG, e);
2418 return false;
Paul Lawrence3806d9c2015-10-29 10:30:46 -07002419 }
2420 }
2421
Jeff Sharkeyb049e212012-09-07 23:16:01 -07002422 @Override
Paul Lawrence945490c2014-03-27 16:37:28 +00002423 public String getPassword() throws RemoteException {
Paul Lawrence76a40572017-03-15 11:08:04 -07002424 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
Rubin Xucd7a0142015-04-17 23:45:27 +01002425 "only keyguard can retrieve password");
Paul Lawrence0bbd1082016-04-26 15:21:02 -07002426
Paul Lawrence945490c2014-03-27 16:37:28 +00002427 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002428 return mVold.fdeGetPassword();
2429 } catch (Exception e) {
2430 Slog.wtf(TAG, e);
Paul Lawrence24063b52015-01-06 13:11:23 -08002431 return null;
Paul Lawrence945490c2014-03-27 16:37:28 +00002432 }
2433 }
2434
2435 @Override
2436 public void clearPassword() throws RemoteException {
Paul Lawrence76a40572017-03-15 11:08:04 -07002437 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
Paul Lawrence0bbd1082016-04-26 15:21:02 -07002438 "only keyguard can clear password");
2439
Paul Lawrence945490c2014-03-27 16:37:28 +00002440 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002441 mVold.fdeClearPassword();
2442 return;
2443 } catch (Exception e) {
2444 Slog.wtf(TAG, e);
2445 return;
Paul Lawrence945490c2014-03-27 16:37:28 +00002446 }
2447 }
2448
2449 @Override
Lenka Trochtovac4dd0212015-11-18 12:22:06 +01002450 public void createUserKey(int userId, int serialNumber, boolean ephemeral) {
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002451 enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
Paul Crowleybcf48ed2015-04-22 13:36:59 +01002452
Paul Crowleybcf48ed2015-04-22 13:36:59 +01002453 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002454 mVold.createUserKey(userId, serialNumber, ephemeral);
Jeff Sharkey43e12112017-09-12 16:31:45 -06002455 } catch (Exception e) {
2456 Slog.wtf(TAG, e);
Paul Crowleybcf48ed2015-04-22 13:36:59 +01002457 }
2458 }
2459
Paul Crowley7ec733f2015-05-19 12:42:00 +01002460 @Override
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002461 public void destroyUserKey(int userId) {
2462 enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
Paul Crowley7ec733f2015-05-19 12:42:00 +01002463
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002464 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002465 mVold.destroyUserKey(userId);
Jeff Sharkey43e12112017-09-12 16:31:45 -06002466 } catch (Exception e) {
2467 Slog.wtf(TAG, e);
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002468 }
2469 }
2470
Jeff Sharkey43e12112017-09-12 16:31:45 -06002471 private String encodeBytes(byte[] bytes) {
Paul Crowleyfaeb3eb2016-02-08 15:58:29 +00002472 if (ArrayUtils.isEmpty(bytes)) {
Jeff Sharkey43e12112017-09-12 16:31:45 -06002473 return "!";
Paul Crowleyfaeb3eb2016-02-08 15:58:29 +00002474 } else {
Jeff Sharkey43e12112017-09-12 16:31:45 -06002475 return HexDump.toHexString(bytes);
Paul Crowleyfaeb3eb2016-02-08 15:58:29 +00002476 }
2477 }
2478
Paul Crowleycc701552016-05-17 14:18:49 -07002479 /*
2480 * Add this token/secret pair to the set of ways we can recover a disk encryption key.
2481 * Changing the token/secret for a disk encryption key is done in two phases: first, adding
2482 * a new token/secret pair with this call, then delting all other pairs with
2483 * fixateNewestUserKeyAuth. This allows other places where a credential is used, such as
2484 * Gatekeeper, to be updated between the two calls.
2485 */
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002486 @Override
Paul Crowleycc701552016-05-17 14:18:49 -07002487 public void addUserKeyAuth(int userId, int serialNumber, byte[] token, byte[] secret) {
Paul Crowleyfaeb3eb2016-02-08 15:58:29 +00002488 enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
Paul Crowleyfaeb3eb2016-02-08 15:58:29 +00002489
2490 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002491 mVold.addUserKeyAuth(userId, serialNumber, encodeBytes(token), encodeBytes(secret));
Jeff Sharkey43e12112017-09-12 16:31:45 -06002492 } catch (Exception e) {
2493 Slog.wtf(TAG, e);
Paul Crowleycc701552016-05-17 14:18:49 -07002494 }
2495 }
2496
2497 /*
2498 * Delete all disk encryption token/secret pairs except the most recently added one
2499 */
2500 @Override
2501 public void fixateNewestUserKeyAuth(int userId) {
2502 enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
Paul Crowleycc701552016-05-17 14:18:49 -07002503
2504 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002505 mVold.fixateNewestUserKeyAuth(userId);
Jeff Sharkey43e12112017-09-12 16:31:45 -06002506 } catch (Exception e) {
2507 Slog.wtf(TAG, e);
Paul Crowleyfaeb3eb2016-02-08 15:58:29 +00002508 }
2509 }
2510
2511 @Override
2512 public void unlockUserKey(int userId, int serialNumber, byte[] token, byte[] secret) {
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002513 enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002514
Jeff Sharkeyce18c812016-04-27 16:00:41 -06002515 if (StorageManager.isFileEncryptedNativeOrEmulated()) {
Rubin Xu3bf722a2016-12-15 16:07:38 +00002516 // When a user has secure lock screen, require secret to actually unlock.
2517 // This check is mostly in place for emulation mode.
2518 if (mLockPatternUtils.isSecure(userId) && ArrayUtils.isEmpty(secret)) {
2519 throw new IllegalStateException("Secret required to unlock secure user " + userId);
Jeff Sharkeyce18c812016-04-27 16:00:41 -06002520 }
Jeff Sharkeyb9fe5372015-12-03 15:23:08 -07002521
Jeff Sharkeyce18c812016-04-27 16:00:41 -06002522 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002523 mVold.unlockUserKey(userId, serialNumber, encodeBytes(token),
2524 encodeBytes(secret));
Jeff Sharkey43e12112017-09-12 16:31:45 -06002525 } catch (Exception e) {
2526 Slog.wtf(TAG, e);
2527 return;
Jeff Sharkeyce18c812016-04-27 16:00:41 -06002528 }
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002529 }
2530
2531 synchronized (mLock) {
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07002532 mLocalUnlockedUsers = ArrayUtils.appendInt(mLocalUnlockedUsers, userId);
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002533 }
Paul Crowley9139a782017-07-26 13:29:25 -07002534 if (userId == UserHandle.USER_SYSTEM) {
2535 String propertyName = "sys.user." + userId + ".ce_available";
2536 Slog.d(TAG, "Setting property: " + propertyName + "=true");
2537 SystemProperties.set(propertyName, "true");
2538 }
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002539 }
2540
2541 @Override
2542 public void lockUserKey(int userId) {
2543 enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002544
2545 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002546 mVold.lockUserKey(userId);
Jeff Sharkey43e12112017-09-12 16:31:45 -06002547 } catch (Exception e) {
2548 Slog.wtf(TAG, e);
2549 return;
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002550 }
2551
2552 synchronized (mLock) {
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07002553 mLocalUnlockedUsers = ArrayUtils.removeInt(mLocalUnlockedUsers, userId);
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002554 }
2555 }
2556
2557 @Override
2558 public boolean isUserKeyUnlocked(int userId) {
Jeff Sharkeyce18c812016-04-27 16:00:41 -06002559 synchronized (mLock) {
2560 return ArrayUtils.contains(mLocalUnlockedUsers, userId);
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002561 }
2562 }
2563
2564 @Override
Jeff Sharkey47f71082016-02-01 17:03:54 -07002565 public void prepareUserStorage(String volumeUuid, int userId, int serialNumber, int flags) {
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002566 enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002567
2568 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002569 mVold.prepareUserStorage(volumeUuid, userId, serialNumber, flags);
Jeff Sharkey43e12112017-09-12 16:31:45 -06002570 } catch (Exception e) {
2571 Slog.wtf(TAG, e);
Paul Crowley7ec733f2015-05-19 12:42:00 +01002572 }
2573 }
2574
Paul Crowleybcf48ed2015-04-22 13:36:59 +01002575 @Override
Jeff Sharkeyfcf1e552016-04-14 20:44:58 -06002576 public void destroyUserStorage(String volumeUuid, int userId, int flags) {
2577 enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
Jeff Sharkeyfcf1e552016-04-14 20:44:58 -06002578
2579 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002580 mVold.destroyUserStorage(volumeUuid, userId, flags);
Jeff Sharkey43e12112017-09-12 16:31:45 -06002581 } catch (Exception e) {
2582 Slog.wtf(TAG, e);
Jeff Sharkeyfcf1e552016-04-14 20:44:58 -06002583 }
2584 }
2585
Daichi Hironoe56740d2017-02-02 13:56:45 +09002586 class AppFuseMountScope extends AppFuseBridge.MountScope {
Daichi Hirono812c95d2017-02-08 16:20:20 +09002587 boolean opened = false;
2588
2589 public AppFuseMountScope(int uid, int pid, int mountId) {
2590 super(uid, pid, mountId);
2591 }
2592
2593 @Override
2594 public ParcelFileDescriptor open() throws NativeDaemonConnectorException {
Jeff Sharkey54402792017-09-15 16:05:19 -06002595 try {
2596 return new ParcelFileDescriptor(
2597 mVold.mountAppFuse(uid, Process.myPid(), mountId));
2598 } catch (Exception e) {
2599 throw new NativeDaemonConnectorException("Failed to mount", e);
Daichi Hirono812c95d2017-02-08 16:20:20 +09002600 }
Daichi Hirono9fb00182016-11-08 14:12:17 +09002601 }
2602
2603 @Override
Daichi Hironoe56740d2017-02-02 13:56:45 +09002604 public void close() throws Exception {
Daichi Hirono812c95d2017-02-08 16:20:20 +09002605 if (opened) {
Jeff Sharkey54402792017-09-15 16:05:19 -06002606 mVold.unmountAppFuse(uid, Process.myPid(), mountId);
Daichi Hirono812c95d2017-02-08 16:20:20 +09002607 opened = false;
2608 }
Daichi Hirono9fb00182016-11-08 14:12:17 +09002609 }
2610 }
2611
2612 @Override
Daichi Hirono812c95d2017-02-08 16:20:20 +09002613 public @Nullable AppFuseMount mountProxyFileDescriptorBridge() {
Daichi Hironoe56740d2017-02-02 13:56:45 +09002614 Slog.v(TAG, "mountProxyFileDescriptorBridge");
Daichi Hirono9fb00182016-11-08 14:12:17 +09002615 final int uid = Binder.getCallingUid();
2616 final int pid = Binder.getCallingPid();
Daichi Hirono9fb00182016-11-08 14:12:17 +09002617
Daichi Hironoe56740d2017-02-02 13:56:45 +09002618 while (true) {
2619 synchronized (mAppFuseLock) {
2620 boolean newlyCreated = false;
2621 if (mAppFuseBridge == null) {
2622 mAppFuseBridge = new AppFuseBridge();
2623 new Thread(mAppFuseBridge, AppFuseBridge.TAG).start();
2624 newlyCreated = true;
Daichi Hirono9fb00182016-11-08 14:12:17 +09002625 }
Daichi Hironoe56740d2017-02-02 13:56:45 +09002626 try {
2627 final int name = mNextAppFuseName++;
2628 try {
2629 return new AppFuseMount(
Daichi Hirono812c95d2017-02-08 16:20:20 +09002630 name, mAppFuseBridge.addBridge(new AppFuseMountScope(uid, pid, name)));
2631 } catch (FuseUnavailableMountException e) {
Daichi Hironoe56740d2017-02-02 13:56:45 +09002632 if (newlyCreated) {
2633 // If newly created bridge fails, it's a real error.
Daichi Hirono812c95d2017-02-08 16:20:20 +09002634 Slog.e(TAG, "", e);
2635 return null;
Daichi Hironoe56740d2017-02-02 13:56:45 +09002636 }
2637 // It seems the thread of mAppFuseBridge has already been terminated.
2638 mAppFuseBridge = null;
2639 }
2640 } catch (NativeDaemonConnectorException e) {
2641 throw e.rethrowAsParcelableException();
2642 }
Daichi Hirono9fb00182016-11-08 14:12:17 +09002643 }
Daichi Hirono9fb00182016-11-08 14:12:17 +09002644 }
2645 }
2646
2647 @Override
Daichi Hirono812c95d2017-02-08 16:20:20 +09002648 public @Nullable ParcelFileDescriptor openProxyFileDescriptor(
2649 int mountId, int fileId, int mode) {
2650 Slog.v(TAG, "mountProxyFileDescriptor");
Daichi Hirono9fb00182016-11-08 14:12:17 +09002651 final int pid = Binder.getCallingPid();
2652 try {
2653 synchronized (mAppFuseLock) {
Daichi Hironoe56740d2017-02-02 13:56:45 +09002654 if (mAppFuseBridge == null) {
Daichi Hirono812c95d2017-02-08 16:20:20 +09002655 Slog.e(TAG, "FuseBridge has not been created");
2656 return null;
Daichi Hirono9fb00182016-11-08 14:12:17 +09002657 }
Daichi Hironoe56740d2017-02-02 13:56:45 +09002658 return mAppFuseBridge.openFile(pid, mountId, fileId, mode);
Daichi Hirono9fb00182016-11-08 14:12:17 +09002659 }
Daichi Hirono812c95d2017-02-08 16:20:20 +09002660 } catch (FuseUnavailableMountException | InterruptedException error) {
2661 Slog.v(TAG, "The mount point has already been invalid", error);
2662 return null;
Daichi Hirono9fb00182016-11-08 14:12:17 +09002663 }
2664 }
2665
Daichi Hirono9e8d9e22015-11-13 14:37:00 +09002666 @Override
Jeff Sharkeyae266462017-11-27 13:32:24 -07002667 public void mkdirs(String callingPkg, String appPath) {
Jeff Sharkey2d8b4e82013-09-17 17:30:33 -07002668 final int userId = UserHandle.getUserId(Binder.getCallingUid());
2669 final UserEnvironment userEnv = new UserEnvironment(userId);
2670
Jeff Sharkey196c7552018-03-26 15:56:50 -06002671 // Ignore requests to create directories while storage is locked
2672 if (!isUserKeyUnlocked(userId)) return;
2673
Jeff Sharkey2d8b4e82013-09-17 17:30:33 -07002674 // Validate that reported package name belongs to caller
2675 final AppOpsManager appOps = (AppOpsManager) mContext.getSystemService(
2676 Context.APP_OPS_SERVICE);
2677 appOps.checkPackage(Binder.getCallingUid(), callingPkg);
2678
Jeff Sharkey48877892015-03-18 11:27:19 -07002679 File appFile = null;
Jeff Sharkey2d8b4e82013-09-17 17:30:33 -07002680 try {
Jeff Sharkey48877892015-03-18 11:27:19 -07002681 appFile = new File(appPath).getCanonicalFile();
Jeff Sharkey2d8b4e82013-09-17 17:30:33 -07002682 } catch (IOException e) {
Jeff Sharkeyae266462017-11-27 13:32:24 -07002683 throw new IllegalStateException("Failed to resolve " + appPath + ": " + e);
Jeff Sharkey2d8b4e82013-09-17 17:30:33 -07002684 }
2685
2686 // Try translating the app path into a vold path, but require that it
2687 // belong to the calling package.
Jeff Sharkey48877892015-03-18 11:27:19 -07002688 if (FileUtils.contains(userEnv.buildExternalStorageAppDataDirs(callingPkg), appFile) ||
2689 FileUtils.contains(userEnv.buildExternalStorageAppObbDirs(callingPkg), appFile) ||
2690 FileUtils.contains(userEnv.buildExternalStorageAppMediaDirs(callingPkg), appFile)) {
2691 appPath = appFile.getAbsolutePath();
2692 if (!appPath.endsWith("/")) {
2693 appPath = appPath + "/";
2694 }
2695
Jeff Sharkey2d8b4e82013-09-17 17:30:33 -07002696 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002697 mVold.mkdirs(appPath);
Jeff Sharkey27a108c2017-11-30 17:11:40 -07002698 return;
Jeff Sharkeyace874b2017-09-07 15:27:33 -06002699 } catch (Exception e) {
Jeff Sharkeyae266462017-11-27 13:32:24 -07002700 throw new IllegalStateException("Failed to prepare " + appPath + ": " + e);
Jeff Sharkey2d8b4e82013-09-17 17:30:33 -07002701 }
2702 }
2703
Jeff Sharkey48877892015-03-18 11:27:19 -07002704 throw new SecurityException("Invalid mkdirs path: " + appFile);
Jeff Sharkey2d8b4e82013-09-17 17:30:33 -07002705 }
2706
2707 @Override
Jeff Sharkey46349872015-07-28 10:49:47 -07002708 public StorageVolume[] getVolumeList(int uid, String packageName, int flags) {
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07002709 final int userId = UserHandle.getUserId(uid);
Jeff Sharkeyc02bfae2016-03-27 15:06:53 -06002710
Jeff Sharkey46349872015-07-28 10:49:47 -07002711 final boolean forWrite = (flags & StorageManager.FLAG_FOR_WRITE) != 0;
Jeff Sharkeyc02bfae2016-03-27 15:06:53 -06002712 final boolean realState = (flags & StorageManager.FLAG_REAL_STATE) != 0;
2713 final boolean includeInvisible = (flags & StorageManager.FLAG_INCLUDE_INVISIBLE) != 0;
Jeff Sharkey46349872015-07-28 10:49:47 -07002714
Jeff Sharkeyc02bfae2016-03-27 15:06:53 -06002715 final boolean userKeyUnlocked;
2716 final boolean storagePermission;
2717 final long token = Binder.clearCallingIdentity();
Svetoslav38c3dbb2015-07-14 11:27:06 -07002718 try {
Jeff Sharkeyc02bfae2016-03-27 15:06:53 -06002719 userKeyUnlocked = isUserKeyUnlocked(userId);
Sudheer Shanka2250d562016-11-07 15:41:02 -08002720 storagePermission = mStorageManagerInternal.hasExternalStorage(uid, packageName);
Svetoslav38c3dbb2015-07-14 11:27:06 -07002721 } finally {
Jeff Sharkeyc02bfae2016-03-27 15:06:53 -06002722 Binder.restoreCallingIdentity(token);
Svetoslav38c3dbb2015-07-14 11:27:06 -07002723 }
Svet Ganov6ee871e2015-07-10 14:29:33 -07002724
Jeff Sharkeyc02bfae2016-03-27 15:06:53 -06002725 boolean foundPrimary = false;
2726
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07002727 final ArrayList<StorageVolume> res = new ArrayList<>();
Jeff Sharkey48877892015-03-18 11:27:19 -07002728 synchronized (mLock) {
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07002729 for (int i = 0; i < mVolumes.size(); i++) {
2730 final VolumeInfo vol = mVolumes.valueAt(i);
Jeff Sharkeyc02bfae2016-03-27 15:06:53 -06002731 switch (vol.getType()) {
2732 case VolumeInfo.TYPE_PUBLIC:
2733 case VolumeInfo.TYPE_EMULATED:
2734 break;
2735 default:
2736 continue;
2737 }
2738
2739 boolean match = false;
2740 if (forWrite) {
2741 match = vol.isVisibleForWrite(userId);
2742 } else {
Felipe Leme123a0e72016-06-10 11:09:11 -07002743 match = vol.isVisibleForRead(userId)
2744 || (includeInvisible && vol.getPath() != null);
Jeff Sharkeyc02bfae2016-03-27 15:06:53 -06002745 }
2746 if (!match) continue;
2747
2748 boolean reportUnmounted = false;
2749 if ((vol.getType() == VolumeInfo.TYPE_EMULATED) && !userKeyUnlocked) {
2750 reportUnmounted = true;
2751 } else if (!storagePermission && !realState) {
2752 reportUnmounted = true;
2753 }
2754
2755 final StorageVolume userVol = vol.buildStorageVolume(mContext, userId,
2756 reportUnmounted);
2757 if (vol.isPrimary()) {
2758 res.add(0, userVol);
2759 foundPrimary = true;
2760 } else {
2761 res.add(userVol);
Jeff Sharkeyb049e212012-09-07 23:16:01 -07002762 }
Mike Lockwood8fa5f802011-03-24 08:12:30 -07002763 }
Mike Lockwood8fa5f802011-03-24 08:12:30 -07002764 }
Jeff Sharkey48877892015-03-18 11:27:19 -07002765
2766 if (!foundPrimary) {
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07002767 Log.w(TAG, "No primary storage defined yet; hacking together a stub");
Jeff Sharkey48877892015-03-18 11:27:19 -07002768
2769 final boolean primaryPhysical = SystemProperties.getBoolean(
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07002770 StorageManager.PROP_PRIMARY_PHYSICAL, false);
Jeff Sharkey48877892015-03-18 11:27:19 -07002771
2772 final String id = "stub_primary";
2773 final File path = Environment.getLegacyExternalStorageDirectory();
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07002774 final String description = mContext.getString(android.R.string.unknownName);
Jeff Sharkey48877892015-03-18 11:27:19 -07002775 final boolean primary = true;
2776 final boolean removable = primaryPhysical;
2777 final boolean emulated = !primaryPhysical;
Jeff Sharkey48877892015-03-18 11:27:19 -07002778 final boolean allowMassStorage = false;
2779 final long maxFileSize = 0L;
2780 final UserHandle owner = new UserHandle(userId);
2781 final String uuid = null;
Jeff Sharkey48877892015-03-18 11:27:19 -07002782 final String state = Environment.MEDIA_REMOVED;
2783
Jerry Zhangf9c5c252017-08-16 18:07:51 -07002784 res.add(0, new StorageVolume(id, path,
2785 description, primary, removable, emulated,
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07002786 allowMassStorage, maxFileSize, owner, uuid, state));
Jeff Sharkey48877892015-03-18 11:27:19 -07002787 }
2788
2789 return res.toArray(new StorageVolume[res.size()]);
Mike Lockwood8fa5f802011-03-24 08:12:30 -07002790 }
2791
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07002792 @Override
2793 public DiskInfo[] getDisks() {
2794 synchronized (mLock) {
2795 final DiskInfo[] res = new DiskInfo[mDisks.size()];
2796 for (int i = 0; i < mDisks.size(); i++) {
2797 res[i] = mDisks.valueAt(i);
2798 }
2799 return res;
2800 }
2801 }
2802
2803 @Override
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07002804 public VolumeInfo[] getVolumes(int flags) {
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07002805 synchronized (mLock) {
2806 final VolumeInfo[] res = new VolumeInfo[mVolumes.size()];
2807 for (int i = 0; i < mVolumes.size(); i++) {
2808 res[i] = mVolumes.valueAt(i);
2809 }
2810 return res;
2811 }
2812 }
2813
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07002814 @Override
2815 public VolumeRecord[] getVolumeRecords(int flags) {
2816 synchronized (mLock) {
2817 final VolumeRecord[] res = new VolumeRecord[mRecords.size()];
2818 for (int i = 0; i < mRecords.size(); i++) {
2819 res[i] = mRecords.valueAt(i);
2820 }
2821 return res;
2822 }
2823 }
2824
Jeff Sharkey9bed0702017-01-23 20:37:05 -07002825 @Override
2826 public long getCacheQuotaBytes(String volumeUuid, int uid) {
2827 if (uid != Binder.getCallingUid()) {
2828 mContext.enforceCallingPermission(android.Manifest.permission.STORAGE_INTERNAL, TAG);
2829 }
Daniel Nishi80fdb012017-03-09 14:30:07 -08002830 final long token = Binder.clearCallingIdentity();
2831 final StorageStatsManager stats = mContext.getSystemService(StorageStatsManager.class);
2832 try {
2833 return stats.getCacheQuotaBytes(volumeUuid, uid);
2834 } finally {
2835 Binder.restoreCallingIdentity(token);
2836 }
Jeff Sharkey9bed0702017-01-23 20:37:05 -07002837 }
2838
2839 @Override
2840 public long getCacheSizeBytes(String volumeUuid, int uid) {
2841 if (uid != Binder.getCallingUid()) {
2842 mContext.enforceCallingPermission(android.Manifest.permission.STORAGE_INTERNAL, TAG);
2843 }
2844 final long token = Binder.clearCallingIdentity();
2845 try {
2846 return mContext.getSystemService(StorageStatsManager.class)
2847 .queryStatsForUid(volumeUuid, uid).getCacheBytes();
Jeff Sharkey789a8fc2017-04-16 13:18:35 -06002848 } catch (IOException e) {
2849 throw new ParcelableException(e);
Jeff Sharkey9bed0702017-01-23 20:37:05 -07002850 } finally {
2851 Binder.restoreCallingIdentity(token);
2852 }
2853 }
2854
Jeff Sharkey35e46d22017-06-09 10:01:20 -06002855 private int adjustAllocateFlags(int flags, int callingUid, String callingPackage) {
2856 // Require permission to allocate aggressively
2857 if ((flags & StorageManager.FLAG_ALLOCATE_AGGRESSIVE) != 0) {
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07002858 mContext.enforceCallingOrSelfPermission(
2859 android.Manifest.permission.ALLOCATE_AGGRESSIVE, TAG);
2860 }
2861
Jeff Sharkey35e46d22017-06-09 10:01:20 -06002862 // Apps normally can't directly defy reserved space
2863 flags &= ~StorageManager.FLAG_ALLOCATE_DEFY_ALL_RESERVED;
2864 flags &= ~StorageManager.FLAG_ALLOCATE_DEFY_HALF_RESERVED;
2865
2866 // However, if app is actively using the camera, then we're willing to
2867 // clear up to half of the reserved cache space, since the user might be
2868 // trying to capture an important memory.
2869 final AppOpsManager appOps = mContext.getSystemService(AppOpsManager.class);
2870 final long token = Binder.clearCallingIdentity();
2871 try {
2872 if (appOps.isOperationActive(AppOpsManager.OP_CAMERA, callingUid, callingPackage)) {
2873 Slog.d(TAG, "UID " + callingUid + " is actively using camera;"
2874 + " letting them defy reserved cached data");
2875 flags |= StorageManager.FLAG_ALLOCATE_DEFY_HALF_RESERVED;
2876 }
2877 } finally {
2878 Binder.restoreCallingIdentity(token);
2879 }
2880
2881 return flags;
2882 }
2883
2884 @Override
2885 public long getAllocatableBytes(String volumeUuid, int flags, String callingPackage) {
2886 flags = adjustAllocateFlags(flags, Binder.getCallingUid(), callingPackage);
2887
2888 final StorageManager storage = mContext.getSystemService(StorageManager.class);
2889 final StorageStatsManager stats = mContext.getSystemService(StorageStatsManager.class);
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07002890 final long token = Binder.clearCallingIdentity();
2891 try {
2892 // In general, apps can allocate as much space as they want, except
2893 // we never let them eat into either the minimum cache space or into
Jeff Sharkeyddff8072017-05-26 13:10:46 -06002894 // the low disk warning space. To avoid user confusion, this logic
2895 // should be kept in sync with getFreeBytes().
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07002896 final File path = storage.findPathForUuid(volumeUuid);
Jeff Sharkeyddff8072017-05-26 13:10:46 -06002897
2898 final long usable = path.getUsableSpace();
2899 final long lowReserved = storage.getStorageLowBytes(path);
2900 final long fullReserved = storage.getStorageFullBytes(path);
2901
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07002902 if (stats.isQuotaSupported(volumeUuid)) {
Jeff Sharkeyddff8072017-05-26 13:10:46 -06002903 final long cacheTotal = stats.getCacheBytes(volumeUuid);
Jeff Sharkey35e46d22017-06-09 10:01:20 -06002904 final long cacheReserved = storage.getStorageCacheBytes(path, flags);
Jeff Sharkeyddff8072017-05-26 13:10:46 -06002905 final long cacheClearable = Math.max(0, cacheTotal - cacheReserved);
2906
Jeff Sharkey35e46d22017-06-09 10:01:20 -06002907 if ((flags & StorageManager.FLAG_ALLOCATE_AGGRESSIVE) != 0) {
2908 return Math.max(0, (usable + cacheClearable) - fullReserved);
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07002909 } else {
Jeff Sharkeyddff8072017-05-26 13:10:46 -06002910 return Math.max(0, (usable + cacheClearable) - lowReserved);
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07002911 }
2912 } else {
2913 // When we don't have fast quota information, we ignore cached
2914 // data and only consider unused bytes.
Jeff Sharkey35e46d22017-06-09 10:01:20 -06002915 if ((flags & StorageManager.FLAG_ALLOCATE_AGGRESSIVE) != 0) {
Jeff Sharkeyddff8072017-05-26 13:10:46 -06002916 return Math.max(0, usable - fullReserved);
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07002917 } else {
Jeff Sharkeyddff8072017-05-26 13:10:46 -06002918 return Math.max(0, usable - lowReserved);
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07002919 }
2920 }
Jeff Sharkey789a8fc2017-04-16 13:18:35 -06002921 } catch (IOException e) {
2922 throw new ParcelableException(e);
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07002923 } finally {
2924 Binder.restoreCallingIdentity(token);
2925 }
Jeff Sharkey500ce9e2017-02-12 02:39:24 -07002926 }
2927
2928 @Override
Jeff Sharkey35e46d22017-06-09 10:01:20 -06002929 public void allocateBytes(String volumeUuid, long bytes, int flags, String callingPackage) {
2930 flags = adjustAllocateFlags(flags, Binder.getCallingUid(), callingPackage);
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07002931
Jeff Sharkey35e46d22017-06-09 10:01:20 -06002932 final long allocatableBytes = getAllocatableBytes(volumeUuid, flags, callingPackage);
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07002933 if (bytes > allocatableBytes) {
2934 throw new ParcelableException(new IOException("Failed to allocate " + bytes
2935 + " because only " + allocatableBytes + " allocatable"));
2936 }
2937
Jeff Sharkey35e46d22017-06-09 10:01:20 -06002938 final StorageManager storage = mContext.getSystemService(StorageManager.class);
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07002939 final long token = Binder.clearCallingIdentity();
2940 try {
Jeff Sharkey789a8fc2017-04-16 13:18:35 -06002941 // Free up enough disk space to satisfy both the requested allocation
2942 // and our low disk warning space.
2943 final File path = storage.findPathForUuid(volumeUuid);
Jeff Sharkeyddff8072017-05-26 13:10:46 -06002944 if ((flags & StorageManager.FLAG_ALLOCATE_AGGRESSIVE) != 0) {
2945 bytes += storage.getStorageFullBytes(path);
2946 } else {
2947 bytes += storage.getStorageLowBytes(path);
2948 }
Jeff Sharkey789a8fc2017-04-16 13:18:35 -06002949
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07002950 mPms.freeStorage(volumeUuid, bytes, flags);
2951 } catch (IOException e) {
2952 throw new ParcelableException(e);
2953 } finally {
2954 Binder.restoreCallingIdentity(token);
Jeff Sharkey500ce9e2017-02-12 02:39:24 -07002955 }
2956 }
2957
Kenny Rootaf9d6672010-10-08 09:21:39 -07002958 private void addObbStateLocked(ObbState obbState) throws RemoteException {
2959 final IBinder binder = obbState.getBinder();
2960 List<ObbState> obbStates = mObbMounts.get(binder);
Kenny Root5919ac62010-10-05 09:49:40 -07002961
Kenny Rootaf9d6672010-10-08 09:21:39 -07002962 if (obbStates == null) {
2963 obbStates = new ArrayList<ObbState>();
2964 mObbMounts.put(binder, obbStates);
2965 } else {
2966 for (final ObbState o : obbStates) {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002967 if (o.rawPath.equals(obbState.rawPath)) {
Kenny Rootaf9d6672010-10-08 09:21:39 -07002968 throw new IllegalStateException("Attempt to add ObbState twice. "
Sudheer Shanka2250d562016-11-07 15:41:02 -08002969 + "This indicates an error in the StorageManagerService logic.");
Kenny Root5919ac62010-10-05 09:49:40 -07002970 }
2971 }
Kenny Roota02b8b02010-08-05 16:14:17 -07002972 }
Kenny Rootaf9d6672010-10-08 09:21:39 -07002973
2974 obbStates.add(obbState);
2975 try {
2976 obbState.link();
2977 } catch (RemoteException e) {
2978 /*
2979 * The binder died before we could link it, so clean up our state
2980 * and return failure.
2981 */
2982 obbStates.remove(obbState);
2983 if (obbStates.isEmpty()) {
2984 mObbMounts.remove(binder);
2985 }
2986
2987 // Rethrow the error so mountObb can get it
2988 throw e;
2989 }
2990
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002991 mObbPathToStateMap.put(obbState.rawPath, obbState);
Kenny Roota02b8b02010-08-05 16:14:17 -07002992 }
2993
Kenny Rootaf9d6672010-10-08 09:21:39 -07002994 private void removeObbStateLocked(ObbState obbState) {
2995 final IBinder binder = obbState.getBinder();
2996 final List<ObbState> obbStates = mObbMounts.get(binder);
2997 if (obbStates != null) {
2998 if (obbStates.remove(obbState)) {
2999 obbState.unlink();
Kenny Root05105f72010-09-22 17:29:43 -07003000 }
Kenny Rootaf9d6672010-10-08 09:21:39 -07003001 if (obbStates.isEmpty()) {
3002 mObbMounts.remove(binder);
3003 }
Kenny Roota02b8b02010-08-05 16:14:17 -07003004 }
Kenny Roota02b8b02010-08-05 16:14:17 -07003005
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003006 mObbPathToStateMap.remove(obbState.rawPath);
Kenny Root38cf8862010-09-26 14:18:51 -07003007 }
3008
Kenny Roota02b8b02010-08-05 16:14:17 -07003009 private class ObbActionHandler extends Handler {
3010 private boolean mBound = false;
Kenny Root480afe72010-10-07 10:17:50 -07003011 private final List<ObbAction> mActions = new LinkedList<ObbAction>();
Kenny Roota02b8b02010-08-05 16:14:17 -07003012
3013 ObbActionHandler(Looper l) {
3014 super(l);
3015 }
3016
3017 @Override
3018 public void handleMessage(Message msg) {
3019 switch (msg.what) {
3020 case OBB_RUN_ACTION: {
Kenny Root480afe72010-10-07 10:17:50 -07003021 final ObbAction action = (ObbAction) msg.obj;
Kenny Roota02b8b02010-08-05 16:14:17 -07003022
3023 if (DEBUG_OBB)
3024 Slog.i(TAG, "OBB_RUN_ACTION: " + action.toString());
3025
3026 // If a bind was already initiated we don't really
3027 // need to do anything. The pending install
3028 // will be processed later on.
3029 if (!mBound) {
3030 // If this is the only one pending we might
3031 // have to bind to the service again.
3032 if (!connectToService()) {
Jeff Sharkey0095a822018-02-15 13:06:53 -07003033 action.notifyObbStateChange(new ObbException(ERROR_INTERNAL,
3034 "Failed to bind to media container service"));
Kenny Roota02b8b02010-08-05 16:14:17 -07003035 return;
Kenny Roota02b8b02010-08-05 16:14:17 -07003036 }
Kenny Roota02b8b02010-08-05 16:14:17 -07003037 }
Kenny Root735de3b2010-09-30 14:11:39 -07003038
Kenny Root735de3b2010-09-30 14:11:39 -07003039 mActions.add(action);
Kenny Roota02b8b02010-08-05 16:14:17 -07003040 break;
3041 }
3042 case OBB_MCS_BOUND: {
3043 if (DEBUG_OBB)
3044 Slog.i(TAG, "OBB_MCS_BOUND");
3045 if (msg.obj != null) {
3046 mContainerService = (IMediaContainerService) msg.obj;
3047 }
3048 if (mContainerService == null) {
3049 // Something seriously wrong. Bail out
Kenny Roota02b8b02010-08-05 16:14:17 -07003050 for (ObbAction action : mActions) {
3051 // Indicate service bind error
Jeff Sharkey0095a822018-02-15 13:06:53 -07003052 action.notifyObbStateChange(new ObbException(ERROR_INTERNAL,
3053 "Failed to bind to media container service"));
Kenny Roota02b8b02010-08-05 16:14:17 -07003054 }
3055 mActions.clear();
3056 } else if (mActions.size() > 0) {
Kenny Root480afe72010-10-07 10:17:50 -07003057 final ObbAction action = mActions.get(0);
Kenny Roota02b8b02010-08-05 16:14:17 -07003058 if (action != null) {
3059 action.execute(this);
3060 }
3061 } else {
3062 // Should never happen ideally.
3063 Slog.w(TAG, "Empty queue");
3064 }
3065 break;
3066 }
3067 case OBB_MCS_RECONNECT: {
3068 if (DEBUG_OBB)
3069 Slog.i(TAG, "OBB_MCS_RECONNECT");
3070 if (mActions.size() > 0) {
3071 if (mBound) {
3072 disconnectService();
3073 }
3074 if (!connectToService()) {
Kenny Roota02b8b02010-08-05 16:14:17 -07003075 for (ObbAction action : mActions) {
3076 // Indicate service bind error
Jeff Sharkey0095a822018-02-15 13:06:53 -07003077 action.notifyObbStateChange(new ObbException(ERROR_INTERNAL,
3078 "Failed to bind to media container service"));
Kenny Roota02b8b02010-08-05 16:14:17 -07003079 }
3080 mActions.clear();
3081 }
3082 }
3083 break;
3084 }
3085 case OBB_MCS_UNBIND: {
3086 if (DEBUG_OBB)
3087 Slog.i(TAG, "OBB_MCS_UNBIND");
3088
3089 // Delete pending install
3090 if (mActions.size() > 0) {
3091 mActions.remove(0);
3092 }
3093 if (mActions.size() == 0) {
3094 if (mBound) {
3095 disconnectService();
3096 }
3097 } else {
3098 // There are more pending requests in queue.
3099 // Just post MCS_BOUND message to trigger processing
3100 // of next pending install.
3101 mObbActionHandler.sendEmptyMessage(OBB_MCS_BOUND);
3102 }
3103 break;
3104 }
Kenny Rootaf9d6672010-10-08 09:21:39 -07003105 case OBB_FLUSH_MOUNT_STATE: {
3106 final String path = (String) msg.obj;
3107
3108 if (DEBUG_OBB)
3109 Slog.i(TAG, "Flushing all OBB state for path " + path);
3110
3111 synchronized (mObbMounts) {
3112 final List<ObbState> obbStatesToRemove = new LinkedList<ObbState>();
3113
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003114 final Iterator<ObbState> i = mObbPathToStateMap.values().iterator();
Kenny Rootaf9d6672010-10-08 09:21:39 -07003115 while (i.hasNext()) {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003116 final ObbState state = i.next();
Kenny Rootaf9d6672010-10-08 09:21:39 -07003117
3118 /*
3119 * If this entry's source file is in the volume path
3120 * that got unmounted, remove it because it's no
3121 * longer valid.
3122 */
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003123 if (state.canonicalPath.startsWith(path)) {
3124 obbStatesToRemove.add(state);
Kenny Rootaf9d6672010-10-08 09:21:39 -07003125 }
3126 }
3127
3128 for (final ObbState obbState : obbStatesToRemove) {
3129 if (DEBUG_OBB)
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003130 Slog.i(TAG, "Removing state for " + obbState.rawPath);
Kenny Rootaf9d6672010-10-08 09:21:39 -07003131
3132 removeObbStateLocked(obbState);
3133
3134 try {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003135 obbState.token.onObbResult(obbState.rawPath, obbState.nonce,
Kenny Rootaf9d6672010-10-08 09:21:39 -07003136 OnObbStateChangeListener.UNMOUNTED);
3137 } catch (RemoteException e) {
3138 Slog.i(TAG, "Couldn't send unmount notification for OBB: "
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003139 + obbState.rawPath);
Kenny Rootaf9d6672010-10-08 09:21:39 -07003140 }
3141 }
3142 }
3143 break;
3144 }
Kenny Roota02b8b02010-08-05 16:14:17 -07003145 }
3146 }
3147
3148 private boolean connectToService() {
3149 if (DEBUG_OBB)
3150 Slog.i(TAG, "Trying to bind to DefaultContainerService");
3151
3152 Intent service = new Intent().setComponent(DEFAULT_CONTAINER_COMPONENT);
Jeff Sharkey6dce4962015-07-03 18:08:41 -07003153 if (mContext.bindServiceAsUser(service, mDefContainerConn, Context.BIND_AUTO_CREATE,
Xiaohui Chene4de5a02015-09-22 15:33:31 -07003154 UserHandle.SYSTEM)) {
Kenny Roota02b8b02010-08-05 16:14:17 -07003155 mBound = true;
3156 return true;
3157 }
3158 return false;
3159 }
3160
3161 private void disconnectService() {
3162 mContainerService = null;
3163 mBound = false;
3164 mContext.unbindService(mDefContainerConn);
3165 }
3166 }
3167
Jeff Sharkey0095a822018-02-15 13:06:53 -07003168 private static class ObbException extends Exception {
3169 public final int status;
3170
3171 public ObbException(int status, String message) {
3172 super(message);
3173 this.status = status;
3174 }
3175
3176 public ObbException(int status, Throwable cause) {
3177 super(cause.getMessage(), cause);
3178 this.status = status;
3179 }
3180 }
3181
Kenny Roota02b8b02010-08-05 16:14:17 -07003182 abstract class ObbAction {
3183 private static final int MAX_RETRIES = 3;
3184 private int mRetries;
3185
3186 ObbState mObbState;
3187
3188 ObbAction(ObbState obbState) {
3189 mObbState = obbState;
3190 }
3191
3192 public void execute(ObbActionHandler handler) {
3193 try {
3194 if (DEBUG_OBB)
Ben Komalo444eca22011-09-01 15:17:44 -07003195 Slog.i(TAG, "Starting to execute action: " + toString());
Kenny Roota02b8b02010-08-05 16:14:17 -07003196 mRetries++;
3197 if (mRetries > MAX_RETRIES) {
Kenny Root480afe72010-10-07 10:17:50 -07003198 mObbActionHandler.sendEmptyMessage(OBB_MCS_UNBIND);
Jeff Sharkey0095a822018-02-15 13:06:53 -07003199 notifyObbStateChange(new ObbException(ERROR_INTERNAL,
3200 "Failed to bind to media container service"));
Kenny Roota02b8b02010-08-05 16:14:17 -07003201 } else {
3202 handleExecute();
3203 if (DEBUG_OBB)
3204 Slog.i(TAG, "Posting install MCS_UNBIND");
3205 mObbActionHandler.sendEmptyMessage(OBB_MCS_UNBIND);
3206 }
Jeff Sharkey0095a822018-02-15 13:06:53 -07003207 } catch (ObbException e) {
3208 notifyObbStateChange(e);
Kenny Root17eb6fb2010-10-06 15:02:52 -07003209 mObbActionHandler.sendEmptyMessage(OBB_MCS_UNBIND);
Kenny Roota02b8b02010-08-05 16:14:17 -07003210 }
3211 }
3212
Jeff Sharkey0095a822018-02-15 13:06:53 -07003213 abstract void handleExecute() throws ObbException;
Kenny Root38cf8862010-09-26 14:18:51 -07003214
Jeff Sharkey0095a822018-02-15 13:06:53 -07003215 protected ObbInfo getObbInfo() throws ObbException {
3216 final ObbInfo obbInfo;
Kenny Root38cf8862010-09-26 14:18:51 -07003217 try {
Xiaohui Chen621b3fc2015-10-02 14:41:42 -07003218 obbInfo = mContainerService.getObbInfo(mObbState.canonicalPath);
Jeff Sharkey0095a822018-02-15 13:06:53 -07003219 } catch (Exception e) {
3220 throw new ObbException(ERROR_PERMISSION_DENIED, e);
Kenny Root38cf8862010-09-26 14:18:51 -07003221 }
Jeff Sharkey0095a822018-02-15 13:06:53 -07003222 if (obbInfo != null) {
3223 return obbInfo;
3224 } else {
3225 throw new ObbException(ERROR_INTERNAL,
3226 "Missing OBB info for: " + mObbState.canonicalPath);
Kenny Root38cf8862010-09-26 14:18:51 -07003227 }
Kenny Root38cf8862010-09-26 14:18:51 -07003228 }
3229
Jeff Sharkey0095a822018-02-15 13:06:53 -07003230 protected void notifyObbStateChange(ObbException e) {
3231 Slog.w(TAG, e);
3232 notifyObbStateChange(e.status);
3233 }
3234
3235 protected void notifyObbStateChange(int status) {
Kenny Rootaf9d6672010-10-08 09:21:39 -07003236 if (mObbState == null || mObbState.token == null) {
3237 return;
3238 }
3239
Kenny Root38cf8862010-09-26 14:18:51 -07003240 try {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003241 mObbState.token.onObbResult(mObbState.rawPath, mObbState.nonce, status);
Kenny Root38cf8862010-09-26 14:18:51 -07003242 } catch (RemoteException e) {
Sudheer Shanka2250d562016-11-07 15:41:02 -08003243 Slog.w(TAG, "StorageEventListener went away while calling onObbStateChanged");
Kenny Root38cf8862010-09-26 14:18:51 -07003244 }
3245 }
Kenny Roota02b8b02010-08-05 16:14:17 -07003246 }
3247
3248 class MountObbAction extends ObbAction {
Ben Komalo444eca22011-09-01 15:17:44 -07003249 private final String mKey;
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003250 private final int mCallingUid;
Kenny Roota02b8b02010-08-05 16:14:17 -07003251
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003252 MountObbAction(ObbState obbState, String key, int callingUid) {
Kenny Roota02b8b02010-08-05 16:14:17 -07003253 super(obbState);
3254 mKey = key;
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003255 mCallingUid = callingUid;
Kenny Roota02b8b02010-08-05 16:14:17 -07003256 }
3257
Jason parks5af0b912010-11-29 09:05:25 -06003258 @Override
Jeff Sharkey0095a822018-02-15 13:06:53 -07003259 public void handleExecute() throws ObbException {
Kenny Rootaf9d6672010-10-08 09:21:39 -07003260 warnOnNotMounted();
3261
Kenny Root38cf8862010-09-26 14:18:51 -07003262 final ObbInfo obbInfo = getObbInfo();
3263
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003264 if (!isUidOwnerOfPackageOrSystem(obbInfo.packageName, mCallingUid)) {
Jeff Sharkey0095a822018-02-15 13:06:53 -07003265 throw new ObbException(ERROR_PERMISSION_DENIED, "Denied attempt to mount OBB "
3266 + obbInfo.filename + " which is owned by " + obbInfo.packageName);
Kenny Roota02b8b02010-08-05 16:14:17 -07003267 }
3268
Kenny Rootaf9d6672010-10-08 09:21:39 -07003269 final boolean isMounted;
3270 synchronized (mObbMounts) {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003271 isMounted = mObbPathToStateMap.containsKey(mObbState.rawPath);
Kenny Rootaf9d6672010-10-08 09:21:39 -07003272 }
3273 if (isMounted) {
Jeff Sharkey0095a822018-02-15 13:06:53 -07003274 throw new ObbException(ERROR_ALREADY_MOUNTED,
3275 "Attempt to mount OBB which is already mounted: " + obbInfo.filename);
Kenny Rootaf9d6672010-10-08 09:21:39 -07003276 }
3277
Kenny Rootaf9d6672010-10-08 09:21:39 -07003278 final String hashedKey;
Jeff Sharkey41cd6812017-09-11 10:32:17 -06003279 final String binderKey;
Kenny Rootaf9d6672010-10-08 09:21:39 -07003280 if (mKey == null) {
3281 hashedKey = "none";
Jeff Sharkey41cd6812017-09-11 10:32:17 -06003282 binderKey = "";
Kenny Rootaf9d6672010-10-08 09:21:39 -07003283 } else {
Kenny Rootaf9d6672010-10-08 09:21:39 -07003284 try {
Kenny Root3b1abba2010-10-13 15:00:07 -07003285 SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
3286
3287 KeySpec ks = new PBEKeySpec(mKey.toCharArray(), obbInfo.salt,
3288 PBKDF2_HASH_ROUNDS, CRYPTO_ALGORITHM_KEY_SIZE);
3289 SecretKey key = factory.generateSecret(ks);
3290 BigInteger bi = new BigInteger(key.getEncoded());
3291 hashedKey = bi.toString(16);
Jeff Sharkey41cd6812017-09-11 10:32:17 -06003292 binderKey = hashedKey;
Jeff Sharkey0095a822018-02-15 13:06:53 -07003293 } catch (GeneralSecurityException e) {
3294 throw new ObbException(ERROR_INTERNAL, e);
Kenny Root38cf8862010-09-26 14:18:51 -07003295 }
Kenny Rootaf9d6672010-10-08 09:21:39 -07003296 }
Kenny Root38cf8862010-09-26 14:18:51 -07003297
Kenny Rootaf9d6672010-10-08 09:21:39 -07003298 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06003299 mObbState.volId = mVold.createObb(mObbState.canonicalPath, binderKey,
3300 mObbState.ownerGid);
3301 mVold.mount(mObbState.volId, 0, -1);
Kenny Roota02b8b02010-08-05 16:14:17 -07003302
Kenny Rootaf9d6672010-10-08 09:21:39 -07003303 if (DEBUG_OBB)
Xiaohui Chen621b3fc2015-10-02 14:41:42 -07003304 Slog.d(TAG, "Successfully mounted OBB " + mObbState.canonicalPath);
Kenny Rootaf9d6672010-10-08 09:21:39 -07003305
3306 synchronized (mObbMounts) {
3307 addObbStateLocked(mObbState);
3308 }
3309
Jeff Sharkey0095a822018-02-15 13:06:53 -07003310 notifyObbStateChange(MOUNTED);
3311 } catch (Exception e) {
3312 throw new ObbException(ERROR_COULD_NOT_MOUNT, e);
Kenny Root02c87302010-07-01 08:10:18 -07003313 }
3314 }
3315
Jason parks5af0b912010-11-29 09:05:25 -06003316 @Override
Kenny Roota02b8b02010-08-05 16:14:17 -07003317 public String toString() {
3318 StringBuilder sb = new StringBuilder();
3319 sb.append("MountObbAction{");
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003320 sb.append(mObbState);
Kenny Roota02b8b02010-08-05 16:14:17 -07003321 sb.append('}');
3322 return sb.toString();
3323 }
3324 }
3325
3326 class UnmountObbAction extends ObbAction {
Ben Komalo444eca22011-09-01 15:17:44 -07003327 private final boolean mForceUnmount;
Kenny Roota02b8b02010-08-05 16:14:17 -07003328
3329 UnmountObbAction(ObbState obbState, boolean force) {
3330 super(obbState);
3331 mForceUnmount = force;
3332 }
3333
Jason parks5af0b912010-11-29 09:05:25 -06003334 @Override
Jeff Sharkey0095a822018-02-15 13:06:53 -07003335 public void handleExecute() throws ObbException {
Kenny Rootaf9d6672010-10-08 09:21:39 -07003336 warnOnNotMounted();
3337
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003338 final ObbState existingState;
Kenny Root38cf8862010-09-26 14:18:51 -07003339 synchronized (mObbMounts) {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003340 existingState = mObbPathToStateMap.get(mObbState.rawPath);
Kenny Rootaf9d6672010-10-08 09:21:39 -07003341 }
Kenny Root38cf8862010-09-26 14:18:51 -07003342
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003343 if (existingState == null) {
Jeff Sharkey0095a822018-02-15 13:06:53 -07003344 throw new ObbException(ERROR_NOT_MOUNTED, "Missing existingState");
Kenny Rootaf9d6672010-10-08 09:21:39 -07003345 }
3346
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003347 if (existingState.ownerGid != mObbState.ownerGid) {
Jeff Sharkey0095a822018-02-15 13:06:53 -07003348 notifyObbStateChange(new ObbException(ERROR_PERMISSION_DENIED,
3349 "Permission denied to unmount OBB " + existingState.rawPath
3350 + " (owned by GID " + existingState.ownerGid + ")"));
Kenny Rootaf9d6672010-10-08 09:21:39 -07003351 return;
3352 }
3353
Kenny Rootaf9d6672010-10-08 09:21:39 -07003354 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06003355 mVold.unmount(mObbState.volId);
3356 mVold.destroyObb(mObbState.volId);
3357 mObbState.volId = null;
Kenny Roota02b8b02010-08-05 16:14:17 -07003358
Kenny Rootaf9d6672010-10-08 09:21:39 -07003359 synchronized (mObbMounts) {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003360 removeObbStateLocked(existingState);
Kenny Root38cf8862010-09-26 14:18:51 -07003361 }
3362
Jeff Sharkey0095a822018-02-15 13:06:53 -07003363 notifyObbStateChange(UNMOUNTED);
3364 } catch (Exception e) {
3365 throw new ObbException(ERROR_COULD_NOT_UNMOUNT, e);
Kenny Roota02b8b02010-08-05 16:14:17 -07003366 }
3367 }
3368
Jason parks5af0b912010-11-29 09:05:25 -06003369 @Override
Kenny Roota02b8b02010-08-05 16:14:17 -07003370 public String toString() {
3371 StringBuilder sb = new StringBuilder();
3372 sb.append("UnmountObbAction{");
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003373 sb.append(mObbState);
Kenny Roota02b8b02010-08-05 16:14:17 -07003374 sb.append(",force=");
3375 sb.append(mForceUnmount);
Kenny Roota02b8b02010-08-05 16:14:17 -07003376 sb.append('}');
3377 return sb.toString();
3378 }
Kenny Root02c87302010-07-01 08:10:18 -07003379 }
Kenny Root38cf8862010-09-26 14:18:51 -07003380
Jeff Sharkey7e19f532017-11-06 13:54:11 -07003381 private void dispatchOnStatus(IVoldTaskListener listener, int status,
3382 PersistableBundle extras) {
3383 if (listener != null) {
3384 try {
3385 listener.onStatus(status, extras);
3386 } catch (RemoteException ignored) {
3387 }
3388 }
3389 }
3390
3391 private void dispatchOnFinished(IVoldTaskListener listener, int status,
3392 PersistableBundle extras) {
3393 if (listener != null) {
3394 try {
3395 listener.onFinished(status, extras);
3396 } catch (RemoteException ignored) {
3397 }
3398 }
3399 }
3400
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07003401 private static class Callbacks extends Handler {
3402 private static final int MSG_STORAGE_STATE_CHANGED = 1;
3403 private static final int MSG_VOLUME_STATE_CHANGED = 2;
Jeff Sharkey50a05452015-04-29 11:24:52 -07003404 private static final int MSG_VOLUME_RECORD_CHANGED = 3;
3405 private static final int MSG_VOLUME_FORGOTTEN = 4;
3406 private static final int MSG_DISK_SCANNED = 5;
Makoto Onuki9dc575d2015-06-12 16:10:25 -07003407 private static final int MSG_DISK_DESTROYED = 6;
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07003408
Sudheer Shanka2250d562016-11-07 15:41:02 -08003409 private final RemoteCallbackList<IStorageEventListener>
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07003410 mCallbacks = new RemoteCallbackList<>();
3411
3412 public Callbacks(Looper looper) {
3413 super(looper);
3414 }
3415
Sudheer Shanka2250d562016-11-07 15:41:02 -08003416 public void register(IStorageEventListener callback) {
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07003417 mCallbacks.register(callback);
3418 }
3419
Sudheer Shanka2250d562016-11-07 15:41:02 -08003420 public void unregister(IStorageEventListener callback) {
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07003421 mCallbacks.unregister(callback);
3422 }
3423
3424 @Override
3425 public void handleMessage(Message msg) {
3426 final SomeArgs args = (SomeArgs) msg.obj;
3427 final int n = mCallbacks.beginBroadcast();
3428 for (int i = 0; i < n; i++) {
Sudheer Shanka2250d562016-11-07 15:41:02 -08003429 final IStorageEventListener callback = mCallbacks.getBroadcastItem(i);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07003430 try {
3431 invokeCallback(callback, msg.what, args);
3432 } catch (RemoteException ignored) {
3433 }
3434 }
3435 mCallbacks.finishBroadcast();
3436 args.recycle();
3437 }
3438
Sudheer Shanka2250d562016-11-07 15:41:02 -08003439 private void invokeCallback(IStorageEventListener callback, int what, SomeArgs args)
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07003440 throws RemoteException {
3441 switch (what) {
3442 case MSG_STORAGE_STATE_CHANGED: {
3443 callback.onStorageStateChanged((String) args.arg1, (String) args.arg2,
3444 (String) args.arg3);
3445 break;
3446 }
3447 case MSG_VOLUME_STATE_CHANGED: {
3448 callback.onVolumeStateChanged((VolumeInfo) args.arg1, args.argi2, args.argi3);
3449 break;
3450 }
Jeff Sharkey50a05452015-04-29 11:24:52 -07003451 case MSG_VOLUME_RECORD_CHANGED: {
3452 callback.onVolumeRecordChanged((VolumeRecord) args.arg1);
3453 break;
3454 }
3455 case MSG_VOLUME_FORGOTTEN: {
3456 callback.onVolumeForgotten((String) args.arg1);
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07003457 break;
3458 }
Jeff Sharkey620b32b2015-04-23 19:36:02 -07003459 case MSG_DISK_SCANNED: {
3460 callback.onDiskScanned((DiskInfo) args.arg1, args.argi2);
Jeff Sharkey7e92ef32015-04-17 17:35:07 -07003461 break;
3462 }
Makoto Onuki9dc575d2015-06-12 16:10:25 -07003463 case MSG_DISK_DESTROYED: {
3464 callback.onDiskDestroyed((DiskInfo) args.arg1);
3465 break;
3466 }
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07003467 }
3468 }
3469
3470 private void notifyStorageStateChanged(String path, String oldState, String newState) {
3471 final SomeArgs args = SomeArgs.obtain();
3472 args.arg1 = path;
3473 args.arg2 = oldState;
3474 args.arg3 = newState;
3475 obtainMessage(MSG_STORAGE_STATE_CHANGED, args).sendToTarget();
3476 }
3477
3478 private void notifyVolumeStateChanged(VolumeInfo vol, int oldState, int newState) {
3479 final SomeArgs args = SomeArgs.obtain();
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07003480 args.arg1 = vol.clone();
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07003481 args.argi2 = oldState;
3482 args.argi3 = newState;
3483 obtainMessage(MSG_VOLUME_STATE_CHANGED, args).sendToTarget();
3484 }
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07003485
Jeff Sharkey50a05452015-04-29 11:24:52 -07003486 private void notifyVolumeRecordChanged(VolumeRecord rec) {
3487 final SomeArgs args = SomeArgs.obtain();
3488 args.arg1 = rec.clone();
3489 obtainMessage(MSG_VOLUME_RECORD_CHANGED, args).sendToTarget();
3490 }
3491
3492 private void notifyVolumeForgotten(String fsUuid) {
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07003493 final SomeArgs args = SomeArgs.obtain();
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07003494 args.arg1 = fsUuid;
Jeff Sharkey50a05452015-04-29 11:24:52 -07003495 obtainMessage(MSG_VOLUME_FORGOTTEN, args).sendToTarget();
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07003496 }
Jeff Sharkey7e92ef32015-04-17 17:35:07 -07003497
Jeff Sharkey620b32b2015-04-23 19:36:02 -07003498 private void notifyDiskScanned(DiskInfo disk, int volumeCount) {
Jeff Sharkey7e92ef32015-04-17 17:35:07 -07003499 final SomeArgs args = SomeArgs.obtain();
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07003500 args.arg1 = disk.clone();
Jeff Sharkey620b32b2015-04-23 19:36:02 -07003501 args.argi2 = volumeCount;
3502 obtainMessage(MSG_DISK_SCANNED, args).sendToTarget();
Jeff Sharkey7e92ef32015-04-17 17:35:07 -07003503 }
Makoto Onuki9dc575d2015-06-12 16:10:25 -07003504
3505 private void notifyDiskDestroyed(DiskInfo disk) {
3506 final SomeArgs args = SomeArgs.obtain();
3507 args.arg1 = disk.clone();
3508 obtainMessage(MSG_DISK_DESTROYED, args).sendToTarget();
3509 }
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07003510 }
3511
Kenny Root38cf8862010-09-26 14:18:51 -07003512 @Override
Jeff Sharkey5aca2b82013-10-16 16:21:54 -07003513 protected void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
Jeff Sharkeyfe9a53b2017-03-31 14:08:23 -06003514 if (!DumpUtils.checkDumpPermission(mContext, TAG, writer)) return;
Jeff Sharkey5aca2b82013-10-16 16:21:54 -07003515
3516 final IndentingPrintWriter pw = new IndentingPrintWriter(writer, " ", 160);
Jeff Sharkey27de30d2015-04-18 16:20:27 -07003517 synchronized (mLock) {
3518 pw.println("Disks:");
3519 pw.increaseIndent();
3520 for (int i = 0; i < mDisks.size(); i++) {
3521 final DiskInfo disk = mDisks.valueAt(i);
3522 disk.dump(pw);
3523 }
3524 pw.decreaseIndent();
3525
3526 pw.println();
3527 pw.println("Volumes:");
3528 pw.increaseIndent();
3529 for (int i = 0; i < mVolumes.size(); i++) {
3530 final VolumeInfo vol = mVolumes.valueAt(i);
3531 if (VolumeInfo.ID_PRIVATE_INTERNAL.equals(vol.id)) continue;
3532 vol.dump(pw);
3533 }
3534 pw.decreaseIndent();
3535
3536 pw.println();
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07003537 pw.println("Records:");
Jeff Sharkey27de30d2015-04-18 16:20:27 -07003538 pw.increaseIndent();
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07003539 for (int i = 0; i < mRecords.size(); i++) {
3540 final VolumeRecord note = mRecords.valueAt(i);
3541 note.dump(pw);
Jeff Sharkey27de30d2015-04-18 16:20:27 -07003542 }
3543 pw.decreaseIndent();
Jeff Sharkey275e3e42015-04-24 16:10:32 -07003544
3545 pw.println();
3546 pw.println("Primary storage UUID: " + mPrimaryStorageUuid);
Felipe Leme281389a2016-10-10 17:12:20 -07003547 final Pair<String, Long> pair = StorageManager.getPrimaryStoragePathAndSize();
3548 if (pair == null) {
3549 pw.println("Internal storage total size: N/A");
3550 } else {
3551 pw.print("Internal storage (");
3552 pw.print(pair.first);
3553 pw.print(") total size: ");
3554 pw.print(pair.second);
3555 pw.print(" (");
Jeff Sharkey9f2dc052018-01-07 16:47:31 -07003556 pw.print(DataUnit.MEBIBYTES.toBytes(pair.second));
3557 pw.println(" MiB)");
Felipe Leme281389a2016-10-10 17:12:20 -07003558 }
Jeff Sharkey4c099d02015-05-15 13:45:00 -07003559 pw.println("Force adoptable: " + mForceAdoptable);
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08003560 pw.println();
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07003561 pw.println("Local unlocked users: " + Arrays.toString(mLocalUnlockedUsers));
3562 pw.println("System unlocked users: " + Arrays.toString(mSystemUnlockedUsers));
Jeff Sharkey27de30d2015-04-18 16:20:27 -07003563 }
Kenny Root38cf8862010-09-26 14:18:51 -07003564
Kenny Root38cf8862010-09-26 14:18:51 -07003565 synchronized (mObbMounts) {
Jeff Sharkey27de30d2015-04-18 16:20:27 -07003566 pw.println();
Jeff Sharkey5aca2b82013-10-16 16:21:54 -07003567 pw.println("mObbMounts:");
3568 pw.increaseIndent();
3569 final Iterator<Entry<IBinder, List<ObbState>>> binders = mObbMounts.entrySet()
3570 .iterator();
Kenny Rootaf9d6672010-10-08 09:21:39 -07003571 while (binders.hasNext()) {
3572 Entry<IBinder, List<ObbState>> e = binders.next();
Jeff Sharkey5aca2b82013-10-16 16:21:54 -07003573 pw.println(e.getKey() + ":");
3574 pw.increaseIndent();
Kenny Rootaf9d6672010-10-08 09:21:39 -07003575 final List<ObbState> obbStates = e.getValue();
Kenny Root38cf8862010-09-26 14:18:51 -07003576 for (final ObbState obbState : obbStates) {
Jeff Sharkey5aca2b82013-10-16 16:21:54 -07003577 pw.println(obbState);
Kenny Root38cf8862010-09-26 14:18:51 -07003578 }
Jeff Sharkey5aca2b82013-10-16 16:21:54 -07003579 pw.decreaseIndent();
Kenny Root38cf8862010-09-26 14:18:51 -07003580 }
Jeff Sharkey5aca2b82013-10-16 16:21:54 -07003581 pw.decreaseIndent();
Kenny Rootaf9d6672010-10-08 09:21:39 -07003582
Jeff Sharkey5aca2b82013-10-16 16:21:54 -07003583 pw.println();
3584 pw.println("mObbPathToStateMap:");
3585 pw.increaseIndent();
Kenny Rootaf9d6672010-10-08 09:21:39 -07003586 final Iterator<Entry<String, ObbState>> maps = mObbPathToStateMap.entrySet().iterator();
3587 while (maps.hasNext()) {
3588 final Entry<String, ObbState> e = maps.next();
Jeff Sharkey5aca2b82013-10-16 16:21:54 -07003589 pw.print(e.getKey());
3590 pw.print(" -> ");
3591 pw.println(e.getValue());
Kenny Rootaf9d6672010-10-08 09:21:39 -07003592 }
Jeff Sharkey5aca2b82013-10-16 16:21:54 -07003593 pw.decreaseIndent();
Kenny Root38cf8862010-09-26 14:18:51 -07003594 }
Kenny Root4161f9b2011-07-13 09:48:33 -07003595
Robert Greenwalt470fd722012-01-18 12:51:15 -08003596 pw.println();
Christopher Tate7265abe2014-11-21 13:54:45 -08003597 pw.print("Last maintenance: ");
Jeff Sharkeye8a4b662015-06-27 15:43:45 -07003598 pw.println(TimeUtils.formatForLogging(mLastMaintenance));
Kenny Root38cf8862010-09-26 14:18:51 -07003599 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003600
Jeff Sharkeyfa23c5a2011-08-09 21:44:24 -07003601 /** {@inheritDoc} */
Jeff Sharkey48877892015-03-18 11:27:19 -07003602 @Override
Jeff Sharkeyfa23c5a2011-08-09 21:44:24 -07003603 public void monitor() {
Jeff Sharkey54402792017-09-15 16:05:19 -06003604 try {
3605 mVold.monitor();
3606 } catch (Exception e) {
3607 Slog.wtf(TAG, e);
Paul Lawrence1c62cbb2015-06-03 14:14:52 -07003608 }
Jeff Sharkeyfa23c5a2011-08-09 21:44:24 -07003609 }
Svet Ganov6ee871e2015-07-10 14:29:33 -07003610
Sudheer Shanka2250d562016-11-07 15:41:02 -08003611 private final class StorageManagerInternalImpl extends StorageManagerInternal {
Svet Ganov6ee871e2015-07-10 14:29:33 -07003612 // Not guarded by a lock.
3613 private final CopyOnWriteArrayList<ExternalStorageMountPolicy> mPolicies =
3614 new CopyOnWriteArrayList<>();
3615
3616 @Override
3617 public void addExternalStoragePolicy(ExternalStorageMountPolicy policy) {
3618 // No locking - CopyOnWriteArrayList
3619 mPolicies.add(policy);
3620 }
3621
3622 @Override
3623 public void onExternalStoragePolicyChanged(int uid, String packageName) {
3624 final int mountMode = getExternalStorageMountMode(uid, packageName);
3625 remountUidExternalStorage(uid, mountMode);
3626 }
3627
3628 @Override
3629 public int getExternalStorageMountMode(int uid, String packageName) {
3630 // No locking - CopyOnWriteArrayList
3631 int mountMode = Integer.MAX_VALUE;
3632 for (ExternalStorageMountPolicy policy : mPolicies) {
3633 final int policyMode = policy.getMountMode(uid, packageName);
3634 if (policyMode == Zygote.MOUNT_EXTERNAL_NONE) {
3635 return Zygote.MOUNT_EXTERNAL_NONE;
3636 }
3637 mountMode = Math.min(mountMode, policyMode);
3638 }
3639 if (mountMode == Integer.MAX_VALUE) {
3640 return Zygote.MOUNT_EXTERNAL_NONE;
3641 }
3642 return mountMode;
3643 }
3644
3645 public boolean hasExternalStorage(int uid, String packageName) {
Amith Yamasani2bd5cff2015-07-22 14:42:31 -07003646 // No need to check for system uid. This avoids a deadlock between
3647 // PackageManagerService and AppOpsService.
3648 if (uid == Process.SYSTEM_UID) {
3649 return true;
3650 }
Svet Ganov6ee871e2015-07-10 14:29:33 -07003651 // No locking - CopyOnWriteArrayList
3652 for (ExternalStorageMountPolicy policy : mPolicies) {
3653 final boolean policyHasStorage = policy.hasExternalStorage(uid, packageName);
3654 if (!policyHasStorage) {
3655 return false;
3656 }
3657 }
3658 return true;
3659 }
3660 }
Jeff Sharkeyfa23c5a2011-08-09 21:44:24 -07003661}