blob: 84b93e36c602f49149060ce5221b922a324426d4 [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 Sharkey4c099d02015-05-15 13:45:00 -070019import static com.android.internal.util.XmlUtils.readBooleanAttribute;
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -070020import static com.android.internal.util.XmlUtils.readIntAttribute;
Jeff Sharkeye8a4b662015-06-27 15:43:45 -070021import static com.android.internal.util.XmlUtils.readLongAttribute;
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -070022import static com.android.internal.util.XmlUtils.readStringAttribute;
Jeff Sharkey4c099d02015-05-15 13:45:00 -070023import static com.android.internal.util.XmlUtils.writeBooleanAttribute;
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -070024import static com.android.internal.util.XmlUtils.writeIntAttribute;
Jeff Sharkeye8a4b662015-06-27 15:43:45 -070025import static com.android.internal.util.XmlUtils.writeLongAttribute;
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -070026import static com.android.internal.util.XmlUtils.writeStringAttribute;
Jeff Sharkey5217cac2015-12-20 15:34:01 -070027
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -070028import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT;
29import static org.xmlpull.v1.XmlPullParser.START_TAG;
30
Jason parks8888c592011-01-20 22:46:41 -060031import android.Manifest;
Jeff Sharkeyef10ee02015-07-05 14:17:27 -070032import android.annotation.Nullable;
Xiaohui Chen621b3fc2015-10-02 14:41:42 -070033import android.app.ActivityManager;
Jeff Sharkey9765e442017-12-14 22:15:14 -070034import android.app.ActivityManagerInternal;
35import android.app.ActivityManagerInternal.ScreenObserver;
Jeff Sharkey2d8b4e82013-09-17 17:30:33 -070036import android.app.AppOpsManager;
Jeff Sharkey14cbe522015-07-08 14:06:37 -070037import android.app.IActivityManager;
Jeff Sharkey9765e442017-12-14 22:15:14 -070038import android.app.KeyguardManager;
Pavel Grafovce72ef02018-01-10 17:14:11 +000039import android.app.admin.SecurityLog;
Jeff Sharkey9bed0702017-01-23 20:37:05 -070040import android.app.usage.StorageStatsManager;
Jeff Sharkeybcd262d2015-06-10 09:41:17 -070041import android.content.BroadcastReceiver;
Kenny Roota02b8b02010-08-05 16:14:17 -070042import android.content.ComponentName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080043import android.content.Context;
44import android.content.Intent;
Jeff Sharkeybcd262d2015-06-10 09:41:17 -070045import android.content.IntentFilter;
Kenny Roota02b8b02010-08-05 16:14:17 -070046import android.content.ServiceConnection;
Jeff Sharkey275e3e42015-04-24 16:10:32 -070047import android.content.pm.IPackageMoveObserver;
48import android.content.pm.PackageManager;
Jeff Sharkey14cbe522015-07-08 14:06:37 -070049import android.content.pm.ProviderInfo;
Jeff Sharkeybcd262d2015-06-10 09:41:17 -070050import android.content.pm.UserInfo;
Elliott Hughesf839b4f2014-09-26 12:30:47 -070051import android.content.res.Configuration;
Kenny Root02c87302010-07-01 08:10:18 -070052import android.content.res.ObbInfo;
Daniel Colascione766b6322018-01-08 19:10:36 -080053import android.database.ContentObserver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080054import android.net.Uri;
Kenny Root02c87302010-07-01 08:10:18 -070055import android.os.Binder;
Jeff Sharkey4c099d02015-05-15 13:45:00 -070056import android.os.DropBoxManager;
Kenny Roota02b8b02010-08-05 16:14:17 -070057import android.os.Environment;
Jeff Sharkeyb049e212012-09-07 23:16:01 -070058import android.os.Environment.UserEnvironment;
Jeff Sharkey48877892015-03-18 11:27:19 -070059import android.os.FileUtils;
Suchi Amalapurapuc42e29e2010-02-22 16:03:53 -080060import android.os.Handler;
Dianne Hackbornefa92b22013-05-03 14:11:43 -070061import android.os.HandlerThread;
Kenny Roota02b8b02010-08-05 16:14:17 -070062import android.os.IBinder;
Jeff Sharkey7e19f532017-11-06 13:54:11 -070063import android.os.IProgressListener;
Jin Qian12690d52017-10-13 18:17:04 -070064import android.os.IStoraged;
Jeff Sharkey1019de92017-09-06 13:47:03 -060065import android.os.IVold;
Jeff Sharkey8058fe62017-09-13 11:50:33 -060066import android.os.IVoldListener;
Jeff Sharkeyb302c542017-09-15 12:57:59 -060067import android.os.IVoldTaskListener;
Daniel Sandler5f27ef42010-03-16 15:42:02 -040068import android.os.Looper;
Suchi Amalapurapuc42e29e2010-02-22 16:03:53 -080069import android.os.Message;
Daichi Hirono9e8d9e22015-11-13 14:37:00 +090070import android.os.ParcelFileDescriptor;
Jeff Sharkey500ce9e2017-02-12 02:39:24 -070071import android.os.ParcelableException;
Jeff Sharkeyb302c542017-09-15 12:57:59 -060072import android.os.PersistableBundle;
Jeff Sharkeyce14cd02015-12-07 15:35:42 -070073import android.os.PowerManager;
Jeff Sharkey9527b222015-06-24 15:24:48 -070074import android.os.Process;
Jeff Sharkey7151a9a2015-04-04 15:22:37 -070075import android.os.RemoteCallbackList;
San Mehat4270e1e2010-01-29 05:32:19 -080076import android.os.RemoteException;
Suchi Amalapurapufd3530f2010-01-18 00:15:59 -080077import android.os.ServiceManager;
Jeff Sharkeyedcdaf62015-07-09 09:45:36 -070078import android.os.SystemClock;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080079import android.os.SystemProperties;
Dianne Hackbornf02b60a2012-08-16 10:48:27 -070080import android.os.UserHandle;
Emily Bernier92aa5a22014-07-07 10:11:48 -040081import android.os.UserManager;
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -070082import android.os.storage.DiskInfo;
Kenny Roota02b8b02010-08-05 16:14:17 -070083import android.os.storage.IObbActionListener;
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -070084import android.os.storage.IStorageEventListener;
Sudheer Shanka2250d562016-11-07 15:41:02 -080085import android.os.storage.IStorageManager;
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -070086import android.os.storage.IStorageShutdownObserver;
Kenny Rootaf9d6672010-10-08 09:21:39 -070087import android.os.storage.OnObbStateChangeListener;
Paul Lawrence46791e72014-04-03 09:10:26 -070088import android.os.storage.StorageManager;
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -070089import android.os.storage.StorageManagerInternal;
Kenny Roota02b8b02010-08-05 16:14:17 -070090import android.os.storage.StorageResultCode;
Mike Lockwood2f6a3882011-05-09 19:08:06 -070091import android.os.storage.StorageVolume;
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -070092import android.os.storage.VolumeInfo;
Jeff Sharkeyb36586a2015-04-27 08:42:28 -070093import android.os.storage.VolumeRecord;
Jeff Sharkey14cbe522015-07-08 14:06:37 -070094import android.provider.MediaStore;
Jeff Sharkeye8a4b662015-06-27 15:43:45 -070095import android.provider.Settings;
Jason parksf7b3cd42011-01-27 09:28:25 -060096import android.text.TextUtils;
Jeff Sharkey1783f142015-04-17 10:52:51 -070097import android.text.format.DateUtils;
Jeff Sharkey48877892015-03-18 11:27:19 -070098import android.util.ArrayMap;
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -070099import android.util.AtomicFile;
Jeff Sharkey9f2dc052018-01-07 16:47:31 -0700100import android.util.DataUnit;
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -0700101import android.util.Log;
Felipe Leme281389a2016-10-10 17:12:20 -0700102import android.util.Pair;
San Mehata5078592010-03-25 09:36:54 -0700103import android.util.Slog;
Jeff Sharkeye8a4b662015-06-27 15:43:45 -0700104import android.util.TimeUtils;
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700105import android.util.Xml;
Jeff Sharkey48877892015-03-18 11:27:19 -0700106
Jeff Sharkey8b2c3a142012-11-12 11:45:05 -0800107import com.android.internal.annotations.GuardedBy;
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700108import com.android.internal.app.IMediaContainerService;
Daichi Hirono9fb00182016-11-08 14:12:17 +0900109import com.android.internal.os.AppFuseMount;
Jeff Sharkey1019de92017-09-06 13:47:03 -0600110import com.android.internal.os.BackgroundThread;
Daichi Hirono812c95d2017-02-08 16:20:20 +0900111import com.android.internal.os.FuseUnavailableMountException;
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700112import com.android.internal.os.SomeArgs;
Jeff Sharkey9527b222015-06-24 15:24:48 -0700113import com.android.internal.os.Zygote;
Jeff Sharkey48877892015-03-18 11:27:19 -0700114import com.android.internal.util.ArrayUtils;
Jeff Sharkeyfe9a53b2017-03-31 14:08:23 -0600115import com.android.internal.util.DumpUtils;
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700116import com.android.internal.util.FastXmlSerializer;
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -0800117import com.android.internal.util.HexDump;
Jeff Sharkey5aca2b82013-10-16 16:21:54 -0700118import com.android.internal.util.IndentingPrintWriter;
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700119import com.android.internal.util.Preconditions;
Jeff Sharkeyb9fe5372015-12-03 15:23:08 -0700120import com.android.internal.widget.LockPatternUtils;
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700121import com.android.server.pm.PackageManagerService;
Daichi Hirono9fb00182016-11-08 14:12:17 +0900122import com.android.server.storage.AppFuseBridge;
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -0700123
Jeff Sharkey5217cac2015-12-20 15:34:01 -0700124import libcore.io.IoUtils;
125import libcore.util.EmptyArray;
126
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700127import org.xmlpull.v1.XmlPullParser;
128import org.xmlpull.v1.XmlPullParserException;
129import org.xmlpull.v1.XmlSerializer;
130
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700131import java.io.File;
Kenny Root38cf8862010-09-26 14:18:51 -0700132import java.io.FileDescriptor;
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700133import java.io.FileInputStream;
134import java.io.FileNotFoundException;
Christopher Tate7265abe2014-11-21 13:54:45 -0800135import java.io.FileOutputStream;
Kenny Root05105f72010-09-22 17:29:43 -0700136import java.io.IOException;
Kenny Root38cf8862010-09-26 14:18:51 -0700137import java.io.PrintWriter;
Kenny Root3b1abba2010-10-13 15:00:07 -0700138import java.math.BigInteger;
Paul Lawrence8e397362014-01-27 15:22:30 -0800139import java.nio.charset.StandardCharsets;
Kenny Root735de3b2010-09-30 14:11:39 -0700140import java.security.NoSuchAlgorithmException;
Kenny Root3b1abba2010-10-13 15:00:07 -0700141import java.security.spec.InvalidKeySpecException;
142import java.security.spec.KeySpec;
San Mehat22dd86e2010-01-12 12:21:18 -0800143import java.util.ArrayList;
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -0800144import java.util.Arrays;
Kenny Roota02b8b02010-08-05 16:14:17 -0700145import java.util.HashMap;
Kenny Root38cf8862010-09-26 14:18:51 -0700146import java.util.Iterator;
Kenny Roota02b8b02010-08-05 16:14:17 -0700147import java.util.LinkedList;
148import java.util.List;
Elliott Hughesf839b4f2014-09-26 12:30:47 -0700149import java.util.Locale;
Kenny Roota02b8b02010-08-05 16:14:17 -0700150import java.util.Map;
Kenny Root38cf8862010-09-26 14:18:51 -0700151import java.util.Map.Entry;
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700152import java.util.Objects;
Svet Ganov6ee871e2015-07-10 14:29:33 -0700153import java.util.concurrent.CopyOnWriteArrayList;
Kenny Root51a573c2012-05-17 13:30:28 -0700154import java.util.concurrent.CountDownLatch;
155import java.util.concurrent.TimeUnit;
Jeff Sharkeyedcdaf62015-07-09 09:45:36 -0700156import java.util.concurrent.TimeoutException;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800157
Kenny Root3b1abba2010-10-13 15:00:07 -0700158import javax.crypto.SecretKey;
159import javax.crypto.SecretKeyFactory;
160import javax.crypto.spec.PBEKeySpec;
161
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800162/**
Jeff Sharkey48877892015-03-18 11:27:19 -0700163 * Service responsible for various storage media. Connects to {@code vold} to
164 * watch for and manage dynamically added storage, such as SD cards and USB mass
165 * storage. Also decides how storage should be presented to users on the device.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800166 */
Jeff Sharkey9765e442017-12-14 22:15:14 -0700167class StorageManagerService extends IStorageManager.Stub
168 implements Watchdog.Monitor, ScreenObserver {
Jason parks5af0b912010-11-29 09:05:25 -0600169
Christopher Tated417d622013-08-19 16:14:25 -0700170 // Static direct instance pointer for the tightly-coupled idle service to use
Sudheer Shanka2250d562016-11-07 15:41:02 -0800171 static StorageManagerService sSelf = null;
Christopher Tated417d622013-08-19 16:14:25 -0700172
Daniel Colascione766b6322018-01-08 19:10:36 -0800173 /* Read during boot to decide whether to enable zram when available */
174 private static final String ZRAM_ENABLED_PROPERTY =
175 "persist.sys.zram_enabled";
176
Jeff Sharkey56e62932015-03-21 20:41:00 -0700177 public static class Lifecycle extends SystemService {
Sudheer Shanka2250d562016-11-07 15:41:02 -0800178 private StorageManagerService mStorageManagerService;
Jeff Sharkey56e62932015-03-21 20:41:00 -0700179
180 public Lifecycle(Context context) {
181 super(context);
182 }
183
184 @Override
185 public void onStart() {
Sudheer Shanka2250d562016-11-07 15:41:02 -0800186 mStorageManagerService = new StorageManagerService(getContext());
187 publishBinderService("mount", mStorageManagerService);
188 mStorageManagerService.start();
Jeff Sharkey56e62932015-03-21 20:41:00 -0700189 }
190
191 @Override
192 public void onBootPhase(int phase) {
193 if (phase == SystemService.PHASE_ACTIVITY_MANAGER_READY) {
Sudheer Shanka2250d562016-11-07 15:41:02 -0800194 mStorageManagerService.systemReady();
Yasuhiro Matsuda87a38b52015-07-24 22:10:16 +0900195 } else if (phase == SystemService.PHASE_BOOT_COMPLETED) {
Sudheer Shanka2250d562016-11-07 15:41:02 -0800196 mStorageManagerService.bootCompleted();
Jeff Sharkey56e62932015-03-21 20:41:00 -0700197 }
198 }
Jeff Sharkey48877892015-03-18 11:27:19 -0700199
200 @Override
Jeff Sharkeyab15c392016-05-05 11:45:01 -0600201 public void onSwitchUser(int userHandle) {
Sudheer Shanka2250d562016-11-07 15:41:02 -0800202 mStorageManagerService.mCurrentUserId = userHandle;
Jeff Sharkeyab15c392016-05-05 11:45:01 -0600203 }
204
205 @Override
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700206 public void onUnlockUser(int userHandle) {
Sudheer Shanka2250d562016-11-07 15:41:02 -0800207 mStorageManagerService.onUnlockUser(userHandle);
Jeff Sharkey48877892015-03-18 11:27:19 -0700208 }
209
210 @Override
211 public void onCleanupUser(int userHandle) {
Sudheer Shanka2250d562016-11-07 15:41:02 -0800212 mStorageManagerService.onCleanupUser(userHandle);
Jeff Sharkey48877892015-03-18 11:27:19 -0700213 }
Jeff Sharkey56e62932015-03-21 20:41:00 -0700214 }
215
Dianne Hackborn40e9f292012-11-27 19:12:23 -0800216 private static final boolean DEBUG_EVENTS = false;
Kenny Rootb7db2722011-01-25 16:39:35 -0800217 private static final boolean DEBUG_OBB = false;
Kenny Root02c87302010-07-01 08:10:18 -0700218
Kenny Root07714d42011-08-17 17:49:28 -0700219 // Disable this since it messes up long-running cryptfs operations.
220 private static final boolean WATCHDOG_ENABLE = false;
221
Jeff Sharkey00455bf2016-11-04 14:45:24 -0600222 /**
223 * Our goal is for all Android devices to be usable as development devices,
224 * which includes the new Direct Boot mode added in N. For devices that
225 * don't have native FBE support, we offer an emulation mode for developer
226 * testing purposes, but if it's prohibitively difficult to support this
227 * mode, it can be disabled for specific products using this flag.
228 */
229 private static final boolean EMULATE_FBE_SUPPORTED = true;
230
Sudheer Shanka2250d562016-11-07 15:41:02 -0800231 private static final String TAG = "StorageManagerService";
Jeff Sharkeye8a4b662015-06-27 15:43:45 -0700232
Jeff Sharkey9756d752015-05-14 21:07:42 -0700233 private static final String TAG_STORAGE_BENCHMARK = "storage_benchmark";
Jeff Sharkeye8a4b662015-06-27 15:43:45 -0700234 private static final String TAG_STORAGE_TRIM = "storage_trim";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800235
Jeff Sharkey275e3e42015-04-24 16:10:32 -0700236 /** Magic value sent by MoveTask.cpp */
237 private static final int MOVE_STATUS_COPY_FINISHED = 82;
238
Jeff Sharkey620b32b2015-04-23 19:36:02 -0700239 private static final int VERSION_INIT = 1;
240 private static final int VERSION_ADD_PRIMARY = 2;
Jeff Sharkeyfced5342015-05-10 14:53:34 -0700241 private static final int VERSION_FIX_PRIMARY = 3;
Jeff Sharkey620b32b2015-04-23 19:36:02 -0700242
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700243 private static final String TAG_VOLUMES = "volumes";
Jeff Sharkey620b32b2015-04-23 19:36:02 -0700244 private static final String ATTR_VERSION = "version";
245 private static final String ATTR_PRIMARY_STORAGE_UUID = "primaryStorageUuid";
Jeff Sharkey4c099d02015-05-15 13:45:00 -0700246 private static final String ATTR_FORCE_ADOPTABLE = "forceAdoptable";
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700247 private static final String TAG_VOLUME = "volume";
248 private static final String ATTR_TYPE = "type";
249 private static final String ATTR_FS_UUID = "fsUuid";
Jeff Sharkey5cc0df22015-06-17 19:44:05 -0700250 private static final String ATTR_PART_GUID = "partGuid";
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700251 private static final String ATTR_NICKNAME = "nickname";
252 private static final String ATTR_USER_FLAGS = "userFlags";
Jeff Sharkeye8a4b662015-06-27 15:43:45 -0700253 private static final String ATTR_CREATED_MILLIS = "createdMillis";
254 private static final String ATTR_LAST_TRIM_MILLIS = "lastTrimMillis";
255 private static final String ATTR_LAST_BENCH_MILLIS = "lastBenchMillis";
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700256
Jeff Sharkeyb36586a2015-04-27 08:42:28 -0700257 private final AtomicFile mSettingsFile;
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700258
Jeff Sharkey48877892015-03-18 11:27:19 -0700259 /**
260 * <em>Never</em> hold the lock while performing downcalls into vold, since
261 * unsolicited events can suddenly appear to update data structures.
262 */
Jeff Sharkey5f3e9342017-03-13 14:53:11 -0600263 private final Object mLock = LockGuard.installNewLock(LockGuard.INDEX_STORAGE);
Jeff Sharkey48877892015-03-18 11:27:19 -0700264
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700265 /** Set of users that we know are unlocked. */
Jeff Sharkey48877892015-03-18 11:27:19 -0700266 @GuardedBy("mLock")
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700267 private int[] mLocalUnlockedUsers = EmptyArray.INT;
268 /** Set of users that system knows are unlocked. */
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -0800269 @GuardedBy("mLock")
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700270 private int[] mSystemUnlockedUsers = EmptyArray.INT;
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700271
272 /** Map from disk ID to disk */
Jeff Sharkey48877892015-03-18 11:27:19 -0700273 @GuardedBy("mLock")
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -0700274 private ArrayMap<String, DiskInfo> mDisks = new ArrayMap<>();
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700275 /** Map from volume ID to disk */
Jeff Sharkey48877892015-03-18 11:27:19 -0700276 @GuardedBy("mLock")
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700277 private final ArrayMap<String, VolumeInfo> mVolumes = new ArrayMap<>();
Jeff Sharkey48877892015-03-18 11:27:19 -0700278
Jeff Sharkeyb36586a2015-04-27 08:42:28 -0700279 /** Map from UUID to record */
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700280 @GuardedBy("mLock")
Jeff Sharkeyb36586a2015-04-27 08:42:28 -0700281 private ArrayMap<String, VolumeRecord> mRecords = new ArrayMap<>();
Jeff Sharkey620b32b2015-04-23 19:36:02 -0700282 @GuardedBy("mLock")
283 private String mPrimaryStorageUuid;
Jeff Sharkey4c099d02015-05-15 13:45:00 -0700284 @GuardedBy("mLock")
285 private boolean mForceAdoptable;
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700286
Jeff Sharkeyeba260d2015-04-19 14:35:16 -0700287 /** Map from disk ID to latches */
288 @GuardedBy("mLock")
289 private ArrayMap<String, CountDownLatch> mDiskScanLatches = new ArrayMap<>();
290
Jeff Sharkey275e3e42015-04-24 16:10:32 -0700291 @GuardedBy("mLock")
292 private IPackageMoveObserver mMoveCallback;
293 @GuardedBy("mLock")
294 private String mMoveTargetUuid;
295
Jeff Sharkeyab15c392016-05-05 11:45:01 -0600296 private volatile int mCurrentUserId = UserHandle.USER_SYSTEM;
297
Daichi Hirono9fb00182016-11-08 14:12:17 +0900298 /** Holding lock for AppFuse business */
299 private final Object mAppFuseLock = new Object();
300
301 @GuardedBy("mAppFuseLock")
302 private int mNextAppFuseName = 0;
303
304 @GuardedBy("mAppFuseLock")
Daichi Hironoe56740d2017-02-02 13:56:45 +0900305 private AppFuseBridge mAppFuseBridge = null;
Daichi Hirono9fb00182016-11-08 14:12:17 +0900306
Jeff Sharkeyef10ee02015-07-05 14:17:27 -0700307 private VolumeInfo findVolumeByIdOrThrow(String id) {
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700308 synchronized (mLock) {
309 final VolumeInfo vol = mVolumes.get(id);
310 if (vol != null) {
311 return vol;
312 }
313 }
314 throw new IllegalArgumentException("No volume found for ID " + id);
315 }
316
Jeff Sharkeyef10ee02015-07-05 14:17:27 -0700317 private String findVolumeIdForPathOrThrow(String path) {
Jeff Sharkey48877892015-03-18 11:27:19 -0700318 synchronized (mLock) {
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -0700319 for (int i = 0; i < mVolumes.size(); i++) {
320 final VolumeInfo vol = mVolumes.valueAt(i);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700321 if (vol.path != null && path.startsWith(vol.path)) {
322 return vol.id;
Jeff Sharkey48877892015-03-18 11:27:19 -0700323 }
324 }
325 }
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700326 throw new IllegalArgumentException("No volume found for path " + path);
Jeff Sharkey48877892015-03-18 11:27:19 -0700327 }
328
Jeff Sharkeye8a4b662015-06-27 15:43:45 -0700329 private VolumeRecord findRecordForPath(String path) {
330 synchronized (mLock) {
331 for (int i = 0; i < mVolumes.size(); i++) {
332 final VolumeInfo vol = mVolumes.valueAt(i);
333 if (vol.path != null && path.startsWith(vol.path)) {
334 return mRecords.get(vol.fsUuid);
335 }
336 }
337 }
338 return null;
339 }
340
341 private String scrubPath(String path) {
342 if (path.startsWith(Environment.getDataDirectory().getAbsolutePath())) {
343 return "internal";
344 }
345 final VolumeRecord rec = findRecordForPath(path);
346 if (rec == null || rec.createdMillis == 0) {
347 return "unknown";
348 } else {
349 return "ext:" + (int) ((System.currentTimeMillis() - rec.createdMillis)
350 / DateUtils.WEEK_IN_MILLIS) + "w";
351 }
352 }
353
Jeff Sharkeyef10ee02015-07-05 14:17:27 -0700354 private @Nullable VolumeInfo findStorageForUuid(String volumeUuid) {
Jeff Sharkey275e3e42015-04-24 16:10:32 -0700355 final StorageManager storage = mContext.getSystemService(StorageManager.class);
356 if (Objects.equals(StorageManager.UUID_PRIVATE_INTERNAL, volumeUuid)) {
Jeff Sharkeyef10ee02015-07-05 14:17:27 -0700357 return storage.findVolumeById(VolumeInfo.ID_EMULATED_INTERNAL);
Jeff Sharkey275e3e42015-04-24 16:10:32 -0700358 } else if (Objects.equals(StorageManager.UUID_PRIMARY_PHYSICAL, volumeUuid)) {
359 return storage.getPrimaryPhysicalVolume();
360 } else {
361 return storage.findEmulatedForPrivate(storage.findVolumeByUuid(volumeUuid));
362 }
363 }
364
Jeff Sharkeye8a4b662015-06-27 15:43:45 -0700365 private boolean shouldBenchmark() {
366 final long benchInterval = Settings.Global.getLong(mContext.getContentResolver(),
367 Settings.Global.STORAGE_BENCHMARK_INTERVAL, DateUtils.WEEK_IN_MILLIS);
Jeff Sharkeye83d8a92015-09-09 14:53:38 -0700368 if (benchInterval == -1) {
369 return false;
370 } else if (benchInterval == 0) {
371 return true;
372 }
373
Jeff Sharkeye8a4b662015-06-27 15:43:45 -0700374 synchronized (mLock) {
375 for (int i = 0; i < mVolumes.size(); i++) {
376 final VolumeInfo vol = mVolumes.valueAt(i);
377 final VolumeRecord rec = mRecords.get(vol.fsUuid);
Jeff Sharkeye83d8a92015-09-09 14:53:38 -0700378 if (vol.isMountedWritable() && rec != null) {
Jeff Sharkeye8a4b662015-06-27 15:43:45 -0700379 final long benchAge = System.currentTimeMillis() - rec.lastBenchMillis;
380 if (benchAge >= benchInterval) {
381 return true;
382 }
383 }
384 }
385 return false;
386 }
387 }
388
Jeff Sharkeyeba260d2015-04-19 14:35:16 -0700389 private CountDownLatch findOrCreateDiskScanLatch(String diskId) {
390 synchronized (mLock) {
391 CountDownLatch latch = mDiskScanLatches.get(diskId);
392 if (latch == null) {
393 latch = new CountDownLatch(1);
394 mDiskScanLatches.put(diskId, latch);
395 }
396 return latch;
397 }
398 }
399
Paul Lawrence8e397362014-01-27 15:22:30 -0800400 /** List of crypto types.
401 * These must match CRYPT_TYPE_XXX in cryptfs.h AND their
402 * corresponding commands in CommandListener.cpp */
403 public static final String[] CRYPTO_TYPES
404 = { "password", "default", "pattern", "pin" };
405
Brian Carlstrom7395a8a2014-04-28 22:11:01 -0700406 private final Context mContext;
Jeff Sharkeycd575992016-03-29 14:12:49 -0600407
Jeff Sharkey1019de92017-09-06 13:47:03 -0600408 private volatile IVold mVold;
Jin Qian12690d52017-10-13 18:17:04 -0700409 private volatile IStoraged mStoraged;
Jeff Sharkey1019de92017-09-06 13:47:03 -0600410
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700411 private volatile boolean mSystemReady = false;
Yasuhiro Matsuda87a38b52015-07-24 22:10:16 +0900412 private volatile boolean mBootCompleted = false;
Jeff Sharkey48877892015-03-18 11:27:19 -0700413 private volatile boolean mDaemonConnected = false;
Jeff Sharkey9765e442017-12-14 22:15:14 -0700414 private volatile boolean mSecureKeyguardShowing = true;
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700415
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700416 private PackageManagerService mPms;
417
418 private final Callbacks mCallbacks;
Jeff Sharkeyb9fe5372015-12-03 15:23:08 -0700419 private final LockPatternUtils mLockPatternUtils;
Jeff Sharkey48877892015-03-18 11:27:19 -0700420
San Mehat6cdd9c02010-02-09 14:45:20 -0800421 /**
Kenny Root3b1abba2010-10-13 15:00:07 -0700422 * The size of the crypto algorithm key in bits for OBB files. Currently
423 * Twofish is used which takes 128-bit keys.
424 */
425 private static final int CRYPTO_ALGORITHM_KEY_SIZE = 128;
426
427 /**
428 * The number of times to run SHA1 in the PBKDF2 function for OBB files.
429 * 1024 is reasonably secure and not too slow.
430 */
431 private static final int PBKDF2_HASH_ROUNDS = 1024;
432
433 /**
Kenny Roota02b8b02010-08-05 16:14:17 -0700434 * Mounted OBB tracking information. Used to track the current state of all
435 * OBBs.
Kenny Root02c87302010-07-01 08:10:18 -0700436 */
Kenny Root735de3b2010-09-30 14:11:39 -0700437 final private Map<IBinder, List<ObbState>> mObbMounts = new HashMap<IBinder, List<ObbState>>();
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700438
439 /** Map from raw paths to {@link ObbState}. */
Kenny Roota02b8b02010-08-05 16:14:17 -0700440 final private Map<String, ObbState> mObbPathToStateMap = new HashMap<String, ObbState>();
441
Svet Ganov6ee871e2015-07-10 14:29:33 -0700442 // Not guarded by a lock.
Sudheer Shanka2250d562016-11-07 15:41:02 -0800443 private final StorageManagerInternalImpl mStorageManagerInternal
444 = new StorageManagerInternalImpl();
Svet Ganov6ee871e2015-07-10 14:29:33 -0700445
Kenny Roota02b8b02010-08-05 16:14:17 -0700446 class ObbState implements IBinder.DeathRecipient {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700447 public ObbState(String rawPath, String canonicalPath, int callingUid,
Jeff Sharkey41cd6812017-09-11 10:32:17 -0600448 IObbActionListener token, int nonce, String volId) {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700449 this.rawPath = rawPath;
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700450 this.canonicalPath = canonicalPath;
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700451 this.ownerGid = UserHandle.getSharedAppGid(callingUid);
Kenny Rootaf9d6672010-10-08 09:21:39 -0700452 this.token = token;
453 this.nonce = nonce;
Jeff Sharkey41cd6812017-09-11 10:32:17 -0600454 this.volId = volId;
Kenny Roota02b8b02010-08-05 16:14:17 -0700455 }
456
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700457 final String rawPath;
458 final String canonicalPath;
Kenny Roota02b8b02010-08-05 16:14:17 -0700459
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700460 final int ownerGid;
Kenny Roota02b8b02010-08-05 16:14:17 -0700461
Kenny Rootaf9d6672010-10-08 09:21:39 -0700462 // Token of remote Binder caller
463 final IObbActionListener token;
464
465 // Identifier to pass back to the token
466 final int nonce;
Kenny Roota02b8b02010-08-05 16:14:17 -0700467
Jeff Sharkey41cd6812017-09-11 10:32:17 -0600468 String volId;
469
Kenny Root735de3b2010-09-30 14:11:39 -0700470 public IBinder getBinder() {
471 return token.asBinder();
472 }
473
Kenny Roota02b8b02010-08-05 16:14:17 -0700474 @Override
475 public void binderDied() {
476 ObbAction action = new UnmountObbAction(this, true);
477 mObbActionHandler.sendMessage(mObbActionHandler.obtainMessage(OBB_RUN_ACTION, action));
Kenny Root735de3b2010-09-30 14:11:39 -0700478 }
Kenny Roota02b8b02010-08-05 16:14:17 -0700479
Kenny Root5919ac62010-10-05 09:49:40 -0700480 public void link() throws RemoteException {
481 getBinder().linkToDeath(this, 0);
482 }
483
484 public void unlink() {
Kenny Root735de3b2010-09-30 14:11:39 -0700485 getBinder().unlinkToDeath(this, 0);
Kenny Roota02b8b02010-08-05 16:14:17 -0700486 }
Kenny Root38cf8862010-09-26 14:18:51 -0700487
488 @Override
489 public String toString() {
490 StringBuilder sb = new StringBuilder("ObbState{");
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700491 sb.append("rawPath=").append(rawPath);
492 sb.append(",canonicalPath=").append(canonicalPath);
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700493 sb.append(",ownerGid=").append(ownerGid);
494 sb.append(",token=").append(token);
495 sb.append(",binder=").append(getBinder());
Jeff Sharkey41cd6812017-09-11 10:32:17 -0600496 sb.append(",volId=").append(volId);
Kenny Root38cf8862010-09-26 14:18:51 -0700497 sb.append('}');
498 return sb.toString();
499 }
Kenny Roota02b8b02010-08-05 16:14:17 -0700500 }
501
502 // OBB Action Handler
503 final private ObbActionHandler mObbActionHandler;
504
505 // OBB action handler messages
506 private static final int OBB_RUN_ACTION = 1;
507 private static final int OBB_MCS_BOUND = 2;
508 private static final int OBB_MCS_UNBIND = 3;
509 private static final int OBB_MCS_RECONNECT = 4;
Kenny Rootaf9d6672010-10-08 09:21:39 -0700510 private static final int OBB_FLUSH_MOUNT_STATE = 5;
Kenny Roota02b8b02010-08-05 16:14:17 -0700511
512 /*
513 * Default Container Service information
514 */
515 static final ComponentName DEFAULT_CONTAINER_COMPONENT = new ComponentName(
516 "com.android.defcontainer", "com.android.defcontainer.DefaultContainerService");
517
518 final private DefaultContainerConnection mDefContainerConn = new DefaultContainerConnection();
519
520 class DefaultContainerConnection implements ServiceConnection {
Jeff Sharkey48877892015-03-18 11:27:19 -0700521 @Override
Kenny Roota02b8b02010-08-05 16:14:17 -0700522 public void onServiceConnected(ComponentName name, IBinder service) {
523 if (DEBUG_OBB)
524 Slog.i(TAG, "onServiceConnected");
525 IMediaContainerService imcs = IMediaContainerService.Stub.asInterface(service);
526 mObbActionHandler.sendMessage(mObbActionHandler.obtainMessage(OBB_MCS_BOUND, imcs));
527 }
528
Jeff Sharkey48877892015-03-18 11:27:19 -0700529 @Override
Kenny Roota02b8b02010-08-05 16:14:17 -0700530 public void onServiceDisconnected(ComponentName name) {
531 if (DEBUG_OBB)
532 Slog.i(TAG, "onServiceDisconnected");
533 }
Jeff Sharkey54402792017-09-15 16:05:19 -0600534 }
Kenny Roota02b8b02010-08-05 16:14:17 -0700535
536 // Used in the ObbActionHandler
537 private IMediaContainerService mContainerService = null;
Kenny Root02c87302010-07-01 08:10:18 -0700538
Christopher Tate7265abe2014-11-21 13:54:45 -0800539 // Last fstrim operation tracking
540 private static final String LAST_FSTRIM_FILE = "last-fstrim";
541 private final File mLastMaintenanceFile;
542 private long mLastMaintenance;
543
Kenny Root02c87302010-07-01 08:10:18 -0700544 // Handler messages
Jeff Sharkey48877892015-03-18 11:27:19 -0700545 private static final int H_SYSTEM_READY = 1;
546 private static final int H_DAEMON_CONNECTED = 2;
547 private static final int H_SHUTDOWN = 3;
548 private static final int H_FSTRIM = 4;
549 private static final int H_VOLUME_MOUNT = 5;
550 private static final int H_VOLUME_BROADCAST = 6;
Jeff Sharkeyabc3e852015-08-03 14:41:13 -0700551 private static final int H_INTERNAL_BROADCAST = 7;
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700552 private static final int H_VOLUME_UNMOUNT = 8;
Jeff Sharkey5a9bb742015-11-03 10:15:57 -0800553 private static final int H_PARTITION_FORGET = 9;
554 private static final int H_RESET = 10;
Jin Qiana85b9912017-10-17 15:48:18 -0700555 private static final int H_RUN_IDLE_MAINT = 11;
556 private static final int H_ABORT_IDLE_MAINT = 12;
Suchi Amalapurapu6ffce2e2010-03-08 14:48:40 -0800557
Sudheer Shanka2250d562016-11-07 15:41:02 -0800558 class StorageManagerServiceHandler extends Handler {
559 public StorageManagerServiceHandler(Looper looper) {
Jeff Sharkey48877892015-03-18 11:27:19 -0700560 super(looper);
Daniel Sandler5f27ef42010-03-16 15:42:02 -0400561 }
562
Jason parks5af0b912010-11-29 09:05:25 -0600563 @Override
Suchi Amalapurapuc42e29e2010-02-22 16:03:53 -0800564 public void handleMessage(Message msg) {
565 switch (msg.what) {
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700566 case H_SYSTEM_READY: {
Jeff Sharkey48877892015-03-18 11:27:19 -0700567 handleSystemReady();
568 break;
569 }
570 case H_DAEMON_CONNECTED: {
571 handleDaemonConnected();
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700572 break;
573 }
Christopher Tated417d622013-08-19 16:14:25 -0700574 case H_FSTRIM: {
Christopher Tated417d622013-08-19 16:14:25 -0700575 Slog.i(TAG, "Running fstrim idle maintenance");
Christopher Tate7265abe2014-11-21 13:54:45 -0800576
577 // Remember when we kicked it off
578 try {
579 mLastMaintenance = System.currentTimeMillis();
580 mLastMaintenanceFile.setLastModified(mLastMaintenance);
581 } catch (Exception e) {
582 Slog.e(TAG, "Unable to record last fstrim!");
583 }
584
Jeff Sharkeyb302c542017-09-15 12:57:59 -0600585 // TODO: Reintroduce shouldBenchmark() test
Jeff Sharkey7e19f532017-11-06 13:54:11 -0700586 fstrim(0, null);
Christopher Tate7265abe2014-11-21 13:54:45 -0800587
Christopher Tated417d622013-08-19 16:14:25 -0700588 // invoke the completion callback, if any
Jeff Sharkeye8a4b662015-06-27 15:43:45 -0700589 // TODO: fstrim is non-blocking, so remove this useless callback
Christopher Tated417d622013-08-19 16:14:25 -0700590 Runnable callback = (Runnable) msg.obj;
591 if (callback != null) {
592 callback.run();
593 }
594 break;
595 }
Jeff Sharkey48877892015-03-18 11:27:19 -0700596 case H_SHUTDOWN: {
Sudheer Shanka2250d562016-11-07 15:41:02 -0800597 final IStorageShutdownObserver obs = (IStorageShutdownObserver) msg.obj;
Jeff Sharkey48877892015-03-18 11:27:19 -0700598 boolean success = false;
599 try {
Jeff Sharkey54402792017-09-15 16:05:19 -0600600 mVold.shutdown();
601 success = true;
Jeff Sharkeyace874b2017-09-07 15:27:33 -0600602 } catch (Exception e) {
603 Slog.wtf(TAG, e);
Jeff Sharkey48877892015-03-18 11:27:19 -0700604 }
605 if (obs != null) {
606 try {
607 obs.onShutDownComplete(success ? 0 : -1);
Jeff Sharkeyace874b2017-09-07 15:27:33 -0600608 } catch (Exception ignored) {
Jeff Sharkey48877892015-03-18 11:27:19 -0700609 }
610 }
611 break;
612 }
613 case H_VOLUME_MOUNT: {
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -0700614 final VolumeInfo vol = (VolumeInfo) msg.obj;
Jeff Sharkey2e606d72015-07-27 14:19:54 -0700615 if (isMountDisallowed(vol)) {
616 Slog.i(TAG, "Ignoring mount " + vol.getId() + " due to policy");
617 break;
618 }
Jeff Sharkey48877892015-03-18 11:27:19 -0700619 try {
Jeff Sharkey54402792017-09-15 16:05:19 -0600620 mVold.mount(vol.id, vol.mountFlags, vol.mountUserId);
Jeff Sharkeyace874b2017-09-07 15:27:33 -0600621 } catch (Exception e) {
622 Slog.wtf(TAG, e);
Jeff Sharkey48877892015-03-18 11:27:19 -0700623 }
624 break;
625 }
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700626 case H_VOLUME_UNMOUNT: {
627 final VolumeInfo vol = (VolumeInfo) msg.obj;
628 unmount(vol.getId());
629 break;
630 }
Jeff Sharkey48877892015-03-18 11:27:19 -0700631 case H_VOLUME_BROADCAST: {
632 final StorageVolume userVol = (StorageVolume) msg.obj;
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700633 final String envState = userVol.getState();
634 Slog.d(TAG, "Volume " + userVol.getId() + " broadcasting " + envState + " to "
Jeff Sharkey48877892015-03-18 11:27:19 -0700635 + userVol.getOwner());
636
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700637 final String action = VolumeInfo.getBroadcastForEnvironment(envState);
Jeff Sharkey48877892015-03-18 11:27:19 -0700638 if (action != null) {
639 final Intent intent = new Intent(action,
640 Uri.fromFile(userVol.getPathFile()));
641 intent.putExtra(StorageVolume.EXTRA_STORAGE_VOLUME, userVol);
Jeff Sharkey082f83b2017-03-26 14:34:47 -0600642 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT
643 | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
Jeff Sharkey48877892015-03-18 11:27:19 -0700644 mContext.sendBroadcastAsUser(intent, userVol.getOwner());
645 }
646 break;
647 }
Jeff Sharkeyabc3e852015-08-03 14:41:13 -0700648 case H_INTERNAL_BROADCAST: {
649 // Internal broadcasts aimed at system components, not for
650 // third-party apps.
651 final Intent intent = (Intent) msg.obj;
652 mContext.sendBroadcastAsUser(intent, UserHandle.ALL,
653 android.Manifest.permission.WRITE_MEDIA_STORAGE);
Jeff Sharkey5a9bb742015-11-03 10:15:57 -0800654 break;
655 }
656 case H_PARTITION_FORGET: {
Jeff Sharkeydb4b6192017-10-24 11:08:50 -0600657 final VolumeRecord rec = (VolumeRecord) msg.obj;
658 forgetPartition(rec.partGuid, rec.fsUuid);
Jeff Sharkey5a9bb742015-11-03 10:15:57 -0800659 break;
660 }
661 case H_RESET: {
662 resetIfReadyAndConnected();
663 break;
Jeff Sharkeyabc3e852015-08-03 14:41:13 -0700664 }
Jin Qiana85b9912017-10-17 15:48:18 -0700665 case H_RUN_IDLE_MAINT: {
666 Slog.i(TAG, "Running idle maintenance");
667 runIdleMaint((Runnable)msg.obj);
668 break;
669 }
670 case H_ABORT_IDLE_MAINT: {
671 Slog.i(TAG, "Aborting idle maintenance");
672 abortIdleMaint((Runnable)msg.obj);
673 break;
674 }
675
Suchi Amalapurapuc42e29e2010-02-22 16:03:53 -0800676 }
677 }
Jeff Sharkey48877892015-03-18 11:27:19 -0700678 }
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700679
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700680 private final Handler mHandler;
Suchi Amalapurapuc42e29e2010-02-22 16:03:53 -0800681
Jeff Sharkeybcd262d2015-06-10 09:41:17 -0700682 private BroadcastReceiver mUserReceiver = new BroadcastReceiver() {
683 @Override
684 public void onReceive(Context context, Intent intent) {
685 final String action = intent.getAction();
686 final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700687 Preconditions.checkArgument(userId >= 0);
Jeff Sharkeybcd262d2015-06-10 09:41:17 -0700688
689 try {
690 if (Intent.ACTION_USER_ADDED.equals(action)) {
691 final UserManager um = mContext.getSystemService(UserManager.class);
692 final int userSerialNumber = um.getUserSerialNumber(userId);
Jeff Sharkey54402792017-09-15 16:05:19 -0600693 mVold.onUserAdded(userId, userSerialNumber);
Jeff Sharkeybcd262d2015-06-10 09:41:17 -0700694 } else if (Intent.ACTION_USER_REMOVED.equals(action)) {
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700695 synchronized (mVolumes) {
696 final int size = mVolumes.size();
697 for (int i = 0; i < size; i++) {
698 final VolumeInfo vol = mVolumes.valueAt(i);
699 if (vol.mountUserId == userId) {
700 vol.mountUserId = UserHandle.USER_NULL;
701 mHandler.obtainMessage(H_VOLUME_UNMOUNT, vol).sendToTarget();
702 }
703 }
704 }
Jeff Sharkey54402792017-09-15 16:05:19 -0600705 mVold.onUserRemoved(userId);
Jeff Sharkeybcd262d2015-06-10 09:41:17 -0700706 }
Jeff Sharkeyace874b2017-09-07 15:27:33 -0600707 } catch (Exception e) {
708 Slog.wtf(TAG, e);
Jeff Sharkeybcd262d2015-06-10 09:41:17 -0700709 }
710 }
711 };
712
Jeff Sharkeyedcdaf62015-07-09 09:45:36 -0700713 private void waitForLatch(CountDownLatch latch, String condition, long timeoutMillis)
714 throws TimeoutException {
715 final long startMillis = SystemClock.elapsedRealtime();
Jeff Sharkeyeba260d2015-04-19 14:35:16 -0700716 while (true) {
Kenny Root51a573c2012-05-17 13:30:28 -0700717 try {
718 if (latch.await(5000, TimeUnit.MILLISECONDS)) {
San Mehat207e5382010-02-04 20:46:54 -0800719 return;
Kenny Root51a573c2012-05-17 13:30:28 -0700720 } else {
721 Slog.w(TAG, "Thread " + Thread.currentThread().getName()
Jeff Sharkey48877892015-03-18 11:27:19 -0700722 + " still waiting for " + condition + "...");
San Mehat207e5382010-02-04 20:46:54 -0800723 }
Kenny Root51a573c2012-05-17 13:30:28 -0700724 } catch (InterruptedException e) {
Jeff Sharkeyeba260d2015-04-19 14:35:16 -0700725 Slog.w(TAG, "Interrupt while waiting for " + condition);
San Mehat207e5382010-02-04 20:46:54 -0800726 }
Jeff Sharkeyedcdaf62015-07-09 09:45:36 -0700727 if (timeoutMillis > 0 && SystemClock.elapsedRealtime() > startMillis + timeoutMillis) {
728 throw new TimeoutException("Thread " + Thread.currentThread().getName()
729 + " gave up waiting for " + condition + " after " + timeoutMillis + "ms");
730 }
San Mehat207e5382010-02-04 20:46:54 -0800731 }
San Mehat1f6301e2010-01-07 22:40:27 -0800732 }
Kenny Root02c87302010-07-01 08:10:18 -0700733
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700734 private void handleSystemReady() {
Jeff Sharkey8924e872015-11-30 12:52:10 -0700735 initIfReadyAndConnected();
Jeff Sharkey5a9bb742015-11-03 10:15:57 -0800736 resetIfReadyAndConnected();
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700737
Jeff Sharkey48877892015-03-18 11:27:19 -0700738 // Start scheduling nominally-daily fstrim operations
Christopher Tate115afda2014-06-06 19:06:26 -0700739 MountServiceIdler.scheduleIdlePass(mContext);
Daniel Colascione766b6322018-01-08 19:10:36 -0800740
741 // Toggle zram-enable system property in response to settings
742 mContext.getContentResolver().registerContentObserver(
743 Settings.Global.getUriFor(Settings.Global.ZRAM_ENABLED),
744 false /*notifyForDescendants*/,
745 new ContentObserver(null /* current thread */) {
746 @Override
747 public void onChange(boolean selfChange) {
748 refreshZramSettings();
749 }
750 });
751 refreshZramSettings();
752 }
753
754 /**
755 * Update the zram_enabled system property (which init reads to
756 * decide whether to enable zram) to reflect the zram_enabled
757 * preference (which we can change for experimentation purposes).
758 */
759 private void refreshZramSettings() {
760 String propertyValue = SystemProperties.get(ZRAM_ENABLED_PROPERTY);
761 if ("".equals(propertyValue)) {
762 return; // System doesn't have zram toggling support
763 }
764 String desiredPropertyValue =
765 Settings.Global.getInt(mContext.getContentResolver(),
766 Settings.Global.ZRAM_ENABLED,
767 1) != 0
768 ? "1" : "0";
769 if (!desiredPropertyValue.equals(propertyValue)) {
770 // Avoid redundant disk writes by setting only if we're
771 // changing the property value. There's no race: we're the
772 // sole writer.
773 SystemProperties.set(ZRAM_ENABLED_PROPERTY, desiredPropertyValue);
774 }
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700775 }
776
Jeff Sharkey14cbe522015-07-08 14:06:37 -0700777 /**
778 * MediaProvider has a ton of code that makes assumptions about storage
779 * paths never changing, so we outright kill them to pick up new state.
780 */
781 @Deprecated
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700782 private void killMediaProvider(List<UserInfo> users) {
783 if (users == null) return;
784
Jeff Sharkeyb3cf9532015-07-17 15:12:39 -0700785 final long token = Binder.clearCallingIdentity();
786 try {
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700787 for (UserInfo user : users) {
788 // System user does not have media provider, so skip.
789 if (user.isSystemOnly()) continue;
790
Jeff Sharkey2a9e3f82015-12-18 10:57:58 -0700791 final ProviderInfo provider = mPms.resolveContentProvider(MediaStore.AUTHORITY,
Jeff Sharkey8a372a02016-03-16 16:25:45 -0600792 PackageManager.MATCH_DIRECT_BOOT_AWARE
793 | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
794 user.id);
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700795 if (provider != null) {
Sudheer Shankadc589ac2016-11-10 15:30:17 -0800796 final IActivityManager am = ActivityManager.getService();
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700797 try {
Jeff Sharkey85f449e2016-06-23 09:26:00 -0600798 am.killApplication(provider.applicationInfo.packageName,
799 UserHandle.getAppId(provider.applicationInfo.uid),
800 UserHandle.USER_ALL, "vold reset");
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700801 // We only need to run this once. It will kill all users' media processes.
802 break;
803 } catch (RemoteException e) {
804 }
Jeff Sharkeyb3cf9532015-07-17 15:12:39 -0700805 }
Jeff Sharkey14cbe522015-07-08 14:06:37 -0700806 }
Jeff Sharkeyb3cf9532015-07-17 15:12:39 -0700807 } finally {
808 Binder.restoreCallingIdentity(token);
Jeff Sharkey14cbe522015-07-08 14:06:37 -0700809 }
810 }
811
Jeff Sharkey5a9bb742015-11-03 10:15:57 -0800812 private void addInternalVolumeLocked() {
Amith Yamasania7892482015-08-07 11:09:05 -0700813 // Create a stub volume that represents internal storage
814 final VolumeInfo internal = new VolumeInfo(VolumeInfo.ID_PRIVATE_INTERNAL,
815 VolumeInfo.TYPE_PRIVATE, null, null);
816 internal.state = VolumeInfo.STATE_MOUNTED;
817 internal.path = Environment.getDataDirectory().getAbsolutePath();
818 mVolumes.put(internal.id, internal);
819 }
820
Jeff Sharkey8924e872015-11-30 12:52:10 -0700821 private void initIfReadyAndConnected() {
822 Slog.d(TAG, "Thinking about init, mSystemReady=" + mSystemReady
823 + ", mDaemonConnected=" + mDaemonConnected);
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700824 if (mSystemReady && mDaemonConnected
Paul Lawrence20be5d62016-02-26 13:51:17 -0800825 && !StorageManager.isFileEncryptedNativeOnly()) {
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700826 // When booting a device without native support, make sure that our
827 // user directories are locked or unlocked based on the current
828 // emulation status.
Paul Lawrence20be5d62016-02-26 13:51:17 -0800829 final boolean initLocked = StorageManager.isFileEncryptedEmulatedOnly();
Paul Crowleyd94ab732016-02-15 06:44:51 +0000830 Slog.d(TAG, "Setting up emulation state, initlocked=" + initLocked);
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700831 final List<UserInfo> users = mContext.getSystemService(UserManager.class).getUsers();
Jeff Sharkey8924e872015-11-30 12:52:10 -0700832 for (UserInfo user : users) {
833 try {
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700834 if (initLocked) {
Jeff Sharkey54402792017-09-15 16:05:19 -0600835 mVold.lockUserKey(user.id);
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700836 } else {
Jeff Sharkey54402792017-09-15 16:05:19 -0600837 mVold.unlockUserKey(user.id, user.serialNumber, encodeBytes(null),
838 encodeBytes(null));
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700839 }
Jeff Sharkey43e12112017-09-12 16:31:45 -0600840 } catch (Exception e) {
841 Slog.wtf(TAG, e);
Jeff Sharkey8924e872015-11-30 12:52:10 -0700842 }
843 }
844 }
845 }
846
Jeff Sharkey5a9bb742015-11-03 10:15:57 -0800847 private void resetIfReadyAndConnected() {
Jeff Sharkey48877892015-03-18 11:27:19 -0700848 Slog.d(TAG, "Thinking about reset, mSystemReady=" + mSystemReady
849 + ", mDaemonConnected=" + mDaemonConnected);
850 if (mSystemReady && mDaemonConnected) {
Jeff Sharkey5a9bb742015-11-03 10:15:57 -0800851 final List<UserInfo> users = mContext.getSystemService(UserManager.class).getUsers();
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700852 killMediaProvider(users);
Jeff Sharkey14cbe522015-07-08 14:06:37 -0700853
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700854 final int[] systemUnlockedUsers;
Jeff Sharkey5a9bb742015-11-03 10:15:57 -0800855 synchronized (mLock) {
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700856 systemUnlockedUsers = mSystemUnlockedUsers;
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700857
Jeff Sharkey5a9bb742015-11-03 10:15:57 -0800858 mDisks.clear();
859 mVolumes.clear();
860
861 addInternalVolumeLocked();
862 }
Jeff Sharkey59d577a2015-04-11 21:27:21 -0700863
Jeff Sharkey48877892015-03-18 11:27:19 -0700864 try {
Jeff Sharkey54402792017-09-15 16:05:19 -0600865 mVold.reset();
Jeff Sharkeybcd262d2015-06-10 09:41:17 -0700866
867 // Tell vold about all existing and started users
Jeff Sharkeybcd262d2015-06-10 09:41:17 -0700868 for (UserInfo user : users) {
Jeff Sharkey54402792017-09-15 16:05:19 -0600869 mVold.onUserAdded(user.id, user.serialNumber);
Jeff Sharkeybcd262d2015-06-10 09:41:17 -0700870 }
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700871 for (int userId : systemUnlockedUsers) {
Jeff Sharkey54402792017-09-15 16:05:19 -0600872 mVold.onUserStarted(userId);
Jin Qian12690d52017-10-13 18:17:04 -0700873 mStoraged.onUserStarted(userId);
Jeff Sharkey50a05452015-04-29 11:24:52 -0700874 }
Jeff Sharkey9765e442017-12-14 22:15:14 -0700875 mVold.onSecureKeyguardStateChanged(mSecureKeyguardShowing);
Jeff Sharkeyace874b2017-09-07 15:27:33 -0600876 } catch (Exception e) {
877 Slog.wtf(TAG, e);
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700878 }
879 }
Jeff Sharkey48877892015-03-18 11:27:19 -0700880 }
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700881
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700882 private void onUnlockUser(int userId) {
883 Slog.d(TAG, "onUnlockUser " + userId);
Jeff Sharkey48877892015-03-18 11:27:19 -0700884
885 // We purposefully block here to make sure that user-specific
886 // staging area is ready so it's ready for zygote-forked apps to
887 // bind mount against.
888 try {
Jeff Sharkey54402792017-09-15 16:05:19 -0600889 mVold.onUserStarted(userId);
Jin Qian12690d52017-10-13 18:17:04 -0700890 mStoraged.onUserStarted(userId);
Jeff Sharkeyace874b2017-09-07 15:27:33 -0600891 } catch (Exception e) {
892 Slog.wtf(TAG, e);
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700893 }
Jeff Sharkey48877892015-03-18 11:27:19 -0700894
895 // Record user as started so newly mounted volumes kick off events
896 // correctly, then synthesize events for any already-mounted volumes.
yuanhuihuiefd1f122016-07-13 21:21:03 +0800897 synchronized (mLock) {
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -0700898 for (int i = 0; i < mVolumes.size(); i++) {
899 final VolumeInfo vol = mVolumes.valueAt(i);
Jeff Sharkey46349872015-07-28 10:49:47 -0700900 if (vol.isVisibleForRead(userId) && vol.isMountedReadable()) {
Svet Ganov6ee871e2015-07-10 14:29:33 -0700901 final StorageVolume userVol = vol.buildStorageVolume(mContext, userId, false);
Jeff Sharkey48877892015-03-18 11:27:19 -0700902 mHandler.obtainMessage(H_VOLUME_BROADCAST, userVol).sendToTarget();
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700903
Jeff Sharkey27de30d2015-04-18 16:20:27 -0700904 final String envState = VolumeInfo.getEnvironmentForState(vol.getState());
905 mCallbacks.notifyStorageStateChanged(userVol.getPath(), envState, envState);
Jeff Sharkey48877892015-03-18 11:27:19 -0700906 }
907 }
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700908 mSystemUnlockedUsers = ArrayUtils.appendInt(mSystemUnlockedUsers, userId);
Jeff Sharkey48877892015-03-18 11:27:19 -0700909 }
910 }
911
912 private void onCleanupUser(int userId) {
913 Slog.d(TAG, "onCleanupUser " + userId);
914
915 try {
Jeff Sharkey54402792017-09-15 16:05:19 -0600916 mVold.onUserStopped(userId);
Jin Qian12690d52017-10-13 18:17:04 -0700917 mStoraged.onUserStopped(userId);
Jeff Sharkeyace874b2017-09-07 15:27:33 -0600918 } catch (Exception e) {
919 Slog.wtf(TAG, e);
Jeff Sharkey48877892015-03-18 11:27:19 -0700920 }
921
yuanhuihuiefd1f122016-07-13 21:21:03 +0800922 synchronized (mLock) {
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700923 mSystemUnlockedUsers = ArrayUtils.removeInt(mSystemUnlockedUsers, userId);
Jeff Sharkey48877892015-03-18 11:27:19 -0700924 }
925 }
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700926
Jeff Sharkey9765e442017-12-14 22:15:14 -0700927 @Override
928 public void onAwakeStateChanged(boolean isAwake) {
929 // Ignored
930 }
931
932 @Override
933 public void onKeyguardStateChanged(boolean isShowing) {
934 // Push down current secure keyguard status so that we ignore malicious
935 // USB devices while locked.
936 mSecureKeyguardShowing = isShowing
937 && mContext.getSystemService(KeyguardManager.class).isDeviceSecure();
938 try {
939 mVold.onSecureKeyguardStateChanged(mSecureKeyguardShowing);
940 } catch (Exception e) {
941 Slog.wtf(TAG, e);
942 }
943 }
944
Christopher Tated417d622013-08-19 16:14:25 -0700945 void runIdleMaintenance(Runnable callback) {
946 mHandler.sendMessage(mHandler.obtainMessage(H_FSTRIM, callback));
947 }
948
Christopher Tate7265abe2014-11-21 13:54:45 -0800949 // Binder entry point for kicking off an immediate fstrim
950 @Override
951 public void runMaintenance() {
Jeff Sharkey48877892015-03-18 11:27:19 -0700952 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
Christopher Tate7265abe2014-11-21 13:54:45 -0800953 runIdleMaintenance(null);
954 }
955
956 @Override
957 public long lastMaintenance() {
958 return mLastMaintenance;
959 }
960
San Mehat4270e1e2010-01-29 05:32:19 -0800961 public void onDaemonConnected() {
Jeff Sharkey48877892015-03-18 11:27:19 -0700962 mDaemonConnected = true;
963 mHandler.obtainMessage(H_DAEMON_CONNECTED).sendToTarget();
964 }
965
966 private void handleDaemonConnected() {
Jeff Sharkey8924e872015-11-30 12:52:10 -0700967 initIfReadyAndConnected();
Jeff Sharkey5a9bb742015-11-03 10:15:57 -0800968 resetIfReadyAndConnected();
Jeff Sharkey48877892015-03-18 11:27:19 -0700969
Jeff Sharkey48877892015-03-18 11:27:19 -0700970 // On an encrypted device we can't see system properties yet, so pull
971 // the system locale out of the mount service.
972 if ("".equals(SystemProperties.get("vold.encrypt_progress"))) {
973 copyLocaleFromMountService();
974 }
San Mehat4270e1e2010-01-29 05:32:19 -0800975 }
976
Elliott Hughesf839b4f2014-09-26 12:30:47 -0700977 private void copyLocaleFromMountService() {
978 String systemLocale;
979 try {
980 systemLocale = getField(StorageManager.SYSTEM_LOCALE_KEY);
981 } catch (RemoteException e) {
982 return;
983 }
984 if (TextUtils.isEmpty(systemLocale)) {
985 return;
986 }
987
988 Slog.d(TAG, "Got locale " + systemLocale + " from mount service");
989 Locale locale = Locale.forLanguageTag(systemLocale);
990 Configuration config = new Configuration();
991 config.setLocale(locale);
992 try {
Sudheer Shankadc589ac2016-11-10 15:30:17 -0800993 ActivityManager.getService().updatePersistentConfiguration(config);
Elliott Hughesf839b4f2014-09-26 12:30:47 -0700994 } catch (RemoteException e) {
995 Slog.e(TAG, "Error setting system locale from mount service", e);
996 }
Elliott Hughes9c33f282014-10-13 12:39:56 -0700997
998 // Temporary workaround for http://b/17945169.
999 Slog.d(TAG, "Setting system properties to " + systemLocale + " from mount service");
Narayan Kamathd30dbb82015-01-15 14:48:15 +00001000 SystemProperties.set("persist.sys.locale", locale.toLanguageTag());
Elliott Hughesf839b4f2014-09-26 12:30:47 -07001001 }
1002
Jeff Sharkey8058fe62017-09-13 11:50:33 -06001003 private final IVoldListener mListener = new IVoldListener.Stub() {
1004 @Override
1005 public void onDiskCreated(String diskId, int flags) {
1006 synchronized (mLock) {
1007 if (SystemProperties.getBoolean(StorageManager.PROP_FORCE_ADOPTABLE, false)
1008 || mForceAdoptable) {
1009 flags |= DiskInfo.FLAG_ADOPTABLE;
1010 }
Jeff Sharkey8058fe62017-09-13 11:50:33 -06001011 mDisks.put(diskId, new DiskInfo(diskId, flags));
1012 }
1013 }
1014
1015 @Override
1016 public void onDiskScanned(String diskId) {
1017 synchronized (mLock) {
1018 final DiskInfo disk = mDisks.get(diskId);
1019 if (disk != null) {
1020 onDiskScannedLocked(disk);
1021 }
1022 }
1023 }
1024
1025 @Override
1026 public void onDiskMetadataChanged(String diskId, long sizeBytes, String label,
1027 String sysPath) {
1028 synchronized (mLock) {
1029 final DiskInfo disk = mDisks.get(diskId);
1030 if (disk != null) {
1031 disk.size = sizeBytes;
1032 disk.label = label;
1033 disk.sysPath = sysPath;
1034 }
1035 }
1036 }
1037
1038 @Override
1039 public void onDiskDestroyed(String diskId) {
1040 synchronized (mLock) {
1041 final DiskInfo disk = mDisks.remove(diskId);
1042 if (disk != null) {
1043 mCallbacks.notifyDiskDestroyed(disk);
1044 }
1045 }
1046 }
1047
1048 @Override
1049 public void onVolumeCreated(String volId, int type, String diskId, String partGuid) {
1050 synchronized (mLock) {
1051 final DiskInfo disk = mDisks.get(diskId);
1052 final VolumeInfo vol = new VolumeInfo(volId, type, disk, partGuid);
1053 mVolumes.put(volId, vol);
1054 onVolumeCreatedLocked(vol);
1055 }
1056 }
1057
1058 @Override
1059 public void onVolumeStateChanged(String volId, int state) {
1060 synchronized (mLock) {
1061 final VolumeInfo vol = mVolumes.get(volId);
1062 if (vol != null) {
1063 final int oldState = vol.state;
1064 final int newState = state;
1065 vol.state = newState;
1066 onVolumeStateChangedLocked(vol, oldState, newState);
1067 }
1068 }
1069 }
1070
1071 @Override
1072 public void onVolumeMetadataChanged(String volId, String fsType, String fsUuid,
1073 String fsLabel) {
1074 synchronized (mLock) {
1075 final VolumeInfo vol = mVolumes.get(volId);
1076 if (vol != null) {
1077 vol.fsType = fsType;
1078 vol.fsUuid = fsUuid;
1079 vol.fsLabel = fsLabel;
1080 }
1081 }
1082 }
1083
1084 @Override
1085 public void onVolumePathChanged(String volId, String path) {
1086 synchronized (mLock) {
1087 final VolumeInfo vol = mVolumes.get(volId);
1088 if (vol != null) {
1089 vol.path = path;
1090 }
1091 }
1092 }
1093
1094 @Override
1095 public void onVolumeInternalPathChanged(String volId, String internalPath) {
1096 synchronized (mLock) {
1097 final VolumeInfo vol = mVolumes.get(volId);
1098 if (vol != null) {
1099 vol.internalPath = internalPath;
1100 }
1101 }
1102 }
1103
1104 @Override
1105 public void onVolumeDestroyed(String volId) {
1106 synchronized (mLock) {
1107 mVolumes.remove(volId);
1108 }
1109 }
1110 };
1111
Jeff Sharkeyeba260d2015-04-19 14:35:16 -07001112 private void onDiskScannedLocked(DiskInfo disk) {
Jeff Sharkey620b32b2015-04-23 19:36:02 -07001113 int volumeCount = 0;
Jeff Sharkeyeba260d2015-04-19 14:35:16 -07001114 for (int i = 0; i < mVolumes.size(); i++) {
1115 final VolumeInfo vol = mVolumes.valueAt(i);
1116 if (Objects.equals(disk.id, vol.getDiskId())) {
Jeff Sharkey620b32b2015-04-23 19:36:02 -07001117 volumeCount++;
Jeff Sharkeyeba260d2015-04-19 14:35:16 -07001118 }
1119 }
1120
Jeff Sharkeyc7acac62015-06-12 16:16:56 -07001121 final Intent intent = new Intent(DiskInfo.ACTION_DISK_SCANNED);
Jeff Sharkey7732e1e2016-03-30 17:14:23 -06001122 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT
1123 | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
Jeff Sharkeyc7acac62015-06-12 16:16:56 -07001124 intent.putExtra(DiskInfo.EXTRA_DISK_ID, disk.id);
1125 intent.putExtra(DiskInfo.EXTRA_VOLUME_COUNT, volumeCount);
Jeff Sharkeyabc3e852015-08-03 14:41:13 -07001126 mHandler.obtainMessage(H_INTERNAL_BROADCAST, intent).sendToTarget();
Jeff Sharkeyc7acac62015-06-12 16:16:56 -07001127
1128 final CountDownLatch latch = mDiskScanLatches.remove(disk.id);
1129 if (latch != null) {
1130 latch.countDown();
1131 }
1132
Jeff Sharkeyf5a6bd72015-05-19 14:42:38 -07001133 disk.volumeCount = volumeCount;
Jeff Sharkey620b32b2015-04-23 19:36:02 -07001134 mCallbacks.notifyDiskScanned(disk, volumeCount);
Jeff Sharkeyeba260d2015-04-19 14:35:16 -07001135 }
1136
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07001137 private void onVolumeCreatedLocked(VolumeInfo vol) {
Jeff Sharkey6855c482016-03-31 14:34:38 -06001138 if (mPms.isOnlyCoreApps()) {
1139 Slog.d(TAG, "System booted in core-only mode; ignoring volume " + vol.getId());
1140 return;
1141 }
1142
Jeff Sharkey275e3e42015-04-24 16:10:32 -07001143 if (vol.type == VolumeInfo.TYPE_EMULATED) {
1144 final StorageManager storage = mContext.getSystemService(StorageManager.class);
1145 final VolumeInfo privateVol = storage.findPrivateForEmulated(vol);
1146
1147 if (Objects.equals(StorageManager.UUID_PRIVATE_INTERNAL, mPrimaryStorageUuid)
1148 && VolumeInfo.ID_PRIVATE_INTERNAL.equals(privateVol.id)) {
1149 Slog.v(TAG, "Found primary storage at " + vol);
1150 vol.mountFlags |= VolumeInfo.MOUNT_FLAG_PRIMARY;
1151 vol.mountFlags |= VolumeInfo.MOUNT_FLAG_VISIBLE;
1152 mHandler.obtainMessage(H_VOLUME_MOUNT, vol).sendToTarget();
1153
1154 } else if (Objects.equals(privateVol.fsUuid, mPrimaryStorageUuid)) {
1155 Slog.v(TAG, "Found primary storage at " + vol);
1156 vol.mountFlags |= VolumeInfo.MOUNT_FLAG_PRIMARY;
1157 vol.mountFlags |= VolumeInfo.MOUNT_FLAG_VISIBLE;
1158 mHandler.obtainMessage(H_VOLUME_MOUNT, vol).sendToTarget();
1159 }
Jeff Sharkeyb049e212012-09-07 23:16:01 -07001160
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07001161 } else if (vol.type == VolumeInfo.TYPE_PUBLIC) {
Jeff Sharkey275e3e42015-04-24 16:10:32 -07001162 // TODO: only look at first public partition
1163 if (Objects.equals(StorageManager.UUID_PRIMARY_PHYSICAL, mPrimaryStorageUuid)
1164 && vol.disk.isDefaultPrimary()) {
1165 Slog.v(TAG, "Found primary storage at " + vol);
Jeff Sharkey7e92ef32015-04-17 17:35:07 -07001166 vol.mountFlags |= VolumeInfo.MOUNT_FLAG_PRIMARY;
1167 vol.mountFlags |= VolumeInfo.MOUNT_FLAG_VISIBLE;
San Mehat4270e1e2010-01-29 05:32:19 -08001168 }
Jeff Sharkey7e92ef32015-04-17 17:35:07 -07001169
1170 // Adoptable public disks are visible to apps, since they meet
1171 // public API requirement of being in a stable location.
Jeff Sharkey275e3e42015-04-24 16:10:32 -07001172 if (vol.disk.isAdoptable()) {
Jeff Sharkey7e92ef32015-04-17 17:35:07 -07001173 vol.mountFlags |= VolumeInfo.MOUNT_FLAG_VISIBLE;
1174 }
1175
Jeff Sharkeyab15c392016-05-05 11:45:01 -06001176 vol.mountUserId = mCurrentUserId;
Jeff Sharkey48877892015-03-18 11:27:19 -07001177 mHandler.obtainMessage(H_VOLUME_MOUNT, vol).sendToTarget();
San Mehat4270e1e2010-01-29 05:32:19 -08001178
Jeff Sharkeyb2b9ab82015-04-05 21:10:42 -07001179 } else if (vol.type == VolumeInfo.TYPE_PRIVATE) {
1180 mHandler.obtainMessage(H_VOLUME_MOUNT, vol).sendToTarget();
1181
San Mehat4270e1e2010-01-29 05:32:19 -08001182 } else {
Jeff Sharkey48877892015-03-18 11:27:19 -07001183 Slog.d(TAG, "Skipping automatic mounting of " + vol);
San Mehat4270e1e2010-01-29 05:32:19 -08001184 }
1185 }
1186
Jeff Sharkeye6c04f92015-04-18 21:38:05 -07001187 private boolean isBroadcastWorthy(VolumeInfo vol) {
1188 switch (vol.getType()) {
Jeff Sharkeyc7acac62015-06-12 16:16:56 -07001189 case VolumeInfo.TYPE_PRIVATE:
Jeff Sharkeye6c04f92015-04-18 21:38:05 -07001190 case VolumeInfo.TYPE_PUBLIC:
1191 case VolumeInfo.TYPE_EMULATED:
1192 break;
1193 default:
1194 return false;
1195 }
1196
1197 switch (vol.getState()) {
1198 case VolumeInfo.STATE_MOUNTED:
1199 case VolumeInfo.STATE_MOUNTED_READ_ONLY:
1200 case VolumeInfo.STATE_EJECTING:
1201 case VolumeInfo.STATE_UNMOUNTED:
Jeff Sharkeyc7acac62015-06-12 16:16:56 -07001202 case VolumeInfo.STATE_UNMOUNTABLE:
Tony Mantlerf0d71052015-06-24 11:45:25 -07001203 case VolumeInfo.STATE_BAD_REMOVAL:
Jeff Sharkeye6c04f92015-04-18 21:38:05 -07001204 break;
1205 default:
1206 return false;
1207 }
1208
1209 return true;
1210 }
1211
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07001212 private void onVolumeStateChangedLocked(VolumeInfo vol, int oldState, int newState) {
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001213 // Remember that we saw this volume so we're ready to accept user
1214 // metadata, or so we can annoy them when a private volume is ejected
1215 if (vol.isMountedReadable() && !TextUtils.isEmpty(vol.fsUuid)) {
Jeff Sharkey5cc0df22015-06-17 19:44:05 -07001216 VolumeRecord rec = mRecords.get(vol.fsUuid);
1217 if (rec == null) {
1218 rec = new VolumeRecord(vol.type, vol.fsUuid);
1219 rec.partGuid = vol.partGuid;
Jeff Sharkeye8a4b662015-06-27 15:43:45 -07001220 rec.createdMillis = System.currentTimeMillis();
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001221 if (vol.type == VolumeInfo.TYPE_PRIVATE) {
1222 rec.nickname = vol.disk.getDescription();
1223 }
1224 mRecords.put(rec.fsUuid, rec);
1225 writeSettingsLocked();
Jeff Sharkey5cc0df22015-06-17 19:44:05 -07001226 } else {
1227 // Handle upgrade case where we didn't store partition GUID
1228 if (TextUtils.isEmpty(rec.partGuid)) {
1229 rec.partGuid = vol.partGuid;
1230 writeSettingsLocked();
1231 }
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001232 }
1233 }
1234
Jeff Sharkeye6c04f92015-04-18 21:38:05 -07001235 mCallbacks.notifyVolumeStateChanged(vol, oldState, newState);
1236
Yasuhiro Matsuda87a38b52015-07-24 22:10:16 +09001237 // Do not broadcast before boot has completed to avoid launching the
1238 // processes that receive the intent unnecessarily.
1239 if (mBootCompleted && isBroadcastWorthy(vol)) {
Jeff Sharkeye6c04f92015-04-18 21:38:05 -07001240 final Intent intent = new Intent(VolumeInfo.ACTION_VOLUME_STATE_CHANGED);
Jeff Sharkeyc7acac62015-06-12 16:16:56 -07001241 intent.putExtra(VolumeInfo.EXTRA_VOLUME_ID, vol.id);
1242 intent.putExtra(VolumeInfo.EXTRA_VOLUME_STATE, newState);
Tony Mantlerf0d71052015-06-24 11:45:25 -07001243 intent.putExtra(VolumeRecord.EXTRA_FS_UUID, vol.fsUuid);
Jeff Sharkey7732e1e2016-03-30 17:14:23 -06001244 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT
1245 | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
Jeff Sharkeyabc3e852015-08-03 14:41:13 -07001246 mHandler.obtainMessage(H_INTERNAL_BROADCAST, intent).sendToTarget();
Jeff Sharkeye6c04f92015-04-18 21:38:05 -07001247 }
Jeff Sharkeyb049e212012-09-07 23:16:01 -07001248
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001249 final String oldStateEnv = VolumeInfo.getEnvironmentForState(oldState);
1250 final String newStateEnv = VolumeInfo.getEnvironmentForState(newState);
Emily Bernier92aa5a22014-07-07 10:11:48 -04001251
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001252 if (!Objects.equals(oldStateEnv, newStateEnv)) {
1253 // Kick state changed event towards all started users. Any users
1254 // started after this point will trigger additional
1255 // user-specific broadcasts.
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07001256 for (int userId : mSystemUnlockedUsers) {
Jeff Sharkey46349872015-07-28 10:49:47 -07001257 if (vol.isVisibleForRead(userId)) {
Svet Ganov6ee871e2015-07-10 14:29:33 -07001258 final StorageVolume userVol = vol.buildStorageVolume(mContext, userId, false);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001259 mHandler.obtainMessage(H_VOLUME_BROADCAST, userVol).sendToTarget();
Jeff Sharkey48877892015-03-18 11:27:19 -07001260
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001261 mCallbacks.notifyStorageStateChanged(userVol.getPath(), oldStateEnv,
1262 newStateEnv);
San Mehat4270e1e2010-01-29 05:32:19 -08001263 }
1264 }
1265 }
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001266
Jeff Sharkey7e92ef32015-04-17 17:35:07 -07001267 if (vol.type == VolumeInfo.TYPE_PUBLIC && vol.state == VolumeInfo.STATE_EJECTING) {
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001268 // TODO: this should eventually be handled by new ObbVolume state changes
1269 /*
1270 * Some OBBs might have been unmounted when this volume was
1271 * unmounted, so send a message to the handler to let it know to
1272 * remove those from the list of mounted OBBS.
1273 */
1274 mObbActionHandler.sendMessage(mObbActionHandler.obtainMessage(
1275 OBB_FLUSH_MOUNT_STATE, vol.path));
1276 }
Pavel Grafovce72ef02018-01-10 17:14:11 +00001277 maybeLogMediaMount(vol, newState);
1278 }
1279
1280 private void maybeLogMediaMount(VolumeInfo vol, int newState) {
1281 if (!SecurityLog.isLoggingEnabled()) {
1282 return;
1283 }
1284
1285 final DiskInfo disk = vol.getDisk();
1286 if (disk == null || (disk.flags & (DiskInfo.FLAG_SD | DiskInfo.FLAG_USB)) == 0) {
1287 return;
1288 }
1289
1290 // Sometimes there is a newline character.
1291 final String label = disk.label != null ? disk.label.trim() : "";
1292
1293 if (newState == VolumeInfo.STATE_MOUNTED
1294 || newState == VolumeInfo.STATE_MOUNTED_READ_ONLY) {
1295 SecurityLog.writeEvent(SecurityLog.TAG_MEDIA_MOUNT, vol.path, label);
1296 } else if (newState == VolumeInfo.STATE_UNMOUNTED
1297 || newState == VolumeInfo.STATE_BAD_REMOVAL) {
1298 SecurityLog.writeEvent(SecurityLog.TAG_MEDIA_UNMOUNT, vol.path, label);
1299 }
San Mehat4270e1e2010-01-29 05:32:19 -08001300 }
1301
Jeff Sharkey275e3e42015-04-24 16:10:32 -07001302 private void onMoveStatusLocked(int status) {
1303 if (mMoveCallback == null) {
1304 Slog.w(TAG, "Odd, status but no move requested");
1305 return;
1306 }
1307
1308 // TODO: estimate remaining time
1309 try {
Jeff Sharkey50a05452015-04-29 11:24:52 -07001310 mMoveCallback.onStatusChanged(-1, status, -1);
Jeff Sharkey275e3e42015-04-24 16:10:32 -07001311 } catch (RemoteException ignored) {
1312 }
1313
1314 // We've finished copying and we're about to clean up old data, so
1315 // remember that move was successful if we get rebooted
1316 if (status == MOVE_STATUS_COPY_FINISHED) {
1317 Slog.d(TAG, "Move to " + mMoveTargetUuid + " copy phase finshed; persisting");
1318
1319 mPrimaryStorageUuid = mMoveTargetUuid;
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001320 writeSettingsLocked();
Jeff Sharkey275e3e42015-04-24 16:10:32 -07001321 }
1322
1323 if (PackageManager.isMoveStatusFinished(status)) {
1324 Slog.d(TAG, "Move to " + mMoveTargetUuid + " finished with status " + status);
1325
1326 mMoveCallback = null;
1327 mMoveTargetUuid = null;
1328 }
1329 }
1330
Jeff Sharkey48877892015-03-18 11:27:19 -07001331 private void enforcePermission(String perm) {
1332 mContext.enforceCallingOrSelfPermission(perm, perm);
Mike Lockwooda5250c92011-05-23 13:44:04 -04001333 }
1334
Jeff Sharkey2e606d72015-07-27 14:19:54 -07001335 /**
1336 * Decide if volume is mountable per device policies.
1337 */
1338 private boolean isMountDisallowed(VolumeInfo vol) {
Philip P. Moltmannec3cbb22016-09-14 13:24:52 -07001339 UserManager userManager = mContext.getSystemService(UserManager.class);
1340
1341 boolean isUsbRestricted = false;
1342 if (vol.disk != null && vol.disk.isUsb()) {
1343 isUsbRestricted = userManager.hasUserRestriction(UserManager.DISALLOW_USB_FILE_TRANSFER,
Jeff Sharkey2e606d72015-07-27 14:19:54 -07001344 Binder.getCallingUserHandle());
Emily Bernier92aa5a22014-07-07 10:11:48 -04001345 }
Philip P. Moltmannec3cbb22016-09-14 13:24:52 -07001346
1347 boolean isTypeRestricted = false;
1348 if (vol.type == VolumeInfo.TYPE_PUBLIC || vol.type == VolumeInfo.TYPE_PRIVATE) {
1349 isTypeRestricted = userManager
1350 .hasUserRestriction(UserManager.DISALLOW_MOUNT_PHYSICAL_MEDIA,
1351 Binder.getCallingUserHandle());
1352 }
1353
1354 return isUsbRestricted || isTypeRestricted;
Emily Bernier92aa5a22014-07-07 10:11:48 -04001355 }
1356
Amith Yamasani462ac3a2015-06-30 14:21:01 -07001357 private void enforceAdminUser() {
1358 UserManager um = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
1359 final int callingUserId = UserHandle.getCallingUserId();
1360 boolean isAdmin;
1361 long token = Binder.clearCallingIdentity();
1362 try {
1363 isAdmin = um.getUserInfo(callingUserId).isAdmin();
1364 } finally {
1365 Binder.restoreCallingIdentity(token);
1366 }
1367 if (!isAdmin) {
1368 throw new SecurityException("Only admin users can adopt sd cards");
1369 }
1370 }
1371
Jeff Sharkeyb049e212012-09-07 23:16:01 -07001372 /**
Sudheer Shanka2250d562016-11-07 15:41:02 -08001373 * Constructs a new StorageManagerService instance
San Mehat207e5382010-02-04 20:46:54 -08001374 *
1375 * @param context Binder context for this service
1376 */
Sudheer Shanka2250d562016-11-07 15:41:02 -08001377 public StorageManagerService(Context context) {
Christopher Tated417d622013-08-19 16:14:25 -07001378 sSelf = this;
1379
San Mehat207e5382010-02-04 20:46:54 -08001380 mContext = context;
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001381 mCallbacks = new Callbacks(FgThread.get().getLooper());
Jeff Sharkeyb9fe5372015-12-03 15:23:08 -07001382 mLockPatternUtils = new LockPatternUtils(mContext);
San Mehat207e5382010-02-04 20:46:54 -08001383
San Mehat207e5382010-02-04 20:46:54 -08001384 // XXX: This will go away soon in favor of IMountServiceObserver
1385 mPms = (PackageManagerService) ServiceManager.getService("package");
1386
Dianne Hackbornefa92b22013-05-03 14:11:43 -07001387 HandlerThread hthread = new HandlerThread(TAG);
1388 hthread.start();
Sudheer Shanka2250d562016-11-07 15:41:02 -08001389 mHandler = new StorageManagerServiceHandler(hthread.getLooper());
Daniel Sandler5f27ef42010-03-16 15:42:02 -04001390
Sudheer Shanka2250d562016-11-07 15:41:02 -08001391 // Add OBB Action Handler to StorageManagerService thread.
Dianne Hackborn8d044e82013-04-30 17:24:15 -07001392 mObbActionHandler = new ObbActionHandler(IoThread.get().getLooper());
Kenny Roota02b8b02010-08-05 16:14:17 -07001393
Christopher Tate7265abe2014-11-21 13:54:45 -08001394 // Initialize the last-fstrim tracking if necessary
1395 File dataDir = Environment.getDataDirectory();
1396 File systemDir = new File(dataDir, "system");
1397 mLastMaintenanceFile = new File(systemDir, LAST_FSTRIM_FILE);
1398 if (!mLastMaintenanceFile.exists()) {
1399 // Not setting mLastMaintenance here means that we will force an
1400 // fstrim during reboot following the OTA that installs this code.
1401 try {
1402 (new FileOutputStream(mLastMaintenanceFile)).close();
1403 } catch (IOException e) {
1404 Slog.e(TAG, "Unable to create fstrim record " + mLastMaintenanceFile.getPath());
1405 }
1406 } else {
1407 mLastMaintenance = mLastMaintenanceFile.lastModified();
1408 }
1409
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001410 mSettingsFile = new AtomicFile(
Dianne Hackborne17b4452018-01-10 13:15:40 -08001411 new File(Environment.getDataSystemDirectory(), "storage.xml"), "storage-settings");
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001412
1413 synchronized (mLock) {
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001414 readSettingsLocked();
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001415 }
1416
Sudheer Shanka2250d562016-11-07 15:41:02 -08001417 LocalServices.addService(StorageManagerInternal.class, mStorageManagerInternal);
Svet Ganov6ee871e2015-07-10 14:29:33 -07001418
Jeff Sharkeybcd262d2015-06-10 09:41:17 -07001419 final IntentFilter userFilter = new IntentFilter();
1420 userFilter.addAction(Intent.ACTION_USER_ADDED);
1421 userFilter.addAction(Intent.ACTION_USER_REMOVED);
1422 mContext.registerReceiver(mUserReceiver, userFilter, null, mHandler);
1423
Jeff Sharkey5a9bb742015-11-03 10:15:57 -08001424 synchronized (mLock) {
1425 addInternalVolumeLocked();
1426 }
Amith Yamasania7892482015-08-07 11:09:05 -07001427
Kenny Root07714d42011-08-17 17:49:28 -07001428 // Add ourself to the Watchdog monitors if enabled.
1429 if (WATCHDOG_ENABLE) {
1430 Watchdog.getInstance().addMonitor(this);
1431 }
San Mehat207e5382010-02-04 20:46:54 -08001432 }
1433
Jeff Sharkeycd575992016-03-29 14:12:49 -06001434 private void start() {
Jeff Sharkey1019de92017-09-06 13:47:03 -06001435 connect();
Jeff Sharkeycd575992016-03-29 14:12:49 -06001436 }
1437
Jeff Sharkey1019de92017-09-06 13:47:03 -06001438 private void connect() {
Jin Qian12690d52017-10-13 18:17:04 -07001439 IBinder binder = ServiceManager.getService("storaged");
1440 if (binder != null) {
1441 try {
1442 binder.linkToDeath(new DeathRecipient() {
1443 @Override
1444 public void binderDied() {
1445 Slog.w(TAG, "storaged died; reconnecting");
1446 mStoraged = null;
1447 connect();
1448 }
1449 }, 0);
1450 } catch (RemoteException e) {
1451 binder = null;
1452 }
1453 }
1454
1455 if (binder != null) {
1456 mStoraged = IStoraged.Stub.asInterface(binder);
1457 } else {
1458 Slog.w(TAG, "storaged not found; trying again");
1459 }
1460
1461 binder = ServiceManager.getService("vold");
Jeff Sharkey1019de92017-09-06 13:47:03 -06001462 if (binder != null) {
1463 try {
1464 binder.linkToDeath(new DeathRecipient() {
1465 @Override
1466 public void binderDied() {
1467 Slog.w(TAG, "vold died; reconnecting");
Jin Qian12690d52017-10-13 18:17:04 -07001468 mVold = null;
Jeff Sharkey1019de92017-09-06 13:47:03 -06001469 connect();
1470 }
1471 }, 0);
1472 } catch (RemoteException e) {
1473 binder = null;
1474 }
1475 }
1476
1477 if (binder != null) {
1478 mVold = IVold.Stub.asInterface(binder);
Jeff Sharkey8058fe62017-09-13 11:50:33 -06001479 try {
1480 mVold.setListener(mListener);
Jeff Sharkey8058fe62017-09-13 11:50:33 -06001481 } catch (RemoteException e) {
Jin Qian12690d52017-10-13 18:17:04 -07001482 mVold = null;
Jeff Sharkey8058fe62017-09-13 11:50:33 -06001483 Slog.w(TAG, "vold listener rejected; trying again", e);
1484 }
Jeff Sharkey1019de92017-09-06 13:47:03 -06001485 } else {
1486 Slog.w(TAG, "vold not found; trying again");
Jeff Sharkey1019de92017-09-06 13:47:03 -06001487 }
Jeff Sharkey8058fe62017-09-13 11:50:33 -06001488
Jin Qian12690d52017-10-13 18:17:04 -07001489 if (mStoraged == null || mVold == null) {
1490 BackgroundThread.getHandler().postDelayed(() -> {
1491 connect();
1492 }, DateUtils.SECOND_IN_MILLIS);
1493 } else {
1494 onDaemonConnected();
1495 }
Jeff Sharkey1019de92017-09-06 13:47:03 -06001496 }
1497
Jeff Sharkey56e62932015-03-21 20:41:00 -07001498 private void systemReady() {
Jeff Sharkey9765e442017-12-14 22:15:14 -07001499 LocalServices.getService(ActivityManagerInternal.class)
1500 .registerScreenObserver(this);
1501
Jeff Sharkeyb049e212012-09-07 23:16:01 -07001502 mSystemReady = true;
1503 mHandler.obtainMessage(H_SYSTEM_READY).sendToTarget();
1504 }
1505
Yasuhiro Matsuda87a38b52015-07-24 22:10:16 +09001506 private void bootCompleted() {
1507 mBootCompleted = true;
1508 }
1509
Jeff Sharkeyfced5342015-05-10 14:53:34 -07001510 private String getDefaultPrimaryStorageUuid() {
1511 if (SystemProperties.getBoolean(StorageManager.PROP_PRIMARY_PHYSICAL, false)) {
1512 return StorageManager.UUID_PRIMARY_PHYSICAL;
1513 } else {
1514 return StorageManager.UUID_PRIVATE_INTERNAL;
1515 }
1516 }
1517
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001518 private void readSettingsLocked() {
1519 mRecords.clear();
Jeff Sharkeyfced5342015-05-10 14:53:34 -07001520 mPrimaryStorageUuid = getDefaultPrimaryStorageUuid();
Jeff Sharkey4c099d02015-05-15 13:45:00 -07001521 mForceAdoptable = false;
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001522
1523 FileInputStream fis = null;
1524 try {
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001525 fis = mSettingsFile.openRead();
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001526 final XmlPullParser in = Xml.newPullParser();
Wojciech Staszkiewicz9e9e2e72015-05-08 14:58:46 +01001527 in.setInput(fis, StandardCharsets.UTF_8.name());
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001528
1529 int type;
1530 while ((type = in.next()) != END_DOCUMENT) {
1531 if (type == START_TAG) {
1532 final String tag = in.getName();
Jeff Sharkey620b32b2015-04-23 19:36:02 -07001533 if (TAG_VOLUMES.equals(tag)) {
1534 final int version = readIntAttribute(in, ATTR_VERSION, VERSION_INIT);
Jeff Sharkeyfced5342015-05-10 14:53:34 -07001535 final boolean primaryPhysical = SystemProperties.getBoolean(
1536 StorageManager.PROP_PRIMARY_PHYSICAL, false);
1537 final boolean validAttr = (version >= VERSION_FIX_PRIMARY)
1538 || (version >= VERSION_ADD_PRIMARY && !primaryPhysical);
1539 if (validAttr) {
Jeff Sharkey620b32b2015-04-23 19:36:02 -07001540 mPrimaryStorageUuid = readStringAttribute(in,
1541 ATTR_PRIMARY_STORAGE_UUID);
Jeff Sharkey620b32b2015-04-23 19:36:02 -07001542 }
Jeff Sharkey4c099d02015-05-15 13:45:00 -07001543 mForceAdoptable = readBooleanAttribute(in, ATTR_FORCE_ADOPTABLE, false);
Jeff Sharkey620b32b2015-04-23 19:36:02 -07001544
1545 } else if (TAG_VOLUME.equals(tag)) {
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001546 final VolumeRecord rec = readVolumeRecord(in);
1547 mRecords.put(rec.fsUuid, rec);
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001548 }
1549 }
1550 }
1551 } catch (FileNotFoundException e) {
1552 // Missing metadata is okay, probably first boot
1553 } catch (IOException e) {
1554 Slog.wtf(TAG, "Failed reading metadata", e);
1555 } catch (XmlPullParserException e) {
1556 Slog.wtf(TAG, "Failed reading metadata", e);
1557 } finally {
1558 IoUtils.closeQuietly(fis);
1559 }
1560 }
1561
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001562 private void writeSettingsLocked() {
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001563 FileOutputStream fos = null;
1564 try {
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001565 fos = mSettingsFile.startWrite();
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001566
1567 XmlSerializer out = new FastXmlSerializer();
Wojciech Staszkiewicz9e9e2e72015-05-08 14:58:46 +01001568 out.setOutput(fos, StandardCharsets.UTF_8.name());
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001569 out.startDocument(null, true);
1570 out.startTag(null, TAG_VOLUMES);
Jeff Sharkeyfced5342015-05-10 14:53:34 -07001571 writeIntAttribute(out, ATTR_VERSION, VERSION_FIX_PRIMARY);
Jeff Sharkey620b32b2015-04-23 19:36:02 -07001572 writeStringAttribute(out, ATTR_PRIMARY_STORAGE_UUID, mPrimaryStorageUuid);
Jeff Sharkey4c099d02015-05-15 13:45:00 -07001573 writeBooleanAttribute(out, ATTR_FORCE_ADOPTABLE, mForceAdoptable);
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001574 final int size = mRecords.size();
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001575 for (int i = 0; i < size; i++) {
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001576 final VolumeRecord rec = mRecords.valueAt(i);
1577 writeVolumeRecord(out, rec);
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001578 }
1579 out.endTag(null, TAG_VOLUMES);
1580 out.endDocument();
1581
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001582 mSettingsFile.finishWrite(fos);
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001583 } catch (IOException e) {
1584 if (fos != null) {
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001585 mSettingsFile.failWrite(fos);
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001586 }
1587 }
1588 }
1589
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001590 public static VolumeRecord readVolumeRecord(XmlPullParser in) throws IOException {
1591 final int type = readIntAttribute(in, ATTR_TYPE);
1592 final String fsUuid = readStringAttribute(in, ATTR_FS_UUID);
1593 final VolumeRecord meta = new VolumeRecord(type, fsUuid);
Jeff Sharkey5cc0df22015-06-17 19:44:05 -07001594 meta.partGuid = readStringAttribute(in, ATTR_PART_GUID);
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001595 meta.nickname = readStringAttribute(in, ATTR_NICKNAME);
1596 meta.userFlags = readIntAttribute(in, ATTR_USER_FLAGS);
Jeff Sharkeye8a4b662015-06-27 15:43:45 -07001597 meta.createdMillis = readLongAttribute(in, ATTR_CREATED_MILLIS);
1598 meta.lastTrimMillis = readLongAttribute(in, ATTR_LAST_TRIM_MILLIS);
1599 meta.lastBenchMillis = readLongAttribute(in, ATTR_LAST_BENCH_MILLIS);
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001600 return meta;
1601 }
1602
1603 public static void writeVolumeRecord(XmlSerializer out, VolumeRecord rec) throws IOException {
1604 out.startTag(null, TAG_VOLUME);
1605 writeIntAttribute(out, ATTR_TYPE, rec.type);
1606 writeStringAttribute(out, ATTR_FS_UUID, rec.fsUuid);
Jeff Sharkey5cc0df22015-06-17 19:44:05 -07001607 writeStringAttribute(out, ATTR_PART_GUID, rec.partGuid);
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001608 writeStringAttribute(out, ATTR_NICKNAME, rec.nickname);
1609 writeIntAttribute(out, ATTR_USER_FLAGS, rec.userFlags);
Jeff Sharkeye8a4b662015-06-27 15:43:45 -07001610 writeLongAttribute(out, ATTR_CREATED_MILLIS, rec.createdMillis);
1611 writeLongAttribute(out, ATTR_LAST_TRIM_MILLIS, rec.lastTrimMillis);
1612 writeLongAttribute(out, ATTR_LAST_BENCH_MILLIS, rec.lastBenchMillis);
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001613 out.endTag(null, TAG_VOLUME);
1614 }
1615
San Mehat207e5382010-02-04 20:46:54 -08001616 /**
San Mehat4270e1e2010-01-29 05:32:19 -08001617 * Exposed API calls below here
1618 */
1619
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001620 @Override
Sudheer Shanka2250d562016-11-07 15:41:02 -08001621 public void registerListener(IStorageEventListener listener) {
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001622 mCallbacks.register(listener);
San Mehat4270e1e2010-01-29 05:32:19 -08001623 }
1624
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001625 @Override
Sudheer Shanka2250d562016-11-07 15:41:02 -08001626 public void unregisterListener(IStorageEventListener listener) {
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001627 mCallbacks.unregister(listener);
San Mehat4270e1e2010-01-29 05:32:19 -08001628 }
1629
Jeff Sharkey48877892015-03-18 11:27:19 -07001630 @Override
Sudheer Shanka2250d562016-11-07 15:41:02 -08001631 public void shutdown(final IStorageShutdownObserver observer) {
Jeff Sharkey48877892015-03-18 11:27:19 -07001632 enforcePermission(android.Manifest.permission.SHUTDOWN);
San Mehat4270e1e2010-01-29 05:32:19 -08001633
San Mehata5078592010-03-25 09:36:54 -07001634 Slog.i(TAG, "Shutting down");
Jeff Sharkey48877892015-03-18 11:27:19 -07001635 mHandler.obtainMessage(H_SHUTDOWN, observer).sendToTarget();
San Mehat4270e1e2010-01-29 05:32:19 -08001636 }
1637
Jeff Sharkey48877892015-03-18 11:27:19 -07001638 @Override
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001639 public void mount(String volId) {
1640 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001641
Jeff Sharkeyef10ee02015-07-05 14:17:27 -07001642 final VolumeInfo vol = findVolumeByIdOrThrow(volId);
Jeff Sharkey2e606d72015-07-27 14:19:54 -07001643 if (isMountDisallowed(vol)) {
1644 throw new SecurityException("Mounting " + volId + " restricted by policy");
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001645 }
1646 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06001647 mVold.mount(vol.id, vol.mountFlags, vol.mountUserId);
Jeff Sharkeyace874b2017-09-07 15:27:33 -06001648 } catch (Exception e) {
1649 Slog.wtf(TAG, e);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001650 }
1651 }
1652
1653 @Override
1654 public void unmount(String volId) {
1655 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001656
Jeff Sharkeyef10ee02015-07-05 14:17:27 -07001657 final VolumeInfo vol = findVolumeByIdOrThrow(volId);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001658 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06001659 mVold.unmount(vol.id);
Jeff Sharkeyace874b2017-09-07 15:27:33 -06001660 } catch (Exception e) {
1661 Slog.wtf(TAG, e);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001662 }
1663 }
1664
1665 @Override
1666 public void format(String volId) {
Jeff Sharkey48877892015-03-18 11:27:19 -07001667 enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);
San Mehat5b77dab2010-01-26 13:28:50 -08001668
Jeff Sharkeyef10ee02015-07-05 14:17:27 -07001669 final VolumeInfo vol = findVolumeByIdOrThrow(volId);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001670 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06001671 mVold.format(vol.id, "auto");
Jeff Sharkeyace874b2017-09-07 15:27:33 -06001672 } catch (Exception e) {
1673 Slog.wtf(TAG, e);
Jeff Sharkey48877892015-03-18 11:27:19 -07001674 }
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001675 }
1676
1677 @Override
Jeff Sharkey7e19f532017-11-06 13:54:11 -07001678 public void benchmark(String volId, IVoldTaskListener listener) {
Jeff Sharkey9756d752015-05-14 21:07:42 -07001679 enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);
Jeff Sharkey9756d752015-05-14 21:07:42 -07001680
1681 try {
Jeff Sharkeyb302c542017-09-15 12:57:59 -06001682 mVold.benchmark(volId, new IVoldTaskListener.Stub() {
1683 @Override
1684 public void onStatus(int status, PersistableBundle extras) {
Jeff Sharkey7e19f532017-11-06 13:54:11 -07001685 dispatchOnStatus(listener, status, extras);
Jeff Sharkeyb302c542017-09-15 12:57:59 -06001686 }
1687
1688 @Override
1689 public void onFinished(int status, PersistableBundle extras) {
Jeff Sharkey7e19f532017-11-06 13:54:11 -07001690 dispatchOnFinished(listener, status, extras);
Jeff Sharkeyb302c542017-09-15 12:57:59 -06001691
1692 final String path = extras.getString("path");
1693 final String ident = extras.getString("ident");
1694 final long create = extras.getLong("create");
1695 final long run = extras.getLong("run");
1696 final long destroy = extras.getLong("destroy");
1697
1698 final DropBoxManager dropBox = mContext.getSystemService(DropBoxManager.class);
1699 dropBox.addText(TAG_STORAGE_BENCHMARK, scrubPath(path)
1700 + " " + ident + " " + create + " " + run + " " + destroy);
1701
1702 synchronized (mLock) {
1703 final VolumeRecord rec = findRecordForPath(path);
1704 if (rec != null) {
1705 rec.lastBenchMillis = System.currentTimeMillis();
1706 writeSettingsLocked();
1707 }
1708 }
1709 }
1710 });
Jeff Sharkey7e19f532017-11-06 13:54:11 -07001711 } catch (RemoteException e) {
1712 throw e.rethrowAsRuntimeException();
Jeff Sharkey9756d752015-05-14 21:07:42 -07001713 }
1714 }
1715
1716 @Override
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001717 public void partitionPublic(String diskId) {
1718 enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001719
Jeff Sharkeyeba260d2015-04-19 14:35:16 -07001720 final CountDownLatch latch = findOrCreateDiskScanLatch(diskId);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001721 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06001722 mVold.partition(diskId, IVold.PARTITION_TYPE_PUBLIC, -1);
Jeff Sharkeyedcdaf62015-07-09 09:45:36 -07001723 waitForLatch(latch, "partitionPublic", 3 * DateUtils.MINUTE_IN_MILLIS);
Jeff Sharkeyace874b2017-09-07 15:27:33 -06001724 } catch (Exception e) {
1725 Slog.wtf(TAG, e);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001726 }
1727 }
1728
1729 @Override
1730 public void partitionPrivate(String diskId) {
1731 enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);
Amith Yamasani462ac3a2015-06-30 14:21:01 -07001732 enforceAdminUser();
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001733
Jeff Sharkeyeba260d2015-04-19 14:35:16 -07001734 final CountDownLatch latch = findOrCreateDiskScanLatch(diskId);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001735 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06001736 mVold.partition(diskId, IVold.PARTITION_TYPE_PRIVATE, -1);
Jeff Sharkeyedcdaf62015-07-09 09:45:36 -07001737 waitForLatch(latch, "partitionPrivate", 3 * DateUtils.MINUTE_IN_MILLIS);
Jeff Sharkeyace874b2017-09-07 15:27:33 -06001738 } catch (Exception e) {
1739 Slog.wtf(TAG, e);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001740 }
1741 }
1742
1743 @Override
1744 public void partitionMixed(String diskId, int ratio) {
1745 enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);
Amith Yamasani462ac3a2015-06-30 14:21:01 -07001746 enforceAdminUser();
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001747
Jeff Sharkeyeba260d2015-04-19 14:35:16 -07001748 final CountDownLatch latch = findOrCreateDiskScanLatch(diskId);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001749 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06001750 mVold.partition(diskId, IVold.PARTITION_TYPE_MIXED, ratio);
Jeff Sharkeyedcdaf62015-07-09 09:45:36 -07001751 waitForLatch(latch, "partitionMixed", 3 * DateUtils.MINUTE_IN_MILLIS);
Jeff Sharkeyace874b2017-09-07 15:27:33 -06001752 } catch (Exception e) {
1753 Slog.wtf(TAG, e);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001754 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001755 }
1756
Jeff Sharkey48877892015-03-18 11:27:19 -07001757 @Override
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001758 public void setVolumeNickname(String fsUuid, String nickname) {
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001759 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001760
Jeff Sharkey50a05452015-04-29 11:24:52 -07001761 Preconditions.checkNotNull(fsUuid);
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001762 synchronized (mLock) {
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001763 final VolumeRecord rec = mRecords.get(fsUuid);
1764 rec.nickname = nickname;
Jeff Sharkey50a05452015-04-29 11:24:52 -07001765 mCallbacks.notifyVolumeRecordChanged(rec);
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001766 writeSettingsLocked();
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001767 }
1768 }
1769
1770 @Override
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001771 public void setVolumeUserFlags(String fsUuid, int flags, int mask) {
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001772 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001773
Jeff Sharkey50a05452015-04-29 11:24:52 -07001774 Preconditions.checkNotNull(fsUuid);
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001775 synchronized (mLock) {
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001776 final VolumeRecord rec = mRecords.get(fsUuid);
1777 rec.userFlags = (rec.userFlags & ~mask) | (flags & mask);
Jeff Sharkey50a05452015-04-29 11:24:52 -07001778 mCallbacks.notifyVolumeRecordChanged(rec);
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001779 writeSettingsLocked();
1780 }
1781 }
1782
1783 @Override
1784 public void forgetVolume(String fsUuid) {
1785 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001786
Jeff Sharkey50a05452015-04-29 11:24:52 -07001787 Preconditions.checkNotNull(fsUuid);
Jeff Sharkey5a9bb742015-11-03 10:15:57 -08001788
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001789 synchronized (mLock) {
Jeff Sharkey5cc0df22015-06-17 19:44:05 -07001790 final VolumeRecord rec = mRecords.remove(fsUuid);
1791 if (rec != null && !TextUtils.isEmpty(rec.partGuid)) {
Jeff Sharkeydb4b6192017-10-24 11:08:50 -06001792 mHandler.obtainMessage(H_PARTITION_FORGET, rec).sendToTarget();
Jeff Sharkey5cc0df22015-06-17 19:44:05 -07001793 }
1794 mCallbacks.notifyVolumeForgotten(fsUuid);
Jeff Sharkey50a05452015-04-29 11:24:52 -07001795
1796 // If this had been primary storage, revert back to internal and
1797 // reset vold so we bind into new volume into place.
1798 if (Objects.equals(mPrimaryStorageUuid, fsUuid)) {
Jeff Sharkeyfced5342015-05-10 14:53:34 -07001799 mPrimaryStorageUuid = getDefaultPrimaryStorageUuid();
Jeff Sharkey5a9bb742015-11-03 10:15:57 -08001800 mHandler.obtainMessage(H_RESET).sendToTarget();
Jeff Sharkey50a05452015-04-29 11:24:52 -07001801 }
1802
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001803 writeSettingsLocked();
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001804 }
1805 }
1806
Jeff Sharkey7d2af542015-05-12 15:27:15 -07001807 @Override
1808 public void forgetAllVolumes() {
1809 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
Jeff Sharkey7d2af542015-05-12 15:27:15 -07001810
Jeff Sharkey50a05452015-04-29 11:24:52 -07001811 synchronized (mLock) {
1812 for (int i = 0; i < mRecords.size(); i++) {
1813 final String fsUuid = mRecords.keyAt(i);
Jeff Sharkey5cc0df22015-06-17 19:44:05 -07001814 final VolumeRecord rec = mRecords.valueAt(i);
1815 if (!TextUtils.isEmpty(rec.partGuid)) {
Jeff Sharkeydb4b6192017-10-24 11:08:50 -06001816 mHandler.obtainMessage(H_PARTITION_FORGET, rec).sendToTarget();
Jeff Sharkey5cc0df22015-06-17 19:44:05 -07001817 }
Jeff Sharkey50a05452015-04-29 11:24:52 -07001818 mCallbacks.notifyVolumeForgotten(fsUuid);
1819 }
Jeff Sharkey50a05452015-04-29 11:24:52 -07001820 mRecords.clear();
Jeff Sharkey50a05452015-04-29 11:24:52 -07001821
Jeff Sharkeyfced5342015-05-10 14:53:34 -07001822 if (!Objects.equals(StorageManager.UUID_PRIVATE_INTERNAL, mPrimaryStorageUuid)) {
1823 mPrimaryStorageUuid = getDefaultPrimaryStorageUuid();
1824 }
1825
1826 writeSettingsLocked();
Jeff Sharkey5a9bb742015-11-03 10:15:57 -08001827 mHandler.obtainMessage(H_RESET).sendToTarget();
Jeff Sharkey50a05452015-04-29 11:24:52 -07001828 }
1829 }
1830
Jeff Sharkeydb4b6192017-10-24 11:08:50 -06001831 private void forgetPartition(String partGuid, String fsUuid) {
Jeff Sharkey5cc0df22015-06-17 19:44:05 -07001832 try {
Jeff Sharkeydb4b6192017-10-24 11:08:50 -06001833 mVold.forgetPartition(partGuid, fsUuid);
Jeff Sharkeyace874b2017-09-07 15:27:33 -06001834 } catch (Exception e) {
1835 Slog.wtf(TAG, e);
Jeff Sharkey5cc0df22015-06-17 19:44:05 -07001836 }
1837 }
1838
Jeff Sharkey31d0b702016-11-21 14:16:53 -07001839 @Override
Jeff Sharkey7e19f532017-11-06 13:54:11 -07001840 public void fstrim(int flags, IVoldTaskListener listener) {
Jeff Sharkey31d0b702016-11-21 14:16:53 -07001841 enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);
Jeff Sharkey31d0b702016-11-21 14:16:53 -07001842
1843 try {
Jeff Sharkeyb302c542017-09-15 12:57:59 -06001844 mVold.fstrim(flags, new IVoldTaskListener.Stub() {
1845 @Override
1846 public void onStatus(int status, PersistableBundle extras) {
Jeff Sharkey7e19f532017-11-06 13:54:11 -07001847 dispatchOnStatus(listener, status, extras);
1848
Jeff Sharkeyb302c542017-09-15 12:57:59 -06001849 // Ignore trim failures
1850 if (status != 0) return;
1851
1852 final String path = extras.getString("path");
1853 final long bytes = extras.getLong("bytes");
1854 final long time = extras.getLong("time");
1855
1856 final DropBoxManager dropBox = mContext.getSystemService(DropBoxManager.class);
1857 dropBox.addText(TAG_STORAGE_TRIM, scrubPath(path) + " " + bytes + " " + time);
1858
1859 synchronized (mLock) {
1860 final VolumeRecord rec = findRecordForPath(path);
1861 if (rec != null) {
1862 rec.lastTrimMillis = System.currentTimeMillis();
1863 writeSettingsLocked();
1864 }
1865 }
1866 }
1867
1868 @Override
1869 public void onFinished(int status, PersistableBundle extras) {
Jeff Sharkey7e19f532017-11-06 13:54:11 -07001870 dispatchOnFinished(listener, status, extras);
1871
Jeff Sharkeyb302c542017-09-15 12:57:59 -06001872 // TODO: benchmark when desired
1873 }
1874 });
Jeff Sharkey7e19f532017-11-06 13:54:11 -07001875 } catch (RemoteException e) {
1876 throw e.rethrowAsRuntimeException();
Jeff Sharkey31d0b702016-11-21 14:16:53 -07001877 }
1878 }
1879
Jin Qiana85b9912017-10-17 15:48:18 -07001880 void runIdleMaint(Runnable callback) {
1881 enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);
1882
1883 try {
1884 mVold.runIdleMaint(new IVoldTaskListener.Stub() {
1885 @Override
1886 public void onStatus(int status, PersistableBundle extras) {
1887 // Not currently used
1888 }
1889 @Override
1890 public void onFinished(int status, PersistableBundle extras) {
1891 if (callback != null) {
1892 BackgroundThread.getHandler().post(callback);
1893 }
1894 }
1895 });
1896 } catch (Exception e) {
1897 Slog.wtf(TAG, e);
1898 }
1899 }
1900
1901 @Override
1902 public void runIdleMaintenance() {
1903 runIdleMaint(null);
1904 }
1905
1906 void abortIdleMaint(Runnable callback) {
1907 enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);
1908
1909 try {
1910 mVold.abortIdleMaint(new IVoldTaskListener.Stub() {
1911 @Override
1912 public void onStatus(int status, PersistableBundle extras) {
1913 // Not currently used
1914 }
1915 @Override
1916 public void onFinished(int status, PersistableBundle extras) {
1917 if (callback != null) {
1918 BackgroundThread.getHandler().post(callback);
1919 }
1920 }
1921 });
1922 } catch (Exception e) {
1923 Slog.wtf(TAG, e);
1924 }
1925 }
1926
1927 @Override
1928 public void abortIdleMaintenance() {
1929 abortIdleMaint(null);
1930 }
1931
Svet Ganov6ee871e2015-07-10 14:29:33 -07001932 private void remountUidExternalStorage(int uid, int mode) {
Jeff Sharkey9527b222015-06-24 15:24:48 -07001933 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06001934 mVold.remountUid(uid, mode);
Jeff Sharkeyace874b2017-09-07 15:27:33 -06001935 } catch (Exception e) {
1936 Slog.wtf(TAG, e);
Jeff Sharkey9527b222015-06-24 15:24:48 -07001937 }
1938 }
1939
1940 @Override
Jeff Sharkey4c099d02015-05-15 13:45:00 -07001941 public void setDebugFlags(int flags, int mask) {
1942 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
Jeff Sharkey4c099d02015-05-15 13:45:00 -07001943
Jeff Sharkeyba512352015-11-12 20:17:45 -08001944 if ((mask & StorageManager.DEBUG_EMULATE_FBE) != 0) {
Jeff Sharkey00455bf2016-11-04 14:45:24 -06001945 if (!EMULATE_FBE_SUPPORTED) {
1946 throw new IllegalStateException(
1947 "Emulation not supported on this device");
1948 }
Paul Lawrence20be5d62016-02-26 13:51:17 -08001949 if (StorageManager.isFileEncryptedNativeOnly()) {
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07001950 throw new IllegalStateException(
Jeff Sharkey00455bf2016-11-04 14:45:24 -06001951 "Emulation not supported on device with native FBE");
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07001952 }
Jeff Sharkey5a785162016-03-21 13:02:06 -06001953 if (mLockPatternUtils.isCredentialRequiredToDecrypt(false)) {
1954 throw new IllegalStateException(
1955 "Emulation requires disabling 'Secure start-up' in Settings > Security");
1956 }
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07001957
Jeff Sharkey1176e512016-02-29 17:01:26 -07001958 final long token = Binder.clearCallingIdentity();
1959 try {
1960 final boolean emulateFbe = (flags & StorageManager.DEBUG_EMULATE_FBE) != 0;
1961 SystemProperties.set(StorageManager.PROP_EMULATE_FBE, Boolean.toString(emulateFbe));
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07001962
Jeff Sharkey1176e512016-02-29 17:01:26 -07001963 // Perform hard reboot to kick policy into place
1964 mContext.getSystemService(PowerManager.class).reboot(null);
1965 } finally {
1966 Binder.restoreCallingIdentity(token);
1967 }
Jeff Sharkeyba512352015-11-12 20:17:45 -08001968 }
Jeff Sharkey4c099d02015-05-15 13:45:00 -07001969
Jeff Sharkeyba512352015-11-12 20:17:45 -08001970 if ((mask & StorageManager.DEBUG_FORCE_ADOPTABLE) != 0) {
1971 synchronized (mLock) {
1972 mForceAdoptable = (flags & StorageManager.DEBUG_FORCE_ADOPTABLE) != 0;
1973
1974 writeSettingsLocked();
1975 mHandler.obtainMessage(H_RESET).sendToTarget();
1976 }
Jeff Sharkey4c099d02015-05-15 13:45:00 -07001977 }
Jeff Sharkey33dd1562016-04-07 11:05:33 -06001978
1979 if ((mask & (StorageManager.DEBUG_SDCARDFS_FORCE_ON
1980 | StorageManager.DEBUG_SDCARDFS_FORCE_OFF)) != 0) {
1981 final String value;
1982 if ((flags & StorageManager.DEBUG_SDCARDFS_FORCE_ON) != 0) {
1983 value = "force_on";
1984 } else if ((flags & StorageManager.DEBUG_SDCARDFS_FORCE_OFF) != 0) {
1985 value = "force_off";
1986 } else {
1987 value = "";
1988 }
1989
1990 final long token = Binder.clearCallingIdentity();
1991 try {
1992 SystemProperties.set(StorageManager.PROP_SDCARDFS, value);
1993
1994 // Reset storage to kick new setting into place
1995 mHandler.obtainMessage(H_RESET).sendToTarget();
1996 } finally {
1997 Binder.restoreCallingIdentity(token);
1998 }
1999 }
Jeff Sharkeye53e2d92017-03-25 23:14:06 -06002000
2001 if ((mask & StorageManager.DEBUG_VIRTUAL_DISK) != 0) {
2002 final boolean enabled = (flags & StorageManager.DEBUG_VIRTUAL_DISK) != 0;
2003
2004 final long token = Binder.clearCallingIdentity();
2005 try {
2006 SystemProperties.set(StorageManager.PROP_VIRTUAL_DISK, Boolean.toString(enabled));
2007
2008 // Reset storage to kick new setting into place
2009 mHandler.obtainMessage(H_RESET).sendToTarget();
2010 } finally {
2011 Binder.restoreCallingIdentity(token);
2012 }
2013 }
Jeff Sharkey4c099d02015-05-15 13:45:00 -07002014 }
2015
2016 @Override
Jeff Sharkey275e3e42015-04-24 16:10:32 -07002017 public String getPrimaryStorageUuid() {
Jeff Sharkey620b32b2015-04-23 19:36:02 -07002018 synchronized (mLock) {
2019 return mPrimaryStorageUuid;
2020 }
2021 }
2022
2023 @Override
Jeff Sharkey275e3e42015-04-24 16:10:32 -07002024 public void setPrimaryStorageUuid(String volumeUuid, IPackageMoveObserver callback) {
2025 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
Jeff Sharkey620b32b2015-04-23 19:36:02 -07002026
Jeff Sharkeya31460c2016-06-22 09:04:33 -06002027 final VolumeInfo from;
2028 final VolumeInfo to;
2029
Jeff Sharkey275e3e42015-04-24 16:10:32 -07002030 synchronized (mLock) {
Jeff Sharkeyfced5342015-05-10 14:53:34 -07002031 if (Objects.equals(mPrimaryStorageUuid, volumeUuid)) {
2032 throw new IllegalArgumentException("Primary storage already at " + volumeUuid);
Jeff Sharkey275e3e42015-04-24 16:10:32 -07002033 }
2034
2035 if (mMoveCallback != null) {
2036 throw new IllegalStateException("Move already in progress");
2037 }
2038 mMoveCallback = callback;
2039 mMoveTargetUuid = volumeUuid;
2040
Jeff Sharkeya65e6492017-06-21 13:45:11 -06002041 // We need all the users unlocked to move their primary storage
2042 final List<UserInfo> users = mContext.getSystemService(UserManager.class).getUsers();
2043 for (UserInfo user : users) {
2044 if (StorageManager.isFileEncryptedNativeOrEmulated()
2045 && !isUserKeyUnlocked(user.id)) {
2046 Slog.w(TAG, "Failing move due to locked user " + user.id);
2047 onMoveStatusLocked(PackageManager.MOVE_FAILED_LOCKED_USER);
2048 return;
2049 }
2050 }
2051
Jeff Sharkeyfced5342015-05-10 14:53:34 -07002052 // When moving to/from primary physical volume, we probably just nuked
2053 // the current storage location, so we have nothing to move.
2054 if (Objects.equals(StorageManager.UUID_PRIMARY_PHYSICAL, mPrimaryStorageUuid)
2055 || Objects.equals(StorageManager.UUID_PRIMARY_PHYSICAL, volumeUuid)) {
2056 Slog.d(TAG, "Skipping move to/from primary physical");
2057 onMoveStatusLocked(MOVE_STATUS_COPY_FINISHED);
2058 onMoveStatusLocked(PackageManager.MOVE_SUCCEEDED);
Jeff Sharkey5a9bb742015-11-03 10:15:57 -08002059 mHandler.obtainMessage(H_RESET).sendToTarget();
Jeff Sharkeya31460c2016-06-22 09:04:33 -06002060 return;
Jeff Sharkeyfced5342015-05-10 14:53:34 -07002061
2062 } else {
Jeff Sharkeya31460c2016-06-22 09:04:33 -06002063 from = findStorageForUuid(mPrimaryStorageUuid);
2064 to = findStorageForUuid(volumeUuid);
Jeff Sharkeyef10ee02015-07-05 14:17:27 -07002065
2066 if (from == null) {
2067 Slog.w(TAG, "Failing move due to missing from volume " + mPrimaryStorageUuid);
2068 onMoveStatusLocked(PackageManager.MOVE_FAILED_INTERNAL_ERROR);
2069 return;
2070 } else if (to == null) {
2071 Slog.w(TAG, "Failing move due to missing to volume " + volumeUuid);
2072 onMoveStatusLocked(PackageManager.MOVE_FAILED_INTERNAL_ERROR);
2073 return;
2074 }
Jeff Sharkey275e3e42015-04-24 16:10:32 -07002075 }
Jeff Sharkey620b32b2015-04-23 19:36:02 -07002076 }
Jeff Sharkeya31460c2016-06-22 09:04:33 -06002077
2078 try {
Jeff Sharkeyb302c542017-09-15 12:57:59 -06002079 mVold.moveStorage(from.id, to.id, new IVoldTaskListener.Stub() {
2080 @Override
2081 public void onStatus(int status, PersistableBundle extras) {
2082 synchronized (mLock) {
2083 onMoveStatusLocked(status);
2084 }
2085 }
2086
2087 @Override
2088 public void onFinished(int status, PersistableBundle extras) {
2089 // Not currently used
2090 }
2091 });
Jeff Sharkeyace874b2017-09-07 15:27:33 -06002092 } catch (Exception e) {
2093 Slog.wtf(TAG, e);
Jeff Sharkeya31460c2016-06-22 09:04:33 -06002094 }
Jeff Sharkey620b32b2015-04-23 19:36:02 -07002095 }
2096
San Mehatb1043402010-02-05 08:26:50 -08002097 private void warnOnNotMounted() {
Jeff Sharkey48877892015-03-18 11:27:19 -07002098 synchronized (mLock) {
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07002099 for (int i = 0; i < mVolumes.size(); i++) {
2100 final VolumeInfo vol = mVolumes.valueAt(i);
Jeff Sharkey27de30d2015-04-18 16:20:27 -07002101 if (vol.isPrimary() && vol.isMountedWritable()) {
Jeff Sharkey48877892015-03-18 11:27:19 -07002102 // Cool beans, we have a mounted primary volume
2103 return;
2104 }
Jeff Sharkey32ee8312012-09-30 13:21:31 -07002105 }
San Mehatb1043402010-02-05 08:26:50 -08002106 }
Jeff Sharkey48877892015-03-18 11:27:19 -07002107
2108 Slog.w(TAG, "No primary storage mounted!");
San Mehatb1043402010-02-05 08:26:50 -08002109 }
2110
Kenny Roota02b8b02010-08-05 16:14:17 -07002111 private boolean isUidOwnerOfPackageOrSystem(String packageName, int callerUid) {
2112 if (callerUid == android.os.Process.SYSTEM_UID) {
2113 return true;
2114 }
2115
Kenny Root02c87302010-07-01 08:10:18 -07002116 if (packageName == null) {
2117 return false;
2118 }
2119
Jeff Sharkeycd654482016-01-08 17:42:11 -07002120 final int packageUid = mPms.getPackageUid(packageName,
2121 PackageManager.MATCH_DEBUG_TRIAGED_MISSING, UserHandle.getUserId(callerUid));
Kenny Root02c87302010-07-01 08:10:18 -07002122
2123 if (DEBUG_OBB) {
2124 Slog.d(TAG, "packageName = " + packageName + ", packageUid = " +
2125 packageUid + ", callerUid = " + callerUid);
2126 }
2127
2128 return callerUid == packageUid;
2129 }
2130
Jeff Sharkey54402792017-09-15 16:05:19 -06002131 @Override
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002132 public String getMountedObbPath(String rawPath) {
2133 Preconditions.checkNotNull(rawPath, "rawPath cannot be null");
Kenny Rootaf9d6672010-10-08 09:21:39 -07002134
Kenny Root02c87302010-07-01 08:10:18 -07002135 warnOnNotMounted();
2136
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002137 final ObbState state;
Rubin Xucd7a0142015-04-17 23:45:27 +01002138 synchronized (mObbMounts) {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002139 state = mObbPathToStateMap.get(rawPath);
2140 }
2141 if (state == null) {
2142 Slog.w(TAG, "Failed to find OBB mounted at " + rawPath);
2143 return null;
2144 }
2145
Jeff Sharkey54402792017-09-15 16:05:19 -06002146 return findVolumeByIdOrThrow(state.volId).getPath().getAbsolutePath();
Kenny Root02c87302010-07-01 08:10:18 -07002147 }
2148
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002149 @Override
2150 public boolean isObbMounted(String rawPath) {
2151 Preconditions.checkNotNull(rawPath, "rawPath cannot be null");
Kenny Rootaf9d6672010-10-08 09:21:39 -07002152 synchronized (mObbMounts) {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002153 return mObbPathToStateMap.containsKey(rawPath);
Kenny Rootaf9d6672010-10-08 09:21:39 -07002154 }
Kenny Root02c87302010-07-01 08:10:18 -07002155 }
2156
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002157 @Override
2158 public void mountObb(
2159 String rawPath, String canonicalPath, String key, IObbActionListener token, int nonce) {
2160 Preconditions.checkNotNull(rawPath, "rawPath cannot be null");
2161 Preconditions.checkNotNull(canonicalPath, "canonicalPath cannot be null");
2162 Preconditions.checkNotNull(token, "token cannot be null");
Kenny Rootaf9d6672010-10-08 09:21:39 -07002163
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002164 final int callingUid = Binder.getCallingUid();
Jeff Sharkey41cd6812017-09-11 10:32:17 -06002165 final ObbState obbState = new ObbState(rawPath, canonicalPath,
2166 callingUid, token, nonce, null);
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002167 final ObbAction action = new MountObbAction(obbState, key, callingUid);
Kenny Roota02b8b02010-08-05 16:14:17 -07002168 mObbActionHandler.sendMessage(mObbActionHandler.obtainMessage(OBB_RUN_ACTION, action));
2169
2170 if (DEBUG_OBB)
2171 Slog.i(TAG, "Send to OBB handler: " + action.toString());
Kenny Root02c87302010-07-01 08:10:18 -07002172 }
2173
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002174 @Override
2175 public void unmountObb(String rawPath, boolean force, IObbActionListener token, int nonce) {
2176 Preconditions.checkNotNull(rawPath, "rawPath cannot be null");
2177
2178 final ObbState existingState;
Rubin Xucd7a0142015-04-17 23:45:27 +01002179 synchronized (mObbMounts) {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002180 existingState = mObbPathToStateMap.get(rawPath);
Kenny Rootf1121dc2010-09-29 07:30:53 -07002181 }
2182
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002183 if (existingState != null) {
2184 // TODO: separate state object from request data
2185 final int callingUid = Binder.getCallingUid();
Jeff Sharkey41cd6812017-09-11 10:32:17 -06002186 final ObbState newState = new ObbState(rawPath, existingState.canonicalPath,
2187 callingUid, token, nonce, existingState.volId);
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002188 final ObbAction action = new UnmountObbAction(newState, force);
2189 mObbActionHandler.sendMessage(mObbActionHandler.obtainMessage(OBB_RUN_ACTION, action));
Kenny Root02c87302010-07-01 08:10:18 -07002190
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002191 if (DEBUG_OBB)
2192 Slog.i(TAG, "Send to OBB handler: " + action.toString());
2193 } else {
2194 Slog.w(TAG, "Unknown OBB mount at " + rawPath);
2195 }
Kenny Roota02b8b02010-08-05 16:14:17 -07002196 }
2197
Ben Komalo444eca22011-09-01 15:17:44 -07002198 @Override
2199 public int getEncryptionState() {
2200 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
2201 "no permission to access the crypt keeper");
2202
Ben Komalo444eca22011-09-01 15:17:44 -07002203 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002204 return mVold.fdeComplete();
2205 } catch (Exception e) {
2206 Slog.wtf(TAG, e);
Sudheer Shankaf7341142016-10-18 17:15:18 -07002207 return StorageManager.ENCRYPTION_STATE_ERROR_UNKNOWN;
Ben Komalo444eca22011-09-01 15:17:44 -07002208 }
2209 }
2210
2211 @Override
Jason parks5af0b912010-11-29 09:05:25 -06002212 public int decryptStorage(String password) {
Jason parks8888c592011-01-20 22:46:41 -06002213 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
2214 "no permission to access the crypt keeper");
Jason parks5af0b912010-11-29 09:05:25 -06002215
Jeff Sharkey8058fe62017-09-13 11:50:33 -06002216 if (TextUtils.isEmpty(password)) {
2217 throw new IllegalArgumentException("password cannot be empty");
2218 }
2219
Jason parks5af0b912010-11-29 09:05:25 -06002220 if (DEBUG_EVENTS) {
2221 Slog.i(TAG, "decrypting storage...");
2222 }
2223
2224 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002225 mVold.fdeCheckPassword(password);
2226 mHandler.postDelayed(() -> {
2227 try {
2228 mVold.fdeRestart();
2229 } catch (Exception e) {
2230 Slog.wtf(TAG, e);
2231 }
2232 }, DateUtils.SECOND_IN_MILLIS);
2233 return 0;
2234 } catch (Exception e) {
2235 Slog.wtf(TAG, e);
2236 return StorageManager.ENCRYPTION_STATE_ERROR_UNKNOWN;
Jason parks5af0b912010-11-29 09:05:25 -06002237 }
Jason parks5af0b912010-11-29 09:05:25 -06002238 }
2239
Jeff Sharkey54402792017-09-15 16:05:19 -06002240 @Override
Paul Lawrence46791e72014-04-03 09:10:26 -07002241 public int encryptStorage(int type, String password) {
Jason parks8888c592011-01-20 22:46:41 -06002242 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
2243 "no permission to access the crypt keeper");
Jason parks56aa5322011-01-07 09:01:15 -06002244
Jeff Sharkey8058fe62017-09-13 11:50:33 -06002245 if (type == StorageManager.CRYPT_TYPE_DEFAULT) {
2246 password = "";
2247 } else if (TextUtils.isEmpty(password)) {
2248 throw new IllegalArgumentException("password cannot be empty");
2249 }
2250
Jason parks56aa5322011-01-07 09:01:15 -06002251 if (DEBUG_EVENTS) {
Jason parks8888c592011-01-20 22:46:41 -06002252 Slog.i(TAG, "encrypting storage...");
Jason parks56aa5322011-01-07 09:01:15 -06002253 }
2254
2255 try {
Paul Lawrence89a0ae42017-12-22 10:11:10 -08002256 mVold.fdeEnable(type, password, 0);
Jeff Sharkey43e12112017-09-12 16:31:45 -06002257 } catch (Exception e) {
2258 Slog.wtf(TAG, e);
2259 return -1;
Jason parks56aa5322011-01-07 09:01:15 -06002260 }
2261
2262 return 0;
2263 }
2264
Paul Lawrence8e397362014-01-27 15:22:30 -08002265 /** Set the password for encrypting the master key.
2266 * @param type One of the CRYPTO_TYPE_XXX consts defined in StorageManager.
2267 * @param password The password to set.
2268 */
Jeff Sharkey54402792017-09-15 16:05:19 -06002269 @Override
Paul Lawrence8e397362014-01-27 15:22:30 -08002270 public int changeEncryptionPassword(int type, String password) {
Jason parksf7b3cd42011-01-27 09:28:25 -06002271 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
2272 "no permission to access the crypt keeper");
2273
Jeff Sharkeyae266462017-11-27 13:32:24 -07002274 if (StorageManager.isFileEncryptedNativeOnly()) {
2275 // Not supported on FBE devices
2276 return -1;
2277 }
2278
Jeff Sharkey8058fe62017-09-13 11:50:33 -06002279 if (type == StorageManager.CRYPT_TYPE_DEFAULT) {
2280 password = "";
2281 } else if (TextUtils.isEmpty(password)) {
2282 throw new IllegalArgumentException("password cannot be empty");
2283 }
2284
Jason parksf7b3cd42011-01-27 09:28:25 -06002285 if (DEBUG_EVENTS) {
2286 Slog.i(TAG, "changing encryption password...");
2287 }
2288
2289 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002290 mVold.fdeChangePassword(type, password);
2291 return 0;
2292 } catch (Exception e) {
2293 Slog.wtf(TAG, e);
2294 return -1;
Jason parksf7b3cd42011-01-27 09:28:25 -06002295 }
2296 }
2297
Christopher Tate32418be2011-10-10 13:51:12 -07002298 /**
2299 * Validate a user-supplied password string with cryptfs
2300 */
2301 @Override
2302 public int verifyEncryptionPassword(String password) throws RemoteException {
2303 // Only the system process is permitted to validate passwords
2304 if (Binder.getCallingUid() != android.os.Process.SYSTEM_UID) {
2305 throw new SecurityException("no permission to access the crypt keeper");
2306 }
2307
2308 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
2309 "no permission to access the crypt keeper");
2310
2311 if (TextUtils.isEmpty(password)) {
2312 throw new IllegalArgumentException("password cannot be empty");
2313 }
2314
Christopher Tate32418be2011-10-10 13:51:12 -07002315 if (DEBUG_EVENTS) {
2316 Slog.i(TAG, "validating encryption password...");
2317 }
2318
2319 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002320 mVold.fdeVerifyPassword(password);
2321 return 0;
2322 } catch (Exception e) {
2323 Slog.wtf(TAG, e);
2324 return -1;
Christopher Tate32418be2011-10-10 13:51:12 -07002325 }
2326 }
2327
Paul Lawrence8e397362014-01-27 15:22:30 -08002328 /**
2329 * Get the type of encryption used to encrypt the master key.
2330 * @return The type, one of the CRYPT_TYPE_XXX consts from StorageManager.
2331 */
2332 @Override
Svetoslav16e4a1a2014-09-29 18:16:20 -07002333 public int getPasswordType() {
Paul Lawrence76a40572017-03-15 11:08:04 -07002334 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
Paul Lawrence9de713d2016-05-02 22:45:33 +00002335 "no permission to access the crypt keeper");
2336
Paul Lawrence8e397362014-01-27 15:22:30 -08002337 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002338 return mVold.fdeGetPasswordType();
2339 } catch (Exception e) {
2340 Slog.wtf(TAG, e);
2341 return -1;
Paul Lawrence8e397362014-01-27 15:22:30 -08002342 }
2343 }
2344
Paul Lawrencee51dcf92014-03-18 10:56:00 -07002345 /**
2346 * Set a field in the crypto header.
2347 * @param field field to set
2348 * @param contents contents to set in field
2349 */
2350 @Override
2351 public void setField(String field, String contents) throws RemoteException {
Paul Lawrence76a40572017-03-15 11:08:04 -07002352 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
Paul Lawrence0bbd1082016-04-26 15:21:02 -07002353 "no permission to access the crypt keeper");
Paul Lawrencee51dcf92014-03-18 10:56:00 -07002354
Jeff Sharkeyae266462017-11-27 13:32:24 -07002355 if (StorageManager.isFileEncryptedNativeOnly()) {
2356 // Not supported on FBE devices
2357 return;
2358 }
2359
Paul Lawrencee51dcf92014-03-18 10:56:00 -07002360 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002361 mVold.fdeSetField(field, contents);
2362 return;
2363 } catch (Exception e) {
2364 Slog.wtf(TAG, e);
2365 return;
Paul Lawrencee51dcf92014-03-18 10:56:00 -07002366 }
2367 }
2368
2369 /**
2370 * Gets a field from the crypto header.
2371 * @param field field to get
2372 * @return contents of field
2373 */
2374 @Override
2375 public String getField(String field) throws RemoteException {
Paul Lawrence76a40572017-03-15 11:08:04 -07002376 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
Paul Lawrence0bbd1082016-04-26 15:21:02 -07002377 "no permission to access the crypt keeper");
Paul Lawrencee51dcf92014-03-18 10:56:00 -07002378
Jeff Sharkeyae266462017-11-27 13:32:24 -07002379 if (StorageManager.isFileEncryptedNativeOnly()) {
2380 // Not supported on FBE devices
2381 return null;
2382 }
2383
Paul Lawrencee51dcf92014-03-18 10:56:00 -07002384 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002385 return mVold.fdeGetField(field);
2386 } catch (Exception e) {
2387 Slog.wtf(TAG, e);
2388 return null;
Paul Lawrencee51dcf92014-03-18 10:56:00 -07002389 }
2390 }
2391
Paul Lawrence3806d9c2015-10-29 10:30:46 -07002392 /**
2393 * Is userdata convertible to file based encryption?
2394 * @return non zero for convertible
2395 */
2396 @Override
2397 public boolean isConvertibleToFBE() throws RemoteException {
Paul Lawrence76a40572017-03-15 11:08:04 -07002398 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
Paul Lawrence0bbd1082016-04-26 15:21:02 -07002399 "no permission to access the crypt keeper");
Paul Lawrence3806d9c2015-10-29 10:30:46 -07002400
Paul Lawrence3806d9c2015-10-29 10:30:46 -07002401 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002402 return mVold.isConvertibleToFbe();
2403 } catch (Exception e) {
2404 Slog.wtf(TAG, e);
2405 return false;
Paul Lawrence3806d9c2015-10-29 10:30:46 -07002406 }
2407 }
2408
Jeff Sharkeyb049e212012-09-07 23:16:01 -07002409 @Override
Paul Lawrence945490c2014-03-27 16:37:28 +00002410 public String getPassword() throws RemoteException {
Paul Lawrence76a40572017-03-15 11:08:04 -07002411 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
Rubin Xucd7a0142015-04-17 23:45:27 +01002412 "only keyguard can retrieve password");
Paul Lawrence0bbd1082016-04-26 15:21:02 -07002413
Paul Lawrence945490c2014-03-27 16:37:28 +00002414 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002415 return mVold.fdeGetPassword();
2416 } catch (Exception e) {
2417 Slog.wtf(TAG, e);
Paul Lawrence24063b52015-01-06 13:11:23 -08002418 return null;
Paul Lawrence945490c2014-03-27 16:37:28 +00002419 }
2420 }
2421
2422 @Override
2423 public void clearPassword() throws RemoteException {
Paul Lawrence76a40572017-03-15 11:08:04 -07002424 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
Paul Lawrence0bbd1082016-04-26 15:21:02 -07002425 "only keyguard can clear password");
2426
Paul Lawrence945490c2014-03-27 16:37:28 +00002427 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002428 mVold.fdeClearPassword();
2429 return;
2430 } catch (Exception e) {
2431 Slog.wtf(TAG, e);
2432 return;
Paul Lawrence945490c2014-03-27 16:37:28 +00002433 }
2434 }
2435
2436 @Override
Lenka Trochtovac4dd0212015-11-18 12:22:06 +01002437 public void createUserKey(int userId, int serialNumber, boolean ephemeral) {
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002438 enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
Paul Crowleybcf48ed2015-04-22 13:36:59 +01002439
Paul Crowleybcf48ed2015-04-22 13:36:59 +01002440 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002441 mVold.createUserKey(userId, serialNumber, ephemeral);
Jeff Sharkey43e12112017-09-12 16:31:45 -06002442 } catch (Exception e) {
2443 Slog.wtf(TAG, e);
Paul Crowleybcf48ed2015-04-22 13:36:59 +01002444 }
2445 }
2446
Paul Crowley7ec733f2015-05-19 12:42:00 +01002447 @Override
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002448 public void destroyUserKey(int userId) {
2449 enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
Paul Crowley7ec733f2015-05-19 12:42:00 +01002450
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002451 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002452 mVold.destroyUserKey(userId);
Jeff Sharkey43e12112017-09-12 16:31:45 -06002453 } catch (Exception e) {
2454 Slog.wtf(TAG, e);
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002455 }
2456 }
2457
Jeff Sharkey43e12112017-09-12 16:31:45 -06002458 private String encodeBytes(byte[] bytes) {
Paul Crowleyfaeb3eb2016-02-08 15:58:29 +00002459 if (ArrayUtils.isEmpty(bytes)) {
Jeff Sharkey43e12112017-09-12 16:31:45 -06002460 return "!";
Paul Crowleyfaeb3eb2016-02-08 15:58:29 +00002461 } else {
Jeff Sharkey43e12112017-09-12 16:31:45 -06002462 return HexDump.toHexString(bytes);
Paul Crowleyfaeb3eb2016-02-08 15:58:29 +00002463 }
2464 }
2465
Paul Crowleycc701552016-05-17 14:18:49 -07002466 /*
2467 * Add this token/secret pair to the set of ways we can recover a disk encryption key.
2468 * Changing the token/secret for a disk encryption key is done in two phases: first, adding
2469 * a new token/secret pair with this call, then delting all other pairs with
2470 * fixateNewestUserKeyAuth. This allows other places where a credential is used, such as
2471 * Gatekeeper, to be updated between the two calls.
2472 */
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002473 @Override
Paul Crowleycc701552016-05-17 14:18:49 -07002474 public void addUserKeyAuth(int userId, int serialNumber, byte[] token, byte[] secret) {
Paul Crowleyfaeb3eb2016-02-08 15:58:29 +00002475 enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
Paul Crowleyfaeb3eb2016-02-08 15:58:29 +00002476
2477 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002478 mVold.addUserKeyAuth(userId, serialNumber, encodeBytes(token), encodeBytes(secret));
Jeff Sharkey43e12112017-09-12 16:31:45 -06002479 } catch (Exception e) {
2480 Slog.wtf(TAG, e);
Paul Crowleycc701552016-05-17 14:18:49 -07002481 }
2482 }
2483
2484 /*
2485 * Delete all disk encryption token/secret pairs except the most recently added one
2486 */
2487 @Override
2488 public void fixateNewestUserKeyAuth(int userId) {
2489 enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
Paul Crowleycc701552016-05-17 14:18:49 -07002490
2491 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002492 mVold.fixateNewestUserKeyAuth(userId);
Jeff Sharkey43e12112017-09-12 16:31:45 -06002493 } catch (Exception e) {
2494 Slog.wtf(TAG, e);
Paul Crowleyfaeb3eb2016-02-08 15:58:29 +00002495 }
2496 }
2497
2498 @Override
2499 public void unlockUserKey(int userId, int serialNumber, byte[] token, byte[] secret) {
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002500 enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002501
Jeff Sharkeyce18c812016-04-27 16:00:41 -06002502 if (StorageManager.isFileEncryptedNativeOrEmulated()) {
Rubin Xu3bf722a2016-12-15 16:07:38 +00002503 // When a user has secure lock screen, require secret to actually unlock.
2504 // This check is mostly in place for emulation mode.
2505 if (mLockPatternUtils.isSecure(userId) && ArrayUtils.isEmpty(secret)) {
2506 throw new IllegalStateException("Secret required to unlock secure user " + userId);
Jeff Sharkeyce18c812016-04-27 16:00:41 -06002507 }
Jeff Sharkeyb9fe5372015-12-03 15:23:08 -07002508
Jeff Sharkeyce18c812016-04-27 16:00:41 -06002509 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002510 mVold.unlockUserKey(userId, serialNumber, encodeBytes(token),
2511 encodeBytes(secret));
Jeff Sharkey43e12112017-09-12 16:31:45 -06002512 } catch (Exception e) {
2513 Slog.wtf(TAG, e);
2514 return;
Jeff Sharkeyce18c812016-04-27 16:00:41 -06002515 }
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002516 }
2517
2518 synchronized (mLock) {
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07002519 mLocalUnlockedUsers = ArrayUtils.appendInt(mLocalUnlockedUsers, userId);
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002520 }
Paul Crowley9139a782017-07-26 13:29:25 -07002521 if (userId == UserHandle.USER_SYSTEM) {
2522 String propertyName = "sys.user." + userId + ".ce_available";
2523 Slog.d(TAG, "Setting property: " + propertyName + "=true");
2524 SystemProperties.set(propertyName, "true");
2525 }
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002526 }
2527
2528 @Override
2529 public void lockUserKey(int userId) {
2530 enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002531
2532 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002533 mVold.lockUserKey(userId);
Jeff Sharkey43e12112017-09-12 16:31:45 -06002534 } catch (Exception e) {
2535 Slog.wtf(TAG, e);
2536 return;
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002537 }
2538
2539 synchronized (mLock) {
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07002540 mLocalUnlockedUsers = ArrayUtils.removeInt(mLocalUnlockedUsers, userId);
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002541 }
2542 }
2543
2544 @Override
2545 public boolean isUserKeyUnlocked(int userId) {
Jeff Sharkeyce18c812016-04-27 16:00:41 -06002546 synchronized (mLock) {
2547 return ArrayUtils.contains(mLocalUnlockedUsers, userId);
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002548 }
2549 }
2550
2551 @Override
Jeff Sharkey47f71082016-02-01 17:03:54 -07002552 public void prepareUserStorage(String volumeUuid, int userId, int serialNumber, int flags) {
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002553 enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002554
2555 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002556 mVold.prepareUserStorage(volumeUuid, userId, serialNumber, flags);
Jeff Sharkey43e12112017-09-12 16:31:45 -06002557 } catch (Exception e) {
2558 Slog.wtf(TAG, e);
Paul Crowley7ec733f2015-05-19 12:42:00 +01002559 }
2560 }
2561
Paul Crowleybcf48ed2015-04-22 13:36:59 +01002562 @Override
Jeff Sharkeyfcf1e552016-04-14 20:44:58 -06002563 public void destroyUserStorage(String volumeUuid, int userId, int flags) {
2564 enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
Jeff Sharkeyfcf1e552016-04-14 20:44:58 -06002565
2566 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002567 mVold.destroyUserStorage(volumeUuid, userId, flags);
Jeff Sharkey43e12112017-09-12 16:31:45 -06002568 } catch (Exception e) {
2569 Slog.wtf(TAG, e);
Jeff Sharkeyfcf1e552016-04-14 20:44:58 -06002570 }
2571 }
2572
Rubin Xuee67b612017-04-27 17:01:05 +01002573 @Override
2574 public void secdiscard(String path) {
2575 enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
Rubin Xuee67b612017-04-27 17:01:05 +01002576
2577 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002578 mVold.secdiscard(path);
Jeff Sharkey43e12112017-09-12 16:31:45 -06002579 } catch (Exception e) {
2580 Slog.wtf(TAG, e);
Rubin Xuee67b612017-04-27 17:01:05 +01002581 }
2582 }
2583
Daichi Hironoe56740d2017-02-02 13:56:45 +09002584 class AppFuseMountScope extends AppFuseBridge.MountScope {
Daichi Hirono812c95d2017-02-08 16:20:20 +09002585 boolean opened = false;
2586
2587 public AppFuseMountScope(int uid, int pid, int mountId) {
2588 super(uid, pid, mountId);
2589 }
2590
2591 @Override
2592 public ParcelFileDescriptor open() throws NativeDaemonConnectorException {
Jeff Sharkey54402792017-09-15 16:05:19 -06002593 try {
2594 return new ParcelFileDescriptor(
2595 mVold.mountAppFuse(uid, Process.myPid(), mountId));
2596 } catch (Exception e) {
2597 throw new NativeDaemonConnectorException("Failed to mount", e);
Daichi Hirono812c95d2017-02-08 16:20:20 +09002598 }
Daichi Hirono9fb00182016-11-08 14:12:17 +09002599 }
2600
2601 @Override
Daichi Hironoe56740d2017-02-02 13:56:45 +09002602 public void close() throws Exception {
Daichi Hirono812c95d2017-02-08 16:20:20 +09002603 if (opened) {
Jeff Sharkey54402792017-09-15 16:05:19 -06002604 mVold.unmountAppFuse(uid, Process.myPid(), mountId);
Daichi Hirono812c95d2017-02-08 16:20:20 +09002605 opened = false;
2606 }
Daichi Hirono9fb00182016-11-08 14:12:17 +09002607 }
2608 }
2609
2610 @Override
Daichi Hirono812c95d2017-02-08 16:20:20 +09002611 public @Nullable AppFuseMount mountProxyFileDescriptorBridge() {
Daichi Hironoe56740d2017-02-02 13:56:45 +09002612 Slog.v(TAG, "mountProxyFileDescriptorBridge");
Daichi Hirono9fb00182016-11-08 14:12:17 +09002613 final int uid = Binder.getCallingUid();
2614 final int pid = Binder.getCallingPid();
Daichi Hirono9fb00182016-11-08 14:12:17 +09002615
Daichi Hironoe56740d2017-02-02 13:56:45 +09002616 while (true) {
2617 synchronized (mAppFuseLock) {
2618 boolean newlyCreated = false;
2619 if (mAppFuseBridge == null) {
2620 mAppFuseBridge = new AppFuseBridge();
2621 new Thread(mAppFuseBridge, AppFuseBridge.TAG).start();
2622 newlyCreated = true;
Daichi Hirono9fb00182016-11-08 14:12:17 +09002623 }
Daichi Hironoe56740d2017-02-02 13:56:45 +09002624 try {
2625 final int name = mNextAppFuseName++;
2626 try {
2627 return new AppFuseMount(
Daichi Hirono812c95d2017-02-08 16:20:20 +09002628 name, mAppFuseBridge.addBridge(new AppFuseMountScope(uid, pid, name)));
2629 } catch (FuseUnavailableMountException e) {
Daichi Hironoe56740d2017-02-02 13:56:45 +09002630 if (newlyCreated) {
2631 // If newly created bridge fails, it's a real error.
Daichi Hirono812c95d2017-02-08 16:20:20 +09002632 Slog.e(TAG, "", e);
2633 return null;
Daichi Hironoe56740d2017-02-02 13:56:45 +09002634 }
2635 // It seems the thread of mAppFuseBridge has already been terminated.
2636 mAppFuseBridge = null;
2637 }
2638 } catch (NativeDaemonConnectorException e) {
2639 throw e.rethrowAsParcelableException();
2640 }
Daichi Hirono9fb00182016-11-08 14:12:17 +09002641 }
Daichi Hirono9fb00182016-11-08 14:12:17 +09002642 }
2643 }
2644
2645 @Override
Daichi Hirono812c95d2017-02-08 16:20:20 +09002646 public @Nullable ParcelFileDescriptor openProxyFileDescriptor(
2647 int mountId, int fileId, int mode) {
2648 Slog.v(TAG, "mountProxyFileDescriptor");
Daichi Hirono9fb00182016-11-08 14:12:17 +09002649 final int pid = Binder.getCallingPid();
2650 try {
2651 synchronized (mAppFuseLock) {
Daichi Hironoe56740d2017-02-02 13:56:45 +09002652 if (mAppFuseBridge == null) {
Daichi Hirono812c95d2017-02-08 16:20:20 +09002653 Slog.e(TAG, "FuseBridge has not been created");
2654 return null;
Daichi Hirono9fb00182016-11-08 14:12:17 +09002655 }
Daichi Hironoe56740d2017-02-02 13:56:45 +09002656 return mAppFuseBridge.openFile(pid, mountId, fileId, mode);
Daichi Hirono9fb00182016-11-08 14:12:17 +09002657 }
Daichi Hirono812c95d2017-02-08 16:20:20 +09002658 } catch (FuseUnavailableMountException | InterruptedException error) {
2659 Slog.v(TAG, "The mount point has already been invalid", error);
2660 return null;
Daichi Hirono9fb00182016-11-08 14:12:17 +09002661 }
2662 }
2663
Daichi Hirono9e8d9e22015-11-13 14:37:00 +09002664 @Override
Jeff Sharkeyae266462017-11-27 13:32:24 -07002665 public void mkdirs(String callingPkg, String appPath) {
Jeff Sharkey2d8b4e82013-09-17 17:30:33 -07002666 final int userId = UserHandle.getUserId(Binder.getCallingUid());
2667 final UserEnvironment userEnv = new UserEnvironment(userId);
2668
2669 // Validate that reported package name belongs to caller
2670 final AppOpsManager appOps = (AppOpsManager) mContext.getSystemService(
2671 Context.APP_OPS_SERVICE);
2672 appOps.checkPackage(Binder.getCallingUid(), callingPkg);
2673
Jeff Sharkey48877892015-03-18 11:27:19 -07002674 File appFile = null;
Jeff Sharkey2d8b4e82013-09-17 17:30:33 -07002675 try {
Jeff Sharkey48877892015-03-18 11:27:19 -07002676 appFile = new File(appPath).getCanonicalFile();
Jeff Sharkey2d8b4e82013-09-17 17:30:33 -07002677 } catch (IOException e) {
Jeff Sharkeyae266462017-11-27 13:32:24 -07002678 throw new IllegalStateException("Failed to resolve " + appPath + ": " + e);
Jeff Sharkey2d8b4e82013-09-17 17:30:33 -07002679 }
2680
2681 // Try translating the app path into a vold path, but require that it
2682 // belong to the calling package.
Jeff Sharkey48877892015-03-18 11:27:19 -07002683 if (FileUtils.contains(userEnv.buildExternalStorageAppDataDirs(callingPkg), appFile) ||
2684 FileUtils.contains(userEnv.buildExternalStorageAppObbDirs(callingPkg), appFile) ||
2685 FileUtils.contains(userEnv.buildExternalStorageAppMediaDirs(callingPkg), appFile)) {
2686 appPath = appFile.getAbsolutePath();
2687 if (!appPath.endsWith("/")) {
2688 appPath = appPath + "/";
2689 }
2690
Jeff Sharkey2d8b4e82013-09-17 17:30:33 -07002691 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002692 mVold.mkdirs(appPath);
Jeff Sharkey27a108c2017-11-30 17:11:40 -07002693 return;
Jeff Sharkeyace874b2017-09-07 15:27:33 -06002694 } catch (Exception e) {
Jeff Sharkeyae266462017-11-27 13:32:24 -07002695 throw new IllegalStateException("Failed to prepare " + appPath + ": " + e);
Jeff Sharkey2d8b4e82013-09-17 17:30:33 -07002696 }
2697 }
2698
Jeff Sharkey48877892015-03-18 11:27:19 -07002699 throw new SecurityException("Invalid mkdirs path: " + appFile);
Jeff Sharkey2d8b4e82013-09-17 17:30:33 -07002700 }
2701
2702 @Override
Jeff Sharkey46349872015-07-28 10:49:47 -07002703 public StorageVolume[] getVolumeList(int uid, String packageName, int flags) {
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07002704 final int userId = UserHandle.getUserId(uid);
Jeff Sharkeyc02bfae2016-03-27 15:06:53 -06002705
Jeff Sharkey46349872015-07-28 10:49:47 -07002706 final boolean forWrite = (flags & StorageManager.FLAG_FOR_WRITE) != 0;
Jeff Sharkeyc02bfae2016-03-27 15:06:53 -06002707 final boolean realState = (flags & StorageManager.FLAG_REAL_STATE) != 0;
2708 final boolean includeInvisible = (flags & StorageManager.FLAG_INCLUDE_INVISIBLE) != 0;
Jeff Sharkey46349872015-07-28 10:49:47 -07002709
Jeff Sharkeyc02bfae2016-03-27 15:06:53 -06002710 final boolean userKeyUnlocked;
2711 final boolean storagePermission;
2712 final long token = Binder.clearCallingIdentity();
Svetoslav38c3dbb2015-07-14 11:27:06 -07002713 try {
Jeff Sharkeyc02bfae2016-03-27 15:06:53 -06002714 userKeyUnlocked = isUserKeyUnlocked(userId);
Sudheer Shanka2250d562016-11-07 15:41:02 -08002715 storagePermission = mStorageManagerInternal.hasExternalStorage(uid, packageName);
Svetoslav38c3dbb2015-07-14 11:27:06 -07002716 } finally {
Jeff Sharkeyc02bfae2016-03-27 15:06:53 -06002717 Binder.restoreCallingIdentity(token);
Svetoslav38c3dbb2015-07-14 11:27:06 -07002718 }
Svet Ganov6ee871e2015-07-10 14:29:33 -07002719
Jeff Sharkeyc02bfae2016-03-27 15:06:53 -06002720 boolean foundPrimary = false;
2721
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07002722 final ArrayList<StorageVolume> res = new ArrayList<>();
Jeff Sharkey48877892015-03-18 11:27:19 -07002723 synchronized (mLock) {
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07002724 for (int i = 0; i < mVolumes.size(); i++) {
2725 final VolumeInfo vol = mVolumes.valueAt(i);
Jeff Sharkeyc02bfae2016-03-27 15:06:53 -06002726 switch (vol.getType()) {
2727 case VolumeInfo.TYPE_PUBLIC:
2728 case VolumeInfo.TYPE_EMULATED:
2729 break;
2730 default:
2731 continue;
2732 }
2733
2734 boolean match = false;
2735 if (forWrite) {
2736 match = vol.isVisibleForWrite(userId);
2737 } else {
Felipe Leme123a0e72016-06-10 11:09:11 -07002738 match = vol.isVisibleForRead(userId)
2739 || (includeInvisible && vol.getPath() != null);
Jeff Sharkeyc02bfae2016-03-27 15:06:53 -06002740 }
2741 if (!match) continue;
2742
2743 boolean reportUnmounted = false;
2744 if ((vol.getType() == VolumeInfo.TYPE_EMULATED) && !userKeyUnlocked) {
2745 reportUnmounted = true;
2746 } else if (!storagePermission && !realState) {
2747 reportUnmounted = true;
2748 }
2749
2750 final StorageVolume userVol = vol.buildStorageVolume(mContext, userId,
2751 reportUnmounted);
2752 if (vol.isPrimary()) {
2753 res.add(0, userVol);
2754 foundPrimary = true;
2755 } else {
2756 res.add(userVol);
Jeff Sharkeyb049e212012-09-07 23:16:01 -07002757 }
Mike Lockwood8fa5f802011-03-24 08:12:30 -07002758 }
Mike Lockwood8fa5f802011-03-24 08:12:30 -07002759 }
Jeff Sharkey48877892015-03-18 11:27:19 -07002760
2761 if (!foundPrimary) {
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07002762 Log.w(TAG, "No primary storage defined yet; hacking together a stub");
Jeff Sharkey48877892015-03-18 11:27:19 -07002763
2764 final boolean primaryPhysical = SystemProperties.getBoolean(
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07002765 StorageManager.PROP_PRIMARY_PHYSICAL, false);
Jeff Sharkey48877892015-03-18 11:27:19 -07002766
2767 final String id = "stub_primary";
2768 final File path = Environment.getLegacyExternalStorageDirectory();
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07002769 final String description = mContext.getString(android.R.string.unknownName);
Jeff Sharkey48877892015-03-18 11:27:19 -07002770 final boolean primary = true;
2771 final boolean removable = primaryPhysical;
2772 final boolean emulated = !primaryPhysical;
Jeff Sharkey48877892015-03-18 11:27:19 -07002773 final boolean allowMassStorage = false;
2774 final long maxFileSize = 0L;
2775 final UserHandle owner = new UserHandle(userId);
2776 final String uuid = null;
Jeff Sharkey48877892015-03-18 11:27:19 -07002777 final String state = Environment.MEDIA_REMOVED;
2778
Jerry Zhangf9c5c252017-08-16 18:07:51 -07002779 res.add(0, new StorageVolume(id, path,
2780 description, primary, removable, emulated,
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07002781 allowMassStorage, maxFileSize, owner, uuid, state));
Jeff Sharkey48877892015-03-18 11:27:19 -07002782 }
2783
2784 return res.toArray(new StorageVolume[res.size()]);
Mike Lockwood8fa5f802011-03-24 08:12:30 -07002785 }
2786
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07002787 @Override
2788 public DiskInfo[] getDisks() {
2789 synchronized (mLock) {
2790 final DiskInfo[] res = new DiskInfo[mDisks.size()];
2791 for (int i = 0; i < mDisks.size(); i++) {
2792 res[i] = mDisks.valueAt(i);
2793 }
2794 return res;
2795 }
2796 }
2797
2798 @Override
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07002799 public VolumeInfo[] getVolumes(int flags) {
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07002800 synchronized (mLock) {
2801 final VolumeInfo[] res = new VolumeInfo[mVolumes.size()];
2802 for (int i = 0; i < mVolumes.size(); i++) {
2803 res[i] = mVolumes.valueAt(i);
2804 }
2805 return res;
2806 }
2807 }
2808
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07002809 @Override
2810 public VolumeRecord[] getVolumeRecords(int flags) {
2811 synchronized (mLock) {
2812 final VolumeRecord[] res = new VolumeRecord[mRecords.size()];
2813 for (int i = 0; i < mRecords.size(); i++) {
2814 res[i] = mRecords.valueAt(i);
2815 }
2816 return res;
2817 }
2818 }
2819
Jeff Sharkey9bed0702017-01-23 20:37:05 -07002820 @Override
2821 public long getCacheQuotaBytes(String volumeUuid, int uid) {
2822 if (uid != Binder.getCallingUid()) {
2823 mContext.enforceCallingPermission(android.Manifest.permission.STORAGE_INTERNAL, TAG);
2824 }
Daniel Nishi80fdb012017-03-09 14:30:07 -08002825 final long token = Binder.clearCallingIdentity();
2826 final StorageStatsManager stats = mContext.getSystemService(StorageStatsManager.class);
2827 try {
2828 return stats.getCacheQuotaBytes(volumeUuid, uid);
2829 } finally {
2830 Binder.restoreCallingIdentity(token);
2831 }
Jeff Sharkey9bed0702017-01-23 20:37:05 -07002832 }
2833
2834 @Override
2835 public long getCacheSizeBytes(String volumeUuid, int uid) {
2836 if (uid != Binder.getCallingUid()) {
2837 mContext.enforceCallingPermission(android.Manifest.permission.STORAGE_INTERNAL, TAG);
2838 }
2839 final long token = Binder.clearCallingIdentity();
2840 try {
2841 return mContext.getSystemService(StorageStatsManager.class)
2842 .queryStatsForUid(volumeUuid, uid).getCacheBytes();
Jeff Sharkey789a8fc2017-04-16 13:18:35 -06002843 } catch (IOException e) {
2844 throw new ParcelableException(e);
Jeff Sharkey9bed0702017-01-23 20:37:05 -07002845 } finally {
2846 Binder.restoreCallingIdentity(token);
2847 }
2848 }
2849
Jeff Sharkey35e46d22017-06-09 10:01:20 -06002850 private int adjustAllocateFlags(int flags, int callingUid, String callingPackage) {
2851 // Require permission to allocate aggressively
2852 if ((flags & StorageManager.FLAG_ALLOCATE_AGGRESSIVE) != 0) {
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07002853 mContext.enforceCallingOrSelfPermission(
2854 android.Manifest.permission.ALLOCATE_AGGRESSIVE, TAG);
2855 }
2856
Jeff Sharkey35e46d22017-06-09 10:01:20 -06002857 // Apps normally can't directly defy reserved space
2858 flags &= ~StorageManager.FLAG_ALLOCATE_DEFY_ALL_RESERVED;
2859 flags &= ~StorageManager.FLAG_ALLOCATE_DEFY_HALF_RESERVED;
2860
2861 // However, if app is actively using the camera, then we're willing to
2862 // clear up to half of the reserved cache space, since the user might be
2863 // trying to capture an important memory.
2864 final AppOpsManager appOps = mContext.getSystemService(AppOpsManager.class);
2865 final long token = Binder.clearCallingIdentity();
2866 try {
2867 if (appOps.isOperationActive(AppOpsManager.OP_CAMERA, callingUid, callingPackage)) {
2868 Slog.d(TAG, "UID " + callingUid + " is actively using camera;"
2869 + " letting them defy reserved cached data");
2870 flags |= StorageManager.FLAG_ALLOCATE_DEFY_HALF_RESERVED;
2871 }
2872 } finally {
2873 Binder.restoreCallingIdentity(token);
2874 }
2875
2876 return flags;
2877 }
2878
2879 @Override
2880 public long getAllocatableBytes(String volumeUuid, int flags, String callingPackage) {
2881 flags = adjustAllocateFlags(flags, Binder.getCallingUid(), callingPackage);
2882
2883 final StorageManager storage = mContext.getSystemService(StorageManager.class);
2884 final StorageStatsManager stats = mContext.getSystemService(StorageStatsManager.class);
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07002885 final long token = Binder.clearCallingIdentity();
2886 try {
2887 // In general, apps can allocate as much space as they want, except
2888 // we never let them eat into either the minimum cache space or into
Jeff Sharkeyddff8072017-05-26 13:10:46 -06002889 // the low disk warning space. To avoid user confusion, this logic
2890 // should be kept in sync with getFreeBytes().
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07002891 final File path = storage.findPathForUuid(volumeUuid);
Jeff Sharkeyddff8072017-05-26 13:10:46 -06002892
2893 final long usable = path.getUsableSpace();
2894 final long lowReserved = storage.getStorageLowBytes(path);
2895 final long fullReserved = storage.getStorageFullBytes(path);
2896
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07002897 if (stats.isQuotaSupported(volumeUuid)) {
Jeff Sharkeyddff8072017-05-26 13:10:46 -06002898 final long cacheTotal = stats.getCacheBytes(volumeUuid);
Jeff Sharkey35e46d22017-06-09 10:01:20 -06002899 final long cacheReserved = storage.getStorageCacheBytes(path, flags);
Jeff Sharkeyddff8072017-05-26 13:10:46 -06002900 final long cacheClearable = Math.max(0, cacheTotal - cacheReserved);
2901
Jeff Sharkey35e46d22017-06-09 10:01:20 -06002902 if ((flags & StorageManager.FLAG_ALLOCATE_AGGRESSIVE) != 0) {
2903 return Math.max(0, (usable + cacheClearable) - fullReserved);
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07002904 } else {
Jeff Sharkeyddff8072017-05-26 13:10:46 -06002905 return Math.max(0, (usable + cacheClearable) - lowReserved);
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07002906 }
2907 } else {
2908 // When we don't have fast quota information, we ignore cached
2909 // data and only consider unused bytes.
Jeff Sharkey35e46d22017-06-09 10:01:20 -06002910 if ((flags & StorageManager.FLAG_ALLOCATE_AGGRESSIVE) != 0) {
Jeff Sharkeyddff8072017-05-26 13:10:46 -06002911 return Math.max(0, usable - fullReserved);
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07002912 } else {
Jeff Sharkeyddff8072017-05-26 13:10:46 -06002913 return Math.max(0, usable - lowReserved);
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07002914 }
2915 }
Jeff Sharkey789a8fc2017-04-16 13:18:35 -06002916 } catch (IOException e) {
2917 throw new ParcelableException(e);
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07002918 } finally {
2919 Binder.restoreCallingIdentity(token);
2920 }
Jeff Sharkey500ce9e2017-02-12 02:39:24 -07002921 }
2922
2923 @Override
Jeff Sharkey35e46d22017-06-09 10:01:20 -06002924 public void allocateBytes(String volumeUuid, long bytes, int flags, String callingPackage) {
2925 flags = adjustAllocateFlags(flags, Binder.getCallingUid(), callingPackage);
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07002926
Jeff Sharkey35e46d22017-06-09 10:01:20 -06002927 final long allocatableBytes = getAllocatableBytes(volumeUuid, flags, callingPackage);
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07002928 if (bytes > allocatableBytes) {
2929 throw new ParcelableException(new IOException("Failed to allocate " + bytes
2930 + " because only " + allocatableBytes + " allocatable"));
2931 }
2932
Jeff Sharkey35e46d22017-06-09 10:01:20 -06002933 final StorageManager storage = mContext.getSystemService(StorageManager.class);
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07002934 final long token = Binder.clearCallingIdentity();
2935 try {
Jeff Sharkey789a8fc2017-04-16 13:18:35 -06002936 // Free up enough disk space to satisfy both the requested allocation
2937 // and our low disk warning space.
2938 final File path = storage.findPathForUuid(volumeUuid);
Jeff Sharkeyddff8072017-05-26 13:10:46 -06002939 if ((flags & StorageManager.FLAG_ALLOCATE_AGGRESSIVE) != 0) {
2940 bytes += storage.getStorageFullBytes(path);
2941 } else {
2942 bytes += storage.getStorageLowBytes(path);
2943 }
Jeff Sharkey789a8fc2017-04-16 13:18:35 -06002944
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07002945 mPms.freeStorage(volumeUuid, bytes, flags);
2946 } catch (IOException e) {
2947 throw new ParcelableException(e);
2948 } finally {
2949 Binder.restoreCallingIdentity(token);
Jeff Sharkey500ce9e2017-02-12 02:39:24 -07002950 }
2951 }
2952
Kenny Rootaf9d6672010-10-08 09:21:39 -07002953 private void addObbStateLocked(ObbState obbState) throws RemoteException {
2954 final IBinder binder = obbState.getBinder();
2955 List<ObbState> obbStates = mObbMounts.get(binder);
Kenny Root5919ac62010-10-05 09:49:40 -07002956
Kenny Rootaf9d6672010-10-08 09:21:39 -07002957 if (obbStates == null) {
2958 obbStates = new ArrayList<ObbState>();
2959 mObbMounts.put(binder, obbStates);
2960 } else {
2961 for (final ObbState o : obbStates) {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002962 if (o.rawPath.equals(obbState.rawPath)) {
Kenny Rootaf9d6672010-10-08 09:21:39 -07002963 throw new IllegalStateException("Attempt to add ObbState twice. "
Sudheer Shanka2250d562016-11-07 15:41:02 -08002964 + "This indicates an error in the StorageManagerService logic.");
Kenny Root5919ac62010-10-05 09:49:40 -07002965 }
2966 }
Kenny Roota02b8b02010-08-05 16:14:17 -07002967 }
Kenny Rootaf9d6672010-10-08 09:21:39 -07002968
2969 obbStates.add(obbState);
2970 try {
2971 obbState.link();
2972 } catch (RemoteException e) {
2973 /*
2974 * The binder died before we could link it, so clean up our state
2975 * and return failure.
2976 */
2977 obbStates.remove(obbState);
2978 if (obbStates.isEmpty()) {
2979 mObbMounts.remove(binder);
2980 }
2981
2982 // Rethrow the error so mountObb can get it
2983 throw e;
2984 }
2985
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002986 mObbPathToStateMap.put(obbState.rawPath, obbState);
Kenny Roota02b8b02010-08-05 16:14:17 -07002987 }
2988
Kenny Rootaf9d6672010-10-08 09:21:39 -07002989 private void removeObbStateLocked(ObbState obbState) {
2990 final IBinder binder = obbState.getBinder();
2991 final List<ObbState> obbStates = mObbMounts.get(binder);
2992 if (obbStates != null) {
2993 if (obbStates.remove(obbState)) {
2994 obbState.unlink();
Kenny Root05105f72010-09-22 17:29:43 -07002995 }
Kenny Rootaf9d6672010-10-08 09:21:39 -07002996 if (obbStates.isEmpty()) {
2997 mObbMounts.remove(binder);
2998 }
Kenny Roota02b8b02010-08-05 16:14:17 -07002999 }
Kenny Roota02b8b02010-08-05 16:14:17 -07003000
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003001 mObbPathToStateMap.remove(obbState.rawPath);
Kenny Root38cf8862010-09-26 14:18:51 -07003002 }
3003
Kenny Roota02b8b02010-08-05 16:14:17 -07003004 private class ObbActionHandler extends Handler {
3005 private boolean mBound = false;
Kenny Root480afe72010-10-07 10:17:50 -07003006 private final List<ObbAction> mActions = new LinkedList<ObbAction>();
Kenny Roota02b8b02010-08-05 16:14:17 -07003007
3008 ObbActionHandler(Looper l) {
3009 super(l);
3010 }
3011
3012 @Override
3013 public void handleMessage(Message msg) {
3014 switch (msg.what) {
3015 case OBB_RUN_ACTION: {
Kenny Root480afe72010-10-07 10:17:50 -07003016 final ObbAction action = (ObbAction) msg.obj;
Kenny Roota02b8b02010-08-05 16:14:17 -07003017
3018 if (DEBUG_OBB)
3019 Slog.i(TAG, "OBB_RUN_ACTION: " + action.toString());
3020
3021 // If a bind was already initiated we don't really
3022 // need to do anything. The pending install
3023 // will be processed later on.
3024 if (!mBound) {
3025 // If this is the only one pending we might
3026 // have to bind to the service again.
3027 if (!connectToService()) {
3028 Slog.e(TAG, "Failed to bind to media container service");
3029 action.handleError();
3030 return;
Kenny Roota02b8b02010-08-05 16:14:17 -07003031 }
Kenny Roota02b8b02010-08-05 16:14:17 -07003032 }
Kenny Root735de3b2010-09-30 14:11:39 -07003033
Kenny Root735de3b2010-09-30 14:11:39 -07003034 mActions.add(action);
Kenny Roota02b8b02010-08-05 16:14:17 -07003035 break;
3036 }
3037 case OBB_MCS_BOUND: {
3038 if (DEBUG_OBB)
3039 Slog.i(TAG, "OBB_MCS_BOUND");
3040 if (msg.obj != null) {
3041 mContainerService = (IMediaContainerService) msg.obj;
3042 }
3043 if (mContainerService == null) {
3044 // Something seriously wrong. Bail out
3045 Slog.e(TAG, "Cannot bind to media container service");
3046 for (ObbAction action : mActions) {
3047 // Indicate service bind error
3048 action.handleError();
3049 }
3050 mActions.clear();
3051 } else if (mActions.size() > 0) {
Kenny Root480afe72010-10-07 10:17:50 -07003052 final ObbAction action = mActions.get(0);
Kenny Roota02b8b02010-08-05 16:14:17 -07003053 if (action != null) {
3054 action.execute(this);
3055 }
3056 } else {
3057 // Should never happen ideally.
3058 Slog.w(TAG, "Empty queue");
3059 }
3060 break;
3061 }
3062 case OBB_MCS_RECONNECT: {
3063 if (DEBUG_OBB)
3064 Slog.i(TAG, "OBB_MCS_RECONNECT");
3065 if (mActions.size() > 0) {
3066 if (mBound) {
3067 disconnectService();
3068 }
3069 if (!connectToService()) {
3070 Slog.e(TAG, "Failed to bind to media container service");
3071 for (ObbAction action : mActions) {
3072 // Indicate service bind error
3073 action.handleError();
3074 }
3075 mActions.clear();
3076 }
3077 }
3078 break;
3079 }
3080 case OBB_MCS_UNBIND: {
3081 if (DEBUG_OBB)
3082 Slog.i(TAG, "OBB_MCS_UNBIND");
3083
3084 // Delete pending install
3085 if (mActions.size() > 0) {
3086 mActions.remove(0);
3087 }
3088 if (mActions.size() == 0) {
3089 if (mBound) {
3090 disconnectService();
3091 }
3092 } else {
3093 // There are more pending requests in queue.
3094 // Just post MCS_BOUND message to trigger processing
3095 // of next pending install.
3096 mObbActionHandler.sendEmptyMessage(OBB_MCS_BOUND);
3097 }
3098 break;
3099 }
Kenny Rootaf9d6672010-10-08 09:21:39 -07003100 case OBB_FLUSH_MOUNT_STATE: {
3101 final String path = (String) msg.obj;
3102
3103 if (DEBUG_OBB)
3104 Slog.i(TAG, "Flushing all OBB state for path " + path);
3105
3106 synchronized (mObbMounts) {
3107 final List<ObbState> obbStatesToRemove = new LinkedList<ObbState>();
3108
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003109 final Iterator<ObbState> i = mObbPathToStateMap.values().iterator();
Kenny Rootaf9d6672010-10-08 09:21:39 -07003110 while (i.hasNext()) {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003111 final ObbState state = i.next();
Kenny Rootaf9d6672010-10-08 09:21:39 -07003112
3113 /*
3114 * If this entry's source file is in the volume path
3115 * that got unmounted, remove it because it's no
3116 * longer valid.
3117 */
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003118 if (state.canonicalPath.startsWith(path)) {
3119 obbStatesToRemove.add(state);
Kenny Rootaf9d6672010-10-08 09:21:39 -07003120 }
3121 }
3122
3123 for (final ObbState obbState : obbStatesToRemove) {
3124 if (DEBUG_OBB)
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003125 Slog.i(TAG, "Removing state for " + obbState.rawPath);
Kenny Rootaf9d6672010-10-08 09:21:39 -07003126
3127 removeObbStateLocked(obbState);
3128
3129 try {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003130 obbState.token.onObbResult(obbState.rawPath, obbState.nonce,
Kenny Rootaf9d6672010-10-08 09:21:39 -07003131 OnObbStateChangeListener.UNMOUNTED);
3132 } catch (RemoteException e) {
3133 Slog.i(TAG, "Couldn't send unmount notification for OBB: "
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003134 + obbState.rawPath);
Kenny Rootaf9d6672010-10-08 09:21:39 -07003135 }
3136 }
3137 }
3138 break;
3139 }
Kenny Roota02b8b02010-08-05 16:14:17 -07003140 }
3141 }
3142
3143 private boolean connectToService() {
3144 if (DEBUG_OBB)
3145 Slog.i(TAG, "Trying to bind to DefaultContainerService");
3146
3147 Intent service = new Intent().setComponent(DEFAULT_CONTAINER_COMPONENT);
Jeff Sharkey6dce4962015-07-03 18:08:41 -07003148 if (mContext.bindServiceAsUser(service, mDefContainerConn, Context.BIND_AUTO_CREATE,
Xiaohui Chene4de5a02015-09-22 15:33:31 -07003149 UserHandle.SYSTEM)) {
Kenny Roota02b8b02010-08-05 16:14:17 -07003150 mBound = true;
3151 return true;
3152 }
3153 return false;
3154 }
3155
3156 private void disconnectService() {
3157 mContainerService = null;
3158 mBound = false;
3159 mContext.unbindService(mDefContainerConn);
3160 }
3161 }
3162
3163 abstract class ObbAction {
3164 private static final int MAX_RETRIES = 3;
3165 private int mRetries;
3166
3167 ObbState mObbState;
3168
3169 ObbAction(ObbState obbState) {
3170 mObbState = obbState;
3171 }
3172
3173 public void execute(ObbActionHandler handler) {
3174 try {
3175 if (DEBUG_OBB)
Ben Komalo444eca22011-09-01 15:17:44 -07003176 Slog.i(TAG, "Starting to execute action: " + toString());
Kenny Roota02b8b02010-08-05 16:14:17 -07003177 mRetries++;
3178 if (mRetries > MAX_RETRIES) {
3179 Slog.w(TAG, "Failed to invoke remote methods on default container service. Giving up");
Kenny Root480afe72010-10-07 10:17:50 -07003180 mObbActionHandler.sendEmptyMessage(OBB_MCS_UNBIND);
Kenny Roota02b8b02010-08-05 16:14:17 -07003181 handleError();
Kenny Roota02b8b02010-08-05 16:14:17 -07003182 } else {
3183 handleExecute();
3184 if (DEBUG_OBB)
3185 Slog.i(TAG, "Posting install MCS_UNBIND");
3186 mObbActionHandler.sendEmptyMessage(OBB_MCS_UNBIND);
3187 }
3188 } catch (RemoteException e) {
3189 if (DEBUG_OBB)
3190 Slog.i(TAG, "Posting install MCS_RECONNECT");
3191 mObbActionHandler.sendEmptyMessage(OBB_MCS_RECONNECT);
3192 } catch (Exception e) {
3193 if (DEBUG_OBB)
3194 Slog.d(TAG, "Error handling OBB action", e);
3195 handleError();
Kenny Root17eb6fb2010-10-06 15:02:52 -07003196 mObbActionHandler.sendEmptyMessage(OBB_MCS_UNBIND);
Kenny Roota02b8b02010-08-05 16:14:17 -07003197 }
3198 }
3199
Kenny Root05105f72010-09-22 17:29:43 -07003200 abstract void handleExecute() throws RemoteException, IOException;
Kenny Roota02b8b02010-08-05 16:14:17 -07003201 abstract void handleError();
Kenny Root38cf8862010-09-26 14:18:51 -07003202
3203 protected ObbInfo getObbInfo() throws IOException {
3204 ObbInfo obbInfo;
3205 try {
Xiaohui Chen621b3fc2015-10-02 14:41:42 -07003206 obbInfo = mContainerService.getObbInfo(mObbState.canonicalPath);
Kenny Root38cf8862010-09-26 14:18:51 -07003207 } catch (RemoteException e) {
3208 Slog.d(TAG, "Couldn't call DefaultContainerService to fetch OBB info for "
Xiaohui Chen621b3fc2015-10-02 14:41:42 -07003209 + mObbState.canonicalPath);
Kenny Root38cf8862010-09-26 14:18:51 -07003210 obbInfo = null;
3211 }
3212 if (obbInfo == null) {
Xiaohui Chen621b3fc2015-10-02 14:41:42 -07003213 throw new IOException("Couldn't read OBB file: " + mObbState.canonicalPath);
Kenny Root38cf8862010-09-26 14:18:51 -07003214 }
3215 return obbInfo;
3216 }
3217
Kenny Rootaf9d6672010-10-08 09:21:39 -07003218 protected void sendNewStatusOrIgnore(int status) {
3219 if (mObbState == null || mObbState.token == null) {
3220 return;
3221 }
3222
Kenny Root38cf8862010-09-26 14:18:51 -07003223 try {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003224 mObbState.token.onObbResult(mObbState.rawPath, mObbState.nonce, status);
Kenny Root38cf8862010-09-26 14:18:51 -07003225 } catch (RemoteException e) {
Sudheer Shanka2250d562016-11-07 15:41:02 -08003226 Slog.w(TAG, "StorageEventListener went away while calling onObbStateChanged");
Kenny Root38cf8862010-09-26 14:18:51 -07003227 }
3228 }
Kenny Roota02b8b02010-08-05 16:14:17 -07003229 }
3230
3231 class MountObbAction extends ObbAction {
Ben Komalo444eca22011-09-01 15:17:44 -07003232 private final String mKey;
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003233 private final int mCallingUid;
Kenny Roota02b8b02010-08-05 16:14:17 -07003234
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003235 MountObbAction(ObbState obbState, String key, int callingUid) {
Kenny Roota02b8b02010-08-05 16:14:17 -07003236 super(obbState);
3237 mKey = key;
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003238 mCallingUid = callingUid;
Kenny Roota02b8b02010-08-05 16:14:17 -07003239 }
3240
Jason parks5af0b912010-11-29 09:05:25 -06003241 @Override
Kenny Root735de3b2010-09-30 14:11:39 -07003242 public void handleExecute() throws IOException, RemoteException {
Kenny Rootaf9d6672010-10-08 09:21:39 -07003243 warnOnNotMounted();
3244
Kenny Root38cf8862010-09-26 14:18:51 -07003245 final ObbInfo obbInfo = getObbInfo();
3246
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003247 if (!isUidOwnerOfPackageOrSystem(obbInfo.packageName, mCallingUid)) {
Kenny Rootaf9d6672010-10-08 09:21:39 -07003248 Slog.w(TAG, "Denied attempt to mount OBB " + obbInfo.filename
3249 + " which is owned by " + obbInfo.packageName);
3250 sendNewStatusOrIgnore(OnObbStateChangeListener.ERROR_PERMISSION_DENIED);
3251 return;
Kenny Roota02b8b02010-08-05 16:14:17 -07003252 }
3253
Kenny Rootaf9d6672010-10-08 09:21:39 -07003254 final boolean isMounted;
3255 synchronized (mObbMounts) {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003256 isMounted = mObbPathToStateMap.containsKey(mObbState.rawPath);
Kenny Rootaf9d6672010-10-08 09:21:39 -07003257 }
3258 if (isMounted) {
3259 Slog.w(TAG, "Attempt to mount OBB which is already mounted: " + obbInfo.filename);
3260 sendNewStatusOrIgnore(OnObbStateChangeListener.ERROR_ALREADY_MOUNTED);
3261 return;
3262 }
3263
Kenny Rootaf9d6672010-10-08 09:21:39 -07003264 final String hashedKey;
Jeff Sharkey41cd6812017-09-11 10:32:17 -06003265 final String binderKey;
Kenny Rootaf9d6672010-10-08 09:21:39 -07003266 if (mKey == null) {
3267 hashedKey = "none";
Jeff Sharkey41cd6812017-09-11 10:32:17 -06003268 binderKey = "";
Kenny Rootaf9d6672010-10-08 09:21:39 -07003269 } else {
Kenny Rootaf9d6672010-10-08 09:21:39 -07003270 try {
Kenny Root3b1abba2010-10-13 15:00:07 -07003271 SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
3272
3273 KeySpec ks = new PBEKeySpec(mKey.toCharArray(), obbInfo.salt,
3274 PBKDF2_HASH_ROUNDS, CRYPTO_ALGORITHM_KEY_SIZE);
3275 SecretKey key = factory.generateSecret(ks);
3276 BigInteger bi = new BigInteger(key.getEncoded());
3277 hashedKey = bi.toString(16);
Jeff Sharkey41cd6812017-09-11 10:32:17 -06003278 binderKey = hashedKey;
Kenny Rootaf9d6672010-10-08 09:21:39 -07003279 } catch (NoSuchAlgorithmException e) {
Kenny Root3b1abba2010-10-13 15:00:07 -07003280 Slog.e(TAG, "Could not load PBKDF2 algorithm", e);
3281 sendNewStatusOrIgnore(OnObbStateChangeListener.ERROR_INTERNAL);
3282 return;
3283 } catch (InvalidKeySpecException e) {
3284 Slog.e(TAG, "Invalid key spec when loading PBKDF2 algorithm", e);
3285 sendNewStatusOrIgnore(OnObbStateChangeListener.ERROR_INTERNAL);
Kenny Root38cf8862010-09-26 14:18:51 -07003286 return;
3287 }
Kenny Rootaf9d6672010-10-08 09:21:39 -07003288 }
Kenny Root38cf8862010-09-26 14:18:51 -07003289
Kenny Rootaf9d6672010-10-08 09:21:39 -07003290 int rc = StorageResultCode.OperationSucceeded;
Kenny Rootaf9d6672010-10-08 09:21:39 -07003291 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06003292 mObbState.volId = mVold.createObb(mObbState.canonicalPath, binderKey,
3293 mObbState.ownerGid);
3294 mVold.mount(mObbState.volId, 0, -1);
Jeff Sharkey41cd6812017-09-11 10:32:17 -06003295 } catch (Exception e) {
3296 Slog.w(TAG, e);
3297 rc = StorageResultCode.OperationFailedInternalError;
Kenny Roota02b8b02010-08-05 16:14:17 -07003298 }
3299
Kenny Rootaf9d6672010-10-08 09:21:39 -07003300 if (rc == StorageResultCode.OperationSucceeded) {
3301 if (DEBUG_OBB)
Xiaohui Chen621b3fc2015-10-02 14:41:42 -07003302 Slog.d(TAG, "Successfully mounted OBB " + mObbState.canonicalPath);
Kenny Rootaf9d6672010-10-08 09:21:39 -07003303
3304 synchronized (mObbMounts) {
3305 addObbStateLocked(mObbState);
3306 }
3307
3308 sendNewStatusOrIgnore(OnObbStateChangeListener.MOUNTED);
Kenny Root02c87302010-07-01 08:10:18 -07003309 } else {
Kenny Root05105f72010-09-22 17:29:43 -07003310 Slog.e(TAG, "Couldn't mount OBB file: " + rc);
Kenny Roota02b8b02010-08-05 16:14:17 -07003311
Kenny Rootaf9d6672010-10-08 09:21:39 -07003312 sendNewStatusOrIgnore(OnObbStateChangeListener.ERROR_COULD_NOT_MOUNT);
Kenny Root02c87302010-07-01 08:10:18 -07003313 }
3314 }
3315
Jason parks5af0b912010-11-29 09:05:25 -06003316 @Override
Kenny Roota02b8b02010-08-05 16:14:17 -07003317 public void handleError() {
Kenny Rootaf9d6672010-10-08 09:21:39 -07003318 sendNewStatusOrIgnore(OnObbStateChangeListener.ERROR_INTERNAL);
Kenny Root02c87302010-07-01 08:10:18 -07003319 }
Kenny Roota02b8b02010-08-05 16:14:17 -07003320
3321 @Override
3322 public String toString() {
3323 StringBuilder sb = new StringBuilder();
3324 sb.append("MountObbAction{");
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003325 sb.append(mObbState);
Kenny Roota02b8b02010-08-05 16:14:17 -07003326 sb.append('}');
3327 return sb.toString();
3328 }
3329 }
3330
3331 class UnmountObbAction extends ObbAction {
Ben Komalo444eca22011-09-01 15:17:44 -07003332 private final boolean mForceUnmount;
Kenny Roota02b8b02010-08-05 16:14:17 -07003333
3334 UnmountObbAction(ObbState obbState, boolean force) {
3335 super(obbState);
3336 mForceUnmount = force;
3337 }
3338
Jason parks5af0b912010-11-29 09:05:25 -06003339 @Override
Kenny Root38cf8862010-09-26 14:18:51 -07003340 public void handleExecute() throws IOException {
Kenny Rootaf9d6672010-10-08 09:21:39 -07003341 warnOnNotMounted();
3342
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003343 final ObbState existingState;
Kenny Root38cf8862010-09-26 14:18:51 -07003344 synchronized (mObbMounts) {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003345 existingState = mObbPathToStateMap.get(mObbState.rawPath);
Kenny Rootaf9d6672010-10-08 09:21:39 -07003346 }
Kenny Root38cf8862010-09-26 14:18:51 -07003347
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003348 if (existingState == null) {
Kenny Rootaf9d6672010-10-08 09:21:39 -07003349 sendNewStatusOrIgnore(OnObbStateChangeListener.ERROR_NOT_MOUNTED);
3350 return;
3351 }
3352
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003353 if (existingState.ownerGid != mObbState.ownerGid) {
3354 Slog.w(TAG, "Permission denied attempting to unmount OBB " + existingState.rawPath
3355 + " (owned by GID " + existingState.ownerGid + ")");
Kenny Rootaf9d6672010-10-08 09:21:39 -07003356 sendNewStatusOrIgnore(OnObbStateChangeListener.ERROR_PERMISSION_DENIED);
3357 return;
3358 }
3359
Kenny Rootaf9d6672010-10-08 09:21:39 -07003360 int rc = StorageResultCode.OperationSucceeded;
Kenny Rootaf9d6672010-10-08 09:21:39 -07003361 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06003362 mVold.unmount(mObbState.volId);
3363 mVold.destroyObb(mObbState.volId);
3364 mObbState.volId = null;
Jeff Sharkey41cd6812017-09-11 10:32:17 -06003365 } catch (Exception e) {
3366 Slog.w(TAG, e);
3367 rc = StorageResultCode.OperationFailedInternalError;
Kenny Roota02b8b02010-08-05 16:14:17 -07003368 }
3369
Kenny Rootaf9d6672010-10-08 09:21:39 -07003370 if (rc == StorageResultCode.OperationSucceeded) {
3371 synchronized (mObbMounts) {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003372 removeObbStateLocked(existingState);
Kenny Root38cf8862010-09-26 14:18:51 -07003373 }
3374
Kenny Rootaf9d6672010-10-08 09:21:39 -07003375 sendNewStatusOrIgnore(OnObbStateChangeListener.UNMOUNTED);
Kenny Roota02b8b02010-08-05 16:14:17 -07003376 } else {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003377 Slog.w(TAG, "Could not unmount OBB: " + existingState);
Kenny Rootaf9d6672010-10-08 09:21:39 -07003378 sendNewStatusOrIgnore(OnObbStateChangeListener.ERROR_COULD_NOT_UNMOUNT);
Kenny Roota02b8b02010-08-05 16:14:17 -07003379 }
3380 }
3381
Jason parks5af0b912010-11-29 09:05:25 -06003382 @Override
Kenny Roota02b8b02010-08-05 16:14:17 -07003383 public void handleError() {
Kenny Rootaf9d6672010-10-08 09:21:39 -07003384 sendNewStatusOrIgnore(OnObbStateChangeListener.ERROR_INTERNAL);
Kenny Roota02b8b02010-08-05 16:14:17 -07003385 }
3386
3387 @Override
3388 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 Sharkey4c099d02015-05-15 13:45:00 -07003577 pw.println("Force adoptable: " + mForceAdoptable);
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08003578 pw.println();
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07003579 pw.println("Local unlocked users: " + Arrays.toString(mLocalUnlockedUsers));
3580 pw.println("System unlocked users: " + Arrays.toString(mSystemUnlockedUsers));
Jeff Sharkey27de30d2015-04-18 16:20:27 -07003581 }
Kenny Root38cf8862010-09-26 14:18:51 -07003582
Kenny Root38cf8862010-09-26 14:18:51 -07003583 synchronized (mObbMounts) {
Jeff Sharkey27de30d2015-04-18 16:20:27 -07003584 pw.println();
Jeff Sharkey5aca2b82013-10-16 16:21:54 -07003585 pw.println("mObbMounts:");
3586 pw.increaseIndent();
3587 final Iterator<Entry<IBinder, List<ObbState>>> binders = mObbMounts.entrySet()
3588 .iterator();
Kenny Rootaf9d6672010-10-08 09:21:39 -07003589 while (binders.hasNext()) {
3590 Entry<IBinder, List<ObbState>> e = binders.next();
Jeff Sharkey5aca2b82013-10-16 16:21:54 -07003591 pw.println(e.getKey() + ":");
3592 pw.increaseIndent();
Kenny Rootaf9d6672010-10-08 09:21:39 -07003593 final List<ObbState> obbStates = e.getValue();
Kenny Root38cf8862010-09-26 14:18:51 -07003594 for (final ObbState obbState : obbStates) {
Jeff Sharkey5aca2b82013-10-16 16:21:54 -07003595 pw.println(obbState);
Kenny Root38cf8862010-09-26 14:18:51 -07003596 }
Jeff Sharkey5aca2b82013-10-16 16:21:54 -07003597 pw.decreaseIndent();
Kenny Root38cf8862010-09-26 14:18:51 -07003598 }
Jeff Sharkey5aca2b82013-10-16 16:21:54 -07003599 pw.decreaseIndent();
Kenny Rootaf9d6672010-10-08 09:21:39 -07003600
Jeff Sharkey5aca2b82013-10-16 16:21:54 -07003601 pw.println();
3602 pw.println("mObbPathToStateMap:");
3603 pw.increaseIndent();
Kenny Rootaf9d6672010-10-08 09:21:39 -07003604 final Iterator<Entry<String, ObbState>> maps = mObbPathToStateMap.entrySet().iterator();
3605 while (maps.hasNext()) {
3606 final Entry<String, ObbState> e = maps.next();
Jeff Sharkey5aca2b82013-10-16 16:21:54 -07003607 pw.print(e.getKey());
3608 pw.print(" -> ");
3609 pw.println(e.getValue());
Kenny Rootaf9d6672010-10-08 09:21:39 -07003610 }
Jeff Sharkey5aca2b82013-10-16 16:21:54 -07003611 pw.decreaseIndent();
Kenny Root38cf8862010-09-26 14:18:51 -07003612 }
Kenny Root4161f9b2011-07-13 09:48:33 -07003613
Robert Greenwalt470fd722012-01-18 12:51:15 -08003614 pw.println();
Christopher Tate7265abe2014-11-21 13:54:45 -08003615 pw.print("Last maintenance: ");
Jeff Sharkeye8a4b662015-06-27 15:43:45 -07003616 pw.println(TimeUtils.formatForLogging(mLastMaintenance));
Kenny Root38cf8862010-09-26 14:18:51 -07003617 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003618
Jeff Sharkeyfa23c5a2011-08-09 21:44:24 -07003619 /** {@inheritDoc} */
Jeff Sharkey48877892015-03-18 11:27:19 -07003620 @Override
Jeff Sharkeyfa23c5a2011-08-09 21:44:24 -07003621 public void monitor() {
Jeff Sharkey54402792017-09-15 16:05:19 -06003622 try {
3623 mVold.monitor();
3624 } catch (Exception e) {
3625 Slog.wtf(TAG, e);
Paul Lawrence1c62cbb2015-06-03 14:14:52 -07003626 }
Jeff Sharkeyfa23c5a2011-08-09 21:44:24 -07003627 }
Svet Ganov6ee871e2015-07-10 14:29:33 -07003628
Sudheer Shanka2250d562016-11-07 15:41:02 -08003629 private final class StorageManagerInternalImpl extends StorageManagerInternal {
Svet Ganov6ee871e2015-07-10 14:29:33 -07003630 // Not guarded by a lock.
3631 private final CopyOnWriteArrayList<ExternalStorageMountPolicy> mPolicies =
3632 new CopyOnWriteArrayList<>();
3633
3634 @Override
3635 public void addExternalStoragePolicy(ExternalStorageMountPolicy policy) {
3636 // No locking - CopyOnWriteArrayList
3637 mPolicies.add(policy);
3638 }
3639
3640 @Override
3641 public void onExternalStoragePolicyChanged(int uid, String packageName) {
3642 final int mountMode = getExternalStorageMountMode(uid, packageName);
3643 remountUidExternalStorage(uid, mountMode);
3644 }
3645
3646 @Override
3647 public int getExternalStorageMountMode(int uid, String packageName) {
3648 // No locking - CopyOnWriteArrayList
3649 int mountMode = Integer.MAX_VALUE;
3650 for (ExternalStorageMountPolicy policy : mPolicies) {
3651 final int policyMode = policy.getMountMode(uid, packageName);
3652 if (policyMode == Zygote.MOUNT_EXTERNAL_NONE) {
3653 return Zygote.MOUNT_EXTERNAL_NONE;
3654 }
3655 mountMode = Math.min(mountMode, policyMode);
3656 }
3657 if (mountMode == Integer.MAX_VALUE) {
3658 return Zygote.MOUNT_EXTERNAL_NONE;
3659 }
3660 return mountMode;
3661 }
3662
3663 public boolean hasExternalStorage(int uid, String packageName) {
Amith Yamasani2bd5cff2015-07-22 14:42:31 -07003664 // No need to check for system uid. This avoids a deadlock between
3665 // PackageManagerService and AppOpsService.
3666 if (uid == Process.SYSTEM_UID) {
3667 return true;
3668 }
Svet Ganov6ee871e2015-07-10 14:29:33 -07003669 // No locking - CopyOnWriteArrayList
3670 for (ExternalStorageMountPolicy policy : mPolicies) {
3671 final boolean policyHasStorage = policy.hasExternalStorage(uid, packageName);
3672 if (!policyHasStorage) {
3673 return false;
3674 }
3675 }
3676 return true;
3677 }
3678 }
Jeff Sharkeyfa23c5a2011-08-09 21:44:24 -07003679}