blob: 7361e70a5bde1ca372ea83b2f0061d8c2048c192 [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;
Daniel Colascione766b6322018-01-08 19:10:36 -080052import android.database.ContentObserver;
Felipe Leme281389a2016-10-10 17:12:20 -070053import android.net.TrafficStats;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080054import android.net.Uri;
Kenny Root02c87302010-07-01 08:10:18 -070055import android.os.Binder;
Jeff Sharkey4c099d02015-05-15 13:45:00 -070056import android.os.DropBoxManager;
Kenny Roota02b8b02010-08-05 16:14:17 -070057import android.os.Environment;
Jeff Sharkeyb049e212012-09-07 23:16:01 -070058import android.os.Environment.UserEnvironment;
Jeff Sharkey48877892015-03-18 11:27:19 -070059import android.os.FileUtils;
Suchi Amalapurapuc42e29e2010-02-22 16:03:53 -080060import android.os.Handler;
Dianne Hackbornefa92b22013-05-03 14:11:43 -070061import android.os.HandlerThread;
Kenny Roota02b8b02010-08-05 16:14:17 -070062import android.os.IBinder;
Jeff Sharkey7e19f532017-11-06 13:54:11 -070063import android.os.IProgressListener;
Jin Qian12690d52017-10-13 18:17:04 -070064import android.os.IStoraged;
Jeff Sharkey1019de92017-09-06 13:47:03 -060065import android.os.IVold;
Jeff Sharkey8058fe62017-09-13 11:50:33 -060066import android.os.IVoldListener;
Jeff Sharkeyb302c542017-09-15 12:57:59 -060067import android.os.IVoldTaskListener;
Daniel Sandler5f27ef42010-03-16 15:42:02 -040068import android.os.Looper;
Suchi Amalapurapuc42e29e2010-02-22 16:03:53 -080069import android.os.Message;
Daichi Hirono9e8d9e22015-11-13 14:37:00 +090070import android.os.ParcelFileDescriptor;
Jeff Sharkey500ce9e2017-02-12 02:39:24 -070071import android.os.ParcelableException;
Jeff Sharkeyb302c542017-09-15 12:57:59 -060072import android.os.PersistableBundle;
Jeff Sharkeyce14cd02015-12-07 15:35:42 -070073import android.os.PowerManager;
Jeff Sharkey9527b222015-06-24 15:24:48 -070074import android.os.Process;
Jeff Sharkey7151a9a2015-04-04 15:22:37 -070075import android.os.RemoteCallbackList;
San Mehat4270e1e2010-01-29 05:32:19 -080076import android.os.RemoteException;
Suchi Amalapurapufd3530f2010-01-18 00:15:59 -080077import android.os.ServiceManager;
Jeff Sharkeyedcdaf62015-07-09 09:45:36 -070078import android.os.SystemClock;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080079import android.os.SystemProperties;
Dianne Hackbornf02b60a2012-08-16 10:48:27 -070080import android.os.UserHandle;
Emily Bernier92aa5a22014-07-07 10:11:48 -040081import android.os.UserManager;
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -070082import android.os.storage.DiskInfo;
Kenny Roota02b8b02010-08-05 16:14:17 -070083import android.os.storage.IObbActionListener;
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -070084import android.os.storage.IStorageEventListener;
Sudheer Shanka2250d562016-11-07 15:41:02 -080085import android.os.storage.IStorageManager;
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -070086import android.os.storage.IStorageShutdownObserver;
Kenny Rootaf9d6672010-10-08 09:21:39 -070087import android.os.storage.OnObbStateChangeListener;
Paul Lawrence46791e72014-04-03 09:10:26 -070088import android.os.storage.StorageManager;
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -070089import android.os.storage.StorageManagerInternal;
Kenny Roota02b8b02010-08-05 16:14:17 -070090import android.os.storage.StorageResultCode;
Mike Lockwood2f6a3882011-05-09 19:08:06 -070091import android.os.storage.StorageVolume;
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -070092import android.os.storage.VolumeInfo;
Jeff Sharkeyb36586a2015-04-27 08:42:28 -070093import android.os.storage.VolumeRecord;
Jeff Sharkey14cbe522015-07-08 14:06:37 -070094import android.provider.MediaStore;
Jeff Sharkeye8a4b662015-06-27 15:43:45 -070095import android.provider.Settings;
Jason parksf7b3cd42011-01-27 09:28:25 -060096import android.text.TextUtils;
Jeff Sharkey1783f142015-04-17 10:52:51 -070097import android.text.format.DateUtils;
Jeff Sharkey48877892015-03-18 11:27:19 -070098import android.util.ArrayMap;
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -070099import android.util.AtomicFile;
Jeff Sharkey9f2dc052018-01-07 16:47:31 -0700100import android.util.DataUnit;
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -0700101import android.util.Log;
Felipe Leme281389a2016-10-10 17:12:20 -0700102import android.util.Pair;
San Mehata5078592010-03-25 09:36:54 -0700103import android.util.Slog;
Jeff Sharkeye8a4b662015-06-27 15:43:45 -0700104import android.util.TimeUtils;
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700105import android.util.Xml;
Jeff Sharkey48877892015-03-18 11:27:19 -0700106
Jeff Sharkey8b2c3a142012-11-12 11:45:05 -0800107import com.android.internal.annotations.GuardedBy;
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700108import com.android.internal.app.IMediaContainerService;
Daichi Hirono9fb00182016-11-08 14:12:17 +0900109import com.android.internal.os.AppFuseMount;
Jeff Sharkey1019de92017-09-06 13:47:03 -0600110import com.android.internal.os.BackgroundThread;
Daichi Hirono812c95d2017-02-08 16:20:20 +0900111import com.android.internal.os.FuseUnavailableMountException;
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700112import com.android.internal.os.SomeArgs;
Jeff Sharkey9527b222015-06-24 15:24:48 -0700113import com.android.internal.os.Zygote;
Jeff Sharkey48877892015-03-18 11:27:19 -0700114import com.android.internal.util.ArrayUtils;
Jeff Sharkeyfe9a53b2017-03-31 14:08:23 -0600115import com.android.internal.util.DumpUtils;
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700116import com.android.internal.util.FastXmlSerializer;
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -0800117import com.android.internal.util.HexDump;
Jeff Sharkey5aca2b82013-10-16 16:21:54 -0700118import com.android.internal.util.IndentingPrintWriter;
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700119import com.android.internal.util.Preconditions;
Jeff Sharkeyb9fe5372015-12-03 15:23:08 -0700120import com.android.internal.widget.LockPatternUtils;
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700121import com.android.server.pm.PackageManagerService;
Daichi Hirono9fb00182016-11-08 14:12:17 +0900122import com.android.server.storage.AppFuseBridge;
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -0700123
Jeff Sharkey5217cac2015-12-20 15:34:01 -0700124import libcore.io.IoUtils;
125import libcore.util.EmptyArray;
126
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700127import org.xmlpull.v1.XmlPullParser;
128import org.xmlpull.v1.XmlPullParserException;
129import org.xmlpull.v1.XmlSerializer;
130
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700131import java.io.File;
Kenny Root38cf8862010-09-26 14:18:51 -0700132import java.io.FileDescriptor;
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700133import java.io.FileInputStream;
134import java.io.FileNotFoundException;
Christopher Tate7265abe2014-11-21 13:54:45 -0800135import java.io.FileOutputStream;
Kenny Root05105f72010-09-22 17:29:43 -0700136import java.io.IOException;
Kenny Root38cf8862010-09-26 14:18:51 -0700137import java.io.PrintWriter;
Kenny Root3b1abba2010-10-13 15:00:07 -0700138import java.math.BigInteger;
Paul Lawrence8e397362014-01-27 15:22:30 -0800139import java.nio.charset.StandardCharsets;
Kenny Root735de3b2010-09-30 14:11:39 -0700140import java.security.NoSuchAlgorithmException;
Kenny Root3b1abba2010-10-13 15:00:07 -0700141import java.security.spec.InvalidKeySpecException;
142import java.security.spec.KeySpec;
San Mehat22dd86e2010-01-12 12:21:18 -0800143import java.util.ArrayList;
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -0800144import java.util.Arrays;
Kenny Roota02b8b02010-08-05 16:14:17 -0700145import java.util.HashMap;
Kenny Root38cf8862010-09-26 14:18:51 -0700146import java.util.Iterator;
Kenny Roota02b8b02010-08-05 16:14:17 -0700147import java.util.LinkedList;
148import java.util.List;
Elliott Hughesf839b4f2014-09-26 12:30:47 -0700149import java.util.Locale;
Kenny Roota02b8b02010-08-05 16:14:17 -0700150import java.util.Map;
Kenny Root38cf8862010-09-26 14:18:51 -0700151import java.util.Map.Entry;
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700152import java.util.Objects;
Jeff Sharkeyb302c542017-09-15 12:57:59 -0600153import java.util.concurrent.CompletableFuture;
Svet Ganov6ee871e2015-07-10 14:29:33 -0700154import java.util.concurrent.CopyOnWriteArrayList;
Kenny Root51a573c2012-05-17 13:30:28 -0700155import java.util.concurrent.CountDownLatch;
156import java.util.concurrent.TimeUnit;
Jeff Sharkeyedcdaf62015-07-09 09:45:36 -0700157import java.util.concurrent.TimeoutException;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800158
Kenny Root3b1abba2010-10-13 15:00:07 -0700159import javax.crypto.SecretKey;
160import javax.crypto.SecretKeyFactory;
161import javax.crypto.spec.PBEKeySpec;
162
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800163/**
Jeff Sharkey48877892015-03-18 11:27:19 -0700164 * Service responsible for various storage media. Connects to {@code vold} to
165 * watch for and manage dynamically added storage, such as SD cards and USB mass
166 * storage. Also decides how storage should be presented to users on the device.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800167 */
Jeff Sharkey9765e442017-12-14 22:15:14 -0700168class StorageManagerService extends IStorageManager.Stub
169 implements Watchdog.Monitor, ScreenObserver {
Jason parks5af0b912010-11-29 09:05:25 -0600170
Christopher Tated417d622013-08-19 16:14:25 -0700171 // Static direct instance pointer for the tightly-coupled idle service to use
Sudheer Shanka2250d562016-11-07 15:41:02 -0800172 static StorageManagerService sSelf = null;
Christopher Tated417d622013-08-19 16:14:25 -0700173
Daniel Colascione766b6322018-01-08 19:10:36 -0800174 /* Read during boot to decide whether to enable zram when available */
175 private static final String ZRAM_ENABLED_PROPERTY =
176 "persist.sys.zram_enabled";
177
Jeff Sharkey56e62932015-03-21 20:41:00 -0700178 public static class Lifecycle extends SystemService {
Sudheer Shanka2250d562016-11-07 15:41:02 -0800179 private StorageManagerService mStorageManagerService;
Jeff Sharkey56e62932015-03-21 20:41:00 -0700180
181 public Lifecycle(Context context) {
182 super(context);
183 }
184
185 @Override
186 public void onStart() {
Sudheer Shanka2250d562016-11-07 15:41:02 -0800187 mStorageManagerService = new StorageManagerService(getContext());
188 publishBinderService("mount", mStorageManagerService);
189 mStorageManagerService.start();
Jeff Sharkey56e62932015-03-21 20:41:00 -0700190 }
191
192 @Override
193 public void onBootPhase(int phase) {
194 if (phase == SystemService.PHASE_ACTIVITY_MANAGER_READY) {
Sudheer Shanka2250d562016-11-07 15:41:02 -0800195 mStorageManagerService.systemReady();
Yasuhiro Matsuda87a38b52015-07-24 22:10:16 +0900196 } else if (phase == SystemService.PHASE_BOOT_COMPLETED) {
Sudheer Shanka2250d562016-11-07 15:41:02 -0800197 mStorageManagerService.bootCompleted();
Jeff Sharkey56e62932015-03-21 20:41:00 -0700198 }
199 }
Jeff Sharkey48877892015-03-18 11:27:19 -0700200
201 @Override
Jeff Sharkeyab15c392016-05-05 11:45:01 -0600202 public void onSwitchUser(int userHandle) {
Sudheer Shanka2250d562016-11-07 15:41:02 -0800203 mStorageManagerService.mCurrentUserId = userHandle;
Jeff Sharkeyab15c392016-05-05 11:45:01 -0600204 }
205
206 @Override
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700207 public void onUnlockUser(int userHandle) {
Sudheer Shanka2250d562016-11-07 15:41:02 -0800208 mStorageManagerService.onUnlockUser(userHandle);
Jeff Sharkey48877892015-03-18 11:27:19 -0700209 }
210
211 @Override
212 public void onCleanupUser(int userHandle) {
Sudheer Shanka2250d562016-11-07 15:41:02 -0800213 mStorageManagerService.onCleanupUser(userHandle);
Jeff Sharkey48877892015-03-18 11:27:19 -0700214 }
Jeff Sharkey56e62932015-03-21 20:41:00 -0700215 }
216
Dianne Hackborn40e9f292012-11-27 19:12:23 -0800217 private static final boolean DEBUG_EVENTS = false;
Kenny Rootb7db2722011-01-25 16:39:35 -0800218 private static final boolean DEBUG_OBB = false;
Kenny Root02c87302010-07-01 08:10:18 -0700219
Kenny Root07714d42011-08-17 17:49:28 -0700220 // Disable this since it messes up long-running cryptfs operations.
221 private static final boolean WATCHDOG_ENABLE = false;
222
Jeff Sharkey00455bf2016-11-04 14:45:24 -0600223 /**
224 * Our goal is for all Android devices to be usable as development devices,
225 * which includes the new Direct Boot mode added in N. For devices that
226 * don't have native FBE support, we offer an emulation mode for developer
227 * testing purposes, but if it's prohibitively difficult to support this
228 * mode, it can be disabled for specific products using this flag.
229 */
230 private static final boolean EMULATE_FBE_SUPPORTED = true;
231
Sudheer Shanka2250d562016-11-07 15:41:02 -0800232 private static final String TAG = "StorageManagerService";
Jeff Sharkeye8a4b662015-06-27 15:43:45 -0700233
Jeff Sharkey9756d752015-05-14 21:07:42 -0700234 private static final String TAG_STORAGE_BENCHMARK = "storage_benchmark";
Jeff Sharkeye8a4b662015-06-27 15:43:45 -0700235 private static final String TAG_STORAGE_TRIM = "storage_trim";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800236
Jeff Sharkey275e3e42015-04-24 16:10:32 -0700237 /** Magic value sent by MoveTask.cpp */
238 private static final int MOVE_STATUS_COPY_FINISHED = 82;
239
Jeff Sharkey620b32b2015-04-23 19:36:02 -0700240 private static final int VERSION_INIT = 1;
241 private static final int VERSION_ADD_PRIMARY = 2;
Jeff Sharkeyfced5342015-05-10 14:53:34 -0700242 private static final int VERSION_FIX_PRIMARY = 3;
Jeff Sharkey620b32b2015-04-23 19:36:02 -0700243
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700244 private static final String TAG_VOLUMES = "volumes";
Jeff Sharkey620b32b2015-04-23 19:36:02 -0700245 private static final String ATTR_VERSION = "version";
246 private static final String ATTR_PRIMARY_STORAGE_UUID = "primaryStorageUuid";
Jeff Sharkey4c099d02015-05-15 13:45:00 -0700247 private static final String ATTR_FORCE_ADOPTABLE = "forceAdoptable";
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700248 private static final String TAG_VOLUME = "volume";
249 private static final String ATTR_TYPE = "type";
250 private static final String ATTR_FS_UUID = "fsUuid";
Jeff Sharkey5cc0df22015-06-17 19:44:05 -0700251 private static final String ATTR_PART_GUID = "partGuid";
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700252 private static final String ATTR_NICKNAME = "nickname";
253 private static final String ATTR_USER_FLAGS = "userFlags";
Jeff Sharkeye8a4b662015-06-27 15:43:45 -0700254 private static final String ATTR_CREATED_MILLIS = "createdMillis";
255 private static final String ATTR_LAST_TRIM_MILLIS = "lastTrimMillis";
256 private static final String ATTR_LAST_BENCH_MILLIS = "lastBenchMillis";
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700257
Jeff Sharkeyb36586a2015-04-27 08:42:28 -0700258 private final AtomicFile mSettingsFile;
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700259
Jeff Sharkey48877892015-03-18 11:27:19 -0700260 /**
261 * <em>Never</em> hold the lock while performing downcalls into vold, since
262 * unsolicited events can suddenly appear to update data structures.
263 */
Jeff Sharkey5f3e9342017-03-13 14:53:11 -0600264 private final Object mLock = LockGuard.installNewLock(LockGuard.INDEX_STORAGE);
Jeff Sharkey48877892015-03-18 11:27:19 -0700265
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700266 /** Set of users that we know are unlocked. */
Jeff Sharkey48877892015-03-18 11:27:19 -0700267 @GuardedBy("mLock")
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700268 private int[] mLocalUnlockedUsers = EmptyArray.INT;
269 /** Set of users that system knows are unlocked. */
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -0800270 @GuardedBy("mLock")
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700271 private int[] mSystemUnlockedUsers = EmptyArray.INT;
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700272
273 /** Map from disk ID to disk */
Jeff Sharkey48877892015-03-18 11:27:19 -0700274 @GuardedBy("mLock")
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -0700275 private ArrayMap<String, DiskInfo> mDisks = new ArrayMap<>();
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700276 /** Map from volume ID to disk */
Jeff Sharkey48877892015-03-18 11:27:19 -0700277 @GuardedBy("mLock")
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700278 private final ArrayMap<String, VolumeInfo> mVolumes = new ArrayMap<>();
Jeff Sharkey48877892015-03-18 11:27:19 -0700279
Jeff Sharkeyb36586a2015-04-27 08:42:28 -0700280 /** Map from UUID to record */
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700281 @GuardedBy("mLock")
Jeff Sharkeyb36586a2015-04-27 08:42:28 -0700282 private ArrayMap<String, VolumeRecord> mRecords = new ArrayMap<>();
Jeff Sharkey620b32b2015-04-23 19:36:02 -0700283 @GuardedBy("mLock")
284 private String mPrimaryStorageUuid;
Jeff Sharkey4c099d02015-05-15 13:45:00 -0700285 @GuardedBy("mLock")
286 private boolean mForceAdoptable;
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700287
Jeff Sharkeyeba260d2015-04-19 14:35:16 -0700288 /** Map from disk ID to latches */
289 @GuardedBy("mLock")
290 private ArrayMap<String, CountDownLatch> mDiskScanLatches = new ArrayMap<>();
291
Jeff Sharkey275e3e42015-04-24 16:10:32 -0700292 @GuardedBy("mLock")
293 private IPackageMoveObserver mMoveCallback;
294 @GuardedBy("mLock")
295 private String mMoveTargetUuid;
296
Jeff Sharkeyab15c392016-05-05 11:45:01 -0600297 private volatile int mCurrentUserId = UserHandle.USER_SYSTEM;
298
Daichi Hirono9fb00182016-11-08 14:12:17 +0900299 /** Holding lock for AppFuse business */
300 private final Object mAppFuseLock = new Object();
301
302 @GuardedBy("mAppFuseLock")
303 private int mNextAppFuseName = 0;
304
305 @GuardedBy("mAppFuseLock")
Daichi Hironoe56740d2017-02-02 13:56:45 +0900306 private AppFuseBridge mAppFuseBridge = null;
Daichi Hirono9fb00182016-11-08 14:12:17 +0900307
Jeff Sharkeyef10ee02015-07-05 14:17:27 -0700308 private VolumeInfo findVolumeByIdOrThrow(String id) {
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700309 synchronized (mLock) {
310 final VolumeInfo vol = mVolumes.get(id);
311 if (vol != null) {
312 return vol;
313 }
314 }
315 throw new IllegalArgumentException("No volume found for ID " + id);
316 }
317
Jeff Sharkeyef10ee02015-07-05 14:17:27 -0700318 private String findVolumeIdForPathOrThrow(String path) {
Jeff Sharkey48877892015-03-18 11:27:19 -0700319 synchronized (mLock) {
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -0700320 for (int i = 0; i < mVolumes.size(); i++) {
321 final VolumeInfo vol = mVolumes.valueAt(i);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700322 if (vol.path != null && path.startsWith(vol.path)) {
323 return vol.id;
Jeff Sharkey48877892015-03-18 11:27:19 -0700324 }
325 }
326 }
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700327 throw new IllegalArgumentException("No volume found for path " + path);
Jeff Sharkey48877892015-03-18 11:27:19 -0700328 }
329
Jeff Sharkeye8a4b662015-06-27 15:43:45 -0700330 private VolumeRecord findRecordForPath(String path) {
331 synchronized (mLock) {
332 for (int i = 0; i < mVolumes.size(); i++) {
333 final VolumeInfo vol = mVolumes.valueAt(i);
334 if (vol.path != null && path.startsWith(vol.path)) {
335 return mRecords.get(vol.fsUuid);
336 }
337 }
338 }
339 return null;
340 }
341
342 private String scrubPath(String path) {
343 if (path.startsWith(Environment.getDataDirectory().getAbsolutePath())) {
344 return "internal";
345 }
346 final VolumeRecord rec = findRecordForPath(path);
347 if (rec == null || rec.createdMillis == 0) {
348 return "unknown";
349 } else {
350 return "ext:" + (int) ((System.currentTimeMillis() - rec.createdMillis)
351 / DateUtils.WEEK_IN_MILLIS) + "w";
352 }
353 }
354
Jeff Sharkeyef10ee02015-07-05 14:17:27 -0700355 private @Nullable VolumeInfo findStorageForUuid(String volumeUuid) {
Jeff Sharkey275e3e42015-04-24 16:10:32 -0700356 final StorageManager storage = mContext.getSystemService(StorageManager.class);
357 if (Objects.equals(StorageManager.UUID_PRIVATE_INTERNAL, volumeUuid)) {
Jeff Sharkeyef10ee02015-07-05 14:17:27 -0700358 return storage.findVolumeById(VolumeInfo.ID_EMULATED_INTERNAL);
Jeff Sharkey275e3e42015-04-24 16:10:32 -0700359 } else if (Objects.equals(StorageManager.UUID_PRIMARY_PHYSICAL, volumeUuid)) {
360 return storage.getPrimaryPhysicalVolume();
361 } else {
362 return storage.findEmulatedForPrivate(storage.findVolumeByUuid(volumeUuid));
363 }
364 }
365
Jeff Sharkeye8a4b662015-06-27 15:43:45 -0700366 private boolean shouldBenchmark() {
367 final long benchInterval = Settings.Global.getLong(mContext.getContentResolver(),
368 Settings.Global.STORAGE_BENCHMARK_INTERVAL, DateUtils.WEEK_IN_MILLIS);
Jeff Sharkeye83d8a92015-09-09 14:53:38 -0700369 if (benchInterval == -1) {
370 return false;
371 } else if (benchInterval == 0) {
372 return true;
373 }
374
Jeff Sharkeye8a4b662015-06-27 15:43:45 -0700375 synchronized (mLock) {
376 for (int i = 0; i < mVolumes.size(); i++) {
377 final VolumeInfo vol = mVolumes.valueAt(i);
378 final VolumeRecord rec = mRecords.get(vol.fsUuid);
Jeff Sharkeye83d8a92015-09-09 14:53:38 -0700379 if (vol.isMountedWritable() && rec != null) {
Jeff Sharkeye8a4b662015-06-27 15:43:45 -0700380 final long benchAge = System.currentTimeMillis() - rec.lastBenchMillis;
381 if (benchAge >= benchInterval) {
382 return true;
383 }
384 }
385 }
386 return false;
387 }
388 }
389
Jeff Sharkeyeba260d2015-04-19 14:35:16 -0700390 private CountDownLatch findOrCreateDiskScanLatch(String diskId) {
391 synchronized (mLock) {
392 CountDownLatch latch = mDiskScanLatches.get(diskId);
393 if (latch == null) {
394 latch = new CountDownLatch(1);
395 mDiskScanLatches.put(diskId, latch);
396 }
397 return latch;
398 }
399 }
400
Paul Lawrence8e397362014-01-27 15:22:30 -0800401 /** List of crypto types.
402 * These must match CRYPT_TYPE_XXX in cryptfs.h AND their
403 * corresponding commands in CommandListener.cpp */
404 public static final String[] CRYPTO_TYPES
405 = { "password", "default", "pattern", "pin" };
406
Brian Carlstrom7395a8a2014-04-28 22:11:01 -0700407 private final Context mContext;
Jeff Sharkeycd575992016-03-29 14:12:49 -0600408
Jeff Sharkey1019de92017-09-06 13:47:03 -0600409 private volatile IVold mVold;
Jin Qian12690d52017-10-13 18:17:04 -0700410 private volatile IStoraged mStoraged;
Jeff Sharkey1019de92017-09-06 13:47:03 -0600411
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700412 private volatile boolean mSystemReady = false;
Yasuhiro Matsuda87a38b52015-07-24 22:10:16 +0900413 private volatile boolean mBootCompleted = false;
Jeff Sharkey48877892015-03-18 11:27:19 -0700414 private volatile boolean mDaemonConnected = false;
Jeff Sharkey9765e442017-12-14 22:15:14 -0700415 private volatile boolean mSecureKeyguardShowing = true;
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700416
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700417 private PackageManagerService mPms;
418
419 private final Callbacks mCallbacks;
Jeff Sharkeyb9fe5372015-12-03 15:23:08 -0700420 private final LockPatternUtils mLockPatternUtils;
Jeff Sharkey48877892015-03-18 11:27:19 -0700421
San Mehat6cdd9c02010-02-09 14:45:20 -0800422 /**
Kenny Root3b1abba2010-10-13 15:00:07 -0700423 * The size of the crypto algorithm key in bits for OBB files. Currently
424 * Twofish is used which takes 128-bit keys.
425 */
426 private static final int CRYPTO_ALGORITHM_KEY_SIZE = 128;
427
428 /**
429 * The number of times to run SHA1 in the PBKDF2 function for OBB files.
430 * 1024 is reasonably secure and not too slow.
431 */
432 private static final int PBKDF2_HASH_ROUNDS = 1024;
433
434 /**
Kenny Roota02b8b02010-08-05 16:14:17 -0700435 * Mounted OBB tracking information. Used to track the current state of all
436 * OBBs.
Kenny Root02c87302010-07-01 08:10:18 -0700437 */
Kenny Root735de3b2010-09-30 14:11:39 -0700438 final private Map<IBinder, List<ObbState>> mObbMounts = new HashMap<IBinder, List<ObbState>>();
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700439
440 /** Map from raw paths to {@link ObbState}. */
Kenny Roota02b8b02010-08-05 16:14:17 -0700441 final private Map<String, ObbState> mObbPathToStateMap = new HashMap<String, ObbState>();
442
Svet Ganov6ee871e2015-07-10 14:29:33 -0700443 // Not guarded by a lock.
Sudheer Shanka2250d562016-11-07 15:41:02 -0800444 private final StorageManagerInternalImpl mStorageManagerInternal
445 = new StorageManagerInternalImpl();
Svet Ganov6ee871e2015-07-10 14:29:33 -0700446
Kenny Roota02b8b02010-08-05 16:14:17 -0700447 class ObbState implements IBinder.DeathRecipient {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700448 public ObbState(String rawPath, String canonicalPath, int callingUid,
Jeff Sharkey41cd6812017-09-11 10:32:17 -0600449 IObbActionListener token, int nonce, String volId) {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700450 this.rawPath = rawPath;
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700451 this.canonicalPath = canonicalPath;
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700452 this.ownerGid = UserHandle.getSharedAppGid(callingUid);
Kenny Rootaf9d6672010-10-08 09:21:39 -0700453 this.token = token;
454 this.nonce = nonce;
Jeff Sharkey41cd6812017-09-11 10:32:17 -0600455 this.volId = volId;
Kenny Roota02b8b02010-08-05 16:14:17 -0700456 }
457
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700458 final String rawPath;
459 final String canonicalPath;
Kenny Roota02b8b02010-08-05 16:14:17 -0700460
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700461 final int ownerGid;
Kenny Roota02b8b02010-08-05 16:14:17 -0700462
Kenny Rootaf9d6672010-10-08 09:21:39 -0700463 // Token of remote Binder caller
464 final IObbActionListener token;
465
466 // Identifier to pass back to the token
467 final int nonce;
Kenny Roota02b8b02010-08-05 16:14:17 -0700468
Jeff Sharkey41cd6812017-09-11 10:32:17 -0600469 String volId;
470
Kenny Root735de3b2010-09-30 14:11:39 -0700471 public IBinder getBinder() {
472 return token.asBinder();
473 }
474
Kenny Roota02b8b02010-08-05 16:14:17 -0700475 @Override
476 public void binderDied() {
477 ObbAction action = new UnmountObbAction(this, true);
478 mObbActionHandler.sendMessage(mObbActionHandler.obtainMessage(OBB_RUN_ACTION, action));
Kenny Root735de3b2010-09-30 14:11:39 -0700479 }
Kenny Roota02b8b02010-08-05 16:14:17 -0700480
Kenny Root5919ac62010-10-05 09:49:40 -0700481 public void link() throws RemoteException {
482 getBinder().linkToDeath(this, 0);
483 }
484
485 public void unlink() {
Kenny Root735de3b2010-09-30 14:11:39 -0700486 getBinder().unlinkToDeath(this, 0);
Kenny Roota02b8b02010-08-05 16:14:17 -0700487 }
Kenny Root38cf8862010-09-26 14:18:51 -0700488
489 @Override
490 public String toString() {
491 StringBuilder sb = new StringBuilder("ObbState{");
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700492 sb.append("rawPath=").append(rawPath);
493 sb.append(",canonicalPath=").append(canonicalPath);
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700494 sb.append(",ownerGid=").append(ownerGid);
495 sb.append(",token=").append(token);
496 sb.append(",binder=").append(getBinder());
Jeff Sharkey41cd6812017-09-11 10:32:17 -0600497 sb.append(",volId=").append(volId);
Kenny Root38cf8862010-09-26 14:18:51 -0700498 sb.append('}');
499 return sb.toString();
500 }
Kenny Roota02b8b02010-08-05 16:14:17 -0700501 }
502
503 // OBB Action Handler
504 final private ObbActionHandler mObbActionHandler;
505
506 // OBB action handler messages
507 private static final int OBB_RUN_ACTION = 1;
508 private static final int OBB_MCS_BOUND = 2;
509 private static final int OBB_MCS_UNBIND = 3;
510 private static final int OBB_MCS_RECONNECT = 4;
Kenny Rootaf9d6672010-10-08 09:21:39 -0700511 private static final int OBB_FLUSH_MOUNT_STATE = 5;
Kenny Roota02b8b02010-08-05 16:14:17 -0700512
513 /*
514 * Default Container Service information
515 */
516 static final ComponentName DEFAULT_CONTAINER_COMPONENT = new ComponentName(
517 "com.android.defcontainer", "com.android.defcontainer.DefaultContainerService");
518
519 final private DefaultContainerConnection mDefContainerConn = new DefaultContainerConnection();
520
521 class DefaultContainerConnection implements ServiceConnection {
Jeff Sharkey48877892015-03-18 11:27:19 -0700522 @Override
Kenny Roota02b8b02010-08-05 16:14:17 -0700523 public void onServiceConnected(ComponentName name, IBinder service) {
524 if (DEBUG_OBB)
525 Slog.i(TAG, "onServiceConnected");
526 IMediaContainerService imcs = IMediaContainerService.Stub.asInterface(service);
527 mObbActionHandler.sendMessage(mObbActionHandler.obtainMessage(OBB_MCS_BOUND, imcs));
528 }
529
Jeff Sharkey48877892015-03-18 11:27:19 -0700530 @Override
Kenny Roota02b8b02010-08-05 16:14:17 -0700531 public void onServiceDisconnected(ComponentName name) {
532 if (DEBUG_OBB)
533 Slog.i(TAG, "onServiceDisconnected");
534 }
Jeff Sharkey54402792017-09-15 16:05:19 -0600535 }
Kenny Roota02b8b02010-08-05 16:14:17 -0700536
537 // Used in the ObbActionHandler
538 private IMediaContainerService mContainerService = null;
Kenny Root02c87302010-07-01 08:10:18 -0700539
Christopher Tate7265abe2014-11-21 13:54:45 -0800540 // Last fstrim operation tracking
541 private static final String LAST_FSTRIM_FILE = "last-fstrim";
542 private final File mLastMaintenanceFile;
543 private long mLastMaintenance;
544
Kenny Root02c87302010-07-01 08:10:18 -0700545 // Handler messages
Jeff Sharkey48877892015-03-18 11:27:19 -0700546 private static final int H_SYSTEM_READY = 1;
547 private static final int H_DAEMON_CONNECTED = 2;
548 private static final int H_SHUTDOWN = 3;
549 private static final int H_FSTRIM = 4;
550 private static final int H_VOLUME_MOUNT = 5;
551 private static final int H_VOLUME_BROADCAST = 6;
Jeff Sharkeyabc3e852015-08-03 14:41:13 -0700552 private static final int H_INTERNAL_BROADCAST = 7;
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700553 private static final int H_VOLUME_UNMOUNT = 8;
Jeff Sharkey5a9bb742015-11-03 10:15:57 -0800554 private static final int H_PARTITION_FORGET = 9;
555 private static final int H_RESET = 10;
Jin Qiana85b9912017-10-17 15:48:18 -0700556 private static final int H_RUN_IDLE_MAINT = 11;
557 private static final int H_ABORT_IDLE_MAINT = 12;
Suchi Amalapurapu6ffce2e2010-03-08 14:48:40 -0800558
Sudheer Shanka2250d562016-11-07 15:41:02 -0800559 class StorageManagerServiceHandler extends Handler {
560 public StorageManagerServiceHandler(Looper looper) {
Jeff Sharkey48877892015-03-18 11:27:19 -0700561 super(looper);
Daniel Sandler5f27ef42010-03-16 15:42:02 -0400562 }
563
Jason parks5af0b912010-11-29 09:05:25 -0600564 @Override
Suchi Amalapurapuc42e29e2010-02-22 16:03:53 -0800565 public void handleMessage(Message msg) {
566 switch (msg.what) {
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700567 case H_SYSTEM_READY: {
Jeff Sharkey48877892015-03-18 11:27:19 -0700568 handleSystemReady();
569 break;
570 }
571 case H_DAEMON_CONNECTED: {
572 handleDaemonConnected();
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700573 break;
574 }
Christopher Tated417d622013-08-19 16:14:25 -0700575 case H_FSTRIM: {
Christopher Tated417d622013-08-19 16:14:25 -0700576 Slog.i(TAG, "Running fstrim idle maintenance");
Christopher Tate7265abe2014-11-21 13:54:45 -0800577
578 // Remember when we kicked it off
579 try {
580 mLastMaintenance = System.currentTimeMillis();
581 mLastMaintenanceFile.setLastModified(mLastMaintenance);
582 } catch (Exception e) {
583 Slog.e(TAG, "Unable to record last fstrim!");
584 }
585
Jeff Sharkeyb302c542017-09-15 12:57:59 -0600586 // TODO: Reintroduce shouldBenchmark() test
Jeff Sharkey7e19f532017-11-06 13:54:11 -0700587 fstrim(0, null);
Christopher Tate7265abe2014-11-21 13:54:45 -0800588
Christopher Tated417d622013-08-19 16:14:25 -0700589 // invoke the completion callback, if any
Jeff Sharkeye8a4b662015-06-27 15:43:45 -0700590 // TODO: fstrim is non-blocking, so remove this useless callback
Christopher Tated417d622013-08-19 16:14:25 -0700591 Runnable callback = (Runnable) msg.obj;
592 if (callback != null) {
593 callback.run();
594 }
595 break;
596 }
Jeff Sharkey48877892015-03-18 11:27:19 -0700597 case H_SHUTDOWN: {
Sudheer Shanka2250d562016-11-07 15:41:02 -0800598 final IStorageShutdownObserver obs = (IStorageShutdownObserver) msg.obj;
Jeff Sharkey48877892015-03-18 11:27:19 -0700599 boolean success = false;
600 try {
Jeff Sharkey54402792017-09-15 16:05:19 -0600601 mVold.shutdown();
602 success = true;
Jeff Sharkeyace874b2017-09-07 15:27:33 -0600603 } catch (Exception e) {
604 Slog.wtf(TAG, e);
Jeff Sharkey48877892015-03-18 11:27:19 -0700605 }
606 if (obs != null) {
607 try {
608 obs.onShutDownComplete(success ? 0 : -1);
Jeff Sharkeyace874b2017-09-07 15:27:33 -0600609 } catch (Exception ignored) {
Jeff Sharkey48877892015-03-18 11:27:19 -0700610 }
611 }
612 break;
613 }
614 case H_VOLUME_MOUNT: {
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -0700615 final VolumeInfo vol = (VolumeInfo) msg.obj;
Jeff Sharkey2e606d72015-07-27 14:19:54 -0700616 if (isMountDisallowed(vol)) {
617 Slog.i(TAG, "Ignoring mount " + vol.getId() + " due to policy");
618 break;
619 }
Jeff Sharkey48877892015-03-18 11:27:19 -0700620 try {
Jeff Sharkey54402792017-09-15 16:05:19 -0600621 mVold.mount(vol.id, vol.mountFlags, vol.mountUserId);
Jeff Sharkeyace874b2017-09-07 15:27:33 -0600622 } catch (Exception e) {
623 Slog.wtf(TAG, e);
Jeff Sharkey48877892015-03-18 11:27:19 -0700624 }
625 break;
626 }
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700627 case H_VOLUME_UNMOUNT: {
628 final VolumeInfo vol = (VolumeInfo) msg.obj;
629 unmount(vol.getId());
630 break;
631 }
Jeff Sharkey48877892015-03-18 11:27:19 -0700632 case H_VOLUME_BROADCAST: {
633 final StorageVolume userVol = (StorageVolume) msg.obj;
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700634 final String envState = userVol.getState();
635 Slog.d(TAG, "Volume " + userVol.getId() + " broadcasting " + envState + " to "
Jeff Sharkey48877892015-03-18 11:27:19 -0700636 + userVol.getOwner());
637
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700638 final String action = VolumeInfo.getBroadcastForEnvironment(envState);
Jeff Sharkey48877892015-03-18 11:27:19 -0700639 if (action != null) {
640 final Intent intent = new Intent(action,
641 Uri.fromFile(userVol.getPathFile()));
642 intent.putExtra(StorageVolume.EXTRA_STORAGE_VOLUME, userVol);
Jeff Sharkey082f83b2017-03-26 14:34:47 -0600643 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT
644 | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
Jeff Sharkey48877892015-03-18 11:27:19 -0700645 mContext.sendBroadcastAsUser(intent, userVol.getOwner());
646 }
647 break;
648 }
Jeff Sharkeyabc3e852015-08-03 14:41:13 -0700649 case H_INTERNAL_BROADCAST: {
650 // Internal broadcasts aimed at system components, not for
651 // third-party apps.
652 final Intent intent = (Intent) msg.obj;
653 mContext.sendBroadcastAsUser(intent, UserHandle.ALL,
654 android.Manifest.permission.WRITE_MEDIA_STORAGE);
Jeff Sharkey5a9bb742015-11-03 10:15:57 -0800655 break;
656 }
657 case H_PARTITION_FORGET: {
Jeff Sharkeydb4b6192017-10-24 11:08:50 -0600658 final VolumeRecord rec = (VolumeRecord) msg.obj;
659 forgetPartition(rec.partGuid, rec.fsUuid);
Jeff Sharkey5a9bb742015-11-03 10:15:57 -0800660 break;
661 }
662 case H_RESET: {
663 resetIfReadyAndConnected();
664 break;
Jeff Sharkeyabc3e852015-08-03 14:41:13 -0700665 }
Jin Qiana85b9912017-10-17 15:48:18 -0700666 case H_RUN_IDLE_MAINT: {
667 Slog.i(TAG, "Running idle maintenance");
668 runIdleMaint((Runnable)msg.obj);
669 break;
670 }
671 case H_ABORT_IDLE_MAINT: {
672 Slog.i(TAG, "Aborting idle maintenance");
673 abortIdleMaint((Runnable)msg.obj);
674 break;
675 }
676
Suchi Amalapurapuc42e29e2010-02-22 16:03:53 -0800677 }
678 }
Jeff Sharkey48877892015-03-18 11:27:19 -0700679 }
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700680
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700681 private final Handler mHandler;
Suchi Amalapurapuc42e29e2010-02-22 16:03:53 -0800682
Jeff Sharkeybcd262d2015-06-10 09:41:17 -0700683 private BroadcastReceiver mUserReceiver = new BroadcastReceiver() {
684 @Override
685 public void onReceive(Context context, Intent intent) {
686 final String action = intent.getAction();
687 final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700688 Preconditions.checkArgument(userId >= 0);
Jeff Sharkeybcd262d2015-06-10 09:41:17 -0700689
690 try {
691 if (Intent.ACTION_USER_ADDED.equals(action)) {
692 final UserManager um = mContext.getSystemService(UserManager.class);
693 final int userSerialNumber = um.getUserSerialNumber(userId);
Jeff Sharkey54402792017-09-15 16:05:19 -0600694 mVold.onUserAdded(userId, userSerialNumber);
Jeff Sharkeybcd262d2015-06-10 09:41:17 -0700695 } else if (Intent.ACTION_USER_REMOVED.equals(action)) {
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700696 synchronized (mVolumes) {
697 final int size = mVolumes.size();
698 for (int i = 0; i < size; i++) {
699 final VolumeInfo vol = mVolumes.valueAt(i);
700 if (vol.mountUserId == userId) {
701 vol.mountUserId = UserHandle.USER_NULL;
702 mHandler.obtainMessage(H_VOLUME_UNMOUNT, vol).sendToTarget();
703 }
704 }
705 }
Jeff Sharkey54402792017-09-15 16:05:19 -0600706 mVold.onUserRemoved(userId);
Jeff Sharkeybcd262d2015-06-10 09:41:17 -0700707 }
Jeff Sharkeyace874b2017-09-07 15:27:33 -0600708 } catch (Exception e) {
709 Slog.wtf(TAG, e);
Jeff Sharkeybcd262d2015-06-10 09:41:17 -0700710 }
711 }
712 };
713
Jeff Sharkeyedcdaf62015-07-09 09:45:36 -0700714 private void waitForLatch(CountDownLatch latch, String condition, long timeoutMillis)
715 throws TimeoutException {
716 final long startMillis = SystemClock.elapsedRealtime();
Jeff Sharkeyeba260d2015-04-19 14:35:16 -0700717 while (true) {
Kenny Root51a573c2012-05-17 13:30:28 -0700718 try {
719 if (latch.await(5000, TimeUnit.MILLISECONDS)) {
San Mehat207e5382010-02-04 20:46:54 -0800720 return;
Kenny Root51a573c2012-05-17 13:30:28 -0700721 } else {
722 Slog.w(TAG, "Thread " + Thread.currentThread().getName()
Jeff Sharkey48877892015-03-18 11:27:19 -0700723 + " still waiting for " + condition + "...");
San Mehat207e5382010-02-04 20:46:54 -0800724 }
Kenny Root51a573c2012-05-17 13:30:28 -0700725 } catch (InterruptedException e) {
Jeff Sharkeyeba260d2015-04-19 14:35:16 -0700726 Slog.w(TAG, "Interrupt while waiting for " + condition);
San Mehat207e5382010-02-04 20:46:54 -0800727 }
Jeff Sharkeyedcdaf62015-07-09 09:45:36 -0700728 if (timeoutMillis > 0 && SystemClock.elapsedRealtime() > startMillis + timeoutMillis) {
729 throw new TimeoutException("Thread " + Thread.currentThread().getName()
730 + " gave up waiting for " + condition + " after " + timeoutMillis + "ms");
731 }
San Mehat207e5382010-02-04 20:46:54 -0800732 }
San Mehat1f6301e2010-01-07 22:40:27 -0800733 }
Kenny Root02c87302010-07-01 08:10:18 -0700734
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700735 private void handleSystemReady() {
Jeff Sharkey8924e872015-11-30 12:52:10 -0700736 initIfReadyAndConnected();
Jeff Sharkey5a9bb742015-11-03 10:15:57 -0800737 resetIfReadyAndConnected();
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700738
Jeff Sharkey48877892015-03-18 11:27:19 -0700739 // Start scheduling nominally-daily fstrim operations
Christopher Tate115afda2014-06-06 19:06:26 -0700740 MountServiceIdler.scheduleIdlePass(mContext);
Daniel Colascione766b6322018-01-08 19:10:36 -0800741
742 // Toggle zram-enable system property in response to settings
743 mContext.getContentResolver().registerContentObserver(
744 Settings.Global.getUriFor(Settings.Global.ZRAM_ENABLED),
745 false /*notifyForDescendants*/,
746 new ContentObserver(null /* current thread */) {
747 @Override
748 public void onChange(boolean selfChange) {
749 refreshZramSettings();
750 }
751 });
752 refreshZramSettings();
753 }
754
755 /**
756 * Update the zram_enabled system property (which init reads to
757 * decide whether to enable zram) to reflect the zram_enabled
758 * preference (which we can change for experimentation purposes).
759 */
760 private void refreshZramSettings() {
761 String propertyValue = SystemProperties.get(ZRAM_ENABLED_PROPERTY);
762 if ("".equals(propertyValue)) {
763 return; // System doesn't have zram toggling support
764 }
765 String desiredPropertyValue =
766 Settings.Global.getInt(mContext.getContentResolver(),
767 Settings.Global.ZRAM_ENABLED,
768 1) != 0
769 ? "1" : "0";
770 if (!desiredPropertyValue.equals(propertyValue)) {
771 // Avoid redundant disk writes by setting only if we're
772 // changing the property value. There's no race: we're the
773 // sole writer.
774 SystemProperties.set(ZRAM_ENABLED_PROPERTY, desiredPropertyValue);
775 }
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700776 }
777
Jeff Sharkey14cbe522015-07-08 14:06:37 -0700778 /**
779 * MediaProvider has a ton of code that makes assumptions about storage
780 * paths never changing, so we outright kill them to pick up new state.
781 */
782 @Deprecated
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700783 private void killMediaProvider(List<UserInfo> users) {
784 if (users == null) return;
785
Jeff Sharkeyb3cf9532015-07-17 15:12:39 -0700786 final long token = Binder.clearCallingIdentity();
787 try {
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700788 for (UserInfo user : users) {
789 // System user does not have media provider, so skip.
790 if (user.isSystemOnly()) continue;
791
Jeff Sharkey2a9e3f82015-12-18 10:57:58 -0700792 final ProviderInfo provider = mPms.resolveContentProvider(MediaStore.AUTHORITY,
Jeff Sharkey8a372a02016-03-16 16:25:45 -0600793 PackageManager.MATCH_DIRECT_BOOT_AWARE
794 | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
795 user.id);
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700796 if (provider != null) {
Sudheer Shankadc589ac2016-11-10 15:30:17 -0800797 final IActivityManager am = ActivityManager.getService();
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700798 try {
Jeff Sharkey85f449e2016-06-23 09:26:00 -0600799 am.killApplication(provider.applicationInfo.packageName,
800 UserHandle.getAppId(provider.applicationInfo.uid),
801 UserHandle.USER_ALL, "vold reset");
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700802 // We only need to run this once. It will kill all users' media processes.
803 break;
804 } catch (RemoteException e) {
805 }
Jeff Sharkeyb3cf9532015-07-17 15:12:39 -0700806 }
Jeff Sharkey14cbe522015-07-08 14:06:37 -0700807 }
Jeff Sharkeyb3cf9532015-07-17 15:12:39 -0700808 } finally {
809 Binder.restoreCallingIdentity(token);
Jeff Sharkey14cbe522015-07-08 14:06:37 -0700810 }
811 }
812
Jeff Sharkey5a9bb742015-11-03 10:15:57 -0800813 private void addInternalVolumeLocked() {
Amith Yamasania7892482015-08-07 11:09:05 -0700814 // Create a stub volume that represents internal storage
815 final VolumeInfo internal = new VolumeInfo(VolumeInfo.ID_PRIVATE_INTERNAL,
816 VolumeInfo.TYPE_PRIVATE, null, null);
817 internal.state = VolumeInfo.STATE_MOUNTED;
818 internal.path = Environment.getDataDirectory().getAbsolutePath();
819 mVolumes.put(internal.id, internal);
820 }
821
Jeff Sharkey8924e872015-11-30 12:52:10 -0700822 private void initIfReadyAndConnected() {
823 Slog.d(TAG, "Thinking about init, mSystemReady=" + mSystemReady
824 + ", mDaemonConnected=" + mDaemonConnected);
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700825 if (mSystemReady && mDaemonConnected
Paul Lawrence20be5d62016-02-26 13:51:17 -0800826 && !StorageManager.isFileEncryptedNativeOnly()) {
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700827 // When booting a device without native support, make sure that our
828 // user directories are locked or unlocked based on the current
829 // emulation status.
Paul Lawrence20be5d62016-02-26 13:51:17 -0800830 final boolean initLocked = StorageManager.isFileEncryptedEmulatedOnly();
Paul Crowleyd94ab732016-02-15 06:44:51 +0000831 Slog.d(TAG, "Setting up emulation state, initlocked=" + initLocked);
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700832 final List<UserInfo> users = mContext.getSystemService(UserManager.class).getUsers();
Jeff Sharkey8924e872015-11-30 12:52:10 -0700833 for (UserInfo user : users) {
834 try {
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700835 if (initLocked) {
Jeff Sharkey54402792017-09-15 16:05:19 -0600836 mVold.lockUserKey(user.id);
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700837 } else {
Jeff Sharkey54402792017-09-15 16:05:19 -0600838 mVold.unlockUserKey(user.id, user.serialNumber, encodeBytes(null),
839 encodeBytes(null));
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700840 }
Jeff Sharkey43e12112017-09-12 16:31:45 -0600841 } catch (Exception e) {
842 Slog.wtf(TAG, e);
Jeff Sharkey8924e872015-11-30 12:52:10 -0700843 }
844 }
845 }
846 }
847
Jeff Sharkey5a9bb742015-11-03 10:15:57 -0800848 private void resetIfReadyAndConnected() {
Jeff Sharkey48877892015-03-18 11:27:19 -0700849 Slog.d(TAG, "Thinking about reset, mSystemReady=" + mSystemReady
850 + ", mDaemonConnected=" + mDaemonConnected);
851 if (mSystemReady && mDaemonConnected) {
Jeff Sharkey5a9bb742015-11-03 10:15:57 -0800852 final List<UserInfo> users = mContext.getSystemService(UserManager.class).getUsers();
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700853 killMediaProvider(users);
Jeff Sharkey14cbe522015-07-08 14:06:37 -0700854
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700855 final int[] systemUnlockedUsers;
Jeff Sharkey5a9bb742015-11-03 10:15:57 -0800856 synchronized (mLock) {
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700857 systemUnlockedUsers = mSystemUnlockedUsers;
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700858
Jeff Sharkey5a9bb742015-11-03 10:15:57 -0800859 mDisks.clear();
860 mVolumes.clear();
861
862 addInternalVolumeLocked();
863 }
Jeff Sharkey59d577a2015-04-11 21:27:21 -0700864
Jeff Sharkey48877892015-03-18 11:27:19 -0700865 try {
Jeff Sharkey54402792017-09-15 16:05:19 -0600866 mVold.reset();
Jeff Sharkeybcd262d2015-06-10 09:41:17 -0700867
868 // Tell vold about all existing and started users
Jeff Sharkeybcd262d2015-06-10 09:41:17 -0700869 for (UserInfo user : users) {
Jeff Sharkey54402792017-09-15 16:05:19 -0600870 mVold.onUserAdded(user.id, user.serialNumber);
Jeff Sharkeybcd262d2015-06-10 09:41:17 -0700871 }
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700872 for (int userId : systemUnlockedUsers) {
Jeff Sharkey54402792017-09-15 16:05:19 -0600873 mVold.onUserStarted(userId);
Jin Qian12690d52017-10-13 18:17:04 -0700874 mStoraged.onUserStarted(userId);
Jeff Sharkey50a05452015-04-29 11:24:52 -0700875 }
Jeff Sharkey9765e442017-12-14 22:15:14 -0700876 mVold.onSecureKeyguardStateChanged(mSecureKeyguardShowing);
Jeff Sharkeyace874b2017-09-07 15:27:33 -0600877 } catch (Exception e) {
878 Slog.wtf(TAG, e);
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700879 }
880 }
Jeff Sharkey48877892015-03-18 11:27:19 -0700881 }
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700882
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700883 private void onUnlockUser(int userId) {
884 Slog.d(TAG, "onUnlockUser " + userId);
Jeff Sharkey48877892015-03-18 11:27:19 -0700885
886 // We purposefully block here to make sure that user-specific
887 // staging area is ready so it's ready for zygote-forked apps to
888 // bind mount against.
889 try {
Jeff Sharkey54402792017-09-15 16:05:19 -0600890 mVold.onUserStarted(userId);
Jin Qian12690d52017-10-13 18:17:04 -0700891 mStoraged.onUserStarted(userId);
Jeff Sharkeyace874b2017-09-07 15:27:33 -0600892 } catch (Exception e) {
893 Slog.wtf(TAG, e);
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700894 }
Jeff Sharkey48877892015-03-18 11:27:19 -0700895
896 // Record user as started so newly mounted volumes kick off events
897 // correctly, then synthesize events for any already-mounted volumes.
yuanhuihuiefd1f122016-07-13 21:21:03 +0800898 synchronized (mLock) {
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -0700899 for (int i = 0; i < mVolumes.size(); i++) {
900 final VolumeInfo vol = mVolumes.valueAt(i);
Jeff Sharkey46349872015-07-28 10:49:47 -0700901 if (vol.isVisibleForRead(userId) && vol.isMountedReadable()) {
Svet Ganov6ee871e2015-07-10 14:29:33 -0700902 final StorageVolume userVol = vol.buildStorageVolume(mContext, userId, false);
Jeff Sharkey48877892015-03-18 11:27:19 -0700903 mHandler.obtainMessage(H_VOLUME_BROADCAST, userVol).sendToTarget();
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700904
Jeff Sharkey27de30d2015-04-18 16:20:27 -0700905 final String envState = VolumeInfo.getEnvironmentForState(vol.getState());
906 mCallbacks.notifyStorageStateChanged(userVol.getPath(), envState, envState);
Jeff Sharkey48877892015-03-18 11:27:19 -0700907 }
908 }
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700909 mSystemUnlockedUsers = ArrayUtils.appendInt(mSystemUnlockedUsers, userId);
Jeff Sharkey48877892015-03-18 11:27:19 -0700910 }
911 }
912
913 private void onCleanupUser(int userId) {
914 Slog.d(TAG, "onCleanupUser " + userId);
915
916 try {
Jeff Sharkey54402792017-09-15 16:05:19 -0600917 mVold.onUserStopped(userId);
Jin Qian12690d52017-10-13 18:17:04 -0700918 mStoraged.onUserStopped(userId);
Jeff Sharkeyace874b2017-09-07 15:27:33 -0600919 } catch (Exception e) {
920 Slog.wtf(TAG, e);
Jeff Sharkey48877892015-03-18 11:27:19 -0700921 }
922
yuanhuihuiefd1f122016-07-13 21:21:03 +0800923 synchronized (mLock) {
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700924 mSystemUnlockedUsers = ArrayUtils.removeInt(mSystemUnlockedUsers, userId);
Jeff Sharkey48877892015-03-18 11:27:19 -0700925 }
926 }
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700927
Jeff Sharkey9765e442017-12-14 22:15:14 -0700928 @Override
929 public void onAwakeStateChanged(boolean isAwake) {
930 // Ignored
931 }
932
933 @Override
934 public void onKeyguardStateChanged(boolean isShowing) {
935 // Push down current secure keyguard status so that we ignore malicious
936 // USB devices while locked.
937 mSecureKeyguardShowing = isShowing
938 && mContext.getSystemService(KeyguardManager.class).isDeviceSecure();
939 try {
940 mVold.onSecureKeyguardStateChanged(mSecureKeyguardShowing);
941 } catch (Exception e) {
942 Slog.wtf(TAG, e);
943 }
944 }
945
Christopher Tated417d622013-08-19 16:14:25 -0700946 void runIdleMaintenance(Runnable callback) {
947 mHandler.sendMessage(mHandler.obtainMessage(H_FSTRIM, callback));
948 }
949
Christopher Tate7265abe2014-11-21 13:54:45 -0800950 // Binder entry point for kicking off an immediate fstrim
951 @Override
952 public void runMaintenance() {
Jeff Sharkey48877892015-03-18 11:27:19 -0700953 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
Christopher Tate7265abe2014-11-21 13:54:45 -0800954 runIdleMaintenance(null);
955 }
956
957 @Override
958 public long lastMaintenance() {
959 return mLastMaintenance;
960 }
961
San Mehat4270e1e2010-01-29 05:32:19 -0800962 public void onDaemonConnected() {
Jeff Sharkey48877892015-03-18 11:27:19 -0700963 mDaemonConnected = true;
964 mHandler.obtainMessage(H_DAEMON_CONNECTED).sendToTarget();
965 }
966
967 private void handleDaemonConnected() {
Jeff Sharkey8924e872015-11-30 12:52:10 -0700968 initIfReadyAndConnected();
Jeff Sharkey5a9bb742015-11-03 10:15:57 -0800969 resetIfReadyAndConnected();
Jeff Sharkey48877892015-03-18 11:27:19 -0700970
Jeff Sharkey48877892015-03-18 11:27:19 -0700971 // On an encrypted device we can't see system properties yet, so pull
972 // the system locale out of the mount service.
973 if ("".equals(SystemProperties.get("vold.encrypt_progress"))) {
974 copyLocaleFromMountService();
975 }
San Mehat4270e1e2010-01-29 05:32:19 -0800976 }
977
Elliott Hughesf839b4f2014-09-26 12:30:47 -0700978 private void copyLocaleFromMountService() {
979 String systemLocale;
980 try {
981 systemLocale = getField(StorageManager.SYSTEM_LOCALE_KEY);
982 } catch (RemoteException e) {
983 return;
984 }
985 if (TextUtils.isEmpty(systemLocale)) {
986 return;
987 }
988
989 Slog.d(TAG, "Got locale " + systemLocale + " from mount service");
990 Locale locale = Locale.forLanguageTag(systemLocale);
991 Configuration config = new Configuration();
992 config.setLocale(locale);
993 try {
Sudheer Shankadc589ac2016-11-10 15:30:17 -0800994 ActivityManager.getService().updatePersistentConfiguration(config);
Elliott Hughesf839b4f2014-09-26 12:30:47 -0700995 } catch (RemoteException e) {
996 Slog.e(TAG, "Error setting system locale from mount service", e);
997 }
Elliott Hughes9c33f282014-10-13 12:39:56 -0700998
999 // Temporary workaround for http://b/17945169.
1000 Slog.d(TAG, "Setting system properties to " + systemLocale + " from mount service");
Narayan Kamathd30dbb82015-01-15 14:48:15 +00001001 SystemProperties.set("persist.sys.locale", locale.toLanguageTag());
Elliott Hughesf839b4f2014-09-26 12:30:47 -07001002 }
1003
Jeff Sharkey8058fe62017-09-13 11:50:33 -06001004 private final IVoldListener mListener = new IVoldListener.Stub() {
1005 @Override
1006 public void onDiskCreated(String diskId, int flags) {
1007 synchronized (mLock) {
1008 if (SystemProperties.getBoolean(StorageManager.PROP_FORCE_ADOPTABLE, false)
1009 || mForceAdoptable) {
1010 flags |= DiskInfo.FLAG_ADOPTABLE;
1011 }
Jeff Sharkey8058fe62017-09-13 11:50:33 -06001012 mDisks.put(diskId, new DiskInfo(diskId, flags));
1013 }
1014 }
1015
1016 @Override
1017 public void onDiskScanned(String diskId) {
1018 synchronized (mLock) {
1019 final DiskInfo disk = mDisks.get(diskId);
1020 if (disk != null) {
1021 onDiskScannedLocked(disk);
1022 }
1023 }
1024 }
1025
1026 @Override
1027 public void onDiskMetadataChanged(String diskId, long sizeBytes, String label,
1028 String sysPath) {
1029 synchronized (mLock) {
1030 final DiskInfo disk = mDisks.get(diskId);
1031 if (disk != null) {
1032 disk.size = sizeBytes;
1033 disk.label = label;
1034 disk.sysPath = sysPath;
1035 }
1036 }
1037 }
1038
1039 @Override
1040 public void onDiskDestroyed(String diskId) {
1041 synchronized (mLock) {
1042 final DiskInfo disk = mDisks.remove(diskId);
1043 if (disk != null) {
1044 mCallbacks.notifyDiskDestroyed(disk);
1045 }
1046 }
1047 }
1048
1049 @Override
1050 public void onVolumeCreated(String volId, int type, String diskId, String partGuid) {
1051 synchronized (mLock) {
1052 final DiskInfo disk = mDisks.get(diskId);
1053 final VolumeInfo vol = new VolumeInfo(volId, type, disk, partGuid);
1054 mVolumes.put(volId, vol);
1055 onVolumeCreatedLocked(vol);
1056 }
1057 }
1058
1059 @Override
1060 public void onVolumeStateChanged(String volId, int state) {
1061 synchronized (mLock) {
1062 final VolumeInfo vol = mVolumes.get(volId);
1063 if (vol != null) {
1064 final int oldState = vol.state;
1065 final int newState = state;
1066 vol.state = newState;
1067 onVolumeStateChangedLocked(vol, oldState, newState);
1068 }
1069 }
1070 }
1071
1072 @Override
1073 public void onVolumeMetadataChanged(String volId, String fsType, String fsUuid,
1074 String fsLabel) {
1075 synchronized (mLock) {
1076 final VolumeInfo vol = mVolumes.get(volId);
1077 if (vol != null) {
1078 vol.fsType = fsType;
1079 vol.fsUuid = fsUuid;
1080 vol.fsLabel = fsLabel;
1081 }
1082 }
1083 }
1084
1085 @Override
1086 public void onVolumePathChanged(String volId, String path) {
1087 synchronized (mLock) {
1088 final VolumeInfo vol = mVolumes.get(volId);
1089 if (vol != null) {
1090 vol.path = path;
1091 }
1092 }
1093 }
1094
1095 @Override
1096 public void onVolumeInternalPathChanged(String volId, String internalPath) {
1097 synchronized (mLock) {
1098 final VolumeInfo vol = mVolumes.get(volId);
1099 if (vol != null) {
1100 vol.internalPath = internalPath;
1101 }
1102 }
1103 }
1104
1105 @Override
1106 public void onVolumeDestroyed(String volId) {
1107 synchronized (mLock) {
1108 mVolumes.remove(volId);
1109 }
1110 }
1111 };
1112
Jeff Sharkeyeba260d2015-04-19 14:35:16 -07001113 private void onDiskScannedLocked(DiskInfo disk) {
Jeff Sharkey620b32b2015-04-23 19:36:02 -07001114 int volumeCount = 0;
Jeff Sharkeyeba260d2015-04-19 14:35:16 -07001115 for (int i = 0; i < mVolumes.size(); i++) {
1116 final VolumeInfo vol = mVolumes.valueAt(i);
1117 if (Objects.equals(disk.id, vol.getDiskId())) {
Jeff Sharkey620b32b2015-04-23 19:36:02 -07001118 volumeCount++;
Jeff Sharkeyeba260d2015-04-19 14:35:16 -07001119 }
1120 }
1121
Jeff Sharkeyc7acac62015-06-12 16:16:56 -07001122 final Intent intent = new Intent(DiskInfo.ACTION_DISK_SCANNED);
Jeff Sharkey7732e1e2016-03-30 17:14:23 -06001123 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT
1124 | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
Jeff Sharkeyc7acac62015-06-12 16:16:56 -07001125 intent.putExtra(DiskInfo.EXTRA_DISK_ID, disk.id);
1126 intent.putExtra(DiskInfo.EXTRA_VOLUME_COUNT, volumeCount);
Jeff Sharkeyabc3e852015-08-03 14:41:13 -07001127 mHandler.obtainMessage(H_INTERNAL_BROADCAST, intent).sendToTarget();
Jeff Sharkeyc7acac62015-06-12 16:16:56 -07001128
1129 final CountDownLatch latch = mDiskScanLatches.remove(disk.id);
1130 if (latch != null) {
1131 latch.countDown();
1132 }
1133
Jeff Sharkeyf5a6bd72015-05-19 14:42:38 -07001134 disk.volumeCount = volumeCount;
Jeff Sharkey620b32b2015-04-23 19:36:02 -07001135 mCallbacks.notifyDiskScanned(disk, volumeCount);
Jeff Sharkeyeba260d2015-04-19 14:35:16 -07001136 }
1137
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07001138 private void onVolumeCreatedLocked(VolumeInfo vol) {
Jeff Sharkey6855c482016-03-31 14:34:38 -06001139 if (mPms.isOnlyCoreApps()) {
1140 Slog.d(TAG, "System booted in core-only mode; ignoring volume " + vol.getId());
1141 return;
1142 }
1143
Jeff Sharkey275e3e42015-04-24 16:10:32 -07001144 if (vol.type == VolumeInfo.TYPE_EMULATED) {
1145 final StorageManager storage = mContext.getSystemService(StorageManager.class);
1146 final VolumeInfo privateVol = storage.findPrivateForEmulated(vol);
1147
1148 if (Objects.equals(StorageManager.UUID_PRIVATE_INTERNAL, mPrimaryStorageUuid)
1149 && VolumeInfo.ID_PRIVATE_INTERNAL.equals(privateVol.id)) {
1150 Slog.v(TAG, "Found primary storage at " + vol);
1151 vol.mountFlags |= VolumeInfo.MOUNT_FLAG_PRIMARY;
1152 vol.mountFlags |= VolumeInfo.MOUNT_FLAG_VISIBLE;
1153 mHandler.obtainMessage(H_VOLUME_MOUNT, vol).sendToTarget();
1154
1155 } else if (Objects.equals(privateVol.fsUuid, mPrimaryStorageUuid)) {
1156 Slog.v(TAG, "Found primary storage at " + vol);
1157 vol.mountFlags |= VolumeInfo.MOUNT_FLAG_PRIMARY;
1158 vol.mountFlags |= VolumeInfo.MOUNT_FLAG_VISIBLE;
1159 mHandler.obtainMessage(H_VOLUME_MOUNT, vol).sendToTarget();
1160 }
Jeff Sharkeyb049e212012-09-07 23:16:01 -07001161
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07001162 } else if (vol.type == VolumeInfo.TYPE_PUBLIC) {
Jeff Sharkey275e3e42015-04-24 16:10:32 -07001163 // TODO: only look at first public partition
1164 if (Objects.equals(StorageManager.UUID_PRIMARY_PHYSICAL, mPrimaryStorageUuid)
1165 && vol.disk.isDefaultPrimary()) {
1166 Slog.v(TAG, "Found primary storage at " + vol);
Jeff Sharkey7e92ef32015-04-17 17:35:07 -07001167 vol.mountFlags |= VolumeInfo.MOUNT_FLAG_PRIMARY;
1168 vol.mountFlags |= VolumeInfo.MOUNT_FLAG_VISIBLE;
San Mehat4270e1e2010-01-29 05:32:19 -08001169 }
Jeff Sharkey7e92ef32015-04-17 17:35:07 -07001170
1171 // Adoptable public disks are visible to apps, since they meet
1172 // public API requirement of being in a stable location.
Jeff Sharkey275e3e42015-04-24 16:10:32 -07001173 if (vol.disk.isAdoptable()) {
Jeff Sharkey7e92ef32015-04-17 17:35:07 -07001174 vol.mountFlags |= VolumeInfo.MOUNT_FLAG_VISIBLE;
1175 }
1176
Jeff Sharkeyab15c392016-05-05 11:45:01 -06001177 vol.mountUserId = mCurrentUserId;
Jeff Sharkey48877892015-03-18 11:27:19 -07001178 mHandler.obtainMessage(H_VOLUME_MOUNT, vol).sendToTarget();
San Mehat4270e1e2010-01-29 05:32:19 -08001179
Jeff Sharkeyb2b9ab82015-04-05 21:10:42 -07001180 } else if (vol.type == VolumeInfo.TYPE_PRIVATE) {
1181 mHandler.obtainMessage(H_VOLUME_MOUNT, vol).sendToTarget();
1182
San Mehat4270e1e2010-01-29 05:32:19 -08001183 } else {
Jeff Sharkey48877892015-03-18 11:27:19 -07001184 Slog.d(TAG, "Skipping automatic mounting of " + vol);
San Mehat4270e1e2010-01-29 05:32:19 -08001185 }
1186 }
1187
Jeff Sharkeye6c04f92015-04-18 21:38:05 -07001188 private boolean isBroadcastWorthy(VolumeInfo vol) {
1189 switch (vol.getType()) {
Jeff Sharkeyc7acac62015-06-12 16:16:56 -07001190 case VolumeInfo.TYPE_PRIVATE:
Jeff Sharkeye6c04f92015-04-18 21:38:05 -07001191 case VolumeInfo.TYPE_PUBLIC:
1192 case VolumeInfo.TYPE_EMULATED:
1193 break;
1194 default:
1195 return false;
1196 }
1197
1198 switch (vol.getState()) {
1199 case VolumeInfo.STATE_MOUNTED:
1200 case VolumeInfo.STATE_MOUNTED_READ_ONLY:
1201 case VolumeInfo.STATE_EJECTING:
1202 case VolumeInfo.STATE_UNMOUNTED:
Jeff Sharkeyc7acac62015-06-12 16:16:56 -07001203 case VolumeInfo.STATE_UNMOUNTABLE:
Tony Mantlerf0d71052015-06-24 11:45:25 -07001204 case VolumeInfo.STATE_BAD_REMOVAL:
Jeff Sharkeye6c04f92015-04-18 21:38:05 -07001205 break;
1206 default:
1207 return false;
1208 }
1209
1210 return true;
1211 }
1212
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07001213 private void onVolumeStateChangedLocked(VolumeInfo vol, int oldState, int newState) {
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001214 // Remember that we saw this volume so we're ready to accept user
1215 // metadata, or so we can annoy them when a private volume is ejected
1216 if (vol.isMountedReadable() && !TextUtils.isEmpty(vol.fsUuid)) {
Jeff Sharkey5cc0df22015-06-17 19:44:05 -07001217 VolumeRecord rec = mRecords.get(vol.fsUuid);
1218 if (rec == null) {
1219 rec = new VolumeRecord(vol.type, vol.fsUuid);
1220 rec.partGuid = vol.partGuid;
Jeff Sharkeye8a4b662015-06-27 15:43:45 -07001221 rec.createdMillis = System.currentTimeMillis();
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001222 if (vol.type == VolumeInfo.TYPE_PRIVATE) {
1223 rec.nickname = vol.disk.getDescription();
1224 }
1225 mRecords.put(rec.fsUuid, rec);
1226 writeSettingsLocked();
Jeff Sharkey5cc0df22015-06-17 19:44:05 -07001227 } else {
1228 // Handle upgrade case where we didn't store partition GUID
1229 if (TextUtils.isEmpty(rec.partGuid)) {
1230 rec.partGuid = vol.partGuid;
1231 writeSettingsLocked();
1232 }
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001233 }
1234 }
1235
Jeff Sharkeye6c04f92015-04-18 21:38:05 -07001236 mCallbacks.notifyVolumeStateChanged(vol, oldState, newState);
1237
Yasuhiro Matsuda87a38b52015-07-24 22:10:16 +09001238 // Do not broadcast before boot has completed to avoid launching the
1239 // processes that receive the intent unnecessarily.
1240 if (mBootCompleted && isBroadcastWorthy(vol)) {
Jeff Sharkeye6c04f92015-04-18 21:38:05 -07001241 final Intent intent = new Intent(VolumeInfo.ACTION_VOLUME_STATE_CHANGED);
Jeff Sharkeyc7acac62015-06-12 16:16:56 -07001242 intent.putExtra(VolumeInfo.EXTRA_VOLUME_ID, vol.id);
1243 intent.putExtra(VolumeInfo.EXTRA_VOLUME_STATE, newState);
Tony Mantlerf0d71052015-06-24 11:45:25 -07001244 intent.putExtra(VolumeRecord.EXTRA_FS_UUID, vol.fsUuid);
Jeff Sharkey7732e1e2016-03-30 17:14:23 -06001245 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT
1246 | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
Jeff Sharkeyabc3e852015-08-03 14:41:13 -07001247 mHandler.obtainMessage(H_INTERNAL_BROADCAST, intent).sendToTarget();
Jeff Sharkeye6c04f92015-04-18 21:38:05 -07001248 }
Jeff Sharkeyb049e212012-09-07 23:16:01 -07001249
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001250 final String oldStateEnv = VolumeInfo.getEnvironmentForState(oldState);
1251 final String newStateEnv = VolumeInfo.getEnvironmentForState(newState);
Emily Bernier92aa5a22014-07-07 10:11:48 -04001252
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001253 if (!Objects.equals(oldStateEnv, newStateEnv)) {
1254 // Kick state changed event towards all started users. Any users
1255 // started after this point will trigger additional
1256 // user-specific broadcasts.
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07001257 for (int userId : mSystemUnlockedUsers) {
Jeff Sharkey46349872015-07-28 10:49:47 -07001258 if (vol.isVisibleForRead(userId)) {
Svet Ganov6ee871e2015-07-10 14:29:33 -07001259 final StorageVolume userVol = vol.buildStorageVolume(mContext, userId, false);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001260 mHandler.obtainMessage(H_VOLUME_BROADCAST, userVol).sendToTarget();
Jeff Sharkey48877892015-03-18 11:27:19 -07001261
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001262 mCallbacks.notifyStorageStateChanged(userVol.getPath(), oldStateEnv,
1263 newStateEnv);
San Mehat4270e1e2010-01-29 05:32:19 -08001264 }
1265 }
1266 }
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001267
Jeff Sharkey7e92ef32015-04-17 17:35:07 -07001268 if (vol.type == VolumeInfo.TYPE_PUBLIC && vol.state == VolumeInfo.STATE_EJECTING) {
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001269 // TODO: this should eventually be handled by new ObbVolume state changes
1270 /*
1271 * Some OBBs might have been unmounted when this volume was
1272 * unmounted, so send a message to the handler to let it know to
1273 * remove those from the list of mounted OBBS.
1274 */
1275 mObbActionHandler.sendMessage(mObbActionHandler.obtainMessage(
1276 OBB_FLUSH_MOUNT_STATE, vol.path));
1277 }
San Mehat4270e1e2010-01-29 05:32:19 -08001278 }
1279
Jeff Sharkey275e3e42015-04-24 16:10:32 -07001280 private void onMoveStatusLocked(int status) {
1281 if (mMoveCallback == null) {
1282 Slog.w(TAG, "Odd, status but no move requested");
1283 return;
1284 }
1285
1286 // TODO: estimate remaining time
1287 try {
Jeff Sharkey50a05452015-04-29 11:24:52 -07001288 mMoveCallback.onStatusChanged(-1, status, -1);
Jeff Sharkey275e3e42015-04-24 16:10:32 -07001289 } catch (RemoteException ignored) {
1290 }
1291
1292 // We've finished copying and we're about to clean up old data, so
1293 // remember that move was successful if we get rebooted
1294 if (status == MOVE_STATUS_COPY_FINISHED) {
1295 Slog.d(TAG, "Move to " + mMoveTargetUuid + " copy phase finshed; persisting");
1296
1297 mPrimaryStorageUuid = mMoveTargetUuid;
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001298 writeSettingsLocked();
Jeff Sharkey275e3e42015-04-24 16:10:32 -07001299 }
1300
1301 if (PackageManager.isMoveStatusFinished(status)) {
1302 Slog.d(TAG, "Move to " + mMoveTargetUuid + " finished with status " + status);
1303
1304 mMoveCallback = null;
1305 mMoveTargetUuid = null;
1306 }
1307 }
1308
Jeff Sharkey48877892015-03-18 11:27:19 -07001309 private void enforcePermission(String perm) {
1310 mContext.enforceCallingOrSelfPermission(perm, perm);
Mike Lockwooda5250c92011-05-23 13:44:04 -04001311 }
1312
Jeff Sharkey2e606d72015-07-27 14:19:54 -07001313 /**
1314 * Decide if volume is mountable per device policies.
1315 */
1316 private boolean isMountDisallowed(VolumeInfo vol) {
Philip P. Moltmannec3cbb22016-09-14 13:24:52 -07001317 UserManager userManager = mContext.getSystemService(UserManager.class);
1318
1319 boolean isUsbRestricted = false;
1320 if (vol.disk != null && vol.disk.isUsb()) {
1321 isUsbRestricted = userManager.hasUserRestriction(UserManager.DISALLOW_USB_FILE_TRANSFER,
Jeff Sharkey2e606d72015-07-27 14:19:54 -07001322 Binder.getCallingUserHandle());
Emily Bernier92aa5a22014-07-07 10:11:48 -04001323 }
Philip P. Moltmannec3cbb22016-09-14 13:24:52 -07001324
1325 boolean isTypeRestricted = false;
1326 if (vol.type == VolumeInfo.TYPE_PUBLIC || vol.type == VolumeInfo.TYPE_PRIVATE) {
1327 isTypeRestricted = userManager
1328 .hasUserRestriction(UserManager.DISALLOW_MOUNT_PHYSICAL_MEDIA,
1329 Binder.getCallingUserHandle());
1330 }
1331
1332 return isUsbRestricted || isTypeRestricted;
Emily Bernier92aa5a22014-07-07 10:11:48 -04001333 }
1334
Amith Yamasani462ac3a2015-06-30 14:21:01 -07001335 private void enforceAdminUser() {
1336 UserManager um = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
1337 final int callingUserId = UserHandle.getCallingUserId();
1338 boolean isAdmin;
1339 long token = Binder.clearCallingIdentity();
1340 try {
1341 isAdmin = um.getUserInfo(callingUserId).isAdmin();
1342 } finally {
1343 Binder.restoreCallingIdentity(token);
1344 }
1345 if (!isAdmin) {
1346 throw new SecurityException("Only admin users can adopt sd cards");
1347 }
1348 }
1349
Jeff Sharkeyb049e212012-09-07 23:16:01 -07001350 /**
Sudheer Shanka2250d562016-11-07 15:41:02 -08001351 * Constructs a new StorageManagerService instance
San Mehat207e5382010-02-04 20:46:54 -08001352 *
1353 * @param context Binder context for this service
1354 */
Sudheer Shanka2250d562016-11-07 15:41:02 -08001355 public StorageManagerService(Context context) {
Christopher Tated417d622013-08-19 16:14:25 -07001356 sSelf = this;
1357
San Mehat207e5382010-02-04 20:46:54 -08001358 mContext = context;
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001359 mCallbacks = new Callbacks(FgThread.get().getLooper());
Jeff Sharkeyb9fe5372015-12-03 15:23:08 -07001360 mLockPatternUtils = new LockPatternUtils(mContext);
San Mehat207e5382010-02-04 20:46:54 -08001361
San Mehat207e5382010-02-04 20:46:54 -08001362 // XXX: This will go away soon in favor of IMountServiceObserver
1363 mPms = (PackageManagerService) ServiceManager.getService("package");
1364
Dianne Hackbornefa92b22013-05-03 14:11:43 -07001365 HandlerThread hthread = new HandlerThread(TAG);
1366 hthread.start();
Sudheer Shanka2250d562016-11-07 15:41:02 -08001367 mHandler = new StorageManagerServiceHandler(hthread.getLooper());
Daniel Sandler5f27ef42010-03-16 15:42:02 -04001368
Sudheer Shanka2250d562016-11-07 15:41:02 -08001369 // Add OBB Action Handler to StorageManagerService thread.
Dianne Hackborn8d044e82013-04-30 17:24:15 -07001370 mObbActionHandler = new ObbActionHandler(IoThread.get().getLooper());
Kenny Roota02b8b02010-08-05 16:14:17 -07001371
Christopher Tate7265abe2014-11-21 13:54:45 -08001372 // Initialize the last-fstrim tracking if necessary
1373 File dataDir = Environment.getDataDirectory();
1374 File systemDir = new File(dataDir, "system");
1375 mLastMaintenanceFile = new File(systemDir, LAST_FSTRIM_FILE);
1376 if (!mLastMaintenanceFile.exists()) {
1377 // Not setting mLastMaintenance here means that we will force an
1378 // fstrim during reboot following the OTA that installs this code.
1379 try {
1380 (new FileOutputStream(mLastMaintenanceFile)).close();
1381 } catch (IOException e) {
1382 Slog.e(TAG, "Unable to create fstrim record " + mLastMaintenanceFile.getPath());
1383 }
1384 } else {
1385 mLastMaintenance = mLastMaintenanceFile.lastModified();
1386 }
1387
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001388 mSettingsFile = new AtomicFile(
Jeff Sharkey8212ae02016-02-10 14:46:43 -07001389 new File(Environment.getDataSystemDirectory(), "storage.xml"));
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001390
1391 synchronized (mLock) {
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001392 readSettingsLocked();
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001393 }
1394
Sudheer Shanka2250d562016-11-07 15:41:02 -08001395 LocalServices.addService(StorageManagerInternal.class, mStorageManagerInternal);
Svet Ganov6ee871e2015-07-10 14:29:33 -07001396
Jeff Sharkeybcd262d2015-06-10 09:41:17 -07001397 final IntentFilter userFilter = new IntentFilter();
1398 userFilter.addAction(Intent.ACTION_USER_ADDED);
1399 userFilter.addAction(Intent.ACTION_USER_REMOVED);
1400 mContext.registerReceiver(mUserReceiver, userFilter, null, mHandler);
1401
Jeff Sharkey5a9bb742015-11-03 10:15:57 -08001402 synchronized (mLock) {
1403 addInternalVolumeLocked();
1404 }
Amith Yamasania7892482015-08-07 11:09:05 -07001405
Kenny Root07714d42011-08-17 17:49:28 -07001406 // Add ourself to the Watchdog monitors if enabled.
1407 if (WATCHDOG_ENABLE) {
1408 Watchdog.getInstance().addMonitor(this);
1409 }
San Mehat207e5382010-02-04 20:46:54 -08001410 }
1411
Jeff Sharkeycd575992016-03-29 14:12:49 -06001412 private void start() {
Jeff Sharkey1019de92017-09-06 13:47:03 -06001413 connect();
Jeff Sharkeycd575992016-03-29 14:12:49 -06001414 }
1415
Jeff Sharkey1019de92017-09-06 13:47:03 -06001416 private void connect() {
Jin Qian12690d52017-10-13 18:17:04 -07001417 IBinder binder = ServiceManager.getService("storaged");
1418 if (binder != null) {
1419 try {
1420 binder.linkToDeath(new DeathRecipient() {
1421 @Override
1422 public void binderDied() {
1423 Slog.w(TAG, "storaged died; reconnecting");
1424 mStoraged = null;
1425 connect();
1426 }
1427 }, 0);
1428 } catch (RemoteException e) {
1429 binder = null;
1430 }
1431 }
1432
1433 if (binder != null) {
1434 mStoraged = IStoraged.Stub.asInterface(binder);
1435 } else {
1436 Slog.w(TAG, "storaged not found; trying again");
1437 }
1438
1439 binder = ServiceManager.getService("vold");
Jeff Sharkey1019de92017-09-06 13:47:03 -06001440 if (binder != null) {
1441 try {
1442 binder.linkToDeath(new DeathRecipient() {
1443 @Override
1444 public void binderDied() {
1445 Slog.w(TAG, "vold died; reconnecting");
Jin Qian12690d52017-10-13 18:17:04 -07001446 mVold = null;
Jeff Sharkey1019de92017-09-06 13:47:03 -06001447 connect();
1448 }
1449 }, 0);
1450 } catch (RemoteException e) {
1451 binder = null;
1452 }
1453 }
1454
1455 if (binder != null) {
1456 mVold = IVold.Stub.asInterface(binder);
Jeff Sharkey8058fe62017-09-13 11:50:33 -06001457 try {
1458 mVold.setListener(mListener);
Jeff Sharkey8058fe62017-09-13 11:50:33 -06001459 } catch (RemoteException e) {
Jin Qian12690d52017-10-13 18:17:04 -07001460 mVold = null;
Jeff Sharkey8058fe62017-09-13 11:50:33 -06001461 Slog.w(TAG, "vold listener rejected; trying again", e);
1462 }
Jeff Sharkey1019de92017-09-06 13:47:03 -06001463 } else {
1464 Slog.w(TAG, "vold not found; trying again");
Jeff Sharkey1019de92017-09-06 13:47:03 -06001465 }
Jeff Sharkey8058fe62017-09-13 11:50:33 -06001466
Jin Qian12690d52017-10-13 18:17:04 -07001467 if (mStoraged == null || mVold == null) {
1468 BackgroundThread.getHandler().postDelayed(() -> {
1469 connect();
1470 }, DateUtils.SECOND_IN_MILLIS);
1471 } else {
1472 onDaemonConnected();
1473 }
Jeff Sharkey1019de92017-09-06 13:47:03 -06001474 }
1475
Jeff Sharkey56e62932015-03-21 20:41:00 -07001476 private void systemReady() {
Jeff Sharkey9765e442017-12-14 22:15:14 -07001477 LocalServices.getService(ActivityManagerInternal.class)
1478 .registerScreenObserver(this);
1479
Jeff Sharkeyb049e212012-09-07 23:16:01 -07001480 mSystemReady = true;
1481 mHandler.obtainMessage(H_SYSTEM_READY).sendToTarget();
1482 }
1483
Yasuhiro Matsuda87a38b52015-07-24 22:10:16 +09001484 private void bootCompleted() {
1485 mBootCompleted = true;
1486 }
1487
Jeff Sharkeyfced5342015-05-10 14:53:34 -07001488 private String getDefaultPrimaryStorageUuid() {
1489 if (SystemProperties.getBoolean(StorageManager.PROP_PRIMARY_PHYSICAL, false)) {
1490 return StorageManager.UUID_PRIMARY_PHYSICAL;
1491 } else {
1492 return StorageManager.UUID_PRIVATE_INTERNAL;
1493 }
1494 }
1495
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001496 private void readSettingsLocked() {
1497 mRecords.clear();
Jeff Sharkeyfced5342015-05-10 14:53:34 -07001498 mPrimaryStorageUuid = getDefaultPrimaryStorageUuid();
Jeff Sharkey4c099d02015-05-15 13:45:00 -07001499 mForceAdoptable = false;
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001500
1501 FileInputStream fis = null;
1502 try {
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001503 fis = mSettingsFile.openRead();
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001504 final XmlPullParser in = Xml.newPullParser();
Wojciech Staszkiewicz9e9e2e72015-05-08 14:58:46 +01001505 in.setInput(fis, StandardCharsets.UTF_8.name());
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001506
1507 int type;
1508 while ((type = in.next()) != END_DOCUMENT) {
1509 if (type == START_TAG) {
1510 final String tag = in.getName();
Jeff Sharkey620b32b2015-04-23 19:36:02 -07001511 if (TAG_VOLUMES.equals(tag)) {
1512 final int version = readIntAttribute(in, ATTR_VERSION, VERSION_INIT);
Jeff Sharkeyfced5342015-05-10 14:53:34 -07001513 final boolean primaryPhysical = SystemProperties.getBoolean(
1514 StorageManager.PROP_PRIMARY_PHYSICAL, false);
1515 final boolean validAttr = (version >= VERSION_FIX_PRIMARY)
1516 || (version >= VERSION_ADD_PRIMARY && !primaryPhysical);
1517 if (validAttr) {
Jeff Sharkey620b32b2015-04-23 19:36:02 -07001518 mPrimaryStorageUuid = readStringAttribute(in,
1519 ATTR_PRIMARY_STORAGE_UUID);
Jeff Sharkey620b32b2015-04-23 19:36:02 -07001520 }
Jeff Sharkey4c099d02015-05-15 13:45:00 -07001521 mForceAdoptable = readBooleanAttribute(in, ATTR_FORCE_ADOPTABLE, false);
Jeff Sharkey620b32b2015-04-23 19:36:02 -07001522
1523 } else if (TAG_VOLUME.equals(tag)) {
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001524 final VolumeRecord rec = readVolumeRecord(in);
1525 mRecords.put(rec.fsUuid, rec);
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001526 }
1527 }
1528 }
1529 } catch (FileNotFoundException e) {
1530 // Missing metadata is okay, probably first boot
1531 } catch (IOException e) {
1532 Slog.wtf(TAG, "Failed reading metadata", e);
1533 } catch (XmlPullParserException e) {
1534 Slog.wtf(TAG, "Failed reading metadata", e);
1535 } finally {
1536 IoUtils.closeQuietly(fis);
1537 }
1538 }
1539
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001540 private void writeSettingsLocked() {
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001541 FileOutputStream fos = null;
1542 try {
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001543 fos = mSettingsFile.startWrite();
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001544
1545 XmlSerializer out = new FastXmlSerializer();
Wojciech Staszkiewicz9e9e2e72015-05-08 14:58:46 +01001546 out.setOutput(fos, StandardCharsets.UTF_8.name());
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001547 out.startDocument(null, true);
1548 out.startTag(null, TAG_VOLUMES);
Jeff Sharkeyfced5342015-05-10 14:53:34 -07001549 writeIntAttribute(out, ATTR_VERSION, VERSION_FIX_PRIMARY);
Jeff Sharkey620b32b2015-04-23 19:36:02 -07001550 writeStringAttribute(out, ATTR_PRIMARY_STORAGE_UUID, mPrimaryStorageUuid);
Jeff Sharkey4c099d02015-05-15 13:45:00 -07001551 writeBooleanAttribute(out, ATTR_FORCE_ADOPTABLE, mForceAdoptable);
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001552 final int size = mRecords.size();
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001553 for (int i = 0; i < size; i++) {
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001554 final VolumeRecord rec = mRecords.valueAt(i);
1555 writeVolumeRecord(out, rec);
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001556 }
1557 out.endTag(null, TAG_VOLUMES);
1558 out.endDocument();
1559
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001560 mSettingsFile.finishWrite(fos);
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001561 } catch (IOException e) {
1562 if (fos != null) {
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001563 mSettingsFile.failWrite(fos);
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001564 }
1565 }
1566 }
1567
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001568 public static VolumeRecord readVolumeRecord(XmlPullParser in) throws IOException {
1569 final int type = readIntAttribute(in, ATTR_TYPE);
1570 final String fsUuid = readStringAttribute(in, ATTR_FS_UUID);
1571 final VolumeRecord meta = new VolumeRecord(type, fsUuid);
Jeff Sharkey5cc0df22015-06-17 19:44:05 -07001572 meta.partGuid = readStringAttribute(in, ATTR_PART_GUID);
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001573 meta.nickname = readStringAttribute(in, ATTR_NICKNAME);
1574 meta.userFlags = readIntAttribute(in, ATTR_USER_FLAGS);
Jeff Sharkeye8a4b662015-06-27 15:43:45 -07001575 meta.createdMillis = readLongAttribute(in, ATTR_CREATED_MILLIS);
1576 meta.lastTrimMillis = readLongAttribute(in, ATTR_LAST_TRIM_MILLIS);
1577 meta.lastBenchMillis = readLongAttribute(in, ATTR_LAST_BENCH_MILLIS);
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001578 return meta;
1579 }
1580
1581 public static void writeVolumeRecord(XmlSerializer out, VolumeRecord rec) throws IOException {
1582 out.startTag(null, TAG_VOLUME);
1583 writeIntAttribute(out, ATTR_TYPE, rec.type);
1584 writeStringAttribute(out, ATTR_FS_UUID, rec.fsUuid);
Jeff Sharkey5cc0df22015-06-17 19:44:05 -07001585 writeStringAttribute(out, ATTR_PART_GUID, rec.partGuid);
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001586 writeStringAttribute(out, ATTR_NICKNAME, rec.nickname);
1587 writeIntAttribute(out, ATTR_USER_FLAGS, rec.userFlags);
Jeff Sharkeye8a4b662015-06-27 15:43:45 -07001588 writeLongAttribute(out, ATTR_CREATED_MILLIS, rec.createdMillis);
1589 writeLongAttribute(out, ATTR_LAST_TRIM_MILLIS, rec.lastTrimMillis);
1590 writeLongAttribute(out, ATTR_LAST_BENCH_MILLIS, rec.lastBenchMillis);
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001591 out.endTag(null, TAG_VOLUME);
1592 }
1593
San Mehat207e5382010-02-04 20:46:54 -08001594 /**
San Mehat4270e1e2010-01-29 05:32:19 -08001595 * Exposed API calls below here
1596 */
1597
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001598 @Override
Sudheer Shanka2250d562016-11-07 15:41:02 -08001599 public void registerListener(IStorageEventListener listener) {
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001600 mCallbacks.register(listener);
San Mehat4270e1e2010-01-29 05:32:19 -08001601 }
1602
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001603 @Override
Sudheer Shanka2250d562016-11-07 15:41:02 -08001604 public void unregisterListener(IStorageEventListener listener) {
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001605 mCallbacks.unregister(listener);
San Mehat4270e1e2010-01-29 05:32:19 -08001606 }
1607
Jeff Sharkey48877892015-03-18 11:27:19 -07001608 @Override
Sudheer Shanka2250d562016-11-07 15:41:02 -08001609 public void shutdown(final IStorageShutdownObserver observer) {
Jeff Sharkey48877892015-03-18 11:27:19 -07001610 enforcePermission(android.Manifest.permission.SHUTDOWN);
San Mehat4270e1e2010-01-29 05:32:19 -08001611
San Mehata5078592010-03-25 09:36:54 -07001612 Slog.i(TAG, "Shutting down");
Jeff Sharkey48877892015-03-18 11:27:19 -07001613 mHandler.obtainMessage(H_SHUTDOWN, observer).sendToTarget();
San Mehat4270e1e2010-01-29 05:32:19 -08001614 }
1615
Jeff Sharkey48877892015-03-18 11:27:19 -07001616 @Override
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001617 public void mount(String volId) {
1618 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001619
Jeff Sharkeyef10ee02015-07-05 14:17:27 -07001620 final VolumeInfo vol = findVolumeByIdOrThrow(volId);
Jeff Sharkey2e606d72015-07-27 14:19:54 -07001621 if (isMountDisallowed(vol)) {
1622 throw new SecurityException("Mounting " + volId + " restricted by policy");
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001623 }
1624 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06001625 mVold.mount(vol.id, vol.mountFlags, vol.mountUserId);
Jeff Sharkeyace874b2017-09-07 15:27:33 -06001626 } catch (Exception e) {
1627 Slog.wtf(TAG, e);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001628 }
1629 }
1630
1631 @Override
1632 public void unmount(String volId) {
1633 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001634
Jeff Sharkeyef10ee02015-07-05 14:17:27 -07001635 final VolumeInfo vol = findVolumeByIdOrThrow(volId);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001636 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06001637 mVold.unmount(vol.id);
Jeff Sharkeyace874b2017-09-07 15:27:33 -06001638 } catch (Exception e) {
1639 Slog.wtf(TAG, e);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001640 }
1641 }
1642
1643 @Override
1644 public void format(String volId) {
Jeff Sharkey48877892015-03-18 11:27:19 -07001645 enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);
San Mehat5b77dab2010-01-26 13:28:50 -08001646
Jeff Sharkeyef10ee02015-07-05 14:17:27 -07001647 final VolumeInfo vol = findVolumeByIdOrThrow(volId);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001648 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06001649 mVold.format(vol.id, "auto");
Jeff Sharkeyace874b2017-09-07 15:27:33 -06001650 } catch (Exception e) {
1651 Slog.wtf(TAG, e);
Jeff Sharkey48877892015-03-18 11:27:19 -07001652 }
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001653 }
1654
1655 @Override
Jeff Sharkey7e19f532017-11-06 13:54:11 -07001656 public void benchmark(String volId, IVoldTaskListener listener) {
Jeff Sharkey9756d752015-05-14 21:07:42 -07001657 enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);
Jeff Sharkey9756d752015-05-14 21:07:42 -07001658
1659 try {
Jeff Sharkeyb302c542017-09-15 12:57:59 -06001660 mVold.benchmark(volId, new IVoldTaskListener.Stub() {
1661 @Override
1662 public void onStatus(int status, PersistableBundle extras) {
Jeff Sharkey7e19f532017-11-06 13:54:11 -07001663 dispatchOnStatus(listener, status, extras);
Jeff Sharkeyb302c542017-09-15 12:57:59 -06001664 }
1665
1666 @Override
1667 public void onFinished(int status, PersistableBundle extras) {
Jeff Sharkey7e19f532017-11-06 13:54:11 -07001668 dispatchOnFinished(listener, status, extras);
Jeff Sharkeyb302c542017-09-15 12:57:59 -06001669
1670 final String path = extras.getString("path");
1671 final String ident = extras.getString("ident");
1672 final long create = extras.getLong("create");
1673 final long run = extras.getLong("run");
1674 final long destroy = extras.getLong("destroy");
1675
1676 final DropBoxManager dropBox = mContext.getSystemService(DropBoxManager.class);
1677 dropBox.addText(TAG_STORAGE_BENCHMARK, scrubPath(path)
1678 + " " + ident + " " + create + " " + run + " " + destroy);
1679
1680 synchronized (mLock) {
1681 final VolumeRecord rec = findRecordForPath(path);
1682 if (rec != null) {
1683 rec.lastBenchMillis = System.currentTimeMillis();
1684 writeSettingsLocked();
1685 }
1686 }
1687 }
1688 });
Jeff Sharkey7e19f532017-11-06 13:54:11 -07001689 } catch (RemoteException e) {
1690 throw e.rethrowAsRuntimeException();
Jeff Sharkey9756d752015-05-14 21:07:42 -07001691 }
1692 }
1693
1694 @Override
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001695 public void partitionPublic(String diskId) {
1696 enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001697
Jeff Sharkeyeba260d2015-04-19 14:35:16 -07001698 final CountDownLatch latch = findOrCreateDiskScanLatch(diskId);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001699 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06001700 mVold.partition(diskId, IVold.PARTITION_TYPE_PUBLIC, -1);
Jeff Sharkeyedcdaf62015-07-09 09:45:36 -07001701 waitForLatch(latch, "partitionPublic", 3 * DateUtils.MINUTE_IN_MILLIS);
Jeff Sharkeyace874b2017-09-07 15:27:33 -06001702 } catch (Exception e) {
1703 Slog.wtf(TAG, e);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001704 }
1705 }
1706
1707 @Override
1708 public void partitionPrivate(String diskId) {
1709 enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);
Amith Yamasani462ac3a2015-06-30 14:21:01 -07001710 enforceAdminUser();
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001711
Jeff Sharkeyeba260d2015-04-19 14:35:16 -07001712 final CountDownLatch latch = findOrCreateDiskScanLatch(diskId);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001713 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06001714 mVold.partition(diskId, IVold.PARTITION_TYPE_PRIVATE, -1);
Jeff Sharkeyedcdaf62015-07-09 09:45:36 -07001715 waitForLatch(latch, "partitionPrivate", 3 * DateUtils.MINUTE_IN_MILLIS);
Jeff Sharkeyace874b2017-09-07 15:27:33 -06001716 } catch (Exception e) {
1717 Slog.wtf(TAG, e);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001718 }
1719 }
1720
1721 @Override
1722 public void partitionMixed(String diskId, int ratio) {
1723 enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);
Amith Yamasani462ac3a2015-06-30 14:21:01 -07001724 enforceAdminUser();
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001725
Jeff Sharkeyeba260d2015-04-19 14:35:16 -07001726 final CountDownLatch latch = findOrCreateDiskScanLatch(diskId);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001727 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06001728 mVold.partition(diskId, IVold.PARTITION_TYPE_MIXED, ratio);
Jeff Sharkeyedcdaf62015-07-09 09:45:36 -07001729 waitForLatch(latch, "partitionMixed", 3 * DateUtils.MINUTE_IN_MILLIS);
Jeff Sharkeyace874b2017-09-07 15:27:33 -06001730 } catch (Exception e) {
1731 Slog.wtf(TAG, e);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001732 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001733 }
1734
Jeff Sharkey48877892015-03-18 11:27:19 -07001735 @Override
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001736 public void setVolumeNickname(String fsUuid, String nickname) {
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001737 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001738
Jeff Sharkey50a05452015-04-29 11:24:52 -07001739 Preconditions.checkNotNull(fsUuid);
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001740 synchronized (mLock) {
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001741 final VolumeRecord rec = mRecords.get(fsUuid);
1742 rec.nickname = nickname;
Jeff Sharkey50a05452015-04-29 11:24:52 -07001743 mCallbacks.notifyVolumeRecordChanged(rec);
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001744 writeSettingsLocked();
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001745 }
1746 }
1747
1748 @Override
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001749 public void setVolumeUserFlags(String fsUuid, int flags, int mask) {
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001750 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001751
Jeff Sharkey50a05452015-04-29 11:24:52 -07001752 Preconditions.checkNotNull(fsUuid);
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001753 synchronized (mLock) {
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001754 final VolumeRecord rec = mRecords.get(fsUuid);
1755 rec.userFlags = (rec.userFlags & ~mask) | (flags & mask);
Jeff Sharkey50a05452015-04-29 11:24:52 -07001756 mCallbacks.notifyVolumeRecordChanged(rec);
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001757 writeSettingsLocked();
1758 }
1759 }
1760
1761 @Override
1762 public void forgetVolume(String fsUuid) {
1763 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001764
Jeff Sharkey50a05452015-04-29 11:24:52 -07001765 Preconditions.checkNotNull(fsUuid);
Jeff Sharkey5a9bb742015-11-03 10:15:57 -08001766
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001767 synchronized (mLock) {
Jeff Sharkey5cc0df22015-06-17 19:44:05 -07001768 final VolumeRecord rec = mRecords.remove(fsUuid);
1769 if (rec != null && !TextUtils.isEmpty(rec.partGuid)) {
Jeff Sharkeydb4b6192017-10-24 11:08:50 -06001770 mHandler.obtainMessage(H_PARTITION_FORGET, rec).sendToTarget();
Jeff Sharkey5cc0df22015-06-17 19:44:05 -07001771 }
1772 mCallbacks.notifyVolumeForgotten(fsUuid);
Jeff Sharkey50a05452015-04-29 11:24:52 -07001773
1774 // If this had been primary storage, revert back to internal and
1775 // reset vold so we bind into new volume into place.
1776 if (Objects.equals(mPrimaryStorageUuid, fsUuid)) {
Jeff Sharkeyfced5342015-05-10 14:53:34 -07001777 mPrimaryStorageUuid = getDefaultPrimaryStorageUuid();
Jeff Sharkey5a9bb742015-11-03 10:15:57 -08001778 mHandler.obtainMessage(H_RESET).sendToTarget();
Jeff Sharkey50a05452015-04-29 11:24:52 -07001779 }
1780
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001781 writeSettingsLocked();
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001782 }
1783 }
1784
Jeff Sharkey7d2af542015-05-12 15:27:15 -07001785 @Override
1786 public void forgetAllVolumes() {
1787 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
Jeff Sharkey7d2af542015-05-12 15:27:15 -07001788
Jeff Sharkey50a05452015-04-29 11:24:52 -07001789 synchronized (mLock) {
1790 for (int i = 0; i < mRecords.size(); i++) {
1791 final String fsUuid = mRecords.keyAt(i);
Jeff Sharkey5cc0df22015-06-17 19:44:05 -07001792 final VolumeRecord rec = mRecords.valueAt(i);
1793 if (!TextUtils.isEmpty(rec.partGuid)) {
Jeff Sharkeydb4b6192017-10-24 11:08:50 -06001794 mHandler.obtainMessage(H_PARTITION_FORGET, rec).sendToTarget();
Jeff Sharkey5cc0df22015-06-17 19:44:05 -07001795 }
Jeff Sharkey50a05452015-04-29 11:24:52 -07001796 mCallbacks.notifyVolumeForgotten(fsUuid);
1797 }
Jeff Sharkey50a05452015-04-29 11:24:52 -07001798 mRecords.clear();
Jeff Sharkey50a05452015-04-29 11:24:52 -07001799
Jeff Sharkeyfced5342015-05-10 14:53:34 -07001800 if (!Objects.equals(StorageManager.UUID_PRIVATE_INTERNAL, mPrimaryStorageUuid)) {
1801 mPrimaryStorageUuid = getDefaultPrimaryStorageUuid();
1802 }
1803
1804 writeSettingsLocked();
Jeff Sharkey5a9bb742015-11-03 10:15:57 -08001805 mHandler.obtainMessage(H_RESET).sendToTarget();
Jeff Sharkey50a05452015-04-29 11:24:52 -07001806 }
1807 }
1808
Jeff Sharkeydb4b6192017-10-24 11:08:50 -06001809 private void forgetPartition(String partGuid, String fsUuid) {
Jeff Sharkey5cc0df22015-06-17 19:44:05 -07001810 try {
Jeff Sharkeydb4b6192017-10-24 11:08:50 -06001811 mVold.forgetPartition(partGuid, fsUuid);
Jeff Sharkeyace874b2017-09-07 15:27:33 -06001812 } catch (Exception e) {
1813 Slog.wtf(TAG, e);
Jeff Sharkey5cc0df22015-06-17 19:44:05 -07001814 }
1815 }
1816
Jeff Sharkey31d0b702016-11-21 14:16:53 -07001817 @Override
Jeff Sharkey7e19f532017-11-06 13:54:11 -07001818 public void fstrim(int flags, IVoldTaskListener listener) {
Jeff Sharkey31d0b702016-11-21 14:16:53 -07001819 enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);
Jeff Sharkey31d0b702016-11-21 14:16:53 -07001820
1821 try {
Jeff Sharkeyb302c542017-09-15 12:57:59 -06001822 mVold.fstrim(flags, new IVoldTaskListener.Stub() {
1823 @Override
1824 public void onStatus(int status, PersistableBundle extras) {
Jeff Sharkey7e19f532017-11-06 13:54:11 -07001825 dispatchOnStatus(listener, status, extras);
1826
Jeff Sharkeyb302c542017-09-15 12:57:59 -06001827 // Ignore trim failures
1828 if (status != 0) return;
1829
1830 final String path = extras.getString("path");
1831 final long bytes = extras.getLong("bytes");
1832 final long time = extras.getLong("time");
1833
1834 final DropBoxManager dropBox = mContext.getSystemService(DropBoxManager.class);
1835 dropBox.addText(TAG_STORAGE_TRIM, scrubPath(path) + " " + bytes + " " + time);
1836
1837 synchronized (mLock) {
1838 final VolumeRecord rec = findRecordForPath(path);
1839 if (rec != null) {
1840 rec.lastTrimMillis = System.currentTimeMillis();
1841 writeSettingsLocked();
1842 }
1843 }
1844 }
1845
1846 @Override
1847 public void onFinished(int status, PersistableBundle extras) {
Jeff Sharkey7e19f532017-11-06 13:54:11 -07001848 dispatchOnFinished(listener, status, extras);
1849
Jeff Sharkeyb302c542017-09-15 12:57:59 -06001850 // TODO: benchmark when desired
1851 }
1852 });
Jeff Sharkey7e19f532017-11-06 13:54:11 -07001853 } catch (RemoteException e) {
1854 throw e.rethrowAsRuntimeException();
Jeff Sharkey31d0b702016-11-21 14:16:53 -07001855 }
1856 }
1857
Jin Qiana85b9912017-10-17 15:48:18 -07001858 void runIdleMaint(Runnable callback) {
1859 enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);
1860
1861 try {
1862 mVold.runIdleMaint(new IVoldTaskListener.Stub() {
1863 @Override
1864 public void onStatus(int status, PersistableBundle extras) {
1865 // Not currently used
1866 }
1867 @Override
1868 public void onFinished(int status, PersistableBundle extras) {
1869 if (callback != null) {
1870 BackgroundThread.getHandler().post(callback);
1871 }
1872 }
1873 });
1874 } catch (Exception e) {
1875 Slog.wtf(TAG, e);
1876 }
1877 }
1878
1879 @Override
1880 public void runIdleMaintenance() {
1881 runIdleMaint(null);
1882 }
1883
1884 void abortIdleMaint(Runnable callback) {
1885 enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);
1886
1887 try {
1888 mVold.abortIdleMaint(new IVoldTaskListener.Stub() {
1889 @Override
1890 public void onStatus(int status, PersistableBundle extras) {
1891 // Not currently used
1892 }
1893 @Override
1894 public void onFinished(int status, PersistableBundle extras) {
1895 if (callback != null) {
1896 BackgroundThread.getHandler().post(callback);
1897 }
1898 }
1899 });
1900 } catch (Exception e) {
1901 Slog.wtf(TAG, e);
1902 }
1903 }
1904
1905 @Override
1906 public void abortIdleMaintenance() {
1907 abortIdleMaint(null);
1908 }
1909
Svet Ganov6ee871e2015-07-10 14:29:33 -07001910 private void remountUidExternalStorage(int uid, int mode) {
Jeff Sharkey9527b222015-06-24 15:24:48 -07001911 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06001912 mVold.remountUid(uid, mode);
Jeff Sharkeyace874b2017-09-07 15:27:33 -06001913 } catch (Exception e) {
1914 Slog.wtf(TAG, e);
Jeff Sharkey9527b222015-06-24 15:24:48 -07001915 }
1916 }
1917
1918 @Override
Jeff Sharkey4c099d02015-05-15 13:45:00 -07001919 public void setDebugFlags(int flags, int mask) {
1920 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
Jeff Sharkey4c099d02015-05-15 13:45:00 -07001921
Jeff Sharkeyba512352015-11-12 20:17:45 -08001922 if ((mask & StorageManager.DEBUG_EMULATE_FBE) != 0) {
Jeff Sharkey00455bf2016-11-04 14:45:24 -06001923 if (!EMULATE_FBE_SUPPORTED) {
1924 throw new IllegalStateException(
1925 "Emulation not supported on this device");
1926 }
Paul Lawrence20be5d62016-02-26 13:51:17 -08001927 if (StorageManager.isFileEncryptedNativeOnly()) {
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07001928 throw new IllegalStateException(
Jeff Sharkey00455bf2016-11-04 14:45:24 -06001929 "Emulation not supported on device with native FBE");
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07001930 }
Jeff Sharkey5a785162016-03-21 13:02:06 -06001931 if (mLockPatternUtils.isCredentialRequiredToDecrypt(false)) {
1932 throw new IllegalStateException(
1933 "Emulation requires disabling 'Secure start-up' in Settings > Security");
1934 }
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07001935
Jeff Sharkey1176e512016-02-29 17:01:26 -07001936 final long token = Binder.clearCallingIdentity();
1937 try {
1938 final boolean emulateFbe = (flags & StorageManager.DEBUG_EMULATE_FBE) != 0;
1939 SystemProperties.set(StorageManager.PROP_EMULATE_FBE, Boolean.toString(emulateFbe));
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07001940
Jeff Sharkey1176e512016-02-29 17:01:26 -07001941 // Perform hard reboot to kick policy into place
1942 mContext.getSystemService(PowerManager.class).reboot(null);
1943 } finally {
1944 Binder.restoreCallingIdentity(token);
1945 }
Jeff Sharkeyba512352015-11-12 20:17:45 -08001946 }
Jeff Sharkey4c099d02015-05-15 13:45:00 -07001947
Jeff Sharkeyba512352015-11-12 20:17:45 -08001948 if ((mask & StorageManager.DEBUG_FORCE_ADOPTABLE) != 0) {
1949 synchronized (mLock) {
1950 mForceAdoptable = (flags & StorageManager.DEBUG_FORCE_ADOPTABLE) != 0;
1951
1952 writeSettingsLocked();
1953 mHandler.obtainMessage(H_RESET).sendToTarget();
1954 }
Jeff Sharkey4c099d02015-05-15 13:45:00 -07001955 }
Jeff Sharkey33dd1562016-04-07 11:05:33 -06001956
1957 if ((mask & (StorageManager.DEBUG_SDCARDFS_FORCE_ON
1958 | StorageManager.DEBUG_SDCARDFS_FORCE_OFF)) != 0) {
1959 final String value;
1960 if ((flags & StorageManager.DEBUG_SDCARDFS_FORCE_ON) != 0) {
1961 value = "force_on";
1962 } else if ((flags & StorageManager.DEBUG_SDCARDFS_FORCE_OFF) != 0) {
1963 value = "force_off";
1964 } else {
1965 value = "";
1966 }
1967
1968 final long token = Binder.clearCallingIdentity();
1969 try {
1970 SystemProperties.set(StorageManager.PROP_SDCARDFS, value);
1971
1972 // Reset storage to kick new setting into place
1973 mHandler.obtainMessage(H_RESET).sendToTarget();
1974 } finally {
1975 Binder.restoreCallingIdentity(token);
1976 }
1977 }
Jeff Sharkeye53e2d92017-03-25 23:14:06 -06001978
1979 if ((mask & StorageManager.DEBUG_VIRTUAL_DISK) != 0) {
1980 final boolean enabled = (flags & StorageManager.DEBUG_VIRTUAL_DISK) != 0;
1981
1982 final long token = Binder.clearCallingIdentity();
1983 try {
1984 SystemProperties.set(StorageManager.PROP_VIRTUAL_DISK, Boolean.toString(enabled));
1985
1986 // Reset storage to kick new setting into place
1987 mHandler.obtainMessage(H_RESET).sendToTarget();
1988 } finally {
1989 Binder.restoreCallingIdentity(token);
1990 }
1991 }
Jeff Sharkey4c099d02015-05-15 13:45:00 -07001992 }
1993
1994 @Override
Jeff Sharkey275e3e42015-04-24 16:10:32 -07001995 public String getPrimaryStorageUuid() {
Jeff Sharkey620b32b2015-04-23 19:36:02 -07001996 synchronized (mLock) {
1997 return mPrimaryStorageUuid;
1998 }
1999 }
2000
2001 @Override
Jeff Sharkey275e3e42015-04-24 16:10:32 -07002002 public void setPrimaryStorageUuid(String volumeUuid, IPackageMoveObserver callback) {
2003 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
Jeff Sharkey620b32b2015-04-23 19:36:02 -07002004
Jeff Sharkeya31460c2016-06-22 09:04:33 -06002005 final VolumeInfo from;
2006 final VolumeInfo to;
2007
Jeff Sharkey275e3e42015-04-24 16:10:32 -07002008 synchronized (mLock) {
Jeff Sharkeyfced5342015-05-10 14:53:34 -07002009 if (Objects.equals(mPrimaryStorageUuid, volumeUuid)) {
2010 throw new IllegalArgumentException("Primary storage already at " + volumeUuid);
Jeff Sharkey275e3e42015-04-24 16:10:32 -07002011 }
2012
2013 if (mMoveCallback != null) {
2014 throw new IllegalStateException("Move already in progress");
2015 }
2016 mMoveCallback = callback;
2017 mMoveTargetUuid = volumeUuid;
2018
Jeff Sharkeya65e6492017-06-21 13:45:11 -06002019 // We need all the users unlocked to move their primary storage
2020 final List<UserInfo> users = mContext.getSystemService(UserManager.class).getUsers();
2021 for (UserInfo user : users) {
2022 if (StorageManager.isFileEncryptedNativeOrEmulated()
2023 && !isUserKeyUnlocked(user.id)) {
2024 Slog.w(TAG, "Failing move due to locked user " + user.id);
2025 onMoveStatusLocked(PackageManager.MOVE_FAILED_LOCKED_USER);
2026 return;
2027 }
2028 }
2029
Jeff Sharkeyfced5342015-05-10 14:53:34 -07002030 // When moving to/from primary physical volume, we probably just nuked
2031 // the current storage location, so we have nothing to move.
2032 if (Objects.equals(StorageManager.UUID_PRIMARY_PHYSICAL, mPrimaryStorageUuid)
2033 || Objects.equals(StorageManager.UUID_PRIMARY_PHYSICAL, volumeUuid)) {
2034 Slog.d(TAG, "Skipping move to/from primary physical");
2035 onMoveStatusLocked(MOVE_STATUS_COPY_FINISHED);
2036 onMoveStatusLocked(PackageManager.MOVE_SUCCEEDED);
Jeff Sharkey5a9bb742015-11-03 10:15:57 -08002037 mHandler.obtainMessage(H_RESET).sendToTarget();
Jeff Sharkeya31460c2016-06-22 09:04:33 -06002038 return;
Jeff Sharkeyfced5342015-05-10 14:53:34 -07002039
2040 } else {
Jeff Sharkeya31460c2016-06-22 09:04:33 -06002041 from = findStorageForUuid(mPrimaryStorageUuid);
2042 to = findStorageForUuid(volumeUuid);
Jeff Sharkeyef10ee02015-07-05 14:17:27 -07002043
2044 if (from == null) {
2045 Slog.w(TAG, "Failing move due to missing from volume " + mPrimaryStorageUuid);
2046 onMoveStatusLocked(PackageManager.MOVE_FAILED_INTERNAL_ERROR);
2047 return;
2048 } else if (to == null) {
2049 Slog.w(TAG, "Failing move due to missing to volume " + volumeUuid);
2050 onMoveStatusLocked(PackageManager.MOVE_FAILED_INTERNAL_ERROR);
2051 return;
2052 }
Jeff Sharkey275e3e42015-04-24 16:10:32 -07002053 }
Jeff Sharkey620b32b2015-04-23 19:36:02 -07002054 }
Jeff Sharkeya31460c2016-06-22 09:04:33 -06002055
2056 try {
Jeff Sharkeyb302c542017-09-15 12:57:59 -06002057 mVold.moveStorage(from.id, to.id, new IVoldTaskListener.Stub() {
2058 @Override
2059 public void onStatus(int status, PersistableBundle extras) {
2060 synchronized (mLock) {
2061 onMoveStatusLocked(status);
2062 }
2063 }
2064
2065 @Override
2066 public void onFinished(int status, PersistableBundle extras) {
2067 // Not currently used
2068 }
2069 });
Jeff Sharkeyace874b2017-09-07 15:27:33 -06002070 } catch (Exception e) {
2071 Slog.wtf(TAG, e);
Jeff Sharkeya31460c2016-06-22 09:04:33 -06002072 }
Jeff Sharkey620b32b2015-04-23 19:36:02 -07002073 }
2074
San Mehatb1043402010-02-05 08:26:50 -08002075 private void warnOnNotMounted() {
Jeff Sharkey48877892015-03-18 11:27:19 -07002076 synchronized (mLock) {
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07002077 for (int i = 0; i < mVolumes.size(); i++) {
2078 final VolumeInfo vol = mVolumes.valueAt(i);
Jeff Sharkey27de30d2015-04-18 16:20:27 -07002079 if (vol.isPrimary() && vol.isMountedWritable()) {
Jeff Sharkey48877892015-03-18 11:27:19 -07002080 // Cool beans, we have a mounted primary volume
2081 return;
2082 }
Jeff Sharkey32ee8312012-09-30 13:21:31 -07002083 }
San Mehatb1043402010-02-05 08:26:50 -08002084 }
Jeff Sharkey48877892015-03-18 11:27:19 -07002085
2086 Slog.w(TAG, "No primary storage mounted!");
San Mehatb1043402010-02-05 08:26:50 -08002087 }
2088
Kenny Roota02b8b02010-08-05 16:14:17 -07002089 private boolean isUidOwnerOfPackageOrSystem(String packageName, int callerUid) {
2090 if (callerUid == android.os.Process.SYSTEM_UID) {
2091 return true;
2092 }
2093
Kenny Root02c87302010-07-01 08:10:18 -07002094 if (packageName == null) {
2095 return false;
2096 }
2097
Jeff Sharkeycd654482016-01-08 17:42:11 -07002098 final int packageUid = mPms.getPackageUid(packageName,
2099 PackageManager.MATCH_DEBUG_TRIAGED_MISSING, UserHandle.getUserId(callerUid));
Kenny Root02c87302010-07-01 08:10:18 -07002100
2101 if (DEBUG_OBB) {
2102 Slog.d(TAG, "packageName = " + packageName + ", packageUid = " +
2103 packageUid + ", callerUid = " + callerUid);
2104 }
2105
2106 return callerUid == packageUid;
2107 }
2108
Jeff Sharkey54402792017-09-15 16:05:19 -06002109 @Override
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002110 public String getMountedObbPath(String rawPath) {
2111 Preconditions.checkNotNull(rawPath, "rawPath cannot be null");
Kenny Rootaf9d6672010-10-08 09:21:39 -07002112
Kenny Root02c87302010-07-01 08:10:18 -07002113 warnOnNotMounted();
2114
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002115 final ObbState state;
Rubin Xucd7a0142015-04-17 23:45:27 +01002116 synchronized (mObbMounts) {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002117 state = mObbPathToStateMap.get(rawPath);
2118 }
2119 if (state == null) {
2120 Slog.w(TAG, "Failed to find OBB mounted at " + rawPath);
2121 return null;
2122 }
2123
Jeff Sharkey54402792017-09-15 16:05:19 -06002124 return findVolumeByIdOrThrow(state.volId).getPath().getAbsolutePath();
Kenny Root02c87302010-07-01 08:10:18 -07002125 }
2126
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002127 @Override
2128 public boolean isObbMounted(String rawPath) {
2129 Preconditions.checkNotNull(rawPath, "rawPath cannot be null");
Kenny Rootaf9d6672010-10-08 09:21:39 -07002130 synchronized (mObbMounts) {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002131 return mObbPathToStateMap.containsKey(rawPath);
Kenny Rootaf9d6672010-10-08 09:21:39 -07002132 }
Kenny Root02c87302010-07-01 08:10:18 -07002133 }
2134
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002135 @Override
2136 public void mountObb(
2137 String rawPath, String canonicalPath, String key, IObbActionListener token, int nonce) {
2138 Preconditions.checkNotNull(rawPath, "rawPath cannot be null");
2139 Preconditions.checkNotNull(canonicalPath, "canonicalPath cannot be null");
2140 Preconditions.checkNotNull(token, "token cannot be null");
Kenny Rootaf9d6672010-10-08 09:21:39 -07002141
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002142 final int callingUid = Binder.getCallingUid();
Jeff Sharkey41cd6812017-09-11 10:32:17 -06002143 final ObbState obbState = new ObbState(rawPath, canonicalPath,
2144 callingUid, token, nonce, null);
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002145 final ObbAction action = new MountObbAction(obbState, key, callingUid);
Kenny Roota02b8b02010-08-05 16:14:17 -07002146 mObbActionHandler.sendMessage(mObbActionHandler.obtainMessage(OBB_RUN_ACTION, action));
2147
2148 if (DEBUG_OBB)
2149 Slog.i(TAG, "Send to OBB handler: " + action.toString());
Kenny Root02c87302010-07-01 08:10:18 -07002150 }
2151
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002152 @Override
2153 public void unmountObb(String rawPath, boolean force, IObbActionListener token, int nonce) {
2154 Preconditions.checkNotNull(rawPath, "rawPath cannot be null");
2155
2156 final ObbState existingState;
Rubin Xucd7a0142015-04-17 23:45:27 +01002157 synchronized (mObbMounts) {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002158 existingState = mObbPathToStateMap.get(rawPath);
Kenny Rootf1121dc2010-09-29 07:30:53 -07002159 }
2160
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002161 if (existingState != null) {
2162 // TODO: separate state object from request data
2163 final int callingUid = Binder.getCallingUid();
Jeff Sharkey41cd6812017-09-11 10:32:17 -06002164 final ObbState newState = new ObbState(rawPath, existingState.canonicalPath,
2165 callingUid, token, nonce, existingState.volId);
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002166 final ObbAction action = new UnmountObbAction(newState, force);
2167 mObbActionHandler.sendMessage(mObbActionHandler.obtainMessage(OBB_RUN_ACTION, action));
Kenny Root02c87302010-07-01 08:10:18 -07002168
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002169 if (DEBUG_OBB)
2170 Slog.i(TAG, "Send to OBB handler: " + action.toString());
2171 } else {
2172 Slog.w(TAG, "Unknown OBB mount at " + rawPath);
2173 }
Kenny Roota02b8b02010-08-05 16:14:17 -07002174 }
2175
Ben Komalo444eca22011-09-01 15:17:44 -07002176 @Override
2177 public int getEncryptionState() {
2178 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
2179 "no permission to access the crypt keeper");
2180
Ben Komalo444eca22011-09-01 15:17:44 -07002181 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002182 return mVold.fdeComplete();
2183 } catch (Exception e) {
2184 Slog.wtf(TAG, e);
Sudheer Shankaf7341142016-10-18 17:15:18 -07002185 return StorageManager.ENCRYPTION_STATE_ERROR_UNKNOWN;
Ben Komalo444eca22011-09-01 15:17:44 -07002186 }
2187 }
2188
2189 @Override
Jason parks5af0b912010-11-29 09:05:25 -06002190 public int decryptStorage(String password) {
Jason parks8888c592011-01-20 22:46:41 -06002191 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
2192 "no permission to access the crypt keeper");
Jason parks5af0b912010-11-29 09:05:25 -06002193
Jeff Sharkey8058fe62017-09-13 11:50:33 -06002194 if (TextUtils.isEmpty(password)) {
2195 throw new IllegalArgumentException("password cannot be empty");
2196 }
2197
Jason parks5af0b912010-11-29 09:05:25 -06002198 if (DEBUG_EVENTS) {
2199 Slog.i(TAG, "decrypting storage...");
2200 }
2201
2202 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002203 mVold.fdeCheckPassword(password);
2204 mHandler.postDelayed(() -> {
2205 try {
2206 mVold.fdeRestart();
2207 } catch (Exception e) {
2208 Slog.wtf(TAG, e);
2209 }
2210 }, DateUtils.SECOND_IN_MILLIS);
2211 return 0;
2212 } catch (Exception e) {
2213 Slog.wtf(TAG, e);
2214 return StorageManager.ENCRYPTION_STATE_ERROR_UNKNOWN;
Jason parks5af0b912010-11-29 09:05:25 -06002215 }
Jason parks5af0b912010-11-29 09:05:25 -06002216 }
2217
Jeff Sharkey54402792017-09-15 16:05:19 -06002218 @Override
Paul Lawrence46791e72014-04-03 09:10:26 -07002219 public int encryptStorage(int type, String password) {
Jason parks8888c592011-01-20 22:46:41 -06002220 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
2221 "no permission to access the crypt keeper");
Jason parks56aa5322011-01-07 09:01:15 -06002222
Jeff Sharkey8058fe62017-09-13 11:50:33 -06002223 if (type == StorageManager.CRYPT_TYPE_DEFAULT) {
2224 password = "";
2225 } else if (TextUtils.isEmpty(password)) {
2226 throw new IllegalArgumentException("password cannot be empty");
2227 }
2228
Jason parks56aa5322011-01-07 09:01:15 -06002229 if (DEBUG_EVENTS) {
Jason parks8888c592011-01-20 22:46:41 -06002230 Slog.i(TAG, "encrypting storage...");
Jason parks56aa5322011-01-07 09:01:15 -06002231 }
2232
2233 try {
Paul Lawrence89a0ae42017-12-22 10:11:10 -08002234 mVold.fdeEnable(type, password, 0);
Jeff Sharkey43e12112017-09-12 16:31:45 -06002235 } catch (Exception e) {
2236 Slog.wtf(TAG, e);
2237 return -1;
Jason parks56aa5322011-01-07 09:01:15 -06002238 }
2239
2240 return 0;
2241 }
2242
Paul Lawrence8e397362014-01-27 15:22:30 -08002243 /** Set the password for encrypting the master key.
2244 * @param type One of the CRYPTO_TYPE_XXX consts defined in StorageManager.
2245 * @param password The password to set.
2246 */
Jeff Sharkey54402792017-09-15 16:05:19 -06002247 @Override
Paul Lawrence8e397362014-01-27 15:22:30 -08002248 public int changeEncryptionPassword(int type, String password) {
Jason parksf7b3cd42011-01-27 09:28:25 -06002249 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
2250 "no permission to access the crypt keeper");
2251
Jeff Sharkeyae266462017-11-27 13:32:24 -07002252 if (StorageManager.isFileEncryptedNativeOnly()) {
2253 // Not supported on FBE devices
2254 return -1;
2255 }
2256
Jeff Sharkey8058fe62017-09-13 11:50:33 -06002257 if (type == StorageManager.CRYPT_TYPE_DEFAULT) {
2258 password = "";
2259 } else if (TextUtils.isEmpty(password)) {
2260 throw new IllegalArgumentException("password cannot be empty");
2261 }
2262
Jason parksf7b3cd42011-01-27 09:28:25 -06002263 if (DEBUG_EVENTS) {
2264 Slog.i(TAG, "changing encryption password...");
2265 }
2266
2267 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002268 mVold.fdeChangePassword(type, password);
2269 return 0;
2270 } catch (Exception e) {
2271 Slog.wtf(TAG, e);
2272 return -1;
Jason parksf7b3cd42011-01-27 09:28:25 -06002273 }
2274 }
2275
Christopher Tate32418be2011-10-10 13:51:12 -07002276 /**
2277 * Validate a user-supplied password string with cryptfs
2278 */
2279 @Override
2280 public int verifyEncryptionPassword(String password) throws RemoteException {
2281 // Only the system process is permitted to validate passwords
2282 if (Binder.getCallingUid() != android.os.Process.SYSTEM_UID) {
2283 throw new SecurityException("no permission to access the crypt keeper");
2284 }
2285
2286 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
2287 "no permission to access the crypt keeper");
2288
2289 if (TextUtils.isEmpty(password)) {
2290 throw new IllegalArgumentException("password cannot be empty");
2291 }
2292
Christopher Tate32418be2011-10-10 13:51:12 -07002293 if (DEBUG_EVENTS) {
2294 Slog.i(TAG, "validating encryption password...");
2295 }
2296
2297 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002298 mVold.fdeVerifyPassword(password);
2299 return 0;
2300 } catch (Exception e) {
2301 Slog.wtf(TAG, e);
2302 return -1;
Christopher Tate32418be2011-10-10 13:51:12 -07002303 }
2304 }
2305
Paul Lawrence8e397362014-01-27 15:22:30 -08002306 /**
2307 * Get the type of encryption used to encrypt the master key.
2308 * @return The type, one of the CRYPT_TYPE_XXX consts from StorageManager.
2309 */
2310 @Override
Svetoslav16e4a1a2014-09-29 18:16:20 -07002311 public int getPasswordType() {
Paul Lawrence76a40572017-03-15 11:08:04 -07002312 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
Paul Lawrence9de713d2016-05-02 22:45:33 +00002313 "no permission to access the crypt keeper");
2314
Paul Lawrence8e397362014-01-27 15:22:30 -08002315 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002316 return mVold.fdeGetPasswordType();
2317 } catch (Exception e) {
2318 Slog.wtf(TAG, e);
2319 return -1;
Paul Lawrence8e397362014-01-27 15:22:30 -08002320 }
2321 }
2322
Paul Lawrencee51dcf92014-03-18 10:56:00 -07002323 /**
2324 * Set a field in the crypto header.
2325 * @param field field to set
2326 * @param contents contents to set in field
2327 */
2328 @Override
2329 public void setField(String field, String contents) throws RemoteException {
Paul Lawrence76a40572017-03-15 11:08:04 -07002330 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
Paul Lawrence0bbd1082016-04-26 15:21:02 -07002331 "no permission to access the crypt keeper");
Paul Lawrencee51dcf92014-03-18 10:56:00 -07002332
Jeff Sharkeyae266462017-11-27 13:32:24 -07002333 if (StorageManager.isFileEncryptedNativeOnly()) {
2334 // Not supported on FBE devices
2335 return;
2336 }
2337
Paul Lawrencee51dcf92014-03-18 10:56:00 -07002338 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002339 mVold.fdeSetField(field, contents);
2340 return;
2341 } catch (Exception e) {
2342 Slog.wtf(TAG, e);
2343 return;
Paul Lawrencee51dcf92014-03-18 10:56:00 -07002344 }
2345 }
2346
2347 /**
2348 * Gets a field from the crypto header.
2349 * @param field field to get
2350 * @return contents of field
2351 */
2352 @Override
2353 public String getField(String field) throws RemoteException {
Paul Lawrence76a40572017-03-15 11:08:04 -07002354 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
Paul Lawrence0bbd1082016-04-26 15:21:02 -07002355 "no permission to access the crypt keeper");
Paul Lawrencee51dcf92014-03-18 10:56:00 -07002356
Jeff Sharkeyae266462017-11-27 13:32:24 -07002357 if (StorageManager.isFileEncryptedNativeOnly()) {
2358 // Not supported on FBE devices
2359 return null;
2360 }
2361
Paul Lawrencee51dcf92014-03-18 10:56:00 -07002362 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002363 return mVold.fdeGetField(field);
2364 } catch (Exception e) {
2365 Slog.wtf(TAG, e);
2366 return null;
Paul Lawrencee51dcf92014-03-18 10:56:00 -07002367 }
2368 }
2369
Paul Lawrence3806d9c2015-10-29 10:30:46 -07002370 /**
2371 * Is userdata convertible to file based encryption?
2372 * @return non zero for convertible
2373 */
2374 @Override
2375 public boolean isConvertibleToFBE() throws RemoteException {
Paul Lawrence76a40572017-03-15 11:08:04 -07002376 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
Paul Lawrence0bbd1082016-04-26 15:21:02 -07002377 "no permission to access the crypt keeper");
Paul Lawrence3806d9c2015-10-29 10:30:46 -07002378
Paul Lawrence3806d9c2015-10-29 10:30:46 -07002379 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002380 return mVold.isConvertibleToFbe();
2381 } catch (Exception e) {
2382 Slog.wtf(TAG, e);
2383 return false;
Paul Lawrence3806d9c2015-10-29 10:30:46 -07002384 }
2385 }
2386
Jeff Sharkeyb049e212012-09-07 23:16:01 -07002387 @Override
Paul Lawrence945490c2014-03-27 16:37:28 +00002388 public String getPassword() throws RemoteException {
Paul Lawrence76a40572017-03-15 11:08:04 -07002389 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
Rubin Xucd7a0142015-04-17 23:45:27 +01002390 "only keyguard can retrieve password");
Paul Lawrence0bbd1082016-04-26 15:21:02 -07002391
Paul Lawrence945490c2014-03-27 16:37:28 +00002392 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002393 return mVold.fdeGetPassword();
2394 } catch (Exception e) {
2395 Slog.wtf(TAG, e);
Paul Lawrence24063b52015-01-06 13:11:23 -08002396 return null;
Paul Lawrence945490c2014-03-27 16:37:28 +00002397 }
2398 }
2399
2400 @Override
2401 public void clearPassword() throws RemoteException {
Paul Lawrence76a40572017-03-15 11:08:04 -07002402 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
Paul Lawrence0bbd1082016-04-26 15:21:02 -07002403 "only keyguard can clear password");
2404
Paul Lawrence945490c2014-03-27 16:37:28 +00002405 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002406 mVold.fdeClearPassword();
2407 return;
2408 } catch (Exception e) {
2409 Slog.wtf(TAG, e);
2410 return;
Paul Lawrence945490c2014-03-27 16:37:28 +00002411 }
2412 }
2413
2414 @Override
Lenka Trochtovac4dd0212015-11-18 12:22:06 +01002415 public void createUserKey(int userId, int serialNumber, boolean ephemeral) {
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002416 enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
Paul Crowleybcf48ed2015-04-22 13:36:59 +01002417
Paul Crowleybcf48ed2015-04-22 13:36:59 +01002418 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002419 mVold.createUserKey(userId, serialNumber, ephemeral);
Jeff Sharkey43e12112017-09-12 16:31:45 -06002420 } catch (Exception e) {
2421 Slog.wtf(TAG, e);
Paul Crowleybcf48ed2015-04-22 13:36:59 +01002422 }
2423 }
2424
Paul Crowley7ec733f2015-05-19 12:42:00 +01002425 @Override
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002426 public void destroyUserKey(int userId) {
2427 enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
Paul Crowley7ec733f2015-05-19 12:42:00 +01002428
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002429 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002430 mVold.destroyUserKey(userId);
Jeff Sharkey43e12112017-09-12 16:31:45 -06002431 } catch (Exception e) {
2432 Slog.wtf(TAG, e);
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002433 }
2434 }
2435
Jeff Sharkey43e12112017-09-12 16:31:45 -06002436 private String encodeBytes(byte[] bytes) {
Paul Crowleyfaeb3eb2016-02-08 15:58:29 +00002437 if (ArrayUtils.isEmpty(bytes)) {
Jeff Sharkey43e12112017-09-12 16:31:45 -06002438 return "!";
Paul Crowleyfaeb3eb2016-02-08 15:58:29 +00002439 } else {
Jeff Sharkey43e12112017-09-12 16:31:45 -06002440 return HexDump.toHexString(bytes);
Paul Crowleyfaeb3eb2016-02-08 15:58:29 +00002441 }
2442 }
2443
Paul Crowleycc701552016-05-17 14:18:49 -07002444 /*
2445 * Add this token/secret pair to the set of ways we can recover a disk encryption key.
2446 * Changing the token/secret for a disk encryption key is done in two phases: first, adding
2447 * a new token/secret pair with this call, then delting all other pairs with
2448 * fixateNewestUserKeyAuth. This allows other places where a credential is used, such as
2449 * Gatekeeper, to be updated between the two calls.
2450 */
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002451 @Override
Paul Crowleycc701552016-05-17 14:18:49 -07002452 public void addUserKeyAuth(int userId, int serialNumber, byte[] token, byte[] secret) {
Paul Crowleyfaeb3eb2016-02-08 15:58:29 +00002453 enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
Paul Crowleyfaeb3eb2016-02-08 15:58:29 +00002454
2455 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002456 mVold.addUserKeyAuth(userId, serialNumber, encodeBytes(token), encodeBytes(secret));
Jeff Sharkey43e12112017-09-12 16:31:45 -06002457 } catch (Exception e) {
2458 Slog.wtf(TAG, e);
Paul Crowleycc701552016-05-17 14:18:49 -07002459 }
2460 }
2461
2462 /*
2463 * Delete all disk encryption token/secret pairs except the most recently added one
2464 */
2465 @Override
2466 public void fixateNewestUserKeyAuth(int userId) {
2467 enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
Paul Crowleycc701552016-05-17 14:18:49 -07002468
2469 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002470 mVold.fixateNewestUserKeyAuth(userId);
Jeff Sharkey43e12112017-09-12 16:31:45 -06002471 } catch (Exception e) {
2472 Slog.wtf(TAG, e);
Paul Crowleyfaeb3eb2016-02-08 15:58:29 +00002473 }
2474 }
2475
2476 @Override
2477 public void unlockUserKey(int userId, int serialNumber, byte[] token, byte[] secret) {
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002478 enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002479
Jeff Sharkeyce18c812016-04-27 16:00:41 -06002480 if (StorageManager.isFileEncryptedNativeOrEmulated()) {
Rubin Xu3bf722a2016-12-15 16:07:38 +00002481 // When a user has secure lock screen, require secret to actually unlock.
2482 // This check is mostly in place for emulation mode.
2483 if (mLockPatternUtils.isSecure(userId) && ArrayUtils.isEmpty(secret)) {
2484 throw new IllegalStateException("Secret required to unlock secure user " + userId);
Jeff Sharkeyce18c812016-04-27 16:00:41 -06002485 }
Jeff Sharkeyb9fe5372015-12-03 15:23:08 -07002486
Jeff Sharkeyce18c812016-04-27 16:00:41 -06002487 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002488 mVold.unlockUserKey(userId, serialNumber, encodeBytes(token),
2489 encodeBytes(secret));
Jeff Sharkey43e12112017-09-12 16:31:45 -06002490 } catch (Exception e) {
2491 Slog.wtf(TAG, e);
2492 return;
Jeff Sharkeyce18c812016-04-27 16:00:41 -06002493 }
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002494 }
2495
2496 synchronized (mLock) {
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07002497 mLocalUnlockedUsers = ArrayUtils.appendInt(mLocalUnlockedUsers, userId);
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002498 }
Paul Crowley9139a782017-07-26 13:29:25 -07002499 if (userId == UserHandle.USER_SYSTEM) {
2500 String propertyName = "sys.user." + userId + ".ce_available";
2501 Slog.d(TAG, "Setting property: " + propertyName + "=true");
2502 SystemProperties.set(propertyName, "true");
2503 }
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002504 }
2505
2506 @Override
2507 public void lockUserKey(int userId) {
2508 enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002509
2510 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002511 mVold.lockUserKey(userId);
Jeff Sharkey43e12112017-09-12 16:31:45 -06002512 } catch (Exception e) {
2513 Slog.wtf(TAG, e);
2514 return;
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002515 }
2516
2517 synchronized (mLock) {
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07002518 mLocalUnlockedUsers = ArrayUtils.removeInt(mLocalUnlockedUsers, userId);
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002519 }
2520 }
2521
2522 @Override
2523 public boolean isUserKeyUnlocked(int userId) {
Jeff Sharkeyce18c812016-04-27 16:00:41 -06002524 synchronized (mLock) {
2525 return ArrayUtils.contains(mLocalUnlockedUsers, userId);
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002526 }
2527 }
2528
2529 @Override
Jeff Sharkey47f71082016-02-01 17:03:54 -07002530 public void prepareUserStorage(String volumeUuid, int userId, int serialNumber, int flags) {
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002531 enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002532
2533 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002534 mVold.prepareUserStorage(volumeUuid, userId, serialNumber, flags);
Jeff Sharkey43e12112017-09-12 16:31:45 -06002535 } catch (Exception e) {
2536 Slog.wtf(TAG, e);
Paul Crowley7ec733f2015-05-19 12:42:00 +01002537 }
2538 }
2539
Paul Crowleybcf48ed2015-04-22 13:36:59 +01002540 @Override
Jeff Sharkeyfcf1e552016-04-14 20:44:58 -06002541 public void destroyUserStorage(String volumeUuid, int userId, int flags) {
2542 enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
Jeff Sharkeyfcf1e552016-04-14 20:44:58 -06002543
2544 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002545 mVold.destroyUserStorage(volumeUuid, userId, flags);
Jeff Sharkey43e12112017-09-12 16:31:45 -06002546 } catch (Exception e) {
2547 Slog.wtf(TAG, e);
Jeff Sharkeyfcf1e552016-04-14 20:44:58 -06002548 }
2549 }
2550
Rubin Xuee67b612017-04-27 17:01:05 +01002551 @Override
2552 public void secdiscard(String path) {
2553 enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
Rubin Xuee67b612017-04-27 17:01:05 +01002554
2555 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002556 mVold.secdiscard(path);
Jeff Sharkey43e12112017-09-12 16:31:45 -06002557 } catch (Exception e) {
2558 Slog.wtf(TAG, e);
Rubin Xuee67b612017-04-27 17:01:05 +01002559 }
2560 }
2561
Daichi Hironoe56740d2017-02-02 13:56:45 +09002562 class AppFuseMountScope extends AppFuseBridge.MountScope {
Daichi Hirono812c95d2017-02-08 16:20:20 +09002563 boolean opened = false;
2564
2565 public AppFuseMountScope(int uid, int pid, int mountId) {
2566 super(uid, pid, mountId);
2567 }
2568
2569 @Override
2570 public ParcelFileDescriptor open() throws NativeDaemonConnectorException {
Jeff Sharkey54402792017-09-15 16:05:19 -06002571 try {
2572 return new ParcelFileDescriptor(
2573 mVold.mountAppFuse(uid, Process.myPid(), mountId));
2574 } catch (Exception e) {
2575 throw new NativeDaemonConnectorException("Failed to mount", e);
Daichi Hirono812c95d2017-02-08 16:20:20 +09002576 }
Daichi Hirono9fb00182016-11-08 14:12:17 +09002577 }
2578
2579 @Override
Daichi Hironoe56740d2017-02-02 13:56:45 +09002580 public void close() throws Exception {
Daichi Hirono812c95d2017-02-08 16:20:20 +09002581 if (opened) {
Jeff Sharkey54402792017-09-15 16:05:19 -06002582 mVold.unmountAppFuse(uid, Process.myPid(), mountId);
Daichi Hirono812c95d2017-02-08 16:20:20 +09002583 opened = false;
2584 }
Daichi Hirono9fb00182016-11-08 14:12:17 +09002585 }
2586 }
2587
2588 @Override
Daichi Hirono812c95d2017-02-08 16:20:20 +09002589 public @Nullable AppFuseMount mountProxyFileDescriptorBridge() {
Daichi Hironoe56740d2017-02-02 13:56:45 +09002590 Slog.v(TAG, "mountProxyFileDescriptorBridge");
Daichi Hirono9fb00182016-11-08 14:12:17 +09002591 final int uid = Binder.getCallingUid();
2592 final int pid = Binder.getCallingPid();
Daichi Hirono9fb00182016-11-08 14:12:17 +09002593
Daichi Hironoe56740d2017-02-02 13:56:45 +09002594 while (true) {
2595 synchronized (mAppFuseLock) {
2596 boolean newlyCreated = false;
2597 if (mAppFuseBridge == null) {
2598 mAppFuseBridge = new AppFuseBridge();
2599 new Thread(mAppFuseBridge, AppFuseBridge.TAG).start();
2600 newlyCreated = true;
Daichi Hirono9fb00182016-11-08 14:12:17 +09002601 }
Daichi Hironoe56740d2017-02-02 13:56:45 +09002602 try {
2603 final int name = mNextAppFuseName++;
2604 try {
2605 return new AppFuseMount(
Daichi Hirono812c95d2017-02-08 16:20:20 +09002606 name, mAppFuseBridge.addBridge(new AppFuseMountScope(uid, pid, name)));
2607 } catch (FuseUnavailableMountException e) {
Daichi Hironoe56740d2017-02-02 13:56:45 +09002608 if (newlyCreated) {
2609 // If newly created bridge fails, it's a real error.
Daichi Hirono812c95d2017-02-08 16:20:20 +09002610 Slog.e(TAG, "", e);
2611 return null;
Daichi Hironoe56740d2017-02-02 13:56:45 +09002612 }
2613 // It seems the thread of mAppFuseBridge has already been terminated.
2614 mAppFuseBridge = null;
2615 }
2616 } catch (NativeDaemonConnectorException e) {
2617 throw e.rethrowAsParcelableException();
2618 }
Daichi Hirono9fb00182016-11-08 14:12:17 +09002619 }
Daichi Hirono9fb00182016-11-08 14:12:17 +09002620 }
2621 }
2622
2623 @Override
Daichi Hirono812c95d2017-02-08 16:20:20 +09002624 public @Nullable ParcelFileDescriptor openProxyFileDescriptor(
2625 int mountId, int fileId, int mode) {
2626 Slog.v(TAG, "mountProxyFileDescriptor");
Daichi Hirono9fb00182016-11-08 14:12:17 +09002627 final int pid = Binder.getCallingPid();
2628 try {
2629 synchronized (mAppFuseLock) {
Daichi Hironoe56740d2017-02-02 13:56:45 +09002630 if (mAppFuseBridge == null) {
Daichi Hirono812c95d2017-02-08 16:20:20 +09002631 Slog.e(TAG, "FuseBridge has not been created");
2632 return null;
Daichi Hirono9fb00182016-11-08 14:12:17 +09002633 }
Daichi Hironoe56740d2017-02-02 13:56:45 +09002634 return mAppFuseBridge.openFile(pid, mountId, fileId, mode);
Daichi Hirono9fb00182016-11-08 14:12:17 +09002635 }
Daichi Hirono812c95d2017-02-08 16:20:20 +09002636 } catch (FuseUnavailableMountException | InterruptedException error) {
2637 Slog.v(TAG, "The mount point has already been invalid", error);
2638 return null;
Daichi Hirono9fb00182016-11-08 14:12:17 +09002639 }
2640 }
2641
Daichi Hirono9e8d9e22015-11-13 14:37:00 +09002642 @Override
Jeff Sharkeyae266462017-11-27 13:32:24 -07002643 public void mkdirs(String callingPkg, String appPath) {
Jeff Sharkey2d8b4e82013-09-17 17:30:33 -07002644 final int userId = UserHandle.getUserId(Binder.getCallingUid());
2645 final UserEnvironment userEnv = new UserEnvironment(userId);
2646
2647 // Validate that reported package name belongs to caller
2648 final AppOpsManager appOps = (AppOpsManager) mContext.getSystemService(
2649 Context.APP_OPS_SERVICE);
2650 appOps.checkPackage(Binder.getCallingUid(), callingPkg);
2651
Jeff Sharkey48877892015-03-18 11:27:19 -07002652 File appFile = null;
Jeff Sharkey2d8b4e82013-09-17 17:30:33 -07002653 try {
Jeff Sharkey48877892015-03-18 11:27:19 -07002654 appFile = new File(appPath).getCanonicalFile();
Jeff Sharkey2d8b4e82013-09-17 17:30:33 -07002655 } catch (IOException e) {
Jeff Sharkeyae266462017-11-27 13:32:24 -07002656 throw new IllegalStateException("Failed to resolve " + appPath + ": " + e);
Jeff Sharkey2d8b4e82013-09-17 17:30:33 -07002657 }
2658
2659 // Try translating the app path into a vold path, but require that it
2660 // belong to the calling package.
Jeff Sharkey48877892015-03-18 11:27:19 -07002661 if (FileUtils.contains(userEnv.buildExternalStorageAppDataDirs(callingPkg), appFile) ||
2662 FileUtils.contains(userEnv.buildExternalStorageAppObbDirs(callingPkg), appFile) ||
2663 FileUtils.contains(userEnv.buildExternalStorageAppMediaDirs(callingPkg), appFile)) {
2664 appPath = appFile.getAbsolutePath();
2665 if (!appPath.endsWith("/")) {
2666 appPath = appPath + "/";
2667 }
2668
Jeff Sharkey2d8b4e82013-09-17 17:30:33 -07002669 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06002670 mVold.mkdirs(appPath);
Jeff Sharkey27a108c2017-11-30 17:11:40 -07002671 return;
Jeff Sharkeyace874b2017-09-07 15:27:33 -06002672 } catch (Exception e) {
Jeff Sharkeyae266462017-11-27 13:32:24 -07002673 throw new IllegalStateException("Failed to prepare " + appPath + ": " + e);
Jeff Sharkey2d8b4e82013-09-17 17:30:33 -07002674 }
2675 }
2676
Jeff Sharkey48877892015-03-18 11:27:19 -07002677 throw new SecurityException("Invalid mkdirs path: " + appFile);
Jeff Sharkey2d8b4e82013-09-17 17:30:33 -07002678 }
2679
2680 @Override
Jeff Sharkey46349872015-07-28 10:49:47 -07002681 public StorageVolume[] getVolumeList(int uid, String packageName, int flags) {
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07002682 final int userId = UserHandle.getUserId(uid);
Jeff Sharkeyc02bfae2016-03-27 15:06:53 -06002683
Jeff Sharkey46349872015-07-28 10:49:47 -07002684 final boolean forWrite = (flags & StorageManager.FLAG_FOR_WRITE) != 0;
Jeff Sharkeyc02bfae2016-03-27 15:06:53 -06002685 final boolean realState = (flags & StorageManager.FLAG_REAL_STATE) != 0;
2686 final boolean includeInvisible = (flags & StorageManager.FLAG_INCLUDE_INVISIBLE) != 0;
Jeff Sharkey46349872015-07-28 10:49:47 -07002687
Jeff Sharkeyc02bfae2016-03-27 15:06:53 -06002688 final boolean userKeyUnlocked;
2689 final boolean storagePermission;
2690 final long token = Binder.clearCallingIdentity();
Svetoslav38c3dbb2015-07-14 11:27:06 -07002691 try {
Jeff Sharkeyc02bfae2016-03-27 15:06:53 -06002692 userKeyUnlocked = isUserKeyUnlocked(userId);
Sudheer Shanka2250d562016-11-07 15:41:02 -08002693 storagePermission = mStorageManagerInternal.hasExternalStorage(uid, packageName);
Svetoslav38c3dbb2015-07-14 11:27:06 -07002694 } finally {
Jeff Sharkeyc02bfae2016-03-27 15:06:53 -06002695 Binder.restoreCallingIdentity(token);
Svetoslav38c3dbb2015-07-14 11:27:06 -07002696 }
Svet Ganov6ee871e2015-07-10 14:29:33 -07002697
Jeff Sharkeyc02bfae2016-03-27 15:06:53 -06002698 boolean foundPrimary = false;
2699
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07002700 final ArrayList<StorageVolume> res = new ArrayList<>();
Jeff Sharkey48877892015-03-18 11:27:19 -07002701 synchronized (mLock) {
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07002702 for (int i = 0; i < mVolumes.size(); i++) {
2703 final VolumeInfo vol = mVolumes.valueAt(i);
Jeff Sharkeyc02bfae2016-03-27 15:06:53 -06002704 switch (vol.getType()) {
2705 case VolumeInfo.TYPE_PUBLIC:
2706 case VolumeInfo.TYPE_EMULATED:
2707 break;
2708 default:
2709 continue;
2710 }
2711
2712 boolean match = false;
2713 if (forWrite) {
2714 match = vol.isVisibleForWrite(userId);
2715 } else {
Felipe Leme123a0e72016-06-10 11:09:11 -07002716 match = vol.isVisibleForRead(userId)
2717 || (includeInvisible && vol.getPath() != null);
Jeff Sharkeyc02bfae2016-03-27 15:06:53 -06002718 }
2719 if (!match) continue;
2720
2721 boolean reportUnmounted = false;
2722 if ((vol.getType() == VolumeInfo.TYPE_EMULATED) && !userKeyUnlocked) {
2723 reportUnmounted = true;
2724 } else if (!storagePermission && !realState) {
2725 reportUnmounted = true;
2726 }
2727
2728 final StorageVolume userVol = vol.buildStorageVolume(mContext, userId,
2729 reportUnmounted);
2730 if (vol.isPrimary()) {
2731 res.add(0, userVol);
2732 foundPrimary = true;
2733 } else {
2734 res.add(userVol);
Jeff Sharkeyb049e212012-09-07 23:16:01 -07002735 }
Mike Lockwood8fa5f802011-03-24 08:12:30 -07002736 }
Mike Lockwood8fa5f802011-03-24 08:12:30 -07002737 }
Jeff Sharkey48877892015-03-18 11:27:19 -07002738
2739 if (!foundPrimary) {
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07002740 Log.w(TAG, "No primary storage defined yet; hacking together a stub");
Jeff Sharkey48877892015-03-18 11:27:19 -07002741
2742 final boolean primaryPhysical = SystemProperties.getBoolean(
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07002743 StorageManager.PROP_PRIMARY_PHYSICAL, false);
Jeff Sharkey48877892015-03-18 11:27:19 -07002744
2745 final String id = "stub_primary";
2746 final File path = Environment.getLegacyExternalStorageDirectory();
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07002747 final String description = mContext.getString(android.R.string.unknownName);
Jeff Sharkey48877892015-03-18 11:27:19 -07002748 final boolean primary = true;
2749 final boolean removable = primaryPhysical;
2750 final boolean emulated = !primaryPhysical;
Jeff Sharkey48877892015-03-18 11:27:19 -07002751 final boolean allowMassStorage = false;
2752 final long maxFileSize = 0L;
2753 final UserHandle owner = new UserHandle(userId);
2754 final String uuid = null;
Jeff Sharkey48877892015-03-18 11:27:19 -07002755 final String state = Environment.MEDIA_REMOVED;
2756
Jerry Zhangf9c5c252017-08-16 18:07:51 -07002757 res.add(0, new StorageVolume(id, path,
2758 description, primary, removable, emulated,
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07002759 allowMassStorage, maxFileSize, owner, uuid, state));
Jeff Sharkey48877892015-03-18 11:27:19 -07002760 }
2761
2762 return res.toArray(new StorageVolume[res.size()]);
Mike Lockwood8fa5f802011-03-24 08:12:30 -07002763 }
2764
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07002765 @Override
2766 public DiskInfo[] getDisks() {
2767 synchronized (mLock) {
2768 final DiskInfo[] res = new DiskInfo[mDisks.size()];
2769 for (int i = 0; i < mDisks.size(); i++) {
2770 res[i] = mDisks.valueAt(i);
2771 }
2772 return res;
2773 }
2774 }
2775
2776 @Override
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07002777 public VolumeInfo[] getVolumes(int flags) {
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07002778 synchronized (mLock) {
2779 final VolumeInfo[] res = new VolumeInfo[mVolumes.size()];
2780 for (int i = 0; i < mVolumes.size(); i++) {
2781 res[i] = mVolumes.valueAt(i);
2782 }
2783 return res;
2784 }
2785 }
2786
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07002787 @Override
2788 public VolumeRecord[] getVolumeRecords(int flags) {
2789 synchronized (mLock) {
2790 final VolumeRecord[] res = new VolumeRecord[mRecords.size()];
2791 for (int i = 0; i < mRecords.size(); i++) {
2792 res[i] = mRecords.valueAt(i);
2793 }
2794 return res;
2795 }
2796 }
2797
Jeff Sharkey9bed0702017-01-23 20:37:05 -07002798 @Override
2799 public long getCacheQuotaBytes(String volumeUuid, int uid) {
2800 if (uid != Binder.getCallingUid()) {
2801 mContext.enforceCallingPermission(android.Manifest.permission.STORAGE_INTERNAL, TAG);
2802 }
Daniel Nishi80fdb012017-03-09 14:30:07 -08002803 final long token = Binder.clearCallingIdentity();
2804 final StorageStatsManager stats = mContext.getSystemService(StorageStatsManager.class);
2805 try {
2806 return stats.getCacheQuotaBytes(volumeUuid, uid);
2807 } finally {
2808 Binder.restoreCallingIdentity(token);
2809 }
Jeff Sharkey9bed0702017-01-23 20:37:05 -07002810 }
2811
2812 @Override
2813 public long getCacheSizeBytes(String volumeUuid, int uid) {
2814 if (uid != Binder.getCallingUid()) {
2815 mContext.enforceCallingPermission(android.Manifest.permission.STORAGE_INTERNAL, TAG);
2816 }
2817 final long token = Binder.clearCallingIdentity();
2818 try {
2819 return mContext.getSystemService(StorageStatsManager.class)
2820 .queryStatsForUid(volumeUuid, uid).getCacheBytes();
Jeff Sharkey789a8fc2017-04-16 13:18:35 -06002821 } catch (IOException e) {
2822 throw new ParcelableException(e);
Jeff Sharkey9bed0702017-01-23 20:37:05 -07002823 } finally {
2824 Binder.restoreCallingIdentity(token);
2825 }
2826 }
2827
Jeff Sharkey35e46d22017-06-09 10:01:20 -06002828 private int adjustAllocateFlags(int flags, int callingUid, String callingPackage) {
2829 // Require permission to allocate aggressively
2830 if ((flags & StorageManager.FLAG_ALLOCATE_AGGRESSIVE) != 0) {
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07002831 mContext.enforceCallingOrSelfPermission(
2832 android.Manifest.permission.ALLOCATE_AGGRESSIVE, TAG);
2833 }
2834
Jeff Sharkey35e46d22017-06-09 10:01:20 -06002835 // Apps normally can't directly defy reserved space
2836 flags &= ~StorageManager.FLAG_ALLOCATE_DEFY_ALL_RESERVED;
2837 flags &= ~StorageManager.FLAG_ALLOCATE_DEFY_HALF_RESERVED;
2838
2839 // However, if app is actively using the camera, then we're willing to
2840 // clear up to half of the reserved cache space, since the user might be
2841 // trying to capture an important memory.
2842 final AppOpsManager appOps = mContext.getSystemService(AppOpsManager.class);
2843 final long token = Binder.clearCallingIdentity();
2844 try {
2845 if (appOps.isOperationActive(AppOpsManager.OP_CAMERA, callingUid, callingPackage)) {
2846 Slog.d(TAG, "UID " + callingUid + " is actively using camera;"
2847 + " letting them defy reserved cached data");
2848 flags |= StorageManager.FLAG_ALLOCATE_DEFY_HALF_RESERVED;
2849 }
2850 } finally {
2851 Binder.restoreCallingIdentity(token);
2852 }
2853
2854 return flags;
2855 }
2856
2857 @Override
2858 public long getAllocatableBytes(String volumeUuid, int flags, String callingPackage) {
2859 flags = adjustAllocateFlags(flags, Binder.getCallingUid(), callingPackage);
2860
2861 final StorageManager storage = mContext.getSystemService(StorageManager.class);
2862 final StorageStatsManager stats = mContext.getSystemService(StorageStatsManager.class);
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07002863 final long token = Binder.clearCallingIdentity();
2864 try {
2865 // In general, apps can allocate as much space as they want, except
2866 // we never let them eat into either the minimum cache space or into
Jeff Sharkeyddff8072017-05-26 13:10:46 -06002867 // the low disk warning space. To avoid user confusion, this logic
2868 // should be kept in sync with getFreeBytes().
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07002869 final File path = storage.findPathForUuid(volumeUuid);
Jeff Sharkeyddff8072017-05-26 13:10:46 -06002870
2871 final long usable = path.getUsableSpace();
2872 final long lowReserved = storage.getStorageLowBytes(path);
2873 final long fullReserved = storage.getStorageFullBytes(path);
2874
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07002875 if (stats.isQuotaSupported(volumeUuid)) {
Jeff Sharkeyddff8072017-05-26 13:10:46 -06002876 final long cacheTotal = stats.getCacheBytes(volumeUuid);
Jeff Sharkey35e46d22017-06-09 10:01:20 -06002877 final long cacheReserved = storage.getStorageCacheBytes(path, flags);
Jeff Sharkeyddff8072017-05-26 13:10:46 -06002878 final long cacheClearable = Math.max(0, cacheTotal - cacheReserved);
2879
Jeff Sharkey35e46d22017-06-09 10:01:20 -06002880 if ((flags & StorageManager.FLAG_ALLOCATE_AGGRESSIVE) != 0) {
2881 return Math.max(0, (usable + cacheClearable) - fullReserved);
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07002882 } else {
Jeff Sharkeyddff8072017-05-26 13:10:46 -06002883 return Math.max(0, (usable + cacheClearable) - lowReserved);
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07002884 }
2885 } else {
2886 // When we don't have fast quota information, we ignore cached
2887 // data and only consider unused bytes.
Jeff Sharkey35e46d22017-06-09 10:01:20 -06002888 if ((flags & StorageManager.FLAG_ALLOCATE_AGGRESSIVE) != 0) {
Jeff Sharkeyddff8072017-05-26 13:10:46 -06002889 return Math.max(0, usable - fullReserved);
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07002890 } else {
Jeff Sharkeyddff8072017-05-26 13:10:46 -06002891 return Math.max(0, usable - lowReserved);
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07002892 }
2893 }
Jeff Sharkey789a8fc2017-04-16 13:18:35 -06002894 } catch (IOException e) {
2895 throw new ParcelableException(e);
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07002896 } finally {
2897 Binder.restoreCallingIdentity(token);
2898 }
Jeff Sharkey500ce9e2017-02-12 02:39:24 -07002899 }
2900
2901 @Override
Jeff Sharkey35e46d22017-06-09 10:01:20 -06002902 public void allocateBytes(String volumeUuid, long bytes, int flags, String callingPackage) {
2903 flags = adjustAllocateFlags(flags, Binder.getCallingUid(), callingPackage);
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07002904
Jeff Sharkey35e46d22017-06-09 10:01:20 -06002905 final long allocatableBytes = getAllocatableBytes(volumeUuid, flags, callingPackage);
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07002906 if (bytes > allocatableBytes) {
2907 throw new ParcelableException(new IOException("Failed to allocate " + bytes
2908 + " because only " + allocatableBytes + " allocatable"));
2909 }
2910
Jeff Sharkey35e46d22017-06-09 10:01:20 -06002911 final StorageManager storage = mContext.getSystemService(StorageManager.class);
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07002912 final long token = Binder.clearCallingIdentity();
2913 try {
Jeff Sharkey789a8fc2017-04-16 13:18:35 -06002914 // Free up enough disk space to satisfy both the requested allocation
2915 // and our low disk warning space.
2916 final File path = storage.findPathForUuid(volumeUuid);
Jeff Sharkeyddff8072017-05-26 13:10:46 -06002917 if ((flags & StorageManager.FLAG_ALLOCATE_AGGRESSIVE) != 0) {
2918 bytes += storage.getStorageFullBytes(path);
2919 } else {
2920 bytes += storage.getStorageLowBytes(path);
2921 }
Jeff Sharkey789a8fc2017-04-16 13:18:35 -06002922
Jeff Sharkeyd5d5e922017-02-21 10:51:23 -07002923 mPms.freeStorage(volumeUuid, bytes, flags);
2924 } catch (IOException e) {
2925 throw new ParcelableException(e);
2926 } finally {
2927 Binder.restoreCallingIdentity(token);
Jeff Sharkey500ce9e2017-02-12 02:39:24 -07002928 }
2929 }
2930
Kenny Rootaf9d6672010-10-08 09:21:39 -07002931 private void addObbStateLocked(ObbState obbState) throws RemoteException {
2932 final IBinder binder = obbState.getBinder();
2933 List<ObbState> obbStates = mObbMounts.get(binder);
Kenny Root5919ac62010-10-05 09:49:40 -07002934
Kenny Rootaf9d6672010-10-08 09:21:39 -07002935 if (obbStates == null) {
2936 obbStates = new ArrayList<ObbState>();
2937 mObbMounts.put(binder, obbStates);
2938 } else {
2939 for (final ObbState o : obbStates) {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002940 if (o.rawPath.equals(obbState.rawPath)) {
Kenny Rootaf9d6672010-10-08 09:21:39 -07002941 throw new IllegalStateException("Attempt to add ObbState twice. "
Sudheer Shanka2250d562016-11-07 15:41:02 -08002942 + "This indicates an error in the StorageManagerService logic.");
Kenny Root5919ac62010-10-05 09:49:40 -07002943 }
2944 }
Kenny Roota02b8b02010-08-05 16:14:17 -07002945 }
Kenny Rootaf9d6672010-10-08 09:21:39 -07002946
2947 obbStates.add(obbState);
2948 try {
2949 obbState.link();
2950 } catch (RemoteException e) {
2951 /*
2952 * The binder died before we could link it, so clean up our state
2953 * and return failure.
2954 */
2955 obbStates.remove(obbState);
2956 if (obbStates.isEmpty()) {
2957 mObbMounts.remove(binder);
2958 }
2959
2960 // Rethrow the error so mountObb can get it
2961 throw e;
2962 }
2963
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002964 mObbPathToStateMap.put(obbState.rawPath, obbState);
Kenny Roota02b8b02010-08-05 16:14:17 -07002965 }
2966
Kenny Rootaf9d6672010-10-08 09:21:39 -07002967 private void removeObbStateLocked(ObbState obbState) {
2968 final IBinder binder = obbState.getBinder();
2969 final List<ObbState> obbStates = mObbMounts.get(binder);
2970 if (obbStates != null) {
2971 if (obbStates.remove(obbState)) {
2972 obbState.unlink();
Kenny Root05105f72010-09-22 17:29:43 -07002973 }
Kenny Rootaf9d6672010-10-08 09:21:39 -07002974 if (obbStates.isEmpty()) {
2975 mObbMounts.remove(binder);
2976 }
Kenny Roota02b8b02010-08-05 16:14:17 -07002977 }
Kenny Roota02b8b02010-08-05 16:14:17 -07002978
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002979 mObbPathToStateMap.remove(obbState.rawPath);
Kenny Root38cf8862010-09-26 14:18:51 -07002980 }
2981
Kenny Roota02b8b02010-08-05 16:14:17 -07002982 private class ObbActionHandler extends Handler {
2983 private boolean mBound = false;
Kenny Root480afe72010-10-07 10:17:50 -07002984 private final List<ObbAction> mActions = new LinkedList<ObbAction>();
Kenny Roota02b8b02010-08-05 16:14:17 -07002985
2986 ObbActionHandler(Looper l) {
2987 super(l);
2988 }
2989
2990 @Override
2991 public void handleMessage(Message msg) {
2992 switch (msg.what) {
2993 case OBB_RUN_ACTION: {
Kenny Root480afe72010-10-07 10:17:50 -07002994 final ObbAction action = (ObbAction) msg.obj;
Kenny Roota02b8b02010-08-05 16:14:17 -07002995
2996 if (DEBUG_OBB)
2997 Slog.i(TAG, "OBB_RUN_ACTION: " + action.toString());
2998
2999 // If a bind was already initiated we don't really
3000 // need to do anything. The pending install
3001 // will be processed later on.
3002 if (!mBound) {
3003 // If this is the only one pending we might
3004 // have to bind to the service again.
3005 if (!connectToService()) {
3006 Slog.e(TAG, "Failed to bind to media container service");
3007 action.handleError();
3008 return;
Kenny Roota02b8b02010-08-05 16:14:17 -07003009 }
Kenny Roota02b8b02010-08-05 16:14:17 -07003010 }
Kenny Root735de3b2010-09-30 14:11:39 -07003011
Kenny Root735de3b2010-09-30 14:11:39 -07003012 mActions.add(action);
Kenny Roota02b8b02010-08-05 16:14:17 -07003013 break;
3014 }
3015 case OBB_MCS_BOUND: {
3016 if (DEBUG_OBB)
3017 Slog.i(TAG, "OBB_MCS_BOUND");
3018 if (msg.obj != null) {
3019 mContainerService = (IMediaContainerService) msg.obj;
3020 }
3021 if (mContainerService == null) {
3022 // Something seriously wrong. Bail out
3023 Slog.e(TAG, "Cannot bind to media container service");
3024 for (ObbAction action : mActions) {
3025 // Indicate service bind error
3026 action.handleError();
3027 }
3028 mActions.clear();
3029 } else if (mActions.size() > 0) {
Kenny Root480afe72010-10-07 10:17:50 -07003030 final ObbAction action = mActions.get(0);
Kenny Roota02b8b02010-08-05 16:14:17 -07003031 if (action != null) {
3032 action.execute(this);
3033 }
3034 } else {
3035 // Should never happen ideally.
3036 Slog.w(TAG, "Empty queue");
3037 }
3038 break;
3039 }
3040 case OBB_MCS_RECONNECT: {
3041 if (DEBUG_OBB)
3042 Slog.i(TAG, "OBB_MCS_RECONNECT");
3043 if (mActions.size() > 0) {
3044 if (mBound) {
3045 disconnectService();
3046 }
3047 if (!connectToService()) {
3048 Slog.e(TAG, "Failed to bind to media container service");
3049 for (ObbAction action : mActions) {
3050 // Indicate service bind error
3051 action.handleError();
3052 }
3053 mActions.clear();
3054 }
3055 }
3056 break;
3057 }
3058 case OBB_MCS_UNBIND: {
3059 if (DEBUG_OBB)
3060 Slog.i(TAG, "OBB_MCS_UNBIND");
3061
3062 // Delete pending install
3063 if (mActions.size() > 0) {
3064 mActions.remove(0);
3065 }
3066 if (mActions.size() == 0) {
3067 if (mBound) {
3068 disconnectService();
3069 }
3070 } else {
3071 // There are more pending requests in queue.
3072 // Just post MCS_BOUND message to trigger processing
3073 // of next pending install.
3074 mObbActionHandler.sendEmptyMessage(OBB_MCS_BOUND);
3075 }
3076 break;
3077 }
Kenny Rootaf9d6672010-10-08 09:21:39 -07003078 case OBB_FLUSH_MOUNT_STATE: {
3079 final String path = (String) msg.obj;
3080
3081 if (DEBUG_OBB)
3082 Slog.i(TAG, "Flushing all OBB state for path " + path);
3083
3084 synchronized (mObbMounts) {
3085 final List<ObbState> obbStatesToRemove = new LinkedList<ObbState>();
3086
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003087 final Iterator<ObbState> i = mObbPathToStateMap.values().iterator();
Kenny Rootaf9d6672010-10-08 09:21:39 -07003088 while (i.hasNext()) {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003089 final ObbState state = i.next();
Kenny Rootaf9d6672010-10-08 09:21:39 -07003090
3091 /*
3092 * If this entry's source file is in the volume path
3093 * that got unmounted, remove it because it's no
3094 * longer valid.
3095 */
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003096 if (state.canonicalPath.startsWith(path)) {
3097 obbStatesToRemove.add(state);
Kenny Rootaf9d6672010-10-08 09:21:39 -07003098 }
3099 }
3100
3101 for (final ObbState obbState : obbStatesToRemove) {
3102 if (DEBUG_OBB)
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003103 Slog.i(TAG, "Removing state for " + obbState.rawPath);
Kenny Rootaf9d6672010-10-08 09:21:39 -07003104
3105 removeObbStateLocked(obbState);
3106
3107 try {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003108 obbState.token.onObbResult(obbState.rawPath, obbState.nonce,
Kenny Rootaf9d6672010-10-08 09:21:39 -07003109 OnObbStateChangeListener.UNMOUNTED);
3110 } catch (RemoteException e) {
3111 Slog.i(TAG, "Couldn't send unmount notification for OBB: "
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003112 + obbState.rawPath);
Kenny Rootaf9d6672010-10-08 09:21:39 -07003113 }
3114 }
3115 }
3116 break;
3117 }
Kenny Roota02b8b02010-08-05 16:14:17 -07003118 }
3119 }
3120
3121 private boolean connectToService() {
3122 if (DEBUG_OBB)
3123 Slog.i(TAG, "Trying to bind to DefaultContainerService");
3124
3125 Intent service = new Intent().setComponent(DEFAULT_CONTAINER_COMPONENT);
Jeff Sharkey6dce4962015-07-03 18:08:41 -07003126 if (mContext.bindServiceAsUser(service, mDefContainerConn, Context.BIND_AUTO_CREATE,
Xiaohui Chene4de5a02015-09-22 15:33:31 -07003127 UserHandle.SYSTEM)) {
Kenny Roota02b8b02010-08-05 16:14:17 -07003128 mBound = true;
3129 return true;
3130 }
3131 return false;
3132 }
3133
3134 private void disconnectService() {
3135 mContainerService = null;
3136 mBound = false;
3137 mContext.unbindService(mDefContainerConn);
3138 }
3139 }
3140
3141 abstract class ObbAction {
3142 private static final int MAX_RETRIES = 3;
3143 private int mRetries;
3144
3145 ObbState mObbState;
3146
3147 ObbAction(ObbState obbState) {
3148 mObbState = obbState;
3149 }
3150
3151 public void execute(ObbActionHandler handler) {
3152 try {
3153 if (DEBUG_OBB)
Ben Komalo444eca22011-09-01 15:17:44 -07003154 Slog.i(TAG, "Starting to execute action: " + toString());
Kenny Roota02b8b02010-08-05 16:14:17 -07003155 mRetries++;
3156 if (mRetries > MAX_RETRIES) {
3157 Slog.w(TAG, "Failed to invoke remote methods on default container service. Giving up");
Kenny Root480afe72010-10-07 10:17:50 -07003158 mObbActionHandler.sendEmptyMessage(OBB_MCS_UNBIND);
Kenny Roota02b8b02010-08-05 16:14:17 -07003159 handleError();
Kenny Roota02b8b02010-08-05 16:14:17 -07003160 } else {
3161 handleExecute();
3162 if (DEBUG_OBB)
3163 Slog.i(TAG, "Posting install MCS_UNBIND");
3164 mObbActionHandler.sendEmptyMessage(OBB_MCS_UNBIND);
3165 }
3166 } catch (RemoteException e) {
3167 if (DEBUG_OBB)
3168 Slog.i(TAG, "Posting install MCS_RECONNECT");
3169 mObbActionHandler.sendEmptyMessage(OBB_MCS_RECONNECT);
3170 } catch (Exception e) {
3171 if (DEBUG_OBB)
3172 Slog.d(TAG, "Error handling OBB action", e);
3173 handleError();
Kenny Root17eb6fb2010-10-06 15:02:52 -07003174 mObbActionHandler.sendEmptyMessage(OBB_MCS_UNBIND);
Kenny Roota02b8b02010-08-05 16:14:17 -07003175 }
3176 }
3177
Kenny Root05105f72010-09-22 17:29:43 -07003178 abstract void handleExecute() throws RemoteException, IOException;
Kenny Roota02b8b02010-08-05 16:14:17 -07003179 abstract void handleError();
Kenny Root38cf8862010-09-26 14:18:51 -07003180
3181 protected ObbInfo getObbInfo() throws IOException {
3182 ObbInfo obbInfo;
3183 try {
Xiaohui Chen621b3fc2015-10-02 14:41:42 -07003184 obbInfo = mContainerService.getObbInfo(mObbState.canonicalPath);
Kenny Root38cf8862010-09-26 14:18:51 -07003185 } catch (RemoteException e) {
3186 Slog.d(TAG, "Couldn't call DefaultContainerService to fetch OBB info for "
Xiaohui Chen621b3fc2015-10-02 14:41:42 -07003187 + mObbState.canonicalPath);
Kenny Root38cf8862010-09-26 14:18:51 -07003188 obbInfo = null;
3189 }
3190 if (obbInfo == null) {
Xiaohui Chen621b3fc2015-10-02 14:41:42 -07003191 throw new IOException("Couldn't read OBB file: " + mObbState.canonicalPath);
Kenny Root38cf8862010-09-26 14:18:51 -07003192 }
3193 return obbInfo;
3194 }
3195
Kenny Rootaf9d6672010-10-08 09:21:39 -07003196 protected void sendNewStatusOrIgnore(int status) {
3197 if (mObbState == null || mObbState.token == null) {
3198 return;
3199 }
3200
Kenny Root38cf8862010-09-26 14:18:51 -07003201 try {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003202 mObbState.token.onObbResult(mObbState.rawPath, mObbState.nonce, status);
Kenny Root38cf8862010-09-26 14:18:51 -07003203 } catch (RemoteException e) {
Sudheer Shanka2250d562016-11-07 15:41:02 -08003204 Slog.w(TAG, "StorageEventListener went away while calling onObbStateChanged");
Kenny Root38cf8862010-09-26 14:18:51 -07003205 }
3206 }
Kenny Roota02b8b02010-08-05 16:14:17 -07003207 }
3208
3209 class MountObbAction extends ObbAction {
Ben Komalo444eca22011-09-01 15:17:44 -07003210 private final String mKey;
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003211 private final int mCallingUid;
Kenny Roota02b8b02010-08-05 16:14:17 -07003212
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003213 MountObbAction(ObbState obbState, String key, int callingUid) {
Kenny Roota02b8b02010-08-05 16:14:17 -07003214 super(obbState);
3215 mKey = key;
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003216 mCallingUid = callingUid;
Kenny Roota02b8b02010-08-05 16:14:17 -07003217 }
3218
Jason parks5af0b912010-11-29 09:05:25 -06003219 @Override
Kenny Root735de3b2010-09-30 14:11:39 -07003220 public void handleExecute() throws IOException, RemoteException {
Kenny Rootaf9d6672010-10-08 09:21:39 -07003221 warnOnNotMounted();
3222
Kenny Root38cf8862010-09-26 14:18:51 -07003223 final ObbInfo obbInfo = getObbInfo();
3224
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003225 if (!isUidOwnerOfPackageOrSystem(obbInfo.packageName, mCallingUid)) {
Kenny Rootaf9d6672010-10-08 09:21:39 -07003226 Slog.w(TAG, "Denied attempt to mount OBB " + obbInfo.filename
3227 + " which is owned by " + obbInfo.packageName);
3228 sendNewStatusOrIgnore(OnObbStateChangeListener.ERROR_PERMISSION_DENIED);
3229 return;
Kenny Roota02b8b02010-08-05 16:14:17 -07003230 }
3231
Kenny Rootaf9d6672010-10-08 09:21:39 -07003232 final boolean isMounted;
3233 synchronized (mObbMounts) {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003234 isMounted = mObbPathToStateMap.containsKey(mObbState.rawPath);
Kenny Rootaf9d6672010-10-08 09:21:39 -07003235 }
3236 if (isMounted) {
3237 Slog.w(TAG, "Attempt to mount OBB which is already mounted: " + obbInfo.filename);
3238 sendNewStatusOrIgnore(OnObbStateChangeListener.ERROR_ALREADY_MOUNTED);
3239 return;
3240 }
3241
Kenny Rootaf9d6672010-10-08 09:21:39 -07003242 final String hashedKey;
Jeff Sharkey41cd6812017-09-11 10:32:17 -06003243 final String binderKey;
Kenny Rootaf9d6672010-10-08 09:21:39 -07003244 if (mKey == null) {
3245 hashedKey = "none";
Jeff Sharkey41cd6812017-09-11 10:32:17 -06003246 binderKey = "";
Kenny Rootaf9d6672010-10-08 09:21:39 -07003247 } else {
Kenny Rootaf9d6672010-10-08 09:21:39 -07003248 try {
Kenny Root3b1abba2010-10-13 15:00:07 -07003249 SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
3250
3251 KeySpec ks = new PBEKeySpec(mKey.toCharArray(), obbInfo.salt,
3252 PBKDF2_HASH_ROUNDS, CRYPTO_ALGORITHM_KEY_SIZE);
3253 SecretKey key = factory.generateSecret(ks);
3254 BigInteger bi = new BigInteger(key.getEncoded());
3255 hashedKey = bi.toString(16);
Jeff Sharkey41cd6812017-09-11 10:32:17 -06003256 binderKey = hashedKey;
Kenny Rootaf9d6672010-10-08 09:21:39 -07003257 } catch (NoSuchAlgorithmException e) {
Kenny Root3b1abba2010-10-13 15:00:07 -07003258 Slog.e(TAG, "Could not load PBKDF2 algorithm", e);
3259 sendNewStatusOrIgnore(OnObbStateChangeListener.ERROR_INTERNAL);
3260 return;
3261 } catch (InvalidKeySpecException e) {
3262 Slog.e(TAG, "Invalid key spec when loading PBKDF2 algorithm", e);
3263 sendNewStatusOrIgnore(OnObbStateChangeListener.ERROR_INTERNAL);
Kenny Root38cf8862010-09-26 14:18:51 -07003264 return;
3265 }
Kenny Rootaf9d6672010-10-08 09:21:39 -07003266 }
Kenny Root38cf8862010-09-26 14:18:51 -07003267
Kenny Rootaf9d6672010-10-08 09:21:39 -07003268 int rc = StorageResultCode.OperationSucceeded;
Kenny Rootaf9d6672010-10-08 09:21:39 -07003269 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06003270 mObbState.volId = mVold.createObb(mObbState.canonicalPath, binderKey,
3271 mObbState.ownerGid);
3272 mVold.mount(mObbState.volId, 0, -1);
Jeff Sharkey41cd6812017-09-11 10:32:17 -06003273 } catch (Exception e) {
3274 Slog.w(TAG, e);
3275 rc = StorageResultCode.OperationFailedInternalError;
Kenny Roota02b8b02010-08-05 16:14:17 -07003276 }
3277
Kenny Rootaf9d6672010-10-08 09:21:39 -07003278 if (rc == StorageResultCode.OperationSucceeded) {
3279 if (DEBUG_OBB)
Xiaohui Chen621b3fc2015-10-02 14:41:42 -07003280 Slog.d(TAG, "Successfully mounted OBB " + mObbState.canonicalPath);
Kenny Rootaf9d6672010-10-08 09:21:39 -07003281
3282 synchronized (mObbMounts) {
3283 addObbStateLocked(mObbState);
3284 }
3285
3286 sendNewStatusOrIgnore(OnObbStateChangeListener.MOUNTED);
Kenny Root02c87302010-07-01 08:10:18 -07003287 } else {
Kenny Root05105f72010-09-22 17:29:43 -07003288 Slog.e(TAG, "Couldn't mount OBB file: " + rc);
Kenny Roota02b8b02010-08-05 16:14:17 -07003289
Kenny Rootaf9d6672010-10-08 09:21:39 -07003290 sendNewStatusOrIgnore(OnObbStateChangeListener.ERROR_COULD_NOT_MOUNT);
Kenny Root02c87302010-07-01 08:10:18 -07003291 }
3292 }
3293
Jason parks5af0b912010-11-29 09:05:25 -06003294 @Override
Kenny Roota02b8b02010-08-05 16:14:17 -07003295 public void handleError() {
Kenny Rootaf9d6672010-10-08 09:21:39 -07003296 sendNewStatusOrIgnore(OnObbStateChangeListener.ERROR_INTERNAL);
Kenny Root02c87302010-07-01 08:10:18 -07003297 }
Kenny Roota02b8b02010-08-05 16:14:17 -07003298
3299 @Override
3300 public String toString() {
3301 StringBuilder sb = new StringBuilder();
3302 sb.append("MountObbAction{");
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003303 sb.append(mObbState);
Kenny Roota02b8b02010-08-05 16:14:17 -07003304 sb.append('}');
3305 return sb.toString();
3306 }
3307 }
3308
3309 class UnmountObbAction extends ObbAction {
Ben Komalo444eca22011-09-01 15:17:44 -07003310 private final boolean mForceUnmount;
Kenny Roota02b8b02010-08-05 16:14:17 -07003311
3312 UnmountObbAction(ObbState obbState, boolean force) {
3313 super(obbState);
3314 mForceUnmount = force;
3315 }
3316
Jason parks5af0b912010-11-29 09:05:25 -06003317 @Override
Kenny Root38cf8862010-09-26 14:18:51 -07003318 public void handleExecute() throws IOException {
Kenny Rootaf9d6672010-10-08 09:21:39 -07003319 warnOnNotMounted();
3320
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003321 final ObbState existingState;
Kenny Root38cf8862010-09-26 14:18:51 -07003322 synchronized (mObbMounts) {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003323 existingState = mObbPathToStateMap.get(mObbState.rawPath);
Kenny Rootaf9d6672010-10-08 09:21:39 -07003324 }
Kenny Root38cf8862010-09-26 14:18:51 -07003325
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003326 if (existingState == null) {
Kenny Rootaf9d6672010-10-08 09:21:39 -07003327 sendNewStatusOrIgnore(OnObbStateChangeListener.ERROR_NOT_MOUNTED);
3328 return;
3329 }
3330
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003331 if (existingState.ownerGid != mObbState.ownerGid) {
3332 Slog.w(TAG, "Permission denied attempting to unmount OBB " + existingState.rawPath
3333 + " (owned by GID " + existingState.ownerGid + ")");
Kenny Rootaf9d6672010-10-08 09:21:39 -07003334 sendNewStatusOrIgnore(OnObbStateChangeListener.ERROR_PERMISSION_DENIED);
3335 return;
3336 }
3337
Kenny Rootaf9d6672010-10-08 09:21:39 -07003338 int rc = StorageResultCode.OperationSucceeded;
Kenny Rootaf9d6672010-10-08 09:21:39 -07003339 try {
Jeff Sharkey54402792017-09-15 16:05:19 -06003340 mVold.unmount(mObbState.volId);
3341 mVold.destroyObb(mObbState.volId);
3342 mObbState.volId = null;
Jeff Sharkey41cd6812017-09-11 10:32:17 -06003343 } catch (Exception e) {
3344 Slog.w(TAG, e);
3345 rc = StorageResultCode.OperationFailedInternalError;
Kenny Roota02b8b02010-08-05 16:14:17 -07003346 }
3347
Kenny Rootaf9d6672010-10-08 09:21:39 -07003348 if (rc == StorageResultCode.OperationSucceeded) {
3349 synchronized (mObbMounts) {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003350 removeObbStateLocked(existingState);
Kenny Root38cf8862010-09-26 14:18:51 -07003351 }
3352
Kenny Rootaf9d6672010-10-08 09:21:39 -07003353 sendNewStatusOrIgnore(OnObbStateChangeListener.UNMOUNTED);
Kenny Roota02b8b02010-08-05 16:14:17 -07003354 } else {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003355 Slog.w(TAG, "Could not unmount OBB: " + existingState);
Kenny Rootaf9d6672010-10-08 09:21:39 -07003356 sendNewStatusOrIgnore(OnObbStateChangeListener.ERROR_COULD_NOT_UNMOUNT);
Kenny Roota02b8b02010-08-05 16:14:17 -07003357 }
3358 }
3359
Jason parks5af0b912010-11-29 09:05:25 -06003360 @Override
Kenny Roota02b8b02010-08-05 16:14:17 -07003361 public void handleError() {
Kenny Rootaf9d6672010-10-08 09:21:39 -07003362 sendNewStatusOrIgnore(OnObbStateChangeListener.ERROR_INTERNAL);
Kenny Roota02b8b02010-08-05 16:14:17 -07003363 }
3364
3365 @Override
3366 public String toString() {
3367 StringBuilder sb = new StringBuilder();
3368 sb.append("UnmountObbAction{");
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003369 sb.append(mObbState);
Kenny Roota02b8b02010-08-05 16:14:17 -07003370 sb.append(",force=");
3371 sb.append(mForceUnmount);
Kenny Roota02b8b02010-08-05 16:14:17 -07003372 sb.append('}');
3373 return sb.toString();
3374 }
Kenny Root02c87302010-07-01 08:10:18 -07003375 }
Kenny Root38cf8862010-09-26 14:18:51 -07003376
Jeff Sharkey7e19f532017-11-06 13:54:11 -07003377 private void dispatchOnStatus(IVoldTaskListener listener, int status,
3378 PersistableBundle extras) {
3379 if (listener != null) {
3380 try {
3381 listener.onStatus(status, extras);
3382 } catch (RemoteException ignored) {
3383 }
3384 }
3385 }
3386
3387 private void dispatchOnFinished(IVoldTaskListener listener, int status,
3388 PersistableBundle extras) {
3389 if (listener != null) {
3390 try {
3391 listener.onFinished(status, extras);
3392 } catch (RemoteException ignored) {
3393 }
3394 }
3395 }
3396
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07003397 private static class Callbacks extends Handler {
3398 private static final int MSG_STORAGE_STATE_CHANGED = 1;
3399 private static final int MSG_VOLUME_STATE_CHANGED = 2;
Jeff Sharkey50a05452015-04-29 11:24:52 -07003400 private static final int MSG_VOLUME_RECORD_CHANGED = 3;
3401 private static final int MSG_VOLUME_FORGOTTEN = 4;
3402 private static final int MSG_DISK_SCANNED = 5;
Makoto Onuki9dc575d2015-06-12 16:10:25 -07003403 private static final int MSG_DISK_DESTROYED = 6;
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07003404
Sudheer Shanka2250d562016-11-07 15:41:02 -08003405 private final RemoteCallbackList<IStorageEventListener>
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07003406 mCallbacks = new RemoteCallbackList<>();
3407
3408 public Callbacks(Looper looper) {
3409 super(looper);
3410 }
3411
Sudheer Shanka2250d562016-11-07 15:41:02 -08003412 public void register(IStorageEventListener callback) {
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07003413 mCallbacks.register(callback);
3414 }
3415
Sudheer Shanka2250d562016-11-07 15:41:02 -08003416 public void unregister(IStorageEventListener callback) {
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07003417 mCallbacks.unregister(callback);
3418 }
3419
3420 @Override
3421 public void handleMessage(Message msg) {
3422 final SomeArgs args = (SomeArgs) msg.obj;
3423 final int n = mCallbacks.beginBroadcast();
3424 for (int i = 0; i < n; i++) {
Sudheer Shanka2250d562016-11-07 15:41:02 -08003425 final IStorageEventListener callback = mCallbacks.getBroadcastItem(i);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07003426 try {
3427 invokeCallback(callback, msg.what, args);
3428 } catch (RemoteException ignored) {
3429 }
3430 }
3431 mCallbacks.finishBroadcast();
3432 args.recycle();
3433 }
3434
Sudheer Shanka2250d562016-11-07 15:41:02 -08003435 private void invokeCallback(IStorageEventListener callback, int what, SomeArgs args)
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07003436 throws RemoteException {
3437 switch (what) {
3438 case MSG_STORAGE_STATE_CHANGED: {
3439 callback.onStorageStateChanged((String) args.arg1, (String) args.arg2,
3440 (String) args.arg3);
3441 break;
3442 }
3443 case MSG_VOLUME_STATE_CHANGED: {
3444 callback.onVolumeStateChanged((VolumeInfo) args.arg1, args.argi2, args.argi3);
3445 break;
3446 }
Jeff Sharkey50a05452015-04-29 11:24:52 -07003447 case MSG_VOLUME_RECORD_CHANGED: {
3448 callback.onVolumeRecordChanged((VolumeRecord) args.arg1);
3449 break;
3450 }
3451 case MSG_VOLUME_FORGOTTEN: {
3452 callback.onVolumeForgotten((String) args.arg1);
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07003453 break;
3454 }
Jeff Sharkey620b32b2015-04-23 19:36:02 -07003455 case MSG_DISK_SCANNED: {
3456 callback.onDiskScanned((DiskInfo) args.arg1, args.argi2);
Jeff Sharkey7e92ef32015-04-17 17:35:07 -07003457 break;
3458 }
Makoto Onuki9dc575d2015-06-12 16:10:25 -07003459 case MSG_DISK_DESTROYED: {
3460 callback.onDiskDestroyed((DiskInfo) args.arg1);
3461 break;
3462 }
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07003463 }
3464 }
3465
3466 private void notifyStorageStateChanged(String path, String oldState, String newState) {
3467 final SomeArgs args = SomeArgs.obtain();
3468 args.arg1 = path;
3469 args.arg2 = oldState;
3470 args.arg3 = newState;
3471 obtainMessage(MSG_STORAGE_STATE_CHANGED, args).sendToTarget();
3472 }
3473
3474 private void notifyVolumeStateChanged(VolumeInfo vol, int oldState, int newState) {
3475 final SomeArgs args = SomeArgs.obtain();
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07003476 args.arg1 = vol.clone();
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07003477 args.argi2 = oldState;
3478 args.argi3 = newState;
3479 obtainMessage(MSG_VOLUME_STATE_CHANGED, args).sendToTarget();
3480 }
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07003481
Jeff Sharkey50a05452015-04-29 11:24:52 -07003482 private void notifyVolumeRecordChanged(VolumeRecord rec) {
3483 final SomeArgs args = SomeArgs.obtain();
3484 args.arg1 = rec.clone();
3485 obtainMessage(MSG_VOLUME_RECORD_CHANGED, args).sendToTarget();
3486 }
3487
3488 private void notifyVolumeForgotten(String fsUuid) {
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07003489 final SomeArgs args = SomeArgs.obtain();
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07003490 args.arg1 = fsUuid;
Jeff Sharkey50a05452015-04-29 11:24:52 -07003491 obtainMessage(MSG_VOLUME_FORGOTTEN, args).sendToTarget();
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07003492 }
Jeff Sharkey7e92ef32015-04-17 17:35:07 -07003493
Jeff Sharkey620b32b2015-04-23 19:36:02 -07003494 private void notifyDiskScanned(DiskInfo disk, int volumeCount) {
Jeff Sharkey7e92ef32015-04-17 17:35:07 -07003495 final SomeArgs args = SomeArgs.obtain();
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07003496 args.arg1 = disk.clone();
Jeff Sharkey620b32b2015-04-23 19:36:02 -07003497 args.argi2 = volumeCount;
3498 obtainMessage(MSG_DISK_SCANNED, args).sendToTarget();
Jeff Sharkey7e92ef32015-04-17 17:35:07 -07003499 }
Makoto Onuki9dc575d2015-06-12 16:10:25 -07003500
3501 private void notifyDiskDestroyed(DiskInfo disk) {
3502 final SomeArgs args = SomeArgs.obtain();
3503 args.arg1 = disk.clone();
3504 obtainMessage(MSG_DISK_DESTROYED, args).sendToTarget();
3505 }
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07003506 }
3507
Kenny Root38cf8862010-09-26 14:18:51 -07003508 @Override
Jeff Sharkey5aca2b82013-10-16 16:21:54 -07003509 protected void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
Jeff Sharkeyfe9a53b2017-03-31 14:08:23 -06003510 if (!DumpUtils.checkDumpPermission(mContext, TAG, writer)) return;
Jeff Sharkey5aca2b82013-10-16 16:21:54 -07003511
3512 final IndentingPrintWriter pw = new IndentingPrintWriter(writer, " ", 160);
Jeff Sharkey27de30d2015-04-18 16:20:27 -07003513 synchronized (mLock) {
3514 pw.println("Disks:");
3515 pw.increaseIndent();
3516 for (int i = 0; i < mDisks.size(); i++) {
3517 final DiskInfo disk = mDisks.valueAt(i);
3518 disk.dump(pw);
3519 }
3520 pw.decreaseIndent();
3521
3522 pw.println();
3523 pw.println("Volumes:");
3524 pw.increaseIndent();
3525 for (int i = 0; i < mVolumes.size(); i++) {
3526 final VolumeInfo vol = mVolumes.valueAt(i);
3527 if (VolumeInfo.ID_PRIVATE_INTERNAL.equals(vol.id)) continue;
3528 vol.dump(pw);
3529 }
3530 pw.decreaseIndent();
3531
3532 pw.println();
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07003533 pw.println("Records:");
Jeff Sharkey27de30d2015-04-18 16:20:27 -07003534 pw.increaseIndent();
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07003535 for (int i = 0; i < mRecords.size(); i++) {
3536 final VolumeRecord note = mRecords.valueAt(i);
3537 note.dump(pw);
Jeff Sharkey27de30d2015-04-18 16:20:27 -07003538 }
3539 pw.decreaseIndent();
Jeff Sharkey275e3e42015-04-24 16:10:32 -07003540
3541 pw.println();
3542 pw.println("Primary storage UUID: " + mPrimaryStorageUuid);
Felipe Leme281389a2016-10-10 17:12:20 -07003543 final Pair<String, Long> pair = StorageManager.getPrimaryStoragePathAndSize();
3544 if (pair == null) {
3545 pw.println("Internal storage total size: N/A");
3546 } else {
3547 pw.print("Internal storage (");
3548 pw.print(pair.first);
3549 pw.print(") total size: ");
3550 pw.print(pair.second);
3551 pw.print(" (");
Jeff Sharkey9f2dc052018-01-07 16:47:31 -07003552 pw.print(DataUnit.MEBIBYTES.toBytes(pair.second));
3553 pw.println(" MiB)");
Felipe Leme281389a2016-10-10 17:12:20 -07003554 }
Jeff Sharkey4c099d02015-05-15 13:45:00 -07003555 pw.println("Force adoptable: " + mForceAdoptable);
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08003556 pw.println();
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07003557 pw.println("Local unlocked users: " + Arrays.toString(mLocalUnlockedUsers));
3558 pw.println("System unlocked users: " + Arrays.toString(mSystemUnlockedUsers));
Jeff Sharkey27de30d2015-04-18 16:20:27 -07003559 }
Kenny Root38cf8862010-09-26 14:18:51 -07003560
Kenny Root38cf8862010-09-26 14:18:51 -07003561 synchronized (mObbMounts) {
Jeff Sharkey27de30d2015-04-18 16:20:27 -07003562 pw.println();
Jeff Sharkey5aca2b82013-10-16 16:21:54 -07003563 pw.println("mObbMounts:");
3564 pw.increaseIndent();
3565 final Iterator<Entry<IBinder, List<ObbState>>> binders = mObbMounts.entrySet()
3566 .iterator();
Kenny Rootaf9d6672010-10-08 09:21:39 -07003567 while (binders.hasNext()) {
3568 Entry<IBinder, List<ObbState>> e = binders.next();
Jeff Sharkey5aca2b82013-10-16 16:21:54 -07003569 pw.println(e.getKey() + ":");
3570 pw.increaseIndent();
Kenny Rootaf9d6672010-10-08 09:21:39 -07003571 final List<ObbState> obbStates = e.getValue();
Kenny Root38cf8862010-09-26 14:18:51 -07003572 for (final ObbState obbState : obbStates) {
Jeff Sharkey5aca2b82013-10-16 16:21:54 -07003573 pw.println(obbState);
Kenny Root38cf8862010-09-26 14:18:51 -07003574 }
Jeff Sharkey5aca2b82013-10-16 16:21:54 -07003575 pw.decreaseIndent();
Kenny Root38cf8862010-09-26 14:18:51 -07003576 }
Jeff Sharkey5aca2b82013-10-16 16:21:54 -07003577 pw.decreaseIndent();
Kenny Rootaf9d6672010-10-08 09:21:39 -07003578
Jeff Sharkey5aca2b82013-10-16 16:21:54 -07003579 pw.println();
3580 pw.println("mObbPathToStateMap:");
3581 pw.increaseIndent();
Kenny Rootaf9d6672010-10-08 09:21:39 -07003582 final Iterator<Entry<String, ObbState>> maps = mObbPathToStateMap.entrySet().iterator();
3583 while (maps.hasNext()) {
3584 final Entry<String, ObbState> e = maps.next();
Jeff Sharkey5aca2b82013-10-16 16:21:54 -07003585 pw.print(e.getKey());
3586 pw.print(" -> ");
3587 pw.println(e.getValue());
Kenny Rootaf9d6672010-10-08 09:21:39 -07003588 }
Jeff Sharkey5aca2b82013-10-16 16:21:54 -07003589 pw.decreaseIndent();
Kenny Root38cf8862010-09-26 14:18:51 -07003590 }
Kenny Root4161f9b2011-07-13 09:48:33 -07003591
Robert Greenwalt470fd722012-01-18 12:51:15 -08003592 pw.println();
Christopher Tate7265abe2014-11-21 13:54:45 -08003593 pw.print("Last maintenance: ");
Jeff Sharkeye8a4b662015-06-27 15:43:45 -07003594 pw.println(TimeUtils.formatForLogging(mLastMaintenance));
Kenny Root38cf8862010-09-26 14:18:51 -07003595 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003596
Jeff Sharkeyfa23c5a2011-08-09 21:44:24 -07003597 /** {@inheritDoc} */
Jeff Sharkey48877892015-03-18 11:27:19 -07003598 @Override
Jeff Sharkeyfa23c5a2011-08-09 21:44:24 -07003599 public void monitor() {
Jeff Sharkey54402792017-09-15 16:05:19 -06003600 try {
3601 mVold.monitor();
3602 } catch (Exception e) {
3603 Slog.wtf(TAG, e);
Paul Lawrence1c62cbb2015-06-03 14:14:52 -07003604 }
Jeff Sharkeyfa23c5a2011-08-09 21:44:24 -07003605 }
Svet Ganov6ee871e2015-07-10 14:29:33 -07003606
Sudheer Shanka2250d562016-11-07 15:41:02 -08003607 private final class StorageManagerInternalImpl extends StorageManagerInternal {
Svet Ganov6ee871e2015-07-10 14:29:33 -07003608 // Not guarded by a lock.
3609 private final CopyOnWriteArrayList<ExternalStorageMountPolicy> mPolicies =
3610 new CopyOnWriteArrayList<>();
3611
3612 @Override
3613 public void addExternalStoragePolicy(ExternalStorageMountPolicy policy) {
3614 // No locking - CopyOnWriteArrayList
3615 mPolicies.add(policy);
3616 }
3617
3618 @Override
3619 public void onExternalStoragePolicyChanged(int uid, String packageName) {
3620 final int mountMode = getExternalStorageMountMode(uid, packageName);
3621 remountUidExternalStorage(uid, mountMode);
3622 }
3623
3624 @Override
3625 public int getExternalStorageMountMode(int uid, String packageName) {
3626 // No locking - CopyOnWriteArrayList
3627 int mountMode = Integer.MAX_VALUE;
3628 for (ExternalStorageMountPolicy policy : mPolicies) {
3629 final int policyMode = policy.getMountMode(uid, packageName);
3630 if (policyMode == Zygote.MOUNT_EXTERNAL_NONE) {
3631 return Zygote.MOUNT_EXTERNAL_NONE;
3632 }
3633 mountMode = Math.min(mountMode, policyMode);
3634 }
3635 if (mountMode == Integer.MAX_VALUE) {
3636 return Zygote.MOUNT_EXTERNAL_NONE;
3637 }
3638 return mountMode;
3639 }
3640
3641 public boolean hasExternalStorage(int uid, String packageName) {
Amith Yamasani2bd5cff2015-07-22 14:42:31 -07003642 // No need to check for system uid. This avoids a deadlock between
3643 // PackageManagerService and AppOpsService.
3644 if (uid == Process.SYSTEM_UID) {
3645 return true;
3646 }
Svet Ganov6ee871e2015-07-10 14:29:33 -07003647 // No locking - CopyOnWriteArrayList
3648 for (ExternalStorageMountPolicy policy : mPolicies) {
3649 final boolean policyHasStorage = policy.hasExternalStorage(uid, packageName);
3650 if (!policyHasStorage) {
3651 return false;
3652 }
3653 }
3654 return true;
3655 }
3656 }
Jeff Sharkeyfa23c5a2011-08-09 21:44:24 -07003657}