blob: 6a0d3ff92db84b14fdd612b0a77220f4375cc8ea [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
2 * Copyright (C) 2007 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.server;
18
Jeff Sharkey4c099d02015-05-15 13:45:00 -070019import static com.android.internal.util.XmlUtils.readBooleanAttribute;
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -070020import static com.android.internal.util.XmlUtils.readIntAttribute;
Jeff Sharkeye8a4b662015-06-27 15:43:45 -070021import static com.android.internal.util.XmlUtils.readLongAttribute;
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -070022import static com.android.internal.util.XmlUtils.readStringAttribute;
Jeff Sharkey4c099d02015-05-15 13:45:00 -070023import static com.android.internal.util.XmlUtils.writeBooleanAttribute;
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -070024import static com.android.internal.util.XmlUtils.writeIntAttribute;
Jeff Sharkeye8a4b662015-06-27 15:43:45 -070025import static com.android.internal.util.XmlUtils.writeLongAttribute;
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -070026import static com.android.internal.util.XmlUtils.writeStringAttribute;
Jeff Sharkey5217cac2015-12-20 15:34:01 -070027
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -070028import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT;
29import static org.xmlpull.v1.XmlPullParser.START_TAG;
30
Jason parks8888c592011-01-20 22:46:41 -060031import android.Manifest;
Jeff Sharkeyef10ee02015-07-05 14:17:27 -070032import android.annotation.Nullable;
Xiaohui Chen621b3fc2015-10-02 14:41:42 -070033import android.app.ActivityManager;
Jeff Sharkey9765e442017-12-14 22:15:14 -070034import android.app.ActivityManagerInternal;
35import android.app.ActivityManagerInternal.ScreenObserver;
Jeff Sharkey2d8b4e82013-09-17 17:30:33 -070036import android.app.AppOpsManager;
Jeff Sharkey14cbe522015-07-08 14:06:37 -070037import android.app.IActivityManager;
Jeff Sharkey9765e442017-12-14 22:15:14 -070038import android.app.KeyguardManager;
Jeff Sharkey9bed0702017-01-23 20:37:05 -070039import android.app.usage.StorageStatsManager;
Jeff Sharkeybcd262d2015-06-10 09:41:17 -070040import android.content.BroadcastReceiver;
Kenny Roota02b8b02010-08-05 16:14:17 -070041import android.content.ComponentName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080042import android.content.Context;
43import android.content.Intent;
Jeff Sharkeybcd262d2015-06-10 09:41:17 -070044import android.content.IntentFilter;
Kenny Roota02b8b02010-08-05 16:14:17 -070045import android.content.ServiceConnection;
Jeff Sharkey275e3e42015-04-24 16:10:32 -070046import android.content.pm.IPackageMoveObserver;
47import android.content.pm.PackageManager;
Jeff Sharkey14cbe522015-07-08 14:06:37 -070048import android.content.pm.ProviderInfo;
Jeff Sharkeybcd262d2015-06-10 09:41:17 -070049import android.content.pm.UserInfo;
Elliott Hughesf839b4f2014-09-26 12:30:47 -070050import android.content.res.Configuration;
Kenny Root02c87302010-07-01 08:10:18 -070051import android.content.res.ObbInfo;
Felipe Leme281389a2016-10-10 17:12:20 -070052import android.net.TrafficStats;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080053import android.net.Uri;
Kenny Root02c87302010-07-01 08:10:18 -070054import android.os.Binder;
Jeff Sharkey4c099d02015-05-15 13:45:00 -070055import android.os.DropBoxManager;
Kenny Roota02b8b02010-08-05 16:14:17 -070056import android.os.Environment;
Jeff Sharkeyb049e212012-09-07 23:16:01 -070057import android.os.Environment.UserEnvironment;
Jeff Sharkey48877892015-03-18 11:27:19 -070058import android.os.FileUtils;
Suchi Amalapurapuc42e29e2010-02-22 16:03:53 -080059import android.os.Handler;
Dianne Hackbornefa92b22013-05-03 14:11:43 -070060import android.os.HandlerThread;
Kenny Roota02b8b02010-08-05 16:14:17 -070061import android.os.IBinder;
Jeff Sharkey7e19f532017-11-06 13:54:11 -070062import android.os.IProgressListener;
Jin Qian12690d52017-10-13 18:17:04 -070063import android.os.IStoraged;
Jeff Sharkey1019de92017-09-06 13:47:03 -060064import android.os.IVold;
Jeff Sharkey8058fe62017-09-13 11:50:33 -060065import android.os.IVoldListener;
Jeff Sharkeyb302c542017-09-15 12:57:59 -060066import android.os.IVoldTaskListener;
Daniel Sandler5f27ef42010-03-16 15:42:02 -040067import android.os.Looper;
Suchi Amalapurapuc42e29e2010-02-22 16:03:53 -080068import android.os.Message;
Daichi Hirono9e8d9e22015-11-13 14:37:00 +090069import android.os.ParcelFileDescriptor;
Jeff Sharkey500ce9e2017-02-12 02:39:24 -070070import android.os.ParcelableException;
Jeff Sharkeyb302c542017-09-15 12:57:59 -060071import android.os.PersistableBundle;
Jeff Sharkeyce14cd02015-12-07 15:35:42 -070072import android.os.PowerManager;
Jeff Sharkey9527b222015-06-24 15:24:48 -070073import android.os.Process;
Jeff Sharkey7151a9a2015-04-04 15:22:37 -070074import android.os.RemoteCallbackList;
San Mehat4270e1e2010-01-29 05:32:19 -080075import android.os.RemoteException;
Suchi Amalapurapufd3530f2010-01-18 00:15:59 -080076import android.os.ServiceManager;
Jeff Sharkeyedcdaf62015-07-09 09:45:36 -070077import android.os.SystemClock;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080078import android.os.SystemProperties;
Dianne Hackbornf02b60a2012-08-16 10:48:27 -070079import android.os.UserHandle;
Emily Bernier92aa5a22014-07-07 10:11:48 -040080import android.os.UserManager;
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -070081import android.os.storage.DiskInfo;
Kenny Roota02b8b02010-08-05 16:14:17 -070082import android.os.storage.IObbActionListener;
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -070083import android.os.storage.IStorageEventListener;
Sudheer Shanka2250d562016-11-07 15:41:02 -080084import android.os.storage.IStorageManager;
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -070085import android.os.storage.IStorageShutdownObserver;
Kenny Rootaf9d6672010-10-08 09:21:39 -070086import android.os.storage.OnObbStateChangeListener;
Paul Lawrence46791e72014-04-03 09:10:26 -070087import android.os.storage.StorageManager;
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -070088import android.os.storage.StorageManagerInternal;
Kenny Roota02b8b02010-08-05 16:14:17 -070089import android.os.storage.StorageResultCode;
Mike Lockwood2f6a3882011-05-09 19:08:06 -070090import android.os.storage.StorageVolume;
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -070091import android.os.storage.VolumeInfo;
Jeff Sharkeyb36586a2015-04-27 08:42:28 -070092import android.os.storage.VolumeRecord;
Jeff Sharkey14cbe522015-07-08 14:06:37 -070093import android.provider.MediaStore;
Jeff Sharkeye8a4b662015-06-27 15:43:45 -070094import android.provider.Settings;
Jason parksf7b3cd42011-01-27 09:28:25 -060095import android.text.TextUtils;
Jeff Sharkey1783f142015-04-17 10:52:51 -070096import android.text.format.DateUtils;
Jeff Sharkey48877892015-03-18 11:27:19 -070097import android.util.ArrayMap;
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -070098import android.util.AtomicFile;
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -070099import android.util.Log;
Felipe Leme281389a2016-10-10 17:12:20 -0700100import android.util.Pair;
San Mehata5078592010-03-25 09:36:54 -0700101import android.util.Slog;
Jeff Sharkeye8a4b662015-06-27 15:43:45 -0700102import android.util.TimeUtils;
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700103import android.util.Xml;
Jeff Sharkey48877892015-03-18 11:27:19 -0700104
Jeff Sharkey8b2c3a142012-11-12 11:45:05 -0800105import com.android.internal.annotations.GuardedBy;
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700106import com.android.internal.app.IMediaContainerService;
Daichi Hirono9fb00182016-11-08 14:12:17 +0900107import com.android.internal.os.AppFuseMount;
Jeff Sharkey1019de92017-09-06 13:47:03 -0600108import com.android.internal.os.BackgroundThread;
Daichi Hirono812c95d2017-02-08 16:20:20 +0900109import com.android.internal.os.FuseUnavailableMountException;
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700110import com.android.internal.os.SomeArgs;
Jeff Sharkey9527b222015-06-24 15:24:48 -0700111import com.android.internal.os.Zygote;
Jeff Sharkey48877892015-03-18 11:27:19 -0700112import com.android.internal.util.ArrayUtils;
Jeff Sharkeyfe9a53b2017-03-31 14:08:23 -0600113import com.android.internal.util.DumpUtils;
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700114import com.android.internal.util.FastXmlSerializer;
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -0800115import com.android.internal.util.HexDump;
Jeff Sharkey5aca2b82013-10-16 16:21:54 -0700116import com.android.internal.util.IndentingPrintWriter;
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700117import com.android.internal.util.Preconditions;
Jeff Sharkeyb9fe5372015-12-03 15:23:08 -0700118import com.android.internal.widget.LockPatternUtils;
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700119import com.android.server.pm.PackageManagerService;
Daichi Hirono9fb00182016-11-08 14:12:17 +0900120import com.android.server.storage.AppFuseBridge;
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -0700121
Jeff Sharkey5217cac2015-12-20 15:34:01 -0700122import libcore.io.IoUtils;
123import libcore.util.EmptyArray;
124
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700125import org.xmlpull.v1.XmlPullParser;
126import org.xmlpull.v1.XmlPullParserException;
127import org.xmlpull.v1.XmlSerializer;
128
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700129import java.io.File;
Kenny Root38cf8862010-09-26 14:18:51 -0700130import java.io.FileDescriptor;
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700131import java.io.FileInputStream;
132import java.io.FileNotFoundException;
Christopher Tate7265abe2014-11-21 13:54:45 -0800133import java.io.FileOutputStream;
Kenny Root05105f72010-09-22 17:29:43 -0700134import java.io.IOException;
Kenny Root38cf8862010-09-26 14:18:51 -0700135import java.io.PrintWriter;
Kenny Root3b1abba2010-10-13 15:00:07 -0700136import java.math.BigInteger;
Paul Lawrence8e397362014-01-27 15:22:30 -0800137import java.nio.charset.StandardCharsets;
Kenny Root735de3b2010-09-30 14:11:39 -0700138import java.security.NoSuchAlgorithmException;
Kenny Root3b1abba2010-10-13 15:00:07 -0700139import java.security.spec.InvalidKeySpecException;
140import java.security.spec.KeySpec;
San Mehat22dd86e2010-01-12 12:21:18 -0800141import java.util.ArrayList;
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -0800142import java.util.Arrays;
Kenny Roota02b8b02010-08-05 16:14:17 -0700143import java.util.HashMap;
Kenny Root38cf8862010-09-26 14:18:51 -0700144import java.util.Iterator;
Kenny Roota02b8b02010-08-05 16:14:17 -0700145import java.util.LinkedList;
146import java.util.List;
Elliott Hughesf839b4f2014-09-26 12:30:47 -0700147import java.util.Locale;
Kenny Roota02b8b02010-08-05 16:14:17 -0700148import java.util.Map;
Kenny Root38cf8862010-09-26 14:18:51 -0700149import java.util.Map.Entry;
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700150import java.util.Objects;
Jeff Sharkeyb302c542017-09-15 12:57:59 -0600151import java.util.concurrent.CompletableFuture;
Svet Ganov6ee871e2015-07-10 14:29:33 -0700152import java.util.concurrent.CopyOnWriteArrayList;
Kenny Root51a573c2012-05-17 13:30:28 -0700153import java.util.concurrent.CountDownLatch;
154import java.util.concurrent.TimeUnit;
Jeff Sharkeyedcdaf62015-07-09 09:45:36 -0700155import java.util.concurrent.TimeoutException;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800156
Kenny Root3b1abba2010-10-13 15:00:07 -0700157import javax.crypto.SecretKey;
158import javax.crypto.SecretKeyFactory;
159import javax.crypto.spec.PBEKeySpec;
160
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800161/**
Jeff Sharkey48877892015-03-18 11:27:19 -0700162 * Service responsible for various storage media. Connects to {@code vold} to
163 * watch for and manage dynamically added storage, such as SD cards and USB mass
164 * storage. Also decides how storage should be presented to users on the device.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800165 */
Jeff Sharkey9765e442017-12-14 22:15:14 -0700166class StorageManagerService extends IStorageManager.Stub
167 implements Watchdog.Monitor, ScreenObserver {
Jason parks5af0b912010-11-29 09:05:25 -0600168
Christopher Tated417d622013-08-19 16:14:25 -0700169 // Static direct instance pointer for the tightly-coupled idle service to use
Sudheer Shanka2250d562016-11-07 15:41:02 -0800170 static StorageManagerService sSelf = null;
Christopher Tated417d622013-08-19 16:14:25 -0700171
Jeff Sharkey56e62932015-03-21 20:41:00 -0700172 public static class Lifecycle extends SystemService {
Sudheer Shanka2250d562016-11-07 15:41:02 -0800173 private StorageManagerService mStorageManagerService;
Jeff Sharkey56e62932015-03-21 20:41:00 -0700174
175 public Lifecycle(Context context) {
176 super(context);
177 }
178
179 @Override
180 public void onStart() {
Sudheer Shanka2250d562016-11-07 15:41:02 -0800181 mStorageManagerService = new StorageManagerService(getContext());
182 publishBinderService("mount", mStorageManagerService);
183 mStorageManagerService.start();
Jeff Sharkey56e62932015-03-21 20:41:00 -0700184 }
185
186 @Override
187 public void onBootPhase(int phase) {
188 if (phase == SystemService.PHASE_ACTIVITY_MANAGER_READY) {
Sudheer Shanka2250d562016-11-07 15:41:02 -0800189 mStorageManagerService.systemReady();
Yasuhiro Matsuda87a38b52015-07-24 22:10:16 +0900190 } else if (phase == SystemService.PHASE_BOOT_COMPLETED) {
Sudheer Shanka2250d562016-11-07 15:41:02 -0800191 mStorageManagerService.bootCompleted();
Jeff Sharkey56e62932015-03-21 20:41:00 -0700192 }
193 }
Jeff Sharkey48877892015-03-18 11:27:19 -0700194
195 @Override
Jeff Sharkeyab15c392016-05-05 11:45:01 -0600196 public void onSwitchUser(int userHandle) {
Sudheer Shanka2250d562016-11-07 15:41:02 -0800197 mStorageManagerService.mCurrentUserId = userHandle;
Jeff Sharkeyab15c392016-05-05 11:45:01 -0600198 }
199
200 @Override
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700201 public void onUnlockUser(int userHandle) {
Sudheer Shanka2250d562016-11-07 15:41:02 -0800202 mStorageManagerService.onUnlockUser(userHandle);
Jeff Sharkey48877892015-03-18 11:27:19 -0700203 }
204
205 @Override
206 public void onCleanupUser(int userHandle) {
Sudheer Shanka2250d562016-11-07 15:41:02 -0800207 mStorageManagerService.onCleanupUser(userHandle);
Jeff Sharkey48877892015-03-18 11:27:19 -0700208 }
Jeff Sharkey56e62932015-03-21 20:41:00 -0700209 }
210
Dianne Hackborn40e9f292012-11-27 19:12:23 -0800211 private static final boolean DEBUG_EVENTS = false;
Kenny Rootb7db2722011-01-25 16:39:35 -0800212 private static final boolean DEBUG_OBB = false;
Kenny Root02c87302010-07-01 08:10:18 -0700213
Kenny Root07714d42011-08-17 17:49:28 -0700214 // Disable this since it messes up long-running cryptfs operations.
215 private static final boolean WATCHDOG_ENABLE = false;
216
Jeff Sharkey00455bf2016-11-04 14:45:24 -0600217 /**
218 * Our goal is for all Android devices to be usable as development devices,
219 * which includes the new Direct Boot mode added in N. For devices that
220 * don't have native FBE support, we offer an emulation mode for developer
221 * testing purposes, but if it's prohibitively difficult to support this
222 * mode, it can be disabled for specific products using this flag.
223 */
224 private static final boolean EMULATE_FBE_SUPPORTED = true;
225
Sudheer Shanka2250d562016-11-07 15:41:02 -0800226 private static final String TAG = "StorageManagerService";
Jeff Sharkeye8a4b662015-06-27 15:43:45 -0700227
Jeff Sharkey9756d752015-05-14 21:07:42 -0700228 private static final String TAG_STORAGE_BENCHMARK = "storage_benchmark";
Jeff Sharkeye8a4b662015-06-27 15:43:45 -0700229 private static final String TAG_STORAGE_TRIM = "storage_trim";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800230
Jeff Sharkey275e3e42015-04-24 16:10:32 -0700231 /** Magic value sent by MoveTask.cpp */
232 private static final int MOVE_STATUS_COPY_FINISHED = 82;
233
Jeff Sharkey620b32b2015-04-23 19:36:02 -0700234 private static final int VERSION_INIT = 1;
235 private static final int VERSION_ADD_PRIMARY = 2;
Jeff Sharkeyfced5342015-05-10 14:53:34 -0700236 private static final int VERSION_FIX_PRIMARY = 3;
Jeff Sharkey620b32b2015-04-23 19:36:02 -0700237
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700238 private static final String TAG_VOLUMES = "volumes";
Jeff Sharkey620b32b2015-04-23 19:36:02 -0700239 private static final String ATTR_VERSION = "version";
240 private static final String ATTR_PRIMARY_STORAGE_UUID = "primaryStorageUuid";
Jeff Sharkey4c099d02015-05-15 13:45:00 -0700241 private static final String ATTR_FORCE_ADOPTABLE = "forceAdoptable";
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700242 private static final String TAG_VOLUME = "volume";
243 private static final String ATTR_TYPE = "type";
244 private static final String ATTR_FS_UUID = "fsUuid";
Jeff Sharkey5cc0df22015-06-17 19:44:05 -0700245 private static final String ATTR_PART_GUID = "partGuid";
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700246 private static final String ATTR_NICKNAME = "nickname";
247 private static final String ATTR_USER_FLAGS = "userFlags";
Jeff Sharkeye8a4b662015-06-27 15:43:45 -0700248 private static final String ATTR_CREATED_MILLIS = "createdMillis";
249 private static final String ATTR_LAST_TRIM_MILLIS = "lastTrimMillis";
250 private static final String ATTR_LAST_BENCH_MILLIS = "lastBenchMillis";
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700251
Jeff Sharkeyb36586a2015-04-27 08:42:28 -0700252 private final AtomicFile mSettingsFile;
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700253
Jeff Sharkey48877892015-03-18 11:27:19 -0700254 /**
255 * <em>Never</em> hold the lock while performing downcalls into vold, since
256 * unsolicited events can suddenly appear to update data structures.
257 */
Jeff Sharkey5f3e9342017-03-13 14:53:11 -0600258 private final Object mLock = LockGuard.installNewLock(LockGuard.INDEX_STORAGE);
Jeff Sharkey48877892015-03-18 11:27:19 -0700259
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700260 /** Set of users that we know are unlocked. */
Jeff Sharkey48877892015-03-18 11:27:19 -0700261 @GuardedBy("mLock")
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700262 private int[] mLocalUnlockedUsers = EmptyArray.INT;
263 /** Set of users that system knows are unlocked. */
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -0800264 @GuardedBy("mLock")
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700265 private int[] mSystemUnlockedUsers = EmptyArray.INT;
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700266
267 /** Map from disk ID to disk */
Jeff Sharkey48877892015-03-18 11:27:19 -0700268 @GuardedBy("mLock")
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -0700269 private ArrayMap<String, DiskInfo> mDisks = new ArrayMap<>();
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700270 /** Map from volume ID to disk */
Jeff Sharkey48877892015-03-18 11:27:19 -0700271 @GuardedBy("mLock")
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700272 private final ArrayMap<String, VolumeInfo> mVolumes = new ArrayMap<>();
Jeff Sharkey48877892015-03-18 11:27:19 -0700273
Jeff Sharkeyb36586a2015-04-27 08:42:28 -0700274 /** Map from UUID to record */
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700275 @GuardedBy("mLock")
Jeff Sharkeyb36586a2015-04-27 08:42:28 -0700276 private ArrayMap<String, VolumeRecord> mRecords = new ArrayMap<>();
Jeff Sharkey620b32b2015-04-23 19:36:02 -0700277 @GuardedBy("mLock")
278 private String mPrimaryStorageUuid;
Jeff Sharkey4c099d02015-05-15 13:45:00 -0700279 @GuardedBy("mLock")
280 private boolean mForceAdoptable;
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700281
Jeff Sharkeyeba260d2015-04-19 14:35:16 -0700282 /** Map from disk ID to latches */
283 @GuardedBy("mLock")
284 private ArrayMap<String, CountDownLatch> mDiskScanLatches = new ArrayMap<>();
285
Jeff Sharkey275e3e42015-04-24 16:10:32 -0700286 @GuardedBy("mLock")
287 private IPackageMoveObserver mMoveCallback;
288 @GuardedBy("mLock")
289 private String mMoveTargetUuid;
290
Jeff Sharkeyab15c392016-05-05 11:45:01 -0600291 private volatile int mCurrentUserId = UserHandle.USER_SYSTEM;
292
Daichi Hirono9fb00182016-11-08 14:12:17 +0900293 /** Holding lock for AppFuse business */
294 private final Object mAppFuseLock = new Object();
295
296 @GuardedBy("mAppFuseLock")
297 private int mNextAppFuseName = 0;
298
299 @GuardedBy("mAppFuseLock")
Daichi Hironoe56740d2017-02-02 13:56:45 +0900300 private AppFuseBridge mAppFuseBridge = null;
Daichi Hirono9fb00182016-11-08 14:12:17 +0900301
Jeff Sharkeyef10ee02015-07-05 14:17:27 -0700302 private VolumeInfo findVolumeByIdOrThrow(String id) {
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700303 synchronized (mLock) {
304 final VolumeInfo vol = mVolumes.get(id);
305 if (vol != null) {
306 return vol;
307 }
308 }
309 throw new IllegalArgumentException("No volume found for ID " + id);
310 }
311
Jeff Sharkeyef10ee02015-07-05 14:17:27 -0700312 private String findVolumeIdForPathOrThrow(String path) {
Jeff Sharkey48877892015-03-18 11:27:19 -0700313 synchronized (mLock) {
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -0700314 for (int i = 0; i < mVolumes.size(); i++) {
315 final VolumeInfo vol = mVolumes.valueAt(i);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700316 if (vol.path != null && path.startsWith(vol.path)) {
317 return vol.id;
Jeff Sharkey48877892015-03-18 11:27:19 -0700318 }
319 }
320 }
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700321 throw new IllegalArgumentException("No volume found for path " + path);
Jeff Sharkey48877892015-03-18 11:27:19 -0700322 }
323
Jeff Sharkeye8a4b662015-06-27 15:43:45 -0700324 private VolumeRecord findRecordForPath(String path) {
325 synchronized (mLock) {
326 for (int i = 0; i < mVolumes.size(); i++) {
327 final VolumeInfo vol = mVolumes.valueAt(i);
328 if (vol.path != null && path.startsWith(vol.path)) {
329 return mRecords.get(vol.fsUuid);
330 }
331 }
332 }
333 return null;
334 }
335
336 private String scrubPath(String path) {
337 if (path.startsWith(Environment.getDataDirectory().getAbsolutePath())) {
338 return "internal";
339 }
340 final VolumeRecord rec = findRecordForPath(path);
341 if (rec == null || rec.createdMillis == 0) {
342 return "unknown";
343 } else {
344 return "ext:" + (int) ((System.currentTimeMillis() - rec.createdMillis)
345 / DateUtils.WEEK_IN_MILLIS) + "w";
346 }
347 }
348
Jeff Sharkeyef10ee02015-07-05 14:17:27 -0700349 private @Nullable VolumeInfo findStorageForUuid(String volumeUuid) {
Jeff Sharkey275e3e42015-04-24 16:10:32 -0700350 final StorageManager storage = mContext.getSystemService(StorageManager.class);
351 if (Objects.equals(StorageManager.UUID_PRIVATE_INTERNAL, volumeUuid)) {
Jeff Sharkeyef10ee02015-07-05 14:17:27 -0700352 return storage.findVolumeById(VolumeInfo.ID_EMULATED_INTERNAL);
Jeff Sharkey275e3e42015-04-24 16:10:32 -0700353 } else if (Objects.equals(StorageManager.UUID_PRIMARY_PHYSICAL, volumeUuid)) {
354 return storage.getPrimaryPhysicalVolume();
355 } else {
356 return storage.findEmulatedForPrivate(storage.findVolumeByUuid(volumeUuid));
357 }
358 }
359
Jeff Sharkeye8a4b662015-06-27 15:43:45 -0700360 private boolean shouldBenchmark() {
361 final long benchInterval = Settings.Global.getLong(mContext.getContentResolver(),
362 Settings.Global.STORAGE_BENCHMARK_INTERVAL, DateUtils.WEEK_IN_MILLIS);
Jeff Sharkeye83d8a92015-09-09 14:53:38 -0700363 if (benchInterval == -1) {
364 return false;
365 } else if (benchInterval == 0) {
366 return true;
367 }
368
Jeff Sharkeye8a4b662015-06-27 15:43:45 -0700369 synchronized (mLock) {
370 for (int i = 0; i < mVolumes.size(); i++) {
371 final VolumeInfo vol = mVolumes.valueAt(i);
372 final VolumeRecord rec = mRecords.get(vol.fsUuid);
Jeff Sharkeye83d8a92015-09-09 14:53:38 -0700373 if (vol.isMountedWritable() && rec != null) {
Jeff Sharkeye8a4b662015-06-27 15:43:45 -0700374 final long benchAge = System.currentTimeMillis() - rec.lastBenchMillis;
375 if (benchAge >= benchInterval) {
376 return true;
377 }
378 }
379 }
380 return false;
381 }
382 }
383
Jeff Sharkeyeba260d2015-04-19 14:35:16 -0700384 private CountDownLatch findOrCreateDiskScanLatch(String diskId) {
385 synchronized (mLock) {
386 CountDownLatch latch = mDiskScanLatches.get(diskId);
387 if (latch == null) {
388 latch = new CountDownLatch(1);
389 mDiskScanLatches.put(diskId, latch);
390 }
391 return latch;
392 }
393 }
394
Paul Lawrence8e397362014-01-27 15:22:30 -0800395 /** List of crypto types.
396 * These must match CRYPT_TYPE_XXX in cryptfs.h AND their
397 * corresponding commands in CommandListener.cpp */
398 public static final String[] CRYPTO_TYPES
399 = { "password", "default", "pattern", "pin" };
400
Brian Carlstrom7395a8a2014-04-28 22:11:01 -0700401 private final Context mContext;
Jeff Sharkeycd575992016-03-29 14:12:49 -0600402
Jeff Sharkey1019de92017-09-06 13:47:03 -0600403 private volatile IVold mVold;
Jin Qian12690d52017-10-13 18:17:04 -0700404 private volatile IStoraged mStoraged;
Jeff Sharkey1019de92017-09-06 13:47:03 -0600405
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700406 private volatile boolean mSystemReady = false;
Yasuhiro Matsuda87a38b52015-07-24 22:10:16 +0900407 private volatile boolean mBootCompleted = false;
Jeff Sharkey48877892015-03-18 11:27:19 -0700408 private volatile boolean mDaemonConnected = false;
Jeff Sharkey9765e442017-12-14 22:15:14 -0700409 private volatile boolean mSecureKeyguardShowing = true;
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700410
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700411 private PackageManagerService mPms;
412
413 private final Callbacks mCallbacks;
Jeff Sharkeyb9fe5372015-12-03 15:23:08 -0700414 private final LockPatternUtils mLockPatternUtils;
Jeff Sharkey48877892015-03-18 11:27:19 -0700415
San Mehat6cdd9c02010-02-09 14:45:20 -0800416 /**
Kenny Root3b1abba2010-10-13 15:00:07 -0700417 * The size of the crypto algorithm key in bits for OBB files. Currently
418 * Twofish is used which takes 128-bit keys.
419 */
420 private static final int CRYPTO_ALGORITHM_KEY_SIZE = 128;
421
422 /**
423 * The number of times to run SHA1 in the PBKDF2 function for OBB files.
424 * 1024 is reasonably secure and not too slow.
425 */
426 private static final int PBKDF2_HASH_ROUNDS = 1024;
427
428 /**
Kenny Roota02b8b02010-08-05 16:14:17 -0700429 * Mounted OBB tracking information. Used to track the current state of all
430 * OBBs.
Kenny Root02c87302010-07-01 08:10:18 -0700431 */
Kenny Root735de3b2010-09-30 14:11:39 -0700432 final private Map<IBinder, List<ObbState>> mObbMounts = new HashMap<IBinder, List<ObbState>>();
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700433
434 /** Map from raw paths to {@link ObbState}. */
Kenny Roota02b8b02010-08-05 16:14:17 -0700435 final private Map<String, ObbState> mObbPathToStateMap = new HashMap<String, ObbState>();
436
Svet Ganov6ee871e2015-07-10 14:29:33 -0700437 // Not guarded by a lock.
Sudheer Shanka2250d562016-11-07 15:41:02 -0800438 private final StorageManagerInternalImpl mStorageManagerInternal
439 = new StorageManagerInternalImpl();
Svet Ganov6ee871e2015-07-10 14:29:33 -0700440
Kenny Roota02b8b02010-08-05 16:14:17 -0700441 class ObbState implements IBinder.DeathRecipient {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700442 public ObbState(String rawPath, String canonicalPath, int callingUid,
Jeff Sharkey41cd6812017-09-11 10:32:17 -0600443 IObbActionListener token, int nonce, String volId) {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700444 this.rawPath = rawPath;
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700445 this.canonicalPath = canonicalPath;
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700446 this.ownerGid = UserHandle.getSharedAppGid(callingUid);
Kenny Rootaf9d6672010-10-08 09:21:39 -0700447 this.token = token;
448 this.nonce = nonce;
Jeff Sharkey41cd6812017-09-11 10:32:17 -0600449 this.volId = volId;
Kenny Roota02b8b02010-08-05 16:14:17 -0700450 }
451
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700452 final String rawPath;
453 final String canonicalPath;
Kenny Roota02b8b02010-08-05 16:14:17 -0700454
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700455 final int ownerGid;
Kenny Roota02b8b02010-08-05 16:14:17 -0700456
Kenny Rootaf9d6672010-10-08 09:21:39 -0700457 // Token of remote Binder caller
458 final IObbActionListener token;
459
460 // Identifier to pass back to the token
461 final int nonce;
Kenny Roota02b8b02010-08-05 16:14:17 -0700462
Jeff Sharkey41cd6812017-09-11 10:32:17 -0600463 String volId;
464
Kenny Root735de3b2010-09-30 14:11:39 -0700465 public IBinder getBinder() {
466 return token.asBinder();
467 }
468
Kenny Roota02b8b02010-08-05 16:14:17 -0700469 @Override
470 public void binderDied() {
471 ObbAction action = new UnmountObbAction(this, true);
472 mObbActionHandler.sendMessage(mObbActionHandler.obtainMessage(OBB_RUN_ACTION, action));
Kenny Root735de3b2010-09-30 14:11:39 -0700473 }
Kenny Roota02b8b02010-08-05 16:14:17 -0700474
Kenny Root5919ac62010-10-05 09:49:40 -0700475 public void link() throws RemoteException {
476 getBinder().linkToDeath(this, 0);
477 }
478
479 public void unlink() {
Kenny Root735de3b2010-09-30 14:11:39 -0700480 getBinder().unlinkToDeath(this, 0);
Kenny Roota02b8b02010-08-05 16:14:17 -0700481 }
Kenny Root38cf8862010-09-26 14:18:51 -0700482
483 @Override
484 public String toString() {
485 StringBuilder sb = new StringBuilder("ObbState{");
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700486 sb.append("rawPath=").append(rawPath);
487 sb.append(",canonicalPath=").append(canonicalPath);
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700488 sb.append(",ownerGid=").append(ownerGid);
489 sb.append(",token=").append(token);
490 sb.append(",binder=").append(getBinder());
Jeff Sharkey41cd6812017-09-11 10:32:17 -0600491 sb.append(",volId=").append(volId);
Kenny Root38cf8862010-09-26 14:18:51 -0700492 sb.append('}');
493 return sb.toString();
494 }
Kenny Roota02b8b02010-08-05 16:14:17 -0700495 }
496
497 // OBB Action Handler
498 final private ObbActionHandler mObbActionHandler;
499
500 // OBB action handler messages
501 private static final int OBB_RUN_ACTION = 1;
502 private static final int OBB_MCS_BOUND = 2;
503 private static final int OBB_MCS_UNBIND = 3;
504 private static final int OBB_MCS_RECONNECT = 4;
Kenny Rootaf9d6672010-10-08 09:21:39 -0700505 private static final int OBB_FLUSH_MOUNT_STATE = 5;
Kenny Roota02b8b02010-08-05 16:14:17 -0700506
507 /*
508 * Default Container Service information
509 */
510 static final ComponentName DEFAULT_CONTAINER_COMPONENT = new ComponentName(
511 "com.android.defcontainer", "com.android.defcontainer.DefaultContainerService");
512
513 final private DefaultContainerConnection mDefContainerConn = new DefaultContainerConnection();
514
515 class DefaultContainerConnection implements ServiceConnection {
Jeff Sharkey48877892015-03-18 11:27:19 -0700516 @Override
Kenny Roota02b8b02010-08-05 16:14:17 -0700517 public void onServiceConnected(ComponentName name, IBinder service) {
518 if (DEBUG_OBB)
519 Slog.i(TAG, "onServiceConnected");
520 IMediaContainerService imcs = IMediaContainerService.Stub.asInterface(service);
521 mObbActionHandler.sendMessage(mObbActionHandler.obtainMessage(OBB_MCS_BOUND, imcs));
522 }
523
Jeff Sharkey48877892015-03-18 11:27:19 -0700524 @Override
Kenny Roota02b8b02010-08-05 16:14:17 -0700525 public void onServiceDisconnected(ComponentName name) {
526 if (DEBUG_OBB)
527 Slog.i(TAG, "onServiceDisconnected");
528 }
Jeff Sharkey54402792017-09-15 16:05:19 -0600529 }
Kenny Roota02b8b02010-08-05 16:14:17 -0700530
531 // Used in the ObbActionHandler
532 private IMediaContainerService mContainerService = null;
Kenny Root02c87302010-07-01 08:10:18 -0700533
Christopher Tate7265abe2014-11-21 13:54:45 -0800534 // Last fstrim operation tracking
535 private static final String LAST_FSTRIM_FILE = "last-fstrim";
536 private final File mLastMaintenanceFile;
537 private long mLastMaintenance;
538
Kenny Root02c87302010-07-01 08:10:18 -0700539 // Handler messages
Jeff Sharkey48877892015-03-18 11:27:19 -0700540 private static final int H_SYSTEM_READY = 1;
541 private static final int H_DAEMON_CONNECTED = 2;
542 private static final int H_SHUTDOWN = 3;
543 private static final int H_FSTRIM = 4;
544 private static final int H_VOLUME_MOUNT = 5;
545 private static final int H_VOLUME_BROADCAST = 6;
Jeff Sharkeyabc3e852015-08-03 14:41:13 -0700546 private static final int H_INTERNAL_BROADCAST = 7;
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700547 private static final int H_VOLUME_UNMOUNT = 8;
Jeff Sharkey5a9bb742015-11-03 10:15:57 -0800548 private static final int H_PARTITION_FORGET = 9;
549 private static final int H_RESET = 10;
Jin Qiana85b9912017-10-17 15:48:18 -0700550 private static final int H_RUN_IDLE_MAINT = 11;
551 private static final int H_ABORT_IDLE_MAINT = 12;
Suchi Amalapurapu6ffce2e2010-03-08 14:48:40 -0800552
Sudheer Shanka2250d562016-11-07 15:41:02 -0800553 class StorageManagerServiceHandler extends Handler {
554 public StorageManagerServiceHandler(Looper looper) {
Jeff Sharkey48877892015-03-18 11:27:19 -0700555 super(looper);
Daniel Sandler5f27ef42010-03-16 15:42:02 -0400556 }
557
Jason parks5af0b912010-11-29 09:05:25 -0600558 @Override
Suchi Amalapurapuc42e29e2010-02-22 16:03:53 -0800559 public void handleMessage(Message msg) {
560 switch (msg.what) {
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700561 case H_SYSTEM_READY: {
Jeff Sharkey48877892015-03-18 11:27:19 -0700562 handleSystemReady();
563 break;
564 }
565 case H_DAEMON_CONNECTED: {
566 handleDaemonConnected();
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700567 break;
568 }
Christopher Tated417d622013-08-19 16:14:25 -0700569 case H_FSTRIM: {
Christopher Tated417d622013-08-19 16:14:25 -0700570 Slog.i(TAG, "Running fstrim idle maintenance");
Christopher Tate7265abe2014-11-21 13:54:45 -0800571
572 // Remember when we kicked it off
573 try {
574 mLastMaintenance = System.currentTimeMillis();
575 mLastMaintenanceFile.setLastModified(mLastMaintenance);
576 } catch (Exception e) {
577 Slog.e(TAG, "Unable to record last fstrim!");
578 }
579
Jeff Sharkeyb302c542017-09-15 12:57:59 -0600580 // TODO: Reintroduce shouldBenchmark() test
Jeff Sharkey7e19f532017-11-06 13:54:11 -0700581 fstrim(0, null);
Christopher Tate7265abe2014-11-21 13:54:45 -0800582
Christopher Tated417d622013-08-19 16:14:25 -0700583 // invoke the completion callback, if any
Jeff Sharkeye8a4b662015-06-27 15:43:45 -0700584 // TODO: fstrim is non-blocking, so remove this useless callback
Christopher Tated417d622013-08-19 16:14:25 -0700585 Runnable callback = (Runnable) msg.obj;
586 if (callback != null) {
587 callback.run();
588 }
589 break;
590 }
Jeff Sharkey48877892015-03-18 11:27:19 -0700591 case H_SHUTDOWN: {
Sudheer Shanka2250d562016-11-07 15:41:02 -0800592 final IStorageShutdownObserver obs = (IStorageShutdownObserver) msg.obj;
Jeff Sharkey48877892015-03-18 11:27:19 -0700593 boolean success = false;
594 try {
Jeff Sharkey54402792017-09-15 16:05:19 -0600595 mVold.shutdown();
596 success = true;
Jeff Sharkeyace874b2017-09-07 15:27:33 -0600597 } catch (Exception e) {
598 Slog.wtf(TAG, e);
Jeff Sharkey48877892015-03-18 11:27:19 -0700599 }
600 if (obs != null) {
601 try {
602 obs.onShutDownComplete(success ? 0 : -1);
Jeff Sharkeyace874b2017-09-07 15:27:33 -0600603 } catch (Exception ignored) {
Jeff Sharkey48877892015-03-18 11:27:19 -0700604 }
605 }
606 break;
607 }
608 case H_VOLUME_MOUNT: {
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -0700609 final VolumeInfo vol = (VolumeInfo) msg.obj;
Jeff Sharkey2e606d72015-07-27 14:19:54 -0700610 if (isMountDisallowed(vol)) {
611 Slog.i(TAG, "Ignoring mount " + vol.getId() + " due to policy");
612 break;
613 }
Jeff Sharkey48877892015-03-18 11:27:19 -0700614 try {
Jeff Sharkey54402792017-09-15 16:05:19 -0600615 mVold.mount(vol.id, vol.mountFlags, vol.mountUserId);
Jeff Sharkeyace874b2017-09-07 15:27:33 -0600616 } catch (Exception e) {
617 Slog.wtf(TAG, e);
Jeff Sharkey48877892015-03-18 11:27:19 -0700618 }
619 break;
620 }
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700621 case H_VOLUME_UNMOUNT: {
622 final VolumeInfo vol = (VolumeInfo) msg.obj;
623 unmount(vol.getId());
624 break;
625 }
Jeff Sharkey48877892015-03-18 11:27:19 -0700626 case H_VOLUME_BROADCAST: {
627 final StorageVolume userVol = (StorageVolume) msg.obj;
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700628 final String envState = userVol.getState();
629 Slog.d(TAG, "Volume " + userVol.getId() + " broadcasting " + envState + " to "
Jeff Sharkey48877892015-03-18 11:27:19 -0700630 + userVol.getOwner());
631
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700632 final String action = VolumeInfo.getBroadcastForEnvironment(envState);
Jeff Sharkey48877892015-03-18 11:27:19 -0700633 if (action != null) {
634 final Intent intent = new Intent(action,
635 Uri.fromFile(userVol.getPathFile()));
636 intent.putExtra(StorageVolume.EXTRA_STORAGE_VOLUME, userVol);
Jeff Sharkey082f83b2017-03-26 14:34:47 -0600637 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT
638 | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
Jeff Sharkey48877892015-03-18 11:27:19 -0700639 mContext.sendBroadcastAsUser(intent, userVol.getOwner());
640 }
641 break;
642 }
Jeff Sharkeyabc3e852015-08-03 14:41:13 -0700643 case H_INTERNAL_BROADCAST: {
644 // Internal broadcasts aimed at system components, not for
645 // third-party apps.
646 final Intent intent = (Intent) msg.obj;
647 mContext.sendBroadcastAsUser(intent, UserHandle.ALL,
648 android.Manifest.permission.WRITE_MEDIA_STORAGE);
Jeff Sharkey5a9bb742015-11-03 10:15:57 -0800649 break;
650 }
651 case H_PARTITION_FORGET: {
Jeff Sharkeydb4b6192017-10-24 11:08:50 -0600652 final VolumeRecord rec = (VolumeRecord) msg.obj;
653 forgetPartition(rec.partGuid, rec.fsUuid);
Jeff Sharkey5a9bb742015-11-03 10:15:57 -0800654 break;
655 }
656 case H_RESET: {
657 resetIfReadyAndConnected();
658 break;
Jeff Sharkeyabc3e852015-08-03 14:41:13 -0700659 }
Jin Qiana85b9912017-10-17 15:48:18 -0700660 case H_RUN_IDLE_MAINT: {
661 Slog.i(TAG, "Running idle maintenance");
662 runIdleMaint((Runnable)msg.obj);
663 break;
664 }
665 case H_ABORT_IDLE_MAINT: {
666 Slog.i(TAG, "Aborting idle maintenance");
667 abortIdleMaint((Runnable)msg.obj);
668 break;
669 }
670
Suchi Amalapurapuc42e29e2010-02-22 16:03:53 -0800671 }
672 }
Jeff Sharkey48877892015-03-18 11:27:19 -0700673 }
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700674
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700675 private final Handler mHandler;
Suchi Amalapurapuc42e29e2010-02-22 16:03:53 -0800676
Jeff Sharkeybcd262d2015-06-10 09:41:17 -0700677 private BroadcastReceiver mUserReceiver = new BroadcastReceiver() {
678 @Override
679 public void onReceive(Context context, Intent intent) {
680 final String action = intent.getAction();
681 final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700682 Preconditions.checkArgument(userId >= 0);
Jeff Sharkeybcd262d2015-06-10 09:41:17 -0700683
684 try {
685 if (Intent.ACTION_USER_ADDED.equals(action)) {
686 final UserManager um = mContext.getSystemService(UserManager.class);
687 final int userSerialNumber = um.getUserSerialNumber(userId);
Jeff Sharkey54402792017-09-15 16:05:19 -0600688 mVold.onUserAdded(userId, userSerialNumber);
Jeff Sharkeybcd262d2015-06-10 09:41:17 -0700689 } else if (Intent.ACTION_USER_REMOVED.equals(action)) {
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700690 synchronized (mVolumes) {
691 final int size = mVolumes.size();
692 for (int i = 0; i < size; i++) {
693 final VolumeInfo vol = mVolumes.valueAt(i);
694 if (vol.mountUserId == userId) {
695 vol.mountUserId = UserHandle.USER_NULL;
696 mHandler.obtainMessage(H_VOLUME_UNMOUNT, vol).sendToTarget();
697 }
698 }
699 }
Jeff Sharkey54402792017-09-15 16:05:19 -0600700 mVold.onUserRemoved(userId);
Jeff Sharkeybcd262d2015-06-10 09:41:17 -0700701 }
Jeff Sharkeyace874b2017-09-07 15:27:33 -0600702 } catch (Exception e) {
703 Slog.wtf(TAG, e);
Jeff Sharkeybcd262d2015-06-10 09:41:17 -0700704 }
705 }
706 };
707
Jeff Sharkeyedcdaf62015-07-09 09:45:36 -0700708 private void waitForLatch(CountDownLatch latch, String condition, long timeoutMillis)
709 throws TimeoutException {
710 final long startMillis = SystemClock.elapsedRealtime();
Jeff Sharkeyeba260d2015-04-19 14:35:16 -0700711 while (true) {
Kenny Root51a573c2012-05-17 13:30:28 -0700712 try {
713 if (latch.await(5000, TimeUnit.MILLISECONDS)) {
San Mehat207e5382010-02-04 20:46:54 -0800714 return;
Kenny Root51a573c2012-05-17 13:30:28 -0700715 } else {
716 Slog.w(TAG, "Thread " + Thread.currentThread().getName()
Jeff Sharkey48877892015-03-18 11:27:19 -0700717 + " still waiting for " + condition + "...");
San Mehat207e5382010-02-04 20:46:54 -0800718 }
Kenny Root51a573c2012-05-17 13:30:28 -0700719 } catch (InterruptedException e) {
Jeff Sharkeyeba260d2015-04-19 14:35:16 -0700720 Slog.w(TAG, "Interrupt while waiting for " + condition);
San Mehat207e5382010-02-04 20:46:54 -0800721 }
Jeff Sharkeyedcdaf62015-07-09 09:45:36 -0700722 if (timeoutMillis > 0 && SystemClock.elapsedRealtime() > startMillis + timeoutMillis) {
723 throw new TimeoutException("Thread " + Thread.currentThread().getName()
724 + " gave up waiting for " + condition + " after " + timeoutMillis + "ms");
725 }
San Mehat207e5382010-02-04 20:46:54 -0800726 }
San Mehat1f6301e2010-01-07 22:40:27 -0800727 }
Kenny Root02c87302010-07-01 08:10:18 -0700728
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700729 private void handleSystemReady() {
Jeff Sharkey8924e872015-11-30 12:52:10 -0700730 initIfReadyAndConnected();
Jeff Sharkey5a9bb742015-11-03 10:15:57 -0800731 resetIfReadyAndConnected();
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700732
Jeff Sharkey48877892015-03-18 11:27:19 -0700733 // Start scheduling nominally-daily fstrim operations
Christopher Tate115afda2014-06-06 19:06:26 -0700734 MountServiceIdler.scheduleIdlePass(mContext);
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700735 }
736
Jeff Sharkey14cbe522015-07-08 14:06:37 -0700737 /**
738 * MediaProvider has a ton of code that makes assumptions about storage
739 * paths never changing, so we outright kill them to pick up new state.
740 */
741 @Deprecated
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700742 private void killMediaProvider(List<UserInfo> users) {
743 if (users == null) return;
744
Jeff Sharkeyb3cf9532015-07-17 15:12:39 -0700745 final long token = Binder.clearCallingIdentity();
746 try {
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700747 for (UserInfo user : users) {
748 // System user does not have media provider, so skip.
749 if (user.isSystemOnly()) continue;
750
Jeff Sharkey2a9e3f82015-12-18 10:57:58 -0700751 final ProviderInfo provider = mPms.resolveContentProvider(MediaStore.AUTHORITY,
Jeff Sharkey8a372a02016-03-16 16:25:45 -0600752 PackageManager.MATCH_DIRECT_BOOT_AWARE
753 | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
754 user.id);
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700755 if (provider != null) {
Sudheer Shankadc589ac2016-11-10 15:30:17 -0800756 final IActivityManager am = ActivityManager.getService();
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700757 try {
Jeff Sharkey85f449e2016-06-23 09:26:00 -0600758 am.killApplication(provider.applicationInfo.packageName,
759 UserHandle.getAppId(provider.applicationInfo.uid),
760 UserHandle.USER_ALL, "vold reset");
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700761 // We only need to run this once. It will kill all users' media processes.
762 break;
763 } catch (RemoteException e) {
764 }
Jeff Sharkeyb3cf9532015-07-17 15:12:39 -0700765 }
Jeff Sharkey14cbe522015-07-08 14:06:37 -0700766 }
Jeff Sharkeyb3cf9532015-07-17 15:12:39 -0700767 } finally {
768 Binder.restoreCallingIdentity(token);
Jeff Sharkey14cbe522015-07-08 14:06:37 -0700769 }
770 }
771
Jeff Sharkey5a9bb742015-11-03 10:15:57 -0800772 private void addInternalVolumeLocked() {
Amith Yamasania7892482015-08-07 11:09:05 -0700773 // Create a stub volume that represents internal storage
774 final VolumeInfo internal = new VolumeInfo(VolumeInfo.ID_PRIVATE_INTERNAL,
775 VolumeInfo.TYPE_PRIVATE, null, null);
776 internal.state = VolumeInfo.STATE_MOUNTED;
777 internal.path = Environment.getDataDirectory().getAbsolutePath();
778 mVolumes.put(internal.id, internal);
779 }
780
Jeff Sharkey8924e872015-11-30 12:52:10 -0700781 private void initIfReadyAndConnected() {
782 Slog.d(TAG, "Thinking about init, mSystemReady=" + mSystemReady
783 + ", mDaemonConnected=" + mDaemonConnected);
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700784 if (mSystemReady && mDaemonConnected
Paul Lawrence20be5d62016-02-26 13:51:17 -0800785 && !StorageManager.isFileEncryptedNativeOnly()) {
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700786 // When booting a device without native support, make sure that our
787 // user directories are locked or unlocked based on the current
788 // emulation status.
Paul Lawrence20be5d62016-02-26 13:51:17 -0800789 final boolean initLocked = StorageManager.isFileEncryptedEmulatedOnly();
Paul Crowleyd94ab732016-02-15 06:44:51 +0000790 Slog.d(TAG, "Setting up emulation state, initlocked=" + initLocked);
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700791 final List<UserInfo> users = mContext.getSystemService(UserManager.class).getUsers();
Jeff Sharkey8924e872015-11-30 12:52:10 -0700792 for (UserInfo user : users) {
793 try {
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700794 if (initLocked) {
Jeff Sharkey54402792017-09-15 16:05:19 -0600795 mVold.lockUserKey(user.id);
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700796 } else {
Jeff Sharkey54402792017-09-15 16:05:19 -0600797 mVold.unlockUserKey(user.id, user.serialNumber, encodeBytes(null),
798 encodeBytes(null));
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700799 }
Jeff Sharkey43e12112017-09-12 16:31:45 -0600800 } catch (Exception e) {
801 Slog.wtf(TAG, e);
Jeff Sharkey8924e872015-11-30 12:52:10 -0700802 }
803 }
804 }
805 }
806
Jeff Sharkey5a9bb742015-11-03 10:15:57 -0800807 private void resetIfReadyAndConnected() {
Jeff Sharkey48877892015-03-18 11:27:19 -0700808 Slog.d(TAG, "Thinking about reset, mSystemReady=" + mSystemReady
809 + ", mDaemonConnected=" + mDaemonConnected);
810 if (mSystemReady && mDaemonConnected) {
Jeff Sharkey5a9bb742015-11-03 10:15:57 -0800811 final List<UserInfo> users = mContext.getSystemService(UserManager.class).getUsers();
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700812 killMediaProvider(users);
Jeff Sharkey14cbe522015-07-08 14:06:37 -0700813
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700814 final int[] systemUnlockedUsers;
Jeff Sharkey5a9bb742015-11-03 10:15:57 -0800815 synchronized (mLock) {
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700816 systemUnlockedUsers = mSystemUnlockedUsers;
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700817
Jeff Sharkey5a9bb742015-11-03 10:15:57 -0800818 mDisks.clear();
819 mVolumes.clear();
820
821 addInternalVolumeLocked();
822 }
Jeff Sharkey59d577a2015-04-11 21:27:21 -0700823
Jeff Sharkey48877892015-03-18 11:27:19 -0700824 try {
Jeff Sharkey54402792017-09-15 16:05:19 -0600825 mVold.reset();
Jeff Sharkeybcd262d2015-06-10 09:41:17 -0700826
827 // Tell vold about all existing and started users
Jeff Sharkeybcd262d2015-06-10 09:41:17 -0700828 for (UserInfo user : users) {
Jeff Sharkey54402792017-09-15 16:05:19 -0600829 mVold.onUserAdded(user.id, user.serialNumber);
Jeff Sharkeybcd262d2015-06-10 09:41:17 -0700830 }
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700831 for (int userId : systemUnlockedUsers) {
Jeff Sharkey54402792017-09-15 16:05:19 -0600832 mVold.onUserStarted(userId);
Jin Qian12690d52017-10-13 18:17:04 -0700833 mStoraged.onUserStarted(userId);
Jeff Sharkey50a05452015-04-29 11:24:52 -0700834 }
Jeff Sharkey9765e442017-12-14 22:15:14 -0700835 mVold.onSecureKeyguardStateChanged(mSecureKeyguardShowing);
Jeff Sharkeyace874b2017-09-07 15:27:33 -0600836 } catch (Exception e) {
837 Slog.wtf(TAG, e);
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700838 }
839 }
Jeff Sharkey48877892015-03-18 11:27:19 -0700840 }
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700841
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700842 private void onUnlockUser(int userId) {
843 Slog.d(TAG, "onUnlockUser " + userId);
Jeff Sharkey48877892015-03-18 11:27:19 -0700844
845 // We purposefully block here to make sure that user-specific
846 // staging area is ready so it's ready for zygote-forked apps to
847 // bind mount against.
848 try {
Jeff Sharkey54402792017-09-15 16:05:19 -0600849 mVold.onUserStarted(userId);
Jin Qian12690d52017-10-13 18:17:04 -0700850 mStoraged.onUserStarted(userId);
Jeff Sharkeyace874b2017-09-07 15:27:33 -0600851 } catch (Exception e) {
852 Slog.wtf(TAG, e);
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700853 }
Jeff Sharkey48877892015-03-18 11:27:19 -0700854
855 // Record user as started so newly mounted volumes kick off events
856 // correctly, then synthesize events for any already-mounted volumes.
yuanhuihuiefd1f122016-07-13 21:21:03 +0800857 synchronized (mLock) {
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -0700858 for (int i = 0; i < mVolumes.size(); i++) {
859 final VolumeInfo vol = mVolumes.valueAt(i);
Jeff Sharkey46349872015-07-28 10:49:47 -0700860 if (vol.isVisibleForRead(userId) && vol.isMountedReadable()) {
Svet Ganov6ee871e2015-07-10 14:29:33 -0700861 final StorageVolume userVol = vol.buildStorageVolume(mContext, userId, false);
Jeff Sharkey48877892015-03-18 11:27:19 -0700862 mHandler.obtainMessage(H_VOLUME_BROADCAST, userVol).sendToTarget();
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700863
Jeff Sharkey27de30d2015-04-18 16:20:27 -0700864 final String envState = VolumeInfo.getEnvironmentForState(vol.getState());
865 mCallbacks.notifyStorageStateChanged(userVol.getPath(), envState, envState);
Jeff Sharkey48877892015-03-18 11:27:19 -0700866 }
867 }
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700868 mSystemUnlockedUsers = ArrayUtils.appendInt(mSystemUnlockedUsers, userId);
Jeff Sharkey48877892015-03-18 11:27:19 -0700869 }
870 }
871
872 private void onCleanupUser(int userId) {
873 Slog.d(TAG, "onCleanupUser " + userId);
874
875 try {
Jeff Sharkey54402792017-09-15 16:05:19 -0600876 mVold.onUserStopped(userId);
Jin Qian12690d52017-10-13 18:17:04 -0700877 mStoraged.onUserStopped(userId);
Jeff Sharkeyace874b2017-09-07 15:27:33 -0600878 } catch (Exception e) {
879 Slog.wtf(TAG, e);
Jeff Sharkey48877892015-03-18 11:27:19 -0700880 }
881
yuanhuihuiefd1f122016-07-13 21:21:03 +0800882 synchronized (mLock) {
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700883 mSystemUnlockedUsers = ArrayUtils.removeInt(mSystemUnlockedUsers, userId);
Jeff Sharkey48877892015-03-18 11:27:19 -0700884 }
885 }
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700886
Jeff Sharkey9765e442017-12-14 22:15:14 -0700887 @Override
888 public void onAwakeStateChanged(boolean isAwake) {
889 // Ignored
890 }
891
892 @Override
893 public void onKeyguardStateChanged(boolean isShowing) {
894 // Push down current secure keyguard status so that we ignore malicious
895 // USB devices while locked.
896 mSecureKeyguardShowing = isShowing
897 && mContext.getSystemService(KeyguardManager.class).isDeviceSecure();
898 try {
899 mVold.onSecureKeyguardStateChanged(mSecureKeyguardShowing);
900 } catch (Exception e) {
901 Slog.wtf(TAG, e);
902 }
903 }
904
Christopher Tated417d622013-08-19 16:14:25 -0700905 void runIdleMaintenance(Runnable callback) {
906 mHandler.sendMessage(mHandler.obtainMessage(H_FSTRIM, callback));
907 }
908
Christopher Tate7265abe2014-11-21 13:54:45 -0800909 // Binder entry point for kicking off an immediate fstrim
910 @Override
911 public void runMaintenance() {
Jeff Sharkey48877892015-03-18 11:27:19 -0700912 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
Christopher Tate7265abe2014-11-21 13:54:45 -0800913 runIdleMaintenance(null);
914 }
915
916 @Override
917 public long lastMaintenance() {
918 return mLastMaintenance;
919 }
920
San Mehat4270e1e2010-01-29 05:32:19 -0800921 public void onDaemonConnected() {
Jeff Sharkey48877892015-03-18 11:27:19 -0700922 mDaemonConnected = true;
923 mHandler.obtainMessage(H_DAEMON_CONNECTED).sendToTarget();
924 }
925
926 private void handleDaemonConnected() {
Jeff Sharkey8924e872015-11-30 12:52:10 -0700927 initIfReadyAndConnected();
Jeff Sharkey5a9bb742015-11-03 10:15:57 -0800928 resetIfReadyAndConnected();
Jeff Sharkey48877892015-03-18 11:27:19 -0700929
Jeff Sharkey48877892015-03-18 11:27:19 -0700930 // On an encrypted device we can't see system properties yet, so pull
931 // the system locale out of the mount service.
932 if ("".equals(SystemProperties.get("vold.encrypt_progress"))) {
933 copyLocaleFromMountService();
934 }
San Mehat4270e1e2010-01-29 05:32:19 -0800935 }
936
Elliott Hughesf839b4f2014-09-26 12:30:47 -0700937 private void copyLocaleFromMountService() {
938 String systemLocale;
939 try {
940 systemLocale = getField(StorageManager.SYSTEM_LOCALE_KEY);
941 } catch (RemoteException e) {
942 return;
943 }
944 if (TextUtils.isEmpty(systemLocale)) {
945 return;
946 }
947
948 Slog.d(TAG, "Got locale " + systemLocale + " from mount service");
949 Locale locale = Locale.forLanguageTag(systemLocale);
950 Configuration config = new Configuration();
951 config.setLocale(locale);
952 try {
Sudheer Shankadc589ac2016-11-10 15:30:17 -0800953 ActivityManager.getService().updatePersistentConfiguration(config);
Elliott Hughesf839b4f2014-09-26 12:30:47 -0700954 } catch (RemoteException e) {
955 Slog.e(TAG, "Error setting system locale from mount service", e);
956 }
Elliott Hughes9c33f282014-10-13 12:39:56 -0700957
958 // Temporary workaround for http://b/17945169.
959 Slog.d(TAG, "Setting system properties to " + systemLocale + " from mount service");
Narayan Kamathd30dbb82015-01-15 14:48:15 +0000960 SystemProperties.set("persist.sys.locale", locale.toLanguageTag());
Elliott Hughesf839b4f2014-09-26 12:30:47 -0700961 }
962
Jeff Sharkey8058fe62017-09-13 11:50:33 -0600963 private final IVoldListener mListener = new IVoldListener.Stub() {
964 @Override
965 public void onDiskCreated(String diskId, int flags) {
966 synchronized (mLock) {
967 if (SystemProperties.getBoolean(StorageManager.PROP_FORCE_ADOPTABLE, false)
968 || mForceAdoptable) {
969 flags |= DiskInfo.FLAG_ADOPTABLE;
970 }
971 // Adoptable storage isn't currently supported on FBE devices
972 if (StorageManager.isFileEncryptedNativeOnly()
973 && !SystemProperties.getBoolean(StorageManager.PROP_ADOPTABLE_FBE, false)) {
974 flags &= ~DiskInfo.FLAG_ADOPTABLE;
975 }
976 mDisks.put(diskId, new DiskInfo(diskId, flags));
977 }
978 }
979
980 @Override
981 public void onDiskScanned(String diskId) {
982 synchronized (mLock) {
983 final DiskInfo disk = mDisks.get(diskId);
984 if (disk != null) {
985 onDiskScannedLocked(disk);
986 }
987 }
988 }
989
990 @Override
991 public void onDiskMetadataChanged(String diskId, long sizeBytes, String label,
992 String sysPath) {
993 synchronized (mLock) {
994 final DiskInfo disk = mDisks.get(diskId);
995 if (disk != null) {
996 disk.size = sizeBytes;
997 disk.label = label;
998 disk.sysPath = sysPath;
999 }
1000 }
1001 }
1002
1003 @Override
1004 public void onDiskDestroyed(String diskId) {
1005 synchronized (mLock) {
1006 final DiskInfo disk = mDisks.remove(diskId);
1007 if (disk != null) {
1008 mCallbacks.notifyDiskDestroyed(disk);
1009 }
1010 }
1011 }
1012
1013 @Override
1014 public void onVolumeCreated(String volId, int type, String diskId, String partGuid) {
1015 synchronized (mLock) {
1016 final DiskInfo disk = mDisks.get(diskId);
1017 final VolumeInfo vol = new VolumeInfo(volId, type, disk, partGuid);
1018 mVolumes.put(volId, vol);
1019 onVolumeCreatedLocked(vol);
1020 }
1021 }
1022
1023 @Override
1024 public void onVolumeStateChanged(String volId, int state) {
1025 synchronized (mLock) {
1026 final VolumeInfo vol = mVolumes.get(volId);
1027 if (vol != null) {
1028 final int oldState = vol.state;
1029 final int newState = state;
1030 vol.state = newState;
1031 onVolumeStateChangedLocked(vol, oldState, newState);
1032 }
1033 }
1034 }
1035
1036 @Override
1037 public void onVolumeMetadataChanged(String volId, String fsType, String fsUuid,
1038 String fsLabel) {
1039 synchronized (mLock) {
1040 final VolumeInfo vol = mVolumes.get(volId);
1041 if (vol != null) {
1042 vol.fsType = fsType;
1043 vol.fsUuid = fsUuid;
1044 vol.fsLabel = fsLabel;
1045 }
1046 }
1047 }
1048
1049 @Override
1050 public void onVolumePathChanged(String volId, String path) {
1051 synchronized (mLock) {
1052 final VolumeInfo vol = mVolumes.get(volId);
1053 if (vol != null) {
1054 vol.path = path;
1055 }
1056 }
1057 }
1058
1059 @Override
1060 public void onVolumeInternalPathChanged(String volId, String internalPath) {
1061 synchronized (mLock) {
1062 final VolumeInfo vol = mVolumes.get(volId);
1063 if (vol != null) {
1064 vol.internalPath = internalPath;
1065 }
1066 }
1067 }
1068
1069 @Override
1070 public void onVolumeDestroyed(String volId) {
1071 synchronized (mLock) {
1072 mVolumes.remove(volId);
1073 }
1074 }
1075 };
1076
Jeff Sharkeyeba260d2015-04-19 14:35:16 -07001077 private void onDiskScannedLocked(DiskInfo disk) {
Jeff Sharkey620b32b2015-04-23 19:36:02 -07001078 int volumeCount = 0;
Jeff Sharkeyeba260d2015-04-19 14:35:16 -07001079 for (int i = 0; i < mVolumes.size(); i++) {
1080 final VolumeInfo vol = mVolumes.valueAt(i);
1081 if (Objects.equals(disk.id, vol.getDiskId())) {
Jeff Sharkey620b32b2015-04-23 19:36:02 -07001082 volumeCount++;
Jeff Sharkeyeba260d2015-04-19 14:35:16 -07001083 }
1084 }
1085
Jeff Sharkeyc7acac62015-06-12 16:16:56 -07001086 final Intent intent = new Intent(DiskInfo.ACTION_DISK_SCANNED);
Jeff Sharkey7732e1e2016-03-30 17:14:23 -06001087 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT
1088 | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
Jeff Sharkeyc7acac62015-06-12 16:16:56 -07001089 intent.putExtra(DiskInfo.EXTRA_DISK_ID, disk.id);
1090 intent.putExtra(DiskInfo.EXTRA_VOLUME_COUNT, volumeCount);
Jeff Sharkeyabc3e852015-08-03 14:41:13 -07001091 mHandler.obtainMessage(H_INTERNAL_BROADCAST, intent).sendToTarget();
Jeff Sharkeyc7acac62015-06-12 16:16:56 -07001092
1093 final CountDownLatch latch = mDiskScanLatches.remove(disk.id);
1094 if (latch != null) {
1095 latch.countDown();
1096 }
1097
Jeff Sharkeyf5a6bd72015-05-19 14:42:38 -07001098 disk.volumeCount = volumeCount;
Jeff Sharkey620b32b2015-04-23 19:36:02 -07001099 mCallbacks.notifyDiskScanned(disk, volumeCount);
Jeff Sharkeyeba260d2015-04-19 14:35:16 -07001100 }
1101
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07001102 private void onVolumeCreatedLocked(VolumeInfo vol) {
Jeff Sharkey6855c482016-03-31 14:34:38 -06001103 if (mPms.isOnlyCoreApps()) {
1104 Slog.d(TAG, "System booted in core-only mode; ignoring volume " + vol.getId());
1105 return;
1106 }
1107
Jeff Sharkey275e3e42015-04-24 16:10:32 -07001108 if (vol.type == VolumeInfo.TYPE_EMULATED) {
1109 final StorageManager storage = mContext.getSystemService(StorageManager.class);
1110 final VolumeInfo privateVol = storage.findPrivateForEmulated(vol);
1111
1112 if (Objects.equals(StorageManager.UUID_PRIVATE_INTERNAL, mPrimaryStorageUuid)
1113 && VolumeInfo.ID_PRIVATE_INTERNAL.equals(privateVol.id)) {
1114 Slog.v(TAG, "Found primary storage at " + vol);
1115 vol.mountFlags |= VolumeInfo.MOUNT_FLAG_PRIMARY;
1116 vol.mountFlags |= VolumeInfo.MOUNT_FLAG_VISIBLE;
1117 mHandler.obtainMessage(H_VOLUME_MOUNT, vol).sendToTarget();
1118
1119 } else if (Objects.equals(privateVol.fsUuid, mPrimaryStorageUuid)) {
1120 Slog.v(TAG, "Found primary storage at " + vol);
1121 vol.mountFlags |= VolumeInfo.MOUNT_FLAG_PRIMARY;
1122 vol.mountFlags |= VolumeInfo.MOUNT_FLAG_VISIBLE;
1123 mHandler.obtainMessage(H_VOLUME_MOUNT, vol).sendToTarget();
1124 }
Jeff Sharkeyb049e212012-09-07 23:16:01 -07001125
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07001126 } else if (vol.type == VolumeInfo.TYPE_PUBLIC) {
Jeff Sharkey275e3e42015-04-24 16:10:32 -07001127 // TODO: only look at first public partition
1128 if (Objects.equals(StorageManager.UUID_PRIMARY_PHYSICAL, mPrimaryStorageUuid)
1129 && vol.disk.isDefaultPrimary()) {
1130 Slog.v(TAG, "Found primary storage at " + vol);
Jeff Sharkey7e92ef32015-04-17 17:35:07 -07001131 vol.mountFlags |= VolumeInfo.MOUNT_FLAG_PRIMARY;
1132 vol.mountFlags |= VolumeInfo.MOUNT_FLAG_VISIBLE;
San Mehat4270e1e2010-01-29 05:32:19 -08001133 }
Jeff Sharkey7e92ef32015-04-17 17:35:07 -07001134
1135 // Adoptable public disks are visible to apps, since they meet
1136 // public API requirement of being in a stable location.
Jeff Sharkey275e3e42015-04-24 16:10:32 -07001137 if (vol.disk.isAdoptable()) {
Jeff Sharkey7e92ef32015-04-17 17:35:07 -07001138 vol.mountFlags |= VolumeInfo.MOUNT_FLAG_VISIBLE;
1139 }
1140
Jeff Sharkeyab15c392016-05-05 11:45:01 -06001141 vol.mountUserId = mCurrentUserId;
Jeff Sharkey48877892015-03-18 11:27:19 -07001142 mHandler.obtainMessage(H_VOLUME_MOUNT, vol).sendToTarget();
San Mehat4270e1e2010-01-29 05:32:19 -08001143
Jeff Sharkeyb2b9ab82015-04-05 21:10:42 -07001144 } else if (vol.type == VolumeInfo.TYPE_PRIVATE) {
1145 mHandler.obtainMessage(H_VOLUME_MOUNT, vol).sendToTarget();
1146
San Mehat4270e1e2010-01-29 05:32:19 -08001147 } else {
Jeff Sharkey48877892015-03-18 11:27:19 -07001148 Slog.d(TAG, "Skipping automatic mounting of " + vol);
San Mehat4270e1e2010-01-29 05:32:19 -08001149 }
1150 }
1151
Jeff Sharkeye6c04f92015-04-18 21:38:05 -07001152 private boolean isBroadcastWorthy(VolumeInfo vol) {
1153 switch (vol.getType()) {
Jeff Sharkeyc7acac62015-06-12 16:16:56 -07001154 case VolumeInfo.TYPE_PRIVATE:
Jeff Sharkeye6c04f92015-04-18 21:38:05 -07001155 case VolumeInfo.TYPE_PUBLIC:
1156 case VolumeInfo.TYPE_EMULATED:
1157 break;
1158 default:
1159 return false;
1160 }
1161
1162 switch (vol.getState()) {
1163 case VolumeInfo.STATE_MOUNTED:
1164 case VolumeInfo.STATE_MOUNTED_READ_ONLY:
1165 case VolumeInfo.STATE_EJECTING:
1166 case VolumeInfo.STATE_UNMOUNTED:
Jeff Sharkeyc7acac62015-06-12 16:16:56 -07001167 case VolumeInfo.STATE_UNMOUNTABLE:
Tony Mantlerf0d71052015-06-24 11:45:25 -07001168 case VolumeInfo.STATE_BAD_REMOVAL:
Jeff Sharkeye6c04f92015-04-18 21:38:05 -07001169 break;
1170 default:
1171 return false;
1172 }
1173
1174 return true;
1175 }
1176
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07001177 private void onVolumeStateChangedLocked(VolumeInfo vol, int oldState, int newState) {
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001178 // Remember that we saw this volume so we're ready to accept user
1179 // metadata, or so we can annoy them when a private volume is ejected
1180 if (vol.isMountedReadable() && !TextUtils.isEmpty(vol.fsUuid)) {
Jeff Sharkey5cc0df22015-06-17 19:44:05 -07001181 VolumeRecord rec = mRecords.get(vol.fsUuid);
1182 if (rec == null) {
1183 rec = new VolumeRecord(vol.type, vol.fsUuid);
1184 rec.partGuid = vol.partGuid;
Jeff Sharkeye8a4b662015-06-27 15:43:45 -07001185 rec.createdMillis = System.currentTimeMillis();
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001186 if (vol.type == VolumeInfo.TYPE_PRIVATE) {
1187 rec.nickname = vol.disk.getDescription();
1188 }
1189 mRecords.put(rec.fsUuid, rec);
1190 writeSettingsLocked();
Jeff Sharkey5cc0df22015-06-17 19:44:05 -07001191 } else {
1192 // Handle upgrade case where we didn't store partition GUID
1193 if (TextUtils.isEmpty(rec.partGuid)) {
1194 rec.partGuid = vol.partGuid;
1195 writeSettingsLocked();
1196 }
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001197 }
1198 }
1199
Jeff Sharkeye6c04f92015-04-18 21:38:05 -07001200 mCallbacks.notifyVolumeStateChanged(vol, oldState, newState);
1201
Yasuhiro Matsuda87a38b52015-07-24 22:10:16 +09001202 // Do not broadcast before boot has completed to avoid launching the
1203 // processes that receive the intent unnecessarily.
1204 if (mBootCompleted && isBroadcastWorthy(vol)) {
Jeff Sharkeye6c04f92015-04-18 21:38:05 -07001205 final Intent intent = new Intent(VolumeInfo.ACTION_VOLUME_STATE_CHANGED);
Jeff Sharkeyc7acac62015-06-12 16:16:56 -07001206 intent.putExtra(VolumeInfo.EXTRA_VOLUME_ID, vol.id);
1207 intent.putExtra(VolumeInfo.EXTRA_VOLUME_STATE, newState);
Tony Mantlerf0d71052015-06-24 11:45:25 -07001208 intent.putExtra(VolumeRecord.EXTRA_FS_UUID, vol.fsUuid);
Jeff Sharkey7732e1e2016-03-30 17:14:23 -06001209 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT
1210 | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
Jeff Sharkeyabc3e852015-08-03 14:41:13 -07001211 mHandler.obtainMessage(H_INTERNAL_BROADCAST, intent).sendToTarget();
Jeff Sharkeye6c04f92015-04-18 21:38:05 -07001212 }
Jeff Sharkeyb049e212012-09-07 23:16:01 -07001213
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001214 final String oldStateEnv = VolumeInfo.getEnvironmentForState(oldState);
1215 final String newStateEnv = VolumeInfo.getEnvironmentForState(newState);
Emily Bernier92aa5a22014-07-07 10:11:48 -04001216
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001217 if (!Objects.equals(oldStateEnv, newStateEnv)) {
1218 // Kick state changed event towards all started users. Any users
1219 // started after this point will trigger additional
1220 // user-specific broadcasts.
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07001221 for (int userId : mSystemUnlockedUsers) {
Jeff Sharkey46349872015-07-28 10:49:47 -07001222 if (vol.isVisibleForRead(userId)) {
Svet Ganov6ee871e2015-07-10 14:29:33 -07001223 final StorageVolume userVol = vol.buildStorageVolume(mContext, userId, false);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001224 mHandler.obtainMessage(H_VOLUME_BROADCAST, userVol).sendToTarget();
Jeff Sharkey48877892015-03-18 11:27:19 -07001225
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001226 mCallbacks.notifyStorageStateChanged(userVol.getPath(), oldStateEnv,
1227 newStateEnv);
San Mehat4270e1e2010-01-29 05:32:19 -08001228 }
1229 }
1230 }
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001231
Jeff Sharkey7e92ef32015-04-17 17:35:07 -07001232 if (vol.type == VolumeInfo.TYPE_PUBLIC && vol.state == VolumeInfo.STATE_EJECTING) {
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001233 // TODO: this should eventually be handled by new ObbVolume state changes
1234 /*
1235 * Some OBBs might have been unmounted when this volume was
1236 * unmounted, so send a message to the handler to let it know to
1237 * remove those from the list of mounted OBBS.
1238 */
1239 mObbActionHandler.sendMessage(mObbActionHandler.obtainMessage(
1240 OBB_FLUSH_MOUNT_STATE, vol.path));
1241 }
San Mehat4270e1e2010-01-29 05:32:19 -08001242 }
1243
Jeff Sharkey275e3e42015-04-24 16:10:32 -07001244 private void onMoveStatusLocked(int status) {
1245 if (mMoveCallback == null) {
1246 Slog.w(TAG, "Odd, status but no move requested");
1247 return;
1248 }
1249
1250 // TODO: estimate remaining time
1251 try {
Jeff Sharkey50a05452015-04-29 11:24:52 -07001252 mMoveCallback.onStatusChanged(-1, status, -1);
Jeff Sharkey275e3e42015-04-24 16:10:32 -07001253 } catch (RemoteException ignored) {
1254 }
1255
1256 // We've finished copying and we're about to clean up old data, so
1257 // remember that move was successful if we get rebooted
1258 if (status == MOVE_STATUS_COPY_FINISHED) {
1259 Slog.d(TAG, "Move to " + mMoveTargetUuid + " copy phase finshed; persisting");
1260
1261 mPrimaryStorageUuid = mMoveTargetUuid;
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001262 writeSettingsLocked();
Jeff Sharkey275e3e42015-04-24 16:10:32 -07001263 }
1264
1265 if (PackageManager.isMoveStatusFinished(status)) {
1266 Slog.d(TAG, "Move to " + mMoveTargetUuid + " finished with status " + status);
1267
1268 mMoveCallback = null;
1269 mMoveTargetUuid = null;
1270 }
1271 }
1272
Jeff Sharkey48877892015-03-18 11:27:19 -07001273 private void enforcePermission(String perm) {
1274 mContext.enforceCallingOrSelfPermission(perm, perm);
Mike Lockwooda5250c92011-05-23 13:44:04 -04001275 }
1276
Jeff Sharkey2e606d72015-07-27 14:19:54 -07001277 /**
1278 * Decide if volume is mountable per device policies.
1279 */
1280 private boolean isMountDisallowed(VolumeInfo vol) {
Philip P. Moltmannec3cbb22016-09-14 13:24:52 -07001281 UserManager userManager = mContext.getSystemService(UserManager.class);
1282
1283 boolean isUsbRestricted = false;
1284 if (vol.disk != null && vol.disk.isUsb()) {
1285 isUsbRestricted = userManager.hasUserRestriction(UserManager.DISALLOW_USB_FILE_TRANSFER,
Jeff Sharkey2e606d72015-07-27 14:19:54 -07001286 Binder.getCallingUserHandle());
Emily Bernier92aa5a22014-07-07 10:11:48 -04001287 }
Philip P. Moltmannec3cbb22016-09-14 13:24:52 -07001288
1289 boolean isTypeRestricted = false;
1290 if (vol.type == VolumeInfo.TYPE_PUBLIC || vol.type == VolumeInfo.TYPE_PRIVATE) {
1291 isTypeRestricted = userManager
1292 .hasUserRestriction(UserManager.DISALLOW_MOUNT_PHYSICAL_MEDIA,
1293 Binder.getCallingUserHandle());
1294 }
1295
1296 return isUsbRestricted || isTypeRestricted;
Emily Bernier92aa5a22014-07-07 10:11:48 -04001297 }
1298
Amith Yamasani462ac3a2015-06-30 14:21:01 -07001299 private void enforceAdminUser() {
1300 UserManager um = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
1301 final int callingUserId = UserHandle.getCallingUserId();
1302 boolean isAdmin;
1303 long token = Binder.clearCallingIdentity();
1304 try {
1305 isAdmin = um.getUserInfo(callingUserId).isAdmin();
1306 } finally {
1307 Binder.restoreCallingIdentity(token);
1308 }
1309 if (!isAdmin) {
1310 throw new SecurityException("Only admin users can adopt sd cards");
1311 }
1312 }
1313
Jeff Sharkeyb049e212012-09-07 23:16:01 -07001314 /**
Sudheer Shanka2250d562016-11-07 15:41:02 -08001315 * Constructs a new StorageManagerService instance
San Mehat207e5382010-02-04 20:46:54 -08001316 *
1317 * @param context Binder context for this service
1318 */
Sudheer Shanka2250d562016-11-07 15:41:02 -08001319 public StorageManagerService(Context context) {
Christopher Tated417d622013-08-19 16:14:25 -07001320 sSelf = this;
1321
San Mehat207e5382010-02-04 20:46:54 -08001322 mContext = context;
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001323 mCallbacks = new Callbacks(FgThread.get().getLooper());
Jeff Sharkeyb9fe5372015-12-03 15:23:08 -07001324 mLockPatternUtils = new LockPatternUtils(mContext);
San Mehat207e5382010-02-04 20:46:54 -08001325
San Mehat207e5382010-02-04 20:46:54 -08001326 // XXX: This will go away soon in favor of IMountServiceObserver
1327 mPms = (PackageManagerService) ServiceManager.getService("package");
1328
Dianne Hackbornefa92b22013-05-03 14:11:43 -07001329 HandlerThread hthread = new HandlerThread(TAG);
1330 hthread.start();
Sudheer Shanka2250d562016-11-07 15:41:02 -08001331 mHandler = new StorageManagerServiceHandler(hthread.getLooper());
Daniel Sandler5f27ef42010-03-16 15:42:02 -04001332
Sudheer Shanka2250d562016-11-07 15:41:02 -08001333 // Add OBB Action Handler to StorageManagerService thread.
Dianne Hackborn8d044e82013-04-30 17:24:15 -07001334 mObbActionHandler = new ObbActionHandler(IoThread.get().getLooper());
Kenny Roota02b8b02010-08-05 16:14:17 -07001335
Christopher Tate7265abe2014-11-21 13:54:45 -08001336 // Initialize the last-fstrim tracking if necessary
1337 File dataDir = Environment.getDataDirectory();
1338 File systemDir = new File(dataDir, "system");
1339 mLastMaintenanceFile = new File(systemDir, LAST_FSTRIM_FILE);
1340 if (!mLastMaintenanceFile.exists()) {
1341 // Not setting mLastMaintenance here means that we will force an
1342 // fstrim during reboot following the OTA that installs this code.
1343 try {
1344 (new FileOutputStream(mLastMaintenanceFile)).close();
1345 } catch (IOException e) {
1346 Slog.e(TAG, "Unable to create fstrim record " + mLastMaintenanceFile.getPath());
1347 }
1348 } else {
1349 mLastMaintenance = mLastMaintenanceFile.lastModified();
1350 }
1351
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001352 mSettingsFile = new AtomicFile(
Jeff Sharkey8212ae02016-02-10 14:46:43 -07001353 new File(Environment.getDataSystemDirectory(), "storage.xml"));
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001354
1355 synchronized (mLock) {
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001356 readSettingsLocked();
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001357 }
1358
Sudheer Shanka2250d562016-11-07 15:41:02 -08001359 LocalServices.addService(StorageManagerInternal.class, mStorageManagerInternal);
Svet Ganov6ee871e2015-07-10 14:29:33 -07001360
Jeff Sharkeybcd262d2015-06-10 09:41:17 -07001361 final IntentFilter userFilter = new IntentFilter();
1362 userFilter.addAction(Intent.ACTION_USER_ADDED);
1363 userFilter.addAction(Intent.ACTION_USER_REMOVED);
1364 mContext.registerReceiver(mUserReceiver, userFilter, null, mHandler);
1365
Jeff Sharkey5a9bb742015-11-03 10:15:57 -08001366 synchronized (mLock) {
1367 addInternalVolumeLocked();
1368 }
Amith Yamasania7892482015-08-07 11:09:05 -07001369
Kenny Root07714d42011-08-17 17:49:28 -07001370 // Add ourself to the Watchdog monitors if enabled.
1371 if (WATCHDOG_ENABLE) {
1372 Watchdog.getInstance().addMonitor(this);
1373 }
San Mehat207e5382010-02-04 20:46:54 -08001374 }
1375
Jeff Sharkeycd575992016-03-29 14:12:49 -06001376 private void start() {
Jeff Sharkey1019de92017-09-06 13:47:03 -06001377 connect();
Jeff Sharkeycd575992016-03-29 14:12:49 -06001378 }
1379
Jeff Sharkey1019de92017-09-06 13:47:03 -06001380 private void connect() {
Jin Qian12690d52017-10-13 18:17:04 -07001381 IBinder binder = ServiceManager.getService("storaged");
1382 if (binder != null) {
1383 try {
1384 binder.linkToDeath(new DeathRecipient() {
1385 @Override
1386 public void binderDied() {
1387 Slog.w(TAG, "storaged died; reconnecting");
1388 mStoraged = null;
1389 connect();
1390 }
1391 }, 0);
1392 } catch (RemoteException e) {
1393 binder = null;
1394 }
1395 }
1396
1397 if (binder != null) {
1398 mStoraged = IStoraged.Stub.asInterface(binder);
1399 } else {
1400 Slog.w(TAG, "storaged not found; trying again");
1401 }
1402
1403 binder = ServiceManager.getService("vold");
Jeff Sharkey1019de92017-09-06 13:47:03 -06001404 if (binder != null) {
1405 try {
1406 binder.linkToDeath(new DeathRecipient() {
1407 @Override
1408 public void binderDied() {
1409 Slog.w(TAG, "vold died; reconnecting");
Jin Qian12690d52017-10-13 18:17:04 -07001410 mVold = null;
Jeff Sharkey1019de92017-09-06 13:47:03 -06001411 connect();
1412 }
1413 }, 0);
1414 } catch (RemoteException e) {
1415 binder = null;
1416 }
1417 }
1418
1419 if (binder != null) {
1420 mVold = IVold.Stub.asInterface(binder);
Jeff Sharkey8058fe62017-09-13 11:50:33 -06001421 try {
1422 mVold.setListener(mListener);
Jeff Sharkey8058fe62017-09-13 11:50:33 -06001423 } catch (RemoteException e) {
Jin Qian12690d52017-10-13 18:17:04 -07001424 mVold = null;
Jeff Sharkey8058fe62017-09-13 11:50:33 -06001425 Slog.w(TAG, "vold listener rejected; trying again", e);
1426 }
Jeff Sharkey1019de92017-09-06 13:47:03 -06001427 } else {
1428 Slog.w(TAG, "vold not found; trying again");
Jeff Sharkey1019de92017-09-06 13:47:03 -06001429 }
Jeff Sharkey8058fe62017-09-13 11:50:33 -06001430
Jin Qian12690d52017-10-13 18:17:04 -07001431 if (mStoraged == null || mVold == null) {
1432 BackgroundThread.getHandler().postDelayed(() -> {
1433 connect();
1434 }, DateUtils.SECOND_IN_MILLIS);
1435 } else {
1436 onDaemonConnected();
1437 }
Jeff Sharkey1019de92017-09-06 13:47:03 -06001438 }
1439
Jeff Sharkey56e62932015-03-21 20:41:00 -07001440 private void systemReady() {
Jeff Sharkey9765e442017-12-14 22:15:14 -07001441 LocalServices.getService(ActivityManagerInternal.class)
1442 .registerScreenObserver(this);
1443
Jeff Sharkeyb049e212012-09-07 23:16:01 -07001444 mSystemReady = true;
1445 mHandler.obtainMessage(H_SYSTEM_READY).sendToTarget();
1446 }
1447
Yasuhiro Matsuda87a38b52015-07-24 22:10:16 +09001448 private void bootCompleted() {
1449 mBootCompleted = true;
1450 }
1451
Jeff Sharkeyfced5342015-05-10 14:53:34 -07001452 private String getDefaultPrimaryStorageUuid() {
1453 if (SystemProperties.getBoolean(StorageManager.PROP_PRIMARY_PHYSICAL, false)) {
1454 return StorageManager.UUID_PRIMARY_PHYSICAL;
1455 } else {
1456 return StorageManager.UUID_PRIVATE_INTERNAL;
1457 }
1458 }
1459
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001460 private void readSettingsLocked() {
1461 mRecords.clear();
Jeff Sharkeyfced5342015-05-10 14:53:34 -07001462 mPrimaryStorageUuid = getDefaultPrimaryStorageUuid();
Jeff Sharkey4c099d02015-05-15 13:45:00 -07001463 mForceAdoptable = false;
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001464
1465 FileInputStream fis = null;
1466 try {
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001467 fis = mSettingsFile.openRead();
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001468 final XmlPullParser in = Xml.newPullParser();
Wojciech Staszkiewicz9e9e2e72015-05-08 14:58:46 +01001469 in.setInput(fis, StandardCharsets.UTF_8.name());
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001470
1471 int type;
1472 while ((type = in.next()) != END_DOCUMENT) {
1473 if (type == START_TAG) {
1474 final String tag = in.getName();
Jeff Sharkey620b32b2015-04-23 19:36:02 -07001475 if (TAG_VOLUMES.equals(tag)) {
1476 final int version = readIntAttribute(in, ATTR_VERSION, VERSION_INIT);
Jeff Sharkeyfced5342015-05-10 14:53:34 -07001477 final boolean primaryPhysical = SystemProperties.getBoolean(
1478 StorageManager.PROP_PRIMARY_PHYSICAL, false);
1479 final boolean validAttr = (version >= VERSION_FIX_PRIMARY)
1480 || (version >= VERSION_ADD_PRIMARY && !primaryPhysical);
1481 if (validAttr) {
Jeff Sharkey620b32b2015-04-23 19:36:02 -07001482 mPrimaryStorageUuid = readStringAttribute(in,
1483 ATTR_PRIMARY_STORAGE_UUID);
Jeff Sharkey620b32b2015-04-23 19:36:02 -07001484 }
Jeff Sharkey4c099d02015-05-15 13:45:00 -07001485 mForceAdoptable = readBooleanAttribute(in, ATTR_FORCE_ADOPTABLE, false);
Jeff Sharkey620b32b2015-04-23 19:36:02 -07001486
1487 } else if (TAG_VOLUME.equals(tag)) {
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001488 final VolumeRecord rec = readVolumeRecord(in);
1489 mRecords.put(rec.fsUuid, rec);
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001490 }
1491 }
1492 }
1493 } catch (FileNotFoundException e) {
1494 // Missing metadata is okay, probably first boot
1495 } catch (IOException e) {
1496 Slog.wtf(TAG, "Failed reading metadata", e);
1497 } catch (XmlPullParserException e) {
1498 Slog.wtf(TAG, "Failed reading metadata", e);
1499 } finally {
1500 IoUtils.closeQuietly(fis);
1501 }
1502 }
1503
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001504 private void writeSettingsLocked() {
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001505 FileOutputStream fos = null;
1506 try {
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001507 fos = mSettingsFile.startWrite();
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001508
1509 XmlSerializer out = new FastXmlSerializer();
Wojciech Staszkiewicz9e9e2e72015-05-08 14:58:46 +01001510 out.setOutput(fos, StandardCharsets.UTF_8.name());
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001511 out.startDocument(null, true);
1512 out.startTag(null, TAG_VOLUMES);
Jeff Sharkeyfced5342015-05-10 14:53:34 -07001513 writeIntAttribute(out, ATTR_VERSION, VERSION_FIX_PRIMARY);
Jeff Sharkey620b32b2015-04-23 19:36:02 -07001514 writeStringAttribute(out, ATTR_PRIMARY_STORAGE_UUID, mPrimaryStorageUuid);
Jeff Sharkey4c099d02015-05-15 13:45:00 -07001515 writeBooleanAttribute(out, ATTR_FORCE_ADOPTABLE, mForceAdoptable);
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001516 final int size = mRecords.size();
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001517 for (int i = 0; i < size; i++) {
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001518 final VolumeRecord rec = mRecords.valueAt(i);
1519 writeVolumeRecord(out, rec);
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001520 }
1521 out.endTag(null, TAG_VOLUMES);
1522 out.endDocument();
1523
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001524 mSettingsFile.finishWrite(fos);
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001525 } catch (IOException e) {
1526 if (fos != null) {
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001527 mSettingsFile.failWrite(fos);
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001528 }
1529 }
1530 }
1531
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001532 public static VolumeRecord readVolumeRecord(XmlPullParser in) throws IOException {
1533 final int type = readIntAttribute(in, ATTR_TYPE);
1534 final String fsUuid = readStringAttribute(in, ATTR_FS_UUID);
1535 final VolumeRecord meta = new VolumeRecord(type, fsUuid);
Jeff Sharkey5cc0df22015-06-17 19:44:05 -07001536 meta.partGuid = readStringAttribute(in, ATTR_PART_GUID);
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001537 meta.nickname = readStringAttribute(in, ATTR_NICKNAME);
1538 meta.userFlags = readIntAttribute(in, ATTR_USER_FLAGS);
Jeff Sharkeye8a4b662015-06-27 15:43:45 -07001539 meta.createdMillis = readLongAttribute(in, ATTR_CREATED_MILLIS);
1540 meta.lastTrimMillis = readLongAttribute(in, ATTR_LAST_TRIM_MILLIS);
1541 meta.lastBenchMillis = readLongAttribute(in, ATTR_LAST_BENCH_MILLIS);
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001542 return meta;
1543 }
1544
1545 public static void writeVolumeRecord(XmlSerializer out, VolumeRecord rec) throws IOException {
1546 out.startTag(null, TAG_VOLUME);
1547 writeIntAttribute(out, ATTR_TYPE, rec.type);
1548 writeStringAttribute(out, ATTR_FS_UUID, rec.fsUuid);
Jeff Sharkey5cc0df22015-06-17 19:44:05 -07001549 writeStringAttribute(out, ATTR_PART_GUID, rec.partGuid);
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001550 writeStringAttribute(out, ATTR_NICKNAME, rec.nickname);
1551 writeIntAttribute(out, ATTR_USER_FLAGS, rec.userFlags);
Jeff Sharkeye8a4b662015-06-27 15:43:45 -07001552 writeLongAttribute(out, ATTR_CREATED_MILLIS, rec.createdMillis);
1553 writeLongAttribute(out, ATTR_LAST_TRIM_MILLIS, rec.lastTrimMillis);
1554 writeLongAttribute(out, ATTR_LAST_BENCH_MILLIS, rec.lastBenchMillis);
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001555 out.endTag(null, TAG_VOLUME);
1556 }
1557
San Mehat207e5382010-02-04 20:46:54 -08001558 /**
San Mehat4270e1e2010-01-29 05:32:19 -08001559 * Exposed API calls below here
1560 */
1561
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001562 @Override
Sudheer Shanka2250d562016-11-07 15:41:02 -08001563 public void registerListener(IStorageEventListener listener) {
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001564 mCallbacks.register(listener);
San Mehat4270e1e2010-01-29 05:32:19 -08001565 }
1566
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001567 @Override
Sudheer Shanka2250d562016-11-07 15:41:02 -08001568 public void unregisterListener(IStorageEventListener listener) {
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001569 mCallbacks.unregister(listener);
San Mehat4270e1e2010-01-29 05:32:19 -08001570 }
1571
Jeff Sharkey48877892015-03-18 11:27:19 -07001572 @Override
Sudheer Shanka2250d562016-11-07 15:41:02 -08001573 public void shutdown(final IStorageShutdownObserver observer) {
Jeff Sharkey48877892015-03-18 11:27:19 -07001574 enforcePermission(android.Manifest.permission.SHUTDOWN);
San Mehat4270e1e2010-01-29 05:32:19 -08001575
San Mehata5078592010-03-25 09:36:54 -07001576 Slog.i(TAG, "Shutting down");
Jeff Sharkey48877892015-03-18 11:27:19 -07001577 mHandler.obtainMessage(H_SHUTDOWN, observer).sendToTarget();
San Mehat4270e1e2010-01-29 05:32:19 -08001578 }
1579
Jeff Sharkey48877892015-03-18 11:27:19 -07001580 @Override
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001581 public void mount(String volId) {
1582 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001583
Jeff Sharkeyef10ee02015-07-05 14:17:27 -07001584 final VolumeInfo vol = findVolumeByIdOrThrow(volId);
Jeff Sharkey2e606d72015-07-27 14:19:54 -07001585 if (isMountDisallowed(vol)) {
1586 throw new SecurityException("Mounting " + volId + " restricted by policy");
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001587 }
1588 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06001589 mVold.mount(vol.id, vol.mountFlags, vol.mountUserId);
Jeff Sharkeyace874b2017-09-07 15:27:33 -06001590 } catch (Exception e) {
1591 Slog.wtf(TAG, e);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001592 }
1593 }
1594
1595 @Override
1596 public void unmount(String volId) {
1597 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001598
Jeff Sharkeyef10ee02015-07-05 14:17:27 -07001599 final VolumeInfo vol = findVolumeByIdOrThrow(volId);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001600 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06001601 mVold.unmount(vol.id);
Jeff Sharkeyace874b2017-09-07 15:27:33 -06001602 } catch (Exception e) {
1603 Slog.wtf(TAG, e);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001604 }
1605 }
1606
1607 @Override
1608 public void format(String volId) {
Jeff Sharkey48877892015-03-18 11:27:19 -07001609 enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);
San Mehat5b77dab2010-01-26 13:28:50 -08001610
Jeff Sharkeyef10ee02015-07-05 14:17:27 -07001611 final VolumeInfo vol = findVolumeByIdOrThrow(volId);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001612 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06001613 mVold.format(vol.id, "auto");
Jeff Sharkeyace874b2017-09-07 15:27:33 -06001614 } catch (Exception e) {
1615 Slog.wtf(TAG, e);
Jeff Sharkey48877892015-03-18 11:27:19 -07001616 }
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001617 }
1618
1619 @Override
Jeff Sharkey7e19f532017-11-06 13:54:11 -07001620 public void benchmark(String volId, IVoldTaskListener listener) {
Jeff Sharkey9756d752015-05-14 21:07:42 -07001621 enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);
Jeff Sharkey9756d752015-05-14 21:07:42 -07001622
1623 try {
Jeff Sharkeyb302c542017-09-15 12:57:59 -06001624 mVold.benchmark(volId, new IVoldTaskListener.Stub() {
1625 @Override
1626 public void onStatus(int status, PersistableBundle extras) {
Jeff Sharkey7e19f532017-11-06 13:54:11 -07001627 dispatchOnStatus(listener, status, extras);
Jeff Sharkeyb302c542017-09-15 12:57:59 -06001628 }
1629
1630 @Override
1631 public void onFinished(int status, PersistableBundle extras) {
Jeff Sharkey7e19f532017-11-06 13:54:11 -07001632 dispatchOnFinished(listener, status, extras);
Jeff Sharkeyb302c542017-09-15 12:57:59 -06001633
1634 final String path = extras.getString("path");
1635 final String ident = extras.getString("ident");
1636 final long create = extras.getLong("create");
1637 final long run = extras.getLong("run");
1638 final long destroy = extras.getLong("destroy");
1639
1640 final DropBoxManager dropBox = mContext.getSystemService(DropBoxManager.class);
1641 dropBox.addText(TAG_STORAGE_BENCHMARK, scrubPath(path)
1642 + " " + ident + " " + create + " " + run + " " + destroy);
1643
1644 synchronized (mLock) {
1645 final VolumeRecord rec = findRecordForPath(path);
1646 if (rec != null) {
1647 rec.lastBenchMillis = System.currentTimeMillis();
1648 writeSettingsLocked();
1649 }
1650 }
1651 }
1652 });
Jeff Sharkey7e19f532017-11-06 13:54:11 -07001653 } catch (RemoteException e) {
1654 throw e.rethrowAsRuntimeException();
Jeff Sharkey9756d752015-05-14 21:07:42 -07001655 }
1656 }
1657
1658 @Override
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001659 public void partitionPublic(String diskId) {
1660 enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001661
Jeff Sharkeyeba260d2015-04-19 14:35:16 -07001662 final CountDownLatch latch = findOrCreateDiskScanLatch(diskId);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001663 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06001664 mVold.partition(diskId, IVold.PARTITION_TYPE_PUBLIC, -1);
Jeff Sharkeyedcdaf62015-07-09 09:45:36 -07001665 waitForLatch(latch, "partitionPublic", 3 * DateUtils.MINUTE_IN_MILLIS);
Jeff Sharkeyace874b2017-09-07 15:27:33 -06001666 } catch (Exception e) {
1667 Slog.wtf(TAG, e);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001668 }
1669 }
1670
1671 @Override
1672 public void partitionPrivate(String diskId) {
1673 enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);
Amith Yamasani462ac3a2015-06-30 14:21:01 -07001674 enforceAdminUser();
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001675
Jeff Sharkeyeba260d2015-04-19 14:35:16 -07001676 final CountDownLatch latch = findOrCreateDiskScanLatch(diskId);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001677 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06001678 mVold.partition(diskId, IVold.PARTITION_TYPE_PRIVATE, -1);
Jeff Sharkeyedcdaf62015-07-09 09:45:36 -07001679 waitForLatch(latch, "partitionPrivate", 3 * DateUtils.MINUTE_IN_MILLIS);
Jeff Sharkeyace874b2017-09-07 15:27:33 -06001680 } catch (Exception e) {
1681 Slog.wtf(TAG, e);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001682 }
1683 }
1684
1685 @Override
1686 public void partitionMixed(String diskId, int ratio) {
1687 enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);
Amith Yamasani462ac3a2015-06-30 14:21:01 -07001688 enforceAdminUser();
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001689
Jeff Sharkeyeba260d2015-04-19 14:35:16 -07001690 final CountDownLatch latch = findOrCreateDiskScanLatch(diskId);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001691 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06001692 mVold.partition(diskId, IVold.PARTITION_TYPE_MIXED, ratio);
Jeff Sharkeyedcdaf62015-07-09 09:45:36 -07001693 waitForLatch(latch, "partitionMixed", 3 * DateUtils.MINUTE_IN_MILLIS);
Jeff Sharkeyace874b2017-09-07 15:27:33 -06001694 } catch (Exception e) {
1695 Slog.wtf(TAG, e);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001696 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001697 }
1698
Jeff Sharkey48877892015-03-18 11:27:19 -07001699 @Override
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001700 public void setVolumeNickname(String fsUuid, String nickname) {
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001701 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001702
Jeff Sharkey50a05452015-04-29 11:24:52 -07001703 Preconditions.checkNotNull(fsUuid);
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001704 synchronized (mLock) {
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001705 final VolumeRecord rec = mRecords.get(fsUuid);
1706 rec.nickname = nickname;
Jeff Sharkey50a05452015-04-29 11:24:52 -07001707 mCallbacks.notifyVolumeRecordChanged(rec);
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001708 writeSettingsLocked();
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001709 }
1710 }
1711
1712 @Override
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001713 public void setVolumeUserFlags(String fsUuid, int flags, int mask) {
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001714 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001715
Jeff Sharkey50a05452015-04-29 11:24:52 -07001716 Preconditions.checkNotNull(fsUuid);
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001717 synchronized (mLock) {
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001718 final VolumeRecord rec = mRecords.get(fsUuid);
1719 rec.userFlags = (rec.userFlags & ~mask) | (flags & mask);
Jeff Sharkey50a05452015-04-29 11:24:52 -07001720 mCallbacks.notifyVolumeRecordChanged(rec);
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001721 writeSettingsLocked();
1722 }
1723 }
1724
1725 @Override
1726 public void forgetVolume(String fsUuid) {
1727 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001728
Jeff Sharkey50a05452015-04-29 11:24:52 -07001729 Preconditions.checkNotNull(fsUuid);
Jeff Sharkey5a9bb742015-11-03 10:15:57 -08001730
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001731 synchronized (mLock) {
Jeff Sharkey5cc0df22015-06-17 19:44:05 -07001732 final VolumeRecord rec = mRecords.remove(fsUuid);
1733 if (rec != null && !TextUtils.isEmpty(rec.partGuid)) {
Jeff Sharkeydb4b6192017-10-24 11:08:50 -06001734 mHandler.obtainMessage(H_PARTITION_FORGET, rec).sendToTarget();
Jeff Sharkey5cc0df22015-06-17 19:44:05 -07001735 }
1736 mCallbacks.notifyVolumeForgotten(fsUuid);
Jeff Sharkey50a05452015-04-29 11:24:52 -07001737
1738 // If this had been primary storage, revert back to internal and
1739 // reset vold so we bind into new volume into place.
1740 if (Objects.equals(mPrimaryStorageUuid, fsUuid)) {
Jeff Sharkeyfced5342015-05-10 14:53:34 -07001741 mPrimaryStorageUuid = getDefaultPrimaryStorageUuid();
Jeff Sharkey5a9bb742015-11-03 10:15:57 -08001742 mHandler.obtainMessage(H_RESET).sendToTarget();
Jeff Sharkey50a05452015-04-29 11:24:52 -07001743 }
1744
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001745 writeSettingsLocked();
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001746 }
1747 }
1748
Jeff Sharkey7d2af542015-05-12 15:27:15 -07001749 @Override
1750 public void forgetAllVolumes() {
1751 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
Jeff Sharkey7d2af542015-05-12 15:27:15 -07001752
Jeff Sharkey50a05452015-04-29 11:24:52 -07001753 synchronized (mLock) {
1754 for (int i = 0; i < mRecords.size(); i++) {
1755 final String fsUuid = mRecords.keyAt(i);
Jeff Sharkey5cc0df22015-06-17 19:44:05 -07001756 final VolumeRecord rec = mRecords.valueAt(i);
1757 if (!TextUtils.isEmpty(rec.partGuid)) {
Jeff Sharkeydb4b6192017-10-24 11:08:50 -06001758 mHandler.obtainMessage(H_PARTITION_FORGET, rec).sendToTarget();
Jeff Sharkey5cc0df22015-06-17 19:44:05 -07001759 }
Jeff Sharkey50a05452015-04-29 11:24:52 -07001760 mCallbacks.notifyVolumeForgotten(fsUuid);
1761 }
Jeff Sharkey50a05452015-04-29 11:24:52 -07001762 mRecords.clear();
Jeff Sharkey50a05452015-04-29 11:24:52 -07001763
Jeff Sharkeyfced5342015-05-10 14:53:34 -07001764 if (!Objects.equals(StorageManager.UUID_PRIVATE_INTERNAL, mPrimaryStorageUuid)) {
1765 mPrimaryStorageUuid = getDefaultPrimaryStorageUuid();
1766 }
1767
1768 writeSettingsLocked();
Jeff Sharkey5a9bb742015-11-03 10:15:57 -08001769 mHandler.obtainMessage(H_RESET).sendToTarget();
Jeff Sharkey50a05452015-04-29 11:24:52 -07001770 }
1771 }
1772
Jeff Sharkeydb4b6192017-10-24 11:08:50 -06001773 private void forgetPartition(String partGuid, String fsUuid) {
Jeff Sharkey5cc0df22015-06-17 19:44:05 -07001774 try {
Jeff Sharkeydb4b6192017-10-24 11:08:50 -06001775 mVold.forgetPartition(partGuid, fsUuid);
Jeff Sharkeyace874b2017-09-07 15:27:33 -06001776 } catch (Exception e) {
1777 Slog.wtf(TAG, e);
Jeff Sharkey5cc0df22015-06-17 19:44:05 -07001778 }
1779 }
1780
Jeff Sharkey31d0b702016-11-21 14:16:53 -07001781 @Override
Jeff Sharkey7e19f532017-11-06 13:54:11 -07001782 public void fstrim(int flags, IVoldTaskListener listener) {
Jeff Sharkey31d0b702016-11-21 14:16:53 -07001783 enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);
Jeff Sharkey31d0b702016-11-21 14:16:53 -07001784
1785 try {
Jeff Sharkeyb302c542017-09-15 12:57:59 -06001786 mVold.fstrim(flags, new IVoldTaskListener.Stub() {
1787 @Override
1788 public void onStatus(int status, PersistableBundle extras) {
Jeff Sharkey7e19f532017-11-06 13:54:11 -07001789 dispatchOnStatus(listener, status, extras);
1790
Jeff Sharkeyb302c542017-09-15 12:57:59 -06001791 // Ignore trim failures
1792 if (status != 0) return;
1793
1794 final String path = extras.getString("path");
1795 final long bytes = extras.getLong("bytes");
1796 final long time = extras.getLong("time");
1797
1798 final DropBoxManager dropBox = mContext.getSystemService(DropBoxManager.class);
1799 dropBox.addText(TAG_STORAGE_TRIM, scrubPath(path) + " " + bytes + " " + time);
1800
1801 synchronized (mLock) {
1802 final VolumeRecord rec = findRecordForPath(path);
1803 if (rec != null) {
1804 rec.lastTrimMillis = System.currentTimeMillis();
1805 writeSettingsLocked();
1806 }
1807 }
1808 }
1809
1810 @Override
1811 public void onFinished(int status, PersistableBundle extras) {
Jeff Sharkey7e19f532017-11-06 13:54:11 -07001812 dispatchOnFinished(listener, status, extras);
1813
Jeff Sharkeyb302c542017-09-15 12:57:59 -06001814 // TODO: benchmark when desired
1815 }
1816 });
Jeff Sharkey7e19f532017-11-06 13:54:11 -07001817 } catch (RemoteException e) {
1818 throw e.rethrowAsRuntimeException();
Jeff Sharkey31d0b702016-11-21 14:16:53 -07001819 }
1820 }
1821
Jin Qiana85b9912017-10-17 15:48:18 -07001822 void runIdleMaint(Runnable callback) {
1823 enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);
1824
1825 try {
1826 mVold.runIdleMaint(new IVoldTaskListener.Stub() {
1827 @Override
1828 public void onStatus(int status, PersistableBundle extras) {
1829 // Not currently used
1830 }
1831 @Override
1832 public void onFinished(int status, PersistableBundle extras) {
1833 if (callback != null) {
1834 BackgroundThread.getHandler().post(callback);
1835 }
1836 }
1837 });
1838 } catch (Exception e) {
1839 Slog.wtf(TAG, e);
1840 }
1841 }
1842
1843 @Override
1844 public void runIdleMaintenance() {
1845 runIdleMaint(null);
1846 }
1847
1848 void abortIdleMaint(Runnable callback) {
1849 enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);
1850
1851 try {
1852 mVold.abortIdleMaint(new IVoldTaskListener.Stub() {
1853 @Override
1854 public void onStatus(int status, PersistableBundle extras) {
1855 // Not currently used
1856 }
1857 @Override
1858 public void onFinished(int status, PersistableBundle extras) {
1859 if (callback != null) {
1860 BackgroundThread.getHandler().post(callback);
1861 }
1862 }
1863 });
1864 } catch (Exception e) {
1865 Slog.wtf(TAG, e);
1866 }
1867 }
1868
1869 @Override
1870 public void abortIdleMaintenance() {
1871 abortIdleMaint(null);
1872 }
1873
Svet Ganov6ee871e2015-07-10 14:29:33 -07001874 private void remountUidExternalStorage(int uid, int mode) {
Jeff Sharkey9527b222015-06-24 15:24:48 -07001875 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06001876 mVold.remountUid(uid, mode);
Jeff Sharkeyace874b2017-09-07 15:27:33 -06001877 } catch (Exception e) {
1878 Slog.wtf(TAG, e);
Jeff Sharkey9527b222015-06-24 15:24:48 -07001879 }
1880 }
1881
1882 @Override
Jeff Sharkey4c099d02015-05-15 13:45:00 -07001883 public void setDebugFlags(int flags, int mask) {
1884 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
Jeff Sharkey4c099d02015-05-15 13:45:00 -07001885
Jeff Sharkeyba512352015-11-12 20:17:45 -08001886 if ((mask & StorageManager.DEBUG_EMULATE_FBE) != 0) {
Jeff Sharkey00455bf2016-11-04 14:45:24 -06001887 if (!EMULATE_FBE_SUPPORTED) {
1888 throw new IllegalStateException(
1889 "Emulation not supported on this device");
1890 }
Paul Lawrence20be5d62016-02-26 13:51:17 -08001891 if (StorageManager.isFileEncryptedNativeOnly()) {
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07001892 throw new IllegalStateException(
Jeff Sharkey00455bf2016-11-04 14:45:24 -06001893 "Emulation not supported on device with native FBE");
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07001894 }
Jeff Sharkey5a785162016-03-21 13:02:06 -06001895 if (mLockPatternUtils.isCredentialRequiredToDecrypt(false)) {
1896 throw new IllegalStateException(
1897 "Emulation requires disabling 'Secure start-up' in Settings > Security");
1898 }
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07001899
Jeff Sharkey1176e512016-02-29 17:01:26 -07001900 final long token = Binder.clearCallingIdentity();
1901 try {
1902 final boolean emulateFbe = (flags & StorageManager.DEBUG_EMULATE_FBE) != 0;
1903 SystemProperties.set(StorageManager.PROP_EMULATE_FBE, Boolean.toString(emulateFbe));
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07001904
Jeff Sharkey1176e512016-02-29 17:01:26 -07001905 // Perform hard reboot to kick policy into place
1906 mContext.getSystemService(PowerManager.class).reboot(null);
1907 } finally {
1908 Binder.restoreCallingIdentity(token);
1909 }
Jeff Sharkeyba512352015-11-12 20:17:45 -08001910 }
Jeff Sharkey4c099d02015-05-15 13:45:00 -07001911
Jeff Sharkeyba512352015-11-12 20:17:45 -08001912 if ((mask & StorageManager.DEBUG_FORCE_ADOPTABLE) != 0) {
Jeff Sharkeya65e6492017-06-21 13:45:11 -06001913 if (StorageManager.isFileEncryptedNativeOnly()
1914 && !SystemProperties.getBoolean(StorageManager.PROP_ADOPTABLE_FBE, false)) {
Jeff Sharkey6ed74182016-08-23 13:53:53 -06001915 throw new IllegalStateException(
1916 "Adoptable storage not available on device with native FBE");
1917 }
1918
Jeff Sharkeyba512352015-11-12 20:17:45 -08001919 synchronized (mLock) {
1920 mForceAdoptable = (flags & StorageManager.DEBUG_FORCE_ADOPTABLE) != 0;
1921
1922 writeSettingsLocked();
1923 mHandler.obtainMessage(H_RESET).sendToTarget();
1924 }
Jeff Sharkey4c099d02015-05-15 13:45:00 -07001925 }
Jeff Sharkey33dd1562016-04-07 11:05:33 -06001926
1927 if ((mask & (StorageManager.DEBUG_SDCARDFS_FORCE_ON
1928 | StorageManager.DEBUG_SDCARDFS_FORCE_OFF)) != 0) {
1929 final String value;
1930 if ((flags & StorageManager.DEBUG_SDCARDFS_FORCE_ON) != 0) {
1931 value = "force_on";
1932 } else if ((flags & StorageManager.DEBUG_SDCARDFS_FORCE_OFF) != 0) {
1933 value = "force_off";
1934 } else {
1935 value = "";
1936 }
1937
1938 final long token = Binder.clearCallingIdentity();
1939 try {
1940 SystemProperties.set(StorageManager.PROP_SDCARDFS, value);
1941
1942 // Reset storage to kick new setting into place
1943 mHandler.obtainMessage(H_RESET).sendToTarget();
1944 } finally {
1945 Binder.restoreCallingIdentity(token);
1946 }
1947 }
Jeff Sharkeye53e2d92017-03-25 23:14:06 -06001948
1949 if ((mask & StorageManager.DEBUG_VIRTUAL_DISK) != 0) {
1950 final boolean enabled = (flags & StorageManager.DEBUG_VIRTUAL_DISK) != 0;
1951
1952 final long token = Binder.clearCallingIdentity();
1953 try {
1954 SystemProperties.set(StorageManager.PROP_VIRTUAL_DISK, Boolean.toString(enabled));
1955
1956 // Reset storage to kick new setting into place
1957 mHandler.obtainMessage(H_RESET).sendToTarget();
1958 } finally {
1959 Binder.restoreCallingIdentity(token);
1960 }
1961 }
Jeff Sharkey4c099d02015-05-15 13:45:00 -07001962 }
1963
1964 @Override
Jeff Sharkey275e3e42015-04-24 16:10:32 -07001965 public String getPrimaryStorageUuid() {
Jeff Sharkey620b32b2015-04-23 19:36:02 -07001966 synchronized (mLock) {
1967 return mPrimaryStorageUuid;
1968 }
1969 }
1970
1971 @Override
Jeff Sharkey275e3e42015-04-24 16:10:32 -07001972 public void setPrimaryStorageUuid(String volumeUuid, IPackageMoveObserver callback) {
1973 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
Jeff Sharkey620b32b2015-04-23 19:36:02 -07001974
Jeff Sharkeya31460c2016-06-22 09:04:33 -06001975 final VolumeInfo from;
1976 final VolumeInfo to;
1977
Jeff Sharkey275e3e42015-04-24 16:10:32 -07001978 synchronized (mLock) {
Jeff Sharkeyfced5342015-05-10 14:53:34 -07001979 if (Objects.equals(mPrimaryStorageUuid, volumeUuid)) {
1980 throw new IllegalArgumentException("Primary storage already at " + volumeUuid);
Jeff Sharkey275e3e42015-04-24 16:10:32 -07001981 }
1982
1983 if (mMoveCallback != null) {
1984 throw new IllegalStateException("Move already in progress");
1985 }
1986 mMoveCallback = callback;
1987 mMoveTargetUuid = volumeUuid;
1988
Jeff Sharkeya65e6492017-06-21 13:45:11 -06001989 // We need all the users unlocked to move their primary storage
1990 final List<UserInfo> users = mContext.getSystemService(UserManager.class).getUsers();
1991 for (UserInfo user : users) {
1992 if (StorageManager.isFileEncryptedNativeOrEmulated()
1993 && !isUserKeyUnlocked(user.id)) {
1994 Slog.w(TAG, "Failing move due to locked user " + user.id);
1995 onMoveStatusLocked(PackageManager.MOVE_FAILED_LOCKED_USER);
1996 return;
1997 }
1998 }
1999
Jeff Sharkeyfced5342015-05-10 14:53:34 -07002000 // When moving to/from primary physical volume, we probably just nuked
2001 // the current storage location, so we have nothing to move.
2002 if (Objects.equals(StorageManager.UUID_PRIMARY_PHYSICAL, mPrimaryStorageUuid)
2003 || Objects.equals(StorageManager.UUID_PRIMARY_PHYSICAL, volumeUuid)) {
2004 Slog.d(TAG, "Skipping move to/from primary physical");
2005 onMoveStatusLocked(MOVE_STATUS_COPY_FINISHED);
2006 onMoveStatusLocked(PackageManager.MOVE_SUCCEEDED);
Jeff Sharkey5a9bb742015-11-03 10:15:57 -08002007 mHandler.obtainMessage(H_RESET).sendToTarget();
Jeff Sharkeya31460c2016-06-22 09:04:33 -06002008 return;
Jeff Sharkeyfced5342015-05-10 14:53:34 -07002009
2010 } else {
Jeff Sharkeya31460c2016-06-22 09:04:33 -06002011 from = findStorageForUuid(mPrimaryStorageUuid);
2012 to = findStorageForUuid(volumeUuid);
Jeff Sharkeyef10ee02015-07-05 14:17:27 -07002013
2014 if (from == null) {
2015 Slog.w(TAG, "Failing move due to missing from volume " + mPrimaryStorageUuid);
2016 onMoveStatusLocked(PackageManager.MOVE_FAILED_INTERNAL_ERROR);
2017 return;
2018 } else if (to == null) {
2019 Slog.w(TAG, "Failing move due to missing to volume " + volumeUuid);
2020 onMoveStatusLocked(PackageManager.MOVE_FAILED_INTERNAL_ERROR);
2021 return;
2022 }
Jeff Sharkey275e3e42015-04-24 16:10:32 -07002023 }
Jeff Sharkey620b32b2015-04-23 19:36:02 -07002024 }
Jeff Sharkeya31460c2016-06-22 09:04:33 -06002025
2026 try {
Jeff Sharkeyb302c542017-09-15 12:57:59 -06002027 mVold.moveStorage(from.id, to.id, new IVoldTaskListener.Stub() {
2028 @Override
2029 public void onStatus(int status, PersistableBundle extras) {
2030 synchronized (mLock) {
2031 onMoveStatusLocked(status);
2032 }
2033 }
2034
2035 @Override
2036 public void onFinished(int status, PersistableBundle extras) {
2037 // Not currently used
2038 }
2039 });
Jeff Sharkeyace874b2017-09-07 15:27:33 -06002040 } catch (Exception e) {
2041 Slog.wtf(TAG, e);
Jeff Sharkeya31460c2016-06-22 09:04:33 -06002042 }
Jeff Sharkey620b32b2015-04-23 19:36:02 -07002043 }
2044
San Mehatb1043402010-02-05 08:26:50 -08002045 private void warnOnNotMounted() {
Jeff Sharkey48877892015-03-18 11:27:19 -07002046 synchronized (mLock) {
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07002047 for (int i = 0; i < mVolumes.size(); i++) {
2048 final VolumeInfo vol = mVolumes.valueAt(i);
Jeff Sharkey27de30d2015-04-18 16:20:27 -07002049 if (vol.isPrimary() && vol.isMountedWritable()) {
Jeff Sharkey48877892015-03-18 11:27:19 -07002050 // Cool beans, we have a mounted primary volume
2051 return;
2052 }
Jeff Sharkey32ee8312012-09-30 13:21:31 -07002053 }
San Mehatb1043402010-02-05 08:26:50 -08002054 }
Jeff Sharkey48877892015-03-18 11:27:19 -07002055
2056 Slog.w(TAG, "No primary storage mounted!");
San Mehatb1043402010-02-05 08:26:50 -08002057 }
2058
Kenny Roota02b8b02010-08-05 16:14:17 -07002059 private boolean isUidOwnerOfPackageOrSystem(String packageName, int callerUid) {
2060 if (callerUid == android.os.Process.SYSTEM_UID) {
2061 return true;
2062 }
2063
Kenny Root02c87302010-07-01 08:10:18 -07002064 if (packageName == null) {
2065 return false;
2066 }
2067
Jeff Sharkeycd654482016-01-08 17:42:11 -07002068 final int packageUid = mPms.getPackageUid(packageName,
2069 PackageManager.MATCH_DEBUG_TRIAGED_MISSING, UserHandle.getUserId(callerUid));
Kenny Root02c87302010-07-01 08:10:18 -07002070
2071 if (DEBUG_OBB) {
2072 Slog.d(TAG, "packageName = " + packageName + ", packageUid = " +
2073 packageUid + ", callerUid = " + callerUid);
2074 }
2075
2076 return callerUid == packageUid;
2077 }
2078
Jeff Sharkey54402792017-09-15 16:05:19 -06002079 @Override
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002080 public String getMountedObbPath(String rawPath) {
2081 Preconditions.checkNotNull(rawPath, "rawPath cannot be null");
Kenny Rootaf9d6672010-10-08 09:21:39 -07002082
Kenny Root02c87302010-07-01 08:10:18 -07002083 warnOnNotMounted();
2084
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002085 final ObbState state;
Rubin Xucd7a0142015-04-17 23:45:27 +01002086 synchronized (mObbMounts) {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002087 state = mObbPathToStateMap.get(rawPath);
2088 }
2089 if (state == null) {
2090 Slog.w(TAG, "Failed to find OBB mounted at " + rawPath);
2091 return null;
2092 }
2093
Jeff Sharkey54402792017-09-15 16:05:19 -06002094 return findVolumeByIdOrThrow(state.volId).getPath().getAbsolutePath();
Kenny Root02c87302010-07-01 08:10:18 -07002095 }
2096
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002097 @Override
2098 public boolean isObbMounted(String rawPath) {
2099 Preconditions.checkNotNull(rawPath, "rawPath cannot be null");
Kenny Rootaf9d6672010-10-08 09:21:39 -07002100 synchronized (mObbMounts) {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002101 return mObbPathToStateMap.containsKey(rawPath);
Kenny Rootaf9d6672010-10-08 09:21:39 -07002102 }
Kenny Root02c87302010-07-01 08:10:18 -07002103 }
2104
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002105 @Override
2106 public void mountObb(
2107 String rawPath, String canonicalPath, String key, IObbActionListener token, int nonce) {
2108 Preconditions.checkNotNull(rawPath, "rawPath cannot be null");
2109 Preconditions.checkNotNull(canonicalPath, "canonicalPath cannot be null");
2110 Preconditions.checkNotNull(token, "token cannot be null");
Kenny Rootaf9d6672010-10-08 09:21:39 -07002111
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002112 final int callingUid = Binder.getCallingUid();
Jeff Sharkey41cd6812017-09-11 10:32:17 -06002113 final ObbState obbState = new ObbState(rawPath, canonicalPath,
2114 callingUid, token, nonce, null);
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002115 final ObbAction action = new MountObbAction(obbState, key, callingUid);
Kenny Roota02b8b02010-08-05 16:14:17 -07002116 mObbActionHandler.sendMessage(mObbActionHandler.obtainMessage(OBB_RUN_ACTION, action));
2117
2118 if (DEBUG_OBB)
2119 Slog.i(TAG, "Send to OBB handler: " + action.toString());
Kenny Root02c87302010-07-01 08:10:18 -07002120 }
2121
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002122 @Override
2123 public void unmountObb(String rawPath, boolean force, IObbActionListener token, int nonce) {
2124 Preconditions.checkNotNull(rawPath, "rawPath cannot be null");
2125
2126 final ObbState existingState;
Rubin Xucd7a0142015-04-17 23:45:27 +01002127 synchronized (mObbMounts) {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002128 existingState = mObbPathToStateMap.get(rawPath);
Kenny Rootf1121dc2010-09-29 07:30:53 -07002129 }
2130
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002131 if (existingState != null) {
2132 // TODO: separate state object from request data
2133 final int callingUid = Binder.getCallingUid();
Jeff Sharkey41cd6812017-09-11 10:32:17 -06002134 final ObbState newState = new ObbState(rawPath, existingState.canonicalPath,
2135 callingUid, token, nonce, existingState.volId);
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002136 final ObbAction action = new UnmountObbAction(newState, force);
2137 mObbActionHandler.sendMessage(mObbActionHandler.obtainMessage(OBB_RUN_ACTION, action));
Kenny Root02c87302010-07-01 08:10:18 -07002138
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002139 if (DEBUG_OBB)
2140 Slog.i(TAG, "Send to OBB handler: " + action.toString());
2141 } else {
2142 Slog.w(TAG, "Unknown OBB mount at " + rawPath);
2143 }
Kenny Roota02b8b02010-08-05 16:14:17 -07002144 }
2145
Ben Komalo444eca22011-09-01 15:17:44 -07002146 @Override
2147 public int getEncryptionState() {
2148 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
2149 "no permission to access the crypt keeper");
2150
Ben Komalo444eca22011-09-01 15:17:44 -07002151 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002152 return mVold.fdeComplete();
2153 } catch (Exception e) {
2154 Slog.wtf(TAG, e);
Sudheer Shankaf7341142016-10-18 17:15:18 -07002155 return StorageManager.ENCRYPTION_STATE_ERROR_UNKNOWN;
Ben Komalo444eca22011-09-01 15:17:44 -07002156 }
2157 }
2158
2159 @Override
Jason parks5af0b912010-11-29 09:05:25 -06002160 public int decryptStorage(String password) {
Jason parks8888c592011-01-20 22:46:41 -06002161 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
2162 "no permission to access the crypt keeper");
Jason parks5af0b912010-11-29 09:05:25 -06002163
Jeff Sharkey8058fe62017-09-13 11:50:33 -06002164 if (TextUtils.isEmpty(password)) {
2165 throw new IllegalArgumentException("password cannot be empty");
2166 }
2167
Jason parks5af0b912010-11-29 09:05:25 -06002168 if (DEBUG_EVENTS) {
2169 Slog.i(TAG, "decrypting storage...");
2170 }
2171
2172 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002173 mVold.fdeCheckPassword(password);
2174 mHandler.postDelayed(() -> {
2175 try {
2176 mVold.fdeRestart();
2177 } catch (Exception e) {
2178 Slog.wtf(TAG, e);
2179 }
2180 }, DateUtils.SECOND_IN_MILLIS);
2181 return 0;
2182 } catch (Exception e) {
2183 Slog.wtf(TAG, e);
2184 return StorageManager.ENCRYPTION_STATE_ERROR_UNKNOWN;
Jason parks5af0b912010-11-29 09:05:25 -06002185 }
Jason parks5af0b912010-11-29 09:05:25 -06002186 }
2187
Jeff Sharkey54402792017-09-15 16:05:19 -06002188 @Override
Paul Lawrence46791e72014-04-03 09:10:26 -07002189 public int encryptStorage(int type, String password) {
Jason parks8888c592011-01-20 22:46:41 -06002190 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
2191 "no permission to access the crypt keeper");
Jason parks56aa5322011-01-07 09:01:15 -06002192
Jeff Sharkey8058fe62017-09-13 11:50:33 -06002193 if (type == StorageManager.CRYPT_TYPE_DEFAULT) {
2194 password = "";
2195 } else if (TextUtils.isEmpty(password)) {
2196 throw new IllegalArgumentException("password cannot be empty");
2197 }
2198
Jason parks56aa5322011-01-07 09:01:15 -06002199 if (DEBUG_EVENTS) {
Jason parks8888c592011-01-20 22:46:41 -06002200 Slog.i(TAG, "encrypting storage...");
Jason parks56aa5322011-01-07 09:01:15 -06002201 }
2202
2203 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002204 mVold.fdeEnable(type, password, IVold.ENCRYPTION_FLAG_IN_PLACE);
Jeff Sharkey43e12112017-09-12 16:31:45 -06002205 } catch (Exception e) {
2206 Slog.wtf(TAG, e);
2207 return -1;
Jason parks56aa5322011-01-07 09:01:15 -06002208 }
2209
2210 return 0;
2211 }
2212
Paul Lawrence8e397362014-01-27 15:22:30 -08002213 /** Set the password for encrypting the master key.
2214 * @param type One of the CRYPTO_TYPE_XXX consts defined in StorageManager.
2215 * @param password The password to set.
2216 */
Jeff Sharkey54402792017-09-15 16:05:19 -06002217 @Override
Paul Lawrence8e397362014-01-27 15:22:30 -08002218 public int changeEncryptionPassword(int type, String password) {
Jason parksf7b3cd42011-01-27 09:28:25 -06002219 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
2220 "no permission to access the crypt keeper");
2221
Jeff Sharkeyae266462017-11-27 13:32:24 -07002222 if (StorageManager.isFileEncryptedNativeOnly()) {
2223 // Not supported on FBE devices
2224 return -1;
2225 }
2226
Jeff Sharkey8058fe62017-09-13 11:50:33 -06002227 if (type == StorageManager.CRYPT_TYPE_DEFAULT) {
2228 password = "";
2229 } else if (TextUtils.isEmpty(password)) {
2230 throw new IllegalArgumentException("password cannot be empty");
2231 }
2232
Jason parksf7b3cd42011-01-27 09:28:25 -06002233 if (DEBUG_EVENTS) {
2234 Slog.i(TAG, "changing encryption password...");
2235 }
2236
2237 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002238 mVold.fdeChangePassword(type, password);
2239 return 0;
2240 } catch (Exception e) {
2241 Slog.wtf(TAG, e);
2242 return -1;
Jason parksf7b3cd42011-01-27 09:28:25 -06002243 }
2244 }
2245
Christopher Tate32418be2011-10-10 13:51:12 -07002246 /**
2247 * Validate a user-supplied password string with cryptfs
2248 */
2249 @Override
2250 public int verifyEncryptionPassword(String password) throws RemoteException {
2251 // Only the system process is permitted to validate passwords
2252 if (Binder.getCallingUid() != android.os.Process.SYSTEM_UID) {
2253 throw new SecurityException("no permission to access the crypt keeper");
2254 }
2255
2256 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
2257 "no permission to access the crypt keeper");
2258
2259 if (TextUtils.isEmpty(password)) {
2260 throw new IllegalArgumentException("password cannot be empty");
2261 }
2262
Christopher Tate32418be2011-10-10 13:51:12 -07002263 if (DEBUG_EVENTS) {
2264 Slog.i(TAG, "validating encryption password...");
2265 }
2266
2267 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002268 mVold.fdeVerifyPassword(password);
2269 return 0;
2270 } catch (Exception e) {
2271 Slog.wtf(TAG, e);
2272 return -1;
Christopher Tate32418be2011-10-10 13:51:12 -07002273 }
2274 }
2275
Paul Lawrence8e397362014-01-27 15:22:30 -08002276 /**
2277 * Get the type of encryption used to encrypt the master key.
2278 * @return The type, one of the CRYPT_TYPE_XXX consts from StorageManager.
2279 */
2280 @Override
Svetoslav16e4a1a2014-09-29 18:16:20 -07002281 public int getPasswordType() {
Paul Lawrence76a40572017-03-15 11:08:04 -07002282 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
Paul Lawrence9de713d2016-05-02 22:45:33 +00002283 "no permission to access the crypt keeper");
2284
Paul Lawrence8e397362014-01-27 15:22:30 -08002285 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002286 return mVold.fdeGetPasswordType();
2287 } catch (Exception e) {
2288 Slog.wtf(TAG, e);
2289 return -1;
Paul Lawrence8e397362014-01-27 15:22:30 -08002290 }
2291 }
2292
Paul Lawrencee51dcf92014-03-18 10:56:00 -07002293 /**
2294 * Set a field in the crypto header.
2295 * @param field field to set
2296 * @param contents contents to set in field
2297 */
2298 @Override
2299 public void setField(String field, String contents) throws RemoteException {
Paul Lawrence76a40572017-03-15 11:08:04 -07002300 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
Paul Lawrence0bbd1082016-04-26 15:21:02 -07002301 "no permission to access the crypt keeper");
Paul Lawrencee51dcf92014-03-18 10:56:00 -07002302
Jeff Sharkeyae266462017-11-27 13:32:24 -07002303 if (StorageManager.isFileEncryptedNativeOnly()) {
2304 // Not supported on FBE devices
2305 return;
2306 }
2307
Paul Lawrencee51dcf92014-03-18 10:56:00 -07002308 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002309 mVold.fdeSetField(field, contents);
2310 return;
2311 } catch (Exception e) {
2312 Slog.wtf(TAG, e);
2313 return;
Paul Lawrencee51dcf92014-03-18 10:56:00 -07002314 }
2315 }
2316
2317 /**
2318 * Gets a field from the crypto header.
2319 * @param field field to get
2320 * @return contents of field
2321 */
2322 @Override
2323 public String getField(String field) throws RemoteException {
Paul Lawrence76a40572017-03-15 11:08:04 -07002324 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
Paul Lawrence0bbd1082016-04-26 15:21:02 -07002325 "no permission to access the crypt keeper");
Paul Lawrencee51dcf92014-03-18 10:56:00 -07002326
Jeff Sharkeyae266462017-11-27 13:32:24 -07002327 if (StorageManager.isFileEncryptedNativeOnly()) {
2328 // Not supported on FBE devices
2329 return null;
2330 }
2331
Paul Lawrencee51dcf92014-03-18 10:56:00 -07002332 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002333 return mVold.fdeGetField(field);
2334 } catch (Exception e) {
2335 Slog.wtf(TAG, e);
2336 return null;
Paul Lawrencee51dcf92014-03-18 10:56:00 -07002337 }
2338 }
2339
Paul Lawrence3806d9c2015-10-29 10:30:46 -07002340 /**
2341 * Is userdata convertible to file based encryption?
2342 * @return non zero for convertible
2343 */
2344 @Override
2345 public boolean isConvertibleToFBE() throws RemoteException {
Paul Lawrence76a40572017-03-15 11:08:04 -07002346 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
Paul Lawrence0bbd1082016-04-26 15:21:02 -07002347 "no permission to access the crypt keeper");
Paul Lawrence3806d9c2015-10-29 10:30:46 -07002348
Paul Lawrence3806d9c2015-10-29 10:30:46 -07002349 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002350 return mVold.isConvertibleToFbe();
2351 } catch (Exception e) {
2352 Slog.wtf(TAG, e);
2353 return false;
Paul Lawrence3806d9c2015-10-29 10:30:46 -07002354 }
2355 }
2356
Jeff Sharkeyb049e212012-09-07 23:16:01 -07002357 @Override
Paul Lawrence945490c2014-03-27 16:37:28 +00002358 public String getPassword() throws RemoteException {
Paul Lawrence76a40572017-03-15 11:08:04 -07002359 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
Rubin Xucd7a0142015-04-17 23:45:27 +01002360 "only keyguard can retrieve password");
Paul Lawrence0bbd1082016-04-26 15:21:02 -07002361
Paul Lawrence945490c2014-03-27 16:37:28 +00002362 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002363 return mVold.fdeGetPassword();
2364 } catch (Exception e) {
2365 Slog.wtf(TAG, e);
Paul Lawrence24063b52015-01-06 13:11:23 -08002366 return null;
Paul Lawrence945490c2014-03-27 16:37:28 +00002367 }
2368 }
2369
2370 @Override
2371 public void clearPassword() throws RemoteException {
Paul Lawrence76a40572017-03-15 11:08:04 -07002372 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
Paul Lawrence0bbd1082016-04-26 15:21:02 -07002373 "only keyguard can clear password");
2374
Paul Lawrence945490c2014-03-27 16:37:28 +00002375 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002376 mVold.fdeClearPassword();
2377 return;
2378 } catch (Exception e) {
2379 Slog.wtf(TAG, e);
2380 return;
Paul Lawrence945490c2014-03-27 16:37:28 +00002381 }
2382 }
2383
2384 @Override
Lenka Trochtovac4dd0212015-11-18 12:22:06 +01002385 public void createUserKey(int userId, int serialNumber, boolean ephemeral) {
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002386 enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
Paul Crowleybcf48ed2015-04-22 13:36:59 +01002387
Paul Crowleybcf48ed2015-04-22 13:36:59 +01002388 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002389 mVold.createUserKey(userId, serialNumber, ephemeral);
Jeff Sharkey43e12112017-09-12 16:31:45 -06002390 } catch (Exception e) {
2391 Slog.wtf(TAG, e);
Paul Crowleybcf48ed2015-04-22 13:36:59 +01002392 }
2393 }
2394
Paul Crowley7ec733f2015-05-19 12:42:00 +01002395 @Override
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002396 public void destroyUserKey(int userId) {
2397 enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
Paul Crowley7ec733f2015-05-19 12:42:00 +01002398
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002399 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002400 mVold.destroyUserKey(userId);
Jeff Sharkey43e12112017-09-12 16:31:45 -06002401 } catch (Exception e) {
2402 Slog.wtf(TAG, e);
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002403 }
2404 }
2405
Jeff Sharkey43e12112017-09-12 16:31:45 -06002406 private String encodeBytes(byte[] bytes) {
Paul Crowleyfaeb3eb2016-02-08 15:58:29 +00002407 if (ArrayUtils.isEmpty(bytes)) {
Jeff Sharkey43e12112017-09-12 16:31:45 -06002408 return "!";
Paul Crowleyfaeb3eb2016-02-08 15:58:29 +00002409 } else {
Jeff Sharkey43e12112017-09-12 16:31:45 -06002410 return HexDump.toHexString(bytes);
Paul Crowleyfaeb3eb2016-02-08 15:58:29 +00002411 }
2412 }
2413
Paul Crowleycc701552016-05-17 14:18:49 -07002414 /*
2415 * Add this token/secret pair to the set of ways we can recover a disk encryption key.
2416 * Changing the token/secret for a disk encryption key is done in two phases: first, adding
2417 * a new token/secret pair with this call, then delting all other pairs with
2418 * fixateNewestUserKeyAuth. This allows other places where a credential is used, such as
2419 * Gatekeeper, to be updated between the two calls.
2420 */
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002421 @Override
Paul Crowleycc701552016-05-17 14:18:49 -07002422 public void addUserKeyAuth(int userId, int serialNumber, byte[] token, byte[] secret) {
Paul Crowleyfaeb3eb2016-02-08 15:58:29 +00002423 enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
Paul Crowleyfaeb3eb2016-02-08 15:58:29 +00002424
2425 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002426 mVold.addUserKeyAuth(userId, serialNumber, encodeBytes(token), encodeBytes(secret));
Jeff Sharkey43e12112017-09-12 16:31:45 -06002427 } catch (Exception e) {
2428 Slog.wtf(TAG, e);
Paul Crowleycc701552016-05-17 14:18:49 -07002429 }
2430 }
2431
2432 /*
2433 * Delete all disk encryption token/secret pairs except the most recently added one
2434 */
2435 @Override
2436 public void fixateNewestUserKeyAuth(int userId) {
2437 enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
Paul Crowleycc701552016-05-17 14:18:49 -07002438
2439 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002440 mVold.fixateNewestUserKeyAuth(userId);
Jeff Sharkey43e12112017-09-12 16:31:45 -06002441 } catch (Exception e) {
2442 Slog.wtf(TAG, e);
Paul Crowleyfaeb3eb2016-02-08 15:58:29 +00002443 }
2444 }
2445
2446 @Override
2447 public void unlockUserKey(int userId, int serialNumber, byte[] token, byte[] secret) {
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002448 enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002449
Jeff Sharkeyce18c812016-04-27 16:00:41 -06002450 if (StorageManager.isFileEncryptedNativeOrEmulated()) {
Rubin Xu3bf722a2016-12-15 16:07:38 +00002451 // When a user has secure lock screen, require secret to actually unlock.
2452 // This check is mostly in place for emulation mode.
2453 if (mLockPatternUtils.isSecure(userId) && ArrayUtils.isEmpty(secret)) {
2454 throw new IllegalStateException("Secret required to unlock secure user " + userId);
Jeff Sharkeyce18c812016-04-27 16:00:41 -06002455 }
Jeff Sharkeyb9fe5372015-12-03 15:23:08 -07002456
Jeff Sharkeyce18c812016-04-27 16:00:41 -06002457 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002458 mVold.unlockUserKey(userId, serialNumber, encodeBytes(token),
2459 encodeBytes(secret));
Jeff Sharkey43e12112017-09-12 16:31:45 -06002460 } catch (Exception e) {
2461 Slog.wtf(TAG, e);
2462 return;
Jeff Sharkeyce18c812016-04-27 16:00:41 -06002463 }
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002464 }
2465
2466 synchronized (mLock) {
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07002467 mLocalUnlockedUsers = ArrayUtils.appendInt(mLocalUnlockedUsers, userId);
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002468 }
Paul Crowley9139a782017-07-26 13:29:25 -07002469 if (userId == UserHandle.USER_SYSTEM) {
2470 String propertyName = "sys.user." + userId + ".ce_available";
2471 Slog.d(TAG, "Setting property: " + propertyName + "=true");
2472 SystemProperties.set(propertyName, "true");
2473 }
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002474 }
2475
2476 @Override
2477 public void lockUserKey(int userId) {
2478 enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002479
2480 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002481 mVold.lockUserKey(userId);
Jeff Sharkey43e12112017-09-12 16:31:45 -06002482 } catch (Exception e) {
2483 Slog.wtf(TAG, e);
2484 return;
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002485 }
2486
2487 synchronized (mLock) {
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07002488 mLocalUnlockedUsers = ArrayUtils.removeInt(mLocalUnlockedUsers, userId);
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002489 }
2490 }
2491
2492 @Override
2493 public boolean isUserKeyUnlocked(int userId) {
Jeff Sharkeyce18c812016-04-27 16:00:41 -06002494 synchronized (mLock) {
2495 return ArrayUtils.contains(mLocalUnlockedUsers, userId);
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002496 }
2497 }
2498
2499 @Override
Jeff Sharkey47f71082016-02-01 17:03:54 -07002500 public void prepareUserStorage(String volumeUuid, int userId, int serialNumber, int flags) {
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002501 enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002502
2503 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002504 mVold.prepareUserStorage(volumeUuid, userId, serialNumber, flags);
Jeff Sharkey43e12112017-09-12 16:31:45 -06002505 } catch (Exception e) {
2506 Slog.wtf(TAG, e);
Paul Crowley7ec733f2015-05-19 12:42:00 +01002507 }
2508 }
2509
Paul Crowleybcf48ed2015-04-22 13:36:59 +01002510 @Override
Jeff Sharkeyfcf1e552016-04-14 20:44:58 -06002511 public void destroyUserStorage(String volumeUuid, int userId, int flags) {
2512 enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
Jeff Sharkeyfcf1e552016-04-14 20:44:58 -06002513
2514 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002515 mVold.destroyUserStorage(volumeUuid, userId, flags);
Jeff Sharkey43e12112017-09-12 16:31:45 -06002516 } catch (Exception e) {
2517 Slog.wtf(TAG, e);
Jeff Sharkeyfcf1e552016-04-14 20:44:58 -06002518 }
2519 }
2520
Rubin Xuee67b612017-04-27 17:01:05 +01002521 @Override
2522 public void secdiscard(String path) {
2523 enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
Rubin Xuee67b612017-04-27 17:01:05 +01002524
2525 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002526 mVold.secdiscard(path);
Jeff Sharkey43e12112017-09-12 16:31:45 -06002527 } catch (Exception e) {
2528 Slog.wtf(TAG, e);
Rubin Xuee67b612017-04-27 17:01:05 +01002529 }
2530 }
2531
Daichi Hironoe56740d2017-02-02 13:56:45 +09002532 class AppFuseMountScope extends AppFuseBridge.MountScope {
Daichi Hirono812c95d2017-02-08 16:20:20 +09002533 boolean opened = false;
2534
2535 public AppFuseMountScope(int uid, int pid, int mountId) {
2536 super(uid, pid, mountId);
2537 }
2538
2539 @Override
2540 public ParcelFileDescriptor open() throws NativeDaemonConnectorException {
Jeff Sharkey54402792017-09-15 16:05:19 -06002541 try {
2542 return new ParcelFileDescriptor(
2543 mVold.mountAppFuse(uid, Process.myPid(), mountId));
2544 } catch (Exception e) {
2545 throw new NativeDaemonConnectorException("Failed to mount", e);
Daichi Hirono812c95d2017-02-08 16:20:20 +09002546 }
Daichi Hirono9fb00182016-11-08 14:12:17 +09002547 }
2548
2549 @Override
Daichi Hironoe56740d2017-02-02 13:56:45 +09002550 public void close() throws Exception {
Daichi Hirono812c95d2017-02-08 16:20:20 +09002551 if (opened) {
Jeff Sharkey54402792017-09-15 16:05:19 -06002552 mVold.unmountAppFuse(uid, Process.myPid(), mountId);
Daichi Hirono812c95d2017-02-08 16:20:20 +09002553 opened = false;
2554 }
Daichi Hirono9fb00182016-11-08 14:12:17 +09002555 }
2556 }
2557
2558 @Override
Daichi Hirono812c95d2017-02-08 16:20:20 +09002559 public @Nullable AppFuseMount mountProxyFileDescriptorBridge() {
Daichi Hironoe56740d2017-02-02 13:56:45 +09002560 Slog.v(TAG, "mountProxyFileDescriptorBridge");
Daichi Hirono9fb00182016-11-08 14:12:17 +09002561 final int uid = Binder.getCallingUid();
2562 final int pid = Binder.getCallingPid();
Daichi Hirono9fb00182016-11-08 14:12:17 +09002563
Daichi Hironoe56740d2017-02-02 13:56:45 +09002564 while (true) {
2565 synchronized (mAppFuseLock) {
2566 boolean newlyCreated = false;
2567 if (mAppFuseBridge == null) {
2568 mAppFuseBridge = new AppFuseBridge();
2569 new Thread(mAppFuseBridge, AppFuseBridge.TAG).start();
2570 newlyCreated = true;
Daichi Hirono9fb00182016-11-08 14:12:17 +09002571 }
Daichi Hironoe56740d2017-02-02 13:56:45 +09002572 try {
2573 final int name = mNextAppFuseName++;
2574 try {
2575 return new AppFuseMount(
Daichi Hirono812c95d2017-02-08 16:20:20 +09002576 name, mAppFuseBridge.addBridge(new AppFuseMountScope(uid, pid, name)));
2577 } catch (FuseUnavailableMountException e) {
Daichi Hironoe56740d2017-02-02 13:56:45 +09002578 if (newlyCreated) {
2579 // If newly created bridge fails, it's a real error.
Daichi Hirono812c95d2017-02-08 16:20:20 +09002580 Slog.e(TAG, "", e);
2581 return null;
Daichi Hironoe56740d2017-02-02 13:56:45 +09002582 }
2583 // It seems the thread of mAppFuseBridge has already been terminated.
2584 mAppFuseBridge = null;
2585 }
2586 } catch (NativeDaemonConnectorException e) {
2587 throw e.rethrowAsParcelableException();
2588 }
Daichi Hirono9fb00182016-11-08 14:12:17 +09002589 }
Daichi Hirono9fb00182016-11-08 14:12:17 +09002590 }
2591 }
2592
2593 @Override
Daichi Hirono812c95d2017-02-08 16:20:20 +09002594 public @Nullable ParcelFileDescriptor openProxyFileDescriptor(
2595 int mountId, int fileId, int mode) {
2596 Slog.v(TAG, "mountProxyFileDescriptor");
Daichi Hirono9fb00182016-11-08 14:12:17 +09002597 final int pid = Binder.getCallingPid();
2598 try {
2599 synchronized (mAppFuseLock) {
Daichi Hironoe56740d2017-02-02 13:56:45 +09002600 if (mAppFuseBridge == null) {
Daichi Hirono812c95d2017-02-08 16:20:20 +09002601 Slog.e(TAG, "FuseBridge has not been created");
2602 return null;
Daichi Hirono9fb00182016-11-08 14:12:17 +09002603 }
Daichi Hironoe56740d2017-02-02 13:56:45 +09002604 return mAppFuseBridge.openFile(pid, mountId, fileId, mode);
Daichi Hirono9fb00182016-11-08 14:12:17 +09002605 }
Daichi Hirono812c95d2017-02-08 16:20:20 +09002606 } catch (FuseUnavailableMountException | InterruptedException error) {
2607 Slog.v(TAG, "The mount point has already been invalid", error);
2608 return null;
Daichi Hirono9fb00182016-11-08 14:12:17 +09002609 }
2610 }
2611
Daichi Hirono9e8d9e22015-11-13 14:37:00 +09002612 @Override
Jeff Sharkeyae266462017-11-27 13:32:24 -07002613 public void mkdirs(String callingPkg, String appPath) {
Jeff Sharkey2d8b4e82013-09-17 17:30:33 -07002614 final int userId = UserHandle.getUserId(Binder.getCallingUid());
2615 final UserEnvironment userEnv = new UserEnvironment(userId);
2616
2617 // Validate that reported package name belongs to caller
2618 final AppOpsManager appOps = (AppOpsManager) mContext.getSystemService(
2619 Context.APP_OPS_SERVICE);
2620 appOps.checkPackage(Binder.getCallingUid(), callingPkg);
2621
Jeff Sharkey48877892015-03-18 11:27:19 -07002622 File appFile = null;
Jeff Sharkey2d8b4e82013-09-17 17:30:33 -07002623 try {
Jeff Sharkey48877892015-03-18 11:27:19 -07002624 appFile = new File(appPath).getCanonicalFile();
Jeff Sharkey2d8b4e82013-09-17 17:30:33 -07002625 } catch (IOException e) {
Jeff Sharkeyae266462017-11-27 13:32:24 -07002626 throw new IllegalStateException("Failed to resolve " + appPath + ": " + e);
Jeff Sharkey2d8b4e82013-09-17 17:30:33 -07002627 }
2628
2629 // Try translating the app path into a vold path, but require that it
2630 // belong to the calling package.
Jeff Sharkey48877892015-03-18 11:27:19 -07002631 if (FileUtils.contains(userEnv.buildExternalStorageAppDataDirs(callingPkg), appFile) ||
2632 FileUtils.contains(userEnv.buildExternalStorageAppObbDirs(callingPkg), appFile) ||
2633 FileUtils.contains(userEnv.buildExternalStorageAppMediaDirs(callingPkg), appFile)) {
2634 appPath = appFile.getAbsolutePath();
2635 if (!appPath.endsWith("/")) {
2636 appPath = appPath + "/";
2637 }
2638
Jeff Sharkey2d8b4e82013-09-17 17:30:33 -07002639 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002640 mVold.mkdirs(appPath);
Jeff Sharkey27a108c2017-11-30 17:11:40 -07002641 return;
Jeff Sharkeyace874b2017-09-07 15:27:33 -06002642 } catch (Exception e) {
Jeff Sharkeyae266462017-11-27 13:32:24 -07002643 throw new IllegalStateException("Failed to prepare " + appPath + ": " + e);
Jeff Sharkey2d8b4e82013-09-17 17:30:33 -07002644 }
2645 }
2646
Jeff Sharkey48877892015-03-18 11:27:19 -07002647 throw new SecurityException("Invalid mkdirs path: " + appFile);
Jeff Sharkey2d8b4e82013-09-17 17:30:33 -07002648 }
2649
2650 @Override
Jeff Sharkey46349872015-07-28 10:49:47 -07002651 public StorageVolume[] getVolumeList(int uid, String packageName, int flags) {
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07002652 final int userId = UserHandle.getUserId(uid);
Jeff Sharkeyc02bfae2016-03-27 15:06:53 -06002653
Jeff Sharkey46349872015-07-28 10:49:47 -07002654 final boolean forWrite = (flags & StorageManager.FLAG_FOR_WRITE) != 0;
Jeff Sharkeyc02bfae2016-03-27 15:06:53 -06002655 final boolean realState = (flags & StorageManager.FLAG_REAL_STATE) != 0;
2656 final boolean includeInvisible = (flags & StorageManager.FLAG_INCLUDE_INVISIBLE) != 0;
Jeff Sharkey46349872015-07-28 10:49:47 -07002657
Jeff Sharkeyc02bfae2016-03-27 15:06:53 -06002658 final boolean userKeyUnlocked;
2659 final boolean storagePermission;
2660 final long token = Binder.clearCallingIdentity();
Svetoslav38c3dbb2015-07-14 11:27:06 -07002661 try {
Jeff Sharkeyc02bfae2016-03-27 15:06:53 -06002662 userKeyUnlocked = isUserKeyUnlocked(userId);
Sudheer Shanka2250d562016-11-07 15:41:02 -08002663 storagePermission = mStorageManagerInternal.hasExternalStorage(uid, packageName);
Svetoslav38c3dbb2015-07-14 11:27:06 -07002664 } finally {
Jeff Sharkeyc02bfae2016-03-27 15:06:53 -06002665 Binder.restoreCallingIdentity(token);
Svetoslav38c3dbb2015-07-14 11:27:06 -07002666 }
Svet Ganov6ee871e2015-07-10 14:29:33 -07002667
Jeff Sharkeyc02bfae2016-03-27 15:06:53 -06002668 boolean foundPrimary = false;
2669
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07002670 final ArrayList<StorageVolume> res = new ArrayList<>();
Jeff Sharkey48877892015-03-18 11:27:19 -07002671 synchronized (mLock) {
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07002672 for (int i = 0; i < mVolumes.size(); i++) {
2673 final VolumeInfo vol = mVolumes.valueAt(i);
Jeff Sharkeyc02bfae2016-03-27 15:06:53 -06002674 switch (vol.getType()) {
2675 case VolumeInfo.TYPE_PUBLIC:
2676 case VolumeInfo.TYPE_EMULATED:
2677 break;
2678 default:
2679 continue;
2680 }
2681
2682 boolean match = false;
2683 if (forWrite) {
2684 match = vol.isVisibleForWrite(userId);
2685 } else {
Felipe Leme123a0e72016-06-10 11:09:11 -07002686 match = vol.isVisibleForRead(userId)
2687 || (includeInvisible && vol.getPath() != null);
Jeff Sharkeyc02bfae2016-03-27 15:06:53 -06002688 }
2689 if (!match) continue;
2690
2691 boolean reportUnmounted = false;
2692 if ((vol.getType() == VolumeInfo.TYPE_EMULATED) && !userKeyUnlocked) {
2693 reportUnmounted = true;
2694 } else if (!storagePermission && !realState) {
2695 reportUnmounted = true;
2696 }
2697
2698 final StorageVolume userVol = vol.buildStorageVolume(mContext, userId,
2699 reportUnmounted);
2700 if (vol.isPrimary()) {
2701 res.add(0, userVol);
2702 foundPrimary = true;
2703 } else {
2704 res.add(userVol);
Jeff Sharkeyb049e212012-09-07 23:16:01 -07002705 }
Mike Lockwood8fa5f802011-03-24 08:12:30 -07002706 }
Mike Lockwood8fa5f802011-03-24 08:12:30 -07002707 }
Jeff Sharkey48877892015-03-18 11:27:19 -07002708
2709 if (!foundPrimary) {
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07002710 Log.w(TAG, "No primary storage defined yet; hacking together a stub");
Jeff Sharkey48877892015-03-18 11:27:19 -07002711
2712 final boolean primaryPhysical = SystemProperties.getBoolean(
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07002713 StorageManager.PROP_PRIMARY_PHYSICAL, false);
Jeff Sharkey48877892015-03-18 11:27:19 -07002714
2715 final String id = "stub_primary";
2716 final File path = Environment.getLegacyExternalStorageDirectory();
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07002717 final String description = mContext.getString(android.R.string.unknownName);
Jeff Sharkey48877892015-03-18 11:27:19 -07002718 final boolean primary = true;
2719 final boolean removable = primaryPhysical;
2720 final boolean emulated = !primaryPhysical;
Jeff Sharkey48877892015-03-18 11:27:19 -07002721 final boolean allowMassStorage = false;
2722 final long maxFileSize = 0L;
2723 final UserHandle owner = new UserHandle(userId);
2724 final String uuid = null;
Jeff Sharkey48877892015-03-18 11:27:19 -07002725 final String state = Environment.MEDIA_REMOVED;
2726
Jerry Zhangf9c5c252017-08-16 18:07:51 -07002727 res.add(0, new StorageVolume(id, path,
2728 description, primary, removable, emulated,
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07002729 allowMassStorage, maxFileSize, owner, uuid, state));
Jeff Sharkey48877892015-03-18 11:27:19 -07002730 }
2731
2732 return res.toArray(new StorageVolume[res.size()]);
Mike Lockwood8fa5f802011-03-24 08:12:30 -07002733 }
2734
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07002735 @Override
2736 public DiskInfo[] getDisks() {
2737 synchronized (mLock) {
2738 final DiskInfo[] res = new DiskInfo[mDisks.size()];
2739 for (int i = 0; i < mDisks.size(); i++) {
2740 res[i] = mDisks.valueAt(i);
2741 }
2742 return res;
2743 }
2744 }
2745
2746 @Override
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07002747 public VolumeInfo[] getVolumes(int flags) {
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07002748 synchronized (mLock) {
2749 final VolumeInfo[] res = new VolumeInfo[mVolumes.size()];
2750 for (int i = 0; i < mVolumes.size(); i++) {
2751 res[i] = mVolumes.valueAt(i);
2752 }
2753 return res;
2754 }
2755 }
2756
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07002757 @Override
2758 public VolumeRecord[] getVolumeRecords(int flags) {
2759 synchronized (mLock) {
2760 final VolumeRecord[] res = new VolumeRecord[mRecords.size()];
2761 for (int i = 0; i < mRecords.size(); i++) {
2762 res[i] = mRecords.valueAt(i);
2763 }
2764 return res;
2765 }
2766 }
2767
Jeff Sharkey9bed0702017-01-23 20:37:05 -07002768 @Override
2769 public long getCacheQuotaBytes(String volumeUuid, int uid) {
2770 if (uid != Binder.getCallingUid()) {
2771 mContext.enforceCallingPermission(android.Manifest.permission.STORAGE_INTERNAL, TAG);
2772 }
Daniel Nishi80fdb012017-03-09 14:30:07 -08002773 final long token = Binder.clearCallingIdentity();
2774 final StorageStatsManager stats = mContext.getSystemService(StorageStatsManager.class);
2775 try {
2776 return stats.getCacheQuotaBytes(volumeUuid, uid);
2777 } finally {
2778 Binder.restoreCallingIdentity(token);
2779 }
Jeff Sharkey9bed0702017-01-23 20:37:05 -07002780 }
2781
2782 @Override
2783 public long getCacheSizeBytes(String volumeUuid, int uid) {
2784 if (uid != Binder.getCallingUid()) {
2785 mContext.enforceCallingPermission(android.Manifest.permission.STORAGE_INTERNAL, TAG);
2786 }
2787 final long token = Binder.clearCallingIdentity();
2788 try {
2789 return mContext.getSystemService(StorageStatsManager.class)
2790 .queryStatsForUid(volumeUuid, uid).getCacheBytes();
Jeff Sharkey789a8fc2017-04-16 13:18:35 -06002791 } catch (IOException e) {
2792 throw new ParcelableException(e);
Jeff Sharkey9bed0702017-01-23 20:37:05 -07002793 } finally {
2794 Binder.restoreCallingIdentity(token);
2795 }
2796 }
2797
Jeff Sharkey35e46d22017-06-09 10:01:20 -06002798 private int adjustAllocateFlags(int flags, int callingUid, String callingPackage) {
2799 // Require permission to allocate aggressively
2800 if ((flags & StorageManager.FLAG_ALLOCATE_AGGRESSIVE) != 0) {
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07002801 mContext.enforceCallingOrSelfPermission(
2802 android.Manifest.permission.ALLOCATE_AGGRESSIVE, TAG);
2803 }
2804
Jeff Sharkey35e46d22017-06-09 10:01:20 -06002805 // Apps normally can't directly defy reserved space
2806 flags &= ~StorageManager.FLAG_ALLOCATE_DEFY_ALL_RESERVED;
2807 flags &= ~StorageManager.FLAG_ALLOCATE_DEFY_HALF_RESERVED;
2808
2809 // However, if app is actively using the camera, then we're willing to
2810 // clear up to half of the reserved cache space, since the user might be
2811 // trying to capture an important memory.
2812 final AppOpsManager appOps = mContext.getSystemService(AppOpsManager.class);
2813 final long token = Binder.clearCallingIdentity();
2814 try {
2815 if (appOps.isOperationActive(AppOpsManager.OP_CAMERA, callingUid, callingPackage)) {
2816 Slog.d(TAG, "UID " + callingUid + " is actively using camera;"
2817 + " letting them defy reserved cached data");
2818 flags |= StorageManager.FLAG_ALLOCATE_DEFY_HALF_RESERVED;
2819 }
2820 } finally {
2821 Binder.restoreCallingIdentity(token);
2822 }
2823
2824 return flags;
2825 }
2826
2827 @Override
2828 public long getAllocatableBytes(String volumeUuid, int flags, String callingPackage) {
2829 flags = adjustAllocateFlags(flags, Binder.getCallingUid(), callingPackage);
2830
2831 final StorageManager storage = mContext.getSystemService(StorageManager.class);
2832 final StorageStatsManager stats = mContext.getSystemService(StorageStatsManager.class);
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07002833 final long token = Binder.clearCallingIdentity();
2834 try {
2835 // In general, apps can allocate as much space as they want, except
2836 // we never let them eat into either the minimum cache space or into
Jeff Sharkeyddff8072017-05-26 13:10:46 -06002837 // the low disk warning space. To avoid user confusion, this logic
2838 // should be kept in sync with getFreeBytes().
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07002839 final File path = storage.findPathForUuid(volumeUuid);
Jeff Sharkeyddff8072017-05-26 13:10:46 -06002840
2841 final long usable = path.getUsableSpace();
2842 final long lowReserved = storage.getStorageLowBytes(path);
2843 final long fullReserved = storage.getStorageFullBytes(path);
2844
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07002845 if (stats.isQuotaSupported(volumeUuid)) {
Jeff Sharkeyddff8072017-05-26 13:10:46 -06002846 final long cacheTotal = stats.getCacheBytes(volumeUuid);
Jeff Sharkey35e46d22017-06-09 10:01:20 -06002847 final long cacheReserved = storage.getStorageCacheBytes(path, flags);
Jeff Sharkeyddff8072017-05-26 13:10:46 -06002848 final long cacheClearable = Math.max(0, cacheTotal - cacheReserved);
2849
Jeff Sharkey35e46d22017-06-09 10:01:20 -06002850 if ((flags & StorageManager.FLAG_ALLOCATE_AGGRESSIVE) != 0) {
2851 return Math.max(0, (usable + cacheClearable) - fullReserved);
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07002852 } else {
Jeff Sharkeyddff8072017-05-26 13:10:46 -06002853 return Math.max(0, (usable + cacheClearable) - lowReserved);
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07002854 }
2855 } else {
2856 // When we don't have fast quota information, we ignore cached
2857 // data and only consider unused bytes.
Jeff Sharkey35e46d22017-06-09 10:01:20 -06002858 if ((flags & StorageManager.FLAG_ALLOCATE_AGGRESSIVE) != 0) {
Jeff Sharkeyddff8072017-05-26 13:10:46 -06002859 return Math.max(0, usable - fullReserved);
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07002860 } else {
Jeff Sharkeyddff8072017-05-26 13:10:46 -06002861 return Math.max(0, usable - lowReserved);
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07002862 }
2863 }
Jeff Sharkey789a8fc2017-04-16 13:18:35 -06002864 } catch (IOException e) {
2865 throw new ParcelableException(e);
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07002866 } finally {
2867 Binder.restoreCallingIdentity(token);
2868 }
Jeff Sharkey500ce9e2017-02-12 02:39:24 -07002869 }
2870
2871 @Override
Jeff Sharkey35e46d22017-06-09 10:01:20 -06002872 public void allocateBytes(String volumeUuid, long bytes, int flags, String callingPackage) {
2873 flags = adjustAllocateFlags(flags, Binder.getCallingUid(), callingPackage);
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07002874
Jeff Sharkey35e46d22017-06-09 10:01:20 -06002875 final long allocatableBytes = getAllocatableBytes(volumeUuid, flags, callingPackage);
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07002876 if (bytes > allocatableBytes) {
2877 throw new ParcelableException(new IOException("Failed to allocate " + bytes
2878 + " because only " + allocatableBytes + " allocatable"));
2879 }
2880
Jeff Sharkey35e46d22017-06-09 10:01:20 -06002881 final StorageManager storage = mContext.getSystemService(StorageManager.class);
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07002882 final long token = Binder.clearCallingIdentity();
2883 try {
Jeff Sharkey789a8fc2017-04-16 13:18:35 -06002884 // Free up enough disk space to satisfy both the requested allocation
2885 // and our low disk warning space.
2886 final File path = storage.findPathForUuid(volumeUuid);
Jeff Sharkeyddff8072017-05-26 13:10:46 -06002887 if ((flags & StorageManager.FLAG_ALLOCATE_AGGRESSIVE) != 0) {
2888 bytes += storage.getStorageFullBytes(path);
2889 } else {
2890 bytes += storage.getStorageLowBytes(path);
2891 }
Jeff Sharkey789a8fc2017-04-16 13:18:35 -06002892
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07002893 mPms.freeStorage(volumeUuid, bytes, flags);
2894 } catch (IOException e) {
2895 throw new ParcelableException(e);
2896 } finally {
2897 Binder.restoreCallingIdentity(token);
Jeff Sharkey500ce9e2017-02-12 02:39:24 -07002898 }
2899 }
2900
Kenny Rootaf9d6672010-10-08 09:21:39 -07002901 private void addObbStateLocked(ObbState obbState) throws RemoteException {
2902 final IBinder binder = obbState.getBinder();
2903 List<ObbState> obbStates = mObbMounts.get(binder);
Kenny Root5919ac62010-10-05 09:49:40 -07002904
Kenny Rootaf9d6672010-10-08 09:21:39 -07002905 if (obbStates == null) {
2906 obbStates = new ArrayList<ObbState>();
2907 mObbMounts.put(binder, obbStates);
2908 } else {
2909 for (final ObbState o : obbStates) {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002910 if (o.rawPath.equals(obbState.rawPath)) {
Kenny Rootaf9d6672010-10-08 09:21:39 -07002911 throw new IllegalStateException("Attempt to add ObbState twice. "
Sudheer Shanka2250d562016-11-07 15:41:02 -08002912 + "This indicates an error in the StorageManagerService logic.");
Kenny Root5919ac62010-10-05 09:49:40 -07002913 }
2914 }
Kenny Roota02b8b02010-08-05 16:14:17 -07002915 }
Kenny Rootaf9d6672010-10-08 09:21:39 -07002916
2917 obbStates.add(obbState);
2918 try {
2919 obbState.link();
2920 } catch (RemoteException e) {
2921 /*
2922 * The binder died before we could link it, so clean up our state
2923 * and return failure.
2924 */
2925 obbStates.remove(obbState);
2926 if (obbStates.isEmpty()) {
2927 mObbMounts.remove(binder);
2928 }
2929
2930 // Rethrow the error so mountObb can get it
2931 throw e;
2932 }
2933
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002934 mObbPathToStateMap.put(obbState.rawPath, obbState);
Kenny Roota02b8b02010-08-05 16:14:17 -07002935 }
2936
Kenny Rootaf9d6672010-10-08 09:21:39 -07002937 private void removeObbStateLocked(ObbState obbState) {
2938 final IBinder binder = obbState.getBinder();
2939 final List<ObbState> obbStates = mObbMounts.get(binder);
2940 if (obbStates != null) {
2941 if (obbStates.remove(obbState)) {
2942 obbState.unlink();
Kenny Root05105f72010-09-22 17:29:43 -07002943 }
Kenny Rootaf9d6672010-10-08 09:21:39 -07002944 if (obbStates.isEmpty()) {
2945 mObbMounts.remove(binder);
2946 }
Kenny Roota02b8b02010-08-05 16:14:17 -07002947 }
Kenny Roota02b8b02010-08-05 16:14:17 -07002948
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002949 mObbPathToStateMap.remove(obbState.rawPath);
Kenny Root38cf8862010-09-26 14:18:51 -07002950 }
2951
Kenny Roota02b8b02010-08-05 16:14:17 -07002952 private class ObbActionHandler extends Handler {
2953 private boolean mBound = false;
Kenny Root480afe72010-10-07 10:17:50 -07002954 private final List<ObbAction> mActions = new LinkedList<ObbAction>();
Kenny Roota02b8b02010-08-05 16:14:17 -07002955
2956 ObbActionHandler(Looper l) {
2957 super(l);
2958 }
2959
2960 @Override
2961 public void handleMessage(Message msg) {
2962 switch (msg.what) {
2963 case OBB_RUN_ACTION: {
Kenny Root480afe72010-10-07 10:17:50 -07002964 final ObbAction action = (ObbAction) msg.obj;
Kenny Roota02b8b02010-08-05 16:14:17 -07002965
2966 if (DEBUG_OBB)
2967 Slog.i(TAG, "OBB_RUN_ACTION: " + action.toString());
2968
2969 // If a bind was already initiated we don't really
2970 // need to do anything. The pending install
2971 // will be processed later on.
2972 if (!mBound) {
2973 // If this is the only one pending we might
2974 // have to bind to the service again.
2975 if (!connectToService()) {
2976 Slog.e(TAG, "Failed to bind to media container service");
2977 action.handleError();
2978 return;
Kenny Roota02b8b02010-08-05 16:14:17 -07002979 }
Kenny Roota02b8b02010-08-05 16:14:17 -07002980 }
Kenny Root735de3b2010-09-30 14:11:39 -07002981
Kenny Root735de3b2010-09-30 14:11:39 -07002982 mActions.add(action);
Kenny Roota02b8b02010-08-05 16:14:17 -07002983 break;
2984 }
2985 case OBB_MCS_BOUND: {
2986 if (DEBUG_OBB)
2987 Slog.i(TAG, "OBB_MCS_BOUND");
2988 if (msg.obj != null) {
2989 mContainerService = (IMediaContainerService) msg.obj;
2990 }
2991 if (mContainerService == null) {
2992 // Something seriously wrong. Bail out
2993 Slog.e(TAG, "Cannot bind to media container service");
2994 for (ObbAction action : mActions) {
2995 // Indicate service bind error
2996 action.handleError();
2997 }
2998 mActions.clear();
2999 } else if (mActions.size() > 0) {
Kenny Root480afe72010-10-07 10:17:50 -07003000 final ObbAction action = mActions.get(0);
Kenny Roota02b8b02010-08-05 16:14:17 -07003001 if (action != null) {
3002 action.execute(this);
3003 }
3004 } else {
3005 // Should never happen ideally.
3006 Slog.w(TAG, "Empty queue");
3007 }
3008 break;
3009 }
3010 case OBB_MCS_RECONNECT: {
3011 if (DEBUG_OBB)
3012 Slog.i(TAG, "OBB_MCS_RECONNECT");
3013 if (mActions.size() > 0) {
3014 if (mBound) {
3015 disconnectService();
3016 }
3017 if (!connectToService()) {
3018 Slog.e(TAG, "Failed to bind to media container service");
3019 for (ObbAction action : mActions) {
3020 // Indicate service bind error
3021 action.handleError();
3022 }
3023 mActions.clear();
3024 }
3025 }
3026 break;
3027 }
3028 case OBB_MCS_UNBIND: {
3029 if (DEBUG_OBB)
3030 Slog.i(TAG, "OBB_MCS_UNBIND");
3031
3032 // Delete pending install
3033 if (mActions.size() > 0) {
3034 mActions.remove(0);
3035 }
3036 if (mActions.size() == 0) {
3037 if (mBound) {
3038 disconnectService();
3039 }
3040 } else {
3041 // There are more pending requests in queue.
3042 // Just post MCS_BOUND message to trigger processing
3043 // of next pending install.
3044 mObbActionHandler.sendEmptyMessage(OBB_MCS_BOUND);
3045 }
3046 break;
3047 }
Kenny Rootaf9d6672010-10-08 09:21:39 -07003048 case OBB_FLUSH_MOUNT_STATE: {
3049 final String path = (String) msg.obj;
3050
3051 if (DEBUG_OBB)
3052 Slog.i(TAG, "Flushing all OBB state for path " + path);
3053
3054 synchronized (mObbMounts) {
3055 final List<ObbState> obbStatesToRemove = new LinkedList<ObbState>();
3056
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003057 final Iterator<ObbState> i = mObbPathToStateMap.values().iterator();
Kenny Rootaf9d6672010-10-08 09:21:39 -07003058 while (i.hasNext()) {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003059 final ObbState state = i.next();
Kenny Rootaf9d6672010-10-08 09:21:39 -07003060
3061 /*
3062 * If this entry's source file is in the volume path
3063 * that got unmounted, remove it because it's no
3064 * longer valid.
3065 */
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003066 if (state.canonicalPath.startsWith(path)) {
3067 obbStatesToRemove.add(state);
Kenny Rootaf9d6672010-10-08 09:21:39 -07003068 }
3069 }
3070
3071 for (final ObbState obbState : obbStatesToRemove) {
3072 if (DEBUG_OBB)
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003073 Slog.i(TAG, "Removing state for " + obbState.rawPath);
Kenny Rootaf9d6672010-10-08 09:21:39 -07003074
3075 removeObbStateLocked(obbState);
3076
3077 try {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003078 obbState.token.onObbResult(obbState.rawPath, obbState.nonce,
Kenny Rootaf9d6672010-10-08 09:21:39 -07003079 OnObbStateChangeListener.UNMOUNTED);
3080 } catch (RemoteException e) {
3081 Slog.i(TAG, "Couldn't send unmount notification for OBB: "
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003082 + obbState.rawPath);
Kenny Rootaf9d6672010-10-08 09:21:39 -07003083 }
3084 }
3085 }
3086 break;
3087 }
Kenny Roota02b8b02010-08-05 16:14:17 -07003088 }
3089 }
3090
3091 private boolean connectToService() {
3092 if (DEBUG_OBB)
3093 Slog.i(TAG, "Trying to bind to DefaultContainerService");
3094
3095 Intent service = new Intent().setComponent(DEFAULT_CONTAINER_COMPONENT);
Jeff Sharkey6dce4962015-07-03 18:08:41 -07003096 if (mContext.bindServiceAsUser(service, mDefContainerConn, Context.BIND_AUTO_CREATE,
Xiaohui Chene4de5a02015-09-22 15:33:31 -07003097 UserHandle.SYSTEM)) {
Kenny Roota02b8b02010-08-05 16:14:17 -07003098 mBound = true;
3099 return true;
3100 }
3101 return false;
3102 }
3103
3104 private void disconnectService() {
3105 mContainerService = null;
3106 mBound = false;
3107 mContext.unbindService(mDefContainerConn);
3108 }
3109 }
3110
3111 abstract class ObbAction {
3112 private static final int MAX_RETRIES = 3;
3113 private int mRetries;
3114
3115 ObbState mObbState;
3116
3117 ObbAction(ObbState obbState) {
3118 mObbState = obbState;
3119 }
3120
3121 public void execute(ObbActionHandler handler) {
3122 try {
3123 if (DEBUG_OBB)
Ben Komalo444eca22011-09-01 15:17:44 -07003124 Slog.i(TAG, "Starting to execute action: " + toString());
Kenny Roota02b8b02010-08-05 16:14:17 -07003125 mRetries++;
3126 if (mRetries > MAX_RETRIES) {
3127 Slog.w(TAG, "Failed to invoke remote methods on default container service. Giving up");
Kenny Root480afe72010-10-07 10:17:50 -07003128 mObbActionHandler.sendEmptyMessage(OBB_MCS_UNBIND);
Kenny Roota02b8b02010-08-05 16:14:17 -07003129 handleError();
Kenny Roota02b8b02010-08-05 16:14:17 -07003130 } else {
3131 handleExecute();
3132 if (DEBUG_OBB)
3133 Slog.i(TAG, "Posting install MCS_UNBIND");
3134 mObbActionHandler.sendEmptyMessage(OBB_MCS_UNBIND);
3135 }
3136 } catch (RemoteException e) {
3137 if (DEBUG_OBB)
3138 Slog.i(TAG, "Posting install MCS_RECONNECT");
3139 mObbActionHandler.sendEmptyMessage(OBB_MCS_RECONNECT);
3140 } catch (Exception e) {
3141 if (DEBUG_OBB)
3142 Slog.d(TAG, "Error handling OBB action", e);
3143 handleError();
Kenny Root17eb6fb2010-10-06 15:02:52 -07003144 mObbActionHandler.sendEmptyMessage(OBB_MCS_UNBIND);
Kenny Roota02b8b02010-08-05 16:14:17 -07003145 }
3146 }
3147
Kenny Root05105f72010-09-22 17:29:43 -07003148 abstract void handleExecute() throws RemoteException, IOException;
Kenny Roota02b8b02010-08-05 16:14:17 -07003149 abstract void handleError();
Kenny Root38cf8862010-09-26 14:18:51 -07003150
3151 protected ObbInfo getObbInfo() throws IOException {
3152 ObbInfo obbInfo;
3153 try {
Xiaohui Chen621b3fc2015-10-02 14:41:42 -07003154 obbInfo = mContainerService.getObbInfo(mObbState.canonicalPath);
Kenny Root38cf8862010-09-26 14:18:51 -07003155 } catch (RemoteException e) {
3156 Slog.d(TAG, "Couldn't call DefaultContainerService to fetch OBB info for "
Xiaohui Chen621b3fc2015-10-02 14:41:42 -07003157 + mObbState.canonicalPath);
Kenny Root38cf8862010-09-26 14:18:51 -07003158 obbInfo = null;
3159 }
3160 if (obbInfo == null) {
Xiaohui Chen621b3fc2015-10-02 14:41:42 -07003161 throw new IOException("Couldn't read OBB file: " + mObbState.canonicalPath);
Kenny Root38cf8862010-09-26 14:18:51 -07003162 }
3163 return obbInfo;
3164 }
3165
Kenny Rootaf9d6672010-10-08 09:21:39 -07003166 protected void sendNewStatusOrIgnore(int status) {
3167 if (mObbState == null || mObbState.token == null) {
3168 return;
3169 }
3170
Kenny Root38cf8862010-09-26 14:18:51 -07003171 try {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003172 mObbState.token.onObbResult(mObbState.rawPath, mObbState.nonce, status);
Kenny Root38cf8862010-09-26 14:18:51 -07003173 } catch (RemoteException e) {
Sudheer Shanka2250d562016-11-07 15:41:02 -08003174 Slog.w(TAG, "StorageEventListener went away while calling onObbStateChanged");
Kenny Root38cf8862010-09-26 14:18:51 -07003175 }
3176 }
Kenny Roota02b8b02010-08-05 16:14:17 -07003177 }
3178
3179 class MountObbAction extends ObbAction {
Ben Komalo444eca22011-09-01 15:17:44 -07003180 private final String mKey;
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003181 private final int mCallingUid;
Kenny Roota02b8b02010-08-05 16:14:17 -07003182
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003183 MountObbAction(ObbState obbState, String key, int callingUid) {
Kenny Roota02b8b02010-08-05 16:14:17 -07003184 super(obbState);
3185 mKey = key;
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003186 mCallingUid = callingUid;
Kenny Roota02b8b02010-08-05 16:14:17 -07003187 }
3188
Jason parks5af0b912010-11-29 09:05:25 -06003189 @Override
Kenny Root735de3b2010-09-30 14:11:39 -07003190 public void handleExecute() throws IOException, RemoteException {
Kenny Rootaf9d6672010-10-08 09:21:39 -07003191 warnOnNotMounted();
3192
Kenny Root38cf8862010-09-26 14:18:51 -07003193 final ObbInfo obbInfo = getObbInfo();
3194
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003195 if (!isUidOwnerOfPackageOrSystem(obbInfo.packageName, mCallingUid)) {
Kenny Rootaf9d6672010-10-08 09:21:39 -07003196 Slog.w(TAG, "Denied attempt to mount OBB " + obbInfo.filename
3197 + " which is owned by " + obbInfo.packageName);
3198 sendNewStatusOrIgnore(OnObbStateChangeListener.ERROR_PERMISSION_DENIED);
3199 return;
Kenny Roota02b8b02010-08-05 16:14:17 -07003200 }
3201
Kenny Rootaf9d6672010-10-08 09:21:39 -07003202 final boolean isMounted;
3203 synchronized (mObbMounts) {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003204 isMounted = mObbPathToStateMap.containsKey(mObbState.rawPath);
Kenny Rootaf9d6672010-10-08 09:21:39 -07003205 }
3206 if (isMounted) {
3207 Slog.w(TAG, "Attempt to mount OBB which is already mounted: " + obbInfo.filename);
3208 sendNewStatusOrIgnore(OnObbStateChangeListener.ERROR_ALREADY_MOUNTED);
3209 return;
3210 }
3211
Kenny Rootaf9d6672010-10-08 09:21:39 -07003212 final String hashedKey;
Jeff Sharkey41cd6812017-09-11 10:32:17 -06003213 final String binderKey;
Kenny Rootaf9d6672010-10-08 09:21:39 -07003214 if (mKey == null) {
3215 hashedKey = "none";
Jeff Sharkey41cd6812017-09-11 10:32:17 -06003216 binderKey = "";
Kenny Rootaf9d6672010-10-08 09:21:39 -07003217 } else {
Kenny Rootaf9d6672010-10-08 09:21:39 -07003218 try {
Kenny Root3b1abba2010-10-13 15:00:07 -07003219 SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
3220
3221 KeySpec ks = new PBEKeySpec(mKey.toCharArray(), obbInfo.salt,
3222 PBKDF2_HASH_ROUNDS, CRYPTO_ALGORITHM_KEY_SIZE);
3223 SecretKey key = factory.generateSecret(ks);
3224 BigInteger bi = new BigInteger(key.getEncoded());
3225 hashedKey = bi.toString(16);
Jeff Sharkey41cd6812017-09-11 10:32:17 -06003226 binderKey = hashedKey;
Kenny Rootaf9d6672010-10-08 09:21:39 -07003227 } catch (NoSuchAlgorithmException e) {
Kenny Root3b1abba2010-10-13 15:00:07 -07003228 Slog.e(TAG, "Could not load PBKDF2 algorithm", e);
3229 sendNewStatusOrIgnore(OnObbStateChangeListener.ERROR_INTERNAL);
3230 return;
3231 } catch (InvalidKeySpecException e) {
3232 Slog.e(TAG, "Invalid key spec when loading PBKDF2 algorithm", e);
3233 sendNewStatusOrIgnore(OnObbStateChangeListener.ERROR_INTERNAL);
Kenny Root38cf8862010-09-26 14:18:51 -07003234 return;
3235 }
Kenny Rootaf9d6672010-10-08 09:21:39 -07003236 }
Kenny Root38cf8862010-09-26 14:18:51 -07003237
Kenny Rootaf9d6672010-10-08 09:21:39 -07003238 int rc = StorageResultCode.OperationSucceeded;
Kenny Rootaf9d6672010-10-08 09:21:39 -07003239 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06003240 mObbState.volId = mVold.createObb(mObbState.canonicalPath, binderKey,
3241 mObbState.ownerGid);
3242 mVold.mount(mObbState.volId, 0, -1);
Jeff Sharkey41cd6812017-09-11 10:32:17 -06003243 } catch (Exception e) {
3244 Slog.w(TAG, e);
3245 rc = StorageResultCode.OperationFailedInternalError;
Kenny Roota02b8b02010-08-05 16:14:17 -07003246 }
3247
Kenny Rootaf9d6672010-10-08 09:21:39 -07003248 if (rc == StorageResultCode.OperationSucceeded) {
3249 if (DEBUG_OBB)
Xiaohui Chen621b3fc2015-10-02 14:41:42 -07003250 Slog.d(TAG, "Successfully mounted OBB " + mObbState.canonicalPath);
Kenny Rootaf9d6672010-10-08 09:21:39 -07003251
3252 synchronized (mObbMounts) {
3253 addObbStateLocked(mObbState);
3254 }
3255
3256 sendNewStatusOrIgnore(OnObbStateChangeListener.MOUNTED);
Kenny Root02c87302010-07-01 08:10:18 -07003257 } else {
Kenny Root05105f72010-09-22 17:29:43 -07003258 Slog.e(TAG, "Couldn't mount OBB file: " + rc);
Kenny Roota02b8b02010-08-05 16:14:17 -07003259
Kenny Rootaf9d6672010-10-08 09:21:39 -07003260 sendNewStatusOrIgnore(OnObbStateChangeListener.ERROR_COULD_NOT_MOUNT);
Kenny Root02c87302010-07-01 08:10:18 -07003261 }
3262 }
3263
Jason parks5af0b912010-11-29 09:05:25 -06003264 @Override
Kenny Roota02b8b02010-08-05 16:14:17 -07003265 public void handleError() {
Kenny Rootaf9d6672010-10-08 09:21:39 -07003266 sendNewStatusOrIgnore(OnObbStateChangeListener.ERROR_INTERNAL);
Kenny Root02c87302010-07-01 08:10:18 -07003267 }
Kenny Roota02b8b02010-08-05 16:14:17 -07003268
3269 @Override
3270 public String toString() {
3271 StringBuilder sb = new StringBuilder();
3272 sb.append("MountObbAction{");
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003273 sb.append(mObbState);
Kenny Roota02b8b02010-08-05 16:14:17 -07003274 sb.append('}');
3275 return sb.toString();
3276 }
3277 }
3278
3279 class UnmountObbAction extends ObbAction {
Ben Komalo444eca22011-09-01 15:17:44 -07003280 private final boolean mForceUnmount;
Kenny Roota02b8b02010-08-05 16:14:17 -07003281
3282 UnmountObbAction(ObbState obbState, boolean force) {
3283 super(obbState);
3284 mForceUnmount = force;
3285 }
3286
Jason parks5af0b912010-11-29 09:05:25 -06003287 @Override
Kenny Root38cf8862010-09-26 14:18:51 -07003288 public void handleExecute() throws IOException {
Kenny Rootaf9d6672010-10-08 09:21:39 -07003289 warnOnNotMounted();
3290
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003291 final ObbState existingState;
Kenny Root38cf8862010-09-26 14:18:51 -07003292 synchronized (mObbMounts) {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003293 existingState = mObbPathToStateMap.get(mObbState.rawPath);
Kenny Rootaf9d6672010-10-08 09:21:39 -07003294 }
Kenny Root38cf8862010-09-26 14:18:51 -07003295
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003296 if (existingState == null) {
Kenny Rootaf9d6672010-10-08 09:21:39 -07003297 sendNewStatusOrIgnore(OnObbStateChangeListener.ERROR_NOT_MOUNTED);
3298 return;
3299 }
3300
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003301 if (existingState.ownerGid != mObbState.ownerGid) {
3302 Slog.w(TAG, "Permission denied attempting to unmount OBB " + existingState.rawPath
3303 + " (owned by GID " + existingState.ownerGid + ")");
Kenny Rootaf9d6672010-10-08 09:21:39 -07003304 sendNewStatusOrIgnore(OnObbStateChangeListener.ERROR_PERMISSION_DENIED);
3305 return;
3306 }
3307
Kenny Rootaf9d6672010-10-08 09:21:39 -07003308 int rc = StorageResultCode.OperationSucceeded;
Kenny Rootaf9d6672010-10-08 09:21:39 -07003309 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06003310 mVold.unmount(mObbState.volId);
3311 mVold.destroyObb(mObbState.volId);
3312 mObbState.volId = null;
Jeff Sharkey41cd6812017-09-11 10:32:17 -06003313 } catch (Exception e) {
3314 Slog.w(TAG, e);
3315 rc = StorageResultCode.OperationFailedInternalError;
Kenny Roota02b8b02010-08-05 16:14:17 -07003316 }
3317
Kenny Rootaf9d6672010-10-08 09:21:39 -07003318 if (rc == StorageResultCode.OperationSucceeded) {
3319 synchronized (mObbMounts) {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003320 removeObbStateLocked(existingState);
Kenny Root38cf8862010-09-26 14:18:51 -07003321 }
3322
Kenny Rootaf9d6672010-10-08 09:21:39 -07003323 sendNewStatusOrIgnore(OnObbStateChangeListener.UNMOUNTED);
Kenny Roota02b8b02010-08-05 16:14:17 -07003324 } else {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003325 Slog.w(TAG, "Could not unmount OBB: " + existingState);
Kenny Rootaf9d6672010-10-08 09:21:39 -07003326 sendNewStatusOrIgnore(OnObbStateChangeListener.ERROR_COULD_NOT_UNMOUNT);
Kenny Roota02b8b02010-08-05 16:14:17 -07003327 }
3328 }
3329
Jason parks5af0b912010-11-29 09:05:25 -06003330 @Override
Kenny Roota02b8b02010-08-05 16:14:17 -07003331 public void handleError() {
Kenny Rootaf9d6672010-10-08 09:21:39 -07003332 sendNewStatusOrIgnore(OnObbStateChangeListener.ERROR_INTERNAL);
Kenny Roota02b8b02010-08-05 16:14:17 -07003333 }
3334
3335 @Override
3336 public String toString() {
3337 StringBuilder sb = new StringBuilder();
3338 sb.append("UnmountObbAction{");
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003339 sb.append(mObbState);
Kenny Roota02b8b02010-08-05 16:14:17 -07003340 sb.append(",force=");
3341 sb.append(mForceUnmount);
Kenny Roota02b8b02010-08-05 16:14:17 -07003342 sb.append('}');
3343 return sb.toString();
3344 }
Kenny Root02c87302010-07-01 08:10:18 -07003345 }
Kenny Root38cf8862010-09-26 14:18:51 -07003346
Jeff Sharkey7e19f532017-11-06 13:54:11 -07003347 private void dispatchOnStatus(IVoldTaskListener listener, int status,
3348 PersistableBundle extras) {
3349 if (listener != null) {
3350 try {
3351 listener.onStatus(status, extras);
3352 } catch (RemoteException ignored) {
3353 }
3354 }
3355 }
3356
3357 private void dispatchOnFinished(IVoldTaskListener listener, int status,
3358 PersistableBundle extras) {
3359 if (listener != null) {
3360 try {
3361 listener.onFinished(status, extras);
3362 } catch (RemoteException ignored) {
3363 }
3364 }
3365 }
3366
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07003367 private static class Callbacks extends Handler {
3368 private static final int MSG_STORAGE_STATE_CHANGED = 1;
3369 private static final int MSG_VOLUME_STATE_CHANGED = 2;
Jeff Sharkey50a05452015-04-29 11:24:52 -07003370 private static final int MSG_VOLUME_RECORD_CHANGED = 3;
3371 private static final int MSG_VOLUME_FORGOTTEN = 4;
3372 private static final int MSG_DISK_SCANNED = 5;
Makoto Onuki9dc575d2015-06-12 16:10:25 -07003373 private static final int MSG_DISK_DESTROYED = 6;
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07003374
Sudheer Shanka2250d562016-11-07 15:41:02 -08003375 private final RemoteCallbackList<IStorageEventListener>
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07003376 mCallbacks = new RemoteCallbackList<>();
3377
3378 public Callbacks(Looper looper) {
3379 super(looper);
3380 }
3381
Sudheer Shanka2250d562016-11-07 15:41:02 -08003382 public void register(IStorageEventListener callback) {
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07003383 mCallbacks.register(callback);
3384 }
3385
Sudheer Shanka2250d562016-11-07 15:41:02 -08003386 public void unregister(IStorageEventListener callback) {
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07003387 mCallbacks.unregister(callback);
3388 }
3389
3390 @Override
3391 public void handleMessage(Message msg) {
3392 final SomeArgs args = (SomeArgs) msg.obj;
3393 final int n = mCallbacks.beginBroadcast();
3394 for (int i = 0; i < n; i++) {
Sudheer Shanka2250d562016-11-07 15:41:02 -08003395 final IStorageEventListener callback = mCallbacks.getBroadcastItem(i);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07003396 try {
3397 invokeCallback(callback, msg.what, args);
3398 } catch (RemoteException ignored) {
3399 }
3400 }
3401 mCallbacks.finishBroadcast();
3402 args.recycle();
3403 }
3404
Sudheer Shanka2250d562016-11-07 15:41:02 -08003405 private void invokeCallback(IStorageEventListener callback, int what, SomeArgs args)
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07003406 throws RemoteException {
3407 switch (what) {
3408 case MSG_STORAGE_STATE_CHANGED: {
3409 callback.onStorageStateChanged((String) args.arg1, (String) args.arg2,
3410 (String) args.arg3);
3411 break;
3412 }
3413 case MSG_VOLUME_STATE_CHANGED: {
3414 callback.onVolumeStateChanged((VolumeInfo) args.arg1, args.argi2, args.argi3);
3415 break;
3416 }
Jeff Sharkey50a05452015-04-29 11:24:52 -07003417 case MSG_VOLUME_RECORD_CHANGED: {
3418 callback.onVolumeRecordChanged((VolumeRecord) args.arg1);
3419 break;
3420 }
3421 case MSG_VOLUME_FORGOTTEN: {
3422 callback.onVolumeForgotten((String) args.arg1);
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07003423 break;
3424 }
Jeff Sharkey620b32b2015-04-23 19:36:02 -07003425 case MSG_DISK_SCANNED: {
3426 callback.onDiskScanned((DiskInfo) args.arg1, args.argi2);
Jeff Sharkey7e92ef32015-04-17 17:35:07 -07003427 break;
3428 }
Makoto Onuki9dc575d2015-06-12 16:10:25 -07003429 case MSG_DISK_DESTROYED: {
3430 callback.onDiskDestroyed((DiskInfo) args.arg1);
3431 break;
3432 }
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07003433 }
3434 }
3435
3436 private void notifyStorageStateChanged(String path, String oldState, String newState) {
3437 final SomeArgs args = SomeArgs.obtain();
3438 args.arg1 = path;
3439 args.arg2 = oldState;
3440 args.arg3 = newState;
3441 obtainMessage(MSG_STORAGE_STATE_CHANGED, args).sendToTarget();
3442 }
3443
3444 private void notifyVolumeStateChanged(VolumeInfo vol, int oldState, int newState) {
3445 final SomeArgs args = SomeArgs.obtain();
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07003446 args.arg1 = vol.clone();
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07003447 args.argi2 = oldState;
3448 args.argi3 = newState;
3449 obtainMessage(MSG_VOLUME_STATE_CHANGED, args).sendToTarget();
3450 }
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07003451
Jeff Sharkey50a05452015-04-29 11:24:52 -07003452 private void notifyVolumeRecordChanged(VolumeRecord rec) {
3453 final SomeArgs args = SomeArgs.obtain();
3454 args.arg1 = rec.clone();
3455 obtainMessage(MSG_VOLUME_RECORD_CHANGED, args).sendToTarget();
3456 }
3457
3458 private void notifyVolumeForgotten(String fsUuid) {
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07003459 final SomeArgs args = SomeArgs.obtain();
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07003460 args.arg1 = fsUuid;
Jeff Sharkey50a05452015-04-29 11:24:52 -07003461 obtainMessage(MSG_VOLUME_FORGOTTEN, args).sendToTarget();
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07003462 }
Jeff Sharkey7e92ef32015-04-17 17:35:07 -07003463
Jeff Sharkey620b32b2015-04-23 19:36:02 -07003464 private void notifyDiskScanned(DiskInfo disk, int volumeCount) {
Jeff Sharkey7e92ef32015-04-17 17:35:07 -07003465 final SomeArgs args = SomeArgs.obtain();
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07003466 args.arg1 = disk.clone();
Jeff Sharkey620b32b2015-04-23 19:36:02 -07003467 args.argi2 = volumeCount;
3468 obtainMessage(MSG_DISK_SCANNED, args).sendToTarget();
Jeff Sharkey7e92ef32015-04-17 17:35:07 -07003469 }
Makoto Onuki9dc575d2015-06-12 16:10:25 -07003470
3471 private void notifyDiskDestroyed(DiskInfo disk) {
3472 final SomeArgs args = SomeArgs.obtain();
3473 args.arg1 = disk.clone();
3474 obtainMessage(MSG_DISK_DESTROYED, args).sendToTarget();
3475 }
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07003476 }
3477
Kenny Root38cf8862010-09-26 14:18:51 -07003478 @Override
Jeff Sharkey5aca2b82013-10-16 16:21:54 -07003479 protected void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
Jeff Sharkeyfe9a53b2017-03-31 14:08:23 -06003480 if (!DumpUtils.checkDumpPermission(mContext, TAG, writer)) return;
Jeff Sharkey5aca2b82013-10-16 16:21:54 -07003481
3482 final IndentingPrintWriter pw = new IndentingPrintWriter(writer, " ", 160);
Jeff Sharkey27de30d2015-04-18 16:20:27 -07003483 synchronized (mLock) {
3484 pw.println("Disks:");
3485 pw.increaseIndent();
3486 for (int i = 0; i < mDisks.size(); i++) {
3487 final DiskInfo disk = mDisks.valueAt(i);
3488 disk.dump(pw);
3489 }
3490 pw.decreaseIndent();
3491
3492 pw.println();
3493 pw.println("Volumes:");
3494 pw.increaseIndent();
3495 for (int i = 0; i < mVolumes.size(); i++) {
3496 final VolumeInfo vol = mVolumes.valueAt(i);
3497 if (VolumeInfo.ID_PRIVATE_INTERNAL.equals(vol.id)) continue;
3498 vol.dump(pw);
3499 }
3500 pw.decreaseIndent();
3501
3502 pw.println();
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07003503 pw.println("Records:");
Jeff Sharkey27de30d2015-04-18 16:20:27 -07003504 pw.increaseIndent();
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07003505 for (int i = 0; i < mRecords.size(); i++) {
3506 final VolumeRecord note = mRecords.valueAt(i);
3507 note.dump(pw);
Jeff Sharkey27de30d2015-04-18 16:20:27 -07003508 }
3509 pw.decreaseIndent();
Jeff Sharkey275e3e42015-04-24 16:10:32 -07003510
3511 pw.println();
3512 pw.println("Primary storage UUID: " + mPrimaryStorageUuid);
Felipe Leme281389a2016-10-10 17:12:20 -07003513 final Pair<String, Long> pair = StorageManager.getPrimaryStoragePathAndSize();
3514 if (pair == null) {
3515 pw.println("Internal storage total size: N/A");
3516 } else {
3517 pw.print("Internal storage (");
3518 pw.print(pair.first);
3519 pw.print(") total size: ");
3520 pw.print(pair.second);
3521 pw.print(" (");
3522 pw.print((float) pair.second / TrafficStats.GB_IN_BYTES);
3523 pw.println(" GB)");
3524 }
Jeff Sharkey4c099d02015-05-15 13:45:00 -07003525 pw.println("Force adoptable: " + mForceAdoptable);
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08003526 pw.println();
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07003527 pw.println("Local unlocked users: " + Arrays.toString(mLocalUnlockedUsers));
3528 pw.println("System unlocked users: " + Arrays.toString(mSystemUnlockedUsers));
Jeff Sharkey27de30d2015-04-18 16:20:27 -07003529 }
Kenny Root38cf8862010-09-26 14:18:51 -07003530
Kenny Root38cf8862010-09-26 14:18:51 -07003531 synchronized (mObbMounts) {
Jeff Sharkey27de30d2015-04-18 16:20:27 -07003532 pw.println();
Jeff Sharkey5aca2b82013-10-16 16:21:54 -07003533 pw.println("mObbMounts:");
3534 pw.increaseIndent();
3535 final Iterator<Entry<IBinder, List<ObbState>>> binders = mObbMounts.entrySet()
3536 .iterator();
Kenny Rootaf9d6672010-10-08 09:21:39 -07003537 while (binders.hasNext()) {
3538 Entry<IBinder, List<ObbState>> e = binders.next();
Jeff Sharkey5aca2b82013-10-16 16:21:54 -07003539 pw.println(e.getKey() + ":");
3540 pw.increaseIndent();
Kenny Rootaf9d6672010-10-08 09:21:39 -07003541 final List<ObbState> obbStates = e.getValue();
Kenny Root38cf8862010-09-26 14:18:51 -07003542 for (final ObbState obbState : obbStates) {
Jeff Sharkey5aca2b82013-10-16 16:21:54 -07003543 pw.println(obbState);
Kenny Root38cf8862010-09-26 14:18:51 -07003544 }
Jeff Sharkey5aca2b82013-10-16 16:21:54 -07003545 pw.decreaseIndent();
Kenny Root38cf8862010-09-26 14:18:51 -07003546 }
Jeff Sharkey5aca2b82013-10-16 16:21:54 -07003547 pw.decreaseIndent();
Kenny Rootaf9d6672010-10-08 09:21:39 -07003548
Jeff Sharkey5aca2b82013-10-16 16:21:54 -07003549 pw.println();
3550 pw.println("mObbPathToStateMap:");
3551 pw.increaseIndent();
Kenny Rootaf9d6672010-10-08 09:21:39 -07003552 final Iterator<Entry<String, ObbState>> maps = mObbPathToStateMap.entrySet().iterator();
3553 while (maps.hasNext()) {
3554 final Entry<String, ObbState> e = maps.next();
Jeff Sharkey5aca2b82013-10-16 16:21:54 -07003555 pw.print(e.getKey());
3556 pw.print(" -> ");
3557 pw.println(e.getValue());
Kenny Rootaf9d6672010-10-08 09:21:39 -07003558 }
Jeff Sharkey5aca2b82013-10-16 16:21:54 -07003559 pw.decreaseIndent();
Kenny Root38cf8862010-09-26 14:18:51 -07003560 }
Kenny Root4161f9b2011-07-13 09:48:33 -07003561
Robert Greenwalt470fd722012-01-18 12:51:15 -08003562 pw.println();
Christopher Tate7265abe2014-11-21 13:54:45 -08003563 pw.print("Last maintenance: ");
Jeff Sharkeye8a4b662015-06-27 15:43:45 -07003564 pw.println(TimeUtils.formatForLogging(mLastMaintenance));
Kenny Root38cf8862010-09-26 14:18:51 -07003565 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003566
Jeff Sharkeyfa23c5a2011-08-09 21:44:24 -07003567 /** {@inheritDoc} */
Jeff Sharkey48877892015-03-18 11:27:19 -07003568 @Override
Jeff Sharkeyfa23c5a2011-08-09 21:44:24 -07003569 public void monitor() {
Jeff Sharkey54402792017-09-15 16:05:19 -06003570 try {
3571 mVold.monitor();
3572 } catch (Exception e) {
3573 Slog.wtf(TAG, e);
Paul Lawrence1c62cbb2015-06-03 14:14:52 -07003574 }
Jeff Sharkeyfa23c5a2011-08-09 21:44:24 -07003575 }
Svet Ganov6ee871e2015-07-10 14:29:33 -07003576
Sudheer Shanka2250d562016-11-07 15:41:02 -08003577 private final class StorageManagerInternalImpl extends StorageManagerInternal {
Svet Ganov6ee871e2015-07-10 14:29:33 -07003578 // Not guarded by a lock.
3579 private final CopyOnWriteArrayList<ExternalStorageMountPolicy> mPolicies =
3580 new CopyOnWriteArrayList<>();
3581
3582 @Override
3583 public void addExternalStoragePolicy(ExternalStorageMountPolicy policy) {
3584 // No locking - CopyOnWriteArrayList
3585 mPolicies.add(policy);
3586 }
3587
3588 @Override
3589 public void onExternalStoragePolicyChanged(int uid, String packageName) {
3590 final int mountMode = getExternalStorageMountMode(uid, packageName);
3591 remountUidExternalStorage(uid, mountMode);
3592 }
3593
3594 @Override
3595 public int getExternalStorageMountMode(int uid, String packageName) {
3596 // No locking - CopyOnWriteArrayList
3597 int mountMode = Integer.MAX_VALUE;
3598 for (ExternalStorageMountPolicy policy : mPolicies) {
3599 final int policyMode = policy.getMountMode(uid, packageName);
3600 if (policyMode == Zygote.MOUNT_EXTERNAL_NONE) {
3601 return Zygote.MOUNT_EXTERNAL_NONE;
3602 }
3603 mountMode = Math.min(mountMode, policyMode);
3604 }
3605 if (mountMode == Integer.MAX_VALUE) {
3606 return Zygote.MOUNT_EXTERNAL_NONE;
3607 }
3608 return mountMode;
3609 }
3610
3611 public boolean hasExternalStorage(int uid, String packageName) {
Amith Yamasani2bd5cff2015-07-22 14:42:31 -07003612 // No need to check for system uid. This avoids a deadlock between
3613 // PackageManagerService and AppOpsService.
3614 if (uid == Process.SYSTEM_UID) {
3615 return true;
3616 }
Svet Ganov6ee871e2015-07-10 14:29:33 -07003617 // No locking - CopyOnWriteArrayList
3618 for (ExternalStorageMountPolicy policy : mPolicies) {
3619 final boolean policyHasStorage = policy.hasExternalStorage(uid, packageName);
3620 if (!policyHasStorage) {
3621 return false;
3622 }
3623 }
3624 return true;
3625 }
3626 }
Jeff Sharkeyfa23c5a2011-08-09 21:44:24 -07003627}