blob: 75e8000ea2c12cae6d097ffadafb7811583d2533 [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 Sharkey2d8b4e82013-09-17 17:30:33 -070034import android.app.AppOpsManager;
Jeff Sharkey14cbe522015-07-08 14:06:37 -070035import android.app.IActivityManager;
Jeff Sharkey9bed0702017-01-23 20:37:05 -070036import android.app.usage.StorageStatsManager;
Jeff Sharkeybcd262d2015-06-10 09:41:17 -070037import android.content.BroadcastReceiver;
Kenny Roota02b8b02010-08-05 16:14:17 -070038import android.content.ComponentName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080039import android.content.Context;
40import android.content.Intent;
Jeff Sharkeybcd262d2015-06-10 09:41:17 -070041import android.content.IntentFilter;
Kenny Roota02b8b02010-08-05 16:14:17 -070042import android.content.ServiceConnection;
Jeff Sharkey275e3e42015-04-24 16:10:32 -070043import android.content.pm.IPackageMoveObserver;
44import android.content.pm.PackageManager;
Jeff Sharkey14cbe522015-07-08 14:06:37 -070045import android.content.pm.ProviderInfo;
Jeff Sharkeybcd262d2015-06-10 09:41:17 -070046import android.content.pm.UserInfo;
Elliott Hughesf839b4f2014-09-26 12:30:47 -070047import android.content.res.Configuration;
Kenny Root02c87302010-07-01 08:10:18 -070048import android.content.res.ObbInfo;
Felipe Leme281389a2016-10-10 17:12:20 -070049import android.net.TrafficStats;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080050import android.net.Uri;
Kenny Root02c87302010-07-01 08:10:18 -070051import android.os.Binder;
Jeff Sharkey4c099d02015-05-15 13:45:00 -070052import android.os.DropBoxManager;
Kenny Roota02b8b02010-08-05 16:14:17 -070053import android.os.Environment;
Jeff Sharkeyb049e212012-09-07 23:16:01 -070054import android.os.Environment.UserEnvironment;
Jeff Sharkey48877892015-03-18 11:27:19 -070055import android.os.FileUtils;
Suchi Amalapurapuc42e29e2010-02-22 16:03:53 -080056import android.os.Handler;
Dianne Hackbornefa92b22013-05-03 14:11:43 -070057import android.os.HandlerThread;
Kenny Roota02b8b02010-08-05 16:14:17 -070058import android.os.IBinder;
Jeff Sharkey7e19f532017-11-06 13:54:11 -070059import android.os.IProgressListener;
Jin Qian12690d52017-10-13 18:17:04 -070060import android.os.IStoraged;
Jeff Sharkey1019de92017-09-06 13:47:03 -060061import android.os.IVold;
Jeff Sharkey8058fe62017-09-13 11:50:33 -060062import android.os.IVoldListener;
Jeff Sharkeyb302c542017-09-15 12:57:59 -060063import android.os.IVoldTaskListener;
Daniel Sandler5f27ef42010-03-16 15:42:02 -040064import android.os.Looper;
Suchi Amalapurapuc42e29e2010-02-22 16:03:53 -080065import android.os.Message;
Daichi Hirono9e8d9e22015-11-13 14:37:00 +090066import android.os.ParcelFileDescriptor;
Jeff Sharkey500ce9e2017-02-12 02:39:24 -070067import android.os.ParcelableException;
Jeff Sharkeyb302c542017-09-15 12:57:59 -060068import android.os.PersistableBundle;
Jeff Sharkeyce14cd02015-12-07 15:35:42 -070069import android.os.PowerManager;
Jeff Sharkey9527b222015-06-24 15:24:48 -070070import android.os.Process;
Jeff Sharkey7151a9a2015-04-04 15:22:37 -070071import android.os.RemoteCallbackList;
San Mehat4270e1e2010-01-29 05:32:19 -080072import android.os.RemoteException;
Suchi Amalapurapufd3530f2010-01-18 00:15:59 -080073import android.os.ServiceManager;
Jeff Sharkeyedcdaf62015-07-09 09:45:36 -070074import android.os.SystemClock;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080075import android.os.SystemProperties;
Dianne Hackbornf02b60a2012-08-16 10:48:27 -070076import android.os.UserHandle;
Emily Bernier92aa5a22014-07-07 10:11:48 -040077import android.os.UserManager;
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -070078import android.os.storage.DiskInfo;
Kenny Roota02b8b02010-08-05 16:14:17 -070079import android.os.storage.IObbActionListener;
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -070080import android.os.storage.IStorageEventListener;
Sudheer Shanka2250d562016-11-07 15:41:02 -080081import android.os.storage.IStorageManager;
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -070082import android.os.storage.IStorageShutdownObserver;
Kenny Rootaf9d6672010-10-08 09:21:39 -070083import android.os.storage.OnObbStateChangeListener;
Paul Lawrence46791e72014-04-03 09:10:26 -070084import android.os.storage.StorageManager;
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -070085import android.os.storage.StorageManagerInternal;
Kenny Roota02b8b02010-08-05 16:14:17 -070086import android.os.storage.StorageResultCode;
Mike Lockwood2f6a3882011-05-09 19:08:06 -070087import android.os.storage.StorageVolume;
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -070088import android.os.storage.VolumeInfo;
Jeff Sharkeyb36586a2015-04-27 08:42:28 -070089import android.os.storage.VolumeRecord;
Jeff Sharkey14cbe522015-07-08 14:06:37 -070090import android.provider.MediaStore;
Jeff Sharkeye8a4b662015-06-27 15:43:45 -070091import android.provider.Settings;
Jason parksf7b3cd42011-01-27 09:28:25 -060092import android.text.TextUtils;
Jeff Sharkey1783f142015-04-17 10:52:51 -070093import android.text.format.DateUtils;
Jeff Sharkey48877892015-03-18 11:27:19 -070094import android.util.ArrayMap;
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -070095import android.util.AtomicFile;
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -070096import android.util.Log;
Felipe Leme281389a2016-10-10 17:12:20 -070097import android.util.Pair;
San Mehata5078592010-03-25 09:36:54 -070098import android.util.Slog;
Jeff Sharkeye8a4b662015-06-27 15:43:45 -070099import android.util.TimeUtils;
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700100import android.util.Xml;
Jeff Sharkey48877892015-03-18 11:27:19 -0700101
Jeff Sharkey8b2c3a142012-11-12 11:45:05 -0800102import com.android.internal.annotations.GuardedBy;
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700103import com.android.internal.app.IMediaContainerService;
Daichi Hirono9fb00182016-11-08 14:12:17 +0900104import com.android.internal.os.AppFuseMount;
Jeff Sharkey1019de92017-09-06 13:47:03 -0600105import com.android.internal.os.BackgroundThread;
Daichi Hirono812c95d2017-02-08 16:20:20 +0900106import com.android.internal.os.FuseUnavailableMountException;
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700107import com.android.internal.os.SomeArgs;
Jeff Sharkey9527b222015-06-24 15:24:48 -0700108import com.android.internal.os.Zygote;
Jeff Sharkey48877892015-03-18 11:27:19 -0700109import com.android.internal.util.ArrayUtils;
Jeff Sharkeyfe9a53b2017-03-31 14:08:23 -0600110import com.android.internal.util.DumpUtils;
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700111import com.android.internal.util.FastXmlSerializer;
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -0800112import com.android.internal.util.HexDump;
Jeff Sharkey5aca2b82013-10-16 16:21:54 -0700113import com.android.internal.util.IndentingPrintWriter;
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700114import com.android.internal.util.Preconditions;
Jeff Sharkeyb9fe5372015-12-03 15:23:08 -0700115import com.android.internal.widget.LockPatternUtils;
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700116import com.android.server.pm.PackageManagerService;
Daichi Hirono9fb00182016-11-08 14:12:17 +0900117import com.android.server.storage.AppFuseBridge;
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -0700118
Jeff Sharkey5217cac2015-12-20 15:34:01 -0700119import libcore.io.IoUtils;
120import libcore.util.EmptyArray;
121
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700122import org.xmlpull.v1.XmlPullParser;
123import org.xmlpull.v1.XmlPullParserException;
124import org.xmlpull.v1.XmlSerializer;
125
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700126import java.io.File;
Kenny Root38cf8862010-09-26 14:18:51 -0700127import java.io.FileDescriptor;
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700128import java.io.FileInputStream;
129import java.io.FileNotFoundException;
Christopher Tate7265abe2014-11-21 13:54:45 -0800130import java.io.FileOutputStream;
Kenny Root05105f72010-09-22 17:29:43 -0700131import java.io.IOException;
Kenny Root38cf8862010-09-26 14:18:51 -0700132import java.io.PrintWriter;
Kenny Root3b1abba2010-10-13 15:00:07 -0700133import java.math.BigInteger;
Paul Lawrence8e397362014-01-27 15:22:30 -0800134import java.nio.charset.StandardCharsets;
Kenny Root735de3b2010-09-30 14:11:39 -0700135import java.security.NoSuchAlgorithmException;
Kenny Root3b1abba2010-10-13 15:00:07 -0700136import java.security.spec.InvalidKeySpecException;
137import java.security.spec.KeySpec;
San Mehat22dd86e2010-01-12 12:21:18 -0800138import java.util.ArrayList;
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -0800139import java.util.Arrays;
Kenny Roota02b8b02010-08-05 16:14:17 -0700140import java.util.HashMap;
Kenny Root38cf8862010-09-26 14:18:51 -0700141import java.util.Iterator;
Kenny Roota02b8b02010-08-05 16:14:17 -0700142import java.util.LinkedList;
143import java.util.List;
Elliott Hughesf839b4f2014-09-26 12:30:47 -0700144import java.util.Locale;
Kenny Roota02b8b02010-08-05 16:14:17 -0700145import java.util.Map;
Kenny Root38cf8862010-09-26 14:18:51 -0700146import java.util.Map.Entry;
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700147import java.util.Objects;
Jeff Sharkeyb302c542017-09-15 12:57:59 -0600148import java.util.concurrent.CompletableFuture;
Svet Ganov6ee871e2015-07-10 14:29:33 -0700149import java.util.concurrent.CopyOnWriteArrayList;
Kenny Root51a573c2012-05-17 13:30:28 -0700150import java.util.concurrent.CountDownLatch;
151import java.util.concurrent.TimeUnit;
Jeff Sharkeyedcdaf62015-07-09 09:45:36 -0700152import java.util.concurrent.TimeoutException;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800153
Kenny Root3b1abba2010-10-13 15:00:07 -0700154import javax.crypto.SecretKey;
155import javax.crypto.SecretKeyFactory;
156import javax.crypto.spec.PBEKeySpec;
157
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800158/**
Jeff Sharkey48877892015-03-18 11:27:19 -0700159 * Service responsible for various storage media. Connects to {@code vold} to
160 * watch for and manage dynamically added storage, such as SD cards and USB mass
161 * storage. Also decides how storage should be presented to users on the device.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800162 */
Jeff Sharkey54402792017-09-15 16:05:19 -0600163class StorageManagerService extends IStorageManager.Stub implements Watchdog.Monitor {
Jason parks5af0b912010-11-29 09:05:25 -0600164
Christopher Tated417d622013-08-19 16:14:25 -0700165 // Static direct instance pointer for the tightly-coupled idle service to use
Sudheer Shanka2250d562016-11-07 15:41:02 -0800166 static StorageManagerService sSelf = null;
Christopher Tated417d622013-08-19 16:14:25 -0700167
Jeff Sharkey56e62932015-03-21 20:41:00 -0700168 public static class Lifecycle extends SystemService {
Sudheer Shanka2250d562016-11-07 15:41:02 -0800169 private StorageManagerService mStorageManagerService;
Jeff Sharkey56e62932015-03-21 20:41:00 -0700170
171 public Lifecycle(Context context) {
172 super(context);
173 }
174
175 @Override
176 public void onStart() {
Sudheer Shanka2250d562016-11-07 15:41:02 -0800177 mStorageManagerService = new StorageManagerService(getContext());
178 publishBinderService("mount", mStorageManagerService);
179 mStorageManagerService.start();
Jeff Sharkey56e62932015-03-21 20:41:00 -0700180 }
181
182 @Override
183 public void onBootPhase(int phase) {
184 if (phase == SystemService.PHASE_ACTIVITY_MANAGER_READY) {
Sudheer Shanka2250d562016-11-07 15:41:02 -0800185 mStorageManagerService.systemReady();
Yasuhiro Matsuda87a38b52015-07-24 22:10:16 +0900186 } else if (phase == SystemService.PHASE_BOOT_COMPLETED) {
Sudheer Shanka2250d562016-11-07 15:41:02 -0800187 mStorageManagerService.bootCompleted();
Jeff Sharkey56e62932015-03-21 20:41:00 -0700188 }
189 }
Jeff Sharkey48877892015-03-18 11:27:19 -0700190
191 @Override
Jeff Sharkeyab15c392016-05-05 11:45:01 -0600192 public void onSwitchUser(int userHandle) {
Sudheer Shanka2250d562016-11-07 15:41:02 -0800193 mStorageManagerService.mCurrentUserId = userHandle;
Jeff Sharkeyab15c392016-05-05 11:45:01 -0600194 }
195
196 @Override
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700197 public void onUnlockUser(int userHandle) {
Sudheer Shanka2250d562016-11-07 15:41:02 -0800198 mStorageManagerService.onUnlockUser(userHandle);
Jeff Sharkey48877892015-03-18 11:27:19 -0700199 }
200
201 @Override
202 public void onCleanupUser(int userHandle) {
Sudheer Shanka2250d562016-11-07 15:41:02 -0800203 mStorageManagerService.onCleanupUser(userHandle);
Jeff Sharkey48877892015-03-18 11:27:19 -0700204 }
Jeff Sharkey56e62932015-03-21 20:41:00 -0700205 }
206
Dianne Hackborn40e9f292012-11-27 19:12:23 -0800207 private static final boolean DEBUG_EVENTS = false;
Kenny Rootb7db2722011-01-25 16:39:35 -0800208 private static final boolean DEBUG_OBB = false;
Kenny Root02c87302010-07-01 08:10:18 -0700209
Kenny Root07714d42011-08-17 17:49:28 -0700210 // Disable this since it messes up long-running cryptfs operations.
211 private static final boolean WATCHDOG_ENABLE = false;
212
Jeff Sharkey00455bf2016-11-04 14:45:24 -0600213 /**
214 * Our goal is for all Android devices to be usable as development devices,
215 * which includes the new Direct Boot mode added in N. For devices that
216 * don't have native FBE support, we offer an emulation mode for developer
217 * testing purposes, but if it's prohibitively difficult to support this
218 * mode, it can be disabled for specific products using this flag.
219 */
220 private static final boolean EMULATE_FBE_SUPPORTED = true;
221
Sudheer Shanka2250d562016-11-07 15:41:02 -0800222 private static final String TAG = "StorageManagerService";
Jeff Sharkeye8a4b662015-06-27 15:43:45 -0700223
Jeff Sharkey9756d752015-05-14 21:07:42 -0700224 private static final String TAG_STORAGE_BENCHMARK = "storage_benchmark";
Jeff Sharkeye8a4b662015-06-27 15:43:45 -0700225 private static final String TAG_STORAGE_TRIM = "storage_trim";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800226
Jeff Sharkey275e3e42015-04-24 16:10:32 -0700227 /** Magic value sent by MoveTask.cpp */
228 private static final int MOVE_STATUS_COPY_FINISHED = 82;
229
Jeff Sharkey620b32b2015-04-23 19:36:02 -0700230 private static final int VERSION_INIT = 1;
231 private static final int VERSION_ADD_PRIMARY = 2;
Jeff Sharkeyfced5342015-05-10 14:53:34 -0700232 private static final int VERSION_FIX_PRIMARY = 3;
Jeff Sharkey620b32b2015-04-23 19:36:02 -0700233
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700234 private static final String TAG_VOLUMES = "volumes";
Jeff Sharkey620b32b2015-04-23 19:36:02 -0700235 private static final String ATTR_VERSION = "version";
236 private static final String ATTR_PRIMARY_STORAGE_UUID = "primaryStorageUuid";
Jeff Sharkey4c099d02015-05-15 13:45:00 -0700237 private static final String ATTR_FORCE_ADOPTABLE = "forceAdoptable";
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700238 private static final String TAG_VOLUME = "volume";
239 private static final String ATTR_TYPE = "type";
240 private static final String ATTR_FS_UUID = "fsUuid";
Jeff Sharkey5cc0df22015-06-17 19:44:05 -0700241 private static final String ATTR_PART_GUID = "partGuid";
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700242 private static final String ATTR_NICKNAME = "nickname";
243 private static final String ATTR_USER_FLAGS = "userFlags";
Jeff Sharkeye8a4b662015-06-27 15:43:45 -0700244 private static final String ATTR_CREATED_MILLIS = "createdMillis";
245 private static final String ATTR_LAST_TRIM_MILLIS = "lastTrimMillis";
246 private static final String ATTR_LAST_BENCH_MILLIS = "lastBenchMillis";
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700247
Jeff Sharkeyb36586a2015-04-27 08:42:28 -0700248 private final AtomicFile mSettingsFile;
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700249
Jeff Sharkey48877892015-03-18 11:27:19 -0700250 /**
251 * <em>Never</em> hold the lock while performing downcalls into vold, since
252 * unsolicited events can suddenly appear to update data structures.
253 */
Jeff Sharkey5f3e9342017-03-13 14:53:11 -0600254 private final Object mLock = LockGuard.installNewLock(LockGuard.INDEX_STORAGE);
Jeff Sharkey48877892015-03-18 11:27:19 -0700255
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700256 /** Set of users that we know are unlocked. */
Jeff Sharkey48877892015-03-18 11:27:19 -0700257 @GuardedBy("mLock")
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700258 private int[] mLocalUnlockedUsers = EmptyArray.INT;
259 /** Set of users that system knows are unlocked. */
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -0800260 @GuardedBy("mLock")
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700261 private int[] mSystemUnlockedUsers = EmptyArray.INT;
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700262
263 /** Map from disk ID to disk */
Jeff Sharkey48877892015-03-18 11:27:19 -0700264 @GuardedBy("mLock")
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -0700265 private ArrayMap<String, DiskInfo> mDisks = new ArrayMap<>();
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700266 /** Map from volume ID to disk */
Jeff Sharkey48877892015-03-18 11:27:19 -0700267 @GuardedBy("mLock")
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700268 private final ArrayMap<String, VolumeInfo> mVolumes = new ArrayMap<>();
Jeff Sharkey48877892015-03-18 11:27:19 -0700269
Jeff Sharkeyb36586a2015-04-27 08:42:28 -0700270 /** Map from UUID to record */
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700271 @GuardedBy("mLock")
Jeff Sharkeyb36586a2015-04-27 08:42:28 -0700272 private ArrayMap<String, VolumeRecord> mRecords = new ArrayMap<>();
Jeff Sharkey620b32b2015-04-23 19:36:02 -0700273 @GuardedBy("mLock")
274 private String mPrimaryStorageUuid;
Jeff Sharkey4c099d02015-05-15 13:45:00 -0700275 @GuardedBy("mLock")
276 private boolean mForceAdoptable;
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700277
Jeff Sharkeyeba260d2015-04-19 14:35:16 -0700278 /** Map from disk ID to latches */
279 @GuardedBy("mLock")
280 private ArrayMap<String, CountDownLatch> mDiskScanLatches = new ArrayMap<>();
281
Jeff Sharkey275e3e42015-04-24 16:10:32 -0700282 @GuardedBy("mLock")
283 private IPackageMoveObserver mMoveCallback;
284 @GuardedBy("mLock")
285 private String mMoveTargetUuid;
286
Jeff Sharkeyab15c392016-05-05 11:45:01 -0600287 private volatile int mCurrentUserId = UserHandle.USER_SYSTEM;
288
Daichi Hirono9fb00182016-11-08 14:12:17 +0900289 /** Holding lock for AppFuse business */
290 private final Object mAppFuseLock = new Object();
291
292 @GuardedBy("mAppFuseLock")
293 private int mNextAppFuseName = 0;
294
295 @GuardedBy("mAppFuseLock")
Daichi Hironoe56740d2017-02-02 13:56:45 +0900296 private AppFuseBridge mAppFuseBridge = null;
Daichi Hirono9fb00182016-11-08 14:12:17 +0900297
Jeff Sharkeyef10ee02015-07-05 14:17:27 -0700298 private VolumeInfo findVolumeByIdOrThrow(String id) {
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700299 synchronized (mLock) {
300 final VolumeInfo vol = mVolumes.get(id);
301 if (vol != null) {
302 return vol;
303 }
304 }
305 throw new IllegalArgumentException("No volume found for ID " + id);
306 }
307
Jeff Sharkeyef10ee02015-07-05 14:17:27 -0700308 private String findVolumeIdForPathOrThrow(String path) {
Jeff Sharkey48877892015-03-18 11:27:19 -0700309 synchronized (mLock) {
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -0700310 for (int i = 0; i < mVolumes.size(); i++) {
311 final VolumeInfo vol = mVolumes.valueAt(i);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700312 if (vol.path != null && path.startsWith(vol.path)) {
313 return vol.id;
Jeff Sharkey48877892015-03-18 11:27:19 -0700314 }
315 }
316 }
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700317 throw new IllegalArgumentException("No volume found for path " + path);
Jeff Sharkey48877892015-03-18 11:27:19 -0700318 }
319
Jeff Sharkeye8a4b662015-06-27 15:43:45 -0700320 private VolumeRecord findRecordForPath(String path) {
321 synchronized (mLock) {
322 for (int i = 0; i < mVolumes.size(); i++) {
323 final VolumeInfo vol = mVolumes.valueAt(i);
324 if (vol.path != null && path.startsWith(vol.path)) {
325 return mRecords.get(vol.fsUuid);
326 }
327 }
328 }
329 return null;
330 }
331
332 private String scrubPath(String path) {
333 if (path.startsWith(Environment.getDataDirectory().getAbsolutePath())) {
334 return "internal";
335 }
336 final VolumeRecord rec = findRecordForPath(path);
337 if (rec == null || rec.createdMillis == 0) {
338 return "unknown";
339 } else {
340 return "ext:" + (int) ((System.currentTimeMillis() - rec.createdMillis)
341 / DateUtils.WEEK_IN_MILLIS) + "w";
342 }
343 }
344
Jeff Sharkeyef10ee02015-07-05 14:17:27 -0700345 private @Nullable VolumeInfo findStorageForUuid(String volumeUuid) {
Jeff Sharkey275e3e42015-04-24 16:10:32 -0700346 final StorageManager storage = mContext.getSystemService(StorageManager.class);
347 if (Objects.equals(StorageManager.UUID_PRIVATE_INTERNAL, volumeUuid)) {
Jeff Sharkeyef10ee02015-07-05 14:17:27 -0700348 return storage.findVolumeById(VolumeInfo.ID_EMULATED_INTERNAL);
Jeff Sharkey275e3e42015-04-24 16:10:32 -0700349 } else if (Objects.equals(StorageManager.UUID_PRIMARY_PHYSICAL, volumeUuid)) {
350 return storage.getPrimaryPhysicalVolume();
351 } else {
352 return storage.findEmulatedForPrivate(storage.findVolumeByUuid(volumeUuid));
353 }
354 }
355
Jeff Sharkeye8a4b662015-06-27 15:43:45 -0700356 private boolean shouldBenchmark() {
357 final long benchInterval = Settings.Global.getLong(mContext.getContentResolver(),
358 Settings.Global.STORAGE_BENCHMARK_INTERVAL, DateUtils.WEEK_IN_MILLIS);
Jeff Sharkeye83d8a92015-09-09 14:53:38 -0700359 if (benchInterval == -1) {
360 return false;
361 } else if (benchInterval == 0) {
362 return true;
363 }
364
Jeff Sharkeye8a4b662015-06-27 15:43:45 -0700365 synchronized (mLock) {
366 for (int i = 0; i < mVolumes.size(); i++) {
367 final VolumeInfo vol = mVolumes.valueAt(i);
368 final VolumeRecord rec = mRecords.get(vol.fsUuid);
Jeff Sharkeye83d8a92015-09-09 14:53:38 -0700369 if (vol.isMountedWritable() && rec != null) {
Jeff Sharkeye8a4b662015-06-27 15:43:45 -0700370 final long benchAge = System.currentTimeMillis() - rec.lastBenchMillis;
371 if (benchAge >= benchInterval) {
372 return true;
373 }
374 }
375 }
376 return false;
377 }
378 }
379
Jeff Sharkeyeba260d2015-04-19 14:35:16 -0700380 private CountDownLatch findOrCreateDiskScanLatch(String diskId) {
381 synchronized (mLock) {
382 CountDownLatch latch = mDiskScanLatches.get(diskId);
383 if (latch == null) {
384 latch = new CountDownLatch(1);
385 mDiskScanLatches.put(diskId, latch);
386 }
387 return latch;
388 }
389 }
390
Paul Lawrence8e397362014-01-27 15:22:30 -0800391 /** List of crypto types.
392 * These must match CRYPT_TYPE_XXX in cryptfs.h AND their
393 * corresponding commands in CommandListener.cpp */
394 public static final String[] CRYPTO_TYPES
395 = { "password", "default", "pattern", "pin" };
396
Brian Carlstrom7395a8a2014-04-28 22:11:01 -0700397 private final Context mContext;
Jeff Sharkeycd575992016-03-29 14:12:49 -0600398
Jeff Sharkey1019de92017-09-06 13:47:03 -0600399 private volatile IVold mVold;
Jin Qian12690d52017-10-13 18:17:04 -0700400 private volatile IStoraged mStoraged;
Jeff Sharkey1019de92017-09-06 13:47:03 -0600401
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700402 private volatile boolean mSystemReady = false;
Yasuhiro Matsuda87a38b52015-07-24 22:10:16 +0900403 private volatile boolean mBootCompleted = false;
Jeff Sharkey48877892015-03-18 11:27:19 -0700404 private volatile boolean mDaemonConnected = false;
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700405
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700406 private PackageManagerService mPms;
407
408 private final Callbacks mCallbacks;
Jeff Sharkeyb9fe5372015-12-03 15:23:08 -0700409 private final LockPatternUtils mLockPatternUtils;
Jeff Sharkey48877892015-03-18 11:27:19 -0700410
San Mehat6cdd9c02010-02-09 14:45:20 -0800411 /**
Kenny Root3b1abba2010-10-13 15:00:07 -0700412 * The size of the crypto algorithm key in bits for OBB files. Currently
413 * Twofish is used which takes 128-bit keys.
414 */
415 private static final int CRYPTO_ALGORITHM_KEY_SIZE = 128;
416
417 /**
418 * The number of times to run SHA1 in the PBKDF2 function for OBB files.
419 * 1024 is reasonably secure and not too slow.
420 */
421 private static final int PBKDF2_HASH_ROUNDS = 1024;
422
423 /**
Kenny Roota02b8b02010-08-05 16:14:17 -0700424 * Mounted OBB tracking information. Used to track the current state of all
425 * OBBs.
Kenny Root02c87302010-07-01 08:10:18 -0700426 */
Kenny Root735de3b2010-09-30 14:11:39 -0700427 final private Map<IBinder, List<ObbState>> mObbMounts = new HashMap<IBinder, List<ObbState>>();
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700428
429 /** Map from raw paths to {@link ObbState}. */
Kenny Roota02b8b02010-08-05 16:14:17 -0700430 final private Map<String, ObbState> mObbPathToStateMap = new HashMap<String, ObbState>();
431
Svet Ganov6ee871e2015-07-10 14:29:33 -0700432 // Not guarded by a lock.
Sudheer Shanka2250d562016-11-07 15:41:02 -0800433 private final StorageManagerInternalImpl mStorageManagerInternal
434 = new StorageManagerInternalImpl();
Svet Ganov6ee871e2015-07-10 14:29:33 -0700435
Kenny Roota02b8b02010-08-05 16:14:17 -0700436 class ObbState implements IBinder.DeathRecipient {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700437 public ObbState(String rawPath, String canonicalPath, int callingUid,
Jeff Sharkey41cd6812017-09-11 10:32:17 -0600438 IObbActionListener token, int nonce, String volId) {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700439 this.rawPath = rawPath;
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700440 this.canonicalPath = canonicalPath;
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700441 this.ownerGid = UserHandle.getSharedAppGid(callingUid);
Kenny Rootaf9d6672010-10-08 09:21:39 -0700442 this.token = token;
443 this.nonce = nonce;
Jeff Sharkey41cd6812017-09-11 10:32:17 -0600444 this.volId = volId;
Kenny Roota02b8b02010-08-05 16:14:17 -0700445 }
446
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700447 final String rawPath;
448 final String canonicalPath;
Kenny Roota02b8b02010-08-05 16:14:17 -0700449
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700450 final int ownerGid;
Kenny Roota02b8b02010-08-05 16:14:17 -0700451
Kenny Rootaf9d6672010-10-08 09:21:39 -0700452 // Token of remote Binder caller
453 final IObbActionListener token;
454
455 // Identifier to pass back to the token
456 final int nonce;
Kenny Roota02b8b02010-08-05 16:14:17 -0700457
Jeff Sharkey41cd6812017-09-11 10:32:17 -0600458 String volId;
459
Kenny Root735de3b2010-09-30 14:11:39 -0700460 public IBinder getBinder() {
461 return token.asBinder();
462 }
463
Kenny Roota02b8b02010-08-05 16:14:17 -0700464 @Override
465 public void binderDied() {
466 ObbAction action = new UnmountObbAction(this, true);
467 mObbActionHandler.sendMessage(mObbActionHandler.obtainMessage(OBB_RUN_ACTION, action));
Kenny Root735de3b2010-09-30 14:11:39 -0700468 }
Kenny Roota02b8b02010-08-05 16:14:17 -0700469
Kenny Root5919ac62010-10-05 09:49:40 -0700470 public void link() throws RemoteException {
471 getBinder().linkToDeath(this, 0);
472 }
473
474 public void unlink() {
Kenny Root735de3b2010-09-30 14:11:39 -0700475 getBinder().unlinkToDeath(this, 0);
Kenny Roota02b8b02010-08-05 16:14:17 -0700476 }
Kenny Root38cf8862010-09-26 14:18:51 -0700477
478 @Override
479 public String toString() {
480 StringBuilder sb = new StringBuilder("ObbState{");
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700481 sb.append("rawPath=").append(rawPath);
482 sb.append(",canonicalPath=").append(canonicalPath);
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700483 sb.append(",ownerGid=").append(ownerGid);
484 sb.append(",token=").append(token);
485 sb.append(",binder=").append(getBinder());
Jeff Sharkey41cd6812017-09-11 10:32:17 -0600486 sb.append(",volId=").append(volId);
Kenny Root38cf8862010-09-26 14:18:51 -0700487 sb.append('}');
488 return sb.toString();
489 }
Kenny Roota02b8b02010-08-05 16:14:17 -0700490 }
491
492 // OBB Action Handler
493 final private ObbActionHandler mObbActionHandler;
494
495 // OBB action handler messages
496 private static final int OBB_RUN_ACTION = 1;
497 private static final int OBB_MCS_BOUND = 2;
498 private static final int OBB_MCS_UNBIND = 3;
499 private static final int OBB_MCS_RECONNECT = 4;
Kenny Rootaf9d6672010-10-08 09:21:39 -0700500 private static final int OBB_FLUSH_MOUNT_STATE = 5;
Kenny Roota02b8b02010-08-05 16:14:17 -0700501
502 /*
503 * Default Container Service information
504 */
505 static final ComponentName DEFAULT_CONTAINER_COMPONENT = new ComponentName(
506 "com.android.defcontainer", "com.android.defcontainer.DefaultContainerService");
507
508 final private DefaultContainerConnection mDefContainerConn = new DefaultContainerConnection();
509
510 class DefaultContainerConnection implements ServiceConnection {
Jeff Sharkey48877892015-03-18 11:27:19 -0700511 @Override
Kenny Roota02b8b02010-08-05 16:14:17 -0700512 public void onServiceConnected(ComponentName name, IBinder service) {
513 if (DEBUG_OBB)
514 Slog.i(TAG, "onServiceConnected");
515 IMediaContainerService imcs = IMediaContainerService.Stub.asInterface(service);
516 mObbActionHandler.sendMessage(mObbActionHandler.obtainMessage(OBB_MCS_BOUND, imcs));
517 }
518
Jeff Sharkey48877892015-03-18 11:27:19 -0700519 @Override
Kenny Roota02b8b02010-08-05 16:14:17 -0700520 public void onServiceDisconnected(ComponentName name) {
521 if (DEBUG_OBB)
522 Slog.i(TAG, "onServiceDisconnected");
523 }
Jeff Sharkey54402792017-09-15 16:05:19 -0600524 }
Kenny Roota02b8b02010-08-05 16:14:17 -0700525
526 // Used in the ObbActionHandler
527 private IMediaContainerService mContainerService = null;
Kenny Root02c87302010-07-01 08:10:18 -0700528
Christopher Tate7265abe2014-11-21 13:54:45 -0800529 // Last fstrim operation tracking
530 private static final String LAST_FSTRIM_FILE = "last-fstrim";
531 private final File mLastMaintenanceFile;
532 private long mLastMaintenance;
533
Kenny Root02c87302010-07-01 08:10:18 -0700534 // Handler messages
Jeff Sharkey48877892015-03-18 11:27:19 -0700535 private static final int H_SYSTEM_READY = 1;
536 private static final int H_DAEMON_CONNECTED = 2;
537 private static final int H_SHUTDOWN = 3;
538 private static final int H_FSTRIM = 4;
539 private static final int H_VOLUME_MOUNT = 5;
540 private static final int H_VOLUME_BROADCAST = 6;
Jeff Sharkeyabc3e852015-08-03 14:41:13 -0700541 private static final int H_INTERNAL_BROADCAST = 7;
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700542 private static final int H_VOLUME_UNMOUNT = 8;
Jeff Sharkey5a9bb742015-11-03 10:15:57 -0800543 private static final int H_PARTITION_FORGET = 9;
544 private static final int H_RESET = 10;
Suchi Amalapurapu6ffce2e2010-03-08 14:48:40 -0800545
Sudheer Shanka2250d562016-11-07 15:41:02 -0800546 class StorageManagerServiceHandler extends Handler {
547 public StorageManagerServiceHandler(Looper looper) {
Jeff Sharkey48877892015-03-18 11:27:19 -0700548 super(looper);
Daniel Sandler5f27ef42010-03-16 15:42:02 -0400549 }
550
Jason parks5af0b912010-11-29 09:05:25 -0600551 @Override
Suchi Amalapurapuc42e29e2010-02-22 16:03:53 -0800552 public void handleMessage(Message msg) {
553 switch (msg.what) {
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700554 case H_SYSTEM_READY: {
Jeff Sharkey48877892015-03-18 11:27:19 -0700555 handleSystemReady();
556 break;
557 }
558 case H_DAEMON_CONNECTED: {
559 handleDaemonConnected();
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700560 break;
561 }
Christopher Tated417d622013-08-19 16:14:25 -0700562 case H_FSTRIM: {
Christopher Tated417d622013-08-19 16:14:25 -0700563 Slog.i(TAG, "Running fstrim idle maintenance");
Christopher Tate7265abe2014-11-21 13:54:45 -0800564
565 // Remember when we kicked it off
566 try {
567 mLastMaintenance = System.currentTimeMillis();
568 mLastMaintenanceFile.setLastModified(mLastMaintenance);
569 } catch (Exception e) {
570 Slog.e(TAG, "Unable to record last fstrim!");
571 }
572
Jeff Sharkeyb302c542017-09-15 12:57:59 -0600573 // TODO: Reintroduce shouldBenchmark() test
Jeff Sharkey7e19f532017-11-06 13:54:11 -0700574 fstrim(0, null);
Christopher Tate7265abe2014-11-21 13:54:45 -0800575
Christopher Tated417d622013-08-19 16:14:25 -0700576 // invoke the completion callback, if any
Jeff Sharkeye8a4b662015-06-27 15:43:45 -0700577 // TODO: fstrim is non-blocking, so remove this useless callback
Christopher Tated417d622013-08-19 16:14:25 -0700578 Runnable callback = (Runnable) msg.obj;
579 if (callback != null) {
580 callback.run();
581 }
582 break;
583 }
Jeff Sharkey48877892015-03-18 11:27:19 -0700584 case H_SHUTDOWN: {
Sudheer Shanka2250d562016-11-07 15:41:02 -0800585 final IStorageShutdownObserver obs = (IStorageShutdownObserver) msg.obj;
Jeff Sharkey48877892015-03-18 11:27:19 -0700586 boolean success = false;
587 try {
Jeff Sharkey54402792017-09-15 16:05:19 -0600588 mVold.shutdown();
589 success = true;
Jeff Sharkeyace874b2017-09-07 15:27:33 -0600590 } catch (Exception e) {
591 Slog.wtf(TAG, e);
Jeff Sharkey48877892015-03-18 11:27:19 -0700592 }
593 if (obs != null) {
594 try {
595 obs.onShutDownComplete(success ? 0 : -1);
Jeff Sharkeyace874b2017-09-07 15:27:33 -0600596 } catch (Exception ignored) {
Jeff Sharkey48877892015-03-18 11:27:19 -0700597 }
598 }
599 break;
600 }
601 case H_VOLUME_MOUNT: {
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -0700602 final VolumeInfo vol = (VolumeInfo) msg.obj;
Jeff Sharkey2e606d72015-07-27 14:19:54 -0700603 if (isMountDisallowed(vol)) {
604 Slog.i(TAG, "Ignoring mount " + vol.getId() + " due to policy");
605 break;
606 }
Jeff Sharkey48877892015-03-18 11:27:19 -0700607 try {
Jeff Sharkey54402792017-09-15 16:05:19 -0600608 mVold.mount(vol.id, vol.mountFlags, vol.mountUserId);
Jeff Sharkeyace874b2017-09-07 15:27:33 -0600609 } catch (Exception e) {
610 Slog.wtf(TAG, e);
Jeff Sharkey48877892015-03-18 11:27:19 -0700611 }
612 break;
613 }
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700614 case H_VOLUME_UNMOUNT: {
615 final VolumeInfo vol = (VolumeInfo) msg.obj;
616 unmount(vol.getId());
617 break;
618 }
Jeff Sharkey48877892015-03-18 11:27:19 -0700619 case H_VOLUME_BROADCAST: {
620 final StorageVolume userVol = (StorageVolume) msg.obj;
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700621 final String envState = userVol.getState();
622 Slog.d(TAG, "Volume " + userVol.getId() + " broadcasting " + envState + " to "
Jeff Sharkey48877892015-03-18 11:27:19 -0700623 + userVol.getOwner());
624
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700625 final String action = VolumeInfo.getBroadcastForEnvironment(envState);
Jeff Sharkey48877892015-03-18 11:27:19 -0700626 if (action != null) {
627 final Intent intent = new Intent(action,
628 Uri.fromFile(userVol.getPathFile()));
629 intent.putExtra(StorageVolume.EXTRA_STORAGE_VOLUME, userVol);
Jeff Sharkey082f83b2017-03-26 14:34:47 -0600630 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT
631 | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
Jeff Sharkey48877892015-03-18 11:27:19 -0700632 mContext.sendBroadcastAsUser(intent, userVol.getOwner());
633 }
634 break;
635 }
Jeff Sharkeyabc3e852015-08-03 14:41:13 -0700636 case H_INTERNAL_BROADCAST: {
637 // Internal broadcasts aimed at system components, not for
638 // third-party apps.
639 final Intent intent = (Intent) msg.obj;
640 mContext.sendBroadcastAsUser(intent, UserHandle.ALL,
641 android.Manifest.permission.WRITE_MEDIA_STORAGE);
Jeff Sharkey5a9bb742015-11-03 10:15:57 -0800642 break;
643 }
644 case H_PARTITION_FORGET: {
Jeff Sharkeydb4b6192017-10-24 11:08:50 -0600645 final VolumeRecord rec = (VolumeRecord) msg.obj;
646 forgetPartition(rec.partGuid, rec.fsUuid);
Jeff Sharkey5a9bb742015-11-03 10:15:57 -0800647 break;
648 }
649 case H_RESET: {
650 resetIfReadyAndConnected();
651 break;
Jeff Sharkeyabc3e852015-08-03 14:41:13 -0700652 }
Suchi Amalapurapuc42e29e2010-02-22 16:03:53 -0800653 }
654 }
Jeff Sharkey48877892015-03-18 11:27:19 -0700655 }
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700656
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700657 private final Handler mHandler;
Suchi Amalapurapuc42e29e2010-02-22 16:03:53 -0800658
Jeff Sharkeybcd262d2015-06-10 09:41:17 -0700659 private BroadcastReceiver mUserReceiver = new BroadcastReceiver() {
660 @Override
661 public void onReceive(Context context, Intent intent) {
662 final String action = intent.getAction();
663 final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700664 Preconditions.checkArgument(userId >= 0);
Jeff Sharkeybcd262d2015-06-10 09:41:17 -0700665
666 try {
667 if (Intent.ACTION_USER_ADDED.equals(action)) {
668 final UserManager um = mContext.getSystemService(UserManager.class);
669 final int userSerialNumber = um.getUserSerialNumber(userId);
Jeff Sharkey54402792017-09-15 16:05:19 -0600670 mVold.onUserAdded(userId, userSerialNumber);
Jeff Sharkeybcd262d2015-06-10 09:41:17 -0700671 } else if (Intent.ACTION_USER_REMOVED.equals(action)) {
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700672 synchronized (mVolumes) {
673 final int size = mVolumes.size();
674 for (int i = 0; i < size; i++) {
675 final VolumeInfo vol = mVolumes.valueAt(i);
676 if (vol.mountUserId == userId) {
677 vol.mountUserId = UserHandle.USER_NULL;
678 mHandler.obtainMessage(H_VOLUME_UNMOUNT, vol).sendToTarget();
679 }
680 }
681 }
Jeff Sharkey54402792017-09-15 16:05:19 -0600682 mVold.onUserRemoved(userId);
Jeff Sharkeybcd262d2015-06-10 09:41:17 -0700683 }
Jeff Sharkeyace874b2017-09-07 15:27:33 -0600684 } catch (Exception e) {
685 Slog.wtf(TAG, e);
Jeff Sharkeybcd262d2015-06-10 09:41:17 -0700686 }
687 }
688 };
689
Jeff Sharkeyedcdaf62015-07-09 09:45:36 -0700690 private void waitForLatch(CountDownLatch latch, String condition, long timeoutMillis)
691 throws TimeoutException {
692 final long startMillis = SystemClock.elapsedRealtime();
Jeff Sharkeyeba260d2015-04-19 14:35:16 -0700693 while (true) {
Kenny Root51a573c2012-05-17 13:30:28 -0700694 try {
695 if (latch.await(5000, TimeUnit.MILLISECONDS)) {
San Mehat207e5382010-02-04 20:46:54 -0800696 return;
Kenny Root51a573c2012-05-17 13:30:28 -0700697 } else {
698 Slog.w(TAG, "Thread " + Thread.currentThread().getName()
Jeff Sharkey48877892015-03-18 11:27:19 -0700699 + " still waiting for " + condition + "...");
San Mehat207e5382010-02-04 20:46:54 -0800700 }
Kenny Root51a573c2012-05-17 13:30:28 -0700701 } catch (InterruptedException e) {
Jeff Sharkeyeba260d2015-04-19 14:35:16 -0700702 Slog.w(TAG, "Interrupt while waiting for " + condition);
San Mehat207e5382010-02-04 20:46:54 -0800703 }
Jeff Sharkeyedcdaf62015-07-09 09:45:36 -0700704 if (timeoutMillis > 0 && SystemClock.elapsedRealtime() > startMillis + timeoutMillis) {
705 throw new TimeoutException("Thread " + Thread.currentThread().getName()
706 + " gave up waiting for " + condition + " after " + timeoutMillis + "ms");
707 }
San Mehat207e5382010-02-04 20:46:54 -0800708 }
San Mehat1f6301e2010-01-07 22:40:27 -0800709 }
Kenny Root02c87302010-07-01 08:10:18 -0700710
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700711 private void handleSystemReady() {
Jeff Sharkey8924e872015-11-30 12:52:10 -0700712 initIfReadyAndConnected();
Jeff Sharkey5a9bb742015-11-03 10:15:57 -0800713 resetIfReadyAndConnected();
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700714
Jeff Sharkey48877892015-03-18 11:27:19 -0700715 // Start scheduling nominally-daily fstrim operations
Christopher Tate115afda2014-06-06 19:06:26 -0700716 MountServiceIdler.scheduleIdlePass(mContext);
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700717 }
718
Jeff Sharkey14cbe522015-07-08 14:06:37 -0700719 /**
720 * MediaProvider has a ton of code that makes assumptions about storage
721 * paths never changing, so we outright kill them to pick up new state.
722 */
723 @Deprecated
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700724 private void killMediaProvider(List<UserInfo> users) {
725 if (users == null) return;
726
Jeff Sharkeyb3cf9532015-07-17 15:12:39 -0700727 final long token = Binder.clearCallingIdentity();
728 try {
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700729 for (UserInfo user : users) {
730 // System user does not have media provider, so skip.
731 if (user.isSystemOnly()) continue;
732
Jeff Sharkey2a9e3f82015-12-18 10:57:58 -0700733 final ProviderInfo provider = mPms.resolveContentProvider(MediaStore.AUTHORITY,
Jeff Sharkey8a372a02016-03-16 16:25:45 -0600734 PackageManager.MATCH_DIRECT_BOOT_AWARE
735 | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
736 user.id);
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700737 if (provider != null) {
Sudheer Shankadc589ac2016-11-10 15:30:17 -0800738 final IActivityManager am = ActivityManager.getService();
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700739 try {
Jeff Sharkey85f449e2016-06-23 09:26:00 -0600740 am.killApplication(provider.applicationInfo.packageName,
741 UserHandle.getAppId(provider.applicationInfo.uid),
742 UserHandle.USER_ALL, "vold reset");
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700743 // We only need to run this once. It will kill all users' media processes.
744 break;
745 } catch (RemoteException e) {
746 }
Jeff Sharkeyb3cf9532015-07-17 15:12:39 -0700747 }
Jeff Sharkey14cbe522015-07-08 14:06:37 -0700748 }
Jeff Sharkeyb3cf9532015-07-17 15:12:39 -0700749 } finally {
750 Binder.restoreCallingIdentity(token);
Jeff Sharkey14cbe522015-07-08 14:06:37 -0700751 }
752 }
753
Jeff Sharkey5a9bb742015-11-03 10:15:57 -0800754 private void addInternalVolumeLocked() {
Amith Yamasania7892482015-08-07 11:09:05 -0700755 // Create a stub volume that represents internal storage
756 final VolumeInfo internal = new VolumeInfo(VolumeInfo.ID_PRIVATE_INTERNAL,
757 VolumeInfo.TYPE_PRIVATE, null, null);
758 internal.state = VolumeInfo.STATE_MOUNTED;
759 internal.path = Environment.getDataDirectory().getAbsolutePath();
760 mVolumes.put(internal.id, internal);
761 }
762
Jeff Sharkey8924e872015-11-30 12:52:10 -0700763 private void initIfReadyAndConnected() {
764 Slog.d(TAG, "Thinking about init, mSystemReady=" + mSystemReady
765 + ", mDaemonConnected=" + mDaemonConnected);
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700766 if (mSystemReady && mDaemonConnected
Paul Lawrence20be5d62016-02-26 13:51:17 -0800767 && !StorageManager.isFileEncryptedNativeOnly()) {
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700768 // When booting a device without native support, make sure that our
769 // user directories are locked or unlocked based on the current
770 // emulation status.
Paul Lawrence20be5d62016-02-26 13:51:17 -0800771 final boolean initLocked = StorageManager.isFileEncryptedEmulatedOnly();
Paul Crowleyd94ab732016-02-15 06:44:51 +0000772 Slog.d(TAG, "Setting up emulation state, initlocked=" + initLocked);
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700773 final List<UserInfo> users = mContext.getSystemService(UserManager.class).getUsers();
Jeff Sharkey8924e872015-11-30 12:52:10 -0700774 for (UserInfo user : users) {
775 try {
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700776 if (initLocked) {
Jeff Sharkey54402792017-09-15 16:05:19 -0600777 mVold.lockUserKey(user.id);
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700778 } else {
Jeff Sharkey54402792017-09-15 16:05:19 -0600779 mVold.unlockUserKey(user.id, user.serialNumber, encodeBytes(null),
780 encodeBytes(null));
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700781 }
Jeff Sharkey43e12112017-09-12 16:31:45 -0600782 } catch (Exception e) {
783 Slog.wtf(TAG, e);
Jeff Sharkey8924e872015-11-30 12:52:10 -0700784 }
785 }
786 }
787 }
788
Jeff Sharkey5a9bb742015-11-03 10:15:57 -0800789 private void resetIfReadyAndConnected() {
Jeff Sharkey48877892015-03-18 11:27:19 -0700790 Slog.d(TAG, "Thinking about reset, mSystemReady=" + mSystemReady
791 + ", mDaemonConnected=" + mDaemonConnected);
792 if (mSystemReady && mDaemonConnected) {
Jeff Sharkey5a9bb742015-11-03 10:15:57 -0800793 final List<UserInfo> users = mContext.getSystemService(UserManager.class).getUsers();
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700794 killMediaProvider(users);
Jeff Sharkey14cbe522015-07-08 14:06:37 -0700795
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700796 final int[] systemUnlockedUsers;
Jeff Sharkey5a9bb742015-11-03 10:15:57 -0800797 synchronized (mLock) {
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700798 systemUnlockedUsers = mSystemUnlockedUsers;
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700799
Jeff Sharkey5a9bb742015-11-03 10:15:57 -0800800 mDisks.clear();
801 mVolumes.clear();
802
803 addInternalVolumeLocked();
804 }
Jeff Sharkey59d577a2015-04-11 21:27:21 -0700805
Jeff Sharkey48877892015-03-18 11:27:19 -0700806 try {
Jeff Sharkey54402792017-09-15 16:05:19 -0600807 mVold.reset();
Jeff Sharkeybcd262d2015-06-10 09:41:17 -0700808
809 // Tell vold about all existing and started users
Jeff Sharkeybcd262d2015-06-10 09:41:17 -0700810 for (UserInfo user : users) {
Jeff Sharkey54402792017-09-15 16:05:19 -0600811 mVold.onUserAdded(user.id, user.serialNumber);
Jeff Sharkeybcd262d2015-06-10 09:41:17 -0700812 }
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700813 for (int userId : systemUnlockedUsers) {
Jeff Sharkey54402792017-09-15 16:05:19 -0600814 mVold.onUserStarted(userId);
Jin Qian12690d52017-10-13 18:17:04 -0700815 mStoraged.onUserStarted(userId);
Jeff Sharkey50a05452015-04-29 11:24:52 -0700816 }
Jeff Sharkeyace874b2017-09-07 15:27:33 -0600817 } catch (Exception e) {
818 Slog.wtf(TAG, e);
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700819 }
820 }
Jeff Sharkey48877892015-03-18 11:27:19 -0700821 }
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700822
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700823 private void onUnlockUser(int userId) {
824 Slog.d(TAG, "onUnlockUser " + userId);
Jeff Sharkey48877892015-03-18 11:27:19 -0700825
826 // We purposefully block here to make sure that user-specific
827 // staging area is ready so it's ready for zygote-forked apps to
828 // bind mount against.
829 try {
Jeff Sharkey54402792017-09-15 16:05:19 -0600830 mVold.onUserStarted(userId);
Jin Qian12690d52017-10-13 18:17:04 -0700831 mStoraged.onUserStarted(userId);
Jeff Sharkeyace874b2017-09-07 15:27:33 -0600832 } catch (Exception e) {
833 Slog.wtf(TAG, e);
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700834 }
Jeff Sharkey48877892015-03-18 11:27:19 -0700835
836 // Record user as started so newly mounted volumes kick off events
837 // correctly, then synthesize events for any already-mounted volumes.
yuanhuihuiefd1f122016-07-13 21:21:03 +0800838 synchronized (mLock) {
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -0700839 for (int i = 0; i < mVolumes.size(); i++) {
840 final VolumeInfo vol = mVolumes.valueAt(i);
Jeff Sharkey46349872015-07-28 10:49:47 -0700841 if (vol.isVisibleForRead(userId) && vol.isMountedReadable()) {
Svet Ganov6ee871e2015-07-10 14:29:33 -0700842 final StorageVolume userVol = vol.buildStorageVolume(mContext, userId, false);
Jeff Sharkey48877892015-03-18 11:27:19 -0700843 mHandler.obtainMessage(H_VOLUME_BROADCAST, userVol).sendToTarget();
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700844
Jeff Sharkey27de30d2015-04-18 16:20:27 -0700845 final String envState = VolumeInfo.getEnvironmentForState(vol.getState());
846 mCallbacks.notifyStorageStateChanged(userVol.getPath(), envState, envState);
Jeff Sharkey48877892015-03-18 11:27:19 -0700847 }
848 }
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700849 mSystemUnlockedUsers = ArrayUtils.appendInt(mSystemUnlockedUsers, userId);
Jeff Sharkey48877892015-03-18 11:27:19 -0700850 }
851 }
852
853 private void onCleanupUser(int userId) {
854 Slog.d(TAG, "onCleanupUser " + userId);
855
856 try {
Jeff Sharkey54402792017-09-15 16:05:19 -0600857 mVold.onUserStopped(userId);
Jin Qian12690d52017-10-13 18:17:04 -0700858 mStoraged.onUserStopped(userId);
Jeff Sharkeyace874b2017-09-07 15:27:33 -0600859 } catch (Exception e) {
860 Slog.wtf(TAG, e);
Jeff Sharkey48877892015-03-18 11:27:19 -0700861 }
862
yuanhuihuiefd1f122016-07-13 21:21:03 +0800863 synchronized (mLock) {
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700864 mSystemUnlockedUsers = ArrayUtils.removeInt(mSystemUnlockedUsers, userId);
Jeff Sharkey48877892015-03-18 11:27:19 -0700865 }
866 }
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700867
Christopher Tated417d622013-08-19 16:14:25 -0700868 void runIdleMaintenance(Runnable callback) {
869 mHandler.sendMessage(mHandler.obtainMessage(H_FSTRIM, callback));
870 }
871
Christopher Tate7265abe2014-11-21 13:54:45 -0800872 // Binder entry point for kicking off an immediate fstrim
873 @Override
874 public void runMaintenance() {
Jeff Sharkey48877892015-03-18 11:27:19 -0700875 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
Christopher Tate7265abe2014-11-21 13:54:45 -0800876 runIdleMaintenance(null);
877 }
878
879 @Override
880 public long lastMaintenance() {
881 return mLastMaintenance;
882 }
883
San Mehat4270e1e2010-01-29 05:32:19 -0800884 public void onDaemonConnected() {
Jeff Sharkey48877892015-03-18 11:27:19 -0700885 mDaemonConnected = true;
886 mHandler.obtainMessage(H_DAEMON_CONNECTED).sendToTarget();
887 }
888
889 private void handleDaemonConnected() {
Jeff Sharkey8924e872015-11-30 12:52:10 -0700890 initIfReadyAndConnected();
Jeff Sharkey5a9bb742015-11-03 10:15:57 -0800891 resetIfReadyAndConnected();
Jeff Sharkey48877892015-03-18 11:27:19 -0700892
Jeff Sharkey48877892015-03-18 11:27:19 -0700893 // On an encrypted device we can't see system properties yet, so pull
894 // the system locale out of the mount service.
895 if ("".equals(SystemProperties.get("vold.encrypt_progress"))) {
896 copyLocaleFromMountService();
897 }
San Mehat4270e1e2010-01-29 05:32:19 -0800898 }
899
Elliott Hughesf839b4f2014-09-26 12:30:47 -0700900 private void copyLocaleFromMountService() {
901 String systemLocale;
902 try {
903 systemLocale = getField(StorageManager.SYSTEM_LOCALE_KEY);
904 } catch (RemoteException e) {
905 return;
906 }
907 if (TextUtils.isEmpty(systemLocale)) {
908 return;
909 }
910
911 Slog.d(TAG, "Got locale " + systemLocale + " from mount service");
912 Locale locale = Locale.forLanguageTag(systemLocale);
913 Configuration config = new Configuration();
914 config.setLocale(locale);
915 try {
Sudheer Shankadc589ac2016-11-10 15:30:17 -0800916 ActivityManager.getService().updatePersistentConfiguration(config);
Elliott Hughesf839b4f2014-09-26 12:30:47 -0700917 } catch (RemoteException e) {
918 Slog.e(TAG, "Error setting system locale from mount service", e);
919 }
Elliott Hughes9c33f282014-10-13 12:39:56 -0700920
921 // Temporary workaround for http://b/17945169.
922 Slog.d(TAG, "Setting system properties to " + systemLocale + " from mount service");
Narayan Kamathd30dbb82015-01-15 14:48:15 +0000923 SystemProperties.set("persist.sys.locale", locale.toLanguageTag());
Elliott Hughesf839b4f2014-09-26 12:30:47 -0700924 }
925
Jeff Sharkey8058fe62017-09-13 11:50:33 -0600926 private final IVoldListener mListener = new IVoldListener.Stub() {
927 @Override
928 public void onDiskCreated(String diskId, int flags) {
929 synchronized (mLock) {
930 if (SystemProperties.getBoolean(StorageManager.PROP_FORCE_ADOPTABLE, false)
931 || mForceAdoptable) {
932 flags |= DiskInfo.FLAG_ADOPTABLE;
933 }
934 // Adoptable storage isn't currently supported on FBE devices
935 if (StorageManager.isFileEncryptedNativeOnly()
936 && !SystemProperties.getBoolean(StorageManager.PROP_ADOPTABLE_FBE, false)) {
937 flags &= ~DiskInfo.FLAG_ADOPTABLE;
938 }
939 mDisks.put(diskId, new DiskInfo(diskId, flags));
940 }
941 }
942
943 @Override
944 public void onDiskScanned(String diskId) {
945 synchronized (mLock) {
946 final DiskInfo disk = mDisks.get(diskId);
947 if (disk != null) {
948 onDiskScannedLocked(disk);
949 }
950 }
951 }
952
953 @Override
954 public void onDiskMetadataChanged(String diskId, long sizeBytes, String label,
955 String sysPath) {
956 synchronized (mLock) {
957 final DiskInfo disk = mDisks.get(diskId);
958 if (disk != null) {
959 disk.size = sizeBytes;
960 disk.label = label;
961 disk.sysPath = sysPath;
962 }
963 }
964 }
965
966 @Override
967 public void onDiskDestroyed(String diskId) {
968 synchronized (mLock) {
969 final DiskInfo disk = mDisks.remove(diskId);
970 if (disk != null) {
971 mCallbacks.notifyDiskDestroyed(disk);
972 }
973 }
974 }
975
976 @Override
977 public void onVolumeCreated(String volId, int type, String diskId, String partGuid) {
978 synchronized (mLock) {
979 final DiskInfo disk = mDisks.get(diskId);
980 final VolumeInfo vol = new VolumeInfo(volId, type, disk, partGuid);
981 mVolumes.put(volId, vol);
982 onVolumeCreatedLocked(vol);
983 }
984 }
985
986 @Override
987 public void onVolumeStateChanged(String volId, int state) {
988 synchronized (mLock) {
989 final VolumeInfo vol = mVolumes.get(volId);
990 if (vol != null) {
991 final int oldState = vol.state;
992 final int newState = state;
993 vol.state = newState;
994 onVolumeStateChangedLocked(vol, oldState, newState);
995 }
996 }
997 }
998
999 @Override
1000 public void onVolumeMetadataChanged(String volId, String fsType, String fsUuid,
1001 String fsLabel) {
1002 synchronized (mLock) {
1003 final VolumeInfo vol = mVolumes.get(volId);
1004 if (vol != null) {
1005 vol.fsType = fsType;
1006 vol.fsUuid = fsUuid;
1007 vol.fsLabel = fsLabel;
1008 }
1009 }
1010 }
1011
1012 @Override
1013 public void onVolumePathChanged(String volId, String path) {
1014 synchronized (mLock) {
1015 final VolumeInfo vol = mVolumes.get(volId);
1016 if (vol != null) {
1017 vol.path = path;
1018 }
1019 }
1020 }
1021
1022 @Override
1023 public void onVolumeInternalPathChanged(String volId, String internalPath) {
1024 synchronized (mLock) {
1025 final VolumeInfo vol = mVolumes.get(volId);
1026 if (vol != null) {
1027 vol.internalPath = internalPath;
1028 }
1029 }
1030 }
1031
1032 @Override
1033 public void onVolumeDestroyed(String volId) {
1034 synchronized (mLock) {
1035 mVolumes.remove(volId);
1036 }
1037 }
1038 };
1039
Jeff Sharkeyeba260d2015-04-19 14:35:16 -07001040 private void onDiskScannedLocked(DiskInfo disk) {
Jeff Sharkey620b32b2015-04-23 19:36:02 -07001041 int volumeCount = 0;
Jeff Sharkeyeba260d2015-04-19 14:35:16 -07001042 for (int i = 0; i < mVolumes.size(); i++) {
1043 final VolumeInfo vol = mVolumes.valueAt(i);
1044 if (Objects.equals(disk.id, vol.getDiskId())) {
Jeff Sharkey620b32b2015-04-23 19:36:02 -07001045 volumeCount++;
Jeff Sharkeyeba260d2015-04-19 14:35:16 -07001046 }
1047 }
1048
Jeff Sharkeyc7acac62015-06-12 16:16:56 -07001049 final Intent intent = new Intent(DiskInfo.ACTION_DISK_SCANNED);
Jeff Sharkey7732e1e2016-03-30 17:14:23 -06001050 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT
1051 | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
Jeff Sharkeyc7acac62015-06-12 16:16:56 -07001052 intent.putExtra(DiskInfo.EXTRA_DISK_ID, disk.id);
1053 intent.putExtra(DiskInfo.EXTRA_VOLUME_COUNT, volumeCount);
Jeff Sharkeyabc3e852015-08-03 14:41:13 -07001054 mHandler.obtainMessage(H_INTERNAL_BROADCAST, intent).sendToTarget();
Jeff Sharkeyc7acac62015-06-12 16:16:56 -07001055
1056 final CountDownLatch latch = mDiskScanLatches.remove(disk.id);
1057 if (latch != null) {
1058 latch.countDown();
1059 }
1060
Jeff Sharkeyf5a6bd72015-05-19 14:42:38 -07001061 disk.volumeCount = volumeCount;
Jeff Sharkey620b32b2015-04-23 19:36:02 -07001062 mCallbacks.notifyDiskScanned(disk, volumeCount);
Jeff Sharkeyeba260d2015-04-19 14:35:16 -07001063 }
1064
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07001065 private void onVolumeCreatedLocked(VolumeInfo vol) {
Jeff Sharkey6855c482016-03-31 14:34:38 -06001066 if (mPms.isOnlyCoreApps()) {
1067 Slog.d(TAG, "System booted in core-only mode; ignoring volume " + vol.getId());
1068 return;
1069 }
1070
Jeff Sharkey275e3e42015-04-24 16:10:32 -07001071 if (vol.type == VolumeInfo.TYPE_EMULATED) {
1072 final StorageManager storage = mContext.getSystemService(StorageManager.class);
1073 final VolumeInfo privateVol = storage.findPrivateForEmulated(vol);
1074
1075 if (Objects.equals(StorageManager.UUID_PRIVATE_INTERNAL, mPrimaryStorageUuid)
1076 && VolumeInfo.ID_PRIVATE_INTERNAL.equals(privateVol.id)) {
1077 Slog.v(TAG, "Found primary storage at " + vol);
1078 vol.mountFlags |= VolumeInfo.MOUNT_FLAG_PRIMARY;
1079 vol.mountFlags |= VolumeInfo.MOUNT_FLAG_VISIBLE;
1080 mHandler.obtainMessage(H_VOLUME_MOUNT, vol).sendToTarget();
1081
1082 } else if (Objects.equals(privateVol.fsUuid, mPrimaryStorageUuid)) {
1083 Slog.v(TAG, "Found primary storage at " + vol);
1084 vol.mountFlags |= VolumeInfo.MOUNT_FLAG_PRIMARY;
1085 vol.mountFlags |= VolumeInfo.MOUNT_FLAG_VISIBLE;
1086 mHandler.obtainMessage(H_VOLUME_MOUNT, vol).sendToTarget();
1087 }
Jeff Sharkeyb049e212012-09-07 23:16:01 -07001088
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07001089 } else if (vol.type == VolumeInfo.TYPE_PUBLIC) {
Jeff Sharkey275e3e42015-04-24 16:10:32 -07001090 // TODO: only look at first public partition
1091 if (Objects.equals(StorageManager.UUID_PRIMARY_PHYSICAL, mPrimaryStorageUuid)
1092 && vol.disk.isDefaultPrimary()) {
1093 Slog.v(TAG, "Found primary storage at " + vol);
Jeff Sharkey7e92ef32015-04-17 17:35:07 -07001094 vol.mountFlags |= VolumeInfo.MOUNT_FLAG_PRIMARY;
1095 vol.mountFlags |= VolumeInfo.MOUNT_FLAG_VISIBLE;
San Mehat4270e1e2010-01-29 05:32:19 -08001096 }
Jeff Sharkey7e92ef32015-04-17 17:35:07 -07001097
1098 // Adoptable public disks are visible to apps, since they meet
1099 // public API requirement of being in a stable location.
Jeff Sharkey275e3e42015-04-24 16:10:32 -07001100 if (vol.disk.isAdoptable()) {
Jeff Sharkey7e92ef32015-04-17 17:35:07 -07001101 vol.mountFlags |= VolumeInfo.MOUNT_FLAG_VISIBLE;
1102 }
1103
Jeff Sharkeyab15c392016-05-05 11:45:01 -06001104 vol.mountUserId = mCurrentUserId;
Jeff Sharkey48877892015-03-18 11:27:19 -07001105 mHandler.obtainMessage(H_VOLUME_MOUNT, vol).sendToTarget();
San Mehat4270e1e2010-01-29 05:32:19 -08001106
Jeff Sharkeyb2b9ab82015-04-05 21:10:42 -07001107 } else if (vol.type == VolumeInfo.TYPE_PRIVATE) {
1108 mHandler.obtainMessage(H_VOLUME_MOUNT, vol).sendToTarget();
1109
San Mehat4270e1e2010-01-29 05:32:19 -08001110 } else {
Jeff Sharkey48877892015-03-18 11:27:19 -07001111 Slog.d(TAG, "Skipping automatic mounting of " + vol);
San Mehat4270e1e2010-01-29 05:32:19 -08001112 }
1113 }
1114
Jeff Sharkeye6c04f92015-04-18 21:38:05 -07001115 private boolean isBroadcastWorthy(VolumeInfo vol) {
1116 switch (vol.getType()) {
Jeff Sharkeyc7acac62015-06-12 16:16:56 -07001117 case VolumeInfo.TYPE_PRIVATE:
Jeff Sharkeye6c04f92015-04-18 21:38:05 -07001118 case VolumeInfo.TYPE_PUBLIC:
1119 case VolumeInfo.TYPE_EMULATED:
1120 break;
1121 default:
1122 return false;
1123 }
1124
1125 switch (vol.getState()) {
1126 case VolumeInfo.STATE_MOUNTED:
1127 case VolumeInfo.STATE_MOUNTED_READ_ONLY:
1128 case VolumeInfo.STATE_EJECTING:
1129 case VolumeInfo.STATE_UNMOUNTED:
Jeff Sharkeyc7acac62015-06-12 16:16:56 -07001130 case VolumeInfo.STATE_UNMOUNTABLE:
Tony Mantlerf0d71052015-06-24 11:45:25 -07001131 case VolumeInfo.STATE_BAD_REMOVAL:
Jeff Sharkeye6c04f92015-04-18 21:38:05 -07001132 break;
1133 default:
1134 return false;
1135 }
1136
1137 return true;
1138 }
1139
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07001140 private void onVolumeStateChangedLocked(VolumeInfo vol, int oldState, int newState) {
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001141 // Remember that we saw this volume so we're ready to accept user
1142 // metadata, or so we can annoy them when a private volume is ejected
1143 if (vol.isMountedReadable() && !TextUtils.isEmpty(vol.fsUuid)) {
Jeff Sharkey5cc0df22015-06-17 19:44:05 -07001144 VolumeRecord rec = mRecords.get(vol.fsUuid);
1145 if (rec == null) {
1146 rec = new VolumeRecord(vol.type, vol.fsUuid);
1147 rec.partGuid = vol.partGuid;
Jeff Sharkeye8a4b662015-06-27 15:43:45 -07001148 rec.createdMillis = System.currentTimeMillis();
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001149 if (vol.type == VolumeInfo.TYPE_PRIVATE) {
1150 rec.nickname = vol.disk.getDescription();
1151 }
1152 mRecords.put(rec.fsUuid, rec);
1153 writeSettingsLocked();
Jeff Sharkey5cc0df22015-06-17 19:44:05 -07001154 } else {
1155 // Handle upgrade case where we didn't store partition GUID
1156 if (TextUtils.isEmpty(rec.partGuid)) {
1157 rec.partGuid = vol.partGuid;
1158 writeSettingsLocked();
1159 }
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001160 }
1161 }
1162
Jeff Sharkeye6c04f92015-04-18 21:38:05 -07001163 mCallbacks.notifyVolumeStateChanged(vol, oldState, newState);
1164
Yasuhiro Matsuda87a38b52015-07-24 22:10:16 +09001165 // Do not broadcast before boot has completed to avoid launching the
1166 // processes that receive the intent unnecessarily.
1167 if (mBootCompleted && isBroadcastWorthy(vol)) {
Jeff Sharkeye6c04f92015-04-18 21:38:05 -07001168 final Intent intent = new Intent(VolumeInfo.ACTION_VOLUME_STATE_CHANGED);
Jeff Sharkeyc7acac62015-06-12 16:16:56 -07001169 intent.putExtra(VolumeInfo.EXTRA_VOLUME_ID, vol.id);
1170 intent.putExtra(VolumeInfo.EXTRA_VOLUME_STATE, newState);
Tony Mantlerf0d71052015-06-24 11:45:25 -07001171 intent.putExtra(VolumeRecord.EXTRA_FS_UUID, vol.fsUuid);
Jeff Sharkey7732e1e2016-03-30 17:14:23 -06001172 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT
1173 | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
Jeff Sharkeyabc3e852015-08-03 14:41:13 -07001174 mHandler.obtainMessage(H_INTERNAL_BROADCAST, intent).sendToTarget();
Jeff Sharkeye6c04f92015-04-18 21:38:05 -07001175 }
Jeff Sharkeyb049e212012-09-07 23:16:01 -07001176
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001177 final String oldStateEnv = VolumeInfo.getEnvironmentForState(oldState);
1178 final String newStateEnv = VolumeInfo.getEnvironmentForState(newState);
Emily Bernier92aa5a22014-07-07 10:11:48 -04001179
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001180 if (!Objects.equals(oldStateEnv, newStateEnv)) {
1181 // Kick state changed event towards all started users. Any users
1182 // started after this point will trigger additional
1183 // user-specific broadcasts.
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07001184 for (int userId : mSystemUnlockedUsers) {
Jeff Sharkey46349872015-07-28 10:49:47 -07001185 if (vol.isVisibleForRead(userId)) {
Svet Ganov6ee871e2015-07-10 14:29:33 -07001186 final StorageVolume userVol = vol.buildStorageVolume(mContext, userId, false);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001187 mHandler.obtainMessage(H_VOLUME_BROADCAST, userVol).sendToTarget();
Jeff Sharkey48877892015-03-18 11:27:19 -07001188
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001189 mCallbacks.notifyStorageStateChanged(userVol.getPath(), oldStateEnv,
1190 newStateEnv);
San Mehat4270e1e2010-01-29 05:32:19 -08001191 }
1192 }
1193 }
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001194
Jeff Sharkey7e92ef32015-04-17 17:35:07 -07001195 if (vol.type == VolumeInfo.TYPE_PUBLIC && vol.state == VolumeInfo.STATE_EJECTING) {
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001196 // TODO: this should eventually be handled by new ObbVolume state changes
1197 /*
1198 * Some OBBs might have been unmounted when this volume was
1199 * unmounted, so send a message to the handler to let it know to
1200 * remove those from the list of mounted OBBS.
1201 */
1202 mObbActionHandler.sendMessage(mObbActionHandler.obtainMessage(
1203 OBB_FLUSH_MOUNT_STATE, vol.path));
1204 }
San Mehat4270e1e2010-01-29 05:32:19 -08001205 }
1206
Jeff Sharkey275e3e42015-04-24 16:10:32 -07001207 private void onMoveStatusLocked(int status) {
1208 if (mMoveCallback == null) {
1209 Slog.w(TAG, "Odd, status but no move requested");
1210 return;
1211 }
1212
1213 // TODO: estimate remaining time
1214 try {
Jeff Sharkey50a05452015-04-29 11:24:52 -07001215 mMoveCallback.onStatusChanged(-1, status, -1);
Jeff Sharkey275e3e42015-04-24 16:10:32 -07001216 } catch (RemoteException ignored) {
1217 }
1218
1219 // We've finished copying and we're about to clean up old data, so
1220 // remember that move was successful if we get rebooted
1221 if (status == MOVE_STATUS_COPY_FINISHED) {
1222 Slog.d(TAG, "Move to " + mMoveTargetUuid + " copy phase finshed; persisting");
1223
1224 mPrimaryStorageUuid = mMoveTargetUuid;
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001225 writeSettingsLocked();
Jeff Sharkey275e3e42015-04-24 16:10:32 -07001226 }
1227
1228 if (PackageManager.isMoveStatusFinished(status)) {
1229 Slog.d(TAG, "Move to " + mMoveTargetUuid + " finished with status " + status);
1230
1231 mMoveCallback = null;
1232 mMoveTargetUuid = null;
1233 }
1234 }
1235
Jeff Sharkey48877892015-03-18 11:27:19 -07001236 private void enforcePermission(String perm) {
1237 mContext.enforceCallingOrSelfPermission(perm, perm);
Mike Lockwooda5250c92011-05-23 13:44:04 -04001238 }
1239
Jeff Sharkey2e606d72015-07-27 14:19:54 -07001240 /**
1241 * Decide if volume is mountable per device policies.
1242 */
1243 private boolean isMountDisallowed(VolumeInfo vol) {
Philip P. Moltmannec3cbb22016-09-14 13:24:52 -07001244 UserManager userManager = mContext.getSystemService(UserManager.class);
1245
1246 boolean isUsbRestricted = false;
1247 if (vol.disk != null && vol.disk.isUsb()) {
1248 isUsbRestricted = userManager.hasUserRestriction(UserManager.DISALLOW_USB_FILE_TRANSFER,
Jeff Sharkey2e606d72015-07-27 14:19:54 -07001249 Binder.getCallingUserHandle());
Emily Bernier92aa5a22014-07-07 10:11:48 -04001250 }
Philip P. Moltmannec3cbb22016-09-14 13:24:52 -07001251
1252 boolean isTypeRestricted = false;
1253 if (vol.type == VolumeInfo.TYPE_PUBLIC || vol.type == VolumeInfo.TYPE_PRIVATE) {
1254 isTypeRestricted = userManager
1255 .hasUserRestriction(UserManager.DISALLOW_MOUNT_PHYSICAL_MEDIA,
1256 Binder.getCallingUserHandle());
1257 }
1258
1259 return isUsbRestricted || isTypeRestricted;
Emily Bernier92aa5a22014-07-07 10:11:48 -04001260 }
1261
Amith Yamasani462ac3a2015-06-30 14:21:01 -07001262 private void enforceAdminUser() {
1263 UserManager um = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
1264 final int callingUserId = UserHandle.getCallingUserId();
1265 boolean isAdmin;
1266 long token = Binder.clearCallingIdentity();
1267 try {
1268 isAdmin = um.getUserInfo(callingUserId).isAdmin();
1269 } finally {
1270 Binder.restoreCallingIdentity(token);
1271 }
1272 if (!isAdmin) {
1273 throw new SecurityException("Only admin users can adopt sd cards");
1274 }
1275 }
1276
Jeff Sharkeyb049e212012-09-07 23:16:01 -07001277 /**
Sudheer Shanka2250d562016-11-07 15:41:02 -08001278 * Constructs a new StorageManagerService instance
San Mehat207e5382010-02-04 20:46:54 -08001279 *
1280 * @param context Binder context for this service
1281 */
Sudheer Shanka2250d562016-11-07 15:41:02 -08001282 public StorageManagerService(Context context) {
Christopher Tated417d622013-08-19 16:14:25 -07001283 sSelf = this;
1284
San Mehat207e5382010-02-04 20:46:54 -08001285 mContext = context;
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001286 mCallbacks = new Callbacks(FgThread.get().getLooper());
Jeff Sharkeyb9fe5372015-12-03 15:23:08 -07001287 mLockPatternUtils = new LockPatternUtils(mContext);
San Mehat207e5382010-02-04 20:46:54 -08001288
San Mehat207e5382010-02-04 20:46:54 -08001289 // XXX: This will go away soon in favor of IMountServiceObserver
1290 mPms = (PackageManagerService) ServiceManager.getService("package");
1291
Dianne Hackbornefa92b22013-05-03 14:11:43 -07001292 HandlerThread hthread = new HandlerThread(TAG);
1293 hthread.start();
Sudheer Shanka2250d562016-11-07 15:41:02 -08001294 mHandler = new StorageManagerServiceHandler(hthread.getLooper());
Daniel Sandler5f27ef42010-03-16 15:42:02 -04001295
Sudheer Shanka2250d562016-11-07 15:41:02 -08001296 // Add OBB Action Handler to StorageManagerService thread.
Dianne Hackborn8d044e82013-04-30 17:24:15 -07001297 mObbActionHandler = new ObbActionHandler(IoThread.get().getLooper());
Kenny Roota02b8b02010-08-05 16:14:17 -07001298
Christopher Tate7265abe2014-11-21 13:54:45 -08001299 // Initialize the last-fstrim tracking if necessary
1300 File dataDir = Environment.getDataDirectory();
1301 File systemDir = new File(dataDir, "system");
1302 mLastMaintenanceFile = new File(systemDir, LAST_FSTRIM_FILE);
1303 if (!mLastMaintenanceFile.exists()) {
1304 // Not setting mLastMaintenance here means that we will force an
1305 // fstrim during reboot following the OTA that installs this code.
1306 try {
1307 (new FileOutputStream(mLastMaintenanceFile)).close();
1308 } catch (IOException e) {
1309 Slog.e(TAG, "Unable to create fstrim record " + mLastMaintenanceFile.getPath());
1310 }
1311 } else {
1312 mLastMaintenance = mLastMaintenanceFile.lastModified();
1313 }
1314
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001315 mSettingsFile = new AtomicFile(
Jeff Sharkey8212ae02016-02-10 14:46:43 -07001316 new File(Environment.getDataSystemDirectory(), "storage.xml"));
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001317
1318 synchronized (mLock) {
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001319 readSettingsLocked();
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001320 }
1321
Sudheer Shanka2250d562016-11-07 15:41:02 -08001322 LocalServices.addService(StorageManagerInternal.class, mStorageManagerInternal);
Svet Ganov6ee871e2015-07-10 14:29:33 -07001323
Jeff Sharkeybcd262d2015-06-10 09:41:17 -07001324 final IntentFilter userFilter = new IntentFilter();
1325 userFilter.addAction(Intent.ACTION_USER_ADDED);
1326 userFilter.addAction(Intent.ACTION_USER_REMOVED);
1327 mContext.registerReceiver(mUserReceiver, userFilter, null, mHandler);
1328
Jeff Sharkey5a9bb742015-11-03 10:15:57 -08001329 synchronized (mLock) {
1330 addInternalVolumeLocked();
1331 }
Amith Yamasania7892482015-08-07 11:09:05 -07001332
Kenny Root07714d42011-08-17 17:49:28 -07001333 // Add ourself to the Watchdog monitors if enabled.
1334 if (WATCHDOG_ENABLE) {
1335 Watchdog.getInstance().addMonitor(this);
1336 }
San Mehat207e5382010-02-04 20:46:54 -08001337 }
1338
Jeff Sharkeycd575992016-03-29 14:12:49 -06001339 private void start() {
Jeff Sharkey1019de92017-09-06 13:47:03 -06001340 connect();
Jeff Sharkeycd575992016-03-29 14:12:49 -06001341 }
1342
Jeff Sharkey1019de92017-09-06 13:47:03 -06001343 private void connect() {
Jin Qian12690d52017-10-13 18:17:04 -07001344 IBinder binder = ServiceManager.getService("storaged");
1345 if (binder != null) {
1346 try {
1347 binder.linkToDeath(new DeathRecipient() {
1348 @Override
1349 public void binderDied() {
1350 Slog.w(TAG, "storaged died; reconnecting");
1351 mStoraged = null;
1352 connect();
1353 }
1354 }, 0);
1355 } catch (RemoteException e) {
1356 binder = null;
1357 }
1358 }
1359
1360 if (binder != null) {
1361 mStoraged = IStoraged.Stub.asInterface(binder);
1362 } else {
1363 Slog.w(TAG, "storaged not found; trying again");
1364 }
1365
1366 binder = ServiceManager.getService("vold");
Jeff Sharkey1019de92017-09-06 13:47:03 -06001367 if (binder != null) {
1368 try {
1369 binder.linkToDeath(new DeathRecipient() {
1370 @Override
1371 public void binderDied() {
1372 Slog.w(TAG, "vold died; reconnecting");
Jin Qian12690d52017-10-13 18:17:04 -07001373 mVold = null;
Jeff Sharkey1019de92017-09-06 13:47:03 -06001374 connect();
1375 }
1376 }, 0);
1377 } catch (RemoteException e) {
1378 binder = null;
1379 }
1380 }
1381
1382 if (binder != null) {
1383 mVold = IVold.Stub.asInterface(binder);
Jeff Sharkey8058fe62017-09-13 11:50:33 -06001384 try {
1385 mVold.setListener(mListener);
Jeff Sharkey8058fe62017-09-13 11:50:33 -06001386 } catch (RemoteException e) {
Jin Qian12690d52017-10-13 18:17:04 -07001387 mVold = null;
Jeff Sharkey8058fe62017-09-13 11:50:33 -06001388 Slog.w(TAG, "vold listener rejected; trying again", e);
1389 }
Jeff Sharkey1019de92017-09-06 13:47:03 -06001390 } else {
1391 Slog.w(TAG, "vold not found; trying again");
Jeff Sharkey1019de92017-09-06 13:47:03 -06001392 }
Jeff Sharkey8058fe62017-09-13 11:50:33 -06001393
Jin Qian12690d52017-10-13 18:17:04 -07001394 if (mStoraged == null || mVold == null) {
1395 BackgroundThread.getHandler().postDelayed(() -> {
1396 connect();
1397 }, DateUtils.SECOND_IN_MILLIS);
1398 } else {
1399 onDaemonConnected();
1400 }
Jeff Sharkey1019de92017-09-06 13:47:03 -06001401 }
1402
Jeff Sharkey56e62932015-03-21 20:41:00 -07001403 private void systemReady() {
Jeff Sharkeyb049e212012-09-07 23:16:01 -07001404 mSystemReady = true;
1405 mHandler.obtainMessage(H_SYSTEM_READY).sendToTarget();
1406 }
1407
Yasuhiro Matsuda87a38b52015-07-24 22:10:16 +09001408 private void bootCompleted() {
1409 mBootCompleted = true;
1410 }
1411
Jeff Sharkeyfced5342015-05-10 14:53:34 -07001412 private String getDefaultPrimaryStorageUuid() {
1413 if (SystemProperties.getBoolean(StorageManager.PROP_PRIMARY_PHYSICAL, false)) {
1414 return StorageManager.UUID_PRIMARY_PHYSICAL;
1415 } else {
1416 return StorageManager.UUID_PRIVATE_INTERNAL;
1417 }
1418 }
1419
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001420 private void readSettingsLocked() {
1421 mRecords.clear();
Jeff Sharkeyfced5342015-05-10 14:53:34 -07001422 mPrimaryStorageUuid = getDefaultPrimaryStorageUuid();
Jeff Sharkey4c099d02015-05-15 13:45:00 -07001423 mForceAdoptable = false;
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001424
1425 FileInputStream fis = null;
1426 try {
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001427 fis = mSettingsFile.openRead();
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001428 final XmlPullParser in = Xml.newPullParser();
Wojciech Staszkiewicz9e9e2e72015-05-08 14:58:46 +01001429 in.setInput(fis, StandardCharsets.UTF_8.name());
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001430
1431 int type;
1432 while ((type = in.next()) != END_DOCUMENT) {
1433 if (type == START_TAG) {
1434 final String tag = in.getName();
Jeff Sharkey620b32b2015-04-23 19:36:02 -07001435 if (TAG_VOLUMES.equals(tag)) {
1436 final int version = readIntAttribute(in, ATTR_VERSION, VERSION_INIT);
Jeff Sharkeyfced5342015-05-10 14:53:34 -07001437 final boolean primaryPhysical = SystemProperties.getBoolean(
1438 StorageManager.PROP_PRIMARY_PHYSICAL, false);
1439 final boolean validAttr = (version >= VERSION_FIX_PRIMARY)
1440 || (version >= VERSION_ADD_PRIMARY && !primaryPhysical);
1441 if (validAttr) {
Jeff Sharkey620b32b2015-04-23 19:36:02 -07001442 mPrimaryStorageUuid = readStringAttribute(in,
1443 ATTR_PRIMARY_STORAGE_UUID);
Jeff Sharkey620b32b2015-04-23 19:36:02 -07001444 }
Jeff Sharkey4c099d02015-05-15 13:45:00 -07001445 mForceAdoptable = readBooleanAttribute(in, ATTR_FORCE_ADOPTABLE, false);
Jeff Sharkey620b32b2015-04-23 19:36:02 -07001446
1447 } else if (TAG_VOLUME.equals(tag)) {
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001448 final VolumeRecord rec = readVolumeRecord(in);
1449 mRecords.put(rec.fsUuid, rec);
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001450 }
1451 }
1452 }
1453 } catch (FileNotFoundException e) {
1454 // Missing metadata is okay, probably first boot
1455 } catch (IOException e) {
1456 Slog.wtf(TAG, "Failed reading metadata", e);
1457 } catch (XmlPullParserException e) {
1458 Slog.wtf(TAG, "Failed reading metadata", e);
1459 } finally {
1460 IoUtils.closeQuietly(fis);
1461 }
1462 }
1463
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001464 private void writeSettingsLocked() {
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001465 FileOutputStream fos = null;
1466 try {
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001467 fos = mSettingsFile.startWrite();
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001468
1469 XmlSerializer out = new FastXmlSerializer();
Wojciech Staszkiewicz9e9e2e72015-05-08 14:58:46 +01001470 out.setOutput(fos, StandardCharsets.UTF_8.name());
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001471 out.startDocument(null, true);
1472 out.startTag(null, TAG_VOLUMES);
Jeff Sharkeyfced5342015-05-10 14:53:34 -07001473 writeIntAttribute(out, ATTR_VERSION, VERSION_FIX_PRIMARY);
Jeff Sharkey620b32b2015-04-23 19:36:02 -07001474 writeStringAttribute(out, ATTR_PRIMARY_STORAGE_UUID, mPrimaryStorageUuid);
Jeff Sharkey4c099d02015-05-15 13:45:00 -07001475 writeBooleanAttribute(out, ATTR_FORCE_ADOPTABLE, mForceAdoptable);
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001476 final int size = mRecords.size();
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001477 for (int i = 0; i < size; i++) {
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001478 final VolumeRecord rec = mRecords.valueAt(i);
1479 writeVolumeRecord(out, rec);
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001480 }
1481 out.endTag(null, TAG_VOLUMES);
1482 out.endDocument();
1483
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001484 mSettingsFile.finishWrite(fos);
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001485 } catch (IOException e) {
1486 if (fos != null) {
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001487 mSettingsFile.failWrite(fos);
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001488 }
1489 }
1490 }
1491
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001492 public static VolumeRecord readVolumeRecord(XmlPullParser in) throws IOException {
1493 final int type = readIntAttribute(in, ATTR_TYPE);
1494 final String fsUuid = readStringAttribute(in, ATTR_FS_UUID);
1495 final VolumeRecord meta = new VolumeRecord(type, fsUuid);
Jeff Sharkey5cc0df22015-06-17 19:44:05 -07001496 meta.partGuid = readStringAttribute(in, ATTR_PART_GUID);
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001497 meta.nickname = readStringAttribute(in, ATTR_NICKNAME);
1498 meta.userFlags = readIntAttribute(in, ATTR_USER_FLAGS);
Jeff Sharkeye8a4b662015-06-27 15:43:45 -07001499 meta.createdMillis = readLongAttribute(in, ATTR_CREATED_MILLIS);
1500 meta.lastTrimMillis = readLongAttribute(in, ATTR_LAST_TRIM_MILLIS);
1501 meta.lastBenchMillis = readLongAttribute(in, ATTR_LAST_BENCH_MILLIS);
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001502 return meta;
1503 }
1504
1505 public static void writeVolumeRecord(XmlSerializer out, VolumeRecord rec) throws IOException {
1506 out.startTag(null, TAG_VOLUME);
1507 writeIntAttribute(out, ATTR_TYPE, rec.type);
1508 writeStringAttribute(out, ATTR_FS_UUID, rec.fsUuid);
Jeff Sharkey5cc0df22015-06-17 19:44:05 -07001509 writeStringAttribute(out, ATTR_PART_GUID, rec.partGuid);
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001510 writeStringAttribute(out, ATTR_NICKNAME, rec.nickname);
1511 writeIntAttribute(out, ATTR_USER_FLAGS, rec.userFlags);
Jeff Sharkeye8a4b662015-06-27 15:43:45 -07001512 writeLongAttribute(out, ATTR_CREATED_MILLIS, rec.createdMillis);
1513 writeLongAttribute(out, ATTR_LAST_TRIM_MILLIS, rec.lastTrimMillis);
1514 writeLongAttribute(out, ATTR_LAST_BENCH_MILLIS, rec.lastBenchMillis);
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001515 out.endTag(null, TAG_VOLUME);
1516 }
1517
San Mehat207e5382010-02-04 20:46:54 -08001518 /**
San Mehat4270e1e2010-01-29 05:32:19 -08001519 * Exposed API calls below here
1520 */
1521
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001522 @Override
Sudheer Shanka2250d562016-11-07 15:41:02 -08001523 public void registerListener(IStorageEventListener listener) {
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001524 mCallbacks.register(listener);
San Mehat4270e1e2010-01-29 05:32:19 -08001525 }
1526
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001527 @Override
Sudheer Shanka2250d562016-11-07 15:41:02 -08001528 public void unregisterListener(IStorageEventListener listener) {
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001529 mCallbacks.unregister(listener);
San Mehat4270e1e2010-01-29 05:32:19 -08001530 }
1531
Jeff Sharkey48877892015-03-18 11:27:19 -07001532 @Override
Sudheer Shanka2250d562016-11-07 15:41:02 -08001533 public void shutdown(final IStorageShutdownObserver observer) {
Jeff Sharkey48877892015-03-18 11:27:19 -07001534 enforcePermission(android.Manifest.permission.SHUTDOWN);
San Mehat4270e1e2010-01-29 05:32:19 -08001535
San Mehata5078592010-03-25 09:36:54 -07001536 Slog.i(TAG, "Shutting down");
Jeff Sharkey48877892015-03-18 11:27:19 -07001537 mHandler.obtainMessage(H_SHUTDOWN, observer).sendToTarget();
San Mehat4270e1e2010-01-29 05:32:19 -08001538 }
1539
Jeff Sharkey48877892015-03-18 11:27:19 -07001540 @Override
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001541 public void mount(String volId) {
1542 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001543
Jeff Sharkeyef10ee02015-07-05 14:17:27 -07001544 final VolumeInfo vol = findVolumeByIdOrThrow(volId);
Jeff Sharkey2e606d72015-07-27 14:19:54 -07001545 if (isMountDisallowed(vol)) {
1546 throw new SecurityException("Mounting " + volId + " restricted by policy");
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001547 }
1548 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06001549 mVold.mount(vol.id, vol.mountFlags, vol.mountUserId);
Jeff Sharkeyace874b2017-09-07 15:27:33 -06001550 } catch (Exception e) {
1551 Slog.wtf(TAG, e);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001552 }
1553 }
1554
1555 @Override
1556 public void unmount(String volId) {
1557 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001558
Jeff Sharkeyef10ee02015-07-05 14:17:27 -07001559 final VolumeInfo vol = findVolumeByIdOrThrow(volId);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001560 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06001561 mVold.unmount(vol.id);
Jeff Sharkeyace874b2017-09-07 15:27:33 -06001562 } catch (Exception e) {
1563 Slog.wtf(TAG, e);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001564 }
1565 }
1566
1567 @Override
1568 public void format(String volId) {
Jeff Sharkey48877892015-03-18 11:27:19 -07001569 enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);
San Mehat5b77dab2010-01-26 13:28:50 -08001570
Jeff Sharkeyef10ee02015-07-05 14:17:27 -07001571 final VolumeInfo vol = findVolumeByIdOrThrow(volId);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001572 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06001573 mVold.format(vol.id, "auto");
Jeff Sharkeyace874b2017-09-07 15:27:33 -06001574 } catch (Exception e) {
1575 Slog.wtf(TAG, e);
Jeff Sharkey48877892015-03-18 11:27:19 -07001576 }
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001577 }
1578
1579 @Override
Jeff Sharkey7e19f532017-11-06 13:54:11 -07001580 public void benchmark(String volId, IVoldTaskListener listener) {
Jeff Sharkey9756d752015-05-14 21:07:42 -07001581 enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);
Jeff Sharkey9756d752015-05-14 21:07:42 -07001582
1583 try {
Jeff Sharkeyb302c542017-09-15 12:57:59 -06001584 mVold.benchmark(volId, new IVoldTaskListener.Stub() {
1585 @Override
1586 public void onStatus(int status, PersistableBundle extras) {
Jeff Sharkey7e19f532017-11-06 13:54:11 -07001587 dispatchOnStatus(listener, status, extras);
Jeff Sharkeyb302c542017-09-15 12:57:59 -06001588 }
1589
1590 @Override
1591 public void onFinished(int status, PersistableBundle extras) {
Jeff Sharkey7e19f532017-11-06 13:54:11 -07001592 dispatchOnFinished(listener, status, extras);
Jeff Sharkeyb302c542017-09-15 12:57:59 -06001593
1594 final String path = extras.getString("path");
1595 final String ident = extras.getString("ident");
1596 final long create = extras.getLong("create");
1597 final long run = extras.getLong("run");
1598 final long destroy = extras.getLong("destroy");
1599
1600 final DropBoxManager dropBox = mContext.getSystemService(DropBoxManager.class);
1601 dropBox.addText(TAG_STORAGE_BENCHMARK, scrubPath(path)
1602 + " " + ident + " " + create + " " + run + " " + destroy);
1603
1604 synchronized (mLock) {
1605 final VolumeRecord rec = findRecordForPath(path);
1606 if (rec != null) {
1607 rec.lastBenchMillis = System.currentTimeMillis();
1608 writeSettingsLocked();
1609 }
1610 }
1611 }
1612 });
Jeff Sharkey7e19f532017-11-06 13:54:11 -07001613 } catch (RemoteException e) {
1614 throw e.rethrowAsRuntimeException();
Jeff Sharkey9756d752015-05-14 21:07:42 -07001615 }
1616 }
1617
1618 @Override
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001619 public void partitionPublic(String diskId) {
1620 enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001621
Jeff Sharkeyeba260d2015-04-19 14:35:16 -07001622 final CountDownLatch latch = findOrCreateDiskScanLatch(diskId);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001623 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06001624 mVold.partition(diskId, IVold.PARTITION_TYPE_PUBLIC, -1);
Jeff Sharkeyedcdaf62015-07-09 09:45:36 -07001625 waitForLatch(latch, "partitionPublic", 3 * DateUtils.MINUTE_IN_MILLIS);
Jeff Sharkeyace874b2017-09-07 15:27:33 -06001626 } catch (Exception e) {
1627 Slog.wtf(TAG, e);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001628 }
1629 }
1630
1631 @Override
1632 public void partitionPrivate(String diskId) {
1633 enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);
Amith Yamasani462ac3a2015-06-30 14:21:01 -07001634 enforceAdminUser();
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001635
Jeff Sharkeyeba260d2015-04-19 14:35:16 -07001636 final CountDownLatch latch = findOrCreateDiskScanLatch(diskId);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001637 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06001638 mVold.partition(diskId, IVold.PARTITION_TYPE_PRIVATE, -1);
Jeff Sharkeyedcdaf62015-07-09 09:45:36 -07001639 waitForLatch(latch, "partitionPrivate", 3 * DateUtils.MINUTE_IN_MILLIS);
Jeff Sharkeyace874b2017-09-07 15:27:33 -06001640 } catch (Exception e) {
1641 Slog.wtf(TAG, e);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001642 }
1643 }
1644
1645 @Override
1646 public void partitionMixed(String diskId, int ratio) {
1647 enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);
Amith Yamasani462ac3a2015-06-30 14:21:01 -07001648 enforceAdminUser();
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001649
Jeff Sharkeyeba260d2015-04-19 14:35:16 -07001650 final CountDownLatch latch = findOrCreateDiskScanLatch(diskId);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001651 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06001652 mVold.partition(diskId, IVold.PARTITION_TYPE_MIXED, ratio);
Jeff Sharkeyedcdaf62015-07-09 09:45:36 -07001653 waitForLatch(latch, "partitionMixed", 3 * DateUtils.MINUTE_IN_MILLIS);
Jeff Sharkeyace874b2017-09-07 15:27:33 -06001654 } catch (Exception e) {
1655 Slog.wtf(TAG, e);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001656 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001657 }
1658
Jeff Sharkey48877892015-03-18 11:27:19 -07001659 @Override
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001660 public void setVolumeNickname(String fsUuid, String nickname) {
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001661 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001662
Jeff Sharkey50a05452015-04-29 11:24:52 -07001663 Preconditions.checkNotNull(fsUuid);
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001664 synchronized (mLock) {
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001665 final VolumeRecord rec = mRecords.get(fsUuid);
1666 rec.nickname = nickname;
Jeff Sharkey50a05452015-04-29 11:24:52 -07001667 mCallbacks.notifyVolumeRecordChanged(rec);
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001668 writeSettingsLocked();
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001669 }
1670 }
1671
1672 @Override
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001673 public void setVolumeUserFlags(String fsUuid, int flags, int mask) {
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001674 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001675
Jeff Sharkey50a05452015-04-29 11:24:52 -07001676 Preconditions.checkNotNull(fsUuid);
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001677 synchronized (mLock) {
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001678 final VolumeRecord rec = mRecords.get(fsUuid);
1679 rec.userFlags = (rec.userFlags & ~mask) | (flags & mask);
Jeff Sharkey50a05452015-04-29 11:24:52 -07001680 mCallbacks.notifyVolumeRecordChanged(rec);
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001681 writeSettingsLocked();
1682 }
1683 }
1684
1685 @Override
1686 public void forgetVolume(String fsUuid) {
1687 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001688
Jeff Sharkey50a05452015-04-29 11:24:52 -07001689 Preconditions.checkNotNull(fsUuid);
Jeff Sharkey5a9bb742015-11-03 10:15:57 -08001690
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001691 synchronized (mLock) {
Jeff Sharkey5cc0df22015-06-17 19:44:05 -07001692 final VolumeRecord rec = mRecords.remove(fsUuid);
1693 if (rec != null && !TextUtils.isEmpty(rec.partGuid)) {
Jeff Sharkeydb4b6192017-10-24 11:08:50 -06001694 mHandler.obtainMessage(H_PARTITION_FORGET, rec).sendToTarget();
Jeff Sharkey5cc0df22015-06-17 19:44:05 -07001695 }
1696 mCallbacks.notifyVolumeForgotten(fsUuid);
Jeff Sharkey50a05452015-04-29 11:24:52 -07001697
1698 // If this had been primary storage, revert back to internal and
1699 // reset vold so we bind into new volume into place.
1700 if (Objects.equals(mPrimaryStorageUuid, fsUuid)) {
Jeff Sharkeyfced5342015-05-10 14:53:34 -07001701 mPrimaryStorageUuid = getDefaultPrimaryStorageUuid();
Jeff Sharkey5a9bb742015-11-03 10:15:57 -08001702 mHandler.obtainMessage(H_RESET).sendToTarget();
Jeff Sharkey50a05452015-04-29 11:24:52 -07001703 }
1704
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001705 writeSettingsLocked();
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001706 }
1707 }
1708
Jeff Sharkey7d2af542015-05-12 15:27:15 -07001709 @Override
1710 public void forgetAllVolumes() {
1711 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
Jeff Sharkey7d2af542015-05-12 15:27:15 -07001712
Jeff Sharkey50a05452015-04-29 11:24:52 -07001713 synchronized (mLock) {
1714 for (int i = 0; i < mRecords.size(); i++) {
1715 final String fsUuid = mRecords.keyAt(i);
Jeff Sharkey5cc0df22015-06-17 19:44:05 -07001716 final VolumeRecord rec = mRecords.valueAt(i);
1717 if (!TextUtils.isEmpty(rec.partGuid)) {
Jeff Sharkeydb4b6192017-10-24 11:08:50 -06001718 mHandler.obtainMessage(H_PARTITION_FORGET, rec).sendToTarget();
Jeff Sharkey5cc0df22015-06-17 19:44:05 -07001719 }
Jeff Sharkey50a05452015-04-29 11:24:52 -07001720 mCallbacks.notifyVolumeForgotten(fsUuid);
1721 }
Jeff Sharkey50a05452015-04-29 11:24:52 -07001722 mRecords.clear();
Jeff Sharkey50a05452015-04-29 11:24:52 -07001723
Jeff Sharkeyfced5342015-05-10 14:53:34 -07001724 if (!Objects.equals(StorageManager.UUID_PRIVATE_INTERNAL, mPrimaryStorageUuid)) {
1725 mPrimaryStorageUuid = getDefaultPrimaryStorageUuid();
1726 }
1727
1728 writeSettingsLocked();
Jeff Sharkey5a9bb742015-11-03 10:15:57 -08001729 mHandler.obtainMessage(H_RESET).sendToTarget();
Jeff Sharkey50a05452015-04-29 11:24:52 -07001730 }
1731 }
1732
Jeff Sharkeydb4b6192017-10-24 11:08:50 -06001733 private void forgetPartition(String partGuid, String fsUuid) {
Jeff Sharkey5cc0df22015-06-17 19:44:05 -07001734 try {
Jeff Sharkeydb4b6192017-10-24 11:08:50 -06001735 mVold.forgetPartition(partGuid, fsUuid);
Jeff Sharkeyace874b2017-09-07 15:27:33 -06001736 } catch (Exception e) {
1737 Slog.wtf(TAG, e);
Jeff Sharkey5cc0df22015-06-17 19:44:05 -07001738 }
1739 }
1740
Jeff Sharkey31d0b702016-11-21 14:16:53 -07001741 @Override
Jeff Sharkey7e19f532017-11-06 13:54:11 -07001742 public void fstrim(int flags, IVoldTaskListener listener) {
Jeff Sharkey31d0b702016-11-21 14:16:53 -07001743 enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);
Jeff Sharkey31d0b702016-11-21 14:16:53 -07001744
1745 try {
Jeff Sharkeyb302c542017-09-15 12:57:59 -06001746 mVold.fstrim(flags, new IVoldTaskListener.Stub() {
1747 @Override
1748 public void onStatus(int status, PersistableBundle extras) {
Jeff Sharkey7e19f532017-11-06 13:54:11 -07001749 dispatchOnStatus(listener, status, extras);
1750
Jeff Sharkeyb302c542017-09-15 12:57:59 -06001751 // Ignore trim failures
1752 if (status != 0) return;
1753
1754 final String path = extras.getString("path");
1755 final long bytes = extras.getLong("bytes");
1756 final long time = extras.getLong("time");
1757
1758 final DropBoxManager dropBox = mContext.getSystemService(DropBoxManager.class);
1759 dropBox.addText(TAG_STORAGE_TRIM, scrubPath(path) + " " + bytes + " " + time);
1760
1761 synchronized (mLock) {
1762 final VolumeRecord rec = findRecordForPath(path);
1763 if (rec != null) {
1764 rec.lastTrimMillis = System.currentTimeMillis();
1765 writeSettingsLocked();
1766 }
1767 }
1768 }
1769
1770 @Override
1771 public void onFinished(int status, PersistableBundle extras) {
Jeff Sharkey7e19f532017-11-06 13:54:11 -07001772 dispatchOnFinished(listener, status, extras);
1773
Jeff Sharkeyb302c542017-09-15 12:57:59 -06001774 // TODO: benchmark when desired
1775 }
1776 });
Jeff Sharkey7e19f532017-11-06 13:54:11 -07001777 } catch (RemoteException e) {
1778 throw e.rethrowAsRuntimeException();
Jeff Sharkey31d0b702016-11-21 14:16:53 -07001779 }
1780 }
1781
Svet Ganov6ee871e2015-07-10 14:29:33 -07001782 private void remountUidExternalStorage(int uid, int mode) {
Jeff Sharkey9527b222015-06-24 15:24:48 -07001783 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06001784 mVold.remountUid(uid, mode);
Jeff Sharkeyace874b2017-09-07 15:27:33 -06001785 } catch (Exception e) {
1786 Slog.wtf(TAG, e);
Jeff Sharkey9527b222015-06-24 15:24:48 -07001787 }
1788 }
1789
1790 @Override
Jeff Sharkey4c099d02015-05-15 13:45:00 -07001791 public void setDebugFlags(int flags, int mask) {
1792 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
Jeff Sharkey4c099d02015-05-15 13:45:00 -07001793
Jeff Sharkeyba512352015-11-12 20:17:45 -08001794 if ((mask & StorageManager.DEBUG_EMULATE_FBE) != 0) {
Jeff Sharkey00455bf2016-11-04 14:45:24 -06001795 if (!EMULATE_FBE_SUPPORTED) {
1796 throw new IllegalStateException(
1797 "Emulation not supported on this device");
1798 }
Paul Lawrence20be5d62016-02-26 13:51:17 -08001799 if (StorageManager.isFileEncryptedNativeOnly()) {
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07001800 throw new IllegalStateException(
Jeff Sharkey00455bf2016-11-04 14:45:24 -06001801 "Emulation not supported on device with native FBE");
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07001802 }
Jeff Sharkey5a785162016-03-21 13:02:06 -06001803 if (mLockPatternUtils.isCredentialRequiredToDecrypt(false)) {
1804 throw new IllegalStateException(
1805 "Emulation requires disabling 'Secure start-up' in Settings > Security");
1806 }
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07001807
Jeff Sharkey1176e512016-02-29 17:01:26 -07001808 final long token = Binder.clearCallingIdentity();
1809 try {
1810 final boolean emulateFbe = (flags & StorageManager.DEBUG_EMULATE_FBE) != 0;
1811 SystemProperties.set(StorageManager.PROP_EMULATE_FBE, Boolean.toString(emulateFbe));
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07001812
Jeff Sharkey1176e512016-02-29 17:01:26 -07001813 // Perform hard reboot to kick policy into place
1814 mContext.getSystemService(PowerManager.class).reboot(null);
1815 } finally {
1816 Binder.restoreCallingIdentity(token);
1817 }
Jeff Sharkeyba512352015-11-12 20:17:45 -08001818 }
Jeff Sharkey4c099d02015-05-15 13:45:00 -07001819
Jeff Sharkeyba512352015-11-12 20:17:45 -08001820 if ((mask & StorageManager.DEBUG_FORCE_ADOPTABLE) != 0) {
Jeff Sharkeya65e6492017-06-21 13:45:11 -06001821 if (StorageManager.isFileEncryptedNativeOnly()
1822 && !SystemProperties.getBoolean(StorageManager.PROP_ADOPTABLE_FBE, false)) {
Jeff Sharkey6ed74182016-08-23 13:53:53 -06001823 throw new IllegalStateException(
1824 "Adoptable storage not available on device with native FBE");
1825 }
1826
Jeff Sharkeyba512352015-11-12 20:17:45 -08001827 synchronized (mLock) {
1828 mForceAdoptable = (flags & StorageManager.DEBUG_FORCE_ADOPTABLE) != 0;
1829
1830 writeSettingsLocked();
1831 mHandler.obtainMessage(H_RESET).sendToTarget();
1832 }
Jeff Sharkey4c099d02015-05-15 13:45:00 -07001833 }
Jeff Sharkey33dd1562016-04-07 11:05:33 -06001834
1835 if ((mask & (StorageManager.DEBUG_SDCARDFS_FORCE_ON
1836 | StorageManager.DEBUG_SDCARDFS_FORCE_OFF)) != 0) {
1837 final String value;
1838 if ((flags & StorageManager.DEBUG_SDCARDFS_FORCE_ON) != 0) {
1839 value = "force_on";
1840 } else if ((flags & StorageManager.DEBUG_SDCARDFS_FORCE_OFF) != 0) {
1841 value = "force_off";
1842 } else {
1843 value = "";
1844 }
1845
1846 final long token = Binder.clearCallingIdentity();
1847 try {
1848 SystemProperties.set(StorageManager.PROP_SDCARDFS, value);
1849
1850 // Reset storage to kick new setting into place
1851 mHandler.obtainMessage(H_RESET).sendToTarget();
1852 } finally {
1853 Binder.restoreCallingIdentity(token);
1854 }
1855 }
Jeff Sharkeye53e2d92017-03-25 23:14:06 -06001856
1857 if ((mask & StorageManager.DEBUG_VIRTUAL_DISK) != 0) {
1858 final boolean enabled = (flags & StorageManager.DEBUG_VIRTUAL_DISK) != 0;
1859
1860 final long token = Binder.clearCallingIdentity();
1861 try {
1862 SystemProperties.set(StorageManager.PROP_VIRTUAL_DISK, Boolean.toString(enabled));
1863
1864 // Reset storage to kick new setting into place
1865 mHandler.obtainMessage(H_RESET).sendToTarget();
1866 } finally {
1867 Binder.restoreCallingIdentity(token);
1868 }
1869 }
Jeff Sharkey4c099d02015-05-15 13:45:00 -07001870 }
1871
1872 @Override
Jeff Sharkey275e3e42015-04-24 16:10:32 -07001873 public String getPrimaryStorageUuid() {
Jeff Sharkey620b32b2015-04-23 19:36:02 -07001874 synchronized (mLock) {
1875 return mPrimaryStorageUuid;
1876 }
1877 }
1878
1879 @Override
Jeff Sharkey275e3e42015-04-24 16:10:32 -07001880 public void setPrimaryStorageUuid(String volumeUuid, IPackageMoveObserver callback) {
1881 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
Jeff Sharkey620b32b2015-04-23 19:36:02 -07001882
Jeff Sharkeya31460c2016-06-22 09:04:33 -06001883 final VolumeInfo from;
1884 final VolumeInfo to;
1885
Jeff Sharkey275e3e42015-04-24 16:10:32 -07001886 synchronized (mLock) {
Jeff Sharkeyfced5342015-05-10 14:53:34 -07001887 if (Objects.equals(mPrimaryStorageUuid, volumeUuid)) {
1888 throw new IllegalArgumentException("Primary storage already at " + volumeUuid);
Jeff Sharkey275e3e42015-04-24 16:10:32 -07001889 }
1890
1891 if (mMoveCallback != null) {
1892 throw new IllegalStateException("Move already in progress");
1893 }
1894 mMoveCallback = callback;
1895 mMoveTargetUuid = volumeUuid;
1896
Jeff Sharkeya65e6492017-06-21 13:45:11 -06001897 // We need all the users unlocked to move their primary storage
1898 final List<UserInfo> users = mContext.getSystemService(UserManager.class).getUsers();
1899 for (UserInfo user : users) {
1900 if (StorageManager.isFileEncryptedNativeOrEmulated()
1901 && !isUserKeyUnlocked(user.id)) {
1902 Slog.w(TAG, "Failing move due to locked user " + user.id);
1903 onMoveStatusLocked(PackageManager.MOVE_FAILED_LOCKED_USER);
1904 return;
1905 }
1906 }
1907
Jeff Sharkeyfced5342015-05-10 14:53:34 -07001908 // When moving to/from primary physical volume, we probably just nuked
1909 // the current storage location, so we have nothing to move.
1910 if (Objects.equals(StorageManager.UUID_PRIMARY_PHYSICAL, mPrimaryStorageUuid)
1911 || Objects.equals(StorageManager.UUID_PRIMARY_PHYSICAL, volumeUuid)) {
1912 Slog.d(TAG, "Skipping move to/from primary physical");
1913 onMoveStatusLocked(MOVE_STATUS_COPY_FINISHED);
1914 onMoveStatusLocked(PackageManager.MOVE_SUCCEEDED);
Jeff Sharkey5a9bb742015-11-03 10:15:57 -08001915 mHandler.obtainMessage(H_RESET).sendToTarget();
Jeff Sharkeya31460c2016-06-22 09:04:33 -06001916 return;
Jeff Sharkeyfced5342015-05-10 14:53:34 -07001917
1918 } else {
Jeff Sharkeya31460c2016-06-22 09:04:33 -06001919 from = findStorageForUuid(mPrimaryStorageUuid);
1920 to = findStorageForUuid(volumeUuid);
Jeff Sharkeyef10ee02015-07-05 14:17:27 -07001921
1922 if (from == null) {
1923 Slog.w(TAG, "Failing move due to missing from volume " + mPrimaryStorageUuid);
1924 onMoveStatusLocked(PackageManager.MOVE_FAILED_INTERNAL_ERROR);
1925 return;
1926 } else if (to == null) {
1927 Slog.w(TAG, "Failing move due to missing to volume " + volumeUuid);
1928 onMoveStatusLocked(PackageManager.MOVE_FAILED_INTERNAL_ERROR);
1929 return;
1930 }
Jeff Sharkey275e3e42015-04-24 16:10:32 -07001931 }
Jeff Sharkey620b32b2015-04-23 19:36:02 -07001932 }
Jeff Sharkeya31460c2016-06-22 09:04:33 -06001933
1934 try {
Jeff Sharkeyb302c542017-09-15 12:57:59 -06001935 mVold.moveStorage(from.id, to.id, new IVoldTaskListener.Stub() {
1936 @Override
1937 public void onStatus(int status, PersistableBundle extras) {
1938 synchronized (mLock) {
1939 onMoveStatusLocked(status);
1940 }
1941 }
1942
1943 @Override
1944 public void onFinished(int status, PersistableBundle extras) {
1945 // Not currently used
1946 }
1947 });
Jeff Sharkeyace874b2017-09-07 15:27:33 -06001948 } catch (Exception e) {
1949 Slog.wtf(TAG, e);
Jeff Sharkeya31460c2016-06-22 09:04:33 -06001950 }
Jeff Sharkey620b32b2015-04-23 19:36:02 -07001951 }
1952
San Mehatb1043402010-02-05 08:26:50 -08001953 private void warnOnNotMounted() {
Jeff Sharkey48877892015-03-18 11:27:19 -07001954 synchronized (mLock) {
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07001955 for (int i = 0; i < mVolumes.size(); i++) {
1956 final VolumeInfo vol = mVolumes.valueAt(i);
Jeff Sharkey27de30d2015-04-18 16:20:27 -07001957 if (vol.isPrimary() && vol.isMountedWritable()) {
Jeff Sharkey48877892015-03-18 11:27:19 -07001958 // Cool beans, we have a mounted primary volume
1959 return;
1960 }
Jeff Sharkey32ee8312012-09-30 13:21:31 -07001961 }
San Mehatb1043402010-02-05 08:26:50 -08001962 }
Jeff Sharkey48877892015-03-18 11:27:19 -07001963
1964 Slog.w(TAG, "No primary storage mounted!");
San Mehatb1043402010-02-05 08:26:50 -08001965 }
1966
Kenny Roota02b8b02010-08-05 16:14:17 -07001967 private boolean isUidOwnerOfPackageOrSystem(String packageName, int callerUid) {
1968 if (callerUid == android.os.Process.SYSTEM_UID) {
1969 return true;
1970 }
1971
Kenny Root02c87302010-07-01 08:10:18 -07001972 if (packageName == null) {
1973 return false;
1974 }
1975
Jeff Sharkeycd654482016-01-08 17:42:11 -07001976 final int packageUid = mPms.getPackageUid(packageName,
1977 PackageManager.MATCH_DEBUG_TRIAGED_MISSING, UserHandle.getUserId(callerUid));
Kenny Root02c87302010-07-01 08:10:18 -07001978
1979 if (DEBUG_OBB) {
1980 Slog.d(TAG, "packageName = " + packageName + ", packageUid = " +
1981 packageUid + ", callerUid = " + callerUid);
1982 }
1983
1984 return callerUid == packageUid;
1985 }
1986
Jeff Sharkey54402792017-09-15 16:05:19 -06001987 @Override
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07001988 public String getMountedObbPath(String rawPath) {
1989 Preconditions.checkNotNull(rawPath, "rawPath cannot be null");
Kenny Rootaf9d6672010-10-08 09:21:39 -07001990
Kenny Root02c87302010-07-01 08:10:18 -07001991 warnOnNotMounted();
1992
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07001993 final ObbState state;
Rubin Xucd7a0142015-04-17 23:45:27 +01001994 synchronized (mObbMounts) {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07001995 state = mObbPathToStateMap.get(rawPath);
1996 }
1997 if (state == null) {
1998 Slog.w(TAG, "Failed to find OBB mounted at " + rawPath);
1999 return null;
2000 }
2001
Jeff Sharkey54402792017-09-15 16:05:19 -06002002 return findVolumeByIdOrThrow(state.volId).getPath().getAbsolutePath();
Kenny Root02c87302010-07-01 08:10:18 -07002003 }
2004
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002005 @Override
2006 public boolean isObbMounted(String rawPath) {
2007 Preconditions.checkNotNull(rawPath, "rawPath cannot be null");
Kenny Rootaf9d6672010-10-08 09:21:39 -07002008 synchronized (mObbMounts) {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002009 return mObbPathToStateMap.containsKey(rawPath);
Kenny Rootaf9d6672010-10-08 09:21:39 -07002010 }
Kenny Root02c87302010-07-01 08:10:18 -07002011 }
2012
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002013 @Override
2014 public void mountObb(
2015 String rawPath, String canonicalPath, String key, IObbActionListener token, int nonce) {
2016 Preconditions.checkNotNull(rawPath, "rawPath cannot be null");
2017 Preconditions.checkNotNull(canonicalPath, "canonicalPath cannot be null");
2018 Preconditions.checkNotNull(token, "token cannot be null");
Kenny Rootaf9d6672010-10-08 09:21:39 -07002019
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002020 final int callingUid = Binder.getCallingUid();
Jeff Sharkey41cd6812017-09-11 10:32:17 -06002021 final ObbState obbState = new ObbState(rawPath, canonicalPath,
2022 callingUid, token, nonce, null);
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002023 final ObbAction action = new MountObbAction(obbState, key, callingUid);
Kenny Roota02b8b02010-08-05 16:14:17 -07002024 mObbActionHandler.sendMessage(mObbActionHandler.obtainMessage(OBB_RUN_ACTION, action));
2025
2026 if (DEBUG_OBB)
2027 Slog.i(TAG, "Send to OBB handler: " + action.toString());
Kenny Root02c87302010-07-01 08:10:18 -07002028 }
2029
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002030 @Override
2031 public void unmountObb(String rawPath, boolean force, IObbActionListener token, int nonce) {
2032 Preconditions.checkNotNull(rawPath, "rawPath cannot be null");
2033
2034 final ObbState existingState;
Rubin Xucd7a0142015-04-17 23:45:27 +01002035 synchronized (mObbMounts) {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002036 existingState = mObbPathToStateMap.get(rawPath);
Kenny Rootf1121dc2010-09-29 07:30:53 -07002037 }
2038
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002039 if (existingState != null) {
2040 // TODO: separate state object from request data
2041 final int callingUid = Binder.getCallingUid();
Jeff Sharkey41cd6812017-09-11 10:32:17 -06002042 final ObbState newState = new ObbState(rawPath, existingState.canonicalPath,
2043 callingUid, token, nonce, existingState.volId);
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002044 final ObbAction action = new UnmountObbAction(newState, force);
2045 mObbActionHandler.sendMessage(mObbActionHandler.obtainMessage(OBB_RUN_ACTION, action));
Kenny Root02c87302010-07-01 08:10:18 -07002046
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002047 if (DEBUG_OBB)
2048 Slog.i(TAG, "Send to OBB handler: " + action.toString());
2049 } else {
2050 Slog.w(TAG, "Unknown OBB mount at " + rawPath);
2051 }
Kenny Roota02b8b02010-08-05 16:14:17 -07002052 }
2053
Ben Komalo444eca22011-09-01 15:17:44 -07002054 @Override
2055 public int getEncryptionState() {
2056 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
2057 "no permission to access the crypt keeper");
2058
Ben Komalo444eca22011-09-01 15:17:44 -07002059 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002060 return mVold.fdeComplete();
2061 } catch (Exception e) {
2062 Slog.wtf(TAG, e);
Sudheer Shankaf7341142016-10-18 17:15:18 -07002063 return StorageManager.ENCRYPTION_STATE_ERROR_UNKNOWN;
Ben Komalo444eca22011-09-01 15:17:44 -07002064 }
2065 }
2066
2067 @Override
Jason parks5af0b912010-11-29 09:05:25 -06002068 public int decryptStorage(String password) {
Jason parks8888c592011-01-20 22:46:41 -06002069 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
2070 "no permission to access the crypt keeper");
Jason parks5af0b912010-11-29 09:05:25 -06002071
Jeff Sharkey8058fe62017-09-13 11:50:33 -06002072 if (TextUtils.isEmpty(password)) {
2073 throw new IllegalArgumentException("password cannot be empty");
2074 }
2075
Jason parks5af0b912010-11-29 09:05:25 -06002076 if (DEBUG_EVENTS) {
2077 Slog.i(TAG, "decrypting storage...");
2078 }
2079
2080 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002081 mVold.fdeCheckPassword(password);
2082 mHandler.postDelayed(() -> {
2083 try {
2084 mVold.fdeRestart();
2085 } catch (Exception e) {
2086 Slog.wtf(TAG, e);
2087 }
2088 }, DateUtils.SECOND_IN_MILLIS);
2089 return 0;
2090 } catch (Exception e) {
2091 Slog.wtf(TAG, e);
2092 return StorageManager.ENCRYPTION_STATE_ERROR_UNKNOWN;
Jason parks5af0b912010-11-29 09:05:25 -06002093 }
Jason parks5af0b912010-11-29 09:05:25 -06002094 }
2095
Jeff Sharkey54402792017-09-15 16:05:19 -06002096 @Override
Paul Lawrence46791e72014-04-03 09:10:26 -07002097 public int encryptStorage(int type, String password) {
Jason parks8888c592011-01-20 22:46:41 -06002098 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
2099 "no permission to access the crypt keeper");
Jason parks56aa5322011-01-07 09:01:15 -06002100
Jeff Sharkey8058fe62017-09-13 11:50:33 -06002101 if (type == StorageManager.CRYPT_TYPE_DEFAULT) {
2102 password = "";
2103 } else if (TextUtils.isEmpty(password)) {
2104 throw new IllegalArgumentException("password cannot be empty");
2105 }
2106
Jason parks56aa5322011-01-07 09:01:15 -06002107 if (DEBUG_EVENTS) {
Jason parks8888c592011-01-20 22:46:41 -06002108 Slog.i(TAG, "encrypting storage...");
Jason parks56aa5322011-01-07 09:01:15 -06002109 }
2110
2111 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002112 mVold.fdeEnable(type, password, IVold.ENCRYPTION_FLAG_IN_PLACE);
Jeff Sharkey43e12112017-09-12 16:31:45 -06002113 } catch (Exception e) {
2114 Slog.wtf(TAG, e);
2115 return -1;
Jason parks56aa5322011-01-07 09:01:15 -06002116 }
2117
2118 return 0;
2119 }
2120
Paul Lawrence8e397362014-01-27 15:22:30 -08002121 /** Set the password for encrypting the master key.
2122 * @param type One of the CRYPTO_TYPE_XXX consts defined in StorageManager.
2123 * @param password The password to set.
2124 */
Jeff Sharkey54402792017-09-15 16:05:19 -06002125 @Override
Paul Lawrence8e397362014-01-27 15:22:30 -08002126 public int changeEncryptionPassword(int type, String password) {
Jason parksf7b3cd42011-01-27 09:28:25 -06002127 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
2128 "no permission to access the crypt keeper");
2129
Jeff Sharkey8058fe62017-09-13 11:50:33 -06002130 if (type == StorageManager.CRYPT_TYPE_DEFAULT) {
2131 password = "";
2132 } else if (TextUtils.isEmpty(password)) {
2133 throw new IllegalArgumentException("password cannot be empty");
2134 }
2135
Jason parksf7b3cd42011-01-27 09:28:25 -06002136 if (DEBUG_EVENTS) {
2137 Slog.i(TAG, "changing encryption password...");
2138 }
2139
2140 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002141 mVold.fdeChangePassword(type, password);
2142 return 0;
2143 } catch (Exception e) {
2144 Slog.wtf(TAG, e);
2145 return -1;
Jason parksf7b3cd42011-01-27 09:28:25 -06002146 }
2147 }
2148
Christopher Tate32418be2011-10-10 13:51:12 -07002149 /**
2150 * Validate a user-supplied password string with cryptfs
2151 */
2152 @Override
2153 public int verifyEncryptionPassword(String password) throws RemoteException {
2154 // Only the system process is permitted to validate passwords
2155 if (Binder.getCallingUid() != android.os.Process.SYSTEM_UID) {
2156 throw new SecurityException("no permission to access the crypt keeper");
2157 }
2158
2159 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
2160 "no permission to access the crypt keeper");
2161
2162 if (TextUtils.isEmpty(password)) {
2163 throw new IllegalArgumentException("password cannot be empty");
2164 }
2165
Christopher Tate32418be2011-10-10 13:51:12 -07002166 if (DEBUG_EVENTS) {
2167 Slog.i(TAG, "validating encryption password...");
2168 }
2169
2170 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002171 mVold.fdeVerifyPassword(password);
2172 return 0;
2173 } catch (Exception e) {
2174 Slog.wtf(TAG, e);
2175 return -1;
Christopher Tate32418be2011-10-10 13:51:12 -07002176 }
2177 }
2178
Paul Lawrence8e397362014-01-27 15:22:30 -08002179 /**
2180 * Get the type of encryption used to encrypt the master key.
2181 * @return The type, one of the CRYPT_TYPE_XXX consts from StorageManager.
2182 */
2183 @Override
Svetoslav16e4a1a2014-09-29 18:16:20 -07002184 public int getPasswordType() {
Paul Lawrence76a40572017-03-15 11:08:04 -07002185 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
Paul Lawrence9de713d2016-05-02 22:45:33 +00002186 "no permission to access the crypt keeper");
2187
Paul Lawrence8e397362014-01-27 15:22:30 -08002188 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002189 return mVold.fdeGetPasswordType();
2190 } catch (Exception e) {
2191 Slog.wtf(TAG, e);
2192 return -1;
Paul Lawrence8e397362014-01-27 15:22:30 -08002193 }
2194 }
2195
Paul Lawrencee51dcf92014-03-18 10:56:00 -07002196 /**
2197 * Set a field in the crypto header.
2198 * @param field field to set
2199 * @param contents contents to set in field
2200 */
2201 @Override
2202 public void setField(String field, String contents) throws RemoteException {
Paul Lawrence76a40572017-03-15 11:08:04 -07002203 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
Paul Lawrence0bbd1082016-04-26 15:21:02 -07002204 "no permission to access the crypt keeper");
Paul Lawrencee51dcf92014-03-18 10:56:00 -07002205
Paul Lawrencee51dcf92014-03-18 10:56:00 -07002206 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002207 mVold.fdeSetField(field, contents);
2208 return;
2209 } catch (Exception e) {
2210 Slog.wtf(TAG, e);
2211 return;
Paul Lawrencee51dcf92014-03-18 10:56:00 -07002212 }
2213 }
2214
2215 /**
2216 * Gets a field from the crypto header.
2217 * @param field field to get
2218 * @return contents of field
2219 */
2220 @Override
2221 public String getField(String field) throws RemoteException {
Paul Lawrence76a40572017-03-15 11:08:04 -07002222 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
Paul Lawrence0bbd1082016-04-26 15:21:02 -07002223 "no permission to access the crypt keeper");
Paul Lawrencee51dcf92014-03-18 10:56:00 -07002224
Paul Lawrencee51dcf92014-03-18 10:56:00 -07002225 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002226 return mVold.fdeGetField(field);
2227 } catch (Exception e) {
2228 Slog.wtf(TAG, e);
2229 return null;
Paul Lawrencee51dcf92014-03-18 10:56:00 -07002230 }
2231 }
2232
Paul Lawrence3806d9c2015-10-29 10:30:46 -07002233 /**
2234 * Is userdata convertible to file based encryption?
2235 * @return non zero for convertible
2236 */
2237 @Override
2238 public boolean isConvertibleToFBE() throws RemoteException {
Paul Lawrence76a40572017-03-15 11:08:04 -07002239 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
Paul Lawrence0bbd1082016-04-26 15:21:02 -07002240 "no permission to access the crypt keeper");
Paul Lawrence3806d9c2015-10-29 10:30:46 -07002241
Paul Lawrence3806d9c2015-10-29 10:30:46 -07002242 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002243 return mVold.isConvertibleToFbe();
2244 } catch (Exception e) {
2245 Slog.wtf(TAG, e);
2246 return false;
Paul Lawrence3806d9c2015-10-29 10:30:46 -07002247 }
2248 }
2249
Jeff Sharkeyb049e212012-09-07 23:16:01 -07002250 @Override
Paul Lawrence945490c2014-03-27 16:37:28 +00002251 public String getPassword() throws RemoteException {
Paul Lawrence76a40572017-03-15 11:08:04 -07002252 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
Rubin Xucd7a0142015-04-17 23:45:27 +01002253 "only keyguard can retrieve password");
Paul Lawrence0bbd1082016-04-26 15:21:02 -07002254
Paul Lawrence945490c2014-03-27 16:37:28 +00002255 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002256 return mVold.fdeGetPassword();
2257 } catch (Exception e) {
2258 Slog.wtf(TAG, e);
Paul Lawrence24063b52015-01-06 13:11:23 -08002259 return null;
Paul Lawrence945490c2014-03-27 16:37:28 +00002260 }
2261 }
2262
2263 @Override
2264 public void clearPassword() throws RemoteException {
Paul Lawrence76a40572017-03-15 11:08:04 -07002265 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
Paul Lawrence0bbd1082016-04-26 15:21:02 -07002266 "only keyguard can clear password");
2267
Paul Lawrence945490c2014-03-27 16:37:28 +00002268 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002269 mVold.fdeClearPassword();
2270 return;
2271 } catch (Exception e) {
2272 Slog.wtf(TAG, e);
2273 return;
Paul Lawrence945490c2014-03-27 16:37:28 +00002274 }
2275 }
2276
2277 @Override
Lenka Trochtovac4dd0212015-11-18 12:22:06 +01002278 public void createUserKey(int userId, int serialNumber, boolean ephemeral) {
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002279 enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
Paul Crowleybcf48ed2015-04-22 13:36:59 +01002280
Paul Crowleybcf48ed2015-04-22 13:36:59 +01002281 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002282 mVold.createUserKey(userId, serialNumber, ephemeral);
Jeff Sharkey43e12112017-09-12 16:31:45 -06002283 } catch (Exception e) {
2284 Slog.wtf(TAG, e);
Paul Crowleybcf48ed2015-04-22 13:36:59 +01002285 }
2286 }
2287
Paul Crowley7ec733f2015-05-19 12:42:00 +01002288 @Override
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002289 public void destroyUserKey(int userId) {
2290 enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
Paul Crowley7ec733f2015-05-19 12:42:00 +01002291
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002292 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002293 mVold.destroyUserKey(userId);
Jeff Sharkey43e12112017-09-12 16:31:45 -06002294 } catch (Exception e) {
2295 Slog.wtf(TAG, e);
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002296 }
2297 }
2298
Jeff Sharkey43e12112017-09-12 16:31:45 -06002299 private String encodeBytes(byte[] bytes) {
Paul Crowleyfaeb3eb2016-02-08 15:58:29 +00002300 if (ArrayUtils.isEmpty(bytes)) {
Jeff Sharkey43e12112017-09-12 16:31:45 -06002301 return "!";
Paul Crowleyfaeb3eb2016-02-08 15:58:29 +00002302 } else {
Jeff Sharkey43e12112017-09-12 16:31:45 -06002303 return HexDump.toHexString(bytes);
Paul Crowleyfaeb3eb2016-02-08 15:58:29 +00002304 }
2305 }
2306
Paul Crowleycc701552016-05-17 14:18:49 -07002307 /*
2308 * Add this token/secret pair to the set of ways we can recover a disk encryption key.
2309 * Changing the token/secret for a disk encryption key is done in two phases: first, adding
2310 * a new token/secret pair with this call, then delting all other pairs with
2311 * fixateNewestUserKeyAuth. This allows other places where a credential is used, such as
2312 * Gatekeeper, to be updated between the two calls.
2313 */
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002314 @Override
Paul Crowleycc701552016-05-17 14:18:49 -07002315 public void addUserKeyAuth(int userId, int serialNumber, byte[] token, byte[] secret) {
Paul Crowleyfaeb3eb2016-02-08 15:58:29 +00002316 enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
Paul Crowleyfaeb3eb2016-02-08 15:58:29 +00002317
2318 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002319 mVold.addUserKeyAuth(userId, serialNumber, encodeBytes(token), encodeBytes(secret));
Jeff Sharkey43e12112017-09-12 16:31:45 -06002320 } catch (Exception e) {
2321 Slog.wtf(TAG, e);
Paul Crowleycc701552016-05-17 14:18:49 -07002322 }
2323 }
2324
2325 /*
2326 * Delete all disk encryption token/secret pairs except the most recently added one
2327 */
2328 @Override
2329 public void fixateNewestUserKeyAuth(int userId) {
2330 enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
Paul Crowleycc701552016-05-17 14:18:49 -07002331
2332 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002333 mVold.fixateNewestUserKeyAuth(userId);
Jeff Sharkey43e12112017-09-12 16:31:45 -06002334 } catch (Exception e) {
2335 Slog.wtf(TAG, e);
Paul Crowleyfaeb3eb2016-02-08 15:58:29 +00002336 }
2337 }
2338
2339 @Override
2340 public void unlockUserKey(int userId, int serialNumber, byte[] token, byte[] secret) {
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002341 enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002342
Jeff Sharkeyce18c812016-04-27 16:00:41 -06002343 if (StorageManager.isFileEncryptedNativeOrEmulated()) {
Rubin Xu3bf722a2016-12-15 16:07:38 +00002344 // When a user has secure lock screen, require secret to actually unlock.
2345 // This check is mostly in place for emulation mode.
2346 if (mLockPatternUtils.isSecure(userId) && ArrayUtils.isEmpty(secret)) {
2347 throw new IllegalStateException("Secret required to unlock secure user " + userId);
Jeff Sharkeyce18c812016-04-27 16:00:41 -06002348 }
Jeff Sharkeyb9fe5372015-12-03 15:23:08 -07002349
Jeff Sharkeyce18c812016-04-27 16:00:41 -06002350 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002351 mVold.unlockUserKey(userId, serialNumber, encodeBytes(token),
2352 encodeBytes(secret));
Jeff Sharkey43e12112017-09-12 16:31:45 -06002353 } catch (Exception e) {
2354 Slog.wtf(TAG, e);
2355 return;
Jeff Sharkeyce18c812016-04-27 16:00:41 -06002356 }
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002357 }
2358
2359 synchronized (mLock) {
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07002360 mLocalUnlockedUsers = ArrayUtils.appendInt(mLocalUnlockedUsers, userId);
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002361 }
Paul Crowley9139a782017-07-26 13:29:25 -07002362 if (userId == UserHandle.USER_SYSTEM) {
2363 String propertyName = "sys.user." + userId + ".ce_available";
2364 Slog.d(TAG, "Setting property: " + propertyName + "=true");
2365 SystemProperties.set(propertyName, "true");
2366 }
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002367 }
2368
2369 @Override
2370 public void lockUserKey(int userId) {
2371 enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002372
2373 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002374 mVold.lockUserKey(userId);
Jeff Sharkey43e12112017-09-12 16:31:45 -06002375 } catch (Exception e) {
2376 Slog.wtf(TAG, e);
2377 return;
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002378 }
2379
2380 synchronized (mLock) {
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07002381 mLocalUnlockedUsers = ArrayUtils.removeInt(mLocalUnlockedUsers, userId);
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002382 }
2383 }
2384
2385 @Override
2386 public boolean isUserKeyUnlocked(int userId) {
Jeff Sharkeyce18c812016-04-27 16:00:41 -06002387 synchronized (mLock) {
2388 return ArrayUtils.contains(mLocalUnlockedUsers, userId);
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002389 }
2390 }
2391
2392 @Override
Jeff Sharkey47f71082016-02-01 17:03:54 -07002393 public void prepareUserStorage(String volumeUuid, int userId, int serialNumber, int flags) {
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002394 enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002395
2396 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002397 mVold.prepareUserStorage(volumeUuid, userId, serialNumber, flags);
Jeff Sharkey43e12112017-09-12 16:31:45 -06002398 } catch (Exception e) {
2399 Slog.wtf(TAG, e);
Paul Crowley7ec733f2015-05-19 12:42:00 +01002400 }
2401 }
2402
Paul Crowleybcf48ed2015-04-22 13:36:59 +01002403 @Override
Jeff Sharkeyfcf1e552016-04-14 20:44:58 -06002404 public void destroyUserStorage(String volumeUuid, int userId, int flags) {
2405 enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
Jeff Sharkeyfcf1e552016-04-14 20:44:58 -06002406
2407 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002408 mVold.destroyUserStorage(volumeUuid, userId, flags);
Jeff Sharkey43e12112017-09-12 16:31:45 -06002409 } catch (Exception e) {
2410 Slog.wtf(TAG, e);
Jeff Sharkeyfcf1e552016-04-14 20:44:58 -06002411 }
2412 }
2413
Rubin Xuee67b612017-04-27 17:01:05 +01002414 @Override
2415 public void secdiscard(String path) {
2416 enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
Rubin Xuee67b612017-04-27 17:01:05 +01002417
2418 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002419 mVold.secdiscard(path);
Jeff Sharkey43e12112017-09-12 16:31:45 -06002420 } catch (Exception e) {
2421 Slog.wtf(TAG, e);
Rubin Xuee67b612017-04-27 17:01:05 +01002422 }
2423 }
2424
Daichi Hironoe56740d2017-02-02 13:56:45 +09002425 class AppFuseMountScope extends AppFuseBridge.MountScope {
Daichi Hirono812c95d2017-02-08 16:20:20 +09002426 boolean opened = false;
2427
2428 public AppFuseMountScope(int uid, int pid, int mountId) {
2429 super(uid, pid, mountId);
2430 }
2431
2432 @Override
2433 public ParcelFileDescriptor open() throws NativeDaemonConnectorException {
Jeff Sharkey54402792017-09-15 16:05:19 -06002434 try {
2435 return new ParcelFileDescriptor(
2436 mVold.mountAppFuse(uid, Process.myPid(), mountId));
2437 } catch (Exception e) {
2438 throw new NativeDaemonConnectorException("Failed to mount", e);
Daichi Hirono812c95d2017-02-08 16:20:20 +09002439 }
Daichi Hirono9fb00182016-11-08 14:12:17 +09002440 }
2441
2442 @Override
Daichi Hironoe56740d2017-02-02 13:56:45 +09002443 public void close() throws Exception {
Daichi Hirono812c95d2017-02-08 16:20:20 +09002444 if (opened) {
Jeff Sharkey54402792017-09-15 16:05:19 -06002445 mVold.unmountAppFuse(uid, Process.myPid(), mountId);
Daichi Hirono812c95d2017-02-08 16:20:20 +09002446 opened = false;
2447 }
Daichi Hirono9fb00182016-11-08 14:12:17 +09002448 }
2449 }
2450
2451 @Override
Daichi Hirono812c95d2017-02-08 16:20:20 +09002452 public @Nullable AppFuseMount mountProxyFileDescriptorBridge() {
Daichi Hironoe56740d2017-02-02 13:56:45 +09002453 Slog.v(TAG, "mountProxyFileDescriptorBridge");
Daichi Hirono9fb00182016-11-08 14:12:17 +09002454 final int uid = Binder.getCallingUid();
2455 final int pid = Binder.getCallingPid();
Daichi Hirono9fb00182016-11-08 14:12:17 +09002456
Daichi Hironoe56740d2017-02-02 13:56:45 +09002457 while (true) {
2458 synchronized (mAppFuseLock) {
2459 boolean newlyCreated = false;
2460 if (mAppFuseBridge == null) {
2461 mAppFuseBridge = new AppFuseBridge();
2462 new Thread(mAppFuseBridge, AppFuseBridge.TAG).start();
2463 newlyCreated = true;
Daichi Hirono9fb00182016-11-08 14:12:17 +09002464 }
Daichi Hironoe56740d2017-02-02 13:56:45 +09002465 try {
2466 final int name = mNextAppFuseName++;
2467 try {
2468 return new AppFuseMount(
Daichi Hirono812c95d2017-02-08 16:20:20 +09002469 name, mAppFuseBridge.addBridge(new AppFuseMountScope(uid, pid, name)));
2470 } catch (FuseUnavailableMountException e) {
Daichi Hironoe56740d2017-02-02 13:56:45 +09002471 if (newlyCreated) {
2472 // If newly created bridge fails, it's a real error.
Daichi Hirono812c95d2017-02-08 16:20:20 +09002473 Slog.e(TAG, "", e);
2474 return null;
Daichi Hironoe56740d2017-02-02 13:56:45 +09002475 }
2476 // It seems the thread of mAppFuseBridge has already been terminated.
2477 mAppFuseBridge = null;
2478 }
2479 } catch (NativeDaemonConnectorException e) {
2480 throw e.rethrowAsParcelableException();
2481 }
Daichi Hirono9fb00182016-11-08 14:12:17 +09002482 }
Daichi Hirono9fb00182016-11-08 14:12:17 +09002483 }
2484 }
2485
2486 @Override
Daichi Hirono812c95d2017-02-08 16:20:20 +09002487 public @Nullable ParcelFileDescriptor openProxyFileDescriptor(
2488 int mountId, int fileId, int mode) {
2489 Slog.v(TAG, "mountProxyFileDescriptor");
Daichi Hirono9fb00182016-11-08 14:12:17 +09002490 final int pid = Binder.getCallingPid();
2491 try {
2492 synchronized (mAppFuseLock) {
Daichi Hironoe56740d2017-02-02 13:56:45 +09002493 if (mAppFuseBridge == null) {
Daichi Hirono812c95d2017-02-08 16:20:20 +09002494 Slog.e(TAG, "FuseBridge has not been created");
2495 return null;
Daichi Hirono9fb00182016-11-08 14:12:17 +09002496 }
Daichi Hironoe56740d2017-02-02 13:56:45 +09002497 return mAppFuseBridge.openFile(pid, mountId, fileId, mode);
Daichi Hirono9fb00182016-11-08 14:12:17 +09002498 }
Daichi Hirono812c95d2017-02-08 16:20:20 +09002499 } catch (FuseUnavailableMountException | InterruptedException error) {
2500 Slog.v(TAG, "The mount point has already been invalid", error);
2501 return null;
Daichi Hirono9fb00182016-11-08 14:12:17 +09002502 }
2503 }
2504
Daichi Hirono9e8d9e22015-11-13 14:37:00 +09002505 @Override
Jeff Sharkey2d8b4e82013-09-17 17:30:33 -07002506 public int mkdirs(String callingPkg, String appPath) {
2507 final int userId = UserHandle.getUserId(Binder.getCallingUid());
2508 final UserEnvironment userEnv = new UserEnvironment(userId);
2509
2510 // Validate that reported package name belongs to caller
2511 final AppOpsManager appOps = (AppOpsManager) mContext.getSystemService(
2512 Context.APP_OPS_SERVICE);
2513 appOps.checkPackage(Binder.getCallingUid(), callingPkg);
2514
Jeff Sharkey48877892015-03-18 11:27:19 -07002515 File appFile = null;
Jeff Sharkey2d8b4e82013-09-17 17:30:33 -07002516 try {
Jeff Sharkey48877892015-03-18 11:27:19 -07002517 appFile = new File(appPath).getCanonicalFile();
Jeff Sharkey2d8b4e82013-09-17 17:30:33 -07002518 } catch (IOException e) {
2519 Slog.e(TAG, "Failed to resolve " + appPath + ": " + e);
2520 return -1;
2521 }
2522
2523 // Try translating the app path into a vold path, but require that it
2524 // belong to the calling package.
Jeff Sharkey48877892015-03-18 11:27:19 -07002525 if (FileUtils.contains(userEnv.buildExternalStorageAppDataDirs(callingPkg), appFile) ||
2526 FileUtils.contains(userEnv.buildExternalStorageAppObbDirs(callingPkg), appFile) ||
2527 FileUtils.contains(userEnv.buildExternalStorageAppMediaDirs(callingPkg), appFile)) {
2528 appPath = appFile.getAbsolutePath();
2529 if (!appPath.endsWith("/")) {
2530 appPath = appPath + "/";
2531 }
2532
Jeff Sharkey2d8b4e82013-09-17 17:30:33 -07002533 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002534 mVold.mkdirs(appPath);
Jeff Sharkey2d8b4e82013-09-17 17:30:33 -07002535 return 0;
Jeff Sharkeyace874b2017-09-07 15:27:33 -06002536 } catch (Exception e) {
2537 Slog.wtf(TAG, e);
Jeff Sharkey2d8b4e82013-09-17 17:30:33 -07002538 }
2539 }
2540
Jeff Sharkey48877892015-03-18 11:27:19 -07002541 throw new SecurityException("Invalid mkdirs path: " + appFile);
Jeff Sharkey2d8b4e82013-09-17 17:30:33 -07002542 }
2543
2544 @Override
Jeff Sharkey46349872015-07-28 10:49:47 -07002545 public StorageVolume[] getVolumeList(int uid, String packageName, int flags) {
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07002546 final int userId = UserHandle.getUserId(uid);
Jeff Sharkeyc02bfae2016-03-27 15:06:53 -06002547
Jeff Sharkey46349872015-07-28 10:49:47 -07002548 final boolean forWrite = (flags & StorageManager.FLAG_FOR_WRITE) != 0;
Jeff Sharkeyc02bfae2016-03-27 15:06:53 -06002549 final boolean realState = (flags & StorageManager.FLAG_REAL_STATE) != 0;
2550 final boolean includeInvisible = (flags & StorageManager.FLAG_INCLUDE_INVISIBLE) != 0;
Jeff Sharkey46349872015-07-28 10:49:47 -07002551
Jeff Sharkeyc02bfae2016-03-27 15:06:53 -06002552 final boolean userKeyUnlocked;
2553 final boolean storagePermission;
2554 final long token = Binder.clearCallingIdentity();
Svetoslav38c3dbb2015-07-14 11:27:06 -07002555 try {
Jeff Sharkeyc02bfae2016-03-27 15:06:53 -06002556 userKeyUnlocked = isUserKeyUnlocked(userId);
Sudheer Shanka2250d562016-11-07 15:41:02 -08002557 storagePermission = mStorageManagerInternal.hasExternalStorage(uid, packageName);
Svetoslav38c3dbb2015-07-14 11:27:06 -07002558 } finally {
Jeff Sharkeyc02bfae2016-03-27 15:06:53 -06002559 Binder.restoreCallingIdentity(token);
Svetoslav38c3dbb2015-07-14 11:27:06 -07002560 }
Svet Ganov6ee871e2015-07-10 14:29:33 -07002561
Jeff Sharkeyc02bfae2016-03-27 15:06:53 -06002562 boolean foundPrimary = false;
2563
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07002564 final ArrayList<StorageVolume> res = new ArrayList<>();
Jeff Sharkey48877892015-03-18 11:27:19 -07002565 synchronized (mLock) {
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07002566 for (int i = 0; i < mVolumes.size(); i++) {
2567 final VolumeInfo vol = mVolumes.valueAt(i);
Jeff Sharkeyc02bfae2016-03-27 15:06:53 -06002568 switch (vol.getType()) {
2569 case VolumeInfo.TYPE_PUBLIC:
2570 case VolumeInfo.TYPE_EMULATED:
2571 break;
2572 default:
2573 continue;
2574 }
2575
2576 boolean match = false;
2577 if (forWrite) {
2578 match = vol.isVisibleForWrite(userId);
2579 } else {
Felipe Leme123a0e72016-06-10 11:09:11 -07002580 match = vol.isVisibleForRead(userId)
2581 || (includeInvisible && vol.getPath() != null);
Jeff Sharkeyc02bfae2016-03-27 15:06:53 -06002582 }
2583 if (!match) continue;
2584
2585 boolean reportUnmounted = false;
2586 if ((vol.getType() == VolumeInfo.TYPE_EMULATED) && !userKeyUnlocked) {
2587 reportUnmounted = true;
2588 } else if (!storagePermission && !realState) {
2589 reportUnmounted = true;
2590 }
2591
2592 final StorageVolume userVol = vol.buildStorageVolume(mContext, userId,
2593 reportUnmounted);
2594 if (vol.isPrimary()) {
2595 res.add(0, userVol);
2596 foundPrimary = true;
2597 } else {
2598 res.add(userVol);
Jeff Sharkeyb049e212012-09-07 23:16:01 -07002599 }
Mike Lockwood8fa5f802011-03-24 08:12:30 -07002600 }
Mike Lockwood8fa5f802011-03-24 08:12:30 -07002601 }
Jeff Sharkey48877892015-03-18 11:27:19 -07002602
2603 if (!foundPrimary) {
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07002604 Log.w(TAG, "No primary storage defined yet; hacking together a stub");
Jeff Sharkey48877892015-03-18 11:27:19 -07002605
2606 final boolean primaryPhysical = SystemProperties.getBoolean(
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07002607 StorageManager.PROP_PRIMARY_PHYSICAL, false);
Jeff Sharkey48877892015-03-18 11:27:19 -07002608
2609 final String id = "stub_primary";
2610 final File path = Environment.getLegacyExternalStorageDirectory();
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07002611 final String description = mContext.getString(android.R.string.unknownName);
Jeff Sharkey48877892015-03-18 11:27:19 -07002612 final boolean primary = true;
2613 final boolean removable = primaryPhysical;
2614 final boolean emulated = !primaryPhysical;
2615 final long mtpReserveSize = 0L;
2616 final boolean allowMassStorage = false;
2617 final long maxFileSize = 0L;
2618 final UserHandle owner = new UserHandle(userId);
2619 final String uuid = null;
Jeff Sharkey48877892015-03-18 11:27:19 -07002620 final String state = Environment.MEDIA_REMOVED;
2621
Jeff Sharkey5af1835d2015-07-07 17:26:59 -07002622 res.add(0, new StorageVolume(id, StorageVolume.STORAGE_ID_INVALID, path,
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07002623 description, primary, removable, emulated, mtpReserveSize,
2624 allowMassStorage, maxFileSize, owner, uuid, state));
Jeff Sharkey48877892015-03-18 11:27:19 -07002625 }
2626
2627 return res.toArray(new StorageVolume[res.size()]);
Mike Lockwood8fa5f802011-03-24 08:12:30 -07002628 }
2629
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07002630 @Override
2631 public DiskInfo[] getDisks() {
2632 synchronized (mLock) {
2633 final DiskInfo[] res = new DiskInfo[mDisks.size()];
2634 for (int i = 0; i < mDisks.size(); i++) {
2635 res[i] = mDisks.valueAt(i);
2636 }
2637 return res;
2638 }
2639 }
2640
2641 @Override
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07002642 public VolumeInfo[] getVolumes(int flags) {
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07002643 synchronized (mLock) {
2644 final VolumeInfo[] res = new VolumeInfo[mVolumes.size()];
2645 for (int i = 0; i < mVolumes.size(); i++) {
2646 res[i] = mVolumes.valueAt(i);
2647 }
2648 return res;
2649 }
2650 }
2651
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07002652 @Override
2653 public VolumeRecord[] getVolumeRecords(int flags) {
2654 synchronized (mLock) {
2655 final VolumeRecord[] res = new VolumeRecord[mRecords.size()];
2656 for (int i = 0; i < mRecords.size(); i++) {
2657 res[i] = mRecords.valueAt(i);
2658 }
2659 return res;
2660 }
2661 }
2662
Jeff Sharkey9bed0702017-01-23 20:37:05 -07002663 @Override
2664 public long getCacheQuotaBytes(String volumeUuid, int uid) {
2665 if (uid != Binder.getCallingUid()) {
2666 mContext.enforceCallingPermission(android.Manifest.permission.STORAGE_INTERNAL, TAG);
2667 }
Daniel Nishi80fdb012017-03-09 14:30:07 -08002668 final long token = Binder.clearCallingIdentity();
2669 final StorageStatsManager stats = mContext.getSystemService(StorageStatsManager.class);
2670 try {
2671 return stats.getCacheQuotaBytes(volumeUuid, uid);
2672 } finally {
2673 Binder.restoreCallingIdentity(token);
2674 }
Jeff Sharkey9bed0702017-01-23 20:37:05 -07002675 }
2676
2677 @Override
2678 public long getCacheSizeBytes(String volumeUuid, int uid) {
2679 if (uid != Binder.getCallingUid()) {
2680 mContext.enforceCallingPermission(android.Manifest.permission.STORAGE_INTERNAL, TAG);
2681 }
2682 final long token = Binder.clearCallingIdentity();
2683 try {
2684 return mContext.getSystemService(StorageStatsManager.class)
2685 .queryStatsForUid(volumeUuid, uid).getCacheBytes();
Jeff Sharkey789a8fc2017-04-16 13:18:35 -06002686 } catch (IOException e) {
2687 throw new ParcelableException(e);
Jeff Sharkey9bed0702017-01-23 20:37:05 -07002688 } finally {
2689 Binder.restoreCallingIdentity(token);
2690 }
2691 }
2692
Jeff Sharkey35e46d22017-06-09 10:01:20 -06002693 private int adjustAllocateFlags(int flags, int callingUid, String callingPackage) {
2694 // Require permission to allocate aggressively
2695 if ((flags & StorageManager.FLAG_ALLOCATE_AGGRESSIVE) != 0) {
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07002696 mContext.enforceCallingOrSelfPermission(
2697 android.Manifest.permission.ALLOCATE_AGGRESSIVE, TAG);
2698 }
2699
Jeff Sharkey35e46d22017-06-09 10:01:20 -06002700 // Apps normally can't directly defy reserved space
2701 flags &= ~StorageManager.FLAG_ALLOCATE_DEFY_ALL_RESERVED;
2702 flags &= ~StorageManager.FLAG_ALLOCATE_DEFY_HALF_RESERVED;
2703
2704 // However, if app is actively using the camera, then we're willing to
2705 // clear up to half of the reserved cache space, since the user might be
2706 // trying to capture an important memory.
2707 final AppOpsManager appOps = mContext.getSystemService(AppOpsManager.class);
2708 final long token = Binder.clearCallingIdentity();
2709 try {
2710 if (appOps.isOperationActive(AppOpsManager.OP_CAMERA, callingUid, callingPackage)) {
2711 Slog.d(TAG, "UID " + callingUid + " is actively using camera;"
2712 + " letting them defy reserved cached data");
2713 flags |= StorageManager.FLAG_ALLOCATE_DEFY_HALF_RESERVED;
2714 }
2715 } finally {
2716 Binder.restoreCallingIdentity(token);
2717 }
2718
2719 return flags;
2720 }
2721
2722 @Override
2723 public long getAllocatableBytes(String volumeUuid, int flags, String callingPackage) {
2724 flags = adjustAllocateFlags(flags, Binder.getCallingUid(), callingPackage);
2725
2726 final StorageManager storage = mContext.getSystemService(StorageManager.class);
2727 final StorageStatsManager stats = mContext.getSystemService(StorageStatsManager.class);
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07002728 final long token = Binder.clearCallingIdentity();
2729 try {
2730 // In general, apps can allocate as much space as they want, except
2731 // we never let them eat into either the minimum cache space or into
Jeff Sharkeyddff8072017-05-26 13:10:46 -06002732 // the low disk warning space. To avoid user confusion, this logic
2733 // should be kept in sync with getFreeBytes().
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07002734 final File path = storage.findPathForUuid(volumeUuid);
Jeff Sharkeyddff8072017-05-26 13:10:46 -06002735
2736 final long usable = path.getUsableSpace();
2737 final long lowReserved = storage.getStorageLowBytes(path);
2738 final long fullReserved = storage.getStorageFullBytes(path);
2739
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07002740 if (stats.isQuotaSupported(volumeUuid)) {
Jeff Sharkeyddff8072017-05-26 13:10:46 -06002741 final long cacheTotal = stats.getCacheBytes(volumeUuid);
Jeff Sharkey35e46d22017-06-09 10:01:20 -06002742 final long cacheReserved = storage.getStorageCacheBytes(path, flags);
Jeff Sharkeyddff8072017-05-26 13:10:46 -06002743 final long cacheClearable = Math.max(0, cacheTotal - cacheReserved);
2744
Jeff Sharkey35e46d22017-06-09 10:01:20 -06002745 if ((flags & StorageManager.FLAG_ALLOCATE_AGGRESSIVE) != 0) {
2746 return Math.max(0, (usable + cacheClearable) - fullReserved);
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07002747 } else {
Jeff Sharkeyddff8072017-05-26 13:10:46 -06002748 return Math.max(0, (usable + cacheClearable) - lowReserved);
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07002749 }
2750 } else {
2751 // When we don't have fast quota information, we ignore cached
2752 // data and only consider unused bytes.
Jeff Sharkey35e46d22017-06-09 10:01:20 -06002753 if ((flags & StorageManager.FLAG_ALLOCATE_AGGRESSIVE) != 0) {
Jeff Sharkeyddff8072017-05-26 13:10:46 -06002754 return Math.max(0, usable - fullReserved);
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07002755 } else {
Jeff Sharkeyddff8072017-05-26 13:10:46 -06002756 return Math.max(0, usable - lowReserved);
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07002757 }
2758 }
Jeff Sharkey789a8fc2017-04-16 13:18:35 -06002759 } catch (IOException e) {
2760 throw new ParcelableException(e);
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07002761 } finally {
2762 Binder.restoreCallingIdentity(token);
2763 }
Jeff Sharkey500ce9e2017-02-12 02:39:24 -07002764 }
2765
2766 @Override
Jeff Sharkey35e46d22017-06-09 10:01:20 -06002767 public void allocateBytes(String volumeUuid, long bytes, int flags, String callingPackage) {
2768 flags = adjustAllocateFlags(flags, Binder.getCallingUid(), callingPackage);
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07002769
Jeff Sharkey35e46d22017-06-09 10:01:20 -06002770 final long allocatableBytes = getAllocatableBytes(volumeUuid, flags, callingPackage);
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07002771 if (bytes > allocatableBytes) {
2772 throw new ParcelableException(new IOException("Failed to allocate " + bytes
2773 + " because only " + allocatableBytes + " allocatable"));
2774 }
2775
Jeff Sharkey35e46d22017-06-09 10:01:20 -06002776 final StorageManager storage = mContext.getSystemService(StorageManager.class);
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07002777 final long token = Binder.clearCallingIdentity();
2778 try {
Jeff Sharkey789a8fc2017-04-16 13:18:35 -06002779 // Free up enough disk space to satisfy both the requested allocation
2780 // and our low disk warning space.
2781 final File path = storage.findPathForUuid(volumeUuid);
Jeff Sharkeyddff8072017-05-26 13:10:46 -06002782 if ((flags & StorageManager.FLAG_ALLOCATE_AGGRESSIVE) != 0) {
2783 bytes += storage.getStorageFullBytes(path);
2784 } else {
2785 bytes += storage.getStorageLowBytes(path);
2786 }
Jeff Sharkey789a8fc2017-04-16 13:18:35 -06002787
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07002788 mPms.freeStorage(volumeUuid, bytes, flags);
2789 } catch (IOException e) {
2790 throw new ParcelableException(e);
2791 } finally {
2792 Binder.restoreCallingIdentity(token);
Jeff Sharkey500ce9e2017-02-12 02:39:24 -07002793 }
2794 }
2795
Kenny Rootaf9d6672010-10-08 09:21:39 -07002796 private void addObbStateLocked(ObbState obbState) throws RemoteException {
2797 final IBinder binder = obbState.getBinder();
2798 List<ObbState> obbStates = mObbMounts.get(binder);
Kenny Root5919ac62010-10-05 09:49:40 -07002799
Kenny Rootaf9d6672010-10-08 09:21:39 -07002800 if (obbStates == null) {
2801 obbStates = new ArrayList<ObbState>();
2802 mObbMounts.put(binder, obbStates);
2803 } else {
2804 for (final ObbState o : obbStates) {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002805 if (o.rawPath.equals(obbState.rawPath)) {
Kenny Rootaf9d6672010-10-08 09:21:39 -07002806 throw new IllegalStateException("Attempt to add ObbState twice. "
Sudheer Shanka2250d562016-11-07 15:41:02 -08002807 + "This indicates an error in the StorageManagerService logic.");
Kenny Root5919ac62010-10-05 09:49:40 -07002808 }
2809 }
Kenny Roota02b8b02010-08-05 16:14:17 -07002810 }
Kenny Rootaf9d6672010-10-08 09:21:39 -07002811
2812 obbStates.add(obbState);
2813 try {
2814 obbState.link();
2815 } catch (RemoteException e) {
2816 /*
2817 * The binder died before we could link it, so clean up our state
2818 * and return failure.
2819 */
2820 obbStates.remove(obbState);
2821 if (obbStates.isEmpty()) {
2822 mObbMounts.remove(binder);
2823 }
2824
2825 // Rethrow the error so mountObb can get it
2826 throw e;
2827 }
2828
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002829 mObbPathToStateMap.put(obbState.rawPath, obbState);
Kenny Roota02b8b02010-08-05 16:14:17 -07002830 }
2831
Kenny Rootaf9d6672010-10-08 09:21:39 -07002832 private void removeObbStateLocked(ObbState obbState) {
2833 final IBinder binder = obbState.getBinder();
2834 final List<ObbState> obbStates = mObbMounts.get(binder);
2835 if (obbStates != null) {
2836 if (obbStates.remove(obbState)) {
2837 obbState.unlink();
Kenny Root05105f72010-09-22 17:29:43 -07002838 }
Kenny Rootaf9d6672010-10-08 09:21:39 -07002839 if (obbStates.isEmpty()) {
2840 mObbMounts.remove(binder);
2841 }
Kenny Roota02b8b02010-08-05 16:14:17 -07002842 }
Kenny Roota02b8b02010-08-05 16:14:17 -07002843
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002844 mObbPathToStateMap.remove(obbState.rawPath);
Kenny Root38cf8862010-09-26 14:18:51 -07002845 }
2846
Kenny Roota02b8b02010-08-05 16:14:17 -07002847 private class ObbActionHandler extends Handler {
2848 private boolean mBound = false;
Kenny Root480afe72010-10-07 10:17:50 -07002849 private final List<ObbAction> mActions = new LinkedList<ObbAction>();
Kenny Roota02b8b02010-08-05 16:14:17 -07002850
2851 ObbActionHandler(Looper l) {
2852 super(l);
2853 }
2854
2855 @Override
2856 public void handleMessage(Message msg) {
2857 switch (msg.what) {
2858 case OBB_RUN_ACTION: {
Kenny Root480afe72010-10-07 10:17:50 -07002859 final ObbAction action = (ObbAction) msg.obj;
Kenny Roota02b8b02010-08-05 16:14:17 -07002860
2861 if (DEBUG_OBB)
2862 Slog.i(TAG, "OBB_RUN_ACTION: " + action.toString());
2863
2864 // If a bind was already initiated we don't really
2865 // need to do anything. The pending install
2866 // will be processed later on.
2867 if (!mBound) {
2868 // If this is the only one pending we might
2869 // have to bind to the service again.
2870 if (!connectToService()) {
2871 Slog.e(TAG, "Failed to bind to media container service");
2872 action.handleError();
2873 return;
Kenny Roota02b8b02010-08-05 16:14:17 -07002874 }
Kenny Roota02b8b02010-08-05 16:14:17 -07002875 }
Kenny Root735de3b2010-09-30 14:11:39 -07002876
Kenny Root735de3b2010-09-30 14:11:39 -07002877 mActions.add(action);
Kenny Roota02b8b02010-08-05 16:14:17 -07002878 break;
2879 }
2880 case OBB_MCS_BOUND: {
2881 if (DEBUG_OBB)
2882 Slog.i(TAG, "OBB_MCS_BOUND");
2883 if (msg.obj != null) {
2884 mContainerService = (IMediaContainerService) msg.obj;
2885 }
2886 if (mContainerService == null) {
2887 // Something seriously wrong. Bail out
2888 Slog.e(TAG, "Cannot bind to media container service");
2889 for (ObbAction action : mActions) {
2890 // Indicate service bind error
2891 action.handleError();
2892 }
2893 mActions.clear();
2894 } else if (mActions.size() > 0) {
Kenny Root480afe72010-10-07 10:17:50 -07002895 final ObbAction action = mActions.get(0);
Kenny Roota02b8b02010-08-05 16:14:17 -07002896 if (action != null) {
2897 action.execute(this);
2898 }
2899 } else {
2900 // Should never happen ideally.
2901 Slog.w(TAG, "Empty queue");
2902 }
2903 break;
2904 }
2905 case OBB_MCS_RECONNECT: {
2906 if (DEBUG_OBB)
2907 Slog.i(TAG, "OBB_MCS_RECONNECT");
2908 if (mActions.size() > 0) {
2909 if (mBound) {
2910 disconnectService();
2911 }
2912 if (!connectToService()) {
2913 Slog.e(TAG, "Failed to bind to media container service");
2914 for (ObbAction action : mActions) {
2915 // Indicate service bind error
2916 action.handleError();
2917 }
2918 mActions.clear();
2919 }
2920 }
2921 break;
2922 }
2923 case OBB_MCS_UNBIND: {
2924 if (DEBUG_OBB)
2925 Slog.i(TAG, "OBB_MCS_UNBIND");
2926
2927 // Delete pending install
2928 if (mActions.size() > 0) {
2929 mActions.remove(0);
2930 }
2931 if (mActions.size() == 0) {
2932 if (mBound) {
2933 disconnectService();
2934 }
2935 } else {
2936 // There are more pending requests in queue.
2937 // Just post MCS_BOUND message to trigger processing
2938 // of next pending install.
2939 mObbActionHandler.sendEmptyMessage(OBB_MCS_BOUND);
2940 }
2941 break;
2942 }
Kenny Rootaf9d6672010-10-08 09:21:39 -07002943 case OBB_FLUSH_MOUNT_STATE: {
2944 final String path = (String) msg.obj;
2945
2946 if (DEBUG_OBB)
2947 Slog.i(TAG, "Flushing all OBB state for path " + path);
2948
2949 synchronized (mObbMounts) {
2950 final List<ObbState> obbStatesToRemove = new LinkedList<ObbState>();
2951
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002952 final Iterator<ObbState> i = mObbPathToStateMap.values().iterator();
Kenny Rootaf9d6672010-10-08 09:21:39 -07002953 while (i.hasNext()) {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002954 final ObbState state = i.next();
Kenny Rootaf9d6672010-10-08 09:21:39 -07002955
2956 /*
2957 * If this entry's source file is in the volume path
2958 * that got unmounted, remove it because it's no
2959 * longer valid.
2960 */
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002961 if (state.canonicalPath.startsWith(path)) {
2962 obbStatesToRemove.add(state);
Kenny Rootaf9d6672010-10-08 09:21:39 -07002963 }
2964 }
2965
2966 for (final ObbState obbState : obbStatesToRemove) {
2967 if (DEBUG_OBB)
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002968 Slog.i(TAG, "Removing state for " + obbState.rawPath);
Kenny Rootaf9d6672010-10-08 09:21:39 -07002969
2970 removeObbStateLocked(obbState);
2971
2972 try {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002973 obbState.token.onObbResult(obbState.rawPath, obbState.nonce,
Kenny Rootaf9d6672010-10-08 09:21:39 -07002974 OnObbStateChangeListener.UNMOUNTED);
2975 } catch (RemoteException e) {
2976 Slog.i(TAG, "Couldn't send unmount notification for OBB: "
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002977 + obbState.rawPath);
Kenny Rootaf9d6672010-10-08 09:21:39 -07002978 }
2979 }
2980 }
2981 break;
2982 }
Kenny Roota02b8b02010-08-05 16:14:17 -07002983 }
2984 }
2985
2986 private boolean connectToService() {
2987 if (DEBUG_OBB)
2988 Slog.i(TAG, "Trying to bind to DefaultContainerService");
2989
2990 Intent service = new Intent().setComponent(DEFAULT_CONTAINER_COMPONENT);
Jeff Sharkey6dce4962015-07-03 18:08:41 -07002991 if (mContext.bindServiceAsUser(service, mDefContainerConn, Context.BIND_AUTO_CREATE,
Xiaohui Chene4de5a02015-09-22 15:33:31 -07002992 UserHandle.SYSTEM)) {
Kenny Roota02b8b02010-08-05 16:14:17 -07002993 mBound = true;
2994 return true;
2995 }
2996 return false;
2997 }
2998
2999 private void disconnectService() {
3000 mContainerService = null;
3001 mBound = false;
3002 mContext.unbindService(mDefContainerConn);
3003 }
3004 }
3005
3006 abstract class ObbAction {
3007 private static final int MAX_RETRIES = 3;
3008 private int mRetries;
3009
3010 ObbState mObbState;
3011
3012 ObbAction(ObbState obbState) {
3013 mObbState = obbState;
3014 }
3015
3016 public void execute(ObbActionHandler handler) {
3017 try {
3018 if (DEBUG_OBB)
Ben Komalo444eca22011-09-01 15:17:44 -07003019 Slog.i(TAG, "Starting to execute action: " + toString());
Kenny Roota02b8b02010-08-05 16:14:17 -07003020 mRetries++;
3021 if (mRetries > MAX_RETRIES) {
3022 Slog.w(TAG, "Failed to invoke remote methods on default container service. Giving up");
Kenny Root480afe72010-10-07 10:17:50 -07003023 mObbActionHandler.sendEmptyMessage(OBB_MCS_UNBIND);
Kenny Roota02b8b02010-08-05 16:14:17 -07003024 handleError();
Kenny Roota02b8b02010-08-05 16:14:17 -07003025 } else {
3026 handleExecute();
3027 if (DEBUG_OBB)
3028 Slog.i(TAG, "Posting install MCS_UNBIND");
3029 mObbActionHandler.sendEmptyMessage(OBB_MCS_UNBIND);
3030 }
3031 } catch (RemoteException e) {
3032 if (DEBUG_OBB)
3033 Slog.i(TAG, "Posting install MCS_RECONNECT");
3034 mObbActionHandler.sendEmptyMessage(OBB_MCS_RECONNECT);
3035 } catch (Exception e) {
3036 if (DEBUG_OBB)
3037 Slog.d(TAG, "Error handling OBB action", e);
3038 handleError();
Kenny Root17eb6fb2010-10-06 15:02:52 -07003039 mObbActionHandler.sendEmptyMessage(OBB_MCS_UNBIND);
Kenny Roota02b8b02010-08-05 16:14:17 -07003040 }
3041 }
3042
Kenny Root05105f72010-09-22 17:29:43 -07003043 abstract void handleExecute() throws RemoteException, IOException;
Kenny Roota02b8b02010-08-05 16:14:17 -07003044 abstract void handleError();
Kenny Root38cf8862010-09-26 14:18:51 -07003045
3046 protected ObbInfo getObbInfo() throws IOException {
3047 ObbInfo obbInfo;
3048 try {
Xiaohui Chen621b3fc2015-10-02 14:41:42 -07003049 obbInfo = mContainerService.getObbInfo(mObbState.canonicalPath);
Kenny Root38cf8862010-09-26 14:18:51 -07003050 } catch (RemoteException e) {
3051 Slog.d(TAG, "Couldn't call DefaultContainerService to fetch OBB info for "
Xiaohui Chen621b3fc2015-10-02 14:41:42 -07003052 + mObbState.canonicalPath);
Kenny Root38cf8862010-09-26 14:18:51 -07003053 obbInfo = null;
3054 }
3055 if (obbInfo == null) {
Xiaohui Chen621b3fc2015-10-02 14:41:42 -07003056 throw new IOException("Couldn't read OBB file: " + mObbState.canonicalPath);
Kenny Root38cf8862010-09-26 14:18:51 -07003057 }
3058 return obbInfo;
3059 }
3060
Kenny Rootaf9d6672010-10-08 09:21:39 -07003061 protected void sendNewStatusOrIgnore(int status) {
3062 if (mObbState == null || mObbState.token == null) {
3063 return;
3064 }
3065
Kenny Root38cf8862010-09-26 14:18:51 -07003066 try {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003067 mObbState.token.onObbResult(mObbState.rawPath, mObbState.nonce, status);
Kenny Root38cf8862010-09-26 14:18:51 -07003068 } catch (RemoteException e) {
Sudheer Shanka2250d562016-11-07 15:41:02 -08003069 Slog.w(TAG, "StorageEventListener went away while calling onObbStateChanged");
Kenny Root38cf8862010-09-26 14:18:51 -07003070 }
3071 }
Kenny Roota02b8b02010-08-05 16:14:17 -07003072 }
3073
3074 class MountObbAction extends ObbAction {
Ben Komalo444eca22011-09-01 15:17:44 -07003075 private final String mKey;
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003076 private final int mCallingUid;
Kenny Roota02b8b02010-08-05 16:14:17 -07003077
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003078 MountObbAction(ObbState obbState, String key, int callingUid) {
Kenny Roota02b8b02010-08-05 16:14:17 -07003079 super(obbState);
3080 mKey = key;
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003081 mCallingUid = callingUid;
Kenny Roota02b8b02010-08-05 16:14:17 -07003082 }
3083
Jason parks5af0b912010-11-29 09:05:25 -06003084 @Override
Kenny Root735de3b2010-09-30 14:11:39 -07003085 public void handleExecute() throws IOException, RemoteException {
Kenny Rootaf9d6672010-10-08 09:21:39 -07003086 warnOnNotMounted();
3087
Kenny Root38cf8862010-09-26 14:18:51 -07003088 final ObbInfo obbInfo = getObbInfo();
3089
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003090 if (!isUidOwnerOfPackageOrSystem(obbInfo.packageName, mCallingUid)) {
Kenny Rootaf9d6672010-10-08 09:21:39 -07003091 Slog.w(TAG, "Denied attempt to mount OBB " + obbInfo.filename
3092 + " which is owned by " + obbInfo.packageName);
3093 sendNewStatusOrIgnore(OnObbStateChangeListener.ERROR_PERMISSION_DENIED);
3094 return;
Kenny Roota02b8b02010-08-05 16:14:17 -07003095 }
3096
Kenny Rootaf9d6672010-10-08 09:21:39 -07003097 final boolean isMounted;
3098 synchronized (mObbMounts) {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003099 isMounted = mObbPathToStateMap.containsKey(mObbState.rawPath);
Kenny Rootaf9d6672010-10-08 09:21:39 -07003100 }
3101 if (isMounted) {
3102 Slog.w(TAG, "Attempt to mount OBB which is already mounted: " + obbInfo.filename);
3103 sendNewStatusOrIgnore(OnObbStateChangeListener.ERROR_ALREADY_MOUNTED);
3104 return;
3105 }
3106
Kenny Rootaf9d6672010-10-08 09:21:39 -07003107 final String hashedKey;
Jeff Sharkey41cd6812017-09-11 10:32:17 -06003108 final String binderKey;
Kenny Rootaf9d6672010-10-08 09:21:39 -07003109 if (mKey == null) {
3110 hashedKey = "none";
Jeff Sharkey41cd6812017-09-11 10:32:17 -06003111 binderKey = "";
Kenny Rootaf9d6672010-10-08 09:21:39 -07003112 } else {
Kenny Rootaf9d6672010-10-08 09:21:39 -07003113 try {
Kenny Root3b1abba2010-10-13 15:00:07 -07003114 SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
3115
3116 KeySpec ks = new PBEKeySpec(mKey.toCharArray(), obbInfo.salt,
3117 PBKDF2_HASH_ROUNDS, CRYPTO_ALGORITHM_KEY_SIZE);
3118 SecretKey key = factory.generateSecret(ks);
3119 BigInteger bi = new BigInteger(key.getEncoded());
3120 hashedKey = bi.toString(16);
Jeff Sharkey41cd6812017-09-11 10:32:17 -06003121 binderKey = hashedKey;
Kenny Rootaf9d6672010-10-08 09:21:39 -07003122 } catch (NoSuchAlgorithmException e) {
Kenny Root3b1abba2010-10-13 15:00:07 -07003123 Slog.e(TAG, "Could not load PBKDF2 algorithm", e);
3124 sendNewStatusOrIgnore(OnObbStateChangeListener.ERROR_INTERNAL);
3125 return;
3126 } catch (InvalidKeySpecException e) {
3127 Slog.e(TAG, "Invalid key spec when loading PBKDF2 algorithm", e);
3128 sendNewStatusOrIgnore(OnObbStateChangeListener.ERROR_INTERNAL);
Kenny Root38cf8862010-09-26 14:18:51 -07003129 return;
3130 }
Kenny Rootaf9d6672010-10-08 09:21:39 -07003131 }
Kenny Root38cf8862010-09-26 14:18:51 -07003132
Kenny Rootaf9d6672010-10-08 09:21:39 -07003133 int rc = StorageResultCode.OperationSucceeded;
Kenny Rootaf9d6672010-10-08 09:21:39 -07003134 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06003135 mObbState.volId = mVold.createObb(mObbState.canonicalPath, binderKey,
3136 mObbState.ownerGid);
3137 mVold.mount(mObbState.volId, 0, -1);
Jeff Sharkey41cd6812017-09-11 10:32:17 -06003138 } catch (Exception e) {
3139 Slog.w(TAG, e);
3140 rc = StorageResultCode.OperationFailedInternalError;
Kenny Roota02b8b02010-08-05 16:14:17 -07003141 }
3142
Kenny Rootaf9d6672010-10-08 09:21:39 -07003143 if (rc == StorageResultCode.OperationSucceeded) {
3144 if (DEBUG_OBB)
Xiaohui Chen621b3fc2015-10-02 14:41:42 -07003145 Slog.d(TAG, "Successfully mounted OBB " + mObbState.canonicalPath);
Kenny Rootaf9d6672010-10-08 09:21:39 -07003146
3147 synchronized (mObbMounts) {
3148 addObbStateLocked(mObbState);
3149 }
3150
3151 sendNewStatusOrIgnore(OnObbStateChangeListener.MOUNTED);
Kenny Root02c87302010-07-01 08:10:18 -07003152 } else {
Kenny Root05105f72010-09-22 17:29:43 -07003153 Slog.e(TAG, "Couldn't mount OBB file: " + rc);
Kenny Roota02b8b02010-08-05 16:14:17 -07003154
Kenny Rootaf9d6672010-10-08 09:21:39 -07003155 sendNewStatusOrIgnore(OnObbStateChangeListener.ERROR_COULD_NOT_MOUNT);
Kenny Root02c87302010-07-01 08:10:18 -07003156 }
3157 }
3158
Jason parks5af0b912010-11-29 09:05:25 -06003159 @Override
Kenny Roota02b8b02010-08-05 16:14:17 -07003160 public void handleError() {
Kenny Rootaf9d6672010-10-08 09:21:39 -07003161 sendNewStatusOrIgnore(OnObbStateChangeListener.ERROR_INTERNAL);
Kenny Root02c87302010-07-01 08:10:18 -07003162 }
Kenny Roota02b8b02010-08-05 16:14:17 -07003163
3164 @Override
3165 public String toString() {
3166 StringBuilder sb = new StringBuilder();
3167 sb.append("MountObbAction{");
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003168 sb.append(mObbState);
Kenny Roota02b8b02010-08-05 16:14:17 -07003169 sb.append('}');
3170 return sb.toString();
3171 }
3172 }
3173
3174 class UnmountObbAction extends ObbAction {
Ben Komalo444eca22011-09-01 15:17:44 -07003175 private final boolean mForceUnmount;
Kenny Roota02b8b02010-08-05 16:14:17 -07003176
3177 UnmountObbAction(ObbState obbState, boolean force) {
3178 super(obbState);
3179 mForceUnmount = force;
3180 }
3181
Jason parks5af0b912010-11-29 09:05:25 -06003182 @Override
Kenny Root38cf8862010-09-26 14:18:51 -07003183 public void handleExecute() throws IOException {
Kenny Rootaf9d6672010-10-08 09:21:39 -07003184 warnOnNotMounted();
3185
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003186 final ObbState existingState;
Kenny Root38cf8862010-09-26 14:18:51 -07003187 synchronized (mObbMounts) {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003188 existingState = mObbPathToStateMap.get(mObbState.rawPath);
Kenny Rootaf9d6672010-10-08 09:21:39 -07003189 }
Kenny Root38cf8862010-09-26 14:18:51 -07003190
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003191 if (existingState == null) {
Kenny Rootaf9d6672010-10-08 09:21:39 -07003192 sendNewStatusOrIgnore(OnObbStateChangeListener.ERROR_NOT_MOUNTED);
3193 return;
3194 }
3195
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003196 if (existingState.ownerGid != mObbState.ownerGid) {
3197 Slog.w(TAG, "Permission denied attempting to unmount OBB " + existingState.rawPath
3198 + " (owned by GID " + existingState.ownerGid + ")");
Kenny Rootaf9d6672010-10-08 09:21:39 -07003199 sendNewStatusOrIgnore(OnObbStateChangeListener.ERROR_PERMISSION_DENIED);
3200 return;
3201 }
3202
Kenny Rootaf9d6672010-10-08 09:21:39 -07003203 int rc = StorageResultCode.OperationSucceeded;
Kenny Rootaf9d6672010-10-08 09:21:39 -07003204 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06003205 mVold.unmount(mObbState.volId);
3206 mVold.destroyObb(mObbState.volId);
3207 mObbState.volId = null;
Jeff Sharkey41cd6812017-09-11 10:32:17 -06003208 } catch (Exception e) {
3209 Slog.w(TAG, e);
3210 rc = StorageResultCode.OperationFailedInternalError;
Kenny Roota02b8b02010-08-05 16:14:17 -07003211 }
3212
Kenny Rootaf9d6672010-10-08 09:21:39 -07003213 if (rc == StorageResultCode.OperationSucceeded) {
3214 synchronized (mObbMounts) {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003215 removeObbStateLocked(existingState);
Kenny Root38cf8862010-09-26 14:18:51 -07003216 }
3217
Kenny Rootaf9d6672010-10-08 09:21:39 -07003218 sendNewStatusOrIgnore(OnObbStateChangeListener.UNMOUNTED);
Kenny Roota02b8b02010-08-05 16:14:17 -07003219 } else {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003220 Slog.w(TAG, "Could not unmount OBB: " + existingState);
Kenny Rootaf9d6672010-10-08 09:21:39 -07003221 sendNewStatusOrIgnore(OnObbStateChangeListener.ERROR_COULD_NOT_UNMOUNT);
Kenny Roota02b8b02010-08-05 16:14:17 -07003222 }
3223 }
3224
Jason parks5af0b912010-11-29 09:05:25 -06003225 @Override
Kenny Roota02b8b02010-08-05 16:14:17 -07003226 public void handleError() {
Kenny Rootaf9d6672010-10-08 09:21:39 -07003227 sendNewStatusOrIgnore(OnObbStateChangeListener.ERROR_INTERNAL);
Kenny Roota02b8b02010-08-05 16:14:17 -07003228 }
3229
3230 @Override
3231 public String toString() {
3232 StringBuilder sb = new StringBuilder();
3233 sb.append("UnmountObbAction{");
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003234 sb.append(mObbState);
Kenny Roota02b8b02010-08-05 16:14:17 -07003235 sb.append(",force=");
3236 sb.append(mForceUnmount);
Kenny Roota02b8b02010-08-05 16:14:17 -07003237 sb.append('}');
3238 return sb.toString();
3239 }
Kenny Root02c87302010-07-01 08:10:18 -07003240 }
Kenny Root38cf8862010-09-26 14:18:51 -07003241
Jeff Sharkey7e19f532017-11-06 13:54:11 -07003242 private void dispatchOnStatus(IVoldTaskListener listener, int status,
3243 PersistableBundle extras) {
3244 if (listener != null) {
3245 try {
3246 listener.onStatus(status, extras);
3247 } catch (RemoteException ignored) {
3248 }
3249 }
3250 }
3251
3252 private void dispatchOnFinished(IVoldTaskListener listener, int status,
3253 PersistableBundle extras) {
3254 if (listener != null) {
3255 try {
3256 listener.onFinished(status, extras);
3257 } catch (RemoteException ignored) {
3258 }
3259 }
3260 }
3261
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07003262 private static class Callbacks extends Handler {
3263 private static final int MSG_STORAGE_STATE_CHANGED = 1;
3264 private static final int MSG_VOLUME_STATE_CHANGED = 2;
Jeff Sharkey50a05452015-04-29 11:24:52 -07003265 private static final int MSG_VOLUME_RECORD_CHANGED = 3;
3266 private static final int MSG_VOLUME_FORGOTTEN = 4;
3267 private static final int MSG_DISK_SCANNED = 5;
Makoto Onuki9dc575d2015-06-12 16:10:25 -07003268 private static final int MSG_DISK_DESTROYED = 6;
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07003269
Sudheer Shanka2250d562016-11-07 15:41:02 -08003270 private final RemoteCallbackList<IStorageEventListener>
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07003271 mCallbacks = new RemoteCallbackList<>();
3272
3273 public Callbacks(Looper looper) {
3274 super(looper);
3275 }
3276
Sudheer Shanka2250d562016-11-07 15:41:02 -08003277 public void register(IStorageEventListener callback) {
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07003278 mCallbacks.register(callback);
3279 }
3280
Sudheer Shanka2250d562016-11-07 15:41:02 -08003281 public void unregister(IStorageEventListener callback) {
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07003282 mCallbacks.unregister(callback);
3283 }
3284
3285 @Override
3286 public void handleMessage(Message msg) {
3287 final SomeArgs args = (SomeArgs) msg.obj;
3288 final int n = mCallbacks.beginBroadcast();
3289 for (int i = 0; i < n; i++) {
Sudheer Shanka2250d562016-11-07 15:41:02 -08003290 final IStorageEventListener callback = mCallbacks.getBroadcastItem(i);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07003291 try {
3292 invokeCallback(callback, msg.what, args);
3293 } catch (RemoteException ignored) {
3294 }
3295 }
3296 mCallbacks.finishBroadcast();
3297 args.recycle();
3298 }
3299
Sudheer Shanka2250d562016-11-07 15:41:02 -08003300 private void invokeCallback(IStorageEventListener callback, int what, SomeArgs args)
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07003301 throws RemoteException {
3302 switch (what) {
3303 case MSG_STORAGE_STATE_CHANGED: {
3304 callback.onStorageStateChanged((String) args.arg1, (String) args.arg2,
3305 (String) args.arg3);
3306 break;
3307 }
3308 case MSG_VOLUME_STATE_CHANGED: {
3309 callback.onVolumeStateChanged((VolumeInfo) args.arg1, args.argi2, args.argi3);
3310 break;
3311 }
Jeff Sharkey50a05452015-04-29 11:24:52 -07003312 case MSG_VOLUME_RECORD_CHANGED: {
3313 callback.onVolumeRecordChanged((VolumeRecord) args.arg1);
3314 break;
3315 }
3316 case MSG_VOLUME_FORGOTTEN: {
3317 callback.onVolumeForgotten((String) args.arg1);
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07003318 break;
3319 }
Jeff Sharkey620b32b2015-04-23 19:36:02 -07003320 case MSG_DISK_SCANNED: {
3321 callback.onDiskScanned((DiskInfo) args.arg1, args.argi2);
Jeff Sharkey7e92ef32015-04-17 17:35:07 -07003322 break;
3323 }
Makoto Onuki9dc575d2015-06-12 16:10:25 -07003324 case MSG_DISK_DESTROYED: {
3325 callback.onDiskDestroyed((DiskInfo) args.arg1);
3326 break;
3327 }
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07003328 }
3329 }
3330
3331 private void notifyStorageStateChanged(String path, String oldState, String newState) {
3332 final SomeArgs args = SomeArgs.obtain();
3333 args.arg1 = path;
3334 args.arg2 = oldState;
3335 args.arg3 = newState;
3336 obtainMessage(MSG_STORAGE_STATE_CHANGED, args).sendToTarget();
3337 }
3338
3339 private void notifyVolumeStateChanged(VolumeInfo vol, int oldState, int newState) {
3340 final SomeArgs args = SomeArgs.obtain();
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07003341 args.arg1 = vol.clone();
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07003342 args.argi2 = oldState;
3343 args.argi3 = newState;
3344 obtainMessage(MSG_VOLUME_STATE_CHANGED, args).sendToTarget();
3345 }
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07003346
Jeff Sharkey50a05452015-04-29 11:24:52 -07003347 private void notifyVolumeRecordChanged(VolumeRecord rec) {
3348 final SomeArgs args = SomeArgs.obtain();
3349 args.arg1 = rec.clone();
3350 obtainMessage(MSG_VOLUME_RECORD_CHANGED, args).sendToTarget();
3351 }
3352
3353 private void notifyVolumeForgotten(String fsUuid) {
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07003354 final SomeArgs args = SomeArgs.obtain();
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07003355 args.arg1 = fsUuid;
Jeff Sharkey50a05452015-04-29 11:24:52 -07003356 obtainMessage(MSG_VOLUME_FORGOTTEN, args).sendToTarget();
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07003357 }
Jeff Sharkey7e92ef32015-04-17 17:35:07 -07003358
Jeff Sharkey620b32b2015-04-23 19:36:02 -07003359 private void notifyDiskScanned(DiskInfo disk, int volumeCount) {
Jeff Sharkey7e92ef32015-04-17 17:35:07 -07003360 final SomeArgs args = SomeArgs.obtain();
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07003361 args.arg1 = disk.clone();
Jeff Sharkey620b32b2015-04-23 19:36:02 -07003362 args.argi2 = volumeCount;
3363 obtainMessage(MSG_DISK_SCANNED, args).sendToTarget();
Jeff Sharkey7e92ef32015-04-17 17:35:07 -07003364 }
Makoto Onuki9dc575d2015-06-12 16:10:25 -07003365
3366 private void notifyDiskDestroyed(DiskInfo disk) {
3367 final SomeArgs args = SomeArgs.obtain();
3368 args.arg1 = disk.clone();
3369 obtainMessage(MSG_DISK_DESTROYED, args).sendToTarget();
3370 }
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07003371 }
3372
Kenny Root38cf8862010-09-26 14:18:51 -07003373 @Override
Jeff Sharkey5aca2b82013-10-16 16:21:54 -07003374 protected void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
Jeff Sharkeyfe9a53b2017-03-31 14:08:23 -06003375 if (!DumpUtils.checkDumpPermission(mContext, TAG, writer)) return;
Jeff Sharkey5aca2b82013-10-16 16:21:54 -07003376
3377 final IndentingPrintWriter pw = new IndentingPrintWriter(writer, " ", 160);
Jeff Sharkey27de30d2015-04-18 16:20:27 -07003378 synchronized (mLock) {
3379 pw.println("Disks:");
3380 pw.increaseIndent();
3381 for (int i = 0; i < mDisks.size(); i++) {
3382 final DiskInfo disk = mDisks.valueAt(i);
3383 disk.dump(pw);
3384 }
3385 pw.decreaseIndent();
3386
3387 pw.println();
3388 pw.println("Volumes:");
3389 pw.increaseIndent();
3390 for (int i = 0; i < mVolumes.size(); i++) {
3391 final VolumeInfo vol = mVolumes.valueAt(i);
3392 if (VolumeInfo.ID_PRIVATE_INTERNAL.equals(vol.id)) continue;
3393 vol.dump(pw);
3394 }
3395 pw.decreaseIndent();
3396
3397 pw.println();
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07003398 pw.println("Records:");
Jeff Sharkey27de30d2015-04-18 16:20:27 -07003399 pw.increaseIndent();
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07003400 for (int i = 0; i < mRecords.size(); i++) {
3401 final VolumeRecord note = mRecords.valueAt(i);
3402 note.dump(pw);
Jeff Sharkey27de30d2015-04-18 16:20:27 -07003403 }
3404 pw.decreaseIndent();
Jeff Sharkey275e3e42015-04-24 16:10:32 -07003405
3406 pw.println();
3407 pw.println("Primary storage UUID: " + mPrimaryStorageUuid);
Felipe Leme281389a2016-10-10 17:12:20 -07003408 final Pair<String, Long> pair = StorageManager.getPrimaryStoragePathAndSize();
3409 if (pair == null) {
3410 pw.println("Internal storage total size: N/A");
3411 } else {
3412 pw.print("Internal storage (");
3413 pw.print(pair.first);
3414 pw.print(") total size: ");
3415 pw.print(pair.second);
3416 pw.print(" (");
3417 pw.print((float) pair.second / TrafficStats.GB_IN_BYTES);
3418 pw.println(" GB)");
3419 }
Jeff Sharkey4c099d02015-05-15 13:45:00 -07003420 pw.println("Force adoptable: " + mForceAdoptable);
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08003421 pw.println();
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07003422 pw.println("Local unlocked users: " + Arrays.toString(mLocalUnlockedUsers));
3423 pw.println("System unlocked users: " + Arrays.toString(mSystemUnlockedUsers));
Jeff Sharkey27de30d2015-04-18 16:20:27 -07003424 }
Kenny Root38cf8862010-09-26 14:18:51 -07003425
Kenny Root38cf8862010-09-26 14:18:51 -07003426 synchronized (mObbMounts) {
Jeff Sharkey27de30d2015-04-18 16:20:27 -07003427 pw.println();
Jeff Sharkey5aca2b82013-10-16 16:21:54 -07003428 pw.println("mObbMounts:");
3429 pw.increaseIndent();
3430 final Iterator<Entry<IBinder, List<ObbState>>> binders = mObbMounts.entrySet()
3431 .iterator();
Kenny Rootaf9d6672010-10-08 09:21:39 -07003432 while (binders.hasNext()) {
3433 Entry<IBinder, List<ObbState>> e = binders.next();
Jeff Sharkey5aca2b82013-10-16 16:21:54 -07003434 pw.println(e.getKey() + ":");
3435 pw.increaseIndent();
Kenny Rootaf9d6672010-10-08 09:21:39 -07003436 final List<ObbState> obbStates = e.getValue();
Kenny Root38cf8862010-09-26 14:18:51 -07003437 for (final ObbState obbState : obbStates) {
Jeff Sharkey5aca2b82013-10-16 16:21:54 -07003438 pw.println(obbState);
Kenny Root38cf8862010-09-26 14:18:51 -07003439 }
Jeff Sharkey5aca2b82013-10-16 16:21:54 -07003440 pw.decreaseIndent();
Kenny Root38cf8862010-09-26 14:18:51 -07003441 }
Jeff Sharkey5aca2b82013-10-16 16:21:54 -07003442 pw.decreaseIndent();
Kenny Rootaf9d6672010-10-08 09:21:39 -07003443
Jeff Sharkey5aca2b82013-10-16 16:21:54 -07003444 pw.println();
3445 pw.println("mObbPathToStateMap:");
3446 pw.increaseIndent();
Kenny Rootaf9d6672010-10-08 09:21:39 -07003447 final Iterator<Entry<String, ObbState>> maps = mObbPathToStateMap.entrySet().iterator();
3448 while (maps.hasNext()) {
3449 final Entry<String, ObbState> e = maps.next();
Jeff Sharkey5aca2b82013-10-16 16:21:54 -07003450 pw.print(e.getKey());
3451 pw.print(" -> ");
3452 pw.println(e.getValue());
Kenny Rootaf9d6672010-10-08 09:21:39 -07003453 }
Jeff Sharkey5aca2b82013-10-16 16:21:54 -07003454 pw.decreaseIndent();
Kenny Root38cf8862010-09-26 14:18:51 -07003455 }
Kenny Root4161f9b2011-07-13 09:48:33 -07003456
Robert Greenwalt470fd722012-01-18 12:51:15 -08003457 pw.println();
Christopher Tate7265abe2014-11-21 13:54:45 -08003458 pw.print("Last maintenance: ");
Jeff Sharkeye8a4b662015-06-27 15:43:45 -07003459 pw.println(TimeUtils.formatForLogging(mLastMaintenance));
Kenny Root38cf8862010-09-26 14:18:51 -07003460 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003461
Jeff Sharkeyfa23c5a2011-08-09 21:44:24 -07003462 /** {@inheritDoc} */
Jeff Sharkey48877892015-03-18 11:27:19 -07003463 @Override
Jeff Sharkeyfa23c5a2011-08-09 21:44:24 -07003464 public void monitor() {
Jeff Sharkey54402792017-09-15 16:05:19 -06003465 try {
3466 mVold.monitor();
3467 } catch (Exception e) {
3468 Slog.wtf(TAG, e);
Paul Lawrence1c62cbb2015-06-03 14:14:52 -07003469 }
Jeff Sharkeyfa23c5a2011-08-09 21:44:24 -07003470 }
Svet Ganov6ee871e2015-07-10 14:29:33 -07003471
Sudheer Shanka2250d562016-11-07 15:41:02 -08003472 private final class StorageManagerInternalImpl extends StorageManagerInternal {
Svet Ganov6ee871e2015-07-10 14:29:33 -07003473 // Not guarded by a lock.
3474 private final CopyOnWriteArrayList<ExternalStorageMountPolicy> mPolicies =
3475 new CopyOnWriteArrayList<>();
3476
3477 @Override
3478 public void addExternalStoragePolicy(ExternalStorageMountPolicy policy) {
3479 // No locking - CopyOnWriteArrayList
3480 mPolicies.add(policy);
3481 }
3482
3483 @Override
3484 public void onExternalStoragePolicyChanged(int uid, String packageName) {
3485 final int mountMode = getExternalStorageMountMode(uid, packageName);
3486 remountUidExternalStorage(uid, mountMode);
3487 }
3488
3489 @Override
3490 public int getExternalStorageMountMode(int uid, String packageName) {
3491 // No locking - CopyOnWriteArrayList
3492 int mountMode = Integer.MAX_VALUE;
3493 for (ExternalStorageMountPolicy policy : mPolicies) {
3494 final int policyMode = policy.getMountMode(uid, packageName);
3495 if (policyMode == Zygote.MOUNT_EXTERNAL_NONE) {
3496 return Zygote.MOUNT_EXTERNAL_NONE;
3497 }
3498 mountMode = Math.min(mountMode, policyMode);
3499 }
3500 if (mountMode == Integer.MAX_VALUE) {
3501 return Zygote.MOUNT_EXTERNAL_NONE;
3502 }
3503 return mountMode;
3504 }
3505
3506 public boolean hasExternalStorage(int uid, String packageName) {
Amith Yamasani2bd5cff2015-07-22 14:42:31 -07003507 // No need to check for system uid. This avoids a deadlock between
3508 // PackageManagerService and AppOpsService.
3509 if (uid == Process.SYSTEM_UID) {
3510 return true;
3511 }
Svet Ganov6ee871e2015-07-10 14:29:33 -07003512 // No locking - CopyOnWriteArrayList
3513 for (ExternalStorageMountPolicy policy : mPolicies) {
3514 final boolean policyHasStorage = policy.hasExternalStorage(uid, packageName);
3515 if (!policyHasStorage) {
3516 return false;
3517 }
3518 }
3519 return true;
3520 }
3521 }
Jeff Sharkeyfa23c5a2011-08-09 21:44:24 -07003522}