blob: 6c2903f347218b27a4eb876d4fdc033a4632ca63 [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
2 * Copyright (C) 2007 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.server;
18
Jeff Sharkey0095a822018-02-15 13:06:53 -070019import static android.os.storage.OnObbStateChangeListener.ERROR_ALREADY_MOUNTED;
20import static android.os.storage.OnObbStateChangeListener.ERROR_COULD_NOT_MOUNT;
21import static android.os.storage.OnObbStateChangeListener.ERROR_COULD_NOT_UNMOUNT;
22import static android.os.storage.OnObbStateChangeListener.ERROR_INTERNAL;
23import static android.os.storage.OnObbStateChangeListener.ERROR_NOT_MOUNTED;
24import static android.os.storage.OnObbStateChangeListener.ERROR_PERMISSION_DENIED;
25import static android.os.storage.OnObbStateChangeListener.MOUNTED;
26import static android.os.storage.OnObbStateChangeListener.UNMOUNTED;
27
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -070028import static com.android.internal.util.XmlUtils.readIntAttribute;
Jeff Sharkeye8a4b662015-06-27 15:43:45 -070029import static com.android.internal.util.XmlUtils.readLongAttribute;
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -070030import static com.android.internal.util.XmlUtils.readStringAttribute;
31import static com.android.internal.util.XmlUtils.writeIntAttribute;
Jeff Sharkeye8a4b662015-06-27 15:43:45 -070032import static com.android.internal.util.XmlUtils.writeLongAttribute;
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -070033import static com.android.internal.util.XmlUtils.writeStringAttribute;
Jeff Sharkey5217cac2015-12-20 15:34:01 -070034
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -070035import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT;
36import static org.xmlpull.v1.XmlPullParser.START_TAG;
37
Jason parks8888c592011-01-20 22:46:41 -060038import android.Manifest;
Jeff Sharkeyef10ee02015-07-05 14:17:27 -070039import android.annotation.Nullable;
Xiaohui Chen621b3fc2015-10-02 14:41:42 -070040import android.app.ActivityManager;
Jeff Sharkey9765e442017-12-14 22:15:14 -070041import android.app.ActivityManagerInternal;
42import android.app.ActivityManagerInternal.ScreenObserver;
Jeff Sharkey2d8b4e82013-09-17 17:30:33 -070043import android.app.AppOpsManager;
Jeff Sharkey14cbe522015-07-08 14:06:37 -070044import android.app.IActivityManager;
Jeff Sharkey9765e442017-12-14 22:15:14 -070045import android.app.KeyguardManager;
Pavel Grafovce72ef02018-01-10 17:14:11 +000046import android.app.admin.SecurityLog;
Jeff Sharkey9bed0702017-01-23 20:37:05 -070047import android.app.usage.StorageStatsManager;
Jeff Sharkeybcd262d2015-06-10 09:41:17 -070048import android.content.BroadcastReceiver;
Kenny Roota02b8b02010-08-05 16:14:17 -070049import android.content.ComponentName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080050import android.content.Context;
51import android.content.Intent;
Jeff Sharkeybcd262d2015-06-10 09:41:17 -070052import android.content.IntentFilter;
Kenny Roota02b8b02010-08-05 16:14:17 -070053import android.content.ServiceConnection;
Jeff Sharkey275e3e42015-04-24 16:10:32 -070054import android.content.pm.IPackageMoveObserver;
55import android.content.pm.PackageManager;
Jeff Sharkey14cbe522015-07-08 14:06:37 -070056import android.content.pm.ProviderInfo;
Jeff Sharkeybcd262d2015-06-10 09:41:17 -070057import android.content.pm.UserInfo;
Elliott Hughesf839b4f2014-09-26 12:30:47 -070058import android.content.res.Configuration;
Kenny Root02c87302010-07-01 08:10:18 -070059import android.content.res.ObbInfo;
Daniel Colascione766b6322018-01-08 19:10:36 -080060import android.database.ContentObserver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080061import android.net.Uri;
Kenny Root02c87302010-07-01 08:10:18 -070062import android.os.Binder;
Jeff Sharkey4c099d02015-05-15 13:45:00 -070063import android.os.DropBoxManager;
Kenny Roota02b8b02010-08-05 16:14:17 -070064import android.os.Environment;
Jeff Sharkeyb049e212012-09-07 23:16:01 -070065import android.os.Environment.UserEnvironment;
Jeff Sharkey48877892015-03-18 11:27:19 -070066import android.os.FileUtils;
Suchi Amalapurapuc42e29e2010-02-22 16:03:53 -080067import android.os.Handler;
Dianne Hackbornefa92b22013-05-03 14:11:43 -070068import android.os.HandlerThread;
Kenny Roota02b8b02010-08-05 16:14:17 -070069import android.os.IBinder;
Jin Qian12690d52017-10-13 18:17:04 -070070import android.os.IStoraged;
Jeff Sharkey1019de92017-09-06 13:47:03 -060071import android.os.IVold;
Jeff Sharkey8058fe62017-09-13 11:50:33 -060072import android.os.IVoldListener;
Jeff Sharkeyb302c542017-09-15 12:57:59 -060073import android.os.IVoldTaskListener;
Daniel Sandler5f27ef42010-03-16 15:42:02 -040074import android.os.Looper;
Suchi Amalapurapuc42e29e2010-02-22 16:03:53 -080075import android.os.Message;
Daichi Hirono9e8d9e22015-11-13 14:37:00 +090076import android.os.ParcelFileDescriptor;
Jeff Sharkey500ce9e2017-02-12 02:39:24 -070077import android.os.ParcelableException;
Jeff Sharkeyb302c542017-09-15 12:57:59 -060078import android.os.PersistableBundle;
Jeff Sharkeyce14cd02015-12-07 15:35:42 -070079import android.os.PowerManager;
Jeff Sharkey9527b222015-06-24 15:24:48 -070080import android.os.Process;
Jeff Sharkey7151a9a2015-04-04 15:22:37 -070081import android.os.RemoteCallbackList;
San Mehat4270e1e2010-01-29 05:32:19 -080082import android.os.RemoteException;
Suchi Amalapurapufd3530f2010-01-18 00:15:59 -080083import android.os.ServiceManager;
Paul Crowleyfc0b5192018-07-02 13:58:10 -070084import android.os.ServiceSpecificException;
Jeff Sharkeyedcdaf62015-07-09 09:45:36 -070085import android.os.SystemClock;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080086import android.os.SystemProperties;
Dianne Hackbornf02b60a2012-08-16 10:48:27 -070087import android.os.UserHandle;
Emily Bernier92aa5a22014-07-07 10:11:48 -040088import android.os.UserManager;
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -070089import android.os.storage.DiskInfo;
Kenny Roota02b8b02010-08-05 16:14:17 -070090import android.os.storage.IObbActionListener;
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -070091import android.os.storage.IStorageEventListener;
Sudheer Shanka2250d562016-11-07 15:41:02 -080092import android.os.storage.IStorageManager;
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -070093import android.os.storage.IStorageShutdownObserver;
Kenny Rootaf9d6672010-10-08 09:21:39 -070094import android.os.storage.OnObbStateChangeListener;
Paul Lawrence46791e72014-04-03 09:10:26 -070095import android.os.storage.StorageManager;
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -070096import android.os.storage.StorageManagerInternal;
Mike Lockwood2f6a3882011-05-09 19:08:06 -070097import android.os.storage.StorageVolume;
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -070098import android.os.storage.VolumeInfo;
Jeff Sharkeyb36586a2015-04-27 08:42:28 -070099import android.os.storage.VolumeRecord;
Jeff Sharkey14cbe522015-07-08 14:06:37 -0700100import android.provider.MediaStore;
Jeff Sharkeye8a4b662015-06-27 15:43:45 -0700101import android.provider.Settings;
Jason parksf7b3cd42011-01-27 09:28:25 -0600102import android.text.TextUtils;
Jeff Sharkey1783f142015-04-17 10:52:51 -0700103import android.text.format.DateUtils;
Jeff Sharkey48877892015-03-18 11:27:19 -0700104import android.util.ArrayMap;
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700105import android.util.AtomicFile;
Jeff Sharkey9f2dc052018-01-07 16:47:31 -0700106import android.util.DataUnit;
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -0700107import android.util.Log;
Felipe Leme281389a2016-10-10 17:12:20 -0700108import android.util.Pair;
San Mehata5078592010-03-25 09:36:54 -0700109import android.util.Slog;
Jeff Sharkeye8a4b662015-06-27 15:43:45 -0700110import android.util.TimeUtils;
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700111import android.util.Xml;
Jeff Sharkey48877892015-03-18 11:27:19 -0700112
Jeff Sharkey8b2c3a142012-11-12 11:45:05 -0800113import com.android.internal.annotations.GuardedBy;
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700114import com.android.internal.app.IMediaContainerService;
Daichi Hirono9fb00182016-11-08 14:12:17 +0900115import com.android.internal.os.AppFuseMount;
Jeff Sharkey1019de92017-09-06 13:47:03 -0600116import com.android.internal.os.BackgroundThread;
Daichi Hirono812c95d2017-02-08 16:20:20 +0900117import com.android.internal.os.FuseUnavailableMountException;
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700118import com.android.internal.os.SomeArgs;
Jeff Sharkey9527b222015-06-24 15:24:48 -0700119import com.android.internal.os.Zygote;
Jeff Sharkey48877892015-03-18 11:27:19 -0700120import com.android.internal.util.ArrayUtils;
Jeff Sharkeyfe9a53b2017-03-31 14:08:23 -0600121import com.android.internal.util.DumpUtils;
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700122import com.android.internal.util.FastXmlSerializer;
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -0800123import com.android.internal.util.HexDump;
Jeff Sharkey5aca2b82013-10-16 16:21:54 -0700124import com.android.internal.util.IndentingPrintWriter;
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700125import com.android.internal.util.Preconditions;
Jeff Sharkeyb9fe5372015-12-03 15:23:08 -0700126import com.android.internal.widget.LockPatternUtils;
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700127import com.android.server.pm.PackageManagerService;
Daichi Hirono9fb00182016-11-08 14:12:17 +0900128import com.android.server.storage.AppFuseBridge;
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -0700129
Jeff Sharkey5217cac2015-12-20 15:34:01 -0700130import libcore.io.IoUtils;
131import libcore.util.EmptyArray;
132
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700133import org.xmlpull.v1.XmlPullParser;
134import org.xmlpull.v1.XmlPullParserException;
135import org.xmlpull.v1.XmlSerializer;
136
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700137import java.io.File;
Kenny Root38cf8862010-09-26 14:18:51 -0700138import java.io.FileDescriptor;
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700139import java.io.FileInputStream;
140import java.io.FileNotFoundException;
Christopher Tate7265abe2014-11-21 13:54:45 -0800141import java.io.FileOutputStream;
Kenny Root05105f72010-09-22 17:29:43 -0700142import java.io.IOException;
Kenny Root38cf8862010-09-26 14:18:51 -0700143import java.io.PrintWriter;
Kenny Root3b1abba2010-10-13 15:00:07 -0700144import java.math.BigInteger;
Paul Lawrence8e397362014-01-27 15:22:30 -0800145import java.nio.charset.StandardCharsets;
Jeff Sharkey0095a822018-02-15 13:06:53 -0700146import java.security.GeneralSecurityException;
Kenny Root3b1abba2010-10-13 15:00:07 -0700147import java.security.spec.KeySpec;
San Mehat22dd86e2010-01-12 12:21:18 -0800148import java.util.ArrayList;
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -0800149import java.util.Arrays;
Kenny Roota02b8b02010-08-05 16:14:17 -0700150import java.util.HashMap;
Kenny Root38cf8862010-09-26 14:18:51 -0700151import java.util.Iterator;
Kenny Roota02b8b02010-08-05 16:14:17 -0700152import java.util.LinkedList;
153import java.util.List;
Elliott Hughesf839b4f2014-09-26 12:30:47 -0700154import java.util.Locale;
Kenny Roota02b8b02010-08-05 16:14:17 -0700155import java.util.Map;
Kenny Root38cf8862010-09-26 14:18:51 -0700156import java.util.Map.Entry;
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700157import java.util.Objects;
Svet Ganov6ee871e2015-07-10 14:29:33 -0700158import java.util.concurrent.CopyOnWriteArrayList;
Kenny Root51a573c2012-05-17 13:30:28 -0700159import java.util.concurrent.CountDownLatch;
160import java.util.concurrent.TimeUnit;
Jeff Sharkeyedcdaf62015-07-09 09:45:36 -0700161import java.util.concurrent.TimeoutException;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800162
Kenny Root3b1abba2010-10-13 15:00:07 -0700163import javax.crypto.SecretKey;
164import javax.crypto.SecretKeyFactory;
165import javax.crypto.spec.PBEKeySpec;
166
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800167/**
Jeff Sharkey48877892015-03-18 11:27:19 -0700168 * Service responsible for various storage media. Connects to {@code vold} to
169 * watch for and manage dynamically added storage, such as SD cards and USB mass
170 * storage. Also decides how storage should be presented to users on the device.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800171 */
Jeff Sharkey9765e442017-12-14 22:15:14 -0700172class StorageManagerService extends IStorageManager.Stub
173 implements Watchdog.Monitor, ScreenObserver {
Jason parks5af0b912010-11-29 09:05:25 -0600174
Christopher Tated417d622013-08-19 16:14:25 -0700175 // Static direct instance pointer for the tightly-coupled idle service to use
Sudheer Shanka2250d562016-11-07 15:41:02 -0800176 static StorageManagerService sSelf = null;
Christopher Tated417d622013-08-19 16:14:25 -0700177
Daniel Colascione766b6322018-01-08 19:10:36 -0800178 /* Read during boot to decide whether to enable zram when available */
179 private static final String ZRAM_ENABLED_PROPERTY =
180 "persist.sys.zram_enabled";
181
Jeff Sharkey56e62932015-03-21 20:41:00 -0700182 public static class Lifecycle extends SystemService {
Sudheer Shanka2250d562016-11-07 15:41:02 -0800183 private StorageManagerService mStorageManagerService;
Jeff Sharkey56e62932015-03-21 20:41:00 -0700184
185 public Lifecycle(Context context) {
186 super(context);
187 }
188
189 @Override
190 public void onStart() {
Sudheer Shanka2250d562016-11-07 15:41:02 -0800191 mStorageManagerService = new StorageManagerService(getContext());
192 publishBinderService("mount", mStorageManagerService);
193 mStorageManagerService.start();
Jeff Sharkey56e62932015-03-21 20:41:00 -0700194 }
195
196 @Override
197 public void onBootPhase(int phase) {
198 if (phase == SystemService.PHASE_ACTIVITY_MANAGER_READY) {
Sudheer Shanka2250d562016-11-07 15:41:02 -0800199 mStorageManagerService.systemReady();
Yasuhiro Matsuda87a38b52015-07-24 22:10:16 +0900200 } else if (phase == SystemService.PHASE_BOOT_COMPLETED) {
Sudheer Shanka2250d562016-11-07 15:41:02 -0800201 mStorageManagerService.bootCompleted();
Jeff Sharkey56e62932015-03-21 20:41:00 -0700202 }
203 }
Jeff Sharkey48877892015-03-18 11:27:19 -0700204
205 @Override
Jeff Sharkeyab15c392016-05-05 11:45:01 -0600206 public void onSwitchUser(int userHandle) {
Sudheer Shanka2250d562016-11-07 15:41:02 -0800207 mStorageManagerService.mCurrentUserId = userHandle;
Jeff Sharkeyab15c392016-05-05 11:45:01 -0600208 }
209
210 @Override
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700211 public void onUnlockUser(int userHandle) {
Sudheer Shanka2250d562016-11-07 15:41:02 -0800212 mStorageManagerService.onUnlockUser(userHandle);
Jeff Sharkey48877892015-03-18 11:27:19 -0700213 }
214
215 @Override
216 public void onCleanupUser(int userHandle) {
Sudheer Shanka2250d562016-11-07 15:41:02 -0800217 mStorageManagerService.onCleanupUser(userHandle);
Jeff Sharkey48877892015-03-18 11:27:19 -0700218 }
Jeff Sharkey56e62932015-03-21 20:41:00 -0700219 }
220
Dianne Hackborn40e9f292012-11-27 19:12:23 -0800221 private static final boolean DEBUG_EVENTS = false;
Kenny Rootb7db2722011-01-25 16:39:35 -0800222 private static final boolean DEBUG_OBB = false;
Kenny Root02c87302010-07-01 08:10:18 -0700223
Kenny Root07714d42011-08-17 17:49:28 -0700224 // Disable this since it messes up long-running cryptfs operations.
225 private static final boolean WATCHDOG_ENABLE = false;
226
Jeff Sharkey00455bf2016-11-04 14:45:24 -0600227 /**
228 * Our goal is for all Android devices to be usable as development devices,
229 * which includes the new Direct Boot mode added in N. For devices that
230 * don't have native FBE support, we offer an emulation mode for developer
231 * testing purposes, but if it's prohibitively difficult to support this
232 * mode, it can be disabled for specific products using this flag.
233 */
234 private static final boolean EMULATE_FBE_SUPPORTED = true;
235
Sudheer Shanka2250d562016-11-07 15:41:02 -0800236 private static final String TAG = "StorageManagerService";
Jeff Sharkeye8a4b662015-06-27 15:43:45 -0700237
Jeff Sharkey9756d752015-05-14 21:07:42 -0700238 private static final String TAG_STORAGE_BENCHMARK = "storage_benchmark";
Jeff Sharkeye8a4b662015-06-27 15:43:45 -0700239 private static final String TAG_STORAGE_TRIM = "storage_trim";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800240
Jeff Sharkey275e3e42015-04-24 16:10:32 -0700241 /** Magic value sent by MoveTask.cpp */
242 private static final int MOVE_STATUS_COPY_FINISHED = 82;
243
Jeff Sharkey620b32b2015-04-23 19:36:02 -0700244 private static final int VERSION_INIT = 1;
245 private static final int VERSION_ADD_PRIMARY = 2;
Jeff Sharkeyfced5342015-05-10 14:53:34 -0700246 private static final int VERSION_FIX_PRIMARY = 3;
Jeff Sharkey620b32b2015-04-23 19:36:02 -0700247
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700248 private static final String TAG_VOLUMES = "volumes";
Jeff Sharkey620b32b2015-04-23 19:36:02 -0700249 private static final String ATTR_VERSION = "version";
250 private static final String ATTR_PRIMARY_STORAGE_UUID = "primaryStorageUuid";
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700251 private static final String TAG_VOLUME = "volume";
252 private static final String ATTR_TYPE = "type";
253 private static final String ATTR_FS_UUID = "fsUuid";
Jeff Sharkey5cc0df22015-06-17 19:44:05 -0700254 private static final String ATTR_PART_GUID = "partGuid";
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700255 private static final String ATTR_NICKNAME = "nickname";
256 private static final String ATTR_USER_FLAGS = "userFlags";
Jeff Sharkeye8a4b662015-06-27 15:43:45 -0700257 private static final String ATTR_CREATED_MILLIS = "createdMillis";
258 private static final String ATTR_LAST_TRIM_MILLIS = "lastTrimMillis";
259 private static final String ATTR_LAST_BENCH_MILLIS = "lastBenchMillis";
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700260
Jeff Sharkeyb36586a2015-04-27 08:42:28 -0700261 private final AtomicFile mSettingsFile;
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700262
Jeff Sharkey48877892015-03-18 11:27:19 -0700263 /**
264 * <em>Never</em> hold the lock while performing downcalls into vold, since
265 * unsolicited events can suddenly appear to update data structures.
266 */
Jeff Sharkey5f3e9342017-03-13 14:53:11 -0600267 private final Object mLock = LockGuard.installNewLock(LockGuard.INDEX_STORAGE);
Jeff Sharkey48877892015-03-18 11:27:19 -0700268
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700269 /** Set of users that we know are unlocked. */
Jeff Sharkey48877892015-03-18 11:27:19 -0700270 @GuardedBy("mLock")
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700271 private int[] mLocalUnlockedUsers = EmptyArray.INT;
272 /** Set of users that system knows are unlocked. */
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -0800273 @GuardedBy("mLock")
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700274 private int[] mSystemUnlockedUsers = EmptyArray.INT;
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700275
276 /** Map from disk ID to disk */
Jeff Sharkey48877892015-03-18 11:27:19 -0700277 @GuardedBy("mLock")
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -0700278 private ArrayMap<String, DiskInfo> mDisks = new ArrayMap<>();
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700279 /** Map from volume ID to disk */
Jeff Sharkey48877892015-03-18 11:27:19 -0700280 @GuardedBy("mLock")
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700281 private final ArrayMap<String, VolumeInfo> mVolumes = new ArrayMap<>();
Jeff Sharkey48877892015-03-18 11:27:19 -0700282
Jeff Sharkeyb36586a2015-04-27 08:42:28 -0700283 /** Map from UUID to record */
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700284 @GuardedBy("mLock")
Jeff Sharkeyb36586a2015-04-27 08:42:28 -0700285 private ArrayMap<String, VolumeRecord> mRecords = new ArrayMap<>();
Jeff Sharkey620b32b2015-04-23 19:36:02 -0700286 @GuardedBy("mLock")
287 private String mPrimaryStorageUuid;
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700288
Jeff Sharkeyeba260d2015-04-19 14:35:16 -0700289 /** Map from disk ID to latches */
290 @GuardedBy("mLock")
291 private ArrayMap<String, CountDownLatch> mDiskScanLatches = new ArrayMap<>();
292
Jeff Sharkey275e3e42015-04-24 16:10:32 -0700293 @GuardedBy("mLock")
294 private IPackageMoveObserver mMoveCallback;
295 @GuardedBy("mLock")
296 private String mMoveTargetUuid;
297
Jeff Sharkeyab15c392016-05-05 11:45:01 -0600298 private volatile int mCurrentUserId = UserHandle.USER_SYSTEM;
299
Daichi Hirono9fb00182016-11-08 14:12:17 +0900300 /** Holding lock for AppFuse business */
301 private final Object mAppFuseLock = new Object();
302
303 @GuardedBy("mAppFuseLock")
304 private int mNextAppFuseName = 0;
305
306 @GuardedBy("mAppFuseLock")
Daichi Hironoe56740d2017-02-02 13:56:45 +0900307 private AppFuseBridge mAppFuseBridge = null;
Daichi Hirono9fb00182016-11-08 14:12:17 +0900308
Jeff Sharkeyef10ee02015-07-05 14:17:27 -0700309 private VolumeInfo findVolumeByIdOrThrow(String id) {
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700310 synchronized (mLock) {
311 final VolumeInfo vol = mVolumes.get(id);
312 if (vol != null) {
313 return vol;
314 }
315 }
316 throw new IllegalArgumentException("No volume found for ID " + id);
317 }
318
Jeff Sharkeyef10ee02015-07-05 14:17:27 -0700319 private String findVolumeIdForPathOrThrow(String path) {
Jeff Sharkey48877892015-03-18 11:27:19 -0700320 synchronized (mLock) {
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -0700321 for (int i = 0; i < mVolumes.size(); i++) {
322 final VolumeInfo vol = mVolumes.valueAt(i);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700323 if (vol.path != null && path.startsWith(vol.path)) {
324 return vol.id;
Jeff Sharkey48877892015-03-18 11:27:19 -0700325 }
326 }
327 }
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700328 throw new IllegalArgumentException("No volume found for path " + path);
Jeff Sharkey48877892015-03-18 11:27:19 -0700329 }
330
Jeff Sharkeye8a4b662015-06-27 15:43:45 -0700331 private VolumeRecord findRecordForPath(String path) {
332 synchronized (mLock) {
333 for (int i = 0; i < mVolumes.size(); i++) {
334 final VolumeInfo vol = mVolumes.valueAt(i);
335 if (vol.path != null && path.startsWith(vol.path)) {
336 return mRecords.get(vol.fsUuid);
337 }
338 }
339 }
340 return null;
341 }
342
343 private String scrubPath(String path) {
344 if (path.startsWith(Environment.getDataDirectory().getAbsolutePath())) {
345 return "internal";
346 }
347 final VolumeRecord rec = findRecordForPath(path);
348 if (rec == null || rec.createdMillis == 0) {
349 return "unknown";
350 } else {
351 return "ext:" + (int) ((System.currentTimeMillis() - rec.createdMillis)
352 / DateUtils.WEEK_IN_MILLIS) + "w";
353 }
354 }
355
Jeff Sharkeyef10ee02015-07-05 14:17:27 -0700356 private @Nullable VolumeInfo findStorageForUuid(String volumeUuid) {
Jeff Sharkey275e3e42015-04-24 16:10:32 -0700357 final StorageManager storage = mContext.getSystemService(StorageManager.class);
358 if (Objects.equals(StorageManager.UUID_PRIVATE_INTERNAL, volumeUuid)) {
Jeff Sharkeyef10ee02015-07-05 14:17:27 -0700359 return storage.findVolumeById(VolumeInfo.ID_EMULATED_INTERNAL);
Jeff Sharkey275e3e42015-04-24 16:10:32 -0700360 } else if (Objects.equals(StorageManager.UUID_PRIMARY_PHYSICAL, volumeUuid)) {
361 return storage.getPrimaryPhysicalVolume();
362 } else {
363 return storage.findEmulatedForPrivate(storage.findVolumeByUuid(volumeUuid));
364 }
365 }
366
Jeff Sharkeye8a4b662015-06-27 15:43:45 -0700367 private boolean shouldBenchmark() {
368 final long benchInterval = Settings.Global.getLong(mContext.getContentResolver(),
369 Settings.Global.STORAGE_BENCHMARK_INTERVAL, DateUtils.WEEK_IN_MILLIS);
Jeff Sharkeye83d8a92015-09-09 14:53:38 -0700370 if (benchInterval == -1) {
371 return false;
372 } else if (benchInterval == 0) {
373 return true;
374 }
375
Jeff Sharkeye8a4b662015-06-27 15:43:45 -0700376 synchronized (mLock) {
377 for (int i = 0; i < mVolumes.size(); i++) {
378 final VolumeInfo vol = mVolumes.valueAt(i);
379 final VolumeRecord rec = mRecords.get(vol.fsUuid);
Jeff Sharkeye83d8a92015-09-09 14:53:38 -0700380 if (vol.isMountedWritable() && rec != null) {
Jeff Sharkeye8a4b662015-06-27 15:43:45 -0700381 final long benchAge = System.currentTimeMillis() - rec.lastBenchMillis;
382 if (benchAge >= benchInterval) {
383 return true;
384 }
385 }
386 }
387 return false;
388 }
389 }
390
Jeff Sharkeyeba260d2015-04-19 14:35:16 -0700391 private CountDownLatch findOrCreateDiskScanLatch(String diskId) {
392 synchronized (mLock) {
393 CountDownLatch latch = mDiskScanLatches.get(diskId);
394 if (latch == null) {
395 latch = new CountDownLatch(1);
396 mDiskScanLatches.put(diskId, latch);
397 }
398 return latch;
399 }
400 }
401
Paul Lawrence8e397362014-01-27 15:22:30 -0800402 /** List of crypto types.
403 * These must match CRYPT_TYPE_XXX in cryptfs.h AND their
404 * corresponding commands in CommandListener.cpp */
405 public static final String[] CRYPTO_TYPES
406 = { "password", "default", "pattern", "pin" };
407
Brian Carlstrom7395a8a2014-04-28 22:11:01 -0700408 private final Context mContext;
Jeff Sharkeycd575992016-03-29 14:12:49 -0600409
Jeff Sharkey1019de92017-09-06 13:47:03 -0600410 private volatile IVold mVold;
Jin Qian12690d52017-10-13 18:17:04 -0700411 private volatile IStoraged mStoraged;
Jeff Sharkey1019de92017-09-06 13:47:03 -0600412
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700413 private volatile boolean mSystemReady = false;
Yasuhiro Matsuda87a38b52015-07-24 22:10:16 +0900414 private volatile boolean mBootCompleted = false;
Jeff Sharkey48877892015-03-18 11:27:19 -0700415 private volatile boolean mDaemonConnected = false;
Jeff Sharkey9765e442017-12-14 22:15:14 -0700416 private volatile boolean mSecureKeyguardShowing = true;
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700417
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700418 private PackageManagerService mPms;
419
420 private final Callbacks mCallbacks;
Jeff Sharkeyb9fe5372015-12-03 15:23:08 -0700421 private final LockPatternUtils mLockPatternUtils;
Jeff Sharkey48877892015-03-18 11:27:19 -0700422
San Mehat6cdd9c02010-02-09 14:45:20 -0800423 /**
Kenny Root3b1abba2010-10-13 15:00:07 -0700424 * The size of the crypto algorithm key in bits for OBB files. Currently
425 * Twofish is used which takes 128-bit keys.
426 */
427 private static final int CRYPTO_ALGORITHM_KEY_SIZE = 128;
428
429 /**
430 * The number of times to run SHA1 in the PBKDF2 function for OBB files.
431 * 1024 is reasonably secure and not too slow.
432 */
433 private static final int PBKDF2_HASH_ROUNDS = 1024;
434
435 /**
Kenny Roota02b8b02010-08-05 16:14:17 -0700436 * Mounted OBB tracking information. Used to track the current state of all
437 * OBBs.
Kenny Root02c87302010-07-01 08:10:18 -0700438 */
Kenny Root735de3b2010-09-30 14:11:39 -0700439 final private Map<IBinder, List<ObbState>> mObbMounts = new HashMap<IBinder, List<ObbState>>();
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700440
441 /** Map from raw paths to {@link ObbState}. */
Kenny Roota02b8b02010-08-05 16:14:17 -0700442 final private Map<String, ObbState> mObbPathToStateMap = new HashMap<String, ObbState>();
443
Svet Ganov6ee871e2015-07-10 14:29:33 -0700444 // Not guarded by a lock.
Sudheer Shanka2250d562016-11-07 15:41:02 -0800445 private final StorageManagerInternalImpl mStorageManagerInternal
446 = new StorageManagerInternalImpl();
Svet Ganov6ee871e2015-07-10 14:29:33 -0700447
Kenny Roota02b8b02010-08-05 16:14:17 -0700448 class ObbState implements IBinder.DeathRecipient {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700449 public ObbState(String rawPath, String canonicalPath, int callingUid,
Jeff Sharkey41cd6812017-09-11 10:32:17 -0600450 IObbActionListener token, int nonce, String volId) {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700451 this.rawPath = rawPath;
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700452 this.canonicalPath = canonicalPath;
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700453 this.ownerGid = UserHandle.getSharedAppGid(callingUid);
Kenny Rootaf9d6672010-10-08 09:21:39 -0700454 this.token = token;
455 this.nonce = nonce;
Jeff Sharkey41cd6812017-09-11 10:32:17 -0600456 this.volId = volId;
Kenny Roota02b8b02010-08-05 16:14:17 -0700457 }
458
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700459 final String rawPath;
460 final String canonicalPath;
Kenny Roota02b8b02010-08-05 16:14:17 -0700461
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700462 final int ownerGid;
Kenny Roota02b8b02010-08-05 16:14:17 -0700463
Kenny Rootaf9d6672010-10-08 09:21:39 -0700464 // Token of remote Binder caller
465 final IObbActionListener token;
466
467 // Identifier to pass back to the token
468 final int nonce;
Kenny Roota02b8b02010-08-05 16:14:17 -0700469
Jeff Sharkey41cd6812017-09-11 10:32:17 -0600470 String volId;
471
Kenny Root735de3b2010-09-30 14:11:39 -0700472 public IBinder getBinder() {
473 return token.asBinder();
474 }
475
Kenny Roota02b8b02010-08-05 16:14:17 -0700476 @Override
477 public void binderDied() {
478 ObbAction action = new UnmountObbAction(this, true);
479 mObbActionHandler.sendMessage(mObbActionHandler.obtainMessage(OBB_RUN_ACTION, action));
Kenny Root735de3b2010-09-30 14:11:39 -0700480 }
Kenny Roota02b8b02010-08-05 16:14:17 -0700481
Kenny Root5919ac62010-10-05 09:49:40 -0700482 public void link() throws RemoteException {
483 getBinder().linkToDeath(this, 0);
484 }
485
486 public void unlink() {
Kenny Root735de3b2010-09-30 14:11:39 -0700487 getBinder().unlinkToDeath(this, 0);
Kenny Roota02b8b02010-08-05 16:14:17 -0700488 }
Kenny Root38cf8862010-09-26 14:18:51 -0700489
490 @Override
491 public String toString() {
492 StringBuilder sb = new StringBuilder("ObbState{");
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700493 sb.append("rawPath=").append(rawPath);
494 sb.append(",canonicalPath=").append(canonicalPath);
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700495 sb.append(",ownerGid=").append(ownerGid);
496 sb.append(",token=").append(token);
497 sb.append(",binder=").append(getBinder());
Jeff Sharkey41cd6812017-09-11 10:32:17 -0600498 sb.append(",volId=").append(volId);
Kenny Root38cf8862010-09-26 14:18:51 -0700499 sb.append('}');
500 return sb.toString();
501 }
Kenny Roota02b8b02010-08-05 16:14:17 -0700502 }
503
504 // OBB Action Handler
505 final private ObbActionHandler mObbActionHandler;
506
507 // OBB action handler messages
508 private static final int OBB_RUN_ACTION = 1;
509 private static final int OBB_MCS_BOUND = 2;
510 private static final int OBB_MCS_UNBIND = 3;
511 private static final int OBB_MCS_RECONNECT = 4;
Kenny Rootaf9d6672010-10-08 09:21:39 -0700512 private static final int OBB_FLUSH_MOUNT_STATE = 5;
Kenny Roota02b8b02010-08-05 16:14:17 -0700513
514 /*
515 * Default Container Service information
516 */
517 static final ComponentName DEFAULT_CONTAINER_COMPONENT = new ComponentName(
518 "com.android.defcontainer", "com.android.defcontainer.DefaultContainerService");
519
520 final private DefaultContainerConnection mDefContainerConn = new DefaultContainerConnection();
521
522 class DefaultContainerConnection implements ServiceConnection {
Jeff Sharkey48877892015-03-18 11:27:19 -0700523 @Override
Kenny Roota02b8b02010-08-05 16:14:17 -0700524 public void onServiceConnected(ComponentName name, IBinder service) {
525 if (DEBUG_OBB)
526 Slog.i(TAG, "onServiceConnected");
527 IMediaContainerService imcs = IMediaContainerService.Stub.asInterface(service);
528 mObbActionHandler.sendMessage(mObbActionHandler.obtainMessage(OBB_MCS_BOUND, imcs));
529 }
530
Jeff Sharkey48877892015-03-18 11:27:19 -0700531 @Override
Kenny Roota02b8b02010-08-05 16:14:17 -0700532 public void onServiceDisconnected(ComponentName name) {
533 if (DEBUG_OBB)
534 Slog.i(TAG, "onServiceDisconnected");
535 }
Jeff Sharkey54402792017-09-15 16:05:19 -0600536 }
Kenny Roota02b8b02010-08-05 16:14:17 -0700537
538 // Used in the ObbActionHandler
539 private IMediaContainerService mContainerService = null;
Kenny Root02c87302010-07-01 08:10:18 -0700540
Christopher Tate7265abe2014-11-21 13:54:45 -0800541 // Last fstrim operation tracking
542 private static final String LAST_FSTRIM_FILE = "last-fstrim";
543 private final File mLastMaintenanceFile;
544 private long mLastMaintenance;
545
Kenny Root02c87302010-07-01 08:10:18 -0700546 // Handler messages
Jeff Sharkey48877892015-03-18 11:27:19 -0700547 private static final int H_SYSTEM_READY = 1;
548 private static final int H_DAEMON_CONNECTED = 2;
549 private static final int H_SHUTDOWN = 3;
550 private static final int H_FSTRIM = 4;
551 private static final int H_VOLUME_MOUNT = 5;
552 private static final int H_VOLUME_BROADCAST = 6;
Jeff Sharkeyabc3e852015-08-03 14:41:13 -0700553 private static final int H_INTERNAL_BROADCAST = 7;
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700554 private static final int H_VOLUME_UNMOUNT = 8;
Jeff Sharkey5a9bb742015-11-03 10:15:57 -0800555 private static final int H_PARTITION_FORGET = 9;
556 private static final int H_RESET = 10;
Jin Qiana85b9912017-10-17 15:48:18 -0700557 private static final int H_RUN_IDLE_MAINT = 11;
558 private static final int H_ABORT_IDLE_MAINT = 12;
Suchi Amalapurapu6ffce2e2010-03-08 14:48:40 -0800559
Sudheer Shanka2250d562016-11-07 15:41:02 -0800560 class StorageManagerServiceHandler extends Handler {
561 public StorageManagerServiceHandler(Looper looper) {
Jeff Sharkey48877892015-03-18 11:27:19 -0700562 super(looper);
Daniel Sandler5f27ef42010-03-16 15:42:02 -0400563 }
564
Jason parks5af0b912010-11-29 09:05:25 -0600565 @Override
Suchi Amalapurapuc42e29e2010-02-22 16:03:53 -0800566 public void handleMessage(Message msg) {
567 switch (msg.what) {
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700568 case H_SYSTEM_READY: {
Jeff Sharkey48877892015-03-18 11:27:19 -0700569 handleSystemReady();
570 break;
571 }
572 case H_DAEMON_CONNECTED: {
573 handleDaemonConnected();
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700574 break;
575 }
Christopher Tated417d622013-08-19 16:14:25 -0700576 case H_FSTRIM: {
Christopher Tated417d622013-08-19 16:14:25 -0700577 Slog.i(TAG, "Running fstrim idle maintenance");
Christopher Tate7265abe2014-11-21 13:54:45 -0800578
579 // Remember when we kicked it off
580 try {
581 mLastMaintenance = System.currentTimeMillis();
582 mLastMaintenanceFile.setLastModified(mLastMaintenance);
583 } catch (Exception e) {
584 Slog.e(TAG, "Unable to record last fstrim!");
585 }
586
Jeff Sharkeyb302c542017-09-15 12:57:59 -0600587 // TODO: Reintroduce shouldBenchmark() test
Jeff Sharkey7e19f532017-11-06 13:54:11 -0700588 fstrim(0, null);
Christopher Tate7265abe2014-11-21 13:54:45 -0800589
Christopher Tated417d622013-08-19 16:14:25 -0700590 // invoke the completion callback, if any
Jeff Sharkeye8a4b662015-06-27 15:43:45 -0700591 // TODO: fstrim is non-blocking, so remove this useless callback
Christopher Tated417d622013-08-19 16:14:25 -0700592 Runnable callback = (Runnable) msg.obj;
593 if (callback != null) {
594 callback.run();
595 }
596 break;
597 }
Jeff Sharkey48877892015-03-18 11:27:19 -0700598 case H_SHUTDOWN: {
Sudheer Shanka2250d562016-11-07 15:41:02 -0800599 final IStorageShutdownObserver obs = (IStorageShutdownObserver) msg.obj;
Jeff Sharkey48877892015-03-18 11:27:19 -0700600 boolean success = false;
601 try {
Jeff Sharkey54402792017-09-15 16:05:19 -0600602 mVold.shutdown();
603 success = true;
Jeff Sharkeyace874b2017-09-07 15:27:33 -0600604 } catch (Exception e) {
605 Slog.wtf(TAG, e);
Jeff Sharkey48877892015-03-18 11:27:19 -0700606 }
607 if (obs != null) {
608 try {
609 obs.onShutDownComplete(success ? 0 : -1);
Jeff Sharkeyace874b2017-09-07 15:27:33 -0600610 } catch (Exception ignored) {
Jeff Sharkey48877892015-03-18 11:27:19 -0700611 }
612 }
613 break;
614 }
615 case H_VOLUME_MOUNT: {
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -0700616 final VolumeInfo vol = (VolumeInfo) msg.obj;
Jeff Sharkey2e606d72015-07-27 14:19:54 -0700617 if (isMountDisallowed(vol)) {
618 Slog.i(TAG, "Ignoring mount " + vol.getId() + " due to policy");
619 break;
620 }
Jeff Sharkey48877892015-03-18 11:27:19 -0700621 try {
Jeff Sharkey54402792017-09-15 16:05:19 -0600622 mVold.mount(vol.id, vol.mountFlags, vol.mountUserId);
Jeff Sharkeyace874b2017-09-07 15:27:33 -0600623 } catch (Exception e) {
624 Slog.wtf(TAG, e);
Jeff Sharkey48877892015-03-18 11:27:19 -0700625 }
626 break;
627 }
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700628 case H_VOLUME_UNMOUNT: {
629 final VolumeInfo vol = (VolumeInfo) msg.obj;
630 unmount(vol.getId());
631 break;
632 }
Jeff Sharkey48877892015-03-18 11:27:19 -0700633 case H_VOLUME_BROADCAST: {
634 final StorageVolume userVol = (StorageVolume) msg.obj;
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700635 final String envState = userVol.getState();
636 Slog.d(TAG, "Volume " + userVol.getId() + " broadcasting " + envState + " to "
Jeff Sharkey48877892015-03-18 11:27:19 -0700637 + userVol.getOwner());
638
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700639 final String action = VolumeInfo.getBroadcastForEnvironment(envState);
Jeff Sharkey48877892015-03-18 11:27:19 -0700640 if (action != null) {
641 final Intent intent = new Intent(action,
642 Uri.fromFile(userVol.getPathFile()));
643 intent.putExtra(StorageVolume.EXTRA_STORAGE_VOLUME, userVol);
Jeff Sharkey082f83b2017-03-26 14:34:47 -0600644 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT
645 | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
Jeff Sharkey48877892015-03-18 11:27:19 -0700646 mContext.sendBroadcastAsUser(intent, userVol.getOwner());
647 }
648 break;
649 }
Jeff Sharkeyabc3e852015-08-03 14:41:13 -0700650 case H_INTERNAL_BROADCAST: {
651 // Internal broadcasts aimed at system components, not for
652 // third-party apps.
653 final Intent intent = (Intent) msg.obj;
654 mContext.sendBroadcastAsUser(intent, UserHandle.ALL,
655 android.Manifest.permission.WRITE_MEDIA_STORAGE);
Jeff Sharkey5a9bb742015-11-03 10:15:57 -0800656 break;
657 }
658 case H_PARTITION_FORGET: {
Jeff Sharkeydb4b6192017-10-24 11:08:50 -0600659 final VolumeRecord rec = (VolumeRecord) msg.obj;
660 forgetPartition(rec.partGuid, rec.fsUuid);
Jeff Sharkey5a9bb742015-11-03 10:15:57 -0800661 break;
662 }
663 case H_RESET: {
664 resetIfReadyAndConnected();
665 break;
Jeff Sharkeyabc3e852015-08-03 14:41:13 -0700666 }
Jin Qiana85b9912017-10-17 15:48:18 -0700667 case H_RUN_IDLE_MAINT: {
668 Slog.i(TAG, "Running idle maintenance");
669 runIdleMaint((Runnable)msg.obj);
670 break;
671 }
672 case H_ABORT_IDLE_MAINT: {
673 Slog.i(TAG, "Aborting idle maintenance");
674 abortIdleMaint((Runnable)msg.obj);
675 break;
676 }
677
Suchi Amalapurapuc42e29e2010-02-22 16:03:53 -0800678 }
679 }
Jeff Sharkey48877892015-03-18 11:27:19 -0700680 }
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700681
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700682 private final Handler mHandler;
Suchi Amalapurapuc42e29e2010-02-22 16:03:53 -0800683
Jeff Sharkeybcd262d2015-06-10 09:41:17 -0700684 private BroadcastReceiver mUserReceiver = new BroadcastReceiver() {
685 @Override
686 public void onReceive(Context context, Intent intent) {
687 final String action = intent.getAction();
688 final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700689 Preconditions.checkArgument(userId >= 0);
Jeff Sharkeybcd262d2015-06-10 09:41:17 -0700690
691 try {
692 if (Intent.ACTION_USER_ADDED.equals(action)) {
693 final UserManager um = mContext.getSystemService(UserManager.class);
694 final int userSerialNumber = um.getUserSerialNumber(userId);
Jeff Sharkey54402792017-09-15 16:05:19 -0600695 mVold.onUserAdded(userId, userSerialNumber);
Jeff Sharkeybcd262d2015-06-10 09:41:17 -0700696 } else if (Intent.ACTION_USER_REMOVED.equals(action)) {
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700697 synchronized (mVolumes) {
698 final int size = mVolumes.size();
699 for (int i = 0; i < size; i++) {
700 final VolumeInfo vol = mVolumes.valueAt(i);
701 if (vol.mountUserId == userId) {
702 vol.mountUserId = UserHandle.USER_NULL;
703 mHandler.obtainMessage(H_VOLUME_UNMOUNT, vol).sendToTarget();
704 }
705 }
706 }
Jeff Sharkey54402792017-09-15 16:05:19 -0600707 mVold.onUserRemoved(userId);
Jeff Sharkeybcd262d2015-06-10 09:41:17 -0700708 }
Jeff Sharkeyace874b2017-09-07 15:27:33 -0600709 } catch (Exception e) {
710 Slog.wtf(TAG, e);
Jeff Sharkeybcd262d2015-06-10 09:41:17 -0700711 }
712 }
713 };
714
Jeff Sharkeyedcdaf62015-07-09 09:45:36 -0700715 private void waitForLatch(CountDownLatch latch, String condition, long timeoutMillis)
716 throws TimeoutException {
717 final long startMillis = SystemClock.elapsedRealtime();
Jeff Sharkeyeba260d2015-04-19 14:35:16 -0700718 while (true) {
Kenny Root51a573c2012-05-17 13:30:28 -0700719 try {
720 if (latch.await(5000, TimeUnit.MILLISECONDS)) {
San Mehat207e5382010-02-04 20:46:54 -0800721 return;
Kenny Root51a573c2012-05-17 13:30:28 -0700722 } else {
723 Slog.w(TAG, "Thread " + Thread.currentThread().getName()
Jeff Sharkey48877892015-03-18 11:27:19 -0700724 + " still waiting for " + condition + "...");
San Mehat207e5382010-02-04 20:46:54 -0800725 }
Kenny Root51a573c2012-05-17 13:30:28 -0700726 } catch (InterruptedException e) {
Jeff Sharkeyeba260d2015-04-19 14:35:16 -0700727 Slog.w(TAG, "Interrupt while waiting for " + condition);
San Mehat207e5382010-02-04 20:46:54 -0800728 }
Jeff Sharkeyedcdaf62015-07-09 09:45:36 -0700729 if (timeoutMillis > 0 && SystemClock.elapsedRealtime() > startMillis + timeoutMillis) {
730 throw new TimeoutException("Thread " + Thread.currentThread().getName()
731 + " gave up waiting for " + condition + " after " + timeoutMillis + "ms");
732 }
San Mehat207e5382010-02-04 20:46:54 -0800733 }
San Mehat1f6301e2010-01-07 22:40:27 -0800734 }
Kenny Root02c87302010-07-01 08:10:18 -0700735
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700736 private void handleSystemReady() {
Jeff Sharkey8924e872015-11-30 12:52:10 -0700737 initIfReadyAndConnected();
Jeff Sharkey5a9bb742015-11-03 10:15:57 -0800738 resetIfReadyAndConnected();
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700739
Jeff Sharkey48877892015-03-18 11:27:19 -0700740 // Start scheduling nominally-daily fstrim operations
Christopher Tate115afda2014-06-06 19:06:26 -0700741 MountServiceIdler.scheduleIdlePass(mContext);
Daniel Colascione766b6322018-01-08 19:10:36 -0800742
743 // Toggle zram-enable system property in response to settings
744 mContext.getContentResolver().registerContentObserver(
745 Settings.Global.getUriFor(Settings.Global.ZRAM_ENABLED),
746 false /*notifyForDescendants*/,
747 new ContentObserver(null /* current thread */) {
748 @Override
749 public void onChange(boolean selfChange) {
750 refreshZramSettings();
751 }
752 });
753 refreshZramSettings();
754 }
755
756 /**
757 * Update the zram_enabled system property (which init reads to
758 * decide whether to enable zram) to reflect the zram_enabled
759 * preference (which we can change for experimentation purposes).
760 */
761 private void refreshZramSettings() {
762 String propertyValue = SystemProperties.get(ZRAM_ENABLED_PROPERTY);
763 if ("".equals(propertyValue)) {
764 return; // System doesn't have zram toggling support
765 }
766 String desiredPropertyValue =
767 Settings.Global.getInt(mContext.getContentResolver(),
768 Settings.Global.ZRAM_ENABLED,
769 1) != 0
770 ? "1" : "0";
771 if (!desiredPropertyValue.equals(propertyValue)) {
772 // Avoid redundant disk writes by setting only if we're
773 // changing the property value. There's no race: we're the
774 // sole writer.
775 SystemProperties.set(ZRAM_ENABLED_PROPERTY, desiredPropertyValue);
776 }
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700777 }
778
Jeff Sharkey14cbe522015-07-08 14:06:37 -0700779 /**
780 * MediaProvider has a ton of code that makes assumptions about storage
781 * paths never changing, so we outright kill them to pick up new state.
782 */
783 @Deprecated
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700784 private void killMediaProvider(List<UserInfo> users) {
785 if (users == null) return;
786
Jeff Sharkeyb3cf9532015-07-17 15:12:39 -0700787 final long token = Binder.clearCallingIdentity();
788 try {
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700789 for (UserInfo user : users) {
790 // System user does not have media provider, so skip.
791 if (user.isSystemOnly()) continue;
792
Jeff Sharkey2a9e3f82015-12-18 10:57:58 -0700793 final ProviderInfo provider = mPms.resolveContentProvider(MediaStore.AUTHORITY,
Jeff Sharkey8a372a02016-03-16 16:25:45 -0600794 PackageManager.MATCH_DIRECT_BOOT_AWARE
795 | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
796 user.id);
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700797 if (provider != null) {
Sudheer Shankadc589ac2016-11-10 15:30:17 -0800798 final IActivityManager am = ActivityManager.getService();
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700799 try {
Jeff Sharkey85f449e2016-06-23 09:26:00 -0600800 am.killApplication(provider.applicationInfo.packageName,
801 UserHandle.getAppId(provider.applicationInfo.uid),
802 UserHandle.USER_ALL, "vold reset");
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700803 // We only need to run this once. It will kill all users' media processes.
804 break;
805 } catch (RemoteException e) {
806 }
Jeff Sharkeyb3cf9532015-07-17 15:12:39 -0700807 }
Jeff Sharkey14cbe522015-07-08 14:06:37 -0700808 }
Jeff Sharkeyb3cf9532015-07-17 15:12:39 -0700809 } finally {
810 Binder.restoreCallingIdentity(token);
Jeff Sharkey14cbe522015-07-08 14:06:37 -0700811 }
812 }
813
Andreas Gampea36dc622018-02-05 17:19:22 -0800814 @GuardedBy("mLock")
Jeff Sharkey5a9bb742015-11-03 10:15:57 -0800815 private void addInternalVolumeLocked() {
Amith Yamasania7892482015-08-07 11:09:05 -0700816 // Create a stub volume that represents internal storage
817 final VolumeInfo internal = new VolumeInfo(VolumeInfo.ID_PRIVATE_INTERNAL,
818 VolumeInfo.TYPE_PRIVATE, null, null);
819 internal.state = VolumeInfo.STATE_MOUNTED;
820 internal.path = Environment.getDataDirectory().getAbsolutePath();
821 mVolumes.put(internal.id, internal);
822 }
823
Jeff Sharkey8924e872015-11-30 12:52:10 -0700824 private void initIfReadyAndConnected() {
825 Slog.d(TAG, "Thinking about init, mSystemReady=" + mSystemReady
826 + ", mDaemonConnected=" + mDaemonConnected);
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700827 if (mSystemReady && mDaemonConnected
Paul Lawrence20be5d62016-02-26 13:51:17 -0800828 && !StorageManager.isFileEncryptedNativeOnly()) {
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700829 // When booting a device without native support, make sure that our
830 // user directories are locked or unlocked based on the current
831 // emulation status.
Paul Lawrence20be5d62016-02-26 13:51:17 -0800832 final boolean initLocked = StorageManager.isFileEncryptedEmulatedOnly();
Paul Crowleyd94ab732016-02-15 06:44:51 +0000833 Slog.d(TAG, "Setting up emulation state, initlocked=" + initLocked);
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700834 final List<UserInfo> users = mContext.getSystemService(UserManager.class).getUsers();
Jeff Sharkey8924e872015-11-30 12:52:10 -0700835 for (UserInfo user : users) {
836 try {
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700837 if (initLocked) {
Jeff Sharkey54402792017-09-15 16:05:19 -0600838 mVold.lockUserKey(user.id);
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700839 } else {
Jeff Sharkey54402792017-09-15 16:05:19 -0600840 mVold.unlockUserKey(user.id, user.serialNumber, encodeBytes(null),
841 encodeBytes(null));
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700842 }
Jeff Sharkey43e12112017-09-12 16:31:45 -0600843 } catch (Exception e) {
844 Slog.wtf(TAG, e);
Jeff Sharkey8924e872015-11-30 12:52:10 -0700845 }
846 }
847 }
848 }
849
Jeff Sharkey5a9bb742015-11-03 10:15:57 -0800850 private void resetIfReadyAndConnected() {
Jeff Sharkey48877892015-03-18 11:27:19 -0700851 Slog.d(TAG, "Thinking about reset, mSystemReady=" + mSystemReady
852 + ", mDaemonConnected=" + mDaemonConnected);
853 if (mSystemReady && mDaemonConnected) {
Jeff Sharkey5a9bb742015-11-03 10:15:57 -0800854 final List<UserInfo> users = mContext.getSystemService(UserManager.class).getUsers();
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700855 killMediaProvider(users);
Jeff Sharkey14cbe522015-07-08 14:06:37 -0700856
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700857 final int[] systemUnlockedUsers;
Jeff Sharkey5a9bb742015-11-03 10:15:57 -0800858 synchronized (mLock) {
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700859 systemUnlockedUsers = mSystemUnlockedUsers;
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700860
Jeff Sharkey5a9bb742015-11-03 10:15:57 -0800861 mDisks.clear();
862 mVolumes.clear();
863
864 addInternalVolumeLocked();
865 }
Jeff Sharkey59d577a2015-04-11 21:27:21 -0700866
Jeff Sharkey48877892015-03-18 11:27:19 -0700867 try {
Jeff Sharkey54402792017-09-15 16:05:19 -0600868 mVold.reset();
Jeff Sharkeybcd262d2015-06-10 09:41:17 -0700869
870 // Tell vold about all existing and started users
Jeff Sharkeybcd262d2015-06-10 09:41:17 -0700871 for (UserInfo user : users) {
Jeff Sharkey54402792017-09-15 16:05:19 -0600872 mVold.onUserAdded(user.id, user.serialNumber);
Jeff Sharkeybcd262d2015-06-10 09:41:17 -0700873 }
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700874 for (int userId : systemUnlockedUsers) {
Jeff Sharkey54402792017-09-15 16:05:19 -0600875 mVold.onUserStarted(userId);
Jin Qian12690d52017-10-13 18:17:04 -0700876 mStoraged.onUserStarted(userId);
Jeff Sharkey50a05452015-04-29 11:24:52 -0700877 }
Jeff Sharkey9765e442017-12-14 22:15:14 -0700878 mVold.onSecureKeyguardStateChanged(mSecureKeyguardShowing);
Jeff Sharkeyace874b2017-09-07 15:27:33 -0600879 } catch (Exception e) {
880 Slog.wtf(TAG, e);
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700881 }
882 }
Jeff Sharkey48877892015-03-18 11:27:19 -0700883 }
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700884
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700885 private void onUnlockUser(int userId) {
886 Slog.d(TAG, "onUnlockUser " + userId);
Jeff Sharkey48877892015-03-18 11:27:19 -0700887
888 // We purposefully block here to make sure that user-specific
889 // staging area is ready so it's ready for zygote-forked apps to
890 // bind mount against.
891 try {
Jeff Sharkey54402792017-09-15 16:05:19 -0600892 mVold.onUserStarted(userId);
Jin Qian12690d52017-10-13 18:17:04 -0700893 mStoraged.onUserStarted(userId);
Jeff Sharkeyace874b2017-09-07 15:27:33 -0600894 } catch (Exception e) {
895 Slog.wtf(TAG, e);
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700896 }
Jeff Sharkey48877892015-03-18 11:27:19 -0700897
898 // Record user as started so newly mounted volumes kick off events
899 // correctly, then synthesize events for any already-mounted volumes.
yuanhuihuiefd1f122016-07-13 21:21:03 +0800900 synchronized (mLock) {
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -0700901 for (int i = 0; i < mVolumes.size(); i++) {
902 final VolumeInfo vol = mVolumes.valueAt(i);
Jeff Sharkey46349872015-07-28 10:49:47 -0700903 if (vol.isVisibleForRead(userId) && vol.isMountedReadable()) {
Svet Ganov6ee871e2015-07-10 14:29:33 -0700904 final StorageVolume userVol = vol.buildStorageVolume(mContext, userId, false);
Jeff Sharkey48877892015-03-18 11:27:19 -0700905 mHandler.obtainMessage(H_VOLUME_BROADCAST, userVol).sendToTarget();
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700906
Jeff Sharkey27de30d2015-04-18 16:20:27 -0700907 final String envState = VolumeInfo.getEnvironmentForState(vol.getState());
908 mCallbacks.notifyStorageStateChanged(userVol.getPath(), envState, envState);
Jeff Sharkey48877892015-03-18 11:27:19 -0700909 }
910 }
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700911 mSystemUnlockedUsers = ArrayUtils.appendInt(mSystemUnlockedUsers, userId);
Jeff Sharkey48877892015-03-18 11:27:19 -0700912 }
913 }
914
915 private void onCleanupUser(int userId) {
916 Slog.d(TAG, "onCleanupUser " + userId);
917
918 try {
Jeff Sharkey54402792017-09-15 16:05:19 -0600919 mVold.onUserStopped(userId);
Jin Qian12690d52017-10-13 18:17:04 -0700920 mStoraged.onUserStopped(userId);
Jeff Sharkeyace874b2017-09-07 15:27:33 -0600921 } catch (Exception e) {
922 Slog.wtf(TAG, e);
Jeff Sharkey48877892015-03-18 11:27:19 -0700923 }
924
yuanhuihuiefd1f122016-07-13 21:21:03 +0800925 synchronized (mLock) {
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700926 mSystemUnlockedUsers = ArrayUtils.removeInt(mSystemUnlockedUsers, userId);
Jeff Sharkey48877892015-03-18 11:27:19 -0700927 }
928 }
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700929
Jeff Sharkey9765e442017-12-14 22:15:14 -0700930 @Override
931 public void onAwakeStateChanged(boolean isAwake) {
932 // Ignored
933 }
934
935 @Override
936 public void onKeyguardStateChanged(boolean isShowing) {
937 // Push down current secure keyguard status so that we ignore malicious
938 // USB devices while locked.
939 mSecureKeyguardShowing = isShowing
940 && mContext.getSystemService(KeyguardManager.class).isDeviceSecure();
941 try {
942 mVold.onSecureKeyguardStateChanged(mSecureKeyguardShowing);
943 } catch (Exception e) {
944 Slog.wtf(TAG, e);
945 }
946 }
947
Christopher Tated417d622013-08-19 16:14:25 -0700948 void runIdleMaintenance(Runnable callback) {
949 mHandler.sendMessage(mHandler.obtainMessage(H_FSTRIM, callback));
950 }
951
Christopher Tate7265abe2014-11-21 13:54:45 -0800952 // Binder entry point for kicking off an immediate fstrim
953 @Override
954 public void runMaintenance() {
Jeff Sharkey48877892015-03-18 11:27:19 -0700955 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
Christopher Tate7265abe2014-11-21 13:54:45 -0800956 runIdleMaintenance(null);
957 }
958
959 @Override
960 public long lastMaintenance() {
961 return mLastMaintenance;
962 }
963
San Mehat4270e1e2010-01-29 05:32:19 -0800964 public void onDaemonConnected() {
Jeff Sharkey48877892015-03-18 11:27:19 -0700965 mDaemonConnected = true;
966 mHandler.obtainMessage(H_DAEMON_CONNECTED).sendToTarget();
967 }
968
969 private void handleDaemonConnected() {
Jeff Sharkey8924e872015-11-30 12:52:10 -0700970 initIfReadyAndConnected();
Jeff Sharkey5a9bb742015-11-03 10:15:57 -0800971 resetIfReadyAndConnected();
Jeff Sharkey48877892015-03-18 11:27:19 -0700972
Jeff Sharkey48877892015-03-18 11:27:19 -0700973 // On an encrypted device we can't see system properties yet, so pull
974 // the system locale out of the mount service.
975 if ("".equals(SystemProperties.get("vold.encrypt_progress"))) {
976 copyLocaleFromMountService();
977 }
San Mehat4270e1e2010-01-29 05:32:19 -0800978 }
979
Elliott Hughesf839b4f2014-09-26 12:30:47 -0700980 private void copyLocaleFromMountService() {
981 String systemLocale;
982 try {
983 systemLocale = getField(StorageManager.SYSTEM_LOCALE_KEY);
984 } catch (RemoteException e) {
985 return;
986 }
987 if (TextUtils.isEmpty(systemLocale)) {
988 return;
989 }
990
991 Slog.d(TAG, "Got locale " + systemLocale + " from mount service");
992 Locale locale = Locale.forLanguageTag(systemLocale);
993 Configuration config = new Configuration();
994 config.setLocale(locale);
995 try {
Sudheer Shankadc589ac2016-11-10 15:30:17 -0800996 ActivityManager.getService().updatePersistentConfiguration(config);
Elliott Hughesf839b4f2014-09-26 12:30:47 -0700997 } catch (RemoteException e) {
998 Slog.e(TAG, "Error setting system locale from mount service", e);
999 }
Elliott Hughes9c33f282014-10-13 12:39:56 -07001000
1001 // Temporary workaround for http://b/17945169.
1002 Slog.d(TAG, "Setting system properties to " + systemLocale + " from mount service");
Narayan Kamathd30dbb82015-01-15 14:48:15 +00001003 SystemProperties.set("persist.sys.locale", locale.toLanguageTag());
Elliott Hughesf839b4f2014-09-26 12:30:47 -07001004 }
1005
Jeff Sharkey8058fe62017-09-13 11:50:33 -06001006 private final IVoldListener mListener = new IVoldListener.Stub() {
1007 @Override
1008 public void onDiskCreated(String diskId, int flags) {
1009 synchronized (mLock) {
Jeff Sharkey901c0422018-04-20 13:11:20 -06001010 final String value = SystemProperties.get(StorageManager.PROP_ADOPTABLE);
1011 switch (value) {
1012 case "force_on":
1013 flags |= DiskInfo.FLAG_ADOPTABLE;
1014 break;
1015 case "force_off":
1016 flags &= ~DiskInfo.FLAG_ADOPTABLE;
1017 break;
Jeff Sharkey8058fe62017-09-13 11:50:33 -06001018 }
Jeff Sharkey8058fe62017-09-13 11:50:33 -06001019 mDisks.put(diskId, new DiskInfo(diskId, flags));
1020 }
1021 }
1022
1023 @Override
1024 public void onDiskScanned(String diskId) {
1025 synchronized (mLock) {
1026 final DiskInfo disk = mDisks.get(diskId);
1027 if (disk != null) {
1028 onDiskScannedLocked(disk);
1029 }
1030 }
1031 }
1032
1033 @Override
1034 public void onDiskMetadataChanged(String diskId, long sizeBytes, String label,
1035 String sysPath) {
1036 synchronized (mLock) {
1037 final DiskInfo disk = mDisks.get(diskId);
1038 if (disk != null) {
1039 disk.size = sizeBytes;
1040 disk.label = label;
1041 disk.sysPath = sysPath;
1042 }
1043 }
1044 }
1045
1046 @Override
1047 public void onDiskDestroyed(String diskId) {
1048 synchronized (mLock) {
1049 final DiskInfo disk = mDisks.remove(diskId);
1050 if (disk != null) {
1051 mCallbacks.notifyDiskDestroyed(disk);
1052 }
1053 }
1054 }
1055
1056 @Override
1057 public void onVolumeCreated(String volId, int type, String diskId, String partGuid) {
1058 synchronized (mLock) {
1059 final DiskInfo disk = mDisks.get(diskId);
1060 final VolumeInfo vol = new VolumeInfo(volId, type, disk, partGuid);
1061 mVolumes.put(volId, vol);
1062 onVolumeCreatedLocked(vol);
1063 }
1064 }
1065
1066 @Override
1067 public void onVolumeStateChanged(String volId, int state) {
1068 synchronized (mLock) {
1069 final VolumeInfo vol = mVolumes.get(volId);
1070 if (vol != null) {
1071 final int oldState = vol.state;
1072 final int newState = state;
1073 vol.state = newState;
1074 onVolumeStateChangedLocked(vol, oldState, newState);
1075 }
1076 }
1077 }
1078
1079 @Override
1080 public void onVolumeMetadataChanged(String volId, String fsType, String fsUuid,
1081 String fsLabel) {
1082 synchronized (mLock) {
1083 final VolumeInfo vol = mVolumes.get(volId);
1084 if (vol != null) {
1085 vol.fsType = fsType;
1086 vol.fsUuid = fsUuid;
1087 vol.fsLabel = fsLabel;
1088 }
1089 }
1090 }
1091
1092 @Override
1093 public void onVolumePathChanged(String volId, String path) {
1094 synchronized (mLock) {
1095 final VolumeInfo vol = mVolumes.get(volId);
1096 if (vol != null) {
1097 vol.path = path;
1098 }
1099 }
1100 }
1101
1102 @Override
1103 public void onVolumeInternalPathChanged(String volId, String internalPath) {
1104 synchronized (mLock) {
1105 final VolumeInfo vol = mVolumes.get(volId);
1106 if (vol != null) {
1107 vol.internalPath = internalPath;
1108 }
1109 }
1110 }
1111
1112 @Override
1113 public void onVolumeDestroyed(String volId) {
1114 synchronized (mLock) {
1115 mVolumes.remove(volId);
1116 }
1117 }
1118 };
1119
Andreas Gampea36dc622018-02-05 17:19:22 -08001120 @GuardedBy("mLock")
Jeff Sharkeyeba260d2015-04-19 14:35:16 -07001121 private void onDiskScannedLocked(DiskInfo disk) {
Jeff Sharkey620b32b2015-04-23 19:36:02 -07001122 int volumeCount = 0;
Jeff Sharkeyeba260d2015-04-19 14:35:16 -07001123 for (int i = 0; i < mVolumes.size(); i++) {
1124 final VolumeInfo vol = mVolumes.valueAt(i);
1125 if (Objects.equals(disk.id, vol.getDiskId())) {
Jeff Sharkey620b32b2015-04-23 19:36:02 -07001126 volumeCount++;
Jeff Sharkeyeba260d2015-04-19 14:35:16 -07001127 }
1128 }
1129
Jeff Sharkeyc7acac62015-06-12 16:16:56 -07001130 final Intent intent = new Intent(DiskInfo.ACTION_DISK_SCANNED);
Jeff Sharkey7732e1e2016-03-30 17:14:23 -06001131 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT
1132 | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
Jeff Sharkeyc7acac62015-06-12 16:16:56 -07001133 intent.putExtra(DiskInfo.EXTRA_DISK_ID, disk.id);
1134 intent.putExtra(DiskInfo.EXTRA_VOLUME_COUNT, volumeCount);
Jeff Sharkeyabc3e852015-08-03 14:41:13 -07001135 mHandler.obtainMessage(H_INTERNAL_BROADCAST, intent).sendToTarget();
Jeff Sharkeyc7acac62015-06-12 16:16:56 -07001136
1137 final CountDownLatch latch = mDiskScanLatches.remove(disk.id);
1138 if (latch != null) {
1139 latch.countDown();
1140 }
1141
Jeff Sharkeyf5a6bd72015-05-19 14:42:38 -07001142 disk.volumeCount = volumeCount;
Jeff Sharkey620b32b2015-04-23 19:36:02 -07001143 mCallbacks.notifyDiskScanned(disk, volumeCount);
Jeff Sharkeyeba260d2015-04-19 14:35:16 -07001144 }
1145
Andreas Gampea36dc622018-02-05 17:19:22 -08001146 @GuardedBy("mLock")
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07001147 private void onVolumeCreatedLocked(VolumeInfo vol) {
Jeff Sharkey6855c482016-03-31 14:34:38 -06001148 if (mPms.isOnlyCoreApps()) {
1149 Slog.d(TAG, "System booted in core-only mode; ignoring volume " + vol.getId());
1150 return;
1151 }
1152
Jeff Sharkey275e3e42015-04-24 16:10:32 -07001153 if (vol.type == VolumeInfo.TYPE_EMULATED) {
1154 final StorageManager storage = mContext.getSystemService(StorageManager.class);
1155 final VolumeInfo privateVol = storage.findPrivateForEmulated(vol);
1156
1157 if (Objects.equals(StorageManager.UUID_PRIVATE_INTERNAL, mPrimaryStorageUuid)
1158 && VolumeInfo.ID_PRIVATE_INTERNAL.equals(privateVol.id)) {
1159 Slog.v(TAG, "Found primary storage at " + vol);
1160 vol.mountFlags |= VolumeInfo.MOUNT_FLAG_PRIMARY;
1161 vol.mountFlags |= VolumeInfo.MOUNT_FLAG_VISIBLE;
1162 mHandler.obtainMessage(H_VOLUME_MOUNT, vol).sendToTarget();
1163
1164 } else if (Objects.equals(privateVol.fsUuid, mPrimaryStorageUuid)) {
1165 Slog.v(TAG, "Found primary storage at " + vol);
1166 vol.mountFlags |= VolumeInfo.MOUNT_FLAG_PRIMARY;
1167 vol.mountFlags |= VolumeInfo.MOUNT_FLAG_VISIBLE;
1168 mHandler.obtainMessage(H_VOLUME_MOUNT, vol).sendToTarget();
1169 }
Jeff Sharkeyb049e212012-09-07 23:16:01 -07001170
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07001171 } else if (vol.type == VolumeInfo.TYPE_PUBLIC) {
Jeff Sharkey275e3e42015-04-24 16:10:32 -07001172 // TODO: only look at first public partition
1173 if (Objects.equals(StorageManager.UUID_PRIMARY_PHYSICAL, mPrimaryStorageUuid)
1174 && vol.disk.isDefaultPrimary()) {
1175 Slog.v(TAG, "Found primary storage at " + vol);
Jeff Sharkey7e92ef32015-04-17 17:35:07 -07001176 vol.mountFlags |= VolumeInfo.MOUNT_FLAG_PRIMARY;
1177 vol.mountFlags |= VolumeInfo.MOUNT_FLAG_VISIBLE;
San Mehat4270e1e2010-01-29 05:32:19 -08001178 }
Jeff Sharkey7e92ef32015-04-17 17:35:07 -07001179
1180 // Adoptable public disks are visible to apps, since they meet
1181 // public API requirement of being in a stable location.
Jeff Sharkey275e3e42015-04-24 16:10:32 -07001182 if (vol.disk.isAdoptable()) {
Jeff Sharkey7e92ef32015-04-17 17:35:07 -07001183 vol.mountFlags |= VolumeInfo.MOUNT_FLAG_VISIBLE;
1184 }
1185
Jeff Sharkeyab15c392016-05-05 11:45:01 -06001186 vol.mountUserId = mCurrentUserId;
Jeff Sharkey48877892015-03-18 11:27:19 -07001187 mHandler.obtainMessage(H_VOLUME_MOUNT, vol).sendToTarget();
San Mehat4270e1e2010-01-29 05:32:19 -08001188
Jeff Sharkeyb2b9ab82015-04-05 21:10:42 -07001189 } else if (vol.type == VolumeInfo.TYPE_PRIVATE) {
1190 mHandler.obtainMessage(H_VOLUME_MOUNT, vol).sendToTarget();
1191
San Mehat4270e1e2010-01-29 05:32:19 -08001192 } else {
Jeff Sharkey48877892015-03-18 11:27:19 -07001193 Slog.d(TAG, "Skipping automatic mounting of " + vol);
San Mehat4270e1e2010-01-29 05:32:19 -08001194 }
1195 }
1196
Jeff Sharkeye6c04f92015-04-18 21:38:05 -07001197 private boolean isBroadcastWorthy(VolumeInfo vol) {
1198 switch (vol.getType()) {
Jeff Sharkeyc7acac62015-06-12 16:16:56 -07001199 case VolumeInfo.TYPE_PRIVATE:
Jeff Sharkeye6c04f92015-04-18 21:38:05 -07001200 case VolumeInfo.TYPE_PUBLIC:
1201 case VolumeInfo.TYPE_EMULATED:
1202 break;
1203 default:
1204 return false;
1205 }
1206
1207 switch (vol.getState()) {
1208 case VolumeInfo.STATE_MOUNTED:
1209 case VolumeInfo.STATE_MOUNTED_READ_ONLY:
1210 case VolumeInfo.STATE_EJECTING:
1211 case VolumeInfo.STATE_UNMOUNTED:
Jeff Sharkeyc7acac62015-06-12 16:16:56 -07001212 case VolumeInfo.STATE_UNMOUNTABLE:
Tony Mantlerf0d71052015-06-24 11:45:25 -07001213 case VolumeInfo.STATE_BAD_REMOVAL:
Jeff Sharkeye6c04f92015-04-18 21:38:05 -07001214 break;
1215 default:
1216 return false;
1217 }
1218
1219 return true;
1220 }
1221
Andreas Gampea36dc622018-02-05 17:19:22 -08001222 @GuardedBy("mLock")
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07001223 private void onVolumeStateChangedLocked(VolumeInfo vol, int oldState, int newState) {
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001224 // Remember that we saw this volume so we're ready to accept user
1225 // metadata, or so we can annoy them when a private volume is ejected
1226 if (vol.isMountedReadable() && !TextUtils.isEmpty(vol.fsUuid)) {
Jeff Sharkey5cc0df22015-06-17 19:44:05 -07001227 VolumeRecord rec = mRecords.get(vol.fsUuid);
1228 if (rec == null) {
1229 rec = new VolumeRecord(vol.type, vol.fsUuid);
1230 rec.partGuid = vol.partGuid;
Jeff Sharkeye8a4b662015-06-27 15:43:45 -07001231 rec.createdMillis = System.currentTimeMillis();
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001232 if (vol.type == VolumeInfo.TYPE_PRIVATE) {
1233 rec.nickname = vol.disk.getDescription();
1234 }
1235 mRecords.put(rec.fsUuid, rec);
1236 writeSettingsLocked();
Jeff Sharkey5cc0df22015-06-17 19:44:05 -07001237 } else {
1238 // Handle upgrade case where we didn't store partition GUID
1239 if (TextUtils.isEmpty(rec.partGuid)) {
1240 rec.partGuid = vol.partGuid;
1241 writeSettingsLocked();
1242 }
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001243 }
1244 }
1245
Jeff Sharkeye6c04f92015-04-18 21:38:05 -07001246 mCallbacks.notifyVolumeStateChanged(vol, oldState, newState);
1247
Yasuhiro Matsuda87a38b52015-07-24 22:10:16 +09001248 // Do not broadcast before boot has completed to avoid launching the
1249 // processes that receive the intent unnecessarily.
1250 if (mBootCompleted && isBroadcastWorthy(vol)) {
Jeff Sharkeye6c04f92015-04-18 21:38:05 -07001251 final Intent intent = new Intent(VolumeInfo.ACTION_VOLUME_STATE_CHANGED);
Jeff Sharkeyc7acac62015-06-12 16:16:56 -07001252 intent.putExtra(VolumeInfo.EXTRA_VOLUME_ID, vol.id);
1253 intent.putExtra(VolumeInfo.EXTRA_VOLUME_STATE, newState);
Tony Mantlerf0d71052015-06-24 11:45:25 -07001254 intent.putExtra(VolumeRecord.EXTRA_FS_UUID, vol.fsUuid);
Jeff Sharkey7732e1e2016-03-30 17:14:23 -06001255 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT
1256 | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
Jeff Sharkeyabc3e852015-08-03 14:41:13 -07001257 mHandler.obtainMessage(H_INTERNAL_BROADCAST, intent).sendToTarget();
Jeff Sharkeye6c04f92015-04-18 21:38:05 -07001258 }
Jeff Sharkeyb049e212012-09-07 23:16:01 -07001259
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001260 final String oldStateEnv = VolumeInfo.getEnvironmentForState(oldState);
1261 final String newStateEnv = VolumeInfo.getEnvironmentForState(newState);
Emily Bernier92aa5a22014-07-07 10:11:48 -04001262
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001263 if (!Objects.equals(oldStateEnv, newStateEnv)) {
1264 // Kick state changed event towards all started users. Any users
1265 // started after this point will trigger additional
1266 // user-specific broadcasts.
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07001267 for (int userId : mSystemUnlockedUsers) {
Jeff Sharkey46349872015-07-28 10:49:47 -07001268 if (vol.isVisibleForRead(userId)) {
Svet Ganov6ee871e2015-07-10 14:29:33 -07001269 final StorageVolume userVol = vol.buildStorageVolume(mContext, userId, false);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001270 mHandler.obtainMessage(H_VOLUME_BROADCAST, userVol).sendToTarget();
Jeff Sharkey48877892015-03-18 11:27:19 -07001271
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001272 mCallbacks.notifyStorageStateChanged(userVol.getPath(), oldStateEnv,
1273 newStateEnv);
San Mehat4270e1e2010-01-29 05:32:19 -08001274 }
1275 }
1276 }
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001277
Jeff Sharkey7e92ef32015-04-17 17:35:07 -07001278 if (vol.type == VolumeInfo.TYPE_PUBLIC && vol.state == VolumeInfo.STATE_EJECTING) {
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001279 // TODO: this should eventually be handled by new ObbVolume state changes
1280 /*
1281 * Some OBBs might have been unmounted when this volume was
1282 * unmounted, so send a message to the handler to let it know to
1283 * remove those from the list of mounted OBBS.
1284 */
1285 mObbActionHandler.sendMessage(mObbActionHandler.obtainMessage(
1286 OBB_FLUSH_MOUNT_STATE, vol.path));
1287 }
Pavel Grafovce72ef02018-01-10 17:14:11 +00001288 maybeLogMediaMount(vol, newState);
1289 }
1290
1291 private void maybeLogMediaMount(VolumeInfo vol, int newState) {
1292 if (!SecurityLog.isLoggingEnabled()) {
1293 return;
1294 }
1295
1296 final DiskInfo disk = vol.getDisk();
1297 if (disk == null || (disk.flags & (DiskInfo.FLAG_SD | DiskInfo.FLAG_USB)) == 0) {
1298 return;
1299 }
1300
1301 // Sometimes there is a newline character.
1302 final String label = disk.label != null ? disk.label.trim() : "";
1303
1304 if (newState == VolumeInfo.STATE_MOUNTED
1305 || newState == VolumeInfo.STATE_MOUNTED_READ_ONLY) {
1306 SecurityLog.writeEvent(SecurityLog.TAG_MEDIA_MOUNT, vol.path, label);
1307 } else if (newState == VolumeInfo.STATE_UNMOUNTED
1308 || newState == VolumeInfo.STATE_BAD_REMOVAL) {
1309 SecurityLog.writeEvent(SecurityLog.TAG_MEDIA_UNMOUNT, vol.path, label);
1310 }
San Mehat4270e1e2010-01-29 05:32:19 -08001311 }
1312
Andreas Gampea36dc622018-02-05 17:19:22 -08001313 @GuardedBy("mLock")
Jeff Sharkey275e3e42015-04-24 16:10:32 -07001314 private void onMoveStatusLocked(int status) {
1315 if (mMoveCallback == null) {
1316 Slog.w(TAG, "Odd, status but no move requested");
1317 return;
1318 }
1319
1320 // TODO: estimate remaining time
1321 try {
Jeff Sharkey50a05452015-04-29 11:24:52 -07001322 mMoveCallback.onStatusChanged(-1, status, -1);
Jeff Sharkey275e3e42015-04-24 16:10:32 -07001323 } catch (RemoteException ignored) {
1324 }
1325
1326 // We've finished copying and we're about to clean up old data, so
1327 // remember that move was successful if we get rebooted
1328 if (status == MOVE_STATUS_COPY_FINISHED) {
1329 Slog.d(TAG, "Move to " + mMoveTargetUuid + " copy phase finshed; persisting");
1330
1331 mPrimaryStorageUuid = mMoveTargetUuid;
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001332 writeSettingsLocked();
Jeff Sharkey275e3e42015-04-24 16:10:32 -07001333 }
1334
1335 if (PackageManager.isMoveStatusFinished(status)) {
1336 Slog.d(TAG, "Move to " + mMoveTargetUuid + " finished with status " + status);
1337
1338 mMoveCallback = null;
1339 mMoveTargetUuid = null;
1340 }
1341 }
1342
Jeff Sharkey48877892015-03-18 11:27:19 -07001343 private void enforcePermission(String perm) {
1344 mContext.enforceCallingOrSelfPermission(perm, perm);
Mike Lockwooda5250c92011-05-23 13:44:04 -04001345 }
1346
Jeff Sharkey2e606d72015-07-27 14:19:54 -07001347 /**
1348 * Decide if volume is mountable per device policies.
1349 */
1350 private boolean isMountDisallowed(VolumeInfo vol) {
Philip P. Moltmannec3cbb22016-09-14 13:24:52 -07001351 UserManager userManager = mContext.getSystemService(UserManager.class);
1352
1353 boolean isUsbRestricted = false;
1354 if (vol.disk != null && vol.disk.isUsb()) {
1355 isUsbRestricted = userManager.hasUserRestriction(UserManager.DISALLOW_USB_FILE_TRANSFER,
Jeff Sharkey2e606d72015-07-27 14:19:54 -07001356 Binder.getCallingUserHandle());
Emily Bernier92aa5a22014-07-07 10:11:48 -04001357 }
Philip P. Moltmannec3cbb22016-09-14 13:24:52 -07001358
1359 boolean isTypeRestricted = false;
1360 if (vol.type == VolumeInfo.TYPE_PUBLIC || vol.type == VolumeInfo.TYPE_PRIVATE) {
1361 isTypeRestricted = userManager
1362 .hasUserRestriction(UserManager.DISALLOW_MOUNT_PHYSICAL_MEDIA,
1363 Binder.getCallingUserHandle());
1364 }
1365
1366 return isUsbRestricted || isTypeRestricted;
Emily Bernier92aa5a22014-07-07 10:11:48 -04001367 }
1368
Amith Yamasani462ac3a2015-06-30 14:21:01 -07001369 private void enforceAdminUser() {
1370 UserManager um = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
1371 final int callingUserId = UserHandle.getCallingUserId();
1372 boolean isAdmin;
1373 long token = Binder.clearCallingIdentity();
1374 try {
1375 isAdmin = um.getUserInfo(callingUserId).isAdmin();
1376 } finally {
1377 Binder.restoreCallingIdentity(token);
1378 }
1379 if (!isAdmin) {
1380 throw new SecurityException("Only admin users can adopt sd cards");
1381 }
1382 }
1383
Jeff Sharkeyb049e212012-09-07 23:16:01 -07001384 /**
Sudheer Shanka2250d562016-11-07 15:41:02 -08001385 * Constructs a new StorageManagerService instance
San Mehat207e5382010-02-04 20:46:54 -08001386 *
1387 * @param context Binder context for this service
1388 */
Sudheer Shanka2250d562016-11-07 15:41:02 -08001389 public StorageManagerService(Context context) {
Christopher Tated417d622013-08-19 16:14:25 -07001390 sSelf = this;
1391
San Mehat207e5382010-02-04 20:46:54 -08001392 mContext = context;
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001393 mCallbacks = new Callbacks(FgThread.get().getLooper());
Jeff Sharkeyb9fe5372015-12-03 15:23:08 -07001394 mLockPatternUtils = new LockPatternUtils(mContext);
San Mehat207e5382010-02-04 20:46:54 -08001395
San Mehat207e5382010-02-04 20:46:54 -08001396 // XXX: This will go away soon in favor of IMountServiceObserver
1397 mPms = (PackageManagerService) ServiceManager.getService("package");
1398
Dianne Hackbornefa92b22013-05-03 14:11:43 -07001399 HandlerThread hthread = new HandlerThread(TAG);
1400 hthread.start();
Sudheer Shanka2250d562016-11-07 15:41:02 -08001401 mHandler = new StorageManagerServiceHandler(hthread.getLooper());
Daniel Sandler5f27ef42010-03-16 15:42:02 -04001402
Sudheer Shanka2250d562016-11-07 15:41:02 -08001403 // Add OBB Action Handler to StorageManagerService thread.
Dianne Hackborn8d044e82013-04-30 17:24:15 -07001404 mObbActionHandler = new ObbActionHandler(IoThread.get().getLooper());
Kenny Roota02b8b02010-08-05 16:14:17 -07001405
Christopher Tate7265abe2014-11-21 13:54:45 -08001406 // Initialize the last-fstrim tracking if necessary
1407 File dataDir = Environment.getDataDirectory();
1408 File systemDir = new File(dataDir, "system");
1409 mLastMaintenanceFile = new File(systemDir, LAST_FSTRIM_FILE);
1410 if (!mLastMaintenanceFile.exists()) {
1411 // Not setting mLastMaintenance here means that we will force an
1412 // fstrim during reboot following the OTA that installs this code.
1413 try {
1414 (new FileOutputStream(mLastMaintenanceFile)).close();
1415 } catch (IOException e) {
1416 Slog.e(TAG, "Unable to create fstrim record " + mLastMaintenanceFile.getPath());
1417 }
1418 } else {
1419 mLastMaintenance = mLastMaintenanceFile.lastModified();
1420 }
1421
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001422 mSettingsFile = new AtomicFile(
Dianne Hackborne17b4452018-01-10 13:15:40 -08001423 new File(Environment.getDataSystemDirectory(), "storage.xml"), "storage-settings");
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001424
1425 synchronized (mLock) {
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001426 readSettingsLocked();
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001427 }
1428
Sudheer Shanka2250d562016-11-07 15:41:02 -08001429 LocalServices.addService(StorageManagerInternal.class, mStorageManagerInternal);
Svet Ganov6ee871e2015-07-10 14:29:33 -07001430
Jeff Sharkeybcd262d2015-06-10 09:41:17 -07001431 final IntentFilter userFilter = new IntentFilter();
1432 userFilter.addAction(Intent.ACTION_USER_ADDED);
1433 userFilter.addAction(Intent.ACTION_USER_REMOVED);
1434 mContext.registerReceiver(mUserReceiver, userFilter, null, mHandler);
1435
Jeff Sharkey5a9bb742015-11-03 10:15:57 -08001436 synchronized (mLock) {
1437 addInternalVolumeLocked();
1438 }
Amith Yamasania7892482015-08-07 11:09:05 -07001439
Kenny Root07714d42011-08-17 17:49:28 -07001440 // Add ourself to the Watchdog monitors if enabled.
1441 if (WATCHDOG_ENABLE) {
1442 Watchdog.getInstance().addMonitor(this);
1443 }
San Mehat207e5382010-02-04 20:46:54 -08001444 }
1445
Jeff Sharkeycd575992016-03-29 14:12:49 -06001446 private void start() {
Jeff Sharkey1019de92017-09-06 13:47:03 -06001447 connect();
Jeff Sharkeycd575992016-03-29 14:12:49 -06001448 }
1449
Jeff Sharkey1019de92017-09-06 13:47:03 -06001450 private void connect() {
Jin Qian12690d52017-10-13 18:17:04 -07001451 IBinder binder = ServiceManager.getService("storaged");
1452 if (binder != null) {
1453 try {
1454 binder.linkToDeath(new DeathRecipient() {
1455 @Override
1456 public void binderDied() {
1457 Slog.w(TAG, "storaged died; reconnecting");
1458 mStoraged = null;
1459 connect();
1460 }
1461 }, 0);
1462 } catch (RemoteException e) {
1463 binder = null;
1464 }
1465 }
1466
1467 if (binder != null) {
1468 mStoraged = IStoraged.Stub.asInterface(binder);
1469 } else {
1470 Slog.w(TAG, "storaged not found; trying again");
1471 }
1472
1473 binder = ServiceManager.getService("vold");
Jeff Sharkey1019de92017-09-06 13:47:03 -06001474 if (binder != null) {
1475 try {
1476 binder.linkToDeath(new DeathRecipient() {
1477 @Override
1478 public void binderDied() {
1479 Slog.w(TAG, "vold died; reconnecting");
Jin Qian12690d52017-10-13 18:17:04 -07001480 mVold = null;
Jeff Sharkey1019de92017-09-06 13:47:03 -06001481 connect();
1482 }
1483 }, 0);
1484 } catch (RemoteException e) {
1485 binder = null;
1486 }
1487 }
1488
1489 if (binder != null) {
1490 mVold = IVold.Stub.asInterface(binder);
Jeff Sharkey8058fe62017-09-13 11:50:33 -06001491 try {
1492 mVold.setListener(mListener);
Jeff Sharkey8058fe62017-09-13 11:50:33 -06001493 } catch (RemoteException e) {
Jin Qian12690d52017-10-13 18:17:04 -07001494 mVold = null;
Jeff Sharkey8058fe62017-09-13 11:50:33 -06001495 Slog.w(TAG, "vold listener rejected; trying again", e);
1496 }
Jeff Sharkey1019de92017-09-06 13:47:03 -06001497 } else {
1498 Slog.w(TAG, "vold not found; trying again");
Jeff Sharkey1019de92017-09-06 13:47:03 -06001499 }
Jeff Sharkey8058fe62017-09-13 11:50:33 -06001500
Jin Qian12690d52017-10-13 18:17:04 -07001501 if (mStoraged == null || mVold == null) {
1502 BackgroundThread.getHandler().postDelayed(() -> {
1503 connect();
1504 }, DateUtils.SECOND_IN_MILLIS);
1505 } else {
1506 onDaemonConnected();
1507 }
Jeff Sharkey1019de92017-09-06 13:47:03 -06001508 }
1509
Jeff Sharkey56e62932015-03-21 20:41:00 -07001510 private void systemReady() {
Jeff Sharkey9765e442017-12-14 22:15:14 -07001511 LocalServices.getService(ActivityManagerInternal.class)
1512 .registerScreenObserver(this);
1513
Jeff Sharkeyb049e212012-09-07 23:16:01 -07001514 mSystemReady = true;
1515 mHandler.obtainMessage(H_SYSTEM_READY).sendToTarget();
1516 }
1517
Yasuhiro Matsuda87a38b52015-07-24 22:10:16 +09001518 private void bootCompleted() {
1519 mBootCompleted = true;
1520 }
1521
Jeff Sharkeyfced5342015-05-10 14:53:34 -07001522 private String getDefaultPrimaryStorageUuid() {
1523 if (SystemProperties.getBoolean(StorageManager.PROP_PRIMARY_PHYSICAL, false)) {
1524 return StorageManager.UUID_PRIMARY_PHYSICAL;
1525 } else {
1526 return StorageManager.UUID_PRIVATE_INTERNAL;
1527 }
1528 }
1529
Andreas Gampea36dc622018-02-05 17:19:22 -08001530 @GuardedBy("mLock")
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001531 private void readSettingsLocked() {
1532 mRecords.clear();
Jeff Sharkeyfced5342015-05-10 14:53:34 -07001533 mPrimaryStorageUuid = getDefaultPrimaryStorageUuid();
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 }
1555
1556 } else if (TAG_VOLUME.equals(tag)) {
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001557 final VolumeRecord rec = readVolumeRecord(in);
1558 mRecords.put(rec.fsUuid, rec);
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001559 }
1560 }
1561 }
1562 } catch (FileNotFoundException e) {
1563 // Missing metadata is okay, probably first boot
1564 } catch (IOException e) {
1565 Slog.wtf(TAG, "Failed reading metadata", e);
1566 } catch (XmlPullParserException e) {
1567 Slog.wtf(TAG, "Failed reading metadata", e);
1568 } finally {
1569 IoUtils.closeQuietly(fis);
1570 }
1571 }
1572
Andreas Gampea36dc622018-02-05 17:19:22 -08001573 @GuardedBy("mLock")
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001574 private void writeSettingsLocked() {
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001575 FileOutputStream fos = null;
1576 try {
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001577 fos = mSettingsFile.startWrite();
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001578
1579 XmlSerializer out = new FastXmlSerializer();
Wojciech Staszkiewicz9e9e2e72015-05-08 14:58:46 +01001580 out.setOutput(fos, StandardCharsets.UTF_8.name());
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001581 out.startDocument(null, true);
1582 out.startTag(null, TAG_VOLUMES);
Jeff Sharkeyfced5342015-05-10 14:53:34 -07001583 writeIntAttribute(out, ATTR_VERSION, VERSION_FIX_PRIMARY);
Jeff Sharkey620b32b2015-04-23 19:36:02 -07001584 writeStringAttribute(out, ATTR_PRIMARY_STORAGE_UUID, mPrimaryStorageUuid);
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001585 final int size = mRecords.size();
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001586 for (int i = 0; i < size; i++) {
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001587 final VolumeRecord rec = mRecords.valueAt(i);
1588 writeVolumeRecord(out, rec);
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001589 }
1590 out.endTag(null, TAG_VOLUMES);
1591 out.endDocument();
1592
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001593 mSettingsFile.finishWrite(fos);
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001594 } catch (IOException e) {
1595 if (fos != null) {
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001596 mSettingsFile.failWrite(fos);
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001597 }
1598 }
1599 }
1600
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001601 public static VolumeRecord readVolumeRecord(XmlPullParser in) throws IOException {
1602 final int type = readIntAttribute(in, ATTR_TYPE);
1603 final String fsUuid = readStringAttribute(in, ATTR_FS_UUID);
1604 final VolumeRecord meta = new VolumeRecord(type, fsUuid);
Jeff Sharkey5cc0df22015-06-17 19:44:05 -07001605 meta.partGuid = readStringAttribute(in, ATTR_PART_GUID);
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001606 meta.nickname = readStringAttribute(in, ATTR_NICKNAME);
1607 meta.userFlags = readIntAttribute(in, ATTR_USER_FLAGS);
Jeff Sharkeye8a4b662015-06-27 15:43:45 -07001608 meta.createdMillis = readLongAttribute(in, ATTR_CREATED_MILLIS);
1609 meta.lastTrimMillis = readLongAttribute(in, ATTR_LAST_TRIM_MILLIS);
1610 meta.lastBenchMillis = readLongAttribute(in, ATTR_LAST_BENCH_MILLIS);
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001611 return meta;
1612 }
1613
1614 public static void writeVolumeRecord(XmlSerializer out, VolumeRecord rec) throws IOException {
1615 out.startTag(null, TAG_VOLUME);
1616 writeIntAttribute(out, ATTR_TYPE, rec.type);
1617 writeStringAttribute(out, ATTR_FS_UUID, rec.fsUuid);
Jeff Sharkey5cc0df22015-06-17 19:44:05 -07001618 writeStringAttribute(out, ATTR_PART_GUID, rec.partGuid);
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001619 writeStringAttribute(out, ATTR_NICKNAME, rec.nickname);
1620 writeIntAttribute(out, ATTR_USER_FLAGS, rec.userFlags);
Jeff Sharkeye8a4b662015-06-27 15:43:45 -07001621 writeLongAttribute(out, ATTR_CREATED_MILLIS, rec.createdMillis);
1622 writeLongAttribute(out, ATTR_LAST_TRIM_MILLIS, rec.lastTrimMillis);
1623 writeLongAttribute(out, ATTR_LAST_BENCH_MILLIS, rec.lastBenchMillis);
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001624 out.endTag(null, TAG_VOLUME);
1625 }
1626
San Mehat207e5382010-02-04 20:46:54 -08001627 /**
San Mehat4270e1e2010-01-29 05:32:19 -08001628 * Exposed API calls below here
1629 */
1630
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001631 @Override
Sudheer Shanka2250d562016-11-07 15:41:02 -08001632 public void registerListener(IStorageEventListener listener) {
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001633 mCallbacks.register(listener);
San Mehat4270e1e2010-01-29 05:32:19 -08001634 }
1635
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001636 @Override
Sudheer Shanka2250d562016-11-07 15:41:02 -08001637 public void unregisterListener(IStorageEventListener listener) {
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001638 mCallbacks.unregister(listener);
San Mehat4270e1e2010-01-29 05:32:19 -08001639 }
1640
Jeff Sharkey48877892015-03-18 11:27:19 -07001641 @Override
Sudheer Shanka2250d562016-11-07 15:41:02 -08001642 public void shutdown(final IStorageShutdownObserver observer) {
Jeff Sharkey48877892015-03-18 11:27:19 -07001643 enforcePermission(android.Manifest.permission.SHUTDOWN);
San Mehat4270e1e2010-01-29 05:32:19 -08001644
San Mehata5078592010-03-25 09:36:54 -07001645 Slog.i(TAG, "Shutting down");
Jeff Sharkey48877892015-03-18 11:27:19 -07001646 mHandler.obtainMessage(H_SHUTDOWN, observer).sendToTarget();
San Mehat4270e1e2010-01-29 05:32:19 -08001647 }
1648
Jeff Sharkey48877892015-03-18 11:27:19 -07001649 @Override
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001650 public void mount(String volId) {
1651 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001652
Jeff Sharkeyef10ee02015-07-05 14:17:27 -07001653 final VolumeInfo vol = findVolumeByIdOrThrow(volId);
Jeff Sharkey2e606d72015-07-27 14:19:54 -07001654 if (isMountDisallowed(vol)) {
1655 throw new SecurityException("Mounting " + volId + " restricted by policy");
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001656 }
1657 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06001658 mVold.mount(vol.id, vol.mountFlags, vol.mountUserId);
Jeff Sharkeyace874b2017-09-07 15:27:33 -06001659 } catch (Exception e) {
1660 Slog.wtf(TAG, e);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001661 }
1662 }
1663
1664 @Override
1665 public void unmount(String volId) {
1666 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001667
Jeff Sharkeyef10ee02015-07-05 14:17:27 -07001668 final VolumeInfo vol = findVolumeByIdOrThrow(volId);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001669 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06001670 mVold.unmount(vol.id);
Jeff Sharkeyace874b2017-09-07 15:27:33 -06001671 } catch (Exception e) {
1672 Slog.wtf(TAG, e);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001673 }
1674 }
1675
1676 @Override
1677 public void format(String volId) {
Jeff Sharkey48877892015-03-18 11:27:19 -07001678 enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);
San Mehat5b77dab2010-01-26 13:28:50 -08001679
Jeff Sharkeyef10ee02015-07-05 14:17:27 -07001680 final VolumeInfo vol = findVolumeByIdOrThrow(volId);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001681 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06001682 mVold.format(vol.id, "auto");
Jeff Sharkeyace874b2017-09-07 15:27:33 -06001683 } catch (Exception e) {
1684 Slog.wtf(TAG, e);
Jeff Sharkey48877892015-03-18 11:27:19 -07001685 }
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001686 }
1687
1688 @Override
Jeff Sharkey7e19f532017-11-06 13:54:11 -07001689 public void benchmark(String volId, IVoldTaskListener listener) {
Jeff Sharkey9756d752015-05-14 21:07:42 -07001690 enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);
Jeff Sharkey9756d752015-05-14 21:07:42 -07001691
1692 try {
Jeff Sharkeyb302c542017-09-15 12:57:59 -06001693 mVold.benchmark(volId, new IVoldTaskListener.Stub() {
1694 @Override
1695 public void onStatus(int status, PersistableBundle extras) {
Jeff Sharkey7e19f532017-11-06 13:54:11 -07001696 dispatchOnStatus(listener, status, extras);
Jeff Sharkeyb302c542017-09-15 12:57:59 -06001697 }
1698
1699 @Override
1700 public void onFinished(int status, PersistableBundle extras) {
Jeff Sharkey7e19f532017-11-06 13:54:11 -07001701 dispatchOnFinished(listener, status, extras);
Jeff Sharkeyb302c542017-09-15 12:57:59 -06001702
1703 final String path = extras.getString("path");
1704 final String ident = extras.getString("ident");
1705 final long create = extras.getLong("create");
1706 final long run = extras.getLong("run");
1707 final long destroy = extras.getLong("destroy");
1708
1709 final DropBoxManager dropBox = mContext.getSystemService(DropBoxManager.class);
1710 dropBox.addText(TAG_STORAGE_BENCHMARK, scrubPath(path)
1711 + " " + ident + " " + create + " " + run + " " + destroy);
1712
1713 synchronized (mLock) {
1714 final VolumeRecord rec = findRecordForPath(path);
1715 if (rec != null) {
1716 rec.lastBenchMillis = System.currentTimeMillis();
1717 writeSettingsLocked();
1718 }
1719 }
1720 }
1721 });
Jeff Sharkey7e19f532017-11-06 13:54:11 -07001722 } catch (RemoteException e) {
1723 throw e.rethrowAsRuntimeException();
Jeff Sharkey9756d752015-05-14 21:07:42 -07001724 }
1725 }
1726
1727 @Override
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001728 public void partitionPublic(String diskId) {
1729 enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001730
Jeff Sharkeyeba260d2015-04-19 14:35:16 -07001731 final CountDownLatch latch = findOrCreateDiskScanLatch(diskId);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001732 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06001733 mVold.partition(diskId, IVold.PARTITION_TYPE_PUBLIC, -1);
Jeff Sharkeyedcdaf62015-07-09 09:45:36 -07001734 waitForLatch(latch, "partitionPublic", 3 * DateUtils.MINUTE_IN_MILLIS);
Jeff Sharkeyace874b2017-09-07 15:27:33 -06001735 } catch (Exception e) {
1736 Slog.wtf(TAG, e);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001737 }
1738 }
1739
1740 @Override
1741 public void partitionPrivate(String diskId) {
1742 enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);
Amith Yamasani462ac3a2015-06-30 14:21:01 -07001743 enforceAdminUser();
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001744
Jeff Sharkeyeba260d2015-04-19 14:35:16 -07001745 final CountDownLatch latch = findOrCreateDiskScanLatch(diskId);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001746 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06001747 mVold.partition(diskId, IVold.PARTITION_TYPE_PRIVATE, -1);
Jeff Sharkeyedcdaf62015-07-09 09:45:36 -07001748 waitForLatch(latch, "partitionPrivate", 3 * DateUtils.MINUTE_IN_MILLIS);
Jeff Sharkeyace874b2017-09-07 15:27:33 -06001749 } catch (Exception e) {
1750 Slog.wtf(TAG, e);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001751 }
1752 }
1753
1754 @Override
1755 public void partitionMixed(String diskId, int ratio) {
1756 enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);
Amith Yamasani462ac3a2015-06-30 14:21:01 -07001757 enforceAdminUser();
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001758
Jeff Sharkeyeba260d2015-04-19 14:35:16 -07001759 final CountDownLatch latch = findOrCreateDiskScanLatch(diskId);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001760 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06001761 mVold.partition(diskId, IVold.PARTITION_TYPE_MIXED, ratio);
Jeff Sharkeyedcdaf62015-07-09 09:45:36 -07001762 waitForLatch(latch, "partitionMixed", 3 * DateUtils.MINUTE_IN_MILLIS);
Jeff Sharkeyace874b2017-09-07 15:27:33 -06001763 } catch (Exception e) {
1764 Slog.wtf(TAG, e);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001765 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001766 }
1767
Jeff Sharkey48877892015-03-18 11:27:19 -07001768 @Override
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001769 public void setVolumeNickname(String fsUuid, String nickname) {
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001770 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001771
Jeff Sharkey50a05452015-04-29 11:24:52 -07001772 Preconditions.checkNotNull(fsUuid);
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001773 synchronized (mLock) {
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001774 final VolumeRecord rec = mRecords.get(fsUuid);
1775 rec.nickname = nickname;
Jeff Sharkey50a05452015-04-29 11:24:52 -07001776 mCallbacks.notifyVolumeRecordChanged(rec);
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001777 writeSettingsLocked();
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001778 }
1779 }
1780
1781 @Override
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001782 public void setVolumeUserFlags(String fsUuid, int flags, int mask) {
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001783 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001784
Jeff Sharkey50a05452015-04-29 11:24:52 -07001785 Preconditions.checkNotNull(fsUuid);
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001786 synchronized (mLock) {
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001787 final VolumeRecord rec = mRecords.get(fsUuid);
1788 rec.userFlags = (rec.userFlags & ~mask) | (flags & mask);
Jeff Sharkey50a05452015-04-29 11:24:52 -07001789 mCallbacks.notifyVolumeRecordChanged(rec);
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001790 writeSettingsLocked();
1791 }
1792 }
1793
1794 @Override
1795 public void forgetVolume(String fsUuid) {
1796 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001797
Jeff Sharkey50a05452015-04-29 11:24:52 -07001798 Preconditions.checkNotNull(fsUuid);
Jeff Sharkey5a9bb742015-11-03 10:15:57 -08001799
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001800 synchronized (mLock) {
Jeff Sharkey5cc0df22015-06-17 19:44:05 -07001801 final VolumeRecord rec = mRecords.remove(fsUuid);
1802 if (rec != null && !TextUtils.isEmpty(rec.partGuid)) {
Jeff Sharkeydb4b6192017-10-24 11:08:50 -06001803 mHandler.obtainMessage(H_PARTITION_FORGET, rec).sendToTarget();
Jeff Sharkey5cc0df22015-06-17 19:44:05 -07001804 }
1805 mCallbacks.notifyVolumeForgotten(fsUuid);
Jeff Sharkey50a05452015-04-29 11:24:52 -07001806
1807 // If this had been primary storage, revert back to internal and
1808 // reset vold so we bind into new volume into place.
1809 if (Objects.equals(mPrimaryStorageUuid, fsUuid)) {
Jeff Sharkeyfced5342015-05-10 14:53:34 -07001810 mPrimaryStorageUuid = getDefaultPrimaryStorageUuid();
Jeff Sharkey5a9bb742015-11-03 10:15:57 -08001811 mHandler.obtainMessage(H_RESET).sendToTarget();
Jeff Sharkey50a05452015-04-29 11:24:52 -07001812 }
1813
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001814 writeSettingsLocked();
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001815 }
1816 }
1817
Jeff Sharkey7d2af542015-05-12 15:27:15 -07001818 @Override
1819 public void forgetAllVolumes() {
1820 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
Jeff Sharkey7d2af542015-05-12 15:27:15 -07001821
Jeff Sharkey50a05452015-04-29 11:24:52 -07001822 synchronized (mLock) {
1823 for (int i = 0; i < mRecords.size(); i++) {
1824 final String fsUuid = mRecords.keyAt(i);
Jeff Sharkey5cc0df22015-06-17 19:44:05 -07001825 final VolumeRecord rec = mRecords.valueAt(i);
1826 if (!TextUtils.isEmpty(rec.partGuid)) {
Jeff Sharkeydb4b6192017-10-24 11:08:50 -06001827 mHandler.obtainMessage(H_PARTITION_FORGET, rec).sendToTarget();
Jeff Sharkey5cc0df22015-06-17 19:44:05 -07001828 }
Jeff Sharkey50a05452015-04-29 11:24:52 -07001829 mCallbacks.notifyVolumeForgotten(fsUuid);
1830 }
Jeff Sharkey50a05452015-04-29 11:24:52 -07001831 mRecords.clear();
Jeff Sharkey50a05452015-04-29 11:24:52 -07001832
Jeff Sharkeyfced5342015-05-10 14:53:34 -07001833 if (!Objects.equals(StorageManager.UUID_PRIVATE_INTERNAL, mPrimaryStorageUuid)) {
1834 mPrimaryStorageUuid = getDefaultPrimaryStorageUuid();
1835 }
1836
1837 writeSettingsLocked();
Jeff Sharkey5a9bb742015-11-03 10:15:57 -08001838 mHandler.obtainMessage(H_RESET).sendToTarget();
Jeff Sharkey50a05452015-04-29 11:24:52 -07001839 }
1840 }
1841
Jeff Sharkeydb4b6192017-10-24 11:08:50 -06001842 private void forgetPartition(String partGuid, String fsUuid) {
Jeff Sharkey5cc0df22015-06-17 19:44:05 -07001843 try {
Jeff Sharkeydb4b6192017-10-24 11:08:50 -06001844 mVold.forgetPartition(partGuid, fsUuid);
Jeff Sharkeyace874b2017-09-07 15:27:33 -06001845 } catch (Exception e) {
1846 Slog.wtf(TAG, e);
Jeff Sharkey5cc0df22015-06-17 19:44:05 -07001847 }
1848 }
1849
Jeff Sharkey31d0b702016-11-21 14:16:53 -07001850 @Override
Jeff Sharkey7e19f532017-11-06 13:54:11 -07001851 public void fstrim(int flags, IVoldTaskListener listener) {
Jeff Sharkey31d0b702016-11-21 14:16:53 -07001852 enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);
Jeff Sharkey31d0b702016-11-21 14:16:53 -07001853
1854 try {
Jeff Sharkeyb302c542017-09-15 12:57:59 -06001855 mVold.fstrim(flags, new IVoldTaskListener.Stub() {
1856 @Override
1857 public void onStatus(int status, PersistableBundle extras) {
Jeff Sharkey7e19f532017-11-06 13:54:11 -07001858 dispatchOnStatus(listener, status, extras);
1859
Jeff Sharkeyb302c542017-09-15 12:57:59 -06001860 // Ignore trim failures
1861 if (status != 0) return;
1862
1863 final String path = extras.getString("path");
1864 final long bytes = extras.getLong("bytes");
1865 final long time = extras.getLong("time");
1866
1867 final DropBoxManager dropBox = mContext.getSystemService(DropBoxManager.class);
1868 dropBox.addText(TAG_STORAGE_TRIM, scrubPath(path) + " " + bytes + " " + time);
1869
1870 synchronized (mLock) {
1871 final VolumeRecord rec = findRecordForPath(path);
1872 if (rec != null) {
1873 rec.lastTrimMillis = System.currentTimeMillis();
1874 writeSettingsLocked();
1875 }
1876 }
1877 }
1878
1879 @Override
1880 public void onFinished(int status, PersistableBundle extras) {
Jeff Sharkey7e19f532017-11-06 13:54:11 -07001881 dispatchOnFinished(listener, status, extras);
1882
Jeff Sharkeyb302c542017-09-15 12:57:59 -06001883 // TODO: benchmark when desired
1884 }
1885 });
Jeff Sharkey7e19f532017-11-06 13:54:11 -07001886 } catch (RemoteException e) {
1887 throw e.rethrowAsRuntimeException();
Jeff Sharkey31d0b702016-11-21 14:16:53 -07001888 }
1889 }
1890
Jin Qiana85b9912017-10-17 15:48:18 -07001891 void runIdleMaint(Runnable callback) {
1892 enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);
1893
1894 try {
1895 mVold.runIdleMaint(new IVoldTaskListener.Stub() {
1896 @Override
1897 public void onStatus(int status, PersistableBundle extras) {
1898 // Not currently used
1899 }
1900 @Override
1901 public void onFinished(int status, PersistableBundle extras) {
1902 if (callback != null) {
1903 BackgroundThread.getHandler().post(callback);
1904 }
1905 }
1906 });
1907 } catch (Exception e) {
1908 Slog.wtf(TAG, e);
1909 }
1910 }
1911
1912 @Override
1913 public void runIdleMaintenance() {
1914 runIdleMaint(null);
1915 }
1916
1917 void abortIdleMaint(Runnable callback) {
1918 enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);
1919
1920 try {
1921 mVold.abortIdleMaint(new IVoldTaskListener.Stub() {
1922 @Override
1923 public void onStatus(int status, PersistableBundle extras) {
1924 // Not currently used
1925 }
1926 @Override
1927 public void onFinished(int status, PersistableBundle extras) {
1928 if (callback != null) {
1929 BackgroundThread.getHandler().post(callback);
1930 }
1931 }
1932 });
1933 } catch (Exception e) {
1934 Slog.wtf(TAG, e);
1935 }
1936 }
1937
1938 @Override
1939 public void abortIdleMaintenance() {
1940 abortIdleMaint(null);
1941 }
1942
Svet Ganov6ee871e2015-07-10 14:29:33 -07001943 private void remountUidExternalStorage(int uid, int mode) {
Jeff Sharkey9527b222015-06-24 15:24:48 -07001944 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06001945 mVold.remountUid(uid, mode);
Jeff Sharkeyace874b2017-09-07 15:27:33 -06001946 } catch (Exception e) {
1947 Slog.wtf(TAG, e);
Jeff Sharkey9527b222015-06-24 15:24:48 -07001948 }
1949 }
1950
1951 @Override
Jeff Sharkey4c099d02015-05-15 13:45:00 -07001952 public void setDebugFlags(int flags, int mask) {
1953 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
Jeff Sharkey4c099d02015-05-15 13:45:00 -07001954
Jeff Sharkeyba512352015-11-12 20:17:45 -08001955 if ((mask & StorageManager.DEBUG_EMULATE_FBE) != 0) {
Jeff Sharkey00455bf2016-11-04 14:45:24 -06001956 if (!EMULATE_FBE_SUPPORTED) {
1957 throw new IllegalStateException(
1958 "Emulation not supported on this device");
1959 }
Paul Lawrence20be5d62016-02-26 13:51:17 -08001960 if (StorageManager.isFileEncryptedNativeOnly()) {
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07001961 throw new IllegalStateException(
Jeff Sharkey00455bf2016-11-04 14:45:24 -06001962 "Emulation not supported on device with native FBE");
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07001963 }
Jeff Sharkey5a785162016-03-21 13:02:06 -06001964 if (mLockPatternUtils.isCredentialRequiredToDecrypt(false)) {
1965 throw new IllegalStateException(
1966 "Emulation requires disabling 'Secure start-up' in Settings > Security");
1967 }
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07001968
Jeff Sharkey1176e512016-02-29 17:01:26 -07001969 final long token = Binder.clearCallingIdentity();
1970 try {
1971 final boolean emulateFbe = (flags & StorageManager.DEBUG_EMULATE_FBE) != 0;
1972 SystemProperties.set(StorageManager.PROP_EMULATE_FBE, Boolean.toString(emulateFbe));
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07001973
Jeff Sharkey1176e512016-02-29 17:01:26 -07001974 // Perform hard reboot to kick policy into place
1975 mContext.getSystemService(PowerManager.class).reboot(null);
1976 } finally {
1977 Binder.restoreCallingIdentity(token);
1978 }
Jeff Sharkeyba512352015-11-12 20:17:45 -08001979 }
Jeff Sharkey4c099d02015-05-15 13:45:00 -07001980
Jeff Sharkey901c0422018-04-20 13:11:20 -06001981 if ((mask & (StorageManager.DEBUG_ADOPTABLE_FORCE_ON
1982 | StorageManager.DEBUG_ADOPTABLE_FORCE_OFF)) != 0) {
1983 final String value;
1984 if ((flags & StorageManager.DEBUG_ADOPTABLE_FORCE_ON) != 0) {
1985 value = "force_on";
1986 } else if ((flags & StorageManager.DEBUG_ADOPTABLE_FORCE_OFF) != 0) {
1987 value = "force_off";
1988 } else {
1989 value = "";
1990 }
Jeff Sharkeyba512352015-11-12 20:17:45 -08001991
Jeff Sharkey901c0422018-04-20 13:11:20 -06001992 final long token = Binder.clearCallingIdentity();
1993 try {
1994 SystemProperties.set(StorageManager.PROP_ADOPTABLE, value);
1995
1996 // Reset storage to kick new setting into place
Jeff Sharkeyba512352015-11-12 20:17:45 -08001997 mHandler.obtainMessage(H_RESET).sendToTarget();
Jeff Sharkey901c0422018-04-20 13:11:20 -06001998 } finally {
1999 Binder.restoreCallingIdentity(token);
Jeff Sharkeyba512352015-11-12 20:17:45 -08002000 }
Jeff Sharkey4c099d02015-05-15 13:45:00 -07002001 }
Jeff Sharkey33dd1562016-04-07 11:05:33 -06002002
2003 if ((mask & (StorageManager.DEBUG_SDCARDFS_FORCE_ON
2004 | StorageManager.DEBUG_SDCARDFS_FORCE_OFF)) != 0) {
2005 final String value;
2006 if ((flags & StorageManager.DEBUG_SDCARDFS_FORCE_ON) != 0) {
2007 value = "force_on";
2008 } else if ((flags & StorageManager.DEBUG_SDCARDFS_FORCE_OFF) != 0) {
2009 value = "force_off";
2010 } else {
2011 value = "";
2012 }
2013
2014 final long token = Binder.clearCallingIdentity();
2015 try {
2016 SystemProperties.set(StorageManager.PROP_SDCARDFS, value);
2017
2018 // Reset storage to kick new setting into place
2019 mHandler.obtainMessage(H_RESET).sendToTarget();
2020 } finally {
2021 Binder.restoreCallingIdentity(token);
2022 }
2023 }
Jeff Sharkeye53e2d92017-03-25 23:14:06 -06002024
2025 if ((mask & StorageManager.DEBUG_VIRTUAL_DISK) != 0) {
2026 final boolean enabled = (flags & StorageManager.DEBUG_VIRTUAL_DISK) != 0;
2027
2028 final long token = Binder.clearCallingIdentity();
2029 try {
2030 SystemProperties.set(StorageManager.PROP_VIRTUAL_DISK, Boolean.toString(enabled));
2031
2032 // Reset storage to kick new setting into place
2033 mHandler.obtainMessage(H_RESET).sendToTarget();
2034 } finally {
2035 Binder.restoreCallingIdentity(token);
2036 }
2037 }
Jeff Sharkey4c099d02015-05-15 13:45:00 -07002038 }
2039
2040 @Override
Jeff Sharkey275e3e42015-04-24 16:10:32 -07002041 public String getPrimaryStorageUuid() {
Jeff Sharkey620b32b2015-04-23 19:36:02 -07002042 synchronized (mLock) {
2043 return mPrimaryStorageUuid;
2044 }
2045 }
2046
2047 @Override
Jeff Sharkey275e3e42015-04-24 16:10:32 -07002048 public void setPrimaryStorageUuid(String volumeUuid, IPackageMoveObserver callback) {
2049 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
Jeff Sharkey620b32b2015-04-23 19:36:02 -07002050
Jeff Sharkeya31460c2016-06-22 09:04:33 -06002051 final VolumeInfo from;
2052 final VolumeInfo to;
2053
Jeff Sharkey275e3e42015-04-24 16:10:32 -07002054 synchronized (mLock) {
Jeff Sharkeyfced5342015-05-10 14:53:34 -07002055 if (Objects.equals(mPrimaryStorageUuid, volumeUuid)) {
2056 throw new IllegalArgumentException("Primary storage already at " + volumeUuid);
Jeff Sharkey275e3e42015-04-24 16:10:32 -07002057 }
2058
2059 if (mMoveCallback != null) {
2060 throw new IllegalStateException("Move already in progress");
2061 }
2062 mMoveCallback = callback;
2063 mMoveTargetUuid = volumeUuid;
2064
Jeff Sharkeya65e6492017-06-21 13:45:11 -06002065 // We need all the users unlocked to move their primary storage
2066 final List<UserInfo> users = mContext.getSystemService(UserManager.class).getUsers();
2067 for (UserInfo user : users) {
2068 if (StorageManager.isFileEncryptedNativeOrEmulated()
2069 && !isUserKeyUnlocked(user.id)) {
2070 Slog.w(TAG, "Failing move due to locked user " + user.id);
2071 onMoveStatusLocked(PackageManager.MOVE_FAILED_LOCKED_USER);
2072 return;
2073 }
2074 }
2075
Jeff Sharkeyfced5342015-05-10 14:53:34 -07002076 // When moving to/from primary physical volume, we probably just nuked
2077 // the current storage location, so we have nothing to move.
2078 if (Objects.equals(StorageManager.UUID_PRIMARY_PHYSICAL, mPrimaryStorageUuid)
2079 || Objects.equals(StorageManager.UUID_PRIMARY_PHYSICAL, volumeUuid)) {
2080 Slog.d(TAG, "Skipping move to/from primary physical");
2081 onMoveStatusLocked(MOVE_STATUS_COPY_FINISHED);
2082 onMoveStatusLocked(PackageManager.MOVE_SUCCEEDED);
Jeff Sharkey5a9bb742015-11-03 10:15:57 -08002083 mHandler.obtainMessage(H_RESET).sendToTarget();
Jeff Sharkeya31460c2016-06-22 09:04:33 -06002084 return;
Jeff Sharkeyfced5342015-05-10 14:53:34 -07002085
2086 } else {
Jeff Sharkeya31460c2016-06-22 09:04:33 -06002087 from = findStorageForUuid(mPrimaryStorageUuid);
2088 to = findStorageForUuid(volumeUuid);
Jeff Sharkeyef10ee02015-07-05 14:17:27 -07002089
2090 if (from == null) {
2091 Slog.w(TAG, "Failing move due to missing from volume " + mPrimaryStorageUuid);
2092 onMoveStatusLocked(PackageManager.MOVE_FAILED_INTERNAL_ERROR);
2093 return;
2094 } else if (to == null) {
2095 Slog.w(TAG, "Failing move due to missing to volume " + volumeUuid);
2096 onMoveStatusLocked(PackageManager.MOVE_FAILED_INTERNAL_ERROR);
2097 return;
2098 }
Jeff Sharkey275e3e42015-04-24 16:10:32 -07002099 }
Jeff Sharkey620b32b2015-04-23 19:36:02 -07002100 }
Jeff Sharkeya31460c2016-06-22 09:04:33 -06002101
2102 try {
Jeff Sharkeyb302c542017-09-15 12:57:59 -06002103 mVold.moveStorage(from.id, to.id, new IVoldTaskListener.Stub() {
2104 @Override
2105 public void onStatus(int status, PersistableBundle extras) {
2106 synchronized (mLock) {
2107 onMoveStatusLocked(status);
2108 }
2109 }
2110
2111 @Override
2112 public void onFinished(int status, PersistableBundle extras) {
2113 // Not currently used
2114 }
2115 });
Jeff Sharkeyace874b2017-09-07 15:27:33 -06002116 } catch (Exception e) {
2117 Slog.wtf(TAG, e);
Jeff Sharkeya31460c2016-06-22 09:04:33 -06002118 }
Jeff Sharkey620b32b2015-04-23 19:36:02 -07002119 }
2120
San Mehatb1043402010-02-05 08:26:50 -08002121 private void warnOnNotMounted() {
Jeff Sharkey48877892015-03-18 11:27:19 -07002122 synchronized (mLock) {
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07002123 for (int i = 0; i < mVolumes.size(); i++) {
2124 final VolumeInfo vol = mVolumes.valueAt(i);
Jeff Sharkey27de30d2015-04-18 16:20:27 -07002125 if (vol.isPrimary() && vol.isMountedWritable()) {
Jeff Sharkey48877892015-03-18 11:27:19 -07002126 // Cool beans, we have a mounted primary volume
2127 return;
2128 }
Jeff Sharkey32ee8312012-09-30 13:21:31 -07002129 }
San Mehatb1043402010-02-05 08:26:50 -08002130 }
Jeff Sharkey48877892015-03-18 11:27:19 -07002131
2132 Slog.w(TAG, "No primary storage mounted!");
San Mehatb1043402010-02-05 08:26:50 -08002133 }
2134
Kenny Roota02b8b02010-08-05 16:14:17 -07002135 private boolean isUidOwnerOfPackageOrSystem(String packageName, int callerUid) {
2136 if (callerUid == android.os.Process.SYSTEM_UID) {
2137 return true;
2138 }
2139
Kenny Root02c87302010-07-01 08:10:18 -07002140 if (packageName == null) {
2141 return false;
2142 }
2143
Jeff Sharkeycd654482016-01-08 17:42:11 -07002144 final int packageUid = mPms.getPackageUid(packageName,
2145 PackageManager.MATCH_DEBUG_TRIAGED_MISSING, UserHandle.getUserId(callerUid));
Kenny Root02c87302010-07-01 08:10:18 -07002146
2147 if (DEBUG_OBB) {
2148 Slog.d(TAG, "packageName = " + packageName + ", packageUid = " +
2149 packageUid + ", callerUid = " + callerUid);
2150 }
2151
2152 return callerUid == packageUid;
2153 }
2154
Jeff Sharkey54402792017-09-15 16:05:19 -06002155 @Override
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002156 public String getMountedObbPath(String rawPath) {
2157 Preconditions.checkNotNull(rawPath, "rawPath cannot be null");
Kenny Rootaf9d6672010-10-08 09:21:39 -07002158
Kenny Root02c87302010-07-01 08:10:18 -07002159 warnOnNotMounted();
2160
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002161 final ObbState state;
Rubin Xucd7a0142015-04-17 23:45:27 +01002162 synchronized (mObbMounts) {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002163 state = mObbPathToStateMap.get(rawPath);
2164 }
2165 if (state == null) {
2166 Slog.w(TAG, "Failed to find OBB mounted at " + rawPath);
2167 return null;
2168 }
2169
Jeff Sharkey54402792017-09-15 16:05:19 -06002170 return findVolumeByIdOrThrow(state.volId).getPath().getAbsolutePath();
Kenny Root02c87302010-07-01 08:10:18 -07002171 }
2172
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002173 @Override
2174 public boolean isObbMounted(String rawPath) {
2175 Preconditions.checkNotNull(rawPath, "rawPath cannot be null");
Kenny Rootaf9d6672010-10-08 09:21:39 -07002176 synchronized (mObbMounts) {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002177 return mObbPathToStateMap.containsKey(rawPath);
Kenny Rootaf9d6672010-10-08 09:21:39 -07002178 }
Kenny Root02c87302010-07-01 08:10:18 -07002179 }
2180
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002181 @Override
2182 public void mountObb(
2183 String rawPath, String canonicalPath, String key, IObbActionListener token, int nonce) {
2184 Preconditions.checkNotNull(rawPath, "rawPath cannot be null");
2185 Preconditions.checkNotNull(canonicalPath, "canonicalPath cannot be null");
2186 Preconditions.checkNotNull(token, "token cannot be null");
Kenny Rootaf9d6672010-10-08 09:21:39 -07002187
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002188 final int callingUid = Binder.getCallingUid();
Jeff Sharkey41cd6812017-09-11 10:32:17 -06002189 final ObbState obbState = new ObbState(rawPath, canonicalPath,
2190 callingUid, token, nonce, null);
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002191 final ObbAction action = new MountObbAction(obbState, key, callingUid);
Kenny Roota02b8b02010-08-05 16:14:17 -07002192 mObbActionHandler.sendMessage(mObbActionHandler.obtainMessage(OBB_RUN_ACTION, action));
2193
2194 if (DEBUG_OBB)
2195 Slog.i(TAG, "Send to OBB handler: " + action.toString());
Kenny Root02c87302010-07-01 08:10:18 -07002196 }
2197
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002198 @Override
2199 public void unmountObb(String rawPath, boolean force, IObbActionListener token, int nonce) {
2200 Preconditions.checkNotNull(rawPath, "rawPath cannot be null");
2201
2202 final ObbState existingState;
Rubin Xucd7a0142015-04-17 23:45:27 +01002203 synchronized (mObbMounts) {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002204 existingState = mObbPathToStateMap.get(rawPath);
Kenny Rootf1121dc2010-09-29 07:30:53 -07002205 }
2206
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002207 if (existingState != null) {
2208 // TODO: separate state object from request data
2209 final int callingUid = Binder.getCallingUid();
Jeff Sharkey41cd6812017-09-11 10:32:17 -06002210 final ObbState newState = new ObbState(rawPath, existingState.canonicalPath,
2211 callingUid, token, nonce, existingState.volId);
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002212 final ObbAction action = new UnmountObbAction(newState, force);
2213 mObbActionHandler.sendMessage(mObbActionHandler.obtainMessage(OBB_RUN_ACTION, action));
Kenny Root02c87302010-07-01 08:10:18 -07002214
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002215 if (DEBUG_OBB)
2216 Slog.i(TAG, "Send to OBB handler: " + action.toString());
2217 } else {
2218 Slog.w(TAG, "Unknown OBB mount at " + rawPath);
2219 }
Kenny Roota02b8b02010-08-05 16:14:17 -07002220 }
2221
Ben Komalo444eca22011-09-01 15:17:44 -07002222 @Override
2223 public int getEncryptionState() {
2224 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
2225 "no permission to access the crypt keeper");
2226
Ben Komalo444eca22011-09-01 15:17:44 -07002227 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002228 return mVold.fdeComplete();
2229 } catch (Exception e) {
2230 Slog.wtf(TAG, e);
Sudheer Shankaf7341142016-10-18 17:15:18 -07002231 return StorageManager.ENCRYPTION_STATE_ERROR_UNKNOWN;
Ben Komalo444eca22011-09-01 15:17:44 -07002232 }
2233 }
2234
2235 @Override
Jason parks5af0b912010-11-29 09:05:25 -06002236 public int decryptStorage(String password) {
Jason parks8888c592011-01-20 22:46:41 -06002237 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
2238 "no permission to access the crypt keeper");
Jason parks5af0b912010-11-29 09:05:25 -06002239
Jeff Sharkey8058fe62017-09-13 11:50:33 -06002240 if (TextUtils.isEmpty(password)) {
2241 throw new IllegalArgumentException("password cannot be empty");
2242 }
2243
Jason parks5af0b912010-11-29 09:05:25 -06002244 if (DEBUG_EVENTS) {
2245 Slog.i(TAG, "decrypting storage...");
2246 }
2247
2248 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002249 mVold.fdeCheckPassword(password);
2250 mHandler.postDelayed(() -> {
2251 try {
2252 mVold.fdeRestart();
2253 } catch (Exception e) {
2254 Slog.wtf(TAG, e);
2255 }
2256 }, DateUtils.SECOND_IN_MILLIS);
2257 return 0;
Paul Crowleyfc0b5192018-07-02 13:58:10 -07002258 } catch (ServiceSpecificException e) {
2259 Slog.e(TAG, "fdeCheckPassword failed", e);
2260 return e.errorCode;
Jeff Sharkey54402792017-09-15 16:05:19 -06002261 } catch (Exception e) {
2262 Slog.wtf(TAG, e);
2263 return StorageManager.ENCRYPTION_STATE_ERROR_UNKNOWN;
Jason parks5af0b912010-11-29 09:05:25 -06002264 }
Jason parks5af0b912010-11-29 09:05:25 -06002265 }
2266
Jeff Sharkey54402792017-09-15 16:05:19 -06002267 @Override
Paul Lawrence46791e72014-04-03 09:10:26 -07002268 public int encryptStorage(int type, String password) {
Jason parks8888c592011-01-20 22:46:41 -06002269 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
2270 "no permission to access the crypt keeper");
Jason parks56aa5322011-01-07 09:01:15 -06002271
Jeff Sharkey8058fe62017-09-13 11:50:33 -06002272 if (type == StorageManager.CRYPT_TYPE_DEFAULT) {
2273 password = "";
2274 } else if (TextUtils.isEmpty(password)) {
2275 throw new IllegalArgumentException("password cannot be empty");
2276 }
2277
Jason parks56aa5322011-01-07 09:01:15 -06002278 if (DEBUG_EVENTS) {
Jason parks8888c592011-01-20 22:46:41 -06002279 Slog.i(TAG, "encrypting storage...");
Jason parks56aa5322011-01-07 09:01:15 -06002280 }
2281
2282 try {
Paul Lawrence89a0ae42017-12-22 10:11:10 -08002283 mVold.fdeEnable(type, password, 0);
Jeff Sharkey43e12112017-09-12 16:31:45 -06002284 } catch (Exception e) {
2285 Slog.wtf(TAG, e);
2286 return -1;
Jason parks56aa5322011-01-07 09:01:15 -06002287 }
2288
2289 return 0;
2290 }
2291
Paul Lawrence8e397362014-01-27 15:22:30 -08002292 /** Set the password for encrypting the master key.
2293 * @param type One of the CRYPTO_TYPE_XXX consts defined in StorageManager.
2294 * @param password The password to set.
2295 */
Jeff Sharkey54402792017-09-15 16:05:19 -06002296 @Override
Paul Lawrence8e397362014-01-27 15:22:30 -08002297 public int changeEncryptionPassword(int type, String password) {
Jason parksf7b3cd42011-01-27 09:28:25 -06002298 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
2299 "no permission to access the crypt keeper");
2300
Jeff Sharkeyae266462017-11-27 13:32:24 -07002301 if (StorageManager.isFileEncryptedNativeOnly()) {
2302 // Not supported on FBE devices
2303 return -1;
2304 }
2305
Jeff Sharkey8058fe62017-09-13 11:50:33 -06002306 if (type == StorageManager.CRYPT_TYPE_DEFAULT) {
2307 password = "";
2308 } else if (TextUtils.isEmpty(password)) {
2309 throw new IllegalArgumentException("password cannot be empty");
2310 }
2311
Jason parksf7b3cd42011-01-27 09:28:25 -06002312 if (DEBUG_EVENTS) {
2313 Slog.i(TAG, "changing encryption password...");
2314 }
2315
2316 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002317 mVold.fdeChangePassword(type, password);
2318 return 0;
2319 } catch (Exception e) {
2320 Slog.wtf(TAG, e);
2321 return -1;
Jason parksf7b3cd42011-01-27 09:28:25 -06002322 }
2323 }
2324
Christopher Tate32418be2011-10-10 13:51:12 -07002325 /**
2326 * Validate a user-supplied password string with cryptfs
2327 */
2328 @Override
2329 public int verifyEncryptionPassword(String password) throws RemoteException {
2330 // Only the system process is permitted to validate passwords
2331 if (Binder.getCallingUid() != android.os.Process.SYSTEM_UID) {
2332 throw new SecurityException("no permission to access the crypt keeper");
2333 }
2334
2335 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
2336 "no permission to access the crypt keeper");
2337
2338 if (TextUtils.isEmpty(password)) {
2339 throw new IllegalArgumentException("password cannot be empty");
2340 }
2341
Christopher Tate32418be2011-10-10 13:51:12 -07002342 if (DEBUG_EVENTS) {
2343 Slog.i(TAG, "validating encryption password...");
2344 }
2345
2346 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002347 mVold.fdeVerifyPassword(password);
2348 return 0;
2349 } catch (Exception e) {
2350 Slog.wtf(TAG, e);
2351 return -1;
Christopher Tate32418be2011-10-10 13:51:12 -07002352 }
2353 }
2354
Paul Lawrence8e397362014-01-27 15:22:30 -08002355 /**
2356 * Get the type of encryption used to encrypt the master key.
2357 * @return The type, one of the CRYPT_TYPE_XXX consts from StorageManager.
2358 */
2359 @Override
Svetoslav16e4a1a2014-09-29 18:16:20 -07002360 public int getPasswordType() {
Paul Lawrence76a40572017-03-15 11:08:04 -07002361 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
Paul Lawrence9de713d2016-05-02 22:45:33 +00002362 "no permission to access the crypt keeper");
2363
Paul Lawrence8e397362014-01-27 15:22:30 -08002364 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002365 return mVold.fdeGetPasswordType();
2366 } catch (Exception e) {
2367 Slog.wtf(TAG, e);
2368 return -1;
Paul Lawrence8e397362014-01-27 15:22:30 -08002369 }
2370 }
2371
Paul Lawrencee51dcf92014-03-18 10:56:00 -07002372 /**
2373 * Set a field in the crypto header.
2374 * @param field field to set
2375 * @param contents contents to set in field
2376 */
2377 @Override
2378 public void setField(String field, String contents) throws RemoteException {
Paul Lawrence76a40572017-03-15 11:08:04 -07002379 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
Paul Lawrence0bbd1082016-04-26 15:21:02 -07002380 "no permission to access the crypt keeper");
Paul Lawrencee51dcf92014-03-18 10:56:00 -07002381
Jeff Sharkeyae266462017-11-27 13:32:24 -07002382 if (StorageManager.isFileEncryptedNativeOnly()) {
2383 // Not supported on FBE devices
2384 return;
2385 }
2386
Paul Lawrencee51dcf92014-03-18 10:56:00 -07002387 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002388 mVold.fdeSetField(field, contents);
2389 return;
2390 } catch (Exception e) {
2391 Slog.wtf(TAG, e);
2392 return;
Paul Lawrencee51dcf92014-03-18 10:56:00 -07002393 }
2394 }
2395
2396 /**
2397 * Gets a field from the crypto header.
2398 * @param field field to get
2399 * @return contents of field
2400 */
2401 @Override
2402 public String getField(String field) throws RemoteException {
Paul Lawrence76a40572017-03-15 11:08:04 -07002403 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
Paul Lawrence0bbd1082016-04-26 15:21:02 -07002404 "no permission to access the crypt keeper");
Paul Lawrencee51dcf92014-03-18 10:56:00 -07002405
Jeff Sharkeyae266462017-11-27 13:32:24 -07002406 if (StorageManager.isFileEncryptedNativeOnly()) {
2407 // Not supported on FBE devices
2408 return null;
2409 }
2410
Paul Lawrencee51dcf92014-03-18 10:56:00 -07002411 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002412 return mVold.fdeGetField(field);
2413 } catch (Exception e) {
2414 Slog.wtf(TAG, e);
2415 return null;
Paul Lawrencee51dcf92014-03-18 10:56:00 -07002416 }
2417 }
2418
Paul Lawrence3806d9c2015-10-29 10:30:46 -07002419 /**
2420 * Is userdata convertible to file based encryption?
2421 * @return non zero for convertible
2422 */
2423 @Override
2424 public boolean isConvertibleToFBE() throws RemoteException {
Paul Lawrence76a40572017-03-15 11:08:04 -07002425 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
Paul Lawrence0bbd1082016-04-26 15:21:02 -07002426 "no permission to access the crypt keeper");
Paul Lawrence3806d9c2015-10-29 10:30:46 -07002427
Paul Lawrence3806d9c2015-10-29 10:30:46 -07002428 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002429 return mVold.isConvertibleToFbe();
2430 } catch (Exception e) {
2431 Slog.wtf(TAG, e);
2432 return false;
Paul Lawrence3806d9c2015-10-29 10:30:46 -07002433 }
2434 }
2435
Jeff Sharkeyb049e212012-09-07 23:16:01 -07002436 @Override
Paul Lawrence945490c2014-03-27 16:37:28 +00002437 public String getPassword() throws RemoteException {
Paul Lawrence76a40572017-03-15 11:08:04 -07002438 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
Rubin Xucd7a0142015-04-17 23:45:27 +01002439 "only keyguard can retrieve password");
Paul Lawrence0bbd1082016-04-26 15:21:02 -07002440
Paul Lawrence945490c2014-03-27 16:37:28 +00002441 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002442 return mVold.fdeGetPassword();
2443 } catch (Exception e) {
2444 Slog.wtf(TAG, e);
Paul Lawrence24063b52015-01-06 13:11:23 -08002445 return null;
Paul Lawrence945490c2014-03-27 16:37:28 +00002446 }
2447 }
2448
2449 @Override
2450 public void clearPassword() throws RemoteException {
Paul Lawrence76a40572017-03-15 11:08:04 -07002451 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
Paul Lawrence0bbd1082016-04-26 15:21:02 -07002452 "only keyguard can clear password");
2453
Paul Lawrence945490c2014-03-27 16:37:28 +00002454 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002455 mVold.fdeClearPassword();
2456 return;
2457 } catch (Exception e) {
2458 Slog.wtf(TAG, e);
2459 return;
Paul Lawrence945490c2014-03-27 16:37:28 +00002460 }
2461 }
2462
2463 @Override
Lenka Trochtovac4dd0212015-11-18 12:22:06 +01002464 public void createUserKey(int userId, int serialNumber, boolean ephemeral) {
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002465 enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
Paul Crowleybcf48ed2015-04-22 13:36:59 +01002466
Paul Crowleybcf48ed2015-04-22 13:36:59 +01002467 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002468 mVold.createUserKey(userId, serialNumber, ephemeral);
Jeff Sharkey43e12112017-09-12 16:31:45 -06002469 } catch (Exception e) {
2470 Slog.wtf(TAG, e);
Paul Crowleybcf48ed2015-04-22 13:36:59 +01002471 }
2472 }
2473
Paul Crowley7ec733f2015-05-19 12:42:00 +01002474 @Override
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002475 public void destroyUserKey(int userId) {
2476 enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
Paul Crowley7ec733f2015-05-19 12:42:00 +01002477
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002478 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002479 mVold.destroyUserKey(userId);
Jeff Sharkey43e12112017-09-12 16:31:45 -06002480 } catch (Exception e) {
2481 Slog.wtf(TAG, e);
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002482 }
2483 }
2484
Jeff Sharkey43e12112017-09-12 16:31:45 -06002485 private String encodeBytes(byte[] bytes) {
Paul Crowleyfaeb3eb2016-02-08 15:58:29 +00002486 if (ArrayUtils.isEmpty(bytes)) {
Jeff Sharkey43e12112017-09-12 16:31:45 -06002487 return "!";
Paul Crowleyfaeb3eb2016-02-08 15:58:29 +00002488 } else {
Jeff Sharkey43e12112017-09-12 16:31:45 -06002489 return HexDump.toHexString(bytes);
Paul Crowleyfaeb3eb2016-02-08 15:58:29 +00002490 }
2491 }
2492
Paul Crowleycc701552016-05-17 14:18:49 -07002493 /*
2494 * Add this token/secret pair to the set of ways we can recover a disk encryption key.
2495 * Changing the token/secret for a disk encryption key is done in two phases: first, adding
2496 * a new token/secret pair with this call, then delting all other pairs with
2497 * fixateNewestUserKeyAuth. This allows other places where a credential is used, such as
2498 * Gatekeeper, to be updated between the two calls.
2499 */
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002500 @Override
Paul Crowleycc701552016-05-17 14:18:49 -07002501 public void addUserKeyAuth(int userId, int serialNumber, byte[] token, byte[] secret) {
Paul Crowleyfaeb3eb2016-02-08 15:58:29 +00002502 enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
Paul Crowleyfaeb3eb2016-02-08 15:58:29 +00002503
2504 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002505 mVold.addUserKeyAuth(userId, serialNumber, encodeBytes(token), encodeBytes(secret));
Jeff Sharkey43e12112017-09-12 16:31:45 -06002506 } catch (Exception e) {
2507 Slog.wtf(TAG, e);
Paul Crowleycc701552016-05-17 14:18:49 -07002508 }
2509 }
2510
2511 /*
2512 * Delete all disk encryption token/secret pairs except the most recently added one
2513 */
2514 @Override
2515 public void fixateNewestUserKeyAuth(int userId) {
2516 enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
Paul Crowleycc701552016-05-17 14:18:49 -07002517
2518 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002519 mVold.fixateNewestUserKeyAuth(userId);
Jeff Sharkey43e12112017-09-12 16:31:45 -06002520 } catch (Exception e) {
2521 Slog.wtf(TAG, e);
Paul Crowleyfaeb3eb2016-02-08 15:58:29 +00002522 }
2523 }
2524
2525 @Override
2526 public void unlockUserKey(int userId, int serialNumber, byte[] token, byte[] secret) {
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002527 enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002528
Jeff Sharkeyce18c812016-04-27 16:00:41 -06002529 if (StorageManager.isFileEncryptedNativeOrEmulated()) {
Rubin Xu3bf722a2016-12-15 16:07:38 +00002530 // When a user has secure lock screen, require secret to actually unlock.
2531 // This check is mostly in place for emulation mode.
2532 if (mLockPatternUtils.isSecure(userId) && ArrayUtils.isEmpty(secret)) {
2533 throw new IllegalStateException("Secret required to unlock secure user " + userId);
Jeff Sharkeyce18c812016-04-27 16:00:41 -06002534 }
Jeff Sharkeyb9fe5372015-12-03 15:23:08 -07002535
Jeff Sharkeyce18c812016-04-27 16:00:41 -06002536 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002537 mVold.unlockUserKey(userId, serialNumber, encodeBytes(token),
2538 encodeBytes(secret));
Jeff Sharkey43e12112017-09-12 16:31:45 -06002539 } catch (Exception e) {
2540 Slog.wtf(TAG, e);
2541 return;
Jeff Sharkeyce18c812016-04-27 16:00:41 -06002542 }
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002543 }
2544
2545 synchronized (mLock) {
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07002546 mLocalUnlockedUsers = ArrayUtils.appendInt(mLocalUnlockedUsers, userId);
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002547 }
2548 }
2549
2550 @Override
2551 public void lockUserKey(int userId) {
2552 enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002553
2554 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002555 mVold.lockUserKey(userId);
Jeff Sharkey43e12112017-09-12 16:31:45 -06002556 } catch (Exception e) {
2557 Slog.wtf(TAG, e);
2558 return;
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002559 }
2560
2561 synchronized (mLock) {
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07002562 mLocalUnlockedUsers = ArrayUtils.removeInt(mLocalUnlockedUsers, userId);
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002563 }
2564 }
2565
2566 @Override
2567 public boolean isUserKeyUnlocked(int userId) {
Jeff Sharkeyce18c812016-04-27 16:00:41 -06002568 synchronized (mLock) {
2569 return ArrayUtils.contains(mLocalUnlockedUsers, userId);
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002570 }
2571 }
2572
2573 @Override
Jeff Sharkey47f71082016-02-01 17:03:54 -07002574 public void prepareUserStorage(String volumeUuid, int userId, int serialNumber, int flags) {
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002575 enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002576
2577 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002578 mVold.prepareUserStorage(volumeUuid, userId, serialNumber, flags);
Jeff Sharkey43e12112017-09-12 16:31:45 -06002579 } catch (Exception e) {
2580 Slog.wtf(TAG, e);
Paul Crowley7ec733f2015-05-19 12:42:00 +01002581 }
2582 }
2583
Paul Crowleybcf48ed2015-04-22 13:36:59 +01002584 @Override
Jeff Sharkeyfcf1e552016-04-14 20:44:58 -06002585 public void destroyUserStorage(String volumeUuid, int userId, int flags) {
2586 enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
Jeff Sharkeyfcf1e552016-04-14 20:44:58 -06002587
2588 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002589 mVold.destroyUserStorage(volumeUuid, userId, flags);
Jeff Sharkey43e12112017-09-12 16:31:45 -06002590 } catch (Exception e) {
2591 Slog.wtf(TAG, e);
Jeff Sharkeyfcf1e552016-04-14 20:44:58 -06002592 }
2593 }
2594
Daichi Hironoe56740d2017-02-02 13:56:45 +09002595 class AppFuseMountScope extends AppFuseBridge.MountScope {
Daichi Hirono812c95d2017-02-08 16:20:20 +09002596 boolean opened = false;
2597
2598 public AppFuseMountScope(int uid, int pid, int mountId) {
2599 super(uid, pid, mountId);
2600 }
2601
2602 @Override
2603 public ParcelFileDescriptor open() throws NativeDaemonConnectorException {
Jeff Sharkey54402792017-09-15 16:05:19 -06002604 try {
2605 return new ParcelFileDescriptor(
2606 mVold.mountAppFuse(uid, Process.myPid(), mountId));
2607 } catch (Exception e) {
2608 throw new NativeDaemonConnectorException("Failed to mount", e);
Daichi Hirono812c95d2017-02-08 16:20:20 +09002609 }
Daichi Hirono9fb00182016-11-08 14:12:17 +09002610 }
2611
2612 @Override
Daichi Hironoe56740d2017-02-02 13:56:45 +09002613 public void close() throws Exception {
Daichi Hirono812c95d2017-02-08 16:20:20 +09002614 if (opened) {
Jeff Sharkey54402792017-09-15 16:05:19 -06002615 mVold.unmountAppFuse(uid, Process.myPid(), mountId);
Daichi Hirono812c95d2017-02-08 16:20:20 +09002616 opened = false;
2617 }
Daichi Hirono9fb00182016-11-08 14:12:17 +09002618 }
2619 }
2620
2621 @Override
Daichi Hirono812c95d2017-02-08 16:20:20 +09002622 public @Nullable AppFuseMount mountProxyFileDescriptorBridge() {
Daichi Hironoe56740d2017-02-02 13:56:45 +09002623 Slog.v(TAG, "mountProxyFileDescriptorBridge");
Daichi Hirono9fb00182016-11-08 14:12:17 +09002624 final int uid = Binder.getCallingUid();
2625 final int pid = Binder.getCallingPid();
Daichi Hirono9fb00182016-11-08 14:12:17 +09002626
Daichi Hironoe56740d2017-02-02 13:56:45 +09002627 while (true) {
2628 synchronized (mAppFuseLock) {
2629 boolean newlyCreated = false;
2630 if (mAppFuseBridge == null) {
2631 mAppFuseBridge = new AppFuseBridge();
2632 new Thread(mAppFuseBridge, AppFuseBridge.TAG).start();
2633 newlyCreated = true;
Daichi Hirono9fb00182016-11-08 14:12:17 +09002634 }
Daichi Hironoe56740d2017-02-02 13:56:45 +09002635 try {
2636 final int name = mNextAppFuseName++;
2637 try {
2638 return new AppFuseMount(
Daichi Hirono812c95d2017-02-08 16:20:20 +09002639 name, mAppFuseBridge.addBridge(new AppFuseMountScope(uid, pid, name)));
2640 } catch (FuseUnavailableMountException e) {
Daichi Hironoe56740d2017-02-02 13:56:45 +09002641 if (newlyCreated) {
2642 // If newly created bridge fails, it's a real error.
Daichi Hirono812c95d2017-02-08 16:20:20 +09002643 Slog.e(TAG, "", e);
2644 return null;
Daichi Hironoe56740d2017-02-02 13:56:45 +09002645 }
2646 // It seems the thread of mAppFuseBridge has already been terminated.
2647 mAppFuseBridge = null;
2648 }
2649 } catch (NativeDaemonConnectorException e) {
2650 throw e.rethrowAsParcelableException();
2651 }
Daichi Hirono9fb00182016-11-08 14:12:17 +09002652 }
Daichi Hirono9fb00182016-11-08 14:12:17 +09002653 }
2654 }
2655
2656 @Override
Daichi Hirono812c95d2017-02-08 16:20:20 +09002657 public @Nullable ParcelFileDescriptor openProxyFileDescriptor(
2658 int mountId, int fileId, int mode) {
2659 Slog.v(TAG, "mountProxyFileDescriptor");
Daichi Hirono9fb00182016-11-08 14:12:17 +09002660 final int pid = Binder.getCallingPid();
2661 try {
2662 synchronized (mAppFuseLock) {
Daichi Hironoe56740d2017-02-02 13:56:45 +09002663 if (mAppFuseBridge == null) {
Daichi Hirono812c95d2017-02-08 16:20:20 +09002664 Slog.e(TAG, "FuseBridge has not been created");
2665 return null;
Daichi Hirono9fb00182016-11-08 14:12:17 +09002666 }
Daichi Hironoe56740d2017-02-02 13:56:45 +09002667 return mAppFuseBridge.openFile(pid, mountId, fileId, mode);
Daichi Hirono9fb00182016-11-08 14:12:17 +09002668 }
Daichi Hirono812c95d2017-02-08 16:20:20 +09002669 } catch (FuseUnavailableMountException | InterruptedException error) {
2670 Slog.v(TAG, "The mount point has already been invalid", error);
2671 return null;
Daichi Hirono9fb00182016-11-08 14:12:17 +09002672 }
2673 }
2674
Daichi Hirono9e8d9e22015-11-13 14:37:00 +09002675 @Override
Jeff Sharkeyae266462017-11-27 13:32:24 -07002676 public void mkdirs(String callingPkg, String appPath) {
Jeff Sharkey2d8b4e82013-09-17 17:30:33 -07002677 final int userId = UserHandle.getUserId(Binder.getCallingUid());
2678 final UserEnvironment userEnv = new UserEnvironment(userId);
Farid Zare Seisanac094512018-04-02 15:06:13 -07002679 final String propertyName = "sys.user." + userId + ".ce_available";
Jeff Sharkey2d8b4e82013-09-17 17:30:33 -07002680
Jeff Sharkey196c7552018-03-26 15:56:50 -06002681 // Ignore requests to create directories while storage is locked
Farid Zare Seisanac094512018-04-02 15:06:13 -07002682 if (!isUserKeyUnlocked(userId)) {
2683 throw new IllegalStateException("Failed to prepare " + appPath);
2684 }
2685
2686 // Ignore requests to create directories if CE storage is not available
Farid Zare Seisan7f6b8122018-03-30 11:19:10 -07002687 if ((userId == UserHandle.USER_SYSTEM)
2688 && !SystemProperties.getBoolean(propertyName, false)) {
Farid Zare Seisanac094512018-04-02 15:06:13 -07002689 throw new IllegalStateException("Failed to prepare " + appPath);
2690 }
Jeff Sharkey196c7552018-03-26 15:56:50 -06002691
Jeff Sharkey2d8b4e82013-09-17 17:30:33 -07002692 // Validate that reported package name belongs to caller
2693 final AppOpsManager appOps = (AppOpsManager) mContext.getSystemService(
2694 Context.APP_OPS_SERVICE);
2695 appOps.checkPackage(Binder.getCallingUid(), callingPkg);
2696
Jeff Sharkey48877892015-03-18 11:27:19 -07002697 File appFile = null;
Jeff Sharkey2d8b4e82013-09-17 17:30:33 -07002698 try {
Jeff Sharkey48877892015-03-18 11:27:19 -07002699 appFile = new File(appPath).getCanonicalFile();
Jeff Sharkey2d8b4e82013-09-17 17:30:33 -07002700 } catch (IOException e) {
Jeff Sharkeyae266462017-11-27 13:32:24 -07002701 throw new IllegalStateException("Failed to resolve " + appPath + ": " + e);
Jeff Sharkey2d8b4e82013-09-17 17:30:33 -07002702 }
2703
2704 // Try translating the app path into a vold path, but require that it
2705 // belong to the calling package.
Jeff Sharkey48877892015-03-18 11:27:19 -07002706 if (FileUtils.contains(userEnv.buildExternalStorageAppDataDirs(callingPkg), appFile) ||
2707 FileUtils.contains(userEnv.buildExternalStorageAppObbDirs(callingPkg), appFile) ||
2708 FileUtils.contains(userEnv.buildExternalStorageAppMediaDirs(callingPkg), appFile)) {
2709 appPath = appFile.getAbsolutePath();
2710 if (!appPath.endsWith("/")) {
2711 appPath = appPath + "/";
2712 }
2713
Jeff Sharkey2d8b4e82013-09-17 17:30:33 -07002714 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002715 mVold.mkdirs(appPath);
Jeff Sharkey27a108c2017-11-30 17:11:40 -07002716 return;
Jeff Sharkeyace874b2017-09-07 15:27:33 -06002717 } catch (Exception e) {
Jeff Sharkeyae266462017-11-27 13:32:24 -07002718 throw new IllegalStateException("Failed to prepare " + appPath + ": " + e);
Jeff Sharkey2d8b4e82013-09-17 17:30:33 -07002719 }
2720 }
2721
Jeff Sharkey48877892015-03-18 11:27:19 -07002722 throw new SecurityException("Invalid mkdirs path: " + appFile);
Jeff Sharkey2d8b4e82013-09-17 17:30:33 -07002723 }
2724
2725 @Override
Jeff Sharkey46349872015-07-28 10:49:47 -07002726 public StorageVolume[] getVolumeList(int uid, String packageName, int flags) {
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07002727 final int userId = UserHandle.getUserId(uid);
Jeff Sharkeyc02bfae2016-03-27 15:06:53 -06002728
Jeff Sharkey46349872015-07-28 10:49:47 -07002729 final boolean forWrite = (flags & StorageManager.FLAG_FOR_WRITE) != 0;
Jeff Sharkeyc02bfae2016-03-27 15:06:53 -06002730 final boolean realState = (flags & StorageManager.FLAG_REAL_STATE) != 0;
2731 final boolean includeInvisible = (flags & StorageManager.FLAG_INCLUDE_INVISIBLE) != 0;
Jeff Sharkey46349872015-07-28 10:49:47 -07002732
Jeff Sharkeyc02bfae2016-03-27 15:06:53 -06002733 final boolean userKeyUnlocked;
2734 final boolean storagePermission;
2735 final long token = Binder.clearCallingIdentity();
Svetoslav38c3dbb2015-07-14 11:27:06 -07002736 try {
Jeff Sharkeyc02bfae2016-03-27 15:06:53 -06002737 userKeyUnlocked = isUserKeyUnlocked(userId);
Sudheer Shanka2250d562016-11-07 15:41:02 -08002738 storagePermission = mStorageManagerInternal.hasExternalStorage(uid, packageName);
Svetoslav38c3dbb2015-07-14 11:27:06 -07002739 } finally {
Jeff Sharkeyc02bfae2016-03-27 15:06:53 -06002740 Binder.restoreCallingIdentity(token);
Svetoslav38c3dbb2015-07-14 11:27:06 -07002741 }
Svet Ganov6ee871e2015-07-10 14:29:33 -07002742
Jeff Sharkeyc02bfae2016-03-27 15:06:53 -06002743 boolean foundPrimary = false;
2744
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07002745 final ArrayList<StorageVolume> res = new ArrayList<>();
Jeff Sharkey48877892015-03-18 11:27:19 -07002746 synchronized (mLock) {
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07002747 for (int i = 0; i < mVolumes.size(); i++) {
2748 final VolumeInfo vol = mVolumes.valueAt(i);
Jeff Sharkeyc02bfae2016-03-27 15:06:53 -06002749 switch (vol.getType()) {
2750 case VolumeInfo.TYPE_PUBLIC:
2751 case VolumeInfo.TYPE_EMULATED:
2752 break;
2753 default:
2754 continue;
2755 }
2756
2757 boolean match = false;
2758 if (forWrite) {
2759 match = vol.isVisibleForWrite(userId);
2760 } else {
Felipe Leme123a0e72016-06-10 11:09:11 -07002761 match = vol.isVisibleForRead(userId)
2762 || (includeInvisible && vol.getPath() != null);
Jeff Sharkeyc02bfae2016-03-27 15:06:53 -06002763 }
2764 if (!match) continue;
2765
2766 boolean reportUnmounted = false;
2767 if ((vol.getType() == VolumeInfo.TYPE_EMULATED) && !userKeyUnlocked) {
2768 reportUnmounted = true;
2769 } else if (!storagePermission && !realState) {
2770 reportUnmounted = true;
2771 }
2772
2773 final StorageVolume userVol = vol.buildStorageVolume(mContext, userId,
2774 reportUnmounted);
2775 if (vol.isPrimary()) {
2776 res.add(0, userVol);
2777 foundPrimary = true;
2778 } else {
2779 res.add(userVol);
Jeff Sharkeyb049e212012-09-07 23:16:01 -07002780 }
Mike Lockwood8fa5f802011-03-24 08:12:30 -07002781 }
Mike Lockwood8fa5f802011-03-24 08:12:30 -07002782 }
Jeff Sharkey48877892015-03-18 11:27:19 -07002783
2784 if (!foundPrimary) {
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07002785 Log.w(TAG, "No primary storage defined yet; hacking together a stub");
Jeff Sharkey48877892015-03-18 11:27:19 -07002786
2787 final boolean primaryPhysical = SystemProperties.getBoolean(
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07002788 StorageManager.PROP_PRIMARY_PHYSICAL, false);
Jeff Sharkey48877892015-03-18 11:27:19 -07002789
2790 final String id = "stub_primary";
2791 final File path = Environment.getLegacyExternalStorageDirectory();
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07002792 final String description = mContext.getString(android.R.string.unknownName);
Jeff Sharkey48877892015-03-18 11:27:19 -07002793 final boolean primary = true;
2794 final boolean removable = primaryPhysical;
2795 final boolean emulated = !primaryPhysical;
Jeff Sharkey48877892015-03-18 11:27:19 -07002796 final boolean allowMassStorage = false;
2797 final long maxFileSize = 0L;
2798 final UserHandle owner = new UserHandle(userId);
2799 final String uuid = null;
Jeff Sharkey48877892015-03-18 11:27:19 -07002800 final String state = Environment.MEDIA_REMOVED;
2801
Jerry Zhang71938e12018-05-10 18:28:29 -07002802 res.add(0, new StorageVolume(id, path, path,
Jerry Zhangf9c5c252017-08-16 18:07:51 -07002803 description, primary, removable, emulated,
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07002804 allowMassStorage, maxFileSize, owner, uuid, state));
Jeff Sharkey48877892015-03-18 11:27:19 -07002805 }
2806
2807 return res.toArray(new StorageVolume[res.size()]);
Mike Lockwood8fa5f802011-03-24 08:12:30 -07002808 }
2809
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07002810 @Override
2811 public DiskInfo[] getDisks() {
2812 synchronized (mLock) {
2813 final DiskInfo[] res = new DiskInfo[mDisks.size()];
2814 for (int i = 0; i < mDisks.size(); i++) {
2815 res[i] = mDisks.valueAt(i);
2816 }
2817 return res;
2818 }
2819 }
2820
2821 @Override
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07002822 public VolumeInfo[] getVolumes(int flags) {
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07002823 synchronized (mLock) {
2824 final VolumeInfo[] res = new VolumeInfo[mVolumes.size()];
2825 for (int i = 0; i < mVolumes.size(); i++) {
2826 res[i] = mVolumes.valueAt(i);
2827 }
2828 return res;
2829 }
2830 }
2831
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07002832 @Override
2833 public VolumeRecord[] getVolumeRecords(int flags) {
2834 synchronized (mLock) {
2835 final VolumeRecord[] res = new VolumeRecord[mRecords.size()];
2836 for (int i = 0; i < mRecords.size(); i++) {
2837 res[i] = mRecords.valueAt(i);
2838 }
2839 return res;
2840 }
2841 }
2842
Jeff Sharkey9bed0702017-01-23 20:37:05 -07002843 @Override
2844 public long getCacheQuotaBytes(String volumeUuid, int uid) {
2845 if (uid != Binder.getCallingUid()) {
2846 mContext.enforceCallingPermission(android.Manifest.permission.STORAGE_INTERNAL, TAG);
2847 }
Daniel Nishi80fdb012017-03-09 14:30:07 -08002848 final long token = Binder.clearCallingIdentity();
2849 final StorageStatsManager stats = mContext.getSystemService(StorageStatsManager.class);
2850 try {
2851 return stats.getCacheQuotaBytes(volumeUuid, uid);
2852 } finally {
2853 Binder.restoreCallingIdentity(token);
2854 }
Jeff Sharkey9bed0702017-01-23 20:37:05 -07002855 }
2856
2857 @Override
2858 public long getCacheSizeBytes(String volumeUuid, int uid) {
2859 if (uid != Binder.getCallingUid()) {
2860 mContext.enforceCallingPermission(android.Manifest.permission.STORAGE_INTERNAL, TAG);
2861 }
2862 final long token = Binder.clearCallingIdentity();
2863 try {
2864 return mContext.getSystemService(StorageStatsManager.class)
2865 .queryStatsForUid(volumeUuid, uid).getCacheBytes();
Jeff Sharkey789a8fc2017-04-16 13:18:35 -06002866 } catch (IOException e) {
2867 throw new ParcelableException(e);
Jeff Sharkey9bed0702017-01-23 20:37:05 -07002868 } finally {
2869 Binder.restoreCallingIdentity(token);
2870 }
2871 }
2872
Jeff Sharkey35e46d22017-06-09 10:01:20 -06002873 private int adjustAllocateFlags(int flags, int callingUid, String callingPackage) {
2874 // Require permission to allocate aggressively
2875 if ((flags & StorageManager.FLAG_ALLOCATE_AGGRESSIVE) != 0) {
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07002876 mContext.enforceCallingOrSelfPermission(
2877 android.Manifest.permission.ALLOCATE_AGGRESSIVE, TAG);
2878 }
2879
Jeff Sharkey35e46d22017-06-09 10:01:20 -06002880 // Apps normally can't directly defy reserved space
2881 flags &= ~StorageManager.FLAG_ALLOCATE_DEFY_ALL_RESERVED;
2882 flags &= ~StorageManager.FLAG_ALLOCATE_DEFY_HALF_RESERVED;
2883
2884 // However, if app is actively using the camera, then we're willing to
2885 // clear up to half of the reserved cache space, since the user might be
2886 // trying to capture an important memory.
2887 final AppOpsManager appOps = mContext.getSystemService(AppOpsManager.class);
2888 final long token = Binder.clearCallingIdentity();
2889 try {
2890 if (appOps.isOperationActive(AppOpsManager.OP_CAMERA, callingUid, callingPackage)) {
2891 Slog.d(TAG, "UID " + callingUid + " is actively using camera;"
2892 + " letting them defy reserved cached data");
2893 flags |= StorageManager.FLAG_ALLOCATE_DEFY_HALF_RESERVED;
2894 }
2895 } finally {
2896 Binder.restoreCallingIdentity(token);
2897 }
2898
2899 return flags;
2900 }
2901
2902 @Override
2903 public long getAllocatableBytes(String volumeUuid, int flags, String callingPackage) {
2904 flags = adjustAllocateFlags(flags, Binder.getCallingUid(), callingPackage);
2905
2906 final StorageManager storage = mContext.getSystemService(StorageManager.class);
2907 final StorageStatsManager stats = mContext.getSystemService(StorageStatsManager.class);
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07002908 final long token = Binder.clearCallingIdentity();
2909 try {
2910 // In general, apps can allocate as much space as they want, except
2911 // we never let them eat into either the minimum cache space or into
Jeff Sharkeyddff8072017-05-26 13:10:46 -06002912 // the low disk warning space. To avoid user confusion, this logic
2913 // should be kept in sync with getFreeBytes().
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07002914 final File path = storage.findPathForUuid(volumeUuid);
Jeff Sharkeyddff8072017-05-26 13:10:46 -06002915
2916 final long usable = path.getUsableSpace();
2917 final long lowReserved = storage.getStorageLowBytes(path);
2918 final long fullReserved = storage.getStorageFullBytes(path);
2919
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07002920 if (stats.isQuotaSupported(volumeUuid)) {
Jeff Sharkeyddff8072017-05-26 13:10:46 -06002921 final long cacheTotal = stats.getCacheBytes(volumeUuid);
Jeff Sharkey35e46d22017-06-09 10:01:20 -06002922 final long cacheReserved = storage.getStorageCacheBytes(path, flags);
Jeff Sharkeyddff8072017-05-26 13:10:46 -06002923 final long cacheClearable = Math.max(0, cacheTotal - cacheReserved);
2924
Jeff Sharkey35e46d22017-06-09 10:01:20 -06002925 if ((flags & StorageManager.FLAG_ALLOCATE_AGGRESSIVE) != 0) {
2926 return Math.max(0, (usable + cacheClearable) - fullReserved);
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07002927 } else {
Jeff Sharkeyddff8072017-05-26 13:10:46 -06002928 return Math.max(0, (usable + cacheClearable) - lowReserved);
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07002929 }
2930 } else {
2931 // When we don't have fast quota information, we ignore cached
2932 // data and only consider unused bytes.
Jeff Sharkey35e46d22017-06-09 10:01:20 -06002933 if ((flags & StorageManager.FLAG_ALLOCATE_AGGRESSIVE) != 0) {
Jeff Sharkeyddff8072017-05-26 13:10:46 -06002934 return Math.max(0, usable - fullReserved);
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07002935 } else {
Jeff Sharkeyddff8072017-05-26 13:10:46 -06002936 return Math.max(0, usable - lowReserved);
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07002937 }
2938 }
Jeff Sharkey789a8fc2017-04-16 13:18:35 -06002939 } catch (IOException e) {
2940 throw new ParcelableException(e);
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07002941 } finally {
2942 Binder.restoreCallingIdentity(token);
2943 }
Jeff Sharkey500ce9e2017-02-12 02:39:24 -07002944 }
2945
2946 @Override
Jeff Sharkey35e46d22017-06-09 10:01:20 -06002947 public void allocateBytes(String volumeUuid, long bytes, int flags, String callingPackage) {
2948 flags = adjustAllocateFlags(flags, Binder.getCallingUid(), callingPackage);
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07002949
Jeff Sharkey35e46d22017-06-09 10:01:20 -06002950 final long allocatableBytes = getAllocatableBytes(volumeUuid, flags, callingPackage);
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07002951 if (bytes > allocatableBytes) {
2952 throw new ParcelableException(new IOException("Failed to allocate " + bytes
2953 + " because only " + allocatableBytes + " allocatable"));
2954 }
2955
Jeff Sharkey35e46d22017-06-09 10:01:20 -06002956 final StorageManager storage = mContext.getSystemService(StorageManager.class);
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07002957 final long token = Binder.clearCallingIdentity();
2958 try {
Jeff Sharkey789a8fc2017-04-16 13:18:35 -06002959 // Free up enough disk space to satisfy both the requested allocation
2960 // and our low disk warning space.
2961 final File path = storage.findPathForUuid(volumeUuid);
Jeff Sharkeyddff8072017-05-26 13:10:46 -06002962 if ((flags & StorageManager.FLAG_ALLOCATE_AGGRESSIVE) != 0) {
2963 bytes += storage.getStorageFullBytes(path);
2964 } else {
2965 bytes += storage.getStorageLowBytes(path);
2966 }
Jeff Sharkey789a8fc2017-04-16 13:18:35 -06002967
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07002968 mPms.freeStorage(volumeUuid, bytes, flags);
2969 } catch (IOException e) {
2970 throw new ParcelableException(e);
2971 } finally {
2972 Binder.restoreCallingIdentity(token);
Jeff Sharkey500ce9e2017-02-12 02:39:24 -07002973 }
2974 }
2975
Kenny Rootaf9d6672010-10-08 09:21:39 -07002976 private void addObbStateLocked(ObbState obbState) throws RemoteException {
2977 final IBinder binder = obbState.getBinder();
2978 List<ObbState> obbStates = mObbMounts.get(binder);
Kenny Root5919ac62010-10-05 09:49:40 -07002979
Kenny Rootaf9d6672010-10-08 09:21:39 -07002980 if (obbStates == null) {
2981 obbStates = new ArrayList<ObbState>();
2982 mObbMounts.put(binder, obbStates);
2983 } else {
2984 for (final ObbState o : obbStates) {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002985 if (o.rawPath.equals(obbState.rawPath)) {
Kenny Rootaf9d6672010-10-08 09:21:39 -07002986 throw new IllegalStateException("Attempt to add ObbState twice. "
Sudheer Shanka2250d562016-11-07 15:41:02 -08002987 + "This indicates an error in the StorageManagerService logic.");
Kenny Root5919ac62010-10-05 09:49:40 -07002988 }
2989 }
Kenny Roota02b8b02010-08-05 16:14:17 -07002990 }
Kenny Rootaf9d6672010-10-08 09:21:39 -07002991
2992 obbStates.add(obbState);
2993 try {
2994 obbState.link();
2995 } catch (RemoteException e) {
2996 /*
2997 * The binder died before we could link it, so clean up our state
2998 * and return failure.
2999 */
3000 obbStates.remove(obbState);
3001 if (obbStates.isEmpty()) {
3002 mObbMounts.remove(binder);
3003 }
3004
3005 // Rethrow the error so mountObb can get it
3006 throw e;
3007 }
3008
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003009 mObbPathToStateMap.put(obbState.rawPath, obbState);
Kenny Roota02b8b02010-08-05 16:14:17 -07003010 }
3011
Kenny Rootaf9d6672010-10-08 09:21:39 -07003012 private void removeObbStateLocked(ObbState obbState) {
3013 final IBinder binder = obbState.getBinder();
3014 final List<ObbState> obbStates = mObbMounts.get(binder);
3015 if (obbStates != null) {
3016 if (obbStates.remove(obbState)) {
3017 obbState.unlink();
Kenny Root05105f72010-09-22 17:29:43 -07003018 }
Kenny Rootaf9d6672010-10-08 09:21:39 -07003019 if (obbStates.isEmpty()) {
3020 mObbMounts.remove(binder);
3021 }
Kenny Roota02b8b02010-08-05 16:14:17 -07003022 }
Kenny Roota02b8b02010-08-05 16:14:17 -07003023
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003024 mObbPathToStateMap.remove(obbState.rawPath);
Kenny Root38cf8862010-09-26 14:18:51 -07003025 }
3026
Kenny Roota02b8b02010-08-05 16:14:17 -07003027 private class ObbActionHandler extends Handler {
3028 private boolean mBound = false;
Kenny Root480afe72010-10-07 10:17:50 -07003029 private final List<ObbAction> mActions = new LinkedList<ObbAction>();
Kenny Roota02b8b02010-08-05 16:14:17 -07003030
3031 ObbActionHandler(Looper l) {
3032 super(l);
3033 }
3034
3035 @Override
3036 public void handleMessage(Message msg) {
3037 switch (msg.what) {
3038 case OBB_RUN_ACTION: {
Kenny Root480afe72010-10-07 10:17:50 -07003039 final ObbAction action = (ObbAction) msg.obj;
Kenny Roota02b8b02010-08-05 16:14:17 -07003040
3041 if (DEBUG_OBB)
3042 Slog.i(TAG, "OBB_RUN_ACTION: " + action.toString());
3043
3044 // If a bind was already initiated we don't really
3045 // need to do anything. The pending install
3046 // will be processed later on.
3047 if (!mBound) {
3048 // If this is the only one pending we might
3049 // have to bind to the service again.
3050 if (!connectToService()) {
Jeff Sharkey0095a822018-02-15 13:06:53 -07003051 action.notifyObbStateChange(new ObbException(ERROR_INTERNAL,
3052 "Failed to bind to media container service"));
Kenny Roota02b8b02010-08-05 16:14:17 -07003053 return;
Kenny Roota02b8b02010-08-05 16:14:17 -07003054 }
Kenny Roota02b8b02010-08-05 16:14:17 -07003055 }
Kenny Root735de3b2010-09-30 14:11:39 -07003056
Kenny Root735de3b2010-09-30 14:11:39 -07003057 mActions.add(action);
Kenny Roota02b8b02010-08-05 16:14:17 -07003058 break;
3059 }
3060 case OBB_MCS_BOUND: {
3061 if (DEBUG_OBB)
3062 Slog.i(TAG, "OBB_MCS_BOUND");
3063 if (msg.obj != null) {
3064 mContainerService = (IMediaContainerService) msg.obj;
3065 }
3066 if (mContainerService == null) {
3067 // Something seriously wrong. Bail out
Kenny Roota02b8b02010-08-05 16:14:17 -07003068 for (ObbAction action : mActions) {
3069 // Indicate service bind error
Jeff Sharkey0095a822018-02-15 13:06:53 -07003070 action.notifyObbStateChange(new ObbException(ERROR_INTERNAL,
3071 "Failed to bind to media container service"));
Kenny Roota02b8b02010-08-05 16:14:17 -07003072 }
3073 mActions.clear();
3074 } else if (mActions.size() > 0) {
Kenny Root480afe72010-10-07 10:17:50 -07003075 final ObbAction action = mActions.get(0);
Kenny Roota02b8b02010-08-05 16:14:17 -07003076 if (action != null) {
3077 action.execute(this);
3078 }
3079 } else {
3080 // Should never happen ideally.
3081 Slog.w(TAG, "Empty queue");
3082 }
3083 break;
3084 }
3085 case OBB_MCS_RECONNECT: {
3086 if (DEBUG_OBB)
3087 Slog.i(TAG, "OBB_MCS_RECONNECT");
3088 if (mActions.size() > 0) {
3089 if (mBound) {
3090 disconnectService();
3091 }
3092 if (!connectToService()) {
Kenny Roota02b8b02010-08-05 16:14:17 -07003093 for (ObbAction action : mActions) {
3094 // Indicate service bind error
Jeff Sharkey0095a822018-02-15 13:06:53 -07003095 action.notifyObbStateChange(new ObbException(ERROR_INTERNAL,
3096 "Failed to bind to media container service"));
Kenny Roota02b8b02010-08-05 16:14:17 -07003097 }
3098 mActions.clear();
3099 }
3100 }
3101 break;
3102 }
3103 case OBB_MCS_UNBIND: {
3104 if (DEBUG_OBB)
3105 Slog.i(TAG, "OBB_MCS_UNBIND");
3106
3107 // Delete pending install
3108 if (mActions.size() > 0) {
3109 mActions.remove(0);
3110 }
3111 if (mActions.size() == 0) {
3112 if (mBound) {
3113 disconnectService();
3114 }
3115 } else {
3116 // There are more pending requests in queue.
3117 // Just post MCS_BOUND message to trigger processing
3118 // of next pending install.
3119 mObbActionHandler.sendEmptyMessage(OBB_MCS_BOUND);
3120 }
3121 break;
3122 }
Kenny Rootaf9d6672010-10-08 09:21:39 -07003123 case OBB_FLUSH_MOUNT_STATE: {
3124 final String path = (String) msg.obj;
3125
3126 if (DEBUG_OBB)
3127 Slog.i(TAG, "Flushing all OBB state for path " + path);
3128
3129 synchronized (mObbMounts) {
3130 final List<ObbState> obbStatesToRemove = new LinkedList<ObbState>();
3131
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003132 final Iterator<ObbState> i = mObbPathToStateMap.values().iterator();
Kenny Rootaf9d6672010-10-08 09:21:39 -07003133 while (i.hasNext()) {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003134 final ObbState state = i.next();
Kenny Rootaf9d6672010-10-08 09:21:39 -07003135
3136 /*
3137 * If this entry's source file is in the volume path
3138 * that got unmounted, remove it because it's no
3139 * longer valid.
3140 */
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003141 if (state.canonicalPath.startsWith(path)) {
3142 obbStatesToRemove.add(state);
Kenny Rootaf9d6672010-10-08 09:21:39 -07003143 }
3144 }
3145
3146 for (final ObbState obbState : obbStatesToRemove) {
3147 if (DEBUG_OBB)
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003148 Slog.i(TAG, "Removing state for " + obbState.rawPath);
Kenny Rootaf9d6672010-10-08 09:21:39 -07003149
3150 removeObbStateLocked(obbState);
3151
3152 try {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003153 obbState.token.onObbResult(obbState.rawPath, obbState.nonce,
Kenny Rootaf9d6672010-10-08 09:21:39 -07003154 OnObbStateChangeListener.UNMOUNTED);
3155 } catch (RemoteException e) {
3156 Slog.i(TAG, "Couldn't send unmount notification for OBB: "
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003157 + obbState.rawPath);
Kenny Rootaf9d6672010-10-08 09:21:39 -07003158 }
3159 }
3160 }
3161 break;
3162 }
Kenny Roota02b8b02010-08-05 16:14:17 -07003163 }
3164 }
3165
3166 private boolean connectToService() {
3167 if (DEBUG_OBB)
3168 Slog.i(TAG, "Trying to bind to DefaultContainerService");
3169
3170 Intent service = new Intent().setComponent(DEFAULT_CONTAINER_COMPONENT);
Jeff Sharkey6dce4962015-07-03 18:08:41 -07003171 if (mContext.bindServiceAsUser(service, mDefContainerConn, Context.BIND_AUTO_CREATE,
Xiaohui Chene4de5a02015-09-22 15:33:31 -07003172 UserHandle.SYSTEM)) {
Kenny Roota02b8b02010-08-05 16:14:17 -07003173 mBound = true;
3174 return true;
3175 }
3176 return false;
3177 }
3178
3179 private void disconnectService() {
3180 mContainerService = null;
3181 mBound = false;
3182 mContext.unbindService(mDefContainerConn);
3183 }
3184 }
3185
Jeff Sharkey0095a822018-02-15 13:06:53 -07003186 private static class ObbException extends Exception {
3187 public final int status;
3188
3189 public ObbException(int status, String message) {
3190 super(message);
3191 this.status = status;
3192 }
3193
3194 public ObbException(int status, Throwable cause) {
3195 super(cause.getMessage(), cause);
3196 this.status = status;
3197 }
3198 }
3199
Kenny Roota02b8b02010-08-05 16:14:17 -07003200 abstract class ObbAction {
3201 private static final int MAX_RETRIES = 3;
3202 private int mRetries;
3203
3204 ObbState mObbState;
3205
3206 ObbAction(ObbState obbState) {
3207 mObbState = obbState;
3208 }
3209
3210 public void execute(ObbActionHandler handler) {
3211 try {
3212 if (DEBUG_OBB)
Ben Komalo444eca22011-09-01 15:17:44 -07003213 Slog.i(TAG, "Starting to execute action: " + toString());
Kenny Roota02b8b02010-08-05 16:14:17 -07003214 mRetries++;
3215 if (mRetries > MAX_RETRIES) {
Kenny Root480afe72010-10-07 10:17:50 -07003216 mObbActionHandler.sendEmptyMessage(OBB_MCS_UNBIND);
Jeff Sharkey0095a822018-02-15 13:06:53 -07003217 notifyObbStateChange(new ObbException(ERROR_INTERNAL,
3218 "Failed to bind to media container service"));
Kenny Roota02b8b02010-08-05 16:14:17 -07003219 } else {
3220 handleExecute();
3221 if (DEBUG_OBB)
3222 Slog.i(TAG, "Posting install MCS_UNBIND");
3223 mObbActionHandler.sendEmptyMessage(OBB_MCS_UNBIND);
3224 }
Jeff Sharkey0095a822018-02-15 13:06:53 -07003225 } catch (ObbException e) {
3226 notifyObbStateChange(e);
Kenny Root17eb6fb2010-10-06 15:02:52 -07003227 mObbActionHandler.sendEmptyMessage(OBB_MCS_UNBIND);
Kenny Roota02b8b02010-08-05 16:14:17 -07003228 }
3229 }
3230
Jeff Sharkey0095a822018-02-15 13:06:53 -07003231 abstract void handleExecute() throws ObbException;
Kenny Root38cf8862010-09-26 14:18:51 -07003232
Jeff Sharkey0095a822018-02-15 13:06:53 -07003233 protected ObbInfo getObbInfo() throws ObbException {
3234 final ObbInfo obbInfo;
Kenny Root38cf8862010-09-26 14:18:51 -07003235 try {
Xiaohui Chen621b3fc2015-10-02 14:41:42 -07003236 obbInfo = mContainerService.getObbInfo(mObbState.canonicalPath);
Jeff Sharkey0095a822018-02-15 13:06:53 -07003237 } catch (Exception e) {
3238 throw new ObbException(ERROR_PERMISSION_DENIED, e);
Kenny Root38cf8862010-09-26 14:18:51 -07003239 }
Jeff Sharkey0095a822018-02-15 13:06:53 -07003240 if (obbInfo != null) {
3241 return obbInfo;
3242 } else {
3243 throw new ObbException(ERROR_INTERNAL,
3244 "Missing OBB info for: " + mObbState.canonicalPath);
Kenny Root38cf8862010-09-26 14:18:51 -07003245 }
Kenny Root38cf8862010-09-26 14:18:51 -07003246 }
3247
Jeff Sharkey0095a822018-02-15 13:06:53 -07003248 protected void notifyObbStateChange(ObbException e) {
3249 Slog.w(TAG, e);
3250 notifyObbStateChange(e.status);
3251 }
3252
3253 protected void notifyObbStateChange(int status) {
Kenny Rootaf9d6672010-10-08 09:21:39 -07003254 if (mObbState == null || mObbState.token == null) {
3255 return;
3256 }
3257
Kenny Root38cf8862010-09-26 14:18:51 -07003258 try {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003259 mObbState.token.onObbResult(mObbState.rawPath, mObbState.nonce, status);
Kenny Root38cf8862010-09-26 14:18:51 -07003260 } catch (RemoteException e) {
Sudheer Shanka2250d562016-11-07 15:41:02 -08003261 Slog.w(TAG, "StorageEventListener went away while calling onObbStateChanged");
Kenny Root38cf8862010-09-26 14:18:51 -07003262 }
3263 }
Kenny Roota02b8b02010-08-05 16:14:17 -07003264 }
3265
3266 class MountObbAction extends ObbAction {
Ben Komalo444eca22011-09-01 15:17:44 -07003267 private final String mKey;
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003268 private final int mCallingUid;
Kenny Roota02b8b02010-08-05 16:14:17 -07003269
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003270 MountObbAction(ObbState obbState, String key, int callingUid) {
Kenny Roota02b8b02010-08-05 16:14:17 -07003271 super(obbState);
3272 mKey = key;
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003273 mCallingUid = callingUid;
Kenny Roota02b8b02010-08-05 16:14:17 -07003274 }
3275
Jason parks5af0b912010-11-29 09:05:25 -06003276 @Override
Jeff Sharkey0095a822018-02-15 13:06:53 -07003277 public void handleExecute() throws ObbException {
Kenny Rootaf9d6672010-10-08 09:21:39 -07003278 warnOnNotMounted();
3279
Kenny Root38cf8862010-09-26 14:18:51 -07003280 final ObbInfo obbInfo = getObbInfo();
3281
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003282 if (!isUidOwnerOfPackageOrSystem(obbInfo.packageName, mCallingUid)) {
Jeff Sharkey0095a822018-02-15 13:06:53 -07003283 throw new ObbException(ERROR_PERMISSION_DENIED, "Denied attempt to mount OBB "
3284 + obbInfo.filename + " which is owned by " + obbInfo.packageName);
Kenny Roota02b8b02010-08-05 16:14:17 -07003285 }
3286
Kenny Rootaf9d6672010-10-08 09:21:39 -07003287 final boolean isMounted;
3288 synchronized (mObbMounts) {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003289 isMounted = mObbPathToStateMap.containsKey(mObbState.rawPath);
Kenny Rootaf9d6672010-10-08 09:21:39 -07003290 }
3291 if (isMounted) {
Jeff Sharkey0095a822018-02-15 13:06:53 -07003292 throw new ObbException(ERROR_ALREADY_MOUNTED,
3293 "Attempt to mount OBB which is already mounted: " + obbInfo.filename);
Kenny Rootaf9d6672010-10-08 09:21:39 -07003294 }
3295
Kenny Rootaf9d6672010-10-08 09:21:39 -07003296 final String hashedKey;
Jeff Sharkey41cd6812017-09-11 10:32:17 -06003297 final String binderKey;
Kenny Rootaf9d6672010-10-08 09:21:39 -07003298 if (mKey == null) {
3299 hashedKey = "none";
Jeff Sharkey41cd6812017-09-11 10:32:17 -06003300 binderKey = "";
Kenny Rootaf9d6672010-10-08 09:21:39 -07003301 } else {
Kenny Rootaf9d6672010-10-08 09:21:39 -07003302 try {
Kenny Root3b1abba2010-10-13 15:00:07 -07003303 SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
3304
3305 KeySpec ks = new PBEKeySpec(mKey.toCharArray(), obbInfo.salt,
3306 PBKDF2_HASH_ROUNDS, CRYPTO_ALGORITHM_KEY_SIZE);
3307 SecretKey key = factory.generateSecret(ks);
3308 BigInteger bi = new BigInteger(key.getEncoded());
3309 hashedKey = bi.toString(16);
Jeff Sharkey41cd6812017-09-11 10:32:17 -06003310 binderKey = hashedKey;
Jeff Sharkey0095a822018-02-15 13:06:53 -07003311 } catch (GeneralSecurityException e) {
3312 throw new ObbException(ERROR_INTERNAL, e);
Kenny Root38cf8862010-09-26 14:18:51 -07003313 }
Kenny Rootaf9d6672010-10-08 09:21:39 -07003314 }
Kenny Root38cf8862010-09-26 14:18:51 -07003315
Kenny Rootaf9d6672010-10-08 09:21:39 -07003316 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06003317 mObbState.volId = mVold.createObb(mObbState.canonicalPath, binderKey,
3318 mObbState.ownerGid);
3319 mVold.mount(mObbState.volId, 0, -1);
Kenny Roota02b8b02010-08-05 16:14:17 -07003320
Kenny Rootaf9d6672010-10-08 09:21:39 -07003321 if (DEBUG_OBB)
Xiaohui Chen621b3fc2015-10-02 14:41:42 -07003322 Slog.d(TAG, "Successfully mounted OBB " + mObbState.canonicalPath);
Kenny Rootaf9d6672010-10-08 09:21:39 -07003323
3324 synchronized (mObbMounts) {
3325 addObbStateLocked(mObbState);
3326 }
3327
Jeff Sharkey0095a822018-02-15 13:06:53 -07003328 notifyObbStateChange(MOUNTED);
3329 } catch (Exception e) {
3330 throw new ObbException(ERROR_COULD_NOT_MOUNT, e);
Kenny Root02c87302010-07-01 08:10:18 -07003331 }
3332 }
3333
Jason parks5af0b912010-11-29 09:05:25 -06003334 @Override
Kenny Roota02b8b02010-08-05 16:14:17 -07003335 public String toString() {
3336 StringBuilder sb = new StringBuilder();
3337 sb.append("MountObbAction{");
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003338 sb.append(mObbState);
Kenny Roota02b8b02010-08-05 16:14:17 -07003339 sb.append('}');
3340 return sb.toString();
3341 }
3342 }
3343
3344 class UnmountObbAction extends ObbAction {
Ben Komalo444eca22011-09-01 15:17:44 -07003345 private final boolean mForceUnmount;
Kenny Roota02b8b02010-08-05 16:14:17 -07003346
3347 UnmountObbAction(ObbState obbState, boolean force) {
3348 super(obbState);
3349 mForceUnmount = force;
3350 }
3351
Jason parks5af0b912010-11-29 09:05:25 -06003352 @Override
Jeff Sharkey0095a822018-02-15 13:06:53 -07003353 public void handleExecute() throws ObbException {
Kenny Rootaf9d6672010-10-08 09:21:39 -07003354 warnOnNotMounted();
3355
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003356 final ObbState existingState;
Kenny Root38cf8862010-09-26 14:18:51 -07003357 synchronized (mObbMounts) {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003358 existingState = mObbPathToStateMap.get(mObbState.rawPath);
Kenny Rootaf9d6672010-10-08 09:21:39 -07003359 }
Kenny Root38cf8862010-09-26 14:18:51 -07003360
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003361 if (existingState == null) {
Jeff Sharkey0095a822018-02-15 13:06:53 -07003362 throw new ObbException(ERROR_NOT_MOUNTED, "Missing existingState");
Kenny Rootaf9d6672010-10-08 09:21:39 -07003363 }
3364
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003365 if (existingState.ownerGid != mObbState.ownerGid) {
Jeff Sharkey0095a822018-02-15 13:06:53 -07003366 notifyObbStateChange(new ObbException(ERROR_PERMISSION_DENIED,
3367 "Permission denied to unmount OBB " + existingState.rawPath
3368 + " (owned by GID " + existingState.ownerGid + ")"));
Kenny Rootaf9d6672010-10-08 09:21:39 -07003369 return;
3370 }
3371
Kenny Rootaf9d6672010-10-08 09:21:39 -07003372 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06003373 mVold.unmount(mObbState.volId);
3374 mVold.destroyObb(mObbState.volId);
3375 mObbState.volId = null;
Kenny Roota02b8b02010-08-05 16:14:17 -07003376
Kenny Rootaf9d6672010-10-08 09:21:39 -07003377 synchronized (mObbMounts) {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003378 removeObbStateLocked(existingState);
Kenny Root38cf8862010-09-26 14:18:51 -07003379 }
3380
Jeff Sharkey0095a822018-02-15 13:06:53 -07003381 notifyObbStateChange(UNMOUNTED);
3382 } catch (Exception e) {
3383 throw new ObbException(ERROR_COULD_NOT_UNMOUNT, e);
Kenny Roota02b8b02010-08-05 16:14:17 -07003384 }
3385 }
3386
Jason parks5af0b912010-11-29 09:05:25 -06003387 @Override
Kenny Roota02b8b02010-08-05 16:14:17 -07003388 public String toString() {
3389 StringBuilder sb = new StringBuilder();
3390 sb.append("UnmountObbAction{");
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003391 sb.append(mObbState);
Kenny Roota02b8b02010-08-05 16:14:17 -07003392 sb.append(",force=");
3393 sb.append(mForceUnmount);
Kenny Roota02b8b02010-08-05 16:14:17 -07003394 sb.append('}');
3395 return sb.toString();
3396 }
Kenny Root02c87302010-07-01 08:10:18 -07003397 }
Kenny Root38cf8862010-09-26 14:18:51 -07003398
Jeff Sharkey7e19f532017-11-06 13:54:11 -07003399 private void dispatchOnStatus(IVoldTaskListener listener, int status,
3400 PersistableBundle extras) {
3401 if (listener != null) {
3402 try {
3403 listener.onStatus(status, extras);
3404 } catch (RemoteException ignored) {
3405 }
3406 }
3407 }
3408
3409 private void dispatchOnFinished(IVoldTaskListener listener, int status,
3410 PersistableBundle extras) {
3411 if (listener != null) {
3412 try {
3413 listener.onFinished(status, extras);
3414 } catch (RemoteException ignored) {
3415 }
3416 }
3417 }
3418
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07003419 private static class Callbacks extends Handler {
3420 private static final int MSG_STORAGE_STATE_CHANGED = 1;
3421 private static final int MSG_VOLUME_STATE_CHANGED = 2;
Jeff Sharkey50a05452015-04-29 11:24:52 -07003422 private static final int MSG_VOLUME_RECORD_CHANGED = 3;
3423 private static final int MSG_VOLUME_FORGOTTEN = 4;
3424 private static final int MSG_DISK_SCANNED = 5;
Makoto Onuki9dc575d2015-06-12 16:10:25 -07003425 private static final int MSG_DISK_DESTROYED = 6;
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07003426
Sudheer Shanka2250d562016-11-07 15:41:02 -08003427 private final RemoteCallbackList<IStorageEventListener>
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07003428 mCallbacks = new RemoteCallbackList<>();
3429
3430 public Callbacks(Looper looper) {
3431 super(looper);
3432 }
3433
Sudheer Shanka2250d562016-11-07 15:41:02 -08003434 public void register(IStorageEventListener callback) {
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07003435 mCallbacks.register(callback);
3436 }
3437
Sudheer Shanka2250d562016-11-07 15:41:02 -08003438 public void unregister(IStorageEventListener callback) {
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07003439 mCallbacks.unregister(callback);
3440 }
3441
3442 @Override
3443 public void handleMessage(Message msg) {
3444 final SomeArgs args = (SomeArgs) msg.obj;
3445 final int n = mCallbacks.beginBroadcast();
3446 for (int i = 0; i < n; i++) {
Sudheer Shanka2250d562016-11-07 15:41:02 -08003447 final IStorageEventListener callback = mCallbacks.getBroadcastItem(i);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07003448 try {
3449 invokeCallback(callback, msg.what, args);
3450 } catch (RemoteException ignored) {
3451 }
3452 }
3453 mCallbacks.finishBroadcast();
3454 args.recycle();
3455 }
3456
Sudheer Shanka2250d562016-11-07 15:41:02 -08003457 private void invokeCallback(IStorageEventListener callback, int what, SomeArgs args)
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07003458 throws RemoteException {
3459 switch (what) {
3460 case MSG_STORAGE_STATE_CHANGED: {
3461 callback.onStorageStateChanged((String) args.arg1, (String) args.arg2,
3462 (String) args.arg3);
3463 break;
3464 }
3465 case MSG_VOLUME_STATE_CHANGED: {
3466 callback.onVolumeStateChanged((VolumeInfo) args.arg1, args.argi2, args.argi3);
3467 break;
3468 }
Jeff Sharkey50a05452015-04-29 11:24:52 -07003469 case MSG_VOLUME_RECORD_CHANGED: {
3470 callback.onVolumeRecordChanged((VolumeRecord) args.arg1);
3471 break;
3472 }
3473 case MSG_VOLUME_FORGOTTEN: {
3474 callback.onVolumeForgotten((String) args.arg1);
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07003475 break;
3476 }
Jeff Sharkey620b32b2015-04-23 19:36:02 -07003477 case MSG_DISK_SCANNED: {
3478 callback.onDiskScanned((DiskInfo) args.arg1, args.argi2);
Jeff Sharkey7e92ef32015-04-17 17:35:07 -07003479 break;
3480 }
Makoto Onuki9dc575d2015-06-12 16:10:25 -07003481 case MSG_DISK_DESTROYED: {
3482 callback.onDiskDestroyed((DiskInfo) args.arg1);
3483 break;
3484 }
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07003485 }
3486 }
3487
3488 private void notifyStorageStateChanged(String path, String oldState, String newState) {
3489 final SomeArgs args = SomeArgs.obtain();
3490 args.arg1 = path;
3491 args.arg2 = oldState;
3492 args.arg3 = newState;
3493 obtainMessage(MSG_STORAGE_STATE_CHANGED, args).sendToTarget();
3494 }
3495
3496 private void notifyVolumeStateChanged(VolumeInfo vol, int oldState, int newState) {
3497 final SomeArgs args = SomeArgs.obtain();
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07003498 args.arg1 = vol.clone();
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07003499 args.argi2 = oldState;
3500 args.argi3 = newState;
3501 obtainMessage(MSG_VOLUME_STATE_CHANGED, args).sendToTarget();
3502 }
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07003503
Jeff Sharkey50a05452015-04-29 11:24:52 -07003504 private void notifyVolumeRecordChanged(VolumeRecord rec) {
3505 final SomeArgs args = SomeArgs.obtain();
3506 args.arg1 = rec.clone();
3507 obtainMessage(MSG_VOLUME_RECORD_CHANGED, args).sendToTarget();
3508 }
3509
3510 private void notifyVolumeForgotten(String fsUuid) {
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07003511 final SomeArgs args = SomeArgs.obtain();
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07003512 args.arg1 = fsUuid;
Jeff Sharkey50a05452015-04-29 11:24:52 -07003513 obtainMessage(MSG_VOLUME_FORGOTTEN, args).sendToTarget();
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07003514 }
Jeff Sharkey7e92ef32015-04-17 17:35:07 -07003515
Jeff Sharkey620b32b2015-04-23 19:36:02 -07003516 private void notifyDiskScanned(DiskInfo disk, int volumeCount) {
Jeff Sharkey7e92ef32015-04-17 17:35:07 -07003517 final SomeArgs args = SomeArgs.obtain();
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07003518 args.arg1 = disk.clone();
Jeff Sharkey620b32b2015-04-23 19:36:02 -07003519 args.argi2 = volumeCount;
3520 obtainMessage(MSG_DISK_SCANNED, args).sendToTarget();
Jeff Sharkey7e92ef32015-04-17 17:35:07 -07003521 }
Makoto Onuki9dc575d2015-06-12 16:10:25 -07003522
3523 private void notifyDiskDestroyed(DiskInfo disk) {
3524 final SomeArgs args = SomeArgs.obtain();
3525 args.arg1 = disk.clone();
3526 obtainMessage(MSG_DISK_DESTROYED, args).sendToTarget();
3527 }
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07003528 }
3529
Kenny Root38cf8862010-09-26 14:18:51 -07003530 @Override
Jeff Sharkey5aca2b82013-10-16 16:21:54 -07003531 protected void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
Jeff Sharkeyfe9a53b2017-03-31 14:08:23 -06003532 if (!DumpUtils.checkDumpPermission(mContext, TAG, writer)) return;
Jeff Sharkey5aca2b82013-10-16 16:21:54 -07003533
3534 final IndentingPrintWriter pw = new IndentingPrintWriter(writer, " ", 160);
Jeff Sharkey27de30d2015-04-18 16:20:27 -07003535 synchronized (mLock) {
3536 pw.println("Disks:");
3537 pw.increaseIndent();
3538 for (int i = 0; i < mDisks.size(); i++) {
3539 final DiskInfo disk = mDisks.valueAt(i);
3540 disk.dump(pw);
3541 }
3542 pw.decreaseIndent();
3543
3544 pw.println();
3545 pw.println("Volumes:");
3546 pw.increaseIndent();
3547 for (int i = 0; i < mVolumes.size(); i++) {
3548 final VolumeInfo vol = mVolumes.valueAt(i);
3549 if (VolumeInfo.ID_PRIVATE_INTERNAL.equals(vol.id)) continue;
3550 vol.dump(pw);
3551 }
3552 pw.decreaseIndent();
3553
3554 pw.println();
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07003555 pw.println("Records:");
Jeff Sharkey27de30d2015-04-18 16:20:27 -07003556 pw.increaseIndent();
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07003557 for (int i = 0; i < mRecords.size(); i++) {
3558 final VolumeRecord note = mRecords.valueAt(i);
3559 note.dump(pw);
Jeff Sharkey27de30d2015-04-18 16:20:27 -07003560 }
3561 pw.decreaseIndent();
Jeff Sharkey275e3e42015-04-24 16:10:32 -07003562
3563 pw.println();
3564 pw.println("Primary storage UUID: " + mPrimaryStorageUuid);
Felipe Leme281389a2016-10-10 17:12:20 -07003565 final Pair<String, Long> pair = StorageManager.getPrimaryStoragePathAndSize();
3566 if (pair == null) {
3567 pw.println("Internal storage total size: N/A");
3568 } else {
3569 pw.print("Internal storage (");
3570 pw.print(pair.first);
3571 pw.print(") total size: ");
3572 pw.print(pair.second);
3573 pw.print(" (");
Jeff Sharkey9f2dc052018-01-07 16:47:31 -07003574 pw.print(DataUnit.MEBIBYTES.toBytes(pair.second));
3575 pw.println(" MiB)");
Felipe Leme281389a2016-10-10 17:12:20 -07003576 }
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07003577 pw.println("Local unlocked users: " + Arrays.toString(mLocalUnlockedUsers));
3578 pw.println("System unlocked users: " + Arrays.toString(mSystemUnlockedUsers));
Jeff Sharkey27de30d2015-04-18 16:20:27 -07003579 }
Kenny Root38cf8862010-09-26 14:18:51 -07003580
Kenny Root38cf8862010-09-26 14:18:51 -07003581 synchronized (mObbMounts) {
Jeff Sharkey27de30d2015-04-18 16:20:27 -07003582 pw.println();
Jeff Sharkey5aca2b82013-10-16 16:21:54 -07003583 pw.println("mObbMounts:");
3584 pw.increaseIndent();
3585 final Iterator<Entry<IBinder, List<ObbState>>> binders = mObbMounts.entrySet()
3586 .iterator();
Kenny Rootaf9d6672010-10-08 09:21:39 -07003587 while (binders.hasNext()) {
3588 Entry<IBinder, List<ObbState>> e = binders.next();
Jeff Sharkey5aca2b82013-10-16 16:21:54 -07003589 pw.println(e.getKey() + ":");
3590 pw.increaseIndent();
Kenny Rootaf9d6672010-10-08 09:21:39 -07003591 final List<ObbState> obbStates = e.getValue();
Kenny Root38cf8862010-09-26 14:18:51 -07003592 for (final ObbState obbState : obbStates) {
Jeff Sharkey5aca2b82013-10-16 16:21:54 -07003593 pw.println(obbState);
Kenny Root38cf8862010-09-26 14:18:51 -07003594 }
Jeff Sharkey5aca2b82013-10-16 16:21:54 -07003595 pw.decreaseIndent();
Kenny Root38cf8862010-09-26 14:18:51 -07003596 }
Jeff Sharkey5aca2b82013-10-16 16:21:54 -07003597 pw.decreaseIndent();
Kenny Rootaf9d6672010-10-08 09:21:39 -07003598
Jeff Sharkey5aca2b82013-10-16 16:21:54 -07003599 pw.println();
3600 pw.println("mObbPathToStateMap:");
3601 pw.increaseIndent();
Kenny Rootaf9d6672010-10-08 09:21:39 -07003602 final Iterator<Entry<String, ObbState>> maps = mObbPathToStateMap.entrySet().iterator();
3603 while (maps.hasNext()) {
3604 final Entry<String, ObbState> e = maps.next();
Jeff Sharkey5aca2b82013-10-16 16:21:54 -07003605 pw.print(e.getKey());
3606 pw.print(" -> ");
3607 pw.println(e.getValue());
Kenny Rootaf9d6672010-10-08 09:21:39 -07003608 }
Jeff Sharkey5aca2b82013-10-16 16:21:54 -07003609 pw.decreaseIndent();
Kenny Root38cf8862010-09-26 14:18:51 -07003610 }
Kenny Root4161f9b2011-07-13 09:48:33 -07003611
Robert Greenwalt470fd722012-01-18 12:51:15 -08003612 pw.println();
Christopher Tate7265abe2014-11-21 13:54:45 -08003613 pw.print("Last maintenance: ");
Jeff Sharkeye8a4b662015-06-27 15:43:45 -07003614 pw.println(TimeUtils.formatForLogging(mLastMaintenance));
Kenny Root38cf8862010-09-26 14:18:51 -07003615 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003616
Jeff Sharkeyfa23c5a2011-08-09 21:44:24 -07003617 /** {@inheritDoc} */
Jeff Sharkey48877892015-03-18 11:27:19 -07003618 @Override
Jeff Sharkeyfa23c5a2011-08-09 21:44:24 -07003619 public void monitor() {
Jeff Sharkey54402792017-09-15 16:05:19 -06003620 try {
3621 mVold.monitor();
3622 } catch (Exception e) {
3623 Slog.wtf(TAG, e);
Paul Lawrence1c62cbb2015-06-03 14:14:52 -07003624 }
Jeff Sharkeyfa23c5a2011-08-09 21:44:24 -07003625 }
Svet Ganov6ee871e2015-07-10 14:29:33 -07003626
Sudheer Shanka2250d562016-11-07 15:41:02 -08003627 private final class StorageManagerInternalImpl extends StorageManagerInternal {
Svet Ganov6ee871e2015-07-10 14:29:33 -07003628 // Not guarded by a lock.
3629 private final CopyOnWriteArrayList<ExternalStorageMountPolicy> mPolicies =
3630 new CopyOnWriteArrayList<>();
3631
3632 @Override
3633 public void addExternalStoragePolicy(ExternalStorageMountPolicy policy) {
3634 // No locking - CopyOnWriteArrayList
3635 mPolicies.add(policy);
3636 }
3637
3638 @Override
3639 public void onExternalStoragePolicyChanged(int uid, String packageName) {
3640 final int mountMode = getExternalStorageMountMode(uid, packageName);
3641 remountUidExternalStorage(uid, mountMode);
3642 }
3643
3644 @Override
3645 public int getExternalStorageMountMode(int uid, String packageName) {
3646 // No locking - CopyOnWriteArrayList
3647 int mountMode = Integer.MAX_VALUE;
3648 for (ExternalStorageMountPolicy policy : mPolicies) {
3649 final int policyMode = policy.getMountMode(uid, packageName);
3650 if (policyMode == Zygote.MOUNT_EXTERNAL_NONE) {
3651 return Zygote.MOUNT_EXTERNAL_NONE;
3652 }
3653 mountMode = Math.min(mountMode, policyMode);
3654 }
3655 if (mountMode == Integer.MAX_VALUE) {
3656 return Zygote.MOUNT_EXTERNAL_NONE;
3657 }
3658 return mountMode;
3659 }
3660
3661 public boolean hasExternalStorage(int uid, String packageName) {
Amith Yamasani2bd5cff2015-07-22 14:42:31 -07003662 // No need to check for system uid. This avoids a deadlock between
3663 // PackageManagerService and AppOpsService.
3664 if (uid == Process.SYSTEM_UID) {
3665 return true;
3666 }
Svet Ganov6ee871e2015-07-10 14:29:33 -07003667 // No locking - CopyOnWriteArrayList
3668 for (ExternalStorageMountPolicy policy : mPolicies) {
3669 final boolean policyHasStorage = policy.hasExternalStorage(uid, packageName);
3670 if (!policyHasStorage) {
3671 return false;
3672 }
3673 }
3674 return true;
3675 }
3676 }
Jeff Sharkeyfa23c5a2011-08-09 21:44:24 -07003677}