blob: 94acd751c6c4d1213f0dfab080170e0f8596c0f0 [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
2 * Copyright (C) 2007 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.server;
18
Jeff Sharkey4c099d02015-05-15 13:45:00 -070019import static com.android.internal.util.XmlUtils.readBooleanAttribute;
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -070020import static com.android.internal.util.XmlUtils.readIntAttribute;
Jeff Sharkeye8a4b662015-06-27 15:43:45 -070021import static com.android.internal.util.XmlUtils.readLongAttribute;
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -070022import static com.android.internal.util.XmlUtils.readStringAttribute;
Jeff Sharkey4c099d02015-05-15 13:45:00 -070023import static com.android.internal.util.XmlUtils.writeBooleanAttribute;
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -070024import static com.android.internal.util.XmlUtils.writeIntAttribute;
Jeff Sharkeye8a4b662015-06-27 15:43:45 -070025import static com.android.internal.util.XmlUtils.writeLongAttribute;
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -070026import static com.android.internal.util.XmlUtils.writeStringAttribute;
Jeff Sharkey5217cac2015-12-20 15:34:01 -070027
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -070028import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT;
29import static org.xmlpull.v1.XmlPullParser.START_TAG;
30
Jason parks8888c592011-01-20 22:46:41 -060031import android.Manifest;
Jeff Sharkeyef10ee02015-07-05 14:17:27 -070032import android.annotation.Nullable;
Xiaohui Chen621b3fc2015-10-02 14:41:42 -070033import android.app.ActivityManager;
Jeff Sharkey2d8b4e82013-09-17 17:30:33 -070034import android.app.AppOpsManager;
Jeff Sharkey14cbe522015-07-08 14:06:37 -070035import android.app.IActivityManager;
Jeff Sharkeybcd262d2015-06-10 09:41:17 -070036import android.content.BroadcastReceiver;
Kenny Roota02b8b02010-08-05 16:14:17 -070037import android.content.ComponentName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080038import android.content.Context;
39import android.content.Intent;
Jeff Sharkeybcd262d2015-06-10 09:41:17 -070040import android.content.IntentFilter;
Kenny Roota02b8b02010-08-05 16:14:17 -070041import android.content.ServiceConnection;
Jeff Sharkey275e3e42015-04-24 16:10:32 -070042import android.content.pm.IPackageMoveObserver;
43import android.content.pm.PackageManager;
Jeff Sharkey14cbe522015-07-08 14:06:37 -070044import android.content.pm.ProviderInfo;
Jeff Sharkeybcd262d2015-06-10 09:41:17 -070045import android.content.pm.UserInfo;
Elliott Hughesf839b4f2014-09-26 12:30:47 -070046import android.content.res.Configuration;
Kenny Root02c87302010-07-01 08:10:18 -070047import android.content.res.ObbInfo;
Felipe Leme281389a2016-10-10 17:12:20 -070048import android.net.TrafficStats;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080049import android.net.Uri;
Kenny Root02c87302010-07-01 08:10:18 -070050import android.os.Binder;
Jeff Sharkey4c099d02015-05-15 13:45:00 -070051import android.os.DropBoxManager;
Kenny Roota02b8b02010-08-05 16:14:17 -070052import android.os.Environment;
Jeff Sharkeyb049e212012-09-07 23:16:01 -070053import android.os.Environment.UserEnvironment;
Jeff Sharkey48877892015-03-18 11:27:19 -070054import android.os.FileUtils;
Suchi Amalapurapuc42e29e2010-02-22 16:03:53 -080055import android.os.Handler;
Dianne Hackbornefa92b22013-05-03 14:11:43 -070056import android.os.HandlerThread;
Kenny Roota02b8b02010-08-05 16:14:17 -070057import android.os.IBinder;
Daniel Sandler5f27ef42010-03-16 15:42:02 -040058import android.os.Looper;
Suchi Amalapurapuc42e29e2010-02-22 16:03:53 -080059import android.os.Message;
Daichi Hirono9e8d9e22015-11-13 14:37:00 +090060import android.os.ParcelFileDescriptor;
Jeff Sharkeyce14cd02015-12-07 15:35:42 -070061import android.os.PowerManager;
Jeff Sharkey9527b222015-06-24 15:24:48 -070062import android.os.Process;
Jeff Sharkey7151a9a2015-04-04 15:22:37 -070063import android.os.RemoteCallbackList;
San Mehat4270e1e2010-01-29 05:32:19 -080064import android.os.RemoteException;
Suchi Amalapurapufd3530f2010-01-18 00:15:59 -080065import android.os.ServiceManager;
Jeff Sharkeyedcdaf62015-07-09 09:45:36 -070066import android.os.SystemClock;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080067import android.os.SystemProperties;
Dianne Hackbornf02b60a2012-08-16 10:48:27 -070068import android.os.UserHandle;
Emily Bernier92aa5a22014-07-07 10:11:48 -040069import android.os.UserManager;
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -070070import android.os.storage.DiskInfo;
Sudheer Shanka2250d562016-11-07 15:41:02 -080071import android.os.storage.IStorageEventListener;
72import android.os.storage.IStorageShutdownObserver;
Kenny Roota02b8b02010-08-05 16:14:17 -070073import android.os.storage.IObbActionListener;
Sudheer Shanka2250d562016-11-07 15:41:02 -080074import android.os.storage.IStorageManager;
75import android.os.storage.StorageManagerInternal;
Kenny Rootaf9d6672010-10-08 09:21:39 -070076import android.os.storage.OnObbStateChangeListener;
Paul Lawrence46791e72014-04-03 09:10:26 -070077import android.os.storage.StorageManager;
Kenny Roota02b8b02010-08-05 16:14:17 -070078import android.os.storage.StorageResultCode;
Mike Lockwood2f6a3882011-05-09 19:08:06 -070079import android.os.storage.StorageVolume;
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -070080import android.os.storage.VolumeInfo;
Jeff Sharkeyb36586a2015-04-27 08:42:28 -070081import android.os.storage.VolumeRecord;
Jeff Sharkey14cbe522015-07-08 14:06:37 -070082import android.provider.MediaStore;
Jeff Sharkeye8a4b662015-06-27 15:43:45 -070083import android.provider.Settings;
Jason parksf7b3cd42011-01-27 09:28:25 -060084import android.text.TextUtils;
Jeff Sharkey1783f142015-04-17 10:52:51 -070085import android.text.format.DateUtils;
Jeff Sharkey48877892015-03-18 11:27:19 -070086import android.util.ArrayMap;
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -070087import android.util.AtomicFile;
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -070088import android.util.Log;
Felipe Leme281389a2016-10-10 17:12:20 -070089import android.util.Pair;
San Mehata5078592010-03-25 09:36:54 -070090import android.util.Slog;
Daichi Hirono9fb00182016-11-08 14:12:17 +090091import android.util.SparseArray;
Jeff Sharkeye8a4b662015-06-27 15:43:45 -070092import android.util.TimeUtils;
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -070093import android.util.Xml;
Jeff Sharkey48877892015-03-18 11:27:19 -070094
Jeff Sharkey8b2c3a142012-11-12 11:45:05 -080095import com.android.internal.annotations.GuardedBy;
Jeff Sharkeyb049e212012-09-07 23:16:01 -070096import com.android.internal.app.IMediaContainerService;
Daichi Hirono9fb00182016-11-08 14:12:17 +090097import com.android.internal.os.AppFuseMount;
Jeff Sharkey7151a9a2015-04-04 15:22:37 -070098import com.android.internal.os.SomeArgs;
Jeff Sharkey9527b222015-06-24 15:24:48 -070099import com.android.internal.os.Zygote;
Jeff Sharkey48877892015-03-18 11:27:19 -0700100import com.android.internal.util.ArrayUtils;
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700101import com.android.internal.util.FastXmlSerializer;
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -0800102import com.android.internal.util.HexDump;
Jeff Sharkey5aca2b82013-10-16 16:21:54 -0700103import com.android.internal.util.IndentingPrintWriter;
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700104import com.android.internal.util.Preconditions;
Jeff Sharkeyb9fe5372015-12-03 15:23:08 -0700105import com.android.internal.widget.LockPatternUtils;
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700106import com.android.server.NativeDaemonConnector.Command;
Jeff Sharkey56cd6462013-06-07 15:09:15 -0700107import com.android.server.NativeDaemonConnector.SensitiveArg;
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700108import com.android.server.pm.PackageManagerService;
Daichi Hirono9fb00182016-11-08 14:12:17 +0900109import com.android.server.storage.AppFuseBridge;
Jeff Sharkey5217cac2015-12-20 15:34:01 -0700110import libcore.io.IoUtils;
111import libcore.util.EmptyArray;
112
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700113import org.xmlpull.v1.XmlPullParser;
114import org.xmlpull.v1.XmlPullParserException;
115import org.xmlpull.v1.XmlSerializer;
116
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700117import java.io.File;
Kenny Root38cf8862010-09-26 14:18:51 -0700118import java.io.FileDescriptor;
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700119import java.io.FileInputStream;
120import java.io.FileNotFoundException;
Christopher Tate7265abe2014-11-21 13:54:45 -0800121import java.io.FileOutputStream;
Kenny Root05105f72010-09-22 17:29:43 -0700122import java.io.IOException;
Kenny Root38cf8862010-09-26 14:18:51 -0700123import java.io.PrintWriter;
Kenny Root3b1abba2010-10-13 15:00:07 -0700124import java.math.BigInteger;
Paul Lawrence8e397362014-01-27 15:22:30 -0800125import java.nio.charset.StandardCharsets;
Kenny Root735de3b2010-09-30 14:11:39 -0700126import java.security.NoSuchAlgorithmException;
Kenny Root3b1abba2010-10-13 15:00:07 -0700127import java.security.spec.InvalidKeySpecException;
128import java.security.spec.KeySpec;
San Mehat22dd86e2010-01-12 12:21:18 -0800129import java.util.ArrayList;
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -0800130import java.util.Arrays;
Kenny Roota02b8b02010-08-05 16:14:17 -0700131import java.util.HashMap;
San Mehat6cdd9c02010-02-09 14:45:20 -0800132import java.util.HashSet;
Kenny Root38cf8862010-09-26 14:18:51 -0700133import java.util.Iterator;
Kenny Roota02b8b02010-08-05 16:14:17 -0700134import java.util.LinkedList;
135import java.util.List;
Elliott Hughesf839b4f2014-09-26 12:30:47 -0700136import java.util.Locale;
Kenny Roota02b8b02010-08-05 16:14:17 -0700137import java.util.Map;
Kenny Root38cf8862010-09-26 14:18:51 -0700138import java.util.Map.Entry;
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700139import java.util.Objects;
Daichi Hirono9fb00182016-11-08 14:12:17 +0900140import java.util.concurrent.ArrayBlockingQueue;
Svet Ganov6ee871e2015-07-10 14:29:33 -0700141import java.util.concurrent.CopyOnWriteArrayList;
Kenny Root51a573c2012-05-17 13:30:28 -0700142import java.util.concurrent.CountDownLatch;
143import java.util.concurrent.TimeUnit;
Jeff Sharkeyedcdaf62015-07-09 09:45:36 -0700144import java.util.concurrent.TimeoutException;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800145
Kenny Root3b1abba2010-10-13 15:00:07 -0700146import javax.crypto.SecretKey;
147import javax.crypto.SecretKeyFactory;
148import javax.crypto.spec.PBEKeySpec;
149
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800150/**
Jeff Sharkey48877892015-03-18 11:27:19 -0700151 * Service responsible for various storage media. Connects to {@code vold} to
152 * watch for and manage dynamically added storage, such as SD cards and USB mass
153 * storage. Also decides how storage should be presented to users on the device.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800154 */
Sudheer Shanka2250d562016-11-07 15:41:02 -0800155class StorageManagerService extends IStorageManager.Stub
Jeff Sharkeyfa23c5a2011-08-09 21:44:24 -0700156 implements INativeDaemonConnectorCallbacks, Watchdog.Monitor {
Jason parks5af0b912010-11-29 09:05:25 -0600157
Christopher Tated417d622013-08-19 16:14:25 -0700158 // Static direct instance pointer for the tightly-coupled idle service to use
Sudheer Shanka2250d562016-11-07 15:41:02 -0800159 static StorageManagerService sSelf = null;
Christopher Tated417d622013-08-19 16:14:25 -0700160
Jeff Sharkey56e62932015-03-21 20:41:00 -0700161 public static class Lifecycle extends SystemService {
Sudheer Shanka2250d562016-11-07 15:41:02 -0800162 private StorageManagerService mStorageManagerService;
Jeff Sharkey56e62932015-03-21 20:41:00 -0700163
164 public Lifecycle(Context context) {
165 super(context);
166 }
167
168 @Override
169 public void onStart() {
Sudheer Shanka2250d562016-11-07 15:41:02 -0800170 mStorageManagerService = new StorageManagerService(getContext());
171 publishBinderService("mount", mStorageManagerService);
172 mStorageManagerService.start();
Jeff Sharkey56e62932015-03-21 20:41:00 -0700173 }
174
175 @Override
176 public void onBootPhase(int phase) {
177 if (phase == SystemService.PHASE_ACTIVITY_MANAGER_READY) {
Sudheer Shanka2250d562016-11-07 15:41:02 -0800178 mStorageManagerService.systemReady();
Yasuhiro Matsuda87a38b52015-07-24 22:10:16 +0900179 } else if (phase == SystemService.PHASE_BOOT_COMPLETED) {
Sudheer Shanka2250d562016-11-07 15:41:02 -0800180 mStorageManagerService.bootCompleted();
Jeff Sharkey56e62932015-03-21 20:41:00 -0700181 }
182 }
Jeff Sharkey48877892015-03-18 11:27:19 -0700183
184 @Override
Jeff Sharkeyab15c392016-05-05 11:45:01 -0600185 public void onSwitchUser(int userHandle) {
Sudheer Shanka2250d562016-11-07 15:41:02 -0800186 mStorageManagerService.mCurrentUserId = userHandle;
Jeff Sharkeyab15c392016-05-05 11:45:01 -0600187 }
188
189 @Override
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700190 public void onUnlockUser(int userHandle) {
Sudheer Shanka2250d562016-11-07 15:41:02 -0800191 mStorageManagerService.onUnlockUser(userHandle);
Jeff Sharkey48877892015-03-18 11:27:19 -0700192 }
193
194 @Override
195 public void onCleanupUser(int userHandle) {
Sudheer Shanka2250d562016-11-07 15:41:02 -0800196 mStorageManagerService.onCleanupUser(userHandle);
Jeff Sharkey48877892015-03-18 11:27:19 -0700197 }
Jeff Sharkey56e62932015-03-21 20:41:00 -0700198 }
199
Dianne Hackborn40e9f292012-11-27 19:12:23 -0800200 private static final boolean DEBUG_EVENTS = false;
Kenny Rootb7db2722011-01-25 16:39:35 -0800201 private static final boolean DEBUG_OBB = false;
Kenny Root02c87302010-07-01 08:10:18 -0700202
Kenny Root07714d42011-08-17 17:49:28 -0700203 // Disable this since it messes up long-running cryptfs operations.
204 private static final boolean WATCHDOG_ENABLE = false;
205
Jeff Sharkey00455bf2016-11-04 14:45:24 -0600206 /**
207 * Our goal is for all Android devices to be usable as development devices,
208 * which includes the new Direct Boot mode added in N. For devices that
209 * don't have native FBE support, we offer an emulation mode for developer
210 * testing purposes, but if it's prohibitively difficult to support this
211 * mode, it can be disabled for specific products using this flag.
212 */
213 private static final boolean EMULATE_FBE_SUPPORTED = true;
214
Sudheer Shanka2250d562016-11-07 15:41:02 -0800215 private static final String TAG = "StorageManagerService";
Jeff Sharkeye8a4b662015-06-27 15:43:45 -0700216
Jeff Sharkey9756d752015-05-14 21:07:42 -0700217 private static final String TAG_STORAGE_BENCHMARK = "storage_benchmark";
Jeff Sharkeye8a4b662015-06-27 15:43:45 -0700218 private static final String TAG_STORAGE_TRIM = "storage_trim";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800219
Kenny Root305bcbf2010-09-03 07:56:38 -0700220 private static final String VOLD_TAG = "VoldConnector";
Paul Lawrence1c62cbb2015-06-03 14:14:52 -0700221 private static final String CRYPTD_TAG = "CryptdConnector";
Kenny Root305bcbf2010-09-03 07:56:38 -0700222
Kenny Rootcf0b38c2011-03-22 14:17:59 -0700223 /** Maximum number of ASEC containers allowed to be mounted. */
224 private static final int MAX_CONTAINERS = 250;
225
Jeff Sharkey275e3e42015-04-24 16:10:32 -0700226 /** Magic value sent by MoveTask.cpp */
227 private static final int MOVE_STATUS_COPY_FINISHED = 82;
228
San Mehat4270e1e2010-01-29 05:32:19 -0800229 /*
230 * Internal vold response code constants
231 */
San Mehat22dd86e2010-01-12 12:21:18 -0800232 class VoldResponseCode {
San Mehat4270e1e2010-01-29 05:32:19 -0800233 /*
234 * 100 series - Requestion action was initiated; expect another reply
235 * before proceeding with a new command.
236 */
San Mehat22dd86e2010-01-12 12:21:18 -0800237 public static final int VolumeListResult = 110;
238 public static final int AsecListResult = 111;
San Mehatc1b4ce92010-02-16 17:13:03 -0800239 public static final int StorageUsersListResult = 112;
Paul Lawrencee51dcf92014-03-18 10:56:00 -0700240 public static final int CryptfsGetfieldResult = 113;
San Mehat22dd86e2010-01-12 12:21:18 -0800241
San Mehat4270e1e2010-01-29 05:32:19 -0800242 /*
243 * 200 series - Requestion action has been successfully completed.
244 */
245 public static final int ShareStatusResult = 210;
San Mehat22dd86e2010-01-12 12:21:18 -0800246 public static final int AsecPathResult = 211;
San Mehat4270e1e2010-01-29 05:32:19 -0800247 public static final int ShareEnabledResult = 212;
San Mehat22dd86e2010-01-12 12:21:18 -0800248
San Mehat4270e1e2010-01-29 05:32:19 -0800249 /*
250 * 400 series - Command was accepted, but the requested action
251 * did not take place.
252 */
253 public static final int OpFailedNoMedia = 401;
254 public static final int OpFailedMediaBlank = 402;
255 public static final int OpFailedMediaCorrupt = 403;
256 public static final int OpFailedVolNotMounted = 404;
San Mehatd9709982010-02-18 11:43:03 -0800257 public static final int OpFailedStorageBusy = 405;
San Mehat2d66cef2010-03-23 11:12:52 -0700258 public static final int OpFailedStorageNotFound = 406;
San Mehat4270e1e2010-01-29 05:32:19 -0800259
260 /*
261 * 600 series - Unsolicited broadcasts.
262 */
Jeff Sharkey48877892015-03-18 11:27:19 -0700263 public static final int DISK_CREATED = 640;
264 public static final int DISK_SIZE_CHANGED = 641;
265 public static final int DISK_LABEL_CHANGED = 642;
Jeff Sharkeyeba260d2015-04-19 14:35:16 -0700266 public static final int DISK_SCANNED = 643;
Jeff Sharkeye8a4b662015-06-27 15:43:45 -0700267 public static final int DISK_SYS_PATH_CHANGED = 644;
Jeff Sharkey48877892015-03-18 11:27:19 -0700268 public static final int DISK_DESTROYED = 649;
269
270 public static final int VOLUME_CREATED = 650;
271 public static final int VOLUME_STATE_CHANGED = 651;
272 public static final int VOLUME_FS_TYPE_CHANGED = 652;
273 public static final int VOLUME_FS_UUID_CHANGED = 653;
274 public static final int VOLUME_FS_LABEL_CHANGED = 654;
275 public static final int VOLUME_PATH_CHANGED = 655;
Jeff Sharkey50a05452015-04-29 11:24:52 -0700276 public static final int VOLUME_INTERNAL_PATH_CHANGED = 656;
Jeff Sharkey48877892015-03-18 11:27:19 -0700277 public static final int VOLUME_DESTROYED = 659;
Svetoslavf23b64d2013-04-25 14:45:54 -0700278
Jeff Sharkey275e3e42015-04-24 16:10:32 -0700279 public static final int MOVE_STATUS = 660;
Jeff Sharkey9756d752015-05-14 21:07:42 -0700280 public static final int BENCHMARK_RESULT = 661;
Jeff Sharkeye8a4b662015-06-27 15:43:45 -0700281 public static final int TRIM_RESULT = 662;
San Mehat22dd86e2010-01-12 12:21:18 -0800282 }
283
Jeff Sharkey620b32b2015-04-23 19:36:02 -0700284 private static final int VERSION_INIT = 1;
285 private static final int VERSION_ADD_PRIMARY = 2;
Jeff Sharkeyfced5342015-05-10 14:53:34 -0700286 private static final int VERSION_FIX_PRIMARY = 3;
Jeff Sharkey620b32b2015-04-23 19:36:02 -0700287
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700288 private static final String TAG_VOLUMES = "volumes";
Jeff Sharkey620b32b2015-04-23 19:36:02 -0700289 private static final String ATTR_VERSION = "version";
290 private static final String ATTR_PRIMARY_STORAGE_UUID = "primaryStorageUuid";
Jeff Sharkey4c099d02015-05-15 13:45:00 -0700291 private static final String ATTR_FORCE_ADOPTABLE = "forceAdoptable";
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700292 private static final String TAG_VOLUME = "volume";
293 private static final String ATTR_TYPE = "type";
294 private static final String ATTR_FS_UUID = "fsUuid";
Jeff Sharkey5cc0df22015-06-17 19:44:05 -0700295 private static final String ATTR_PART_GUID = "partGuid";
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700296 private static final String ATTR_NICKNAME = "nickname";
297 private static final String ATTR_USER_FLAGS = "userFlags";
Jeff Sharkeye8a4b662015-06-27 15:43:45 -0700298 private static final String ATTR_CREATED_MILLIS = "createdMillis";
299 private static final String ATTR_LAST_TRIM_MILLIS = "lastTrimMillis";
300 private static final String ATTR_LAST_BENCH_MILLIS = "lastBenchMillis";
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700301
Jeff Sharkeyb36586a2015-04-27 08:42:28 -0700302 private final AtomicFile mSettingsFile;
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700303
Jeff Sharkey48877892015-03-18 11:27:19 -0700304 /**
305 * <em>Never</em> hold the lock while performing downcalls into vold, since
306 * unsolicited events can suddenly appear to update data structures.
307 */
308 private final Object mLock = new Object();
309
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700310 /** Set of users that we know are unlocked. */
Jeff Sharkey48877892015-03-18 11:27:19 -0700311 @GuardedBy("mLock")
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700312 private int[] mLocalUnlockedUsers = EmptyArray.INT;
313 /** Set of users that system knows are unlocked. */
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -0800314 @GuardedBy("mLock")
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700315 private int[] mSystemUnlockedUsers = EmptyArray.INT;
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700316
317 /** Map from disk ID to disk */
Jeff Sharkey48877892015-03-18 11:27:19 -0700318 @GuardedBy("mLock")
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -0700319 private ArrayMap<String, DiskInfo> mDisks = new ArrayMap<>();
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700320 /** Map from volume ID to disk */
Jeff Sharkey48877892015-03-18 11:27:19 -0700321 @GuardedBy("mLock")
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700322 private final ArrayMap<String, VolumeInfo> mVolumes = new ArrayMap<>();
Jeff Sharkey48877892015-03-18 11:27:19 -0700323
Jeff Sharkeyb36586a2015-04-27 08:42:28 -0700324 /** Map from UUID to record */
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700325 @GuardedBy("mLock")
Jeff Sharkeyb36586a2015-04-27 08:42:28 -0700326 private ArrayMap<String, VolumeRecord> mRecords = new ArrayMap<>();
Jeff Sharkey620b32b2015-04-23 19:36:02 -0700327 @GuardedBy("mLock")
328 private String mPrimaryStorageUuid;
Jeff Sharkey4c099d02015-05-15 13:45:00 -0700329 @GuardedBy("mLock")
330 private boolean mForceAdoptable;
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700331
Jeff Sharkeyeba260d2015-04-19 14:35:16 -0700332 /** Map from disk ID to latches */
333 @GuardedBy("mLock")
334 private ArrayMap<String, CountDownLatch> mDiskScanLatches = new ArrayMap<>();
335
Jeff Sharkey275e3e42015-04-24 16:10:32 -0700336 @GuardedBy("mLock")
337 private IPackageMoveObserver mMoveCallback;
338 @GuardedBy("mLock")
339 private String mMoveTargetUuid;
340
Jeff Sharkeyab15c392016-05-05 11:45:01 -0600341 private volatile int mCurrentUserId = UserHandle.USER_SYSTEM;
342
Daichi Hirono9fb00182016-11-08 14:12:17 +0900343 /** Holding lock for AppFuse business */
344 private final Object mAppFuseLock = new Object();
345
346 @GuardedBy("mAppFuseLock")
347 private int mNextAppFuseName = 0;
348
349 @GuardedBy("mAppFuseLock")
350 private final SparseArray<Integer> mAppFusePids = new SparseArray<>();
351
Jeff Sharkeyef10ee02015-07-05 14:17:27 -0700352 private VolumeInfo findVolumeByIdOrThrow(String id) {
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700353 synchronized (mLock) {
354 final VolumeInfo vol = mVolumes.get(id);
355 if (vol != null) {
356 return vol;
357 }
358 }
359 throw new IllegalArgumentException("No volume found for ID " + id);
360 }
361
Jeff Sharkeyef10ee02015-07-05 14:17:27 -0700362 private String findVolumeIdForPathOrThrow(String path) {
Jeff Sharkey48877892015-03-18 11:27:19 -0700363 synchronized (mLock) {
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -0700364 for (int i = 0; i < mVolumes.size(); i++) {
365 final VolumeInfo vol = mVolumes.valueAt(i);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700366 if (vol.path != null && path.startsWith(vol.path)) {
367 return vol.id;
Jeff Sharkey48877892015-03-18 11:27:19 -0700368 }
369 }
370 }
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700371 throw new IllegalArgumentException("No volume found for path " + path);
Jeff Sharkey48877892015-03-18 11:27:19 -0700372 }
373
Jeff Sharkeye8a4b662015-06-27 15:43:45 -0700374 private VolumeRecord findRecordForPath(String path) {
375 synchronized (mLock) {
376 for (int i = 0; i < mVolumes.size(); i++) {
377 final VolumeInfo vol = mVolumes.valueAt(i);
378 if (vol.path != null && path.startsWith(vol.path)) {
379 return mRecords.get(vol.fsUuid);
380 }
381 }
382 }
383 return null;
384 }
385
386 private String scrubPath(String path) {
387 if (path.startsWith(Environment.getDataDirectory().getAbsolutePath())) {
388 return "internal";
389 }
390 final VolumeRecord rec = findRecordForPath(path);
391 if (rec == null || rec.createdMillis == 0) {
392 return "unknown";
393 } else {
394 return "ext:" + (int) ((System.currentTimeMillis() - rec.createdMillis)
395 / DateUtils.WEEK_IN_MILLIS) + "w";
396 }
397 }
398
Jeff Sharkeyef10ee02015-07-05 14:17:27 -0700399 private @Nullable VolumeInfo findStorageForUuid(String volumeUuid) {
Jeff Sharkey275e3e42015-04-24 16:10:32 -0700400 final StorageManager storage = mContext.getSystemService(StorageManager.class);
401 if (Objects.equals(StorageManager.UUID_PRIVATE_INTERNAL, volumeUuid)) {
Jeff Sharkeyef10ee02015-07-05 14:17:27 -0700402 return storage.findVolumeById(VolumeInfo.ID_EMULATED_INTERNAL);
Jeff Sharkey275e3e42015-04-24 16:10:32 -0700403 } else if (Objects.equals(StorageManager.UUID_PRIMARY_PHYSICAL, volumeUuid)) {
404 return storage.getPrimaryPhysicalVolume();
405 } else {
406 return storage.findEmulatedForPrivate(storage.findVolumeByUuid(volumeUuid));
407 }
408 }
409
Jeff Sharkeye8a4b662015-06-27 15:43:45 -0700410 private boolean shouldBenchmark() {
411 final long benchInterval = Settings.Global.getLong(mContext.getContentResolver(),
412 Settings.Global.STORAGE_BENCHMARK_INTERVAL, DateUtils.WEEK_IN_MILLIS);
Jeff Sharkeye83d8a92015-09-09 14:53:38 -0700413 if (benchInterval == -1) {
414 return false;
415 } else if (benchInterval == 0) {
416 return true;
417 }
418
Jeff Sharkeye8a4b662015-06-27 15:43:45 -0700419 synchronized (mLock) {
420 for (int i = 0; i < mVolumes.size(); i++) {
421 final VolumeInfo vol = mVolumes.valueAt(i);
422 final VolumeRecord rec = mRecords.get(vol.fsUuid);
Jeff Sharkeye83d8a92015-09-09 14:53:38 -0700423 if (vol.isMountedWritable() && rec != null) {
Jeff Sharkeye8a4b662015-06-27 15:43:45 -0700424 final long benchAge = System.currentTimeMillis() - rec.lastBenchMillis;
425 if (benchAge >= benchInterval) {
426 return true;
427 }
428 }
429 }
430 return false;
431 }
432 }
433
Jeff Sharkeyeba260d2015-04-19 14:35:16 -0700434 private CountDownLatch findOrCreateDiskScanLatch(String diskId) {
435 synchronized (mLock) {
436 CountDownLatch latch = mDiskScanLatches.get(diskId);
437 if (latch == null) {
438 latch = new CountDownLatch(1);
439 mDiskScanLatches.put(diskId, latch);
440 }
441 return latch;
442 }
443 }
444
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -0800445 private static String escapeNull(String arg) {
446 if (TextUtils.isEmpty(arg)) {
447 return "!";
448 } else {
449 if (arg.indexOf('\0') != -1 || arg.indexOf(' ') != -1) {
450 throw new IllegalArgumentException(arg);
451 }
452 return arg;
453 }
454 }
455
Paul Lawrence8e397362014-01-27 15:22:30 -0800456 /** List of crypto types.
457 * These must match CRYPT_TYPE_XXX in cryptfs.h AND their
458 * corresponding commands in CommandListener.cpp */
459 public static final String[] CRYPTO_TYPES
460 = { "password", "default", "pattern", "pin" };
461
Brian Carlstrom7395a8a2014-04-28 22:11:01 -0700462 private final Context mContext;
Jeff Sharkeycd575992016-03-29 14:12:49 -0600463
Brian Carlstromdfad99a2014-05-07 15:21:14 -0700464 private final NativeDaemonConnector mConnector;
Paul Lawrence1c62cbb2015-06-03 14:14:52 -0700465 private final NativeDaemonConnector mCryptConnector;
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700466
Jeff Sharkeycd575992016-03-29 14:12:49 -0600467 private final Thread mConnectorThread;
468 private final Thread mCryptConnectorThread;
469
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700470 private volatile boolean mSystemReady = false;
Yasuhiro Matsuda87a38b52015-07-24 22:10:16 +0900471 private volatile boolean mBootCompleted = false;
Jeff Sharkey48877892015-03-18 11:27:19 -0700472 private volatile boolean mDaemonConnected = false;
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700473
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700474 private PackageManagerService mPms;
475
476 private final Callbacks mCallbacks;
Jeff Sharkeyb9fe5372015-12-03 15:23:08 -0700477 private final LockPatternUtils mLockPatternUtils;
Jeff Sharkey48877892015-03-18 11:27:19 -0700478
Paul Lawrence1c62cbb2015-06-03 14:14:52 -0700479 // Two connectors - mConnector & mCryptConnector
480 private final CountDownLatch mConnectedSignal = new CountDownLatch(2);
Jeff Sharkey0be607c2012-11-14 14:39:19 -0800481 private final CountDownLatch mAsecsScanned = new CountDownLatch(1);
Jeff Sharkey48877892015-03-18 11:27:19 -0700482
483 private final Object mUnmountLock = new Object();
484 @GuardedBy("mUnmountLock")
485 private CountDownLatch mUnmountSignal;
Suchi Amalapurapufd3530f2010-01-18 00:15:59 -0800486
San Mehat6cdd9c02010-02-09 14:45:20 -0800487 /**
488 * Private hash of currently mounted secure containers.
Suchi Amalapurapu0eec21d2010-02-25 17:07:14 -0800489 * Used as a lock in methods to manipulate secure containers.
San Mehat6cdd9c02010-02-09 14:45:20 -0800490 */
Suchi Amalapurapu0eec21d2010-02-25 17:07:14 -0800491 final private HashSet<String> mAsecMountSet = new HashSet<String>();
San Mehat6cdd9c02010-02-09 14:45:20 -0800492
Kenny Root02c87302010-07-01 08:10:18 -0700493 /**
Kenny Root3b1abba2010-10-13 15:00:07 -0700494 * The size of the crypto algorithm key in bits for OBB files. Currently
495 * Twofish is used which takes 128-bit keys.
496 */
497 private static final int CRYPTO_ALGORITHM_KEY_SIZE = 128;
498
499 /**
500 * The number of times to run SHA1 in the PBKDF2 function for OBB files.
501 * 1024 is reasonably secure and not too slow.
502 */
503 private static final int PBKDF2_HASH_ROUNDS = 1024;
504
505 /**
Kenny Roota02b8b02010-08-05 16:14:17 -0700506 * Mounted OBB tracking information. Used to track the current state of all
507 * OBBs.
Kenny Root02c87302010-07-01 08:10:18 -0700508 */
Kenny Root735de3b2010-09-30 14:11:39 -0700509 final private Map<IBinder, List<ObbState>> mObbMounts = new HashMap<IBinder, List<ObbState>>();
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700510
511 /** Map from raw paths to {@link ObbState}. */
Kenny Roota02b8b02010-08-05 16:14:17 -0700512 final private Map<String, ObbState> mObbPathToStateMap = new HashMap<String, ObbState>();
513
Svet Ganov6ee871e2015-07-10 14:29:33 -0700514 // Not guarded by a lock.
Sudheer Shanka2250d562016-11-07 15:41:02 -0800515 private final StorageManagerInternalImpl mStorageManagerInternal
516 = new StorageManagerInternalImpl();
Svet Ganov6ee871e2015-07-10 14:29:33 -0700517
Kenny Roota02b8b02010-08-05 16:14:17 -0700518 class ObbState implements IBinder.DeathRecipient {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700519 public ObbState(String rawPath, String canonicalPath, int callingUid,
520 IObbActionListener token, int nonce) {
521 this.rawPath = rawPath;
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700522 this.canonicalPath = canonicalPath;
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700523
524 this.ownerGid = UserHandle.getSharedAppGid(callingUid);
Kenny Rootaf9d6672010-10-08 09:21:39 -0700525 this.token = token;
526 this.nonce = nonce;
Kenny Roota02b8b02010-08-05 16:14:17 -0700527 }
528
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700529 final String rawPath;
530 final String canonicalPath;
Kenny Roota02b8b02010-08-05 16:14:17 -0700531
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700532 final int ownerGid;
Kenny Roota02b8b02010-08-05 16:14:17 -0700533
Kenny Rootaf9d6672010-10-08 09:21:39 -0700534 // Token of remote Binder caller
535 final IObbActionListener token;
536
537 // Identifier to pass back to the token
538 final int nonce;
Kenny Roota02b8b02010-08-05 16:14:17 -0700539
Kenny Root735de3b2010-09-30 14:11:39 -0700540 public IBinder getBinder() {
541 return token.asBinder();
542 }
543
Kenny Roota02b8b02010-08-05 16:14:17 -0700544 @Override
545 public void binderDied() {
546 ObbAction action = new UnmountObbAction(this, true);
547 mObbActionHandler.sendMessage(mObbActionHandler.obtainMessage(OBB_RUN_ACTION, action));
Kenny Root735de3b2010-09-30 14:11:39 -0700548 }
Kenny Roota02b8b02010-08-05 16:14:17 -0700549
Kenny Root5919ac62010-10-05 09:49:40 -0700550 public void link() throws RemoteException {
551 getBinder().linkToDeath(this, 0);
552 }
553
554 public void unlink() {
Kenny Root735de3b2010-09-30 14:11:39 -0700555 getBinder().unlinkToDeath(this, 0);
Kenny Roota02b8b02010-08-05 16:14:17 -0700556 }
Kenny Root38cf8862010-09-26 14:18:51 -0700557
558 @Override
559 public String toString() {
560 StringBuilder sb = new StringBuilder("ObbState{");
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700561 sb.append("rawPath=").append(rawPath);
562 sb.append(",canonicalPath=").append(canonicalPath);
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700563 sb.append(",ownerGid=").append(ownerGid);
564 sb.append(",token=").append(token);
565 sb.append(",binder=").append(getBinder());
Kenny Root38cf8862010-09-26 14:18:51 -0700566 sb.append('}');
567 return sb.toString();
568 }
Kenny Roota02b8b02010-08-05 16:14:17 -0700569 }
570
571 // OBB Action Handler
572 final private ObbActionHandler mObbActionHandler;
573
574 // OBB action handler messages
575 private static final int OBB_RUN_ACTION = 1;
576 private static final int OBB_MCS_BOUND = 2;
577 private static final int OBB_MCS_UNBIND = 3;
578 private static final int OBB_MCS_RECONNECT = 4;
Kenny Rootaf9d6672010-10-08 09:21:39 -0700579 private static final int OBB_FLUSH_MOUNT_STATE = 5;
Kenny Roota02b8b02010-08-05 16:14:17 -0700580
581 /*
582 * Default Container Service information
583 */
584 static final ComponentName DEFAULT_CONTAINER_COMPONENT = new ComponentName(
585 "com.android.defcontainer", "com.android.defcontainer.DefaultContainerService");
586
587 final private DefaultContainerConnection mDefContainerConn = new DefaultContainerConnection();
588
589 class DefaultContainerConnection implements ServiceConnection {
Jeff Sharkey48877892015-03-18 11:27:19 -0700590 @Override
Kenny Roota02b8b02010-08-05 16:14:17 -0700591 public void onServiceConnected(ComponentName name, IBinder service) {
592 if (DEBUG_OBB)
593 Slog.i(TAG, "onServiceConnected");
594 IMediaContainerService imcs = IMediaContainerService.Stub.asInterface(service);
595 mObbActionHandler.sendMessage(mObbActionHandler.obtainMessage(OBB_MCS_BOUND, imcs));
596 }
597
Jeff Sharkey48877892015-03-18 11:27:19 -0700598 @Override
Kenny Roota02b8b02010-08-05 16:14:17 -0700599 public void onServiceDisconnected(ComponentName name) {
600 if (DEBUG_OBB)
601 Slog.i(TAG, "onServiceDisconnected");
602 }
603 };
604
605 // Used in the ObbActionHandler
606 private IMediaContainerService mContainerService = null;
Kenny Root02c87302010-07-01 08:10:18 -0700607
Christopher Tate7265abe2014-11-21 13:54:45 -0800608 // Last fstrim operation tracking
609 private static final String LAST_FSTRIM_FILE = "last-fstrim";
610 private final File mLastMaintenanceFile;
611 private long mLastMaintenance;
612
Kenny Root02c87302010-07-01 08:10:18 -0700613 // Handler messages
Jeff Sharkey48877892015-03-18 11:27:19 -0700614 private static final int H_SYSTEM_READY = 1;
615 private static final int H_DAEMON_CONNECTED = 2;
616 private static final int H_SHUTDOWN = 3;
617 private static final int H_FSTRIM = 4;
618 private static final int H_VOLUME_MOUNT = 5;
619 private static final int H_VOLUME_BROADCAST = 6;
Jeff Sharkeyabc3e852015-08-03 14:41:13 -0700620 private static final int H_INTERNAL_BROADCAST = 7;
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700621 private static final int H_VOLUME_UNMOUNT = 8;
Jeff Sharkey5a9bb742015-11-03 10:15:57 -0800622 private static final int H_PARTITION_FORGET = 9;
623 private static final int H_RESET = 10;
Suchi Amalapurapu6ffce2e2010-03-08 14:48:40 -0800624
Sudheer Shanka2250d562016-11-07 15:41:02 -0800625 class StorageManagerServiceHandler extends Handler {
626 public StorageManagerServiceHandler(Looper looper) {
Jeff Sharkey48877892015-03-18 11:27:19 -0700627 super(looper);
Daniel Sandler5f27ef42010-03-16 15:42:02 -0400628 }
629
Jason parks5af0b912010-11-29 09:05:25 -0600630 @Override
Suchi Amalapurapuc42e29e2010-02-22 16:03:53 -0800631 public void handleMessage(Message msg) {
632 switch (msg.what) {
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700633 case H_SYSTEM_READY: {
Jeff Sharkey48877892015-03-18 11:27:19 -0700634 handleSystemReady();
635 break;
636 }
637 case H_DAEMON_CONNECTED: {
638 handleDaemonConnected();
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700639 break;
640 }
Christopher Tated417d622013-08-19 16:14:25 -0700641 case H_FSTRIM: {
Jeff Sharkey1783f142015-04-17 10:52:51 -0700642 if (!isReady()) {
643 Slog.i(TAG, "fstrim requested, but no daemon connection yet; trying again");
Christopher Tate7618db12015-04-28 16:32:55 -0700644 sendMessageDelayed(obtainMessage(H_FSTRIM, msg.obj),
645 DateUtils.SECOND_IN_MILLIS);
646 break;
Jeff Sharkey1783f142015-04-17 10:52:51 -0700647 }
648
Christopher Tated417d622013-08-19 16:14:25 -0700649 Slog.i(TAG, "Running fstrim idle maintenance");
Christopher Tate7265abe2014-11-21 13:54:45 -0800650
651 // Remember when we kicked it off
652 try {
653 mLastMaintenance = System.currentTimeMillis();
654 mLastMaintenanceFile.setLastModified(mLastMaintenance);
655 } catch (Exception e) {
656 Slog.e(TAG, "Unable to record last fstrim!");
657 }
658
Jeff Sharkey31d0b702016-11-21 14:16:53 -0700659 final int flags = shouldBenchmark() ? StorageManager.FSTRIM_FLAG_BENCHMARK : 0;
660 fstrim(flags);
Christopher Tate7265abe2014-11-21 13:54:45 -0800661
Christopher Tated417d622013-08-19 16:14:25 -0700662 // invoke the completion callback, if any
Jeff Sharkeye8a4b662015-06-27 15:43:45 -0700663 // TODO: fstrim is non-blocking, so remove this useless callback
Christopher Tated417d622013-08-19 16:14:25 -0700664 Runnable callback = (Runnable) msg.obj;
665 if (callback != null) {
666 callback.run();
667 }
668 break;
669 }
Jeff Sharkey48877892015-03-18 11:27:19 -0700670 case H_SHUTDOWN: {
Sudheer Shanka2250d562016-11-07 15:41:02 -0800671 final IStorageShutdownObserver obs = (IStorageShutdownObserver) msg.obj;
Jeff Sharkey48877892015-03-18 11:27:19 -0700672 boolean success = false;
673 try {
674 success = mConnector.execute("volume", "shutdown").isClassOk();
675 } catch (NativeDaemonConnectorException ignored) {
676 }
677 if (obs != null) {
678 try {
679 obs.onShutDownComplete(success ? 0 : -1);
680 } catch (RemoteException ignored) {
681 }
682 }
683 break;
684 }
685 case H_VOLUME_MOUNT: {
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -0700686 final VolumeInfo vol = (VolumeInfo) msg.obj;
Jeff Sharkey2e606d72015-07-27 14:19:54 -0700687 if (isMountDisallowed(vol)) {
688 Slog.i(TAG, "Ignoring mount " + vol.getId() + " due to policy");
689 break;
690 }
Jeff Sharkey48877892015-03-18 11:27:19 -0700691 try {
Jeff Sharkey7e92ef32015-04-17 17:35:07 -0700692 mConnector.execute("volume", "mount", vol.id, vol.mountFlags,
693 vol.mountUserId);
Jeff Sharkey48877892015-03-18 11:27:19 -0700694 } catch (NativeDaemonConnectorException ignored) {
695 }
696 break;
697 }
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700698 case H_VOLUME_UNMOUNT: {
699 final VolumeInfo vol = (VolumeInfo) msg.obj;
700 unmount(vol.getId());
701 break;
702 }
Jeff Sharkey48877892015-03-18 11:27:19 -0700703 case H_VOLUME_BROADCAST: {
704 final StorageVolume userVol = (StorageVolume) msg.obj;
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700705 final String envState = userVol.getState();
706 Slog.d(TAG, "Volume " + userVol.getId() + " broadcasting " + envState + " to "
Jeff Sharkey48877892015-03-18 11:27:19 -0700707 + userVol.getOwner());
708
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700709 final String action = VolumeInfo.getBroadcastForEnvironment(envState);
Jeff Sharkey48877892015-03-18 11:27:19 -0700710 if (action != null) {
711 final Intent intent = new Intent(action,
712 Uri.fromFile(userVol.getPathFile()));
713 intent.putExtra(StorageVolume.EXTRA_STORAGE_VOLUME, userVol);
714 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
715 mContext.sendBroadcastAsUser(intent, userVol.getOwner());
716 }
717 break;
718 }
Jeff Sharkeyabc3e852015-08-03 14:41:13 -0700719 case H_INTERNAL_BROADCAST: {
720 // Internal broadcasts aimed at system components, not for
721 // third-party apps.
722 final Intent intent = (Intent) msg.obj;
723 mContext.sendBroadcastAsUser(intent, UserHandle.ALL,
724 android.Manifest.permission.WRITE_MEDIA_STORAGE);
Jeff Sharkey5a9bb742015-11-03 10:15:57 -0800725 break;
726 }
727 case H_PARTITION_FORGET: {
728 final String partGuid = (String) msg.obj;
729 forgetPartition(partGuid);
730 break;
731 }
732 case H_RESET: {
733 resetIfReadyAndConnected();
734 break;
Jeff Sharkeyabc3e852015-08-03 14:41:13 -0700735 }
Suchi Amalapurapuc42e29e2010-02-22 16:03:53 -0800736 }
737 }
Jeff Sharkey48877892015-03-18 11:27:19 -0700738 }
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700739
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700740 private final Handler mHandler;
Suchi Amalapurapuc42e29e2010-02-22 16:03:53 -0800741
Jeff Sharkeybcd262d2015-06-10 09:41:17 -0700742 private BroadcastReceiver mUserReceiver = new BroadcastReceiver() {
743 @Override
744 public void onReceive(Context context, Intent intent) {
745 final String action = intent.getAction();
746 final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700747 Preconditions.checkArgument(userId >= 0);
Jeff Sharkeybcd262d2015-06-10 09:41:17 -0700748
749 try {
750 if (Intent.ACTION_USER_ADDED.equals(action)) {
751 final UserManager um = mContext.getSystemService(UserManager.class);
752 final int userSerialNumber = um.getUserSerialNumber(userId);
753 mConnector.execute("volume", "user_added", userId, userSerialNumber);
754 } else if (Intent.ACTION_USER_REMOVED.equals(action)) {
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700755 synchronized (mVolumes) {
756 final int size = mVolumes.size();
757 for (int i = 0; i < size; i++) {
758 final VolumeInfo vol = mVolumes.valueAt(i);
759 if (vol.mountUserId == userId) {
760 vol.mountUserId = UserHandle.USER_NULL;
761 mHandler.obtainMessage(H_VOLUME_UNMOUNT, vol).sendToTarget();
762 }
763 }
764 }
Jeff Sharkeybcd262d2015-06-10 09:41:17 -0700765 mConnector.execute("volume", "user_removed", userId);
766 }
767 } catch (NativeDaemonConnectorException e) {
768 Slog.w(TAG, "Failed to send user details to vold", e);
769 }
770 }
771 };
772
Jeff Sharkey56e62932015-03-21 20:41:00 -0700773 @Override
774 public void waitForAsecScan() {
Jeff Sharkey48877892015-03-18 11:27:19 -0700775 waitForLatch(mAsecsScanned, "mAsecsScanned");
Kenny Root51a573c2012-05-17 13:30:28 -0700776 }
777
San Mehat207e5382010-02-04 20:46:54 -0800778 private void waitForReady() {
Jeff Sharkey48877892015-03-18 11:27:19 -0700779 waitForLatch(mConnectedSignal, "mConnectedSignal");
Kenny Root51a573c2012-05-17 13:30:28 -0700780 }
781
Jeff Sharkey48877892015-03-18 11:27:19 -0700782 private void waitForLatch(CountDownLatch latch, String condition) {
Jeff Sharkeyedcdaf62015-07-09 09:45:36 -0700783 try {
784 waitForLatch(latch, condition, -1);
785 } catch (TimeoutException ignored) {
786 }
787 }
788
789 private void waitForLatch(CountDownLatch latch, String condition, long timeoutMillis)
790 throws TimeoutException {
791 final long startMillis = SystemClock.elapsedRealtime();
Jeff Sharkeyeba260d2015-04-19 14:35:16 -0700792 while (true) {
Kenny Root51a573c2012-05-17 13:30:28 -0700793 try {
794 if (latch.await(5000, TimeUnit.MILLISECONDS)) {
San Mehat207e5382010-02-04 20:46:54 -0800795 return;
Kenny Root51a573c2012-05-17 13:30:28 -0700796 } else {
797 Slog.w(TAG, "Thread " + Thread.currentThread().getName()
Jeff Sharkey48877892015-03-18 11:27:19 -0700798 + " still waiting for " + condition + "...");
San Mehat207e5382010-02-04 20:46:54 -0800799 }
Kenny Root51a573c2012-05-17 13:30:28 -0700800 } catch (InterruptedException e) {
Jeff Sharkeyeba260d2015-04-19 14:35:16 -0700801 Slog.w(TAG, "Interrupt while waiting for " + condition);
San Mehat207e5382010-02-04 20:46:54 -0800802 }
Jeff Sharkeyedcdaf62015-07-09 09:45:36 -0700803 if (timeoutMillis > 0 && SystemClock.elapsedRealtime() > startMillis + timeoutMillis) {
804 throw new TimeoutException("Thread " + Thread.currentThread().getName()
805 + " gave up waiting for " + condition + " after " + timeoutMillis + "ms");
806 }
San Mehat207e5382010-02-04 20:46:54 -0800807 }
San Mehat1f6301e2010-01-07 22:40:27 -0800808 }
Kenny Root02c87302010-07-01 08:10:18 -0700809
Paul Lawrence945490c2014-03-27 16:37:28 +0000810 private boolean isReady() {
811 try {
812 return mConnectedSignal.await(0, TimeUnit.MILLISECONDS);
813 } catch (InterruptedException e) {
814 return false;
815 }
816 }
817
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700818 private void handleSystemReady() {
Jeff Sharkey8924e872015-11-30 12:52:10 -0700819 initIfReadyAndConnected();
Jeff Sharkey5a9bb742015-11-03 10:15:57 -0800820 resetIfReadyAndConnected();
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700821
Jeff Sharkey48877892015-03-18 11:27:19 -0700822 // Start scheduling nominally-daily fstrim operations
Christopher Tate115afda2014-06-06 19:06:26 -0700823 MountServiceIdler.scheduleIdlePass(mContext);
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700824 }
825
Jeff Sharkey14cbe522015-07-08 14:06:37 -0700826 /**
827 * MediaProvider has a ton of code that makes assumptions about storage
828 * paths never changing, so we outright kill them to pick up new state.
829 */
830 @Deprecated
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700831 private void killMediaProvider(List<UserInfo> users) {
832 if (users == null) return;
833
Jeff Sharkeyb3cf9532015-07-17 15:12:39 -0700834 final long token = Binder.clearCallingIdentity();
835 try {
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700836 for (UserInfo user : users) {
837 // System user does not have media provider, so skip.
838 if (user.isSystemOnly()) continue;
839
Jeff Sharkey2a9e3f82015-12-18 10:57:58 -0700840 final ProviderInfo provider = mPms.resolveContentProvider(MediaStore.AUTHORITY,
Jeff Sharkey8a372a02016-03-16 16:25:45 -0600841 PackageManager.MATCH_DIRECT_BOOT_AWARE
842 | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
843 user.id);
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700844 if (provider != null) {
Sudheer Shankadc589ac2016-11-10 15:30:17 -0800845 final IActivityManager am = ActivityManager.getService();
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700846 try {
Jeff Sharkey85f449e2016-06-23 09:26:00 -0600847 am.killApplication(provider.applicationInfo.packageName,
848 UserHandle.getAppId(provider.applicationInfo.uid),
849 UserHandle.USER_ALL, "vold reset");
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700850 // We only need to run this once. It will kill all users' media processes.
851 break;
852 } catch (RemoteException e) {
853 }
Jeff Sharkeyb3cf9532015-07-17 15:12:39 -0700854 }
Jeff Sharkey14cbe522015-07-08 14:06:37 -0700855 }
Jeff Sharkeyb3cf9532015-07-17 15:12:39 -0700856 } finally {
857 Binder.restoreCallingIdentity(token);
Jeff Sharkey14cbe522015-07-08 14:06:37 -0700858 }
859 }
860
Jeff Sharkey5a9bb742015-11-03 10:15:57 -0800861 private void addInternalVolumeLocked() {
Amith Yamasania7892482015-08-07 11:09:05 -0700862 // Create a stub volume that represents internal storage
863 final VolumeInfo internal = new VolumeInfo(VolumeInfo.ID_PRIVATE_INTERNAL,
864 VolumeInfo.TYPE_PRIVATE, null, null);
865 internal.state = VolumeInfo.STATE_MOUNTED;
866 internal.path = Environment.getDataDirectory().getAbsolutePath();
867 mVolumes.put(internal.id, internal);
868 }
869
Jeff Sharkey8924e872015-11-30 12:52:10 -0700870 private void initIfReadyAndConnected() {
871 Slog.d(TAG, "Thinking about init, mSystemReady=" + mSystemReady
872 + ", mDaemonConnected=" + mDaemonConnected);
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700873 if (mSystemReady && mDaemonConnected
Paul Lawrence20be5d62016-02-26 13:51:17 -0800874 && !StorageManager.isFileEncryptedNativeOnly()) {
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700875 // When booting a device without native support, make sure that our
876 // user directories are locked or unlocked based on the current
877 // emulation status.
Paul Lawrence20be5d62016-02-26 13:51:17 -0800878 final boolean initLocked = StorageManager.isFileEncryptedEmulatedOnly();
Paul Crowleyd94ab732016-02-15 06:44:51 +0000879 Slog.d(TAG, "Setting up emulation state, initlocked=" + initLocked);
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700880 final List<UserInfo> users = mContext.getSystemService(UserManager.class).getUsers();
Jeff Sharkey8924e872015-11-30 12:52:10 -0700881 for (UserInfo user : users) {
882 try {
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700883 if (initLocked) {
884 mCryptConnector.execute("cryptfs", "lock_user_key", user.id);
885 } else {
886 mCryptConnector.execute("cryptfs", "unlock_user_key", user.id,
Paul Crowleyd94ab732016-02-15 06:44:51 +0000887 user.serialNumber, "!", "!");
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700888 }
Jeff Sharkey8924e872015-11-30 12:52:10 -0700889 } catch (NativeDaemonConnectorException e) {
890 Slog.w(TAG, "Failed to init vold", e);
891 }
892 }
893 }
894 }
895
Jeff Sharkey5a9bb742015-11-03 10:15:57 -0800896 private void resetIfReadyAndConnected() {
Jeff Sharkey48877892015-03-18 11:27:19 -0700897 Slog.d(TAG, "Thinking about reset, mSystemReady=" + mSystemReady
898 + ", mDaemonConnected=" + mDaemonConnected);
899 if (mSystemReady && mDaemonConnected) {
Jeff Sharkey5a9bb742015-11-03 10:15:57 -0800900 final List<UserInfo> users = mContext.getSystemService(UserManager.class).getUsers();
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700901 killMediaProvider(users);
Jeff Sharkey14cbe522015-07-08 14:06:37 -0700902
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700903 final int[] systemUnlockedUsers;
Jeff Sharkey5a9bb742015-11-03 10:15:57 -0800904 synchronized (mLock) {
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700905 systemUnlockedUsers = mSystemUnlockedUsers;
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700906
Jeff Sharkey5a9bb742015-11-03 10:15:57 -0800907 mDisks.clear();
908 mVolumes.clear();
909
910 addInternalVolumeLocked();
911 }
Jeff Sharkey59d577a2015-04-11 21:27:21 -0700912
Jeff Sharkey48877892015-03-18 11:27:19 -0700913 try {
914 mConnector.execute("volume", "reset");
Jeff Sharkeybcd262d2015-06-10 09:41:17 -0700915
916 // Tell vold about all existing and started users
Jeff Sharkeybcd262d2015-06-10 09:41:17 -0700917 for (UserInfo user : users) {
918 mConnector.execute("volume", "user_added", user.id, user.serialNumber);
919 }
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700920 for (int userId : systemUnlockedUsers) {
Jeff Sharkeybcd262d2015-06-10 09:41:17 -0700921 mConnector.execute("volume", "user_started", userId);
Jeff Sharkey50a05452015-04-29 11:24:52 -0700922 }
Jeff Sharkey48877892015-03-18 11:27:19 -0700923 } catch (NativeDaemonConnectorException e) {
924 Slog.w(TAG, "Failed to reset vold", e);
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700925 }
926 }
Jeff Sharkey48877892015-03-18 11:27:19 -0700927 }
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700928
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700929 private void onUnlockUser(int userId) {
930 Slog.d(TAG, "onUnlockUser " + userId);
Jeff Sharkey48877892015-03-18 11:27:19 -0700931
932 // We purposefully block here to make sure that user-specific
933 // staging area is ready so it's ready for zygote-forked apps to
934 // bind mount against.
935 try {
Jeff Sharkeybcd262d2015-06-10 09:41:17 -0700936 mConnector.execute("volume", "user_started", userId);
Jeff Sharkey48877892015-03-18 11:27:19 -0700937 } catch (NativeDaemonConnectorException ignored) {
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700938 }
Jeff Sharkey48877892015-03-18 11:27:19 -0700939
940 // Record user as started so newly mounted volumes kick off events
941 // correctly, then synthesize events for any already-mounted volumes.
yuanhuihuiefd1f122016-07-13 21:21:03 +0800942 synchronized (mLock) {
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -0700943 for (int i = 0; i < mVolumes.size(); i++) {
944 final VolumeInfo vol = mVolumes.valueAt(i);
Jeff Sharkey46349872015-07-28 10:49:47 -0700945 if (vol.isVisibleForRead(userId) && vol.isMountedReadable()) {
Svet Ganov6ee871e2015-07-10 14:29:33 -0700946 final StorageVolume userVol = vol.buildStorageVolume(mContext, userId, false);
Jeff Sharkey48877892015-03-18 11:27:19 -0700947 mHandler.obtainMessage(H_VOLUME_BROADCAST, userVol).sendToTarget();
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700948
Jeff Sharkey27de30d2015-04-18 16:20:27 -0700949 final String envState = VolumeInfo.getEnvironmentForState(vol.getState());
950 mCallbacks.notifyStorageStateChanged(userVol.getPath(), envState, envState);
Jeff Sharkey48877892015-03-18 11:27:19 -0700951 }
952 }
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700953 mSystemUnlockedUsers = ArrayUtils.appendInt(mSystemUnlockedUsers, userId);
Jeff Sharkey48877892015-03-18 11:27:19 -0700954 }
955 }
956
957 private void onCleanupUser(int userId) {
958 Slog.d(TAG, "onCleanupUser " + userId);
959
960 try {
Jeff Sharkeybcd262d2015-06-10 09:41:17 -0700961 mConnector.execute("volume", "user_stopped", userId);
Jeff Sharkey48877892015-03-18 11:27:19 -0700962 } catch (NativeDaemonConnectorException ignored) {
963 }
964
yuanhuihuiefd1f122016-07-13 21:21:03 +0800965 synchronized (mLock) {
Jeff Sharkeyce14cd02015-12-07 15:35:42 -0700966 mSystemUnlockedUsers = ArrayUtils.removeInt(mSystemUnlockedUsers, userId);
Jeff Sharkey48877892015-03-18 11:27:19 -0700967 }
968 }
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700969
Christopher Tated417d622013-08-19 16:14:25 -0700970 void runIdleMaintenance(Runnable callback) {
971 mHandler.sendMessage(mHandler.obtainMessage(H_FSTRIM, callback));
972 }
973
Christopher Tate7265abe2014-11-21 13:54:45 -0800974 // Binder entry point for kicking off an immediate fstrim
975 @Override
976 public void runMaintenance() {
Jeff Sharkey48877892015-03-18 11:27:19 -0700977 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
Christopher Tate7265abe2014-11-21 13:54:45 -0800978 runIdleMaintenance(null);
979 }
980
981 @Override
982 public long lastMaintenance() {
983 return mLastMaintenance;
984 }
985
San Mehat4270e1e2010-01-29 05:32:19 -0800986 /**
San Mehat4270e1e2010-01-29 05:32:19 -0800987 * Callback from NativeDaemonConnector
988 */
Jeff Sharkey48877892015-03-18 11:27:19 -0700989 @Override
San Mehat4270e1e2010-01-29 05:32:19 -0800990 public void onDaemonConnected() {
Jeff Sharkey48877892015-03-18 11:27:19 -0700991 mDaemonConnected = true;
992 mHandler.obtainMessage(H_DAEMON_CONNECTED).sendToTarget();
993 }
994
995 private void handleDaemonConnected() {
Jeff Sharkey8924e872015-11-30 12:52:10 -0700996 initIfReadyAndConnected();
Jeff Sharkey5a9bb742015-11-03 10:15:57 -0800997 resetIfReadyAndConnected();
Jeff Sharkey48877892015-03-18 11:27:19 -0700998
San Mehat4270e1e2010-01-29 05:32:19 -0800999 /*
Jeff Sharkey48877892015-03-18 11:27:19 -07001000 * Now that we've done our initialization, release
1001 * the hounds!
San Mehat4270e1e2010-01-29 05:32:19 -08001002 */
Jeff Sharkey48877892015-03-18 11:27:19 -07001003 mConnectedSignal.countDown();
Paul Lawrence1c62cbb2015-06-03 14:14:52 -07001004 if (mConnectedSignal.getCount() != 0) {
1005 // More daemons need to connect
1006 return;
1007 }
Mike Lockwood7fa24aa2011-03-23 14:52:34 -04001008
Jeff Sharkey48877892015-03-18 11:27:19 -07001009 // On an encrypted device we can't see system properties yet, so pull
1010 // the system locale out of the mount service.
1011 if ("".equals(SystemProperties.get("vold.encrypt_progress"))) {
1012 copyLocaleFromMountService();
1013 }
Jeff Sharkeyb049e212012-09-07 23:16:01 -07001014
Jeff Sharkey48877892015-03-18 11:27:19 -07001015 // Let package manager load internal ASECs.
1016 mPms.scanAvailableAsecs();
Mike Lockwood7fa24aa2011-03-23 14:52:34 -04001017
Jeff Sharkey48877892015-03-18 11:27:19 -07001018 // Notify people waiting for ASECs to be scanned that it's done.
1019 mAsecsScanned.countDown();
San Mehat4270e1e2010-01-29 05:32:19 -08001020 }
1021
Elliott Hughesf839b4f2014-09-26 12:30:47 -07001022 private void copyLocaleFromMountService() {
1023 String systemLocale;
1024 try {
1025 systemLocale = getField(StorageManager.SYSTEM_LOCALE_KEY);
1026 } catch (RemoteException e) {
1027 return;
1028 }
1029 if (TextUtils.isEmpty(systemLocale)) {
1030 return;
1031 }
1032
1033 Slog.d(TAG, "Got locale " + systemLocale + " from mount service");
1034 Locale locale = Locale.forLanguageTag(systemLocale);
1035 Configuration config = new Configuration();
1036 config.setLocale(locale);
1037 try {
Sudheer Shankadc589ac2016-11-10 15:30:17 -08001038 ActivityManager.getService().updatePersistentConfiguration(config);
Elliott Hughesf839b4f2014-09-26 12:30:47 -07001039 } catch (RemoteException e) {
1040 Slog.e(TAG, "Error setting system locale from mount service", e);
1041 }
Elliott Hughes9c33f282014-10-13 12:39:56 -07001042
1043 // Temporary workaround for http://b/17945169.
1044 Slog.d(TAG, "Setting system properties to " + systemLocale + " from mount service");
Narayan Kamathd30dbb82015-01-15 14:48:15 +00001045 SystemProperties.set("persist.sys.locale", locale.toLanguageTag());
Elliott Hughesf839b4f2014-09-26 12:30:47 -07001046 }
1047
San Mehat4270e1e2010-01-29 05:32:19 -08001048 /**
San Mehat4270e1e2010-01-29 05:32:19 -08001049 * Callback from NativeDaemonConnector
1050 */
Jeff Sharkey48877892015-03-18 11:27:19 -07001051 @Override
Dianne Hackborn77b987f2014-02-26 16:20:52 -08001052 public boolean onCheckHoldWakeLock(int code) {
1053 return false;
1054 }
1055
1056 /**
1057 * Callback from NativeDaemonConnector
1058 */
Jeff Sharkey48877892015-03-18 11:27:19 -07001059 @Override
San Mehat4270e1e2010-01-29 05:32:19 -08001060 public boolean onEvent(int code, String raw, String[] cooked) {
Jeff Sharkey48877892015-03-18 11:27:19 -07001061 synchronized (mLock) {
1062 return onEventLocked(code, raw, cooked);
Suchi Amalapurapu8a9ab242010-03-11 16:49:16 -08001063 }
Jeff Sharkey48877892015-03-18 11:27:19 -07001064 }
Jeff Sharkey5aca2b82013-10-16 16:21:54 -07001065
Jeff Sharkey48877892015-03-18 11:27:19 -07001066 private boolean onEventLocked(int code, String raw, String[] cooked) {
1067 switch (code) {
1068 case VoldResponseCode.DISK_CREATED: {
1069 if (cooked.length != 3) break;
1070 final String id = cooked[1];
Jeff Sharkey74acbbb2015-04-21 12:14:03 -07001071 int flags = Integer.parseInt(cooked[2]);
Jeff Sharkey4c099d02015-05-15 13:45:00 -07001072 if (SystemProperties.getBoolean(StorageManager.PROP_FORCE_ADOPTABLE, false)
1073 || mForceAdoptable) {
Jeff Sharkey74acbbb2015-04-21 12:14:03 -07001074 flags |= DiskInfo.FLAG_ADOPTABLE;
1075 }
Jeff Sharkey6ed74182016-08-23 13:53:53 -06001076 // Adoptable storage isn't currently supported on FBE devices
1077 if (StorageManager.isFileEncryptedNativeOnly()) {
1078 flags &= ~DiskInfo.FLAG_ADOPTABLE;
1079 }
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07001080 mDisks.put(id, new DiskInfo(id, flags));
Jeff Sharkey48877892015-03-18 11:27:19 -07001081 break;
Jeff Sharkey5aca2b82013-10-16 16:21:54 -07001082 }
Jeff Sharkey48877892015-03-18 11:27:19 -07001083 case VoldResponseCode.DISK_SIZE_CHANGED: {
1084 if (cooked.length != 3) break;
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07001085 final DiskInfo disk = mDisks.get(cooked[1]);
Jeff Sharkey48877892015-03-18 11:27:19 -07001086 if (disk != null) {
1087 disk.size = Long.parseLong(cooked[2]);
San Mehat4270e1e2010-01-29 05:32:19 -08001088 }
Jeff Sharkey48877892015-03-18 11:27:19 -07001089 break;
1090 }
1091 case VoldResponseCode.DISK_LABEL_CHANGED: {
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07001092 final DiskInfo disk = mDisks.get(cooked[1]);
Jeff Sharkey48877892015-03-18 11:27:19 -07001093 if (disk != null) {
Jeff Sharkey27de30d2015-04-18 16:20:27 -07001094 final StringBuilder builder = new StringBuilder();
1095 for (int i = 2; i < cooked.length; i++) {
1096 builder.append(cooked[i]).append(' ');
1097 }
1098 disk.label = builder.toString().trim();
Jeff Sharkey48877892015-03-18 11:27:19 -07001099 }
1100 break;
1101 }
Jeff Sharkeyeba260d2015-04-19 14:35:16 -07001102 case VoldResponseCode.DISK_SCANNED: {
Jeff Sharkey7e92ef32015-04-17 17:35:07 -07001103 if (cooked.length != 2) break;
1104 final DiskInfo disk = mDisks.get(cooked[1]);
Jeff Sharkeyeba260d2015-04-19 14:35:16 -07001105 if (disk != null) {
1106 onDiskScannedLocked(disk);
1107 }
Jeff Sharkey59d577a2015-04-11 21:27:21 -07001108 break;
1109 }
Jeff Sharkeye8a4b662015-06-27 15:43:45 -07001110 case VoldResponseCode.DISK_SYS_PATH_CHANGED: {
1111 if (cooked.length != 3) break;
1112 final DiskInfo disk = mDisks.get(cooked[1]);
1113 if (disk != null) {
1114 disk.sysPath = cooked[2];
1115 }
1116 break;
1117 }
Jeff Sharkey48877892015-03-18 11:27:19 -07001118 case VoldResponseCode.DISK_DESTROYED: {
1119 if (cooked.length != 2) break;
Makoto Onuki9dc575d2015-06-12 16:10:25 -07001120 final DiskInfo disk = mDisks.remove(cooked[1]);
1121 if (disk != null) {
1122 mCallbacks.notifyDiskDestroyed(disk);
1123 }
Jeff Sharkey48877892015-03-18 11:27:19 -07001124 break;
1125 }
San Mehat4270e1e2010-01-29 05:32:19 -08001126
Jeff Sharkey48877892015-03-18 11:27:19 -07001127 case VoldResponseCode.VOLUME_CREATED: {
Jeff Sharkey48877892015-03-18 11:27:19 -07001128 final String id = cooked[1];
1129 final int type = Integer.parseInt(cooked[2]);
Jeff Sharkey5cc0df22015-06-17 19:44:05 -07001130 final String diskId = TextUtils.nullIfEmpty(cooked[3]);
1131 final String partGuid = TextUtils.nullIfEmpty(cooked[4]);
1132
Jeff Sharkey27de30d2015-04-18 16:20:27 -07001133 final DiskInfo disk = mDisks.get(diskId);
Jeff Sharkey5af1835d2015-07-07 17:26:59 -07001134 final VolumeInfo vol = new VolumeInfo(id, type, disk, partGuid);
Jeff Sharkey48877892015-03-18 11:27:19 -07001135 mVolumes.put(id, vol);
1136 onVolumeCreatedLocked(vol);
1137 break;
1138 }
1139 case VoldResponseCode.VOLUME_STATE_CHANGED: {
1140 if (cooked.length != 3) break;
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07001141 final VolumeInfo vol = mVolumes.get(cooked[1]);
Jeff Sharkey48877892015-03-18 11:27:19 -07001142 if (vol != null) {
1143 final int oldState = vol.state;
1144 final int newState = Integer.parseInt(cooked[2]);
1145 vol.state = newState;
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001146 onVolumeStateChangedLocked(vol, oldState, newState);
Jeff Sharkey48877892015-03-18 11:27:19 -07001147 }
1148 break;
1149 }
1150 case VoldResponseCode.VOLUME_FS_TYPE_CHANGED: {
1151 if (cooked.length != 3) break;
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07001152 final VolumeInfo vol = mVolumes.get(cooked[1]);
Jeff Sharkey48877892015-03-18 11:27:19 -07001153 if (vol != null) {
1154 vol.fsType = cooked[2];
1155 }
1156 break;
1157 }
1158 case VoldResponseCode.VOLUME_FS_UUID_CHANGED: {
1159 if (cooked.length != 3) break;
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07001160 final VolumeInfo vol = mVolumes.get(cooked[1]);
Jeff Sharkey48877892015-03-18 11:27:19 -07001161 if (vol != null) {
1162 vol.fsUuid = cooked[2];
1163 }
1164 break;
1165 }
1166 case VoldResponseCode.VOLUME_FS_LABEL_CHANGED: {
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07001167 final VolumeInfo vol = mVolumes.get(cooked[1]);
Jeff Sharkey48877892015-03-18 11:27:19 -07001168 if (vol != null) {
Jeff Sharkey27de30d2015-04-18 16:20:27 -07001169 final StringBuilder builder = new StringBuilder();
1170 for (int i = 2; i < cooked.length; i++) {
1171 builder.append(cooked[i]).append(' ');
1172 }
1173 vol.fsLabel = builder.toString().trim();
Jeff Sharkey48877892015-03-18 11:27:19 -07001174 }
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001175 // TODO: notify listeners that label changed
Jeff Sharkey48877892015-03-18 11:27:19 -07001176 break;
1177 }
1178 case VoldResponseCode.VOLUME_PATH_CHANGED: {
1179 if (cooked.length != 3) break;
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07001180 final VolumeInfo vol = mVolumes.get(cooked[1]);
Jeff Sharkey48877892015-03-18 11:27:19 -07001181 if (vol != null) {
1182 vol.path = cooked[2];
1183 }
1184 break;
1185 }
Jeff Sharkey50a05452015-04-29 11:24:52 -07001186 case VoldResponseCode.VOLUME_INTERNAL_PATH_CHANGED: {
1187 if (cooked.length != 3) break;
1188 final VolumeInfo vol = mVolumes.get(cooked[1]);
1189 if (vol != null) {
1190 vol.internalPath = cooked[2];
1191 }
1192 break;
1193 }
Jeff Sharkey48877892015-03-18 11:27:19 -07001194 case VoldResponseCode.VOLUME_DESTROYED: {
1195 if (cooked.length != 2) break;
1196 mVolumes.remove(cooked[1]);
1197 break;
1198 }
San Mehat4270e1e2010-01-29 05:32:19 -08001199
Jeff Sharkey275e3e42015-04-24 16:10:32 -07001200 case VoldResponseCode.MOVE_STATUS: {
1201 final int status = Integer.parseInt(cooked[1]);
1202 onMoveStatusLocked(status);
1203 break;
1204 }
Jeff Sharkey9756d752015-05-14 21:07:42 -07001205 case VoldResponseCode.BENCHMARK_RESULT: {
Jeff Sharkeye8a4b662015-06-27 15:43:45 -07001206 if (cooked.length != 7) break;
1207 final String path = cooked[1];
1208 final String ident = cooked[2];
1209 final long create = Long.parseLong(cooked[3]);
1210 final long drop = Long.parseLong(cooked[4]);
1211 final long run = Long.parseLong(cooked[5]);
1212 final long destroy = Long.parseLong(cooked[6]);
1213
Jeff Sharkey9756d752015-05-14 21:07:42 -07001214 final DropBoxManager dropBox = mContext.getSystemService(DropBoxManager.class);
Jeff Sharkeye8a4b662015-06-27 15:43:45 -07001215 dropBox.addText(TAG_STORAGE_BENCHMARK, scrubPath(path)
1216 + " " + ident + " " + create + " " + run + " " + destroy);
1217
1218 final VolumeRecord rec = findRecordForPath(path);
1219 if (rec != null) {
1220 rec.lastBenchMillis = System.currentTimeMillis();
1221 writeSettingsLocked();
1222 }
1223
1224 break;
1225 }
1226 case VoldResponseCode.TRIM_RESULT: {
1227 if (cooked.length != 4) break;
1228 final String path = cooked[1];
1229 final long bytes = Long.parseLong(cooked[2]);
1230 final long time = Long.parseLong(cooked[3]);
1231
1232 final DropBoxManager dropBox = mContext.getSystemService(DropBoxManager.class);
1233 dropBox.addText(TAG_STORAGE_TRIM, scrubPath(path)
1234 + " " + bytes + " " + time);
1235
1236 final VolumeRecord rec = findRecordForPath(path);
1237 if (rec != null) {
1238 rec.lastTrimMillis = System.currentTimeMillis();
1239 writeSettingsLocked();
1240 }
1241
Jeff Sharkey9756d752015-05-14 21:07:42 -07001242 break;
1243 }
1244
Jeff Sharkey48877892015-03-18 11:27:19 -07001245 default: {
1246 Slog.d(TAG, "Unhandled vold event " + code);
Mike Lockwooda5250c92011-05-23 13:44:04 -04001247 }
San Mehat4270e1e2010-01-29 05:32:19 -08001248 }
1249
Daniel Sandler5f27ef42010-03-16 15:42:02 -04001250 return true;
San Mehat4270e1e2010-01-29 05:32:19 -08001251 }
1252
Jeff Sharkeyeba260d2015-04-19 14:35:16 -07001253 private void onDiskScannedLocked(DiskInfo disk) {
Jeff Sharkey620b32b2015-04-23 19:36:02 -07001254 int volumeCount = 0;
Jeff Sharkeyeba260d2015-04-19 14:35:16 -07001255 for (int i = 0; i < mVolumes.size(); i++) {
1256 final VolumeInfo vol = mVolumes.valueAt(i);
1257 if (Objects.equals(disk.id, vol.getDiskId())) {
Jeff Sharkey620b32b2015-04-23 19:36:02 -07001258 volumeCount++;
Jeff Sharkeyeba260d2015-04-19 14:35:16 -07001259 }
1260 }
1261
Jeff Sharkeyc7acac62015-06-12 16:16:56 -07001262 final Intent intent = new Intent(DiskInfo.ACTION_DISK_SCANNED);
Jeff Sharkey7732e1e2016-03-30 17:14:23 -06001263 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT
1264 | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
Jeff Sharkeyc7acac62015-06-12 16:16:56 -07001265 intent.putExtra(DiskInfo.EXTRA_DISK_ID, disk.id);
1266 intent.putExtra(DiskInfo.EXTRA_VOLUME_COUNT, volumeCount);
Jeff Sharkeyabc3e852015-08-03 14:41:13 -07001267 mHandler.obtainMessage(H_INTERNAL_BROADCAST, intent).sendToTarget();
Jeff Sharkeyc7acac62015-06-12 16:16:56 -07001268
1269 final CountDownLatch latch = mDiskScanLatches.remove(disk.id);
1270 if (latch != null) {
1271 latch.countDown();
1272 }
1273
Jeff Sharkeyf5a6bd72015-05-19 14:42:38 -07001274 disk.volumeCount = volumeCount;
Jeff Sharkey620b32b2015-04-23 19:36:02 -07001275 mCallbacks.notifyDiskScanned(disk, volumeCount);
Jeff Sharkeyeba260d2015-04-19 14:35:16 -07001276 }
1277
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07001278 private void onVolumeCreatedLocked(VolumeInfo vol) {
Jeff Sharkey6855c482016-03-31 14:34:38 -06001279 if (mPms.isOnlyCoreApps()) {
1280 Slog.d(TAG, "System booted in core-only mode; ignoring volume " + vol.getId());
1281 return;
1282 }
1283
Jeff Sharkey275e3e42015-04-24 16:10:32 -07001284 if (vol.type == VolumeInfo.TYPE_EMULATED) {
1285 final StorageManager storage = mContext.getSystemService(StorageManager.class);
1286 final VolumeInfo privateVol = storage.findPrivateForEmulated(vol);
1287
1288 if (Objects.equals(StorageManager.UUID_PRIVATE_INTERNAL, mPrimaryStorageUuid)
1289 && VolumeInfo.ID_PRIVATE_INTERNAL.equals(privateVol.id)) {
1290 Slog.v(TAG, "Found primary storage at " + vol);
1291 vol.mountFlags |= VolumeInfo.MOUNT_FLAG_PRIMARY;
1292 vol.mountFlags |= VolumeInfo.MOUNT_FLAG_VISIBLE;
1293 mHandler.obtainMessage(H_VOLUME_MOUNT, vol).sendToTarget();
1294
1295 } else if (Objects.equals(privateVol.fsUuid, mPrimaryStorageUuid)) {
1296 Slog.v(TAG, "Found primary storage at " + vol);
1297 vol.mountFlags |= VolumeInfo.MOUNT_FLAG_PRIMARY;
1298 vol.mountFlags |= VolumeInfo.MOUNT_FLAG_VISIBLE;
1299 mHandler.obtainMessage(H_VOLUME_MOUNT, vol).sendToTarget();
1300 }
Jeff Sharkeyb049e212012-09-07 23:16:01 -07001301
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07001302 } else if (vol.type == VolumeInfo.TYPE_PUBLIC) {
Jeff Sharkey275e3e42015-04-24 16:10:32 -07001303 // TODO: only look at first public partition
1304 if (Objects.equals(StorageManager.UUID_PRIMARY_PHYSICAL, mPrimaryStorageUuid)
1305 && vol.disk.isDefaultPrimary()) {
1306 Slog.v(TAG, "Found primary storage at " + vol);
Jeff Sharkey7e92ef32015-04-17 17:35:07 -07001307 vol.mountFlags |= VolumeInfo.MOUNT_FLAG_PRIMARY;
1308 vol.mountFlags |= VolumeInfo.MOUNT_FLAG_VISIBLE;
San Mehat4270e1e2010-01-29 05:32:19 -08001309 }
Jeff Sharkey7e92ef32015-04-17 17:35:07 -07001310
1311 // Adoptable public disks are visible to apps, since they meet
1312 // public API requirement of being in a stable location.
Jeff Sharkey275e3e42015-04-24 16:10:32 -07001313 if (vol.disk.isAdoptable()) {
Jeff Sharkey7e92ef32015-04-17 17:35:07 -07001314 vol.mountFlags |= VolumeInfo.MOUNT_FLAG_VISIBLE;
1315 }
1316
Jeff Sharkeyab15c392016-05-05 11:45:01 -06001317 vol.mountUserId = mCurrentUserId;
Jeff Sharkey48877892015-03-18 11:27:19 -07001318 mHandler.obtainMessage(H_VOLUME_MOUNT, vol).sendToTarget();
San Mehat4270e1e2010-01-29 05:32:19 -08001319
Jeff Sharkeyb2b9ab82015-04-05 21:10:42 -07001320 } else if (vol.type == VolumeInfo.TYPE_PRIVATE) {
1321 mHandler.obtainMessage(H_VOLUME_MOUNT, vol).sendToTarget();
1322
San Mehat4270e1e2010-01-29 05:32:19 -08001323 } else {
Jeff Sharkey48877892015-03-18 11:27:19 -07001324 Slog.d(TAG, "Skipping automatic mounting of " + vol);
San Mehat4270e1e2010-01-29 05:32:19 -08001325 }
1326 }
1327
Jeff Sharkeye6c04f92015-04-18 21:38:05 -07001328 private boolean isBroadcastWorthy(VolumeInfo vol) {
1329 switch (vol.getType()) {
Jeff Sharkeyc7acac62015-06-12 16:16:56 -07001330 case VolumeInfo.TYPE_PRIVATE:
Jeff Sharkeye6c04f92015-04-18 21:38:05 -07001331 case VolumeInfo.TYPE_PUBLIC:
1332 case VolumeInfo.TYPE_EMULATED:
1333 break;
1334 default:
1335 return false;
1336 }
1337
1338 switch (vol.getState()) {
1339 case VolumeInfo.STATE_MOUNTED:
1340 case VolumeInfo.STATE_MOUNTED_READ_ONLY:
1341 case VolumeInfo.STATE_EJECTING:
1342 case VolumeInfo.STATE_UNMOUNTED:
Jeff Sharkeyc7acac62015-06-12 16:16:56 -07001343 case VolumeInfo.STATE_UNMOUNTABLE:
Tony Mantlerf0d71052015-06-24 11:45:25 -07001344 case VolumeInfo.STATE_BAD_REMOVAL:
Jeff Sharkeye6c04f92015-04-18 21:38:05 -07001345 break;
1346 default:
1347 return false;
1348 }
1349
1350 return true;
1351 }
1352
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07001353 private void onVolumeStateChangedLocked(VolumeInfo vol, int oldState, int newState) {
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001354 // Remember that we saw this volume so we're ready to accept user
1355 // metadata, or so we can annoy them when a private volume is ejected
1356 if (vol.isMountedReadable() && !TextUtils.isEmpty(vol.fsUuid)) {
Jeff Sharkey5cc0df22015-06-17 19:44:05 -07001357 VolumeRecord rec = mRecords.get(vol.fsUuid);
1358 if (rec == null) {
1359 rec = new VolumeRecord(vol.type, vol.fsUuid);
1360 rec.partGuid = vol.partGuid;
Jeff Sharkeye8a4b662015-06-27 15:43:45 -07001361 rec.createdMillis = System.currentTimeMillis();
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001362 if (vol.type == VolumeInfo.TYPE_PRIVATE) {
1363 rec.nickname = vol.disk.getDescription();
1364 }
1365 mRecords.put(rec.fsUuid, rec);
1366 writeSettingsLocked();
Jeff Sharkey5cc0df22015-06-17 19:44:05 -07001367 } else {
1368 // Handle upgrade case where we didn't store partition GUID
1369 if (TextUtils.isEmpty(rec.partGuid)) {
1370 rec.partGuid = vol.partGuid;
1371 writeSettingsLocked();
1372 }
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001373 }
1374 }
1375
Jeff Sharkeye6c04f92015-04-18 21:38:05 -07001376 mCallbacks.notifyVolumeStateChanged(vol, oldState, newState);
1377
Yasuhiro Matsuda87a38b52015-07-24 22:10:16 +09001378 // Do not broadcast before boot has completed to avoid launching the
1379 // processes that receive the intent unnecessarily.
1380 if (mBootCompleted && isBroadcastWorthy(vol)) {
Jeff Sharkeye6c04f92015-04-18 21:38:05 -07001381 final Intent intent = new Intent(VolumeInfo.ACTION_VOLUME_STATE_CHANGED);
Jeff Sharkeyc7acac62015-06-12 16:16:56 -07001382 intent.putExtra(VolumeInfo.EXTRA_VOLUME_ID, vol.id);
1383 intent.putExtra(VolumeInfo.EXTRA_VOLUME_STATE, newState);
Tony Mantlerf0d71052015-06-24 11:45:25 -07001384 intent.putExtra(VolumeRecord.EXTRA_FS_UUID, vol.fsUuid);
Jeff Sharkey7732e1e2016-03-30 17:14:23 -06001385 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT
1386 | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
Jeff Sharkeyabc3e852015-08-03 14:41:13 -07001387 mHandler.obtainMessage(H_INTERNAL_BROADCAST, intent).sendToTarget();
Jeff Sharkeye6c04f92015-04-18 21:38:05 -07001388 }
Jeff Sharkeyb049e212012-09-07 23:16:01 -07001389
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001390 final String oldStateEnv = VolumeInfo.getEnvironmentForState(oldState);
1391 final String newStateEnv = VolumeInfo.getEnvironmentForState(newState);
Emily Bernier92aa5a22014-07-07 10:11:48 -04001392
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001393 if (!Objects.equals(oldStateEnv, newStateEnv)) {
1394 // Kick state changed event towards all started users. Any users
1395 // started after this point will trigger additional
1396 // user-specific broadcasts.
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07001397 for (int userId : mSystemUnlockedUsers) {
Jeff Sharkey46349872015-07-28 10:49:47 -07001398 if (vol.isVisibleForRead(userId)) {
Svet Ganov6ee871e2015-07-10 14:29:33 -07001399 final StorageVolume userVol = vol.buildStorageVolume(mContext, userId, false);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001400 mHandler.obtainMessage(H_VOLUME_BROADCAST, userVol).sendToTarget();
Jeff Sharkey48877892015-03-18 11:27:19 -07001401
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001402 mCallbacks.notifyStorageStateChanged(userVol.getPath(), oldStateEnv,
1403 newStateEnv);
San Mehat4270e1e2010-01-29 05:32:19 -08001404 }
1405 }
1406 }
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001407
Jeff Sharkey7e92ef32015-04-17 17:35:07 -07001408 if (vol.type == VolumeInfo.TYPE_PUBLIC && vol.state == VolumeInfo.STATE_EJECTING) {
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001409 // TODO: this should eventually be handled by new ObbVolume state changes
1410 /*
1411 * Some OBBs might have been unmounted when this volume was
1412 * unmounted, so send a message to the handler to let it know to
1413 * remove those from the list of mounted OBBS.
1414 */
1415 mObbActionHandler.sendMessage(mObbActionHandler.obtainMessage(
1416 OBB_FLUSH_MOUNT_STATE, vol.path));
1417 }
San Mehat4270e1e2010-01-29 05:32:19 -08001418 }
1419
Jeff Sharkey275e3e42015-04-24 16:10:32 -07001420 private void onMoveStatusLocked(int status) {
1421 if (mMoveCallback == null) {
1422 Slog.w(TAG, "Odd, status but no move requested");
1423 return;
1424 }
1425
1426 // TODO: estimate remaining time
1427 try {
Jeff Sharkey50a05452015-04-29 11:24:52 -07001428 mMoveCallback.onStatusChanged(-1, status, -1);
Jeff Sharkey275e3e42015-04-24 16:10:32 -07001429 } catch (RemoteException ignored) {
1430 }
1431
1432 // We've finished copying and we're about to clean up old data, so
1433 // remember that move was successful if we get rebooted
1434 if (status == MOVE_STATUS_COPY_FINISHED) {
1435 Slog.d(TAG, "Move to " + mMoveTargetUuid + " copy phase finshed; persisting");
1436
1437 mPrimaryStorageUuid = mMoveTargetUuid;
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001438 writeSettingsLocked();
Jeff Sharkey275e3e42015-04-24 16:10:32 -07001439 }
1440
1441 if (PackageManager.isMoveStatusFinished(status)) {
1442 Slog.d(TAG, "Move to " + mMoveTargetUuid + " finished with status " + status);
1443
1444 mMoveCallback = null;
1445 mMoveTargetUuid = null;
1446 }
1447 }
1448
Jeff Sharkey48877892015-03-18 11:27:19 -07001449 private void enforcePermission(String perm) {
1450 mContext.enforceCallingOrSelfPermission(perm, perm);
Mike Lockwooda5250c92011-05-23 13:44:04 -04001451 }
1452
Jeff Sharkey2e606d72015-07-27 14:19:54 -07001453 /**
1454 * Decide if volume is mountable per device policies.
1455 */
1456 private boolean isMountDisallowed(VolumeInfo vol) {
Philip P. Moltmannec3cbb22016-09-14 13:24:52 -07001457 UserManager userManager = mContext.getSystemService(UserManager.class);
1458
1459 boolean isUsbRestricted = false;
1460 if (vol.disk != null && vol.disk.isUsb()) {
1461 isUsbRestricted = userManager.hasUserRestriction(UserManager.DISALLOW_USB_FILE_TRANSFER,
Jeff Sharkey2e606d72015-07-27 14:19:54 -07001462 Binder.getCallingUserHandle());
Emily Bernier92aa5a22014-07-07 10:11:48 -04001463 }
Philip P. Moltmannec3cbb22016-09-14 13:24:52 -07001464
1465 boolean isTypeRestricted = false;
1466 if (vol.type == VolumeInfo.TYPE_PUBLIC || vol.type == VolumeInfo.TYPE_PRIVATE) {
1467 isTypeRestricted = userManager
1468 .hasUserRestriction(UserManager.DISALLOW_MOUNT_PHYSICAL_MEDIA,
1469 Binder.getCallingUserHandle());
1470 }
1471
1472 return isUsbRestricted || isTypeRestricted;
Emily Bernier92aa5a22014-07-07 10:11:48 -04001473 }
1474
Amith Yamasani462ac3a2015-06-30 14:21:01 -07001475 private void enforceAdminUser() {
1476 UserManager um = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
1477 final int callingUserId = UserHandle.getCallingUserId();
1478 boolean isAdmin;
1479 long token = Binder.clearCallingIdentity();
1480 try {
1481 isAdmin = um.getUserInfo(callingUserId).isAdmin();
1482 } finally {
1483 Binder.restoreCallingIdentity(token);
1484 }
1485 if (!isAdmin) {
1486 throw new SecurityException("Only admin users can adopt sd cards");
1487 }
1488 }
1489
Jeff Sharkeyb049e212012-09-07 23:16:01 -07001490 /**
Sudheer Shanka2250d562016-11-07 15:41:02 -08001491 * Constructs a new StorageManagerService instance
San Mehat207e5382010-02-04 20:46:54 -08001492 *
1493 * @param context Binder context for this service
1494 */
Sudheer Shanka2250d562016-11-07 15:41:02 -08001495 public StorageManagerService(Context context) {
Christopher Tated417d622013-08-19 16:14:25 -07001496 sSelf = this;
1497
San Mehat207e5382010-02-04 20:46:54 -08001498 mContext = context;
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001499 mCallbacks = new Callbacks(FgThread.get().getLooper());
Jeff Sharkeyb9fe5372015-12-03 15:23:08 -07001500 mLockPatternUtils = new LockPatternUtils(mContext);
San Mehat207e5382010-02-04 20:46:54 -08001501
San Mehat207e5382010-02-04 20:46:54 -08001502 // XXX: This will go away soon in favor of IMountServiceObserver
1503 mPms = (PackageManagerService) ServiceManager.getService("package");
1504
Dianne Hackbornefa92b22013-05-03 14:11:43 -07001505 HandlerThread hthread = new HandlerThread(TAG);
1506 hthread.start();
Sudheer Shanka2250d562016-11-07 15:41:02 -08001507 mHandler = new StorageManagerServiceHandler(hthread.getLooper());
Daniel Sandler5f27ef42010-03-16 15:42:02 -04001508
Sudheer Shanka2250d562016-11-07 15:41:02 -08001509 // Add OBB Action Handler to StorageManagerService thread.
Dianne Hackborn8d044e82013-04-30 17:24:15 -07001510 mObbActionHandler = new ObbActionHandler(IoThread.get().getLooper());
Kenny Roota02b8b02010-08-05 16:14:17 -07001511
Christopher Tate7265abe2014-11-21 13:54:45 -08001512 // Initialize the last-fstrim tracking if necessary
1513 File dataDir = Environment.getDataDirectory();
1514 File systemDir = new File(dataDir, "system");
1515 mLastMaintenanceFile = new File(systemDir, LAST_FSTRIM_FILE);
1516 if (!mLastMaintenanceFile.exists()) {
1517 // Not setting mLastMaintenance here means that we will force an
1518 // fstrim during reboot following the OTA that installs this code.
1519 try {
1520 (new FileOutputStream(mLastMaintenanceFile)).close();
1521 } catch (IOException e) {
1522 Slog.e(TAG, "Unable to create fstrim record " + mLastMaintenanceFile.getPath());
1523 }
1524 } else {
1525 mLastMaintenance = mLastMaintenanceFile.lastModified();
1526 }
1527
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001528 mSettingsFile = new AtomicFile(
Jeff Sharkey8212ae02016-02-10 14:46:43 -07001529 new File(Environment.getDataSystemDirectory(), "storage.xml"));
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001530
1531 synchronized (mLock) {
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001532 readSettingsLocked();
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001533 }
1534
Sudheer Shanka2250d562016-11-07 15:41:02 -08001535 LocalServices.addService(StorageManagerInternal.class, mStorageManagerInternal);
Svet Ganov6ee871e2015-07-10 14:29:33 -07001536
Marco Nelissenc34ebce2010-02-18 13:39:41 -08001537 /*
Kenny Root305bcbf2010-09-03 07:56:38 -07001538 * Create the connection to vold with a maximum queue of twice the
1539 * amount of containers we'd ever expect to have. This keeps an
1540 * "asec list" from blocking a thread repeatedly.
1541 */
Paul Lawrence1c62cbb2015-06-03 14:14:52 -07001542
Dianne Hackborn77b987f2014-02-26 16:20:52 -08001543 mConnector = new NativeDaemonConnector(this, "vold", MAX_CONTAINERS * 2, VOLD_TAG, 25,
1544 null);
Jeff Sharkey48877892015-03-18 11:27:19 -07001545 mConnector.setDebug(true);
Jeff Sharkey8948c012015-11-03 12:33:54 -08001546 mConnector.setWarnIfHeld(mLock);
Jeff Sharkeycd575992016-03-29 14:12:49 -06001547 mConnectorThread = new Thread(mConnector, VOLD_TAG);
Jeff Sharkeyfa23c5a2011-08-09 21:44:24 -07001548
Paul Lawrence1c62cbb2015-06-03 14:14:52 -07001549 // Reuse parameters from first connector since they are tested and safe
1550 mCryptConnector = new NativeDaemonConnector(this, "cryptd",
1551 MAX_CONTAINERS * 2, CRYPTD_TAG, 25, null);
1552 mCryptConnector.setDebug(true);
Jeff Sharkeycd575992016-03-29 14:12:49 -06001553 mCryptConnectorThread = new Thread(mCryptConnector, CRYPTD_TAG);
Paul Lawrence1c62cbb2015-06-03 14:14:52 -07001554
Jeff Sharkeybcd262d2015-06-10 09:41:17 -07001555 final IntentFilter userFilter = new IntentFilter();
1556 userFilter.addAction(Intent.ACTION_USER_ADDED);
1557 userFilter.addAction(Intent.ACTION_USER_REMOVED);
1558 mContext.registerReceiver(mUserReceiver, userFilter, null, mHandler);
1559
Jeff Sharkey5a9bb742015-11-03 10:15:57 -08001560 synchronized (mLock) {
1561 addInternalVolumeLocked();
1562 }
Amith Yamasania7892482015-08-07 11:09:05 -07001563
Kenny Root07714d42011-08-17 17:49:28 -07001564 // Add ourself to the Watchdog monitors if enabled.
1565 if (WATCHDOG_ENABLE) {
1566 Watchdog.getInstance().addMonitor(this);
1567 }
San Mehat207e5382010-02-04 20:46:54 -08001568 }
1569
Jeff Sharkeycd575992016-03-29 14:12:49 -06001570 private void start() {
1571 mConnectorThread.start();
1572 mCryptConnectorThread.start();
1573 }
1574
Jeff Sharkey56e62932015-03-21 20:41:00 -07001575 private void systemReady() {
Jeff Sharkeyb049e212012-09-07 23:16:01 -07001576 mSystemReady = true;
1577 mHandler.obtainMessage(H_SYSTEM_READY).sendToTarget();
1578 }
1579
Yasuhiro Matsuda87a38b52015-07-24 22:10:16 +09001580 private void bootCompleted() {
1581 mBootCompleted = true;
1582 }
1583
Jeff Sharkeyfced5342015-05-10 14:53:34 -07001584 private String getDefaultPrimaryStorageUuid() {
1585 if (SystemProperties.getBoolean(StorageManager.PROP_PRIMARY_PHYSICAL, false)) {
1586 return StorageManager.UUID_PRIMARY_PHYSICAL;
1587 } else {
1588 return StorageManager.UUID_PRIVATE_INTERNAL;
1589 }
1590 }
1591
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001592 private void readSettingsLocked() {
1593 mRecords.clear();
Jeff Sharkeyfced5342015-05-10 14:53:34 -07001594 mPrimaryStorageUuid = getDefaultPrimaryStorageUuid();
Jeff Sharkey4c099d02015-05-15 13:45:00 -07001595 mForceAdoptable = false;
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001596
1597 FileInputStream fis = null;
1598 try {
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001599 fis = mSettingsFile.openRead();
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001600 final XmlPullParser in = Xml.newPullParser();
Wojciech Staszkiewicz9e9e2e72015-05-08 14:58:46 +01001601 in.setInput(fis, StandardCharsets.UTF_8.name());
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001602
1603 int type;
1604 while ((type = in.next()) != END_DOCUMENT) {
1605 if (type == START_TAG) {
1606 final String tag = in.getName();
Jeff Sharkey620b32b2015-04-23 19:36:02 -07001607 if (TAG_VOLUMES.equals(tag)) {
1608 final int version = readIntAttribute(in, ATTR_VERSION, VERSION_INIT);
Jeff Sharkeyfced5342015-05-10 14:53:34 -07001609 final boolean primaryPhysical = SystemProperties.getBoolean(
1610 StorageManager.PROP_PRIMARY_PHYSICAL, false);
1611 final boolean validAttr = (version >= VERSION_FIX_PRIMARY)
1612 || (version >= VERSION_ADD_PRIMARY && !primaryPhysical);
1613 if (validAttr) {
Jeff Sharkey620b32b2015-04-23 19:36:02 -07001614 mPrimaryStorageUuid = readStringAttribute(in,
1615 ATTR_PRIMARY_STORAGE_UUID);
Jeff Sharkey620b32b2015-04-23 19:36:02 -07001616 }
Jeff Sharkey4c099d02015-05-15 13:45:00 -07001617 mForceAdoptable = readBooleanAttribute(in, ATTR_FORCE_ADOPTABLE, false);
Jeff Sharkey620b32b2015-04-23 19:36:02 -07001618
1619 } else if (TAG_VOLUME.equals(tag)) {
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001620 final VolumeRecord rec = readVolumeRecord(in);
1621 mRecords.put(rec.fsUuid, rec);
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001622 }
1623 }
1624 }
1625 } catch (FileNotFoundException e) {
1626 // Missing metadata is okay, probably first boot
1627 } catch (IOException e) {
1628 Slog.wtf(TAG, "Failed reading metadata", e);
1629 } catch (XmlPullParserException e) {
1630 Slog.wtf(TAG, "Failed reading metadata", e);
1631 } finally {
1632 IoUtils.closeQuietly(fis);
1633 }
1634 }
1635
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001636 private void writeSettingsLocked() {
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001637 FileOutputStream fos = null;
1638 try {
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001639 fos = mSettingsFile.startWrite();
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001640
1641 XmlSerializer out = new FastXmlSerializer();
Wojciech Staszkiewicz9e9e2e72015-05-08 14:58:46 +01001642 out.setOutput(fos, StandardCharsets.UTF_8.name());
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001643 out.startDocument(null, true);
1644 out.startTag(null, TAG_VOLUMES);
Jeff Sharkeyfced5342015-05-10 14:53:34 -07001645 writeIntAttribute(out, ATTR_VERSION, VERSION_FIX_PRIMARY);
Jeff Sharkey620b32b2015-04-23 19:36:02 -07001646 writeStringAttribute(out, ATTR_PRIMARY_STORAGE_UUID, mPrimaryStorageUuid);
Jeff Sharkey4c099d02015-05-15 13:45:00 -07001647 writeBooleanAttribute(out, ATTR_FORCE_ADOPTABLE, mForceAdoptable);
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001648 final int size = mRecords.size();
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001649 for (int i = 0; i < size; i++) {
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001650 final VolumeRecord rec = mRecords.valueAt(i);
1651 writeVolumeRecord(out, rec);
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001652 }
1653 out.endTag(null, TAG_VOLUMES);
1654 out.endDocument();
1655
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001656 mSettingsFile.finishWrite(fos);
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001657 } catch (IOException e) {
1658 if (fos != null) {
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001659 mSettingsFile.failWrite(fos);
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001660 }
1661 }
1662 }
1663
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001664 public static VolumeRecord readVolumeRecord(XmlPullParser in) throws IOException {
1665 final int type = readIntAttribute(in, ATTR_TYPE);
1666 final String fsUuid = readStringAttribute(in, ATTR_FS_UUID);
1667 final VolumeRecord meta = new VolumeRecord(type, fsUuid);
Jeff Sharkey5cc0df22015-06-17 19:44:05 -07001668 meta.partGuid = readStringAttribute(in, ATTR_PART_GUID);
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001669 meta.nickname = readStringAttribute(in, ATTR_NICKNAME);
1670 meta.userFlags = readIntAttribute(in, ATTR_USER_FLAGS);
Jeff Sharkeye8a4b662015-06-27 15:43:45 -07001671 meta.createdMillis = readLongAttribute(in, ATTR_CREATED_MILLIS);
1672 meta.lastTrimMillis = readLongAttribute(in, ATTR_LAST_TRIM_MILLIS);
1673 meta.lastBenchMillis = readLongAttribute(in, ATTR_LAST_BENCH_MILLIS);
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001674 return meta;
1675 }
1676
1677 public static void writeVolumeRecord(XmlSerializer out, VolumeRecord rec) throws IOException {
1678 out.startTag(null, TAG_VOLUME);
1679 writeIntAttribute(out, ATTR_TYPE, rec.type);
1680 writeStringAttribute(out, ATTR_FS_UUID, rec.fsUuid);
Jeff Sharkey5cc0df22015-06-17 19:44:05 -07001681 writeStringAttribute(out, ATTR_PART_GUID, rec.partGuid);
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001682 writeStringAttribute(out, ATTR_NICKNAME, rec.nickname);
1683 writeIntAttribute(out, ATTR_USER_FLAGS, rec.userFlags);
Jeff Sharkeye8a4b662015-06-27 15:43:45 -07001684 writeLongAttribute(out, ATTR_CREATED_MILLIS, rec.createdMillis);
1685 writeLongAttribute(out, ATTR_LAST_TRIM_MILLIS, rec.lastTrimMillis);
1686 writeLongAttribute(out, ATTR_LAST_BENCH_MILLIS, rec.lastBenchMillis);
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001687 out.endTag(null, TAG_VOLUME);
1688 }
1689
San Mehat207e5382010-02-04 20:46:54 -08001690 /**
San Mehat4270e1e2010-01-29 05:32:19 -08001691 * Exposed API calls below here
1692 */
1693
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001694 @Override
Sudheer Shanka2250d562016-11-07 15:41:02 -08001695 public void registerListener(IStorageEventListener listener) {
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001696 mCallbacks.register(listener);
San Mehat4270e1e2010-01-29 05:32:19 -08001697 }
1698
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001699 @Override
Sudheer Shanka2250d562016-11-07 15:41:02 -08001700 public void unregisterListener(IStorageEventListener listener) {
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001701 mCallbacks.unregister(listener);
San Mehat4270e1e2010-01-29 05:32:19 -08001702 }
1703
Jeff Sharkey48877892015-03-18 11:27:19 -07001704 @Override
Sudheer Shanka2250d562016-11-07 15:41:02 -08001705 public void shutdown(final IStorageShutdownObserver observer) {
Jeff Sharkey48877892015-03-18 11:27:19 -07001706 enforcePermission(android.Manifest.permission.SHUTDOWN);
San Mehat4270e1e2010-01-29 05:32:19 -08001707
San Mehata5078592010-03-25 09:36:54 -07001708 Slog.i(TAG, "Shutting down");
Jeff Sharkey48877892015-03-18 11:27:19 -07001709 mHandler.obtainMessage(H_SHUTDOWN, observer).sendToTarget();
San Mehat4270e1e2010-01-29 05:32:19 -08001710 }
1711
Jeff Sharkey48877892015-03-18 11:27:19 -07001712 @Override
San Mehatb1043402010-02-05 08:26:50 -08001713 public boolean isUsbMassStorageConnected() {
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001714 throw new UnsupportedOperationException();
San Mehatb1043402010-02-05 08:26:50 -08001715 }
1716
Jeff Sharkey48877892015-03-18 11:27:19 -07001717 @Override
Suchi Amalapurapu0eec21d2010-02-25 17:07:14 -08001718 public void setUsbMassStorageEnabled(boolean enable) {
Jeff Sharkey48877892015-03-18 11:27:19 -07001719 throw new UnsupportedOperationException();
San Mehatb1043402010-02-05 08:26:50 -08001720 }
1721
Jeff Sharkey48877892015-03-18 11:27:19 -07001722 @Override
San Mehatb1043402010-02-05 08:26:50 -08001723 public boolean isUsbMassStorageEnabled() {
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001724 throw new UnsupportedOperationException();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001725 }
Jason parks9ed98bc2011-01-17 09:58:35 -06001726
Jeff Sharkey48877892015-03-18 11:27:19 -07001727 @Override
San Mehat4270e1e2010-01-29 05:32:19 -08001728 public String getVolumeState(String mountPoint) {
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07001729 throw new UnsupportedOperationException();
San Mehat7fd0fee2009-12-17 07:12:23 -08001730 }
1731
Jeff Sharkeyb049e212012-09-07 23:16:01 -07001732 @Override
Kenny Roote1ff2142010-10-12 11:20:01 -07001733 public boolean isExternalStorageEmulated() {
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07001734 throw new UnsupportedOperationException();
Kenny Roote1ff2142010-10-12 11:20:01 -07001735 }
1736
Jeff Sharkey48877892015-03-18 11:27:19 -07001737 @Override
San Mehat4270e1e2010-01-29 05:32:19 -08001738 public int mountVolume(String path) {
Jeff Sharkeyef10ee02015-07-05 14:17:27 -07001739 mount(findVolumeIdForPathOrThrow(path));
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001740 return 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001741 }
1742
Jeff Sharkey48877892015-03-18 11:27:19 -07001743 @Override
Ben Komalo13c71972011-09-07 16:35:56 -07001744 public void unmountVolume(String path, boolean force, boolean removeEncryption) {
Jeff Sharkeyef10ee02015-07-05 14:17:27 -07001745 unmount(findVolumeIdForPathOrThrow(path));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001746 }
1747
Jeff Sharkey48877892015-03-18 11:27:19 -07001748 @Override
San Mehat4270e1e2010-01-29 05:32:19 -08001749 public int formatVolume(String path) {
Jeff Sharkeyef10ee02015-07-05 14:17:27 -07001750 format(findVolumeIdForPathOrThrow(path));
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001751 return 0;
1752 }
1753
1754 @Override
1755 public void mount(String volId) {
1756 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
1757 waitForReady();
1758
Jeff Sharkeyef10ee02015-07-05 14:17:27 -07001759 final VolumeInfo vol = findVolumeByIdOrThrow(volId);
Jeff Sharkey2e606d72015-07-27 14:19:54 -07001760 if (isMountDisallowed(vol)) {
1761 throw new SecurityException("Mounting " + volId + " restricted by policy");
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001762 }
1763 try {
Jeff Sharkey7e92ef32015-04-17 17:35:07 -07001764 mConnector.execute("volume", "mount", vol.id, vol.mountFlags, vol.mountUserId);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001765 } catch (NativeDaemonConnectorException e) {
1766 throw e.rethrowAsParcelableException();
1767 }
1768 }
1769
1770 @Override
1771 public void unmount(String volId) {
1772 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
1773 waitForReady();
1774
Jeff Sharkeyef10ee02015-07-05 14:17:27 -07001775 final VolumeInfo vol = findVolumeByIdOrThrow(volId);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001776
1777 // TODO: expand PMS to know about multiple volumes
Jeff Sharkey275e3e42015-04-24 16:10:32 -07001778 if (vol.isPrimaryPhysical()) {
1779 final long ident = Binder.clearCallingIdentity();
1780 try {
1781 synchronized (mUnmountLock) {
1782 mUnmountSignal = new CountDownLatch(1);
1783 mPms.updateExternalMediaStatus(false, true);
1784 waitForLatch(mUnmountSignal, "mUnmountSignal");
1785 mUnmountSignal = null;
1786 }
1787 } finally {
1788 Binder.restoreCallingIdentity(ident);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001789 }
1790 }
1791
1792 try {
1793 mConnector.execute("volume", "unmount", vol.id);
1794 } catch (NativeDaemonConnectorException e) {
1795 throw e.rethrowAsParcelableException();
1796 }
1797 }
1798
1799 @Override
1800 public void format(String volId) {
Jeff Sharkey48877892015-03-18 11:27:19 -07001801 enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);
San Mehat207e5382010-02-04 20:46:54 -08001802 waitForReady();
San Mehat5b77dab2010-01-26 13:28:50 -08001803
Jeff Sharkeyef10ee02015-07-05 14:17:27 -07001804 final VolumeInfo vol = findVolumeByIdOrThrow(volId);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001805 try {
Jeff Sharkey4e83cc92015-05-27 14:38:39 -07001806 mConnector.execute("volume", "format", vol.id, "auto");
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001807 } catch (NativeDaemonConnectorException e) {
1808 throw e.rethrowAsParcelableException();
Jeff Sharkey48877892015-03-18 11:27:19 -07001809 }
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001810 }
1811
1812 @Override
Jeff Sharkey9756d752015-05-14 21:07:42 -07001813 public long benchmark(String volId) {
1814 enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);
1815 waitForReady();
1816
1817 try {
Jeff Sharkey14cbe522015-07-08 14:06:37 -07001818 // TODO: make benchmark async so we don't block other commands
1819 final NativeDaemonEvent res = mConnector.execute(3 * DateUtils.MINUTE_IN_MILLIS,
1820 "volume", "benchmark", volId);
Jeff Sharkey9756d752015-05-14 21:07:42 -07001821 return Long.parseLong(res.getMessage());
Todd Kennedy8101ee62015-06-23 13:35:28 -07001822 } catch (NativeDaemonTimeoutException e) {
1823 return Long.MAX_VALUE;
Jeff Sharkey9756d752015-05-14 21:07:42 -07001824 } catch (NativeDaemonConnectorException e) {
1825 throw e.rethrowAsParcelableException();
1826 }
1827 }
1828
1829 @Override
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001830 public void partitionPublic(String diskId) {
1831 enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);
1832 waitForReady();
1833
Jeff Sharkeyeba260d2015-04-19 14:35:16 -07001834 final CountDownLatch latch = findOrCreateDiskScanLatch(diskId);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001835 try {
1836 mConnector.execute("volume", "partition", diskId, "public");
Jeff Sharkeyedcdaf62015-07-09 09:45:36 -07001837 waitForLatch(latch, "partitionPublic", 3 * DateUtils.MINUTE_IN_MILLIS);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001838 } catch (NativeDaemonConnectorException e) {
1839 throw e.rethrowAsParcelableException();
Jeff Sharkeyedcdaf62015-07-09 09:45:36 -07001840 } catch (TimeoutException e) {
1841 throw new IllegalStateException(e);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001842 }
1843 }
1844
1845 @Override
1846 public void partitionPrivate(String diskId) {
1847 enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);
Amith Yamasani462ac3a2015-06-30 14:21:01 -07001848 enforceAdminUser();
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001849 waitForReady();
1850
Jeff Sharkeyeba260d2015-04-19 14:35:16 -07001851 final CountDownLatch latch = findOrCreateDiskScanLatch(diskId);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001852 try {
1853 mConnector.execute("volume", "partition", diskId, "private");
Jeff Sharkeyedcdaf62015-07-09 09:45:36 -07001854 waitForLatch(latch, "partitionPrivate", 3 * DateUtils.MINUTE_IN_MILLIS);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001855 } catch (NativeDaemonConnectorException e) {
1856 throw e.rethrowAsParcelableException();
Jeff Sharkeyedcdaf62015-07-09 09:45:36 -07001857 } catch (TimeoutException e) {
1858 throw new IllegalStateException(e);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001859 }
1860 }
1861
1862 @Override
1863 public void partitionMixed(String diskId, int ratio) {
1864 enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);
Amith Yamasani462ac3a2015-06-30 14:21:01 -07001865 enforceAdminUser();
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001866 waitForReady();
1867
Jeff Sharkeyeba260d2015-04-19 14:35:16 -07001868 final CountDownLatch latch = findOrCreateDiskScanLatch(diskId);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001869 try {
1870 mConnector.execute("volume", "partition", diskId, "mixed", ratio);
Jeff Sharkeyedcdaf62015-07-09 09:45:36 -07001871 waitForLatch(latch, "partitionMixed", 3 * DateUtils.MINUTE_IN_MILLIS);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001872 } catch (NativeDaemonConnectorException e) {
1873 throw e.rethrowAsParcelableException();
Jeff Sharkeyedcdaf62015-07-09 09:45:36 -07001874 } catch (TimeoutException e) {
1875 throw new IllegalStateException(e);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07001876 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001877 }
1878
Jeff Sharkey48877892015-03-18 11:27:19 -07001879 @Override
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001880 public void setVolumeNickname(String fsUuid, String nickname) {
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001881 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
1882 waitForReady();
1883
Jeff Sharkey50a05452015-04-29 11:24:52 -07001884 Preconditions.checkNotNull(fsUuid);
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001885 synchronized (mLock) {
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001886 final VolumeRecord rec = mRecords.get(fsUuid);
1887 rec.nickname = nickname;
Jeff Sharkey50a05452015-04-29 11:24:52 -07001888 mCallbacks.notifyVolumeRecordChanged(rec);
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001889 writeSettingsLocked();
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001890 }
1891 }
1892
1893 @Override
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001894 public void setVolumeUserFlags(String fsUuid, int flags, int mask) {
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001895 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
1896 waitForReady();
1897
Jeff Sharkey50a05452015-04-29 11:24:52 -07001898 Preconditions.checkNotNull(fsUuid);
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001899 synchronized (mLock) {
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001900 final VolumeRecord rec = mRecords.get(fsUuid);
1901 rec.userFlags = (rec.userFlags & ~mask) | (flags & mask);
Jeff Sharkey50a05452015-04-29 11:24:52 -07001902 mCallbacks.notifyVolumeRecordChanged(rec);
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001903 writeSettingsLocked();
1904 }
1905 }
1906
1907 @Override
1908 public void forgetVolume(String fsUuid) {
1909 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
1910 waitForReady();
1911
Jeff Sharkey50a05452015-04-29 11:24:52 -07001912 Preconditions.checkNotNull(fsUuid);
Jeff Sharkey5a9bb742015-11-03 10:15:57 -08001913
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001914 synchronized (mLock) {
Jeff Sharkey5cc0df22015-06-17 19:44:05 -07001915 final VolumeRecord rec = mRecords.remove(fsUuid);
1916 if (rec != null && !TextUtils.isEmpty(rec.partGuid)) {
Jeff Sharkey5a9bb742015-11-03 10:15:57 -08001917 mHandler.obtainMessage(H_PARTITION_FORGET, rec.partGuid).sendToTarget();
Jeff Sharkey5cc0df22015-06-17 19:44:05 -07001918 }
1919 mCallbacks.notifyVolumeForgotten(fsUuid);
Jeff Sharkey50a05452015-04-29 11:24:52 -07001920
1921 // If this had been primary storage, revert back to internal and
1922 // reset vold so we bind into new volume into place.
1923 if (Objects.equals(mPrimaryStorageUuid, fsUuid)) {
Jeff Sharkeyfced5342015-05-10 14:53:34 -07001924 mPrimaryStorageUuid = getDefaultPrimaryStorageUuid();
Jeff Sharkey5a9bb742015-11-03 10:15:57 -08001925 mHandler.obtainMessage(H_RESET).sendToTarget();
Jeff Sharkey50a05452015-04-29 11:24:52 -07001926 }
1927
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07001928 writeSettingsLocked();
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07001929 }
1930 }
1931
Jeff Sharkey7d2af542015-05-12 15:27:15 -07001932 @Override
1933 public void forgetAllVolumes() {
1934 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
1935 waitForReady();
1936
Jeff Sharkey50a05452015-04-29 11:24:52 -07001937 synchronized (mLock) {
1938 for (int i = 0; i < mRecords.size(); i++) {
1939 final String fsUuid = mRecords.keyAt(i);
Jeff Sharkey5cc0df22015-06-17 19:44:05 -07001940 final VolumeRecord rec = mRecords.valueAt(i);
1941 if (!TextUtils.isEmpty(rec.partGuid)) {
Jeff Sharkey5a9bb742015-11-03 10:15:57 -08001942 mHandler.obtainMessage(H_PARTITION_FORGET, rec.partGuid).sendToTarget();
Jeff Sharkey5cc0df22015-06-17 19:44:05 -07001943 }
Jeff Sharkey50a05452015-04-29 11:24:52 -07001944 mCallbacks.notifyVolumeForgotten(fsUuid);
1945 }
Jeff Sharkey50a05452015-04-29 11:24:52 -07001946 mRecords.clear();
Jeff Sharkey50a05452015-04-29 11:24:52 -07001947
Jeff Sharkeyfced5342015-05-10 14:53:34 -07001948 if (!Objects.equals(StorageManager.UUID_PRIVATE_INTERNAL, mPrimaryStorageUuid)) {
1949 mPrimaryStorageUuid = getDefaultPrimaryStorageUuid();
1950 }
1951
1952 writeSettingsLocked();
Jeff Sharkey5a9bb742015-11-03 10:15:57 -08001953 mHandler.obtainMessage(H_RESET).sendToTarget();
Jeff Sharkey50a05452015-04-29 11:24:52 -07001954 }
1955 }
1956
Jeff Sharkey5cc0df22015-06-17 19:44:05 -07001957 private void forgetPartition(String partGuid) {
1958 try {
1959 mConnector.execute("volume", "forget_partition", partGuid);
1960 } catch (NativeDaemonConnectorException e) {
1961 Slog.w(TAG, "Failed to forget key for " + partGuid + ": " + e);
1962 }
1963 }
1964
Jeff Sharkey31d0b702016-11-21 14:16:53 -07001965 @Override
1966 public void fstrim(int flags) {
1967 enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);
1968 waitForReady();
1969
1970 String cmd;
1971 if ((flags & StorageManager.FSTRIM_FLAG_DEEP) != 0) {
1972 cmd = "dodtrim";
1973 } else {
1974 cmd = "dotrim";
1975 }
1976 if ((flags & StorageManager.FSTRIM_FLAG_BENCHMARK) != 0) {
1977 cmd += "bench";
1978 }
1979
1980 try {
1981 mConnector.execute("fstrim", cmd);
1982 } catch (NativeDaemonConnectorException e) {
1983 Slog.e(TAG, "Failed to run fstrim: " + e);
1984 }
1985 }
1986
Svet Ganov6ee871e2015-07-10 14:29:33 -07001987 private void remountUidExternalStorage(int uid, int mode) {
Jeff Sharkey9527b222015-06-24 15:24:48 -07001988 waitForReady();
1989
Svet Ganov6ee871e2015-07-10 14:29:33 -07001990 String modeName = "none";
1991 switch (mode) {
1992 case Zygote.MOUNT_EXTERNAL_DEFAULT: {
1993 modeName = "default";
1994 } break;
1995
1996 case Zygote.MOUNT_EXTERNAL_READ: {
1997 modeName = "read";
1998 } break;
1999
2000 case Zygote.MOUNT_EXTERNAL_WRITE: {
2001 modeName = "write";
2002 } break;
Jeff Sharkey9527b222015-06-24 15:24:48 -07002003 }
2004
2005 try {
Svet Ganov6ee871e2015-07-10 14:29:33 -07002006 mConnector.execute("volume", "remount_uid", uid, modeName);
Jeff Sharkey9527b222015-06-24 15:24:48 -07002007 } catch (NativeDaemonConnectorException e) {
Svet Ganov6ee871e2015-07-10 14:29:33 -07002008 Slog.w(TAG, "Failed to remount UID " + uid + " as " + modeName + ": " + e);
Jeff Sharkey9527b222015-06-24 15:24:48 -07002009 }
2010 }
2011
2012 @Override
Jeff Sharkey4c099d02015-05-15 13:45:00 -07002013 public void setDebugFlags(int flags, int mask) {
2014 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
2015 waitForReady();
2016
Jeff Sharkeyba512352015-11-12 20:17:45 -08002017 if ((mask & StorageManager.DEBUG_EMULATE_FBE) != 0) {
Jeff Sharkey00455bf2016-11-04 14:45:24 -06002018 if (!EMULATE_FBE_SUPPORTED) {
2019 throw new IllegalStateException(
2020 "Emulation not supported on this device");
2021 }
Paul Lawrence20be5d62016-02-26 13:51:17 -08002022 if (StorageManager.isFileEncryptedNativeOnly()) {
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07002023 throw new IllegalStateException(
Jeff Sharkey00455bf2016-11-04 14:45:24 -06002024 "Emulation not supported on device with native FBE");
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07002025 }
Jeff Sharkey5a785162016-03-21 13:02:06 -06002026 if (mLockPatternUtils.isCredentialRequiredToDecrypt(false)) {
2027 throw new IllegalStateException(
2028 "Emulation requires disabling 'Secure start-up' in Settings > Security");
2029 }
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07002030
Jeff Sharkey1176e512016-02-29 17:01:26 -07002031 final long token = Binder.clearCallingIdentity();
2032 try {
2033 final boolean emulateFbe = (flags & StorageManager.DEBUG_EMULATE_FBE) != 0;
2034 SystemProperties.set(StorageManager.PROP_EMULATE_FBE, Boolean.toString(emulateFbe));
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07002035
Jeff Sharkey1176e512016-02-29 17:01:26 -07002036 // Perform hard reboot to kick policy into place
2037 mContext.getSystemService(PowerManager.class).reboot(null);
2038 } finally {
2039 Binder.restoreCallingIdentity(token);
2040 }
Jeff Sharkeyba512352015-11-12 20:17:45 -08002041 }
Jeff Sharkey4c099d02015-05-15 13:45:00 -07002042
Jeff Sharkeyba512352015-11-12 20:17:45 -08002043 if ((mask & StorageManager.DEBUG_FORCE_ADOPTABLE) != 0) {
Jeff Sharkey6ed74182016-08-23 13:53:53 -06002044 if (StorageManager.isFileEncryptedNativeOnly()) {
2045 throw new IllegalStateException(
2046 "Adoptable storage not available on device with native FBE");
2047 }
2048
Jeff Sharkeyba512352015-11-12 20:17:45 -08002049 synchronized (mLock) {
2050 mForceAdoptable = (flags & StorageManager.DEBUG_FORCE_ADOPTABLE) != 0;
2051
2052 writeSettingsLocked();
2053 mHandler.obtainMessage(H_RESET).sendToTarget();
2054 }
Jeff Sharkey4c099d02015-05-15 13:45:00 -07002055 }
Jeff Sharkey33dd1562016-04-07 11:05:33 -06002056
2057 if ((mask & (StorageManager.DEBUG_SDCARDFS_FORCE_ON
2058 | StorageManager.DEBUG_SDCARDFS_FORCE_OFF)) != 0) {
2059 final String value;
2060 if ((flags & StorageManager.DEBUG_SDCARDFS_FORCE_ON) != 0) {
2061 value = "force_on";
2062 } else if ((flags & StorageManager.DEBUG_SDCARDFS_FORCE_OFF) != 0) {
2063 value = "force_off";
2064 } else {
2065 value = "";
2066 }
2067
2068 final long token = Binder.clearCallingIdentity();
2069 try {
2070 SystemProperties.set(StorageManager.PROP_SDCARDFS, value);
2071
2072 // Reset storage to kick new setting into place
2073 mHandler.obtainMessage(H_RESET).sendToTarget();
2074 } finally {
2075 Binder.restoreCallingIdentity(token);
2076 }
2077 }
Jeff Sharkey4c099d02015-05-15 13:45:00 -07002078 }
2079
2080 @Override
Jeff Sharkey275e3e42015-04-24 16:10:32 -07002081 public String getPrimaryStorageUuid() {
2082 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
2083 waitForReady();
2084
Jeff Sharkey620b32b2015-04-23 19:36:02 -07002085 synchronized (mLock) {
2086 return mPrimaryStorageUuid;
2087 }
2088 }
2089
2090 @Override
Jeff Sharkey275e3e42015-04-24 16:10:32 -07002091 public void setPrimaryStorageUuid(String volumeUuid, IPackageMoveObserver callback) {
2092 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
2093 waitForReady();
Jeff Sharkey620b32b2015-04-23 19:36:02 -07002094
Jeff Sharkeya31460c2016-06-22 09:04:33 -06002095 final VolumeInfo from;
2096 final VolumeInfo to;
2097
Jeff Sharkey275e3e42015-04-24 16:10:32 -07002098 synchronized (mLock) {
Jeff Sharkeyfced5342015-05-10 14:53:34 -07002099 if (Objects.equals(mPrimaryStorageUuid, volumeUuid)) {
2100 throw new IllegalArgumentException("Primary storage already at " + volumeUuid);
Jeff Sharkey275e3e42015-04-24 16:10:32 -07002101 }
2102
2103 if (mMoveCallback != null) {
2104 throw new IllegalStateException("Move already in progress");
2105 }
2106 mMoveCallback = callback;
2107 mMoveTargetUuid = volumeUuid;
2108
Jeff Sharkeyfced5342015-05-10 14:53:34 -07002109 // When moving to/from primary physical volume, we probably just nuked
2110 // the current storage location, so we have nothing to move.
2111 if (Objects.equals(StorageManager.UUID_PRIMARY_PHYSICAL, mPrimaryStorageUuid)
2112 || Objects.equals(StorageManager.UUID_PRIMARY_PHYSICAL, volumeUuid)) {
2113 Slog.d(TAG, "Skipping move to/from primary physical");
2114 onMoveStatusLocked(MOVE_STATUS_COPY_FINISHED);
2115 onMoveStatusLocked(PackageManager.MOVE_SUCCEEDED);
Jeff Sharkey5a9bb742015-11-03 10:15:57 -08002116 mHandler.obtainMessage(H_RESET).sendToTarget();
Jeff Sharkeya31460c2016-06-22 09:04:33 -06002117 return;
Jeff Sharkeyfced5342015-05-10 14:53:34 -07002118
2119 } else {
Jeff Sharkeya31460c2016-06-22 09:04:33 -06002120 from = findStorageForUuid(mPrimaryStorageUuid);
2121 to = findStorageForUuid(volumeUuid);
Jeff Sharkeyef10ee02015-07-05 14:17:27 -07002122
2123 if (from == null) {
2124 Slog.w(TAG, "Failing move due to missing from volume " + mPrimaryStorageUuid);
2125 onMoveStatusLocked(PackageManager.MOVE_FAILED_INTERNAL_ERROR);
2126 return;
2127 } else if (to == null) {
2128 Slog.w(TAG, "Failing move due to missing to volume " + volumeUuid);
2129 onMoveStatusLocked(PackageManager.MOVE_FAILED_INTERNAL_ERROR);
2130 return;
2131 }
Jeff Sharkey275e3e42015-04-24 16:10:32 -07002132 }
Jeff Sharkey620b32b2015-04-23 19:36:02 -07002133 }
Jeff Sharkeya31460c2016-06-22 09:04:33 -06002134
2135 try {
2136 mConnector.execute("volume", "move_storage", from.id, to.id);
2137 } catch (NativeDaemonConnectorException e) {
2138 throw e.rethrowAsParcelableException();
2139 }
Jeff Sharkey620b32b2015-04-23 19:36:02 -07002140 }
2141
2142 @Override
Mike Lockwoodecedfdc2011-06-08 15:11:59 -07002143 public int[] getStorageUsers(String path) {
Jeff Sharkey48877892015-03-18 11:27:19 -07002144 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
San Mehatc1b4ce92010-02-16 17:13:03 -08002145 waitForReady();
2146 try {
Jeff Sharkeydd519fa2011-12-02 14:11:21 -08002147 final String[] r = NativeDaemonEvent.filterMessageList(
2148 mConnector.executeForList("storage", "users", path),
2149 VoldResponseCode.StorageUsersListResult);
2150
San Mehatc1b4ce92010-02-16 17:13:03 -08002151 // FMT: <pid> <process name>
2152 int[] data = new int[r.length];
2153 for (int i = 0; i < r.length; i++) {
Jeff Sharkeydd519fa2011-12-02 14:11:21 -08002154 String[] tok = r[i].split(" ");
San Mehatc1b4ce92010-02-16 17:13:03 -08002155 try {
2156 data[i] = Integer.parseInt(tok[0]);
2157 } catch (NumberFormatException nfe) {
San Mehata5078592010-03-25 09:36:54 -07002158 Slog.e(TAG, String.format("Error parsing pid %s", tok[0]));
San Mehatc1b4ce92010-02-16 17:13:03 -08002159 return new int[0];
2160 }
2161 }
2162 return data;
2163 } catch (NativeDaemonConnectorException e) {
San Mehata5078592010-03-25 09:36:54 -07002164 Slog.e(TAG, "Failed to retrieve storage users list", e);
San Mehatc1b4ce92010-02-16 17:13:03 -08002165 return new int[0];
2166 }
2167 }
2168
San Mehatb1043402010-02-05 08:26:50 -08002169 private void warnOnNotMounted() {
Jeff Sharkey48877892015-03-18 11:27:19 -07002170 synchronized (mLock) {
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07002171 for (int i = 0; i < mVolumes.size(); i++) {
2172 final VolumeInfo vol = mVolumes.valueAt(i);
Jeff Sharkey27de30d2015-04-18 16:20:27 -07002173 if (vol.isPrimary() && vol.isMountedWritable()) {
Jeff Sharkey48877892015-03-18 11:27:19 -07002174 // Cool beans, we have a mounted primary volume
2175 return;
2176 }
Jeff Sharkey32ee8312012-09-30 13:21:31 -07002177 }
San Mehatb1043402010-02-05 08:26:50 -08002178 }
Jeff Sharkey48877892015-03-18 11:27:19 -07002179
2180 Slog.w(TAG, "No primary storage mounted!");
San Mehatb1043402010-02-05 08:26:50 -08002181 }
2182
San Mehat4270e1e2010-01-29 05:32:19 -08002183 public String[] getSecureContainerList() {
Jeff Sharkey48877892015-03-18 11:27:19 -07002184 enforcePermission(android.Manifest.permission.ASEC_ACCESS);
San Mehat207e5382010-02-04 20:46:54 -08002185 waitForReady();
San Mehatb1043402010-02-05 08:26:50 -08002186 warnOnNotMounted();
San Mehatf919cd022010-02-04 15:10:38 -08002187
San Mehat4270e1e2010-01-29 05:32:19 -08002188 try {
Jeff Sharkeydd519fa2011-12-02 14:11:21 -08002189 return NativeDaemonEvent.filterMessageList(
2190 mConnector.executeForList("asec", "list"), VoldResponseCode.AsecListResult);
San Mehat4270e1e2010-01-29 05:32:19 -08002191 } catch (NativeDaemonConnectorException e) {
2192 return new String[0];
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002193 }
2194 }
San Mehat36972292010-01-06 11:06:32 -08002195
Kenny Root6dceb882012-04-12 14:23:49 -07002196 public int createSecureContainer(String id, int sizeMb, String fstype, String key,
2197 int ownerUid, boolean external) {
Jeff Sharkey48877892015-03-18 11:27:19 -07002198 enforcePermission(android.Manifest.permission.ASEC_CREATE);
San Mehat207e5382010-02-04 20:46:54 -08002199 waitForReady();
San Mehatb1043402010-02-05 08:26:50 -08002200 warnOnNotMounted();
San Mehat4270e1e2010-01-29 05:32:19 -08002201
San Mehatb1043402010-02-05 08:26:50 -08002202 int rc = StorageResultCode.OperationSucceeded;
San Mehat4270e1e2010-01-29 05:32:19 -08002203 try {
Jeff Sharkey56cd6462013-06-07 15:09:15 -07002204 mConnector.execute("asec", "create", id, sizeMb, fstype, new SensitiveArg(key),
2205 ownerUid, external ? "1" : "0");
San Mehat4270e1e2010-01-29 05:32:19 -08002206 } catch (NativeDaemonConnectorException e) {
San Mehatb1043402010-02-05 08:26:50 -08002207 rc = StorageResultCode.OperationFailedInternalError;
San Mehat02735bc2010-01-26 15:18:08 -08002208 }
San Mehata181b212010-02-11 06:50:20 -08002209
2210 if (rc == StorageResultCode.OperationSucceeded) {
2211 synchronized (mAsecMountSet) {
2212 mAsecMountSet.add(id);
2213 }
2214 }
San Mehat4270e1e2010-01-29 05:32:19 -08002215 return rc;
San Mehat36972292010-01-06 11:06:32 -08002216 }
2217
Jeff Sharkey941a8ba2014-08-20 16:26:32 -07002218 @Override
2219 public int resizeSecureContainer(String id, int sizeMb, String key) {
Jeff Sharkey48877892015-03-18 11:27:19 -07002220 enforcePermission(android.Manifest.permission.ASEC_CREATE);
Jeff Sharkey941a8ba2014-08-20 16:26:32 -07002221 waitForReady();
2222 warnOnNotMounted();
2223
2224 int rc = StorageResultCode.OperationSucceeded;
2225 try {
2226 mConnector.execute("asec", "resize", id, sizeMb, new SensitiveArg(key));
2227 } catch (NativeDaemonConnectorException e) {
2228 rc = StorageResultCode.OperationFailedInternalError;
2229 }
2230 return rc;
2231 }
2232
San Mehat4270e1e2010-01-29 05:32:19 -08002233 public int finalizeSecureContainer(String id) {
Jeff Sharkey48877892015-03-18 11:27:19 -07002234 enforcePermission(android.Manifest.permission.ASEC_CREATE);
San Mehatb1043402010-02-05 08:26:50 -08002235 warnOnNotMounted();
San Mehat4270e1e2010-01-29 05:32:19 -08002236
San Mehatb1043402010-02-05 08:26:50 -08002237 int rc = StorageResultCode.OperationSucceeded;
San Mehat4270e1e2010-01-29 05:32:19 -08002238 try {
Jeff Sharkeydd519fa2011-12-02 14:11:21 -08002239 mConnector.execute("asec", "finalize", id);
San Mehata181b212010-02-11 06:50:20 -08002240 /*
2241 * Finalization does a remount, so no need
2242 * to update mAsecMountSet
2243 */
San Mehat4270e1e2010-01-29 05:32:19 -08002244 } catch (NativeDaemonConnectorException e) {
San Mehatb1043402010-02-05 08:26:50 -08002245 rc = StorageResultCode.OperationFailedInternalError;
San Mehat02735bc2010-01-26 15:18:08 -08002246 }
San Mehat4270e1e2010-01-29 05:32:19 -08002247 return rc;
San Mehat36972292010-01-06 11:06:32 -08002248 }
2249
Kenny Root6dceb882012-04-12 14:23:49 -07002250 public int fixPermissionsSecureContainer(String id, int gid, String filename) {
Jeff Sharkey48877892015-03-18 11:27:19 -07002251 enforcePermission(android.Manifest.permission.ASEC_CREATE);
Kenny Root6dceb882012-04-12 14:23:49 -07002252 warnOnNotMounted();
2253
2254 int rc = StorageResultCode.OperationSucceeded;
2255 try {
2256 mConnector.execute("asec", "fixperms", id, gid, filename);
2257 /*
2258 * Fix permissions does a remount, so no need to update
2259 * mAsecMountSet
2260 */
2261 } catch (NativeDaemonConnectorException e) {
2262 rc = StorageResultCode.OperationFailedInternalError;
2263 }
2264 return rc;
2265 }
2266
San Mehatd9709982010-02-18 11:43:03 -08002267 public int destroySecureContainer(String id, boolean force) {
Jeff Sharkey48877892015-03-18 11:27:19 -07002268 enforcePermission(android.Manifest.permission.ASEC_DESTROY);
San Mehat207e5382010-02-04 20:46:54 -08002269 waitForReady();
San Mehatb1043402010-02-05 08:26:50 -08002270 warnOnNotMounted();
San Mehatf919cd022010-02-04 15:10:38 -08002271
Kenny Rootaa485402010-09-14 14:49:41 -07002272 /*
2273 * Force a GC to make sure AssetManagers in other threads of the
2274 * system_server are cleaned up. We have to do this since AssetManager
2275 * instances are kept as a WeakReference and it's possible we have files
2276 * open on the external storage.
2277 */
2278 Runtime.getRuntime().gc();
2279
San Mehatb1043402010-02-05 08:26:50 -08002280 int rc = StorageResultCode.OperationSucceeded;
San Mehat4270e1e2010-01-29 05:32:19 -08002281 try {
Jeff Sharkeydd519fa2011-12-02 14:11:21 -08002282 final Command cmd = new Command("asec", "destroy", id);
2283 if (force) {
2284 cmd.appendArg("force");
2285 }
2286 mConnector.execute(cmd);
San Mehat4270e1e2010-01-29 05:32:19 -08002287 } catch (NativeDaemonConnectorException e) {
San Mehatd9709982010-02-18 11:43:03 -08002288 int code = e.getCode();
2289 if (code == VoldResponseCode.OpFailedStorageBusy) {
2290 rc = StorageResultCode.OperationFailedStorageBusy;
2291 } else {
2292 rc = StorageResultCode.OperationFailedInternalError;
2293 }
San Mehat02735bc2010-01-26 15:18:08 -08002294 }
San Mehata181b212010-02-11 06:50:20 -08002295
2296 if (rc == StorageResultCode.OperationSucceeded) {
2297 synchronized (mAsecMountSet) {
2298 if (mAsecMountSet.contains(id)) {
2299 mAsecMountSet.remove(id);
2300 }
2301 }
2302 }
2303
San Mehat4270e1e2010-01-29 05:32:19 -08002304 return rc;
San Mehat36972292010-01-06 11:06:32 -08002305 }
Jason parks9ed98bc2011-01-17 09:58:35 -06002306
Jeff Sharkey941a8ba2014-08-20 16:26:32 -07002307 public int mountSecureContainer(String id, String key, int ownerUid, boolean readOnly) {
Jeff Sharkey48877892015-03-18 11:27:19 -07002308 enforcePermission(android.Manifest.permission.ASEC_MOUNT_UNMOUNT);
San Mehat207e5382010-02-04 20:46:54 -08002309 waitForReady();
San Mehatb1043402010-02-05 08:26:50 -08002310 warnOnNotMounted();
San Mehat4270e1e2010-01-29 05:32:19 -08002311
San Mehata181b212010-02-11 06:50:20 -08002312 synchronized (mAsecMountSet) {
2313 if (mAsecMountSet.contains(id)) {
2314 return StorageResultCode.OperationFailedStorageMounted;
2315 }
2316 }
2317
San Mehatb1043402010-02-05 08:26:50 -08002318 int rc = StorageResultCode.OperationSucceeded;
San Mehat4270e1e2010-01-29 05:32:19 -08002319 try {
Jeff Sharkey941a8ba2014-08-20 16:26:32 -07002320 mConnector.execute("asec", "mount", id, new SensitiveArg(key), ownerUid,
2321 readOnly ? "ro" : "rw");
San Mehat4270e1e2010-01-29 05:32:19 -08002322 } catch (NativeDaemonConnectorException e) {
Kenny Rootf0304622010-03-19 19:20:42 -07002323 int code = e.getCode();
2324 if (code != VoldResponseCode.OpFailedStorageBusy) {
2325 rc = StorageResultCode.OperationFailedInternalError;
2326 }
San Mehat02735bc2010-01-26 15:18:08 -08002327 }
San Mehat6cdd9c02010-02-09 14:45:20 -08002328
2329 if (rc == StorageResultCode.OperationSucceeded) {
2330 synchronized (mAsecMountSet) {
2331 mAsecMountSet.add(id);
2332 }
2333 }
San Mehat4270e1e2010-01-29 05:32:19 -08002334 return rc;
San Mehat36972292010-01-06 11:06:32 -08002335 }
2336
San Mehatd9709982010-02-18 11:43:03 -08002337 public int unmountSecureContainer(String id, boolean force) {
Jeff Sharkey48877892015-03-18 11:27:19 -07002338 enforcePermission(android.Manifest.permission.ASEC_MOUNT_UNMOUNT);
San Mehat207e5382010-02-04 20:46:54 -08002339 waitForReady();
San Mehatb1043402010-02-05 08:26:50 -08002340 warnOnNotMounted();
San Mehat4270e1e2010-01-29 05:32:19 -08002341
San Mehat6cdd9c02010-02-09 14:45:20 -08002342 synchronized (mAsecMountSet) {
2343 if (!mAsecMountSet.contains(id)) {
San Mehata181b212010-02-11 06:50:20 -08002344 return StorageResultCode.OperationFailedStorageNotMounted;
San Mehat6cdd9c02010-02-09 14:45:20 -08002345 }
2346 }
2347
Kenny Rootaa485402010-09-14 14:49:41 -07002348 /*
2349 * Force a GC to make sure AssetManagers in other threads of the
2350 * system_server are cleaned up. We have to do this since AssetManager
2351 * instances are kept as a WeakReference and it's possible we have files
2352 * open on the external storage.
2353 */
2354 Runtime.getRuntime().gc();
2355
San Mehatb1043402010-02-05 08:26:50 -08002356 int rc = StorageResultCode.OperationSucceeded;
San Mehat4270e1e2010-01-29 05:32:19 -08002357 try {
Jeff Sharkeydd519fa2011-12-02 14:11:21 -08002358 final Command cmd = new Command("asec", "unmount", id);
2359 if (force) {
2360 cmd.appendArg("force");
2361 }
2362 mConnector.execute(cmd);
San Mehat4270e1e2010-01-29 05:32:19 -08002363 } catch (NativeDaemonConnectorException e) {
San Mehatd9709982010-02-18 11:43:03 -08002364 int code = e.getCode();
2365 if (code == VoldResponseCode.OpFailedStorageBusy) {
2366 rc = StorageResultCode.OperationFailedStorageBusy;
2367 } else {
2368 rc = StorageResultCode.OperationFailedInternalError;
2369 }
San Mehat02735bc2010-01-26 15:18:08 -08002370 }
San Mehat6cdd9c02010-02-09 14:45:20 -08002371
2372 if (rc == StorageResultCode.OperationSucceeded) {
2373 synchronized (mAsecMountSet) {
2374 mAsecMountSet.remove(id);
2375 }
2376 }
San Mehat4270e1e2010-01-29 05:32:19 -08002377 return rc;
San Mehat9dba7092010-01-18 06:47:41 -08002378 }
2379
San Mehat6cdd9c02010-02-09 14:45:20 -08002380 public boolean isSecureContainerMounted(String id) {
Jeff Sharkey48877892015-03-18 11:27:19 -07002381 enforcePermission(android.Manifest.permission.ASEC_ACCESS);
San Mehat6cdd9c02010-02-09 14:45:20 -08002382 waitForReady();
2383 warnOnNotMounted();
2384
2385 synchronized (mAsecMountSet) {
2386 return mAsecMountSet.contains(id);
2387 }
2388 }
2389
San Mehat4270e1e2010-01-29 05:32:19 -08002390 public int renameSecureContainer(String oldId, String newId) {
Jeff Sharkey48877892015-03-18 11:27:19 -07002391 enforcePermission(android.Manifest.permission.ASEC_RENAME);
San Mehat207e5382010-02-04 20:46:54 -08002392 waitForReady();
San Mehatb1043402010-02-05 08:26:50 -08002393 warnOnNotMounted();
San Mehat4270e1e2010-01-29 05:32:19 -08002394
San Mehata181b212010-02-11 06:50:20 -08002395 synchronized (mAsecMountSet) {
San Mehat85451ee2010-02-24 08:54:18 -08002396 /*
Jason parks9ed98bc2011-01-17 09:58:35 -06002397 * Because a mounted container has active internal state which cannot be
San Mehat85451ee2010-02-24 08:54:18 -08002398 * changed while active, we must ensure both ids are not currently mounted.
2399 */
2400 if (mAsecMountSet.contains(oldId) || mAsecMountSet.contains(newId)) {
San Mehata181b212010-02-11 06:50:20 -08002401 return StorageResultCode.OperationFailedStorageMounted;
2402 }
2403 }
2404
San Mehatb1043402010-02-05 08:26:50 -08002405 int rc = StorageResultCode.OperationSucceeded;
San Mehat4270e1e2010-01-29 05:32:19 -08002406 try {
Jeff Sharkeydd519fa2011-12-02 14:11:21 -08002407 mConnector.execute("asec", "rename", oldId, newId);
San Mehat4270e1e2010-01-29 05:32:19 -08002408 } catch (NativeDaemonConnectorException e) {
San Mehatb1043402010-02-05 08:26:50 -08002409 rc = StorageResultCode.OperationFailedInternalError;
San Mehat02735bc2010-01-26 15:18:08 -08002410 }
San Mehata181b212010-02-11 06:50:20 -08002411
San Mehat4270e1e2010-01-29 05:32:19 -08002412 return rc;
San Mehat45f61042010-01-23 08:12:43 -08002413 }
2414
San Mehat4270e1e2010-01-29 05:32:19 -08002415 public String getSecureContainerPath(String id) {
Jeff Sharkey48877892015-03-18 11:27:19 -07002416 enforcePermission(android.Manifest.permission.ASEC_ACCESS);
San Mehat207e5382010-02-04 20:46:54 -08002417 waitForReady();
San Mehatb1043402010-02-05 08:26:50 -08002418 warnOnNotMounted();
San Mehatf919cd022010-02-04 15:10:38 -08002419
Jeff Sharkeydd519fa2011-12-02 14:11:21 -08002420 final NativeDaemonEvent event;
San Mehat2d66cef2010-03-23 11:12:52 -07002421 try {
Jeff Sharkeydd519fa2011-12-02 14:11:21 -08002422 event = mConnector.execute("asec", "path", id);
2423 event.checkCode(VoldResponseCode.AsecPathResult);
2424 return event.getMessage();
San Mehat2d66cef2010-03-23 11:12:52 -07002425 } catch (NativeDaemonConnectorException e) {
2426 int code = e.getCode();
2427 if (code == VoldResponseCode.OpFailedStorageNotFound) {
Fredrik Helmera20c8ef2011-02-09 16:16:10 +01002428 Slog.i(TAG, String.format("Container '%s' not found", id));
2429 return null;
San Mehat22dd86e2010-01-12 12:21:18 -08002430 } else {
San Mehat2d66cef2010-03-23 11:12:52 -07002431 throw new IllegalStateException(String.format("Unexpected response code %d", code));
San Mehat22dd86e2010-01-12 12:21:18 -08002432 }
2433 }
San Mehat22dd86e2010-01-12 12:21:18 -08002434 }
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07002435
Dianne Hackborn292f8bc2011-06-27 16:27:41 -07002436 public String getSecureContainerFilesystemPath(String id) {
Jeff Sharkey48877892015-03-18 11:27:19 -07002437 enforcePermission(android.Manifest.permission.ASEC_ACCESS);
Dianne Hackborn292f8bc2011-06-27 16:27:41 -07002438 waitForReady();
2439 warnOnNotMounted();
2440
Jeff Sharkeydd519fa2011-12-02 14:11:21 -08002441 final NativeDaemonEvent event;
Dianne Hackborn292f8bc2011-06-27 16:27:41 -07002442 try {
Jeff Sharkeydd519fa2011-12-02 14:11:21 -08002443 event = mConnector.execute("asec", "fspath", id);
2444 event.checkCode(VoldResponseCode.AsecPathResult);
2445 return event.getMessage();
Dianne Hackborn292f8bc2011-06-27 16:27:41 -07002446 } catch (NativeDaemonConnectorException e) {
2447 int code = e.getCode();
2448 if (code == VoldResponseCode.OpFailedStorageNotFound) {
2449 Slog.i(TAG, String.format("Container '%s' not found", id));
2450 return null;
2451 } else {
2452 throw new IllegalStateException(String.format("Unexpected response code %d", code));
2453 }
2454 }
2455 }
2456
Jeff Sharkey48877892015-03-18 11:27:19 -07002457 @Override
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07002458 public void finishMediaUpdate() {
Jeff Sharkey9527b222015-06-24 15:24:48 -07002459 if (Binder.getCallingUid() != Process.SYSTEM_UID) {
Rubin Xucd7a0142015-04-17 23:45:27 +01002460 throw new SecurityException("no permission to call finishMediaUpdate()");
2461 }
Jeff Sharkey48877892015-03-18 11:27:19 -07002462 if (mUnmountSignal != null) {
2463 mUnmountSignal.countDown();
2464 } else {
2465 Slog.w(TAG, "Odd, nobody asked to unmount?");
2466 }
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07002467 }
Kenny Root02c87302010-07-01 08:10:18 -07002468
Kenny Roota02b8b02010-08-05 16:14:17 -07002469 private boolean isUidOwnerOfPackageOrSystem(String packageName, int callerUid) {
2470 if (callerUid == android.os.Process.SYSTEM_UID) {
2471 return true;
2472 }
2473
Kenny Root02c87302010-07-01 08:10:18 -07002474 if (packageName == null) {
2475 return false;
2476 }
2477
Jeff Sharkeycd654482016-01-08 17:42:11 -07002478 final int packageUid = mPms.getPackageUid(packageName,
2479 PackageManager.MATCH_DEBUG_TRIAGED_MISSING, UserHandle.getUserId(callerUid));
Kenny Root02c87302010-07-01 08:10:18 -07002480
2481 if (DEBUG_OBB) {
2482 Slog.d(TAG, "packageName = " + packageName + ", packageUid = " +
2483 packageUid + ", callerUid = " + callerUid);
2484 }
2485
2486 return callerUid == packageUid;
2487 }
2488
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002489 public String getMountedObbPath(String rawPath) {
2490 Preconditions.checkNotNull(rawPath, "rawPath cannot be null");
Kenny Rootaf9d6672010-10-08 09:21:39 -07002491
Kenny Root02c87302010-07-01 08:10:18 -07002492 waitForReady();
2493 warnOnNotMounted();
2494
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002495 final ObbState state;
Rubin Xucd7a0142015-04-17 23:45:27 +01002496 synchronized (mObbMounts) {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002497 state = mObbPathToStateMap.get(rawPath);
2498 }
2499 if (state == null) {
2500 Slog.w(TAG, "Failed to find OBB mounted at " + rawPath);
2501 return null;
2502 }
2503
Jeff Sharkeydd519fa2011-12-02 14:11:21 -08002504 final NativeDaemonEvent event;
Kenny Root02c87302010-07-01 08:10:18 -07002505 try {
Xiaohui Chen621b3fc2015-10-02 14:41:42 -07002506 event = mConnector.execute("obb", "path", state.canonicalPath);
Jeff Sharkeydd519fa2011-12-02 14:11:21 -08002507 event.checkCode(VoldResponseCode.AsecPathResult);
2508 return event.getMessage();
Kenny Root02c87302010-07-01 08:10:18 -07002509 } catch (NativeDaemonConnectorException e) {
2510 int code = e.getCode();
2511 if (code == VoldResponseCode.OpFailedStorageNotFound) {
Kenny Roota02b8b02010-08-05 16:14:17 -07002512 return null;
Kenny Root02c87302010-07-01 08:10:18 -07002513 } else {
2514 throw new IllegalStateException(String.format("Unexpected response code %d", code));
2515 }
2516 }
2517 }
2518
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002519 @Override
2520 public boolean isObbMounted(String rawPath) {
2521 Preconditions.checkNotNull(rawPath, "rawPath cannot be null");
Kenny Rootaf9d6672010-10-08 09:21:39 -07002522 synchronized (mObbMounts) {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002523 return mObbPathToStateMap.containsKey(rawPath);
Kenny Rootaf9d6672010-10-08 09:21:39 -07002524 }
Kenny Root02c87302010-07-01 08:10:18 -07002525 }
2526
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002527 @Override
2528 public void mountObb(
2529 String rawPath, String canonicalPath, String key, IObbActionListener token, int nonce) {
2530 Preconditions.checkNotNull(rawPath, "rawPath cannot be null");
2531 Preconditions.checkNotNull(canonicalPath, "canonicalPath cannot be null");
2532 Preconditions.checkNotNull(token, "token cannot be null");
Kenny Rootaf9d6672010-10-08 09:21:39 -07002533
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002534 final int callingUid = Binder.getCallingUid();
2535 final ObbState obbState = new ObbState(rawPath, canonicalPath, callingUid, token, nonce);
2536 final ObbAction action = new MountObbAction(obbState, key, callingUid);
Kenny Roota02b8b02010-08-05 16:14:17 -07002537 mObbActionHandler.sendMessage(mObbActionHandler.obtainMessage(OBB_RUN_ACTION, action));
2538
2539 if (DEBUG_OBB)
2540 Slog.i(TAG, "Send to OBB handler: " + action.toString());
Kenny Root02c87302010-07-01 08:10:18 -07002541 }
2542
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002543 @Override
2544 public void unmountObb(String rawPath, boolean force, IObbActionListener token, int nonce) {
2545 Preconditions.checkNotNull(rawPath, "rawPath cannot be null");
2546
2547 final ObbState existingState;
Rubin Xucd7a0142015-04-17 23:45:27 +01002548 synchronized (mObbMounts) {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002549 existingState = mObbPathToStateMap.get(rawPath);
Kenny Rootf1121dc2010-09-29 07:30:53 -07002550 }
2551
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002552 if (existingState != null) {
2553 // TODO: separate state object from request data
2554 final int callingUid = Binder.getCallingUid();
2555 final ObbState newState = new ObbState(
2556 rawPath, existingState.canonicalPath, callingUid, token, nonce);
2557 final ObbAction action = new UnmountObbAction(newState, force);
2558 mObbActionHandler.sendMessage(mObbActionHandler.obtainMessage(OBB_RUN_ACTION, action));
Kenny Root02c87302010-07-01 08:10:18 -07002559
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07002560 if (DEBUG_OBB)
2561 Slog.i(TAG, "Send to OBB handler: " + action.toString());
2562 } else {
2563 Slog.w(TAG, "Unknown OBB mount at " + rawPath);
2564 }
Kenny Roota02b8b02010-08-05 16:14:17 -07002565 }
2566
Ben Komalo444eca22011-09-01 15:17:44 -07002567 @Override
2568 public int getEncryptionState() {
2569 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
2570 "no permission to access the crypt keeper");
2571
2572 waitForReady();
2573
Jeff Sharkeydd519fa2011-12-02 14:11:21 -08002574 final NativeDaemonEvent event;
Ben Komalo444eca22011-09-01 15:17:44 -07002575 try {
Paul Lawrence1c62cbb2015-06-03 14:14:52 -07002576 event = mCryptConnector.execute("cryptfs", "cryptocomplete");
Jeff Sharkeydd519fa2011-12-02 14:11:21 -08002577 return Integer.parseInt(event.getMessage());
Ben Komalo444eca22011-09-01 15:17:44 -07002578 } catch (NumberFormatException e) {
2579 // Bad result - unexpected.
2580 Slog.w(TAG, "Unable to parse result from cryptfs cryptocomplete");
Sudheer Shankaf7341142016-10-18 17:15:18 -07002581 return StorageManager.ENCRYPTION_STATE_ERROR_UNKNOWN;
Ben Komalo444eca22011-09-01 15:17:44 -07002582 } catch (NativeDaemonConnectorException e) {
2583 // Something bad happened.
2584 Slog.w(TAG, "Error in communicating with cryptfs in validating");
Sudheer Shankaf7341142016-10-18 17:15:18 -07002585 return StorageManager.ENCRYPTION_STATE_ERROR_UNKNOWN;
Ben Komalo444eca22011-09-01 15:17:44 -07002586 }
2587 }
2588
2589 @Override
Jason parks5af0b912010-11-29 09:05:25 -06002590 public int decryptStorage(String password) {
Jason parksf7b3cd42011-01-27 09:28:25 -06002591 if (TextUtils.isEmpty(password)) {
2592 throw new IllegalArgumentException("password cannot be empty");
Jason parks5af0b912010-11-29 09:05:25 -06002593 }
2594
Jason parks8888c592011-01-20 22:46:41 -06002595 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
2596 "no permission to access the crypt keeper");
Jason parks5af0b912010-11-29 09:05:25 -06002597
2598 waitForReady();
2599
2600 if (DEBUG_EVENTS) {
2601 Slog.i(TAG, "decrypting storage...");
2602 }
2603
Jeff Sharkeydd519fa2011-12-02 14:11:21 -08002604 final NativeDaemonEvent event;
Jason parks5af0b912010-11-29 09:05:25 -06002605 try {
Paul Lawrence05487612015-06-09 13:35:38 -07002606 event = mCryptConnector.execute("cryptfs", "checkpw", new SensitiveArg(password));
Jason parks9ed98bc2011-01-17 09:58:35 -06002607
Fredrik Roubertda6aedf2011-12-20 17:34:43 +01002608 final int code = Integer.parseInt(event.getMessage());
Jason parks9ed98bc2011-01-17 09:58:35 -06002609 if (code == 0) {
2610 // Decrypt was successful. Post a delayed message before restarting in order
2611 // to let the UI to clear itself
2612 mHandler.postDelayed(new Runnable() {
2613 public void run() {
Jeff Sharkey31c6e482011-11-18 17:09:01 -08002614 try {
Paul Lawrence1c62cbb2015-06-03 14:14:52 -07002615 mCryptConnector.execute("cryptfs", "restart");
Jeff Sharkey31c6e482011-11-18 17:09:01 -08002616 } catch (NativeDaemonConnectorException e) {
2617 Slog.e(TAG, "problem executing in background", e);
2618 }
Jason parks9ed98bc2011-01-17 09:58:35 -06002619 }
Jason parksf7b3cd42011-01-27 09:28:25 -06002620 }, 1000); // 1 second
Jason parks9ed98bc2011-01-17 09:58:35 -06002621 }
2622
2623 return code;
Jason parks5af0b912010-11-29 09:05:25 -06002624 } catch (NativeDaemonConnectorException e) {
2625 // Decryption failed
2626 return e.getCode();
2627 }
Jason parks5af0b912010-11-29 09:05:25 -06002628 }
2629
Paul Lawrence46791e72014-04-03 09:10:26 -07002630 public int encryptStorage(int type, String password) {
2631 if (TextUtils.isEmpty(password) && type != StorageManager.CRYPT_TYPE_DEFAULT) {
Jason parksf7b3cd42011-01-27 09:28:25 -06002632 throw new IllegalArgumentException("password cannot be empty");
Jason parks56aa5322011-01-07 09:01:15 -06002633 }
2634
Jason parks8888c592011-01-20 22:46:41 -06002635 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
2636 "no permission to access the crypt keeper");
Jason parks56aa5322011-01-07 09:01:15 -06002637
2638 waitForReady();
2639
2640 if (DEBUG_EVENTS) {
Jason parks8888c592011-01-20 22:46:41 -06002641 Slog.i(TAG, "encrypting storage...");
Jason parks56aa5322011-01-07 09:01:15 -06002642 }
2643
2644 try {
Paul Lawrence5096d9e2015-09-09 13:05:45 -07002645 if (type == StorageManager.CRYPT_TYPE_DEFAULT) {
2646 mCryptConnector.execute("cryptfs", "enablecrypto", "inplace",
2647 CRYPTO_TYPES[type]);
2648 } else {
2649 mCryptConnector.execute("cryptfs", "enablecrypto", "inplace",
2650 CRYPTO_TYPES[type], new SensitiveArg(password));
2651 }
Jason parks56aa5322011-01-07 09:01:15 -06002652 } catch (NativeDaemonConnectorException e) {
2653 // Encryption failed
2654 return e.getCode();
2655 }
2656
2657 return 0;
2658 }
2659
Paul Lawrence8e397362014-01-27 15:22:30 -08002660 /** Set the password for encrypting the master key.
2661 * @param type One of the CRYPTO_TYPE_XXX consts defined in StorageManager.
2662 * @param password The password to set.
2663 */
2664 public int changeEncryptionPassword(int type, String password) {
Jason parksf7b3cd42011-01-27 09:28:25 -06002665 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
2666 "no permission to access the crypt keeper");
2667
2668 waitForReady();
2669
2670 if (DEBUG_EVENTS) {
2671 Slog.i(TAG, "changing encryption password...");
2672 }
2673
2674 try {
Paul Lawrence1c62cbb2015-06-03 14:14:52 -07002675 NativeDaemonEvent event = mCryptConnector.execute("cryptfs", "changepw", CRYPTO_TYPES[type],
Paul Lawrence05487612015-06-09 13:35:38 -07002676 new SensitiveArg(password));
Jeff Sharkeydd519fa2011-12-02 14:11:21 -08002677 return Integer.parseInt(event.getMessage());
Jason parksf7b3cd42011-01-27 09:28:25 -06002678 } catch (NativeDaemonConnectorException e) {
2679 // Encryption failed
2680 return e.getCode();
2681 }
2682 }
2683
Christopher Tate32418be2011-10-10 13:51:12 -07002684 /**
2685 * Validate a user-supplied password string with cryptfs
2686 */
2687 @Override
2688 public int verifyEncryptionPassword(String password) throws RemoteException {
2689 // Only the system process is permitted to validate passwords
2690 if (Binder.getCallingUid() != android.os.Process.SYSTEM_UID) {
2691 throw new SecurityException("no permission to access the crypt keeper");
2692 }
2693
2694 mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
2695 "no permission to access the crypt keeper");
2696
2697 if (TextUtils.isEmpty(password)) {
2698 throw new IllegalArgumentException("password cannot be empty");
2699 }
2700
2701 waitForReady();
2702
2703 if (DEBUG_EVENTS) {
2704 Slog.i(TAG, "validating encryption password...");
2705 }
2706
Jeff Sharkeydd519fa2011-12-02 14:11:21 -08002707 final NativeDaemonEvent event;
Christopher Tate32418be2011-10-10 13:51:12 -07002708 try {
Paul Lawrence05487612015-06-09 13:35:38 -07002709 event = mCryptConnector.execute("cryptfs", "verifypw", new SensitiveArg(password));
Jeff Sharkeydd519fa2011-12-02 14:11:21 -08002710 Slog.i(TAG, "cryptfs verifypw => " + event.getMessage());
2711 return Integer.parseInt(event.getMessage());
Christopher Tate32418be2011-10-10 13:51:12 -07002712 } catch (NativeDaemonConnectorException e) {
2713 // Encryption failed
2714 return e.getCode();
2715 }
2716 }
2717
Paul Lawrence8e397362014-01-27 15:22:30 -08002718 /**
2719 * Get the type of encryption used to encrypt the master key.
2720 * @return The type, one of the CRYPT_TYPE_XXX consts from StorageManager.
2721 */
2722 @Override
Svetoslav16e4a1a2014-09-29 18:16:20 -07002723 public int getPasswordType() {
Paul Lawrence9de713d2016-05-02 22:45:33 +00002724 mContext.enforceCallingOrSelfPermission(Manifest.permission.STORAGE_INTERNAL,
2725 "no permission to access the crypt keeper");
2726
Paul Lawrence8e397362014-01-27 15:22:30 -08002727 waitForReady();
2728
2729 final NativeDaemonEvent event;
2730 try {
Paul Lawrence1c62cbb2015-06-03 14:14:52 -07002731 event = mCryptConnector.execute("cryptfs", "getpwtype");
Paul Lawrence8e397362014-01-27 15:22:30 -08002732 for (int i = 0; i < CRYPTO_TYPES.length; ++i) {
2733 if (CRYPTO_TYPES[i].equals(event.getMessage()))
2734 return i;
2735 }
2736
2737 throw new IllegalStateException("unexpected return from cryptfs");
2738 } catch (NativeDaemonConnectorException e) {
2739 throw e.rethrowAsParcelableException();
2740 }
2741 }
2742
Paul Lawrencee51dcf92014-03-18 10:56:00 -07002743 /**
2744 * Set a field in the crypto header.
2745 * @param field field to set
2746 * @param contents contents to set in field
2747 */
2748 @Override
2749 public void setField(String field, String contents) throws RemoteException {
Paul Lawrence0bbd1082016-04-26 15:21:02 -07002750 mContext.enforceCallingOrSelfPermission(Manifest.permission.STORAGE_INTERNAL,
2751 "no permission to access the crypt keeper");
Paul Lawrencee51dcf92014-03-18 10:56:00 -07002752
2753 waitForReady();
2754
2755 final NativeDaemonEvent event;
2756 try {
Paul Lawrence1c62cbb2015-06-03 14:14:52 -07002757 event = mCryptConnector.execute("cryptfs", "setfield", field, contents);
Paul Lawrencee51dcf92014-03-18 10:56:00 -07002758 } catch (NativeDaemonConnectorException e) {
2759 throw e.rethrowAsParcelableException();
2760 }
2761 }
2762
2763 /**
2764 * Gets a field from the crypto header.
2765 * @param field field to get
2766 * @return contents of field
2767 */
2768 @Override
2769 public String getField(String field) throws RemoteException {
Paul Lawrence0bbd1082016-04-26 15:21:02 -07002770 mContext.enforceCallingOrSelfPermission(Manifest.permission.STORAGE_INTERNAL,
2771 "no permission to access the crypt keeper");
Paul Lawrencee51dcf92014-03-18 10:56:00 -07002772
2773 waitForReady();
2774
2775 final NativeDaemonEvent event;
2776 try {
2777 final String[] contents = NativeDaemonEvent.filterMessageList(
Paul Lawrence1c62cbb2015-06-03 14:14:52 -07002778 mCryptConnector.executeForList("cryptfs", "getfield", field),
Paul Lawrencee51dcf92014-03-18 10:56:00 -07002779 VoldResponseCode.CryptfsGetfieldResult);
2780 String result = new String();
2781 for (String content : contents) {
2782 result += content;
2783 }
2784 return result;
2785 } catch (NativeDaemonConnectorException e) {
2786 throw e.rethrowAsParcelableException();
2787 }
2788 }
2789
Paul Lawrence3806d9c2015-10-29 10:30:46 -07002790 /**
2791 * Is userdata convertible to file based encryption?
2792 * @return non zero for convertible
2793 */
2794 @Override
2795 public boolean isConvertibleToFBE() throws RemoteException {
Paul Lawrence0bbd1082016-04-26 15:21:02 -07002796 mContext.enforceCallingOrSelfPermission(Manifest.permission.STORAGE_INTERNAL,
2797 "no permission to access the crypt keeper");
Paul Lawrence3806d9c2015-10-29 10:30:46 -07002798
2799 waitForReady();
2800
2801 final NativeDaemonEvent event;
2802 try {
2803 event = mCryptConnector.execute("cryptfs", "isConvertibleToFBE");
2804 return Integer.parseInt(event.getMessage()) != 0;
2805 } catch (NativeDaemonConnectorException e) {
2806 throw e.rethrowAsParcelableException();
2807 }
2808 }
2809
Jeff Sharkeyb049e212012-09-07 23:16:01 -07002810 @Override
Paul Lawrence945490c2014-03-27 16:37:28 +00002811 public String getPassword() throws RemoteException {
Paul Lawrence0bbd1082016-04-26 15:21:02 -07002812 mContext.enforceCallingOrSelfPermission(Manifest.permission.STORAGE_INTERNAL,
Rubin Xucd7a0142015-04-17 23:45:27 +01002813 "only keyguard can retrieve password");
Paul Lawrence0bbd1082016-04-26 15:21:02 -07002814
Paul Lawrence945490c2014-03-27 16:37:28 +00002815 if (!isReady()) {
2816 return new String();
2817 }
2818
2819 final NativeDaemonEvent event;
2820 try {
Paul Lawrence1c62cbb2015-06-03 14:14:52 -07002821 event = mCryptConnector.execute("cryptfs", "getpw");
Paul Lawrence24063b52015-01-06 13:11:23 -08002822 if ("-1".equals(event.getMessage())) {
2823 // -1 equals no password
2824 return null;
2825 }
Paul Lawrence05487612015-06-09 13:35:38 -07002826 return event.getMessage();
Paul Lawrence945490c2014-03-27 16:37:28 +00002827 } catch (NativeDaemonConnectorException e) {
2828 throw e.rethrowAsParcelableException();
Paul Lawrence24063b52015-01-06 13:11:23 -08002829 } catch (IllegalArgumentException e) {
2830 Slog.e(TAG, "Invalid response to getPassword");
2831 return null;
Paul Lawrence945490c2014-03-27 16:37:28 +00002832 }
2833 }
2834
2835 @Override
2836 public void clearPassword() throws RemoteException {
Paul Lawrence0bbd1082016-04-26 15:21:02 -07002837 mContext.enforceCallingOrSelfPermission(Manifest.permission.STORAGE_INTERNAL,
2838 "only keyguard can clear password");
2839
Paul Lawrence945490c2014-03-27 16:37:28 +00002840 if (!isReady()) {
2841 return;
2842 }
2843
2844 final NativeDaemonEvent event;
2845 try {
Paul Lawrence1c62cbb2015-06-03 14:14:52 -07002846 event = mCryptConnector.execute("cryptfs", "clearpw");
Paul Lawrence945490c2014-03-27 16:37:28 +00002847 } catch (NativeDaemonConnectorException e) {
2848 throw e.rethrowAsParcelableException();
2849 }
2850 }
2851
2852 @Override
Lenka Trochtovac4dd0212015-11-18 12:22:06 +01002853 public void createUserKey(int userId, int serialNumber, boolean ephemeral) {
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002854 enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
Paul Crowleybcf48ed2015-04-22 13:36:59 +01002855 waitForReady();
2856
Paul Crowleybcf48ed2015-04-22 13:36:59 +01002857 try {
Lenka Trochtovac4dd0212015-11-18 12:22:06 +01002858 mCryptConnector.execute("cryptfs", "create_user_key", userId, serialNumber,
2859 ephemeral ? 1 : 0);
Paul Crowleybcf48ed2015-04-22 13:36:59 +01002860 } catch (NativeDaemonConnectorException e) {
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002861 throw e.rethrowAsParcelableException();
Paul Crowleybcf48ed2015-04-22 13:36:59 +01002862 }
2863 }
2864
Paul Crowley7ec733f2015-05-19 12:42:00 +01002865 @Override
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002866 public void destroyUserKey(int userId) {
2867 enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
Paul Crowley7ec733f2015-05-19 12:42:00 +01002868 waitForReady();
2869
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002870 try {
2871 mCryptConnector.execute("cryptfs", "destroy_user_key", userId);
2872 } catch (NativeDaemonConnectorException e) {
2873 throw e.rethrowAsParcelableException();
2874 }
2875 }
2876
Paul Crowleyfaeb3eb2016-02-08 15:58:29 +00002877 private SensitiveArg encodeBytes(byte[] bytes) {
2878 if (ArrayUtils.isEmpty(bytes)) {
2879 return new SensitiveArg("!");
2880 } else {
2881 return new SensitiveArg(HexDump.toHexString(bytes));
2882 }
2883 }
2884
Paul Crowleycc701552016-05-17 14:18:49 -07002885 /*
2886 * Add this token/secret pair to the set of ways we can recover a disk encryption key.
2887 * Changing the token/secret for a disk encryption key is done in two phases: first, adding
2888 * a new token/secret pair with this call, then delting all other pairs with
2889 * fixateNewestUserKeyAuth. This allows other places where a credential is used, such as
2890 * Gatekeeper, to be updated between the two calls.
2891 */
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002892 @Override
Paul Crowleycc701552016-05-17 14:18:49 -07002893 public void addUserKeyAuth(int userId, int serialNumber, byte[] token, byte[] secret) {
Paul Crowleyfaeb3eb2016-02-08 15:58:29 +00002894 enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
2895 waitForReady();
2896
2897 try {
Paul Crowleycc701552016-05-17 14:18:49 -07002898 mCryptConnector.execute("cryptfs", "add_user_key_auth", userId, serialNumber,
2899 encodeBytes(token), encodeBytes(secret));
2900 } catch (NativeDaemonConnectorException e) {
2901 throw e.rethrowAsParcelableException();
2902 }
2903 }
2904
2905 /*
2906 * Delete all disk encryption token/secret pairs except the most recently added one
2907 */
2908 @Override
2909 public void fixateNewestUserKeyAuth(int userId) {
2910 enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
2911 waitForReady();
2912
2913 try {
2914 mCryptConnector.execute("cryptfs", "fixate_newest_user_key_auth", userId);
Paul Crowleyfaeb3eb2016-02-08 15:58:29 +00002915 } catch (NativeDaemonConnectorException e) {
2916 throw e.rethrowAsParcelableException();
2917 }
2918 }
2919
2920 @Override
2921 public void unlockUserKey(int userId, int serialNumber, byte[] token, byte[] secret) {
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002922 enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
2923 waitForReady();
2924
Jeff Sharkeyce18c812016-04-27 16:00:41 -06002925 if (StorageManager.isFileEncryptedNativeOrEmulated()) {
2926 // When a user has secure lock screen, require a challenge token to
2927 // actually unlock. This check is mostly in place for emulation mode.
2928 if (mLockPatternUtils.isSecure(userId) && ArrayUtils.isEmpty(token)) {
2929 throw new IllegalStateException("Token required to unlock secure user " + userId);
2930 }
Jeff Sharkeyb9fe5372015-12-03 15:23:08 -07002931
Jeff Sharkeyce18c812016-04-27 16:00:41 -06002932 try {
2933 mCryptConnector.execute("cryptfs", "unlock_user_key", userId, serialNumber,
2934 encodeBytes(token), encodeBytes(secret));
2935 } catch (NativeDaemonConnectorException e) {
2936 throw e.rethrowAsParcelableException();
2937 }
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002938 }
2939
2940 synchronized (mLock) {
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07002941 mLocalUnlockedUsers = ArrayUtils.appendInt(mLocalUnlockedUsers, userId);
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002942 }
2943 }
2944
2945 @Override
2946 public void lockUserKey(int userId) {
2947 enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
2948 waitForReady();
2949
2950 try {
2951 mCryptConnector.execute("cryptfs", "lock_user_key", userId);
2952 } catch (NativeDaemonConnectorException e) {
2953 throw e.rethrowAsParcelableException();
2954 }
2955
2956 synchronized (mLock) {
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07002957 mLocalUnlockedUsers = ArrayUtils.removeInt(mLocalUnlockedUsers, userId);
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002958 }
2959 }
2960
2961 @Override
2962 public boolean isUserKeyUnlocked(int userId) {
Jeff Sharkeyce18c812016-04-27 16:00:41 -06002963 synchronized (mLock) {
2964 return ArrayUtils.contains(mLocalUnlockedUsers, userId);
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002965 }
2966 }
2967
2968 @Override
Jeff Sharkey47f71082016-02-01 17:03:54 -07002969 public void prepareUserStorage(String volumeUuid, int userId, int serialNumber, int flags) {
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002970 enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
2971 waitForReady();
2972
2973 try {
2974 mCryptConnector.execute("cryptfs", "prepare_user_storage", escapeNull(volumeUuid),
Jeff Sharkey47f71082016-02-01 17:03:54 -07002975 userId, serialNumber, flags);
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002976 } catch (NativeDaemonConnectorException e) {
2977 throw e.rethrowAsParcelableException();
Paul Crowley7ec733f2015-05-19 12:42:00 +01002978 }
2979 }
2980
Paul Crowleybcf48ed2015-04-22 13:36:59 +01002981 @Override
Jeff Sharkeyfcf1e552016-04-14 20:44:58 -06002982 public void destroyUserStorage(String volumeUuid, int userId, int flags) {
2983 enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
2984 waitForReady();
2985
2986 try {
2987 mCryptConnector.execute("cryptfs", "destroy_user_storage", escapeNull(volumeUuid),
2988 userId, flags);
2989 } catch (NativeDaemonConnectorException e) {
2990 throw e.rethrowAsParcelableException();
2991 }
2992 }
2993
Daichi Hirono9fb00182016-11-08 14:12:17 +09002994 class CloseableHolder<T extends AutoCloseable> implements AutoCloseable {
2995 @Nullable T mCloseable;
2996
2997 CloseableHolder(T closeable) {
2998 mCloseable = closeable;
2999 }
3000
3001 @Nullable T get() {
3002 return mCloseable;
3003 }
3004
3005 @Nullable T release() {
3006 final T result = mCloseable;
3007 mCloseable = null;
3008 return result;
3009 }
3010
3011 @Override
3012 public void close() {
3013 if (mCloseable != null) {
3014 IoUtils.closeQuietly(mCloseable);
3015 }
3016 }
3017 }
3018
3019 class AppFuseMountScope implements AppFuseBridge.IMountScope {
3020 final int mUid;
3021 final int mName;
3022 final ParcelFileDescriptor mDeviceFd;
3023
3024 AppFuseMountScope(int uid, int pid, int name) throws NativeDaemonConnectorException {
3025 final NativeDaemonEvent event = mConnector.execute(
3026 "appfuse", "mount", uid, Process.myPid(), name);
3027 mUid = uid;
3028 mName = name;
3029 synchronized (mLock) {
3030 mAppFusePids.put(name, pid);
3031 }
3032 if (event.getFileDescriptors() != null &&
3033 event.getFileDescriptors().length > 0) {
3034 mDeviceFd = new ParcelFileDescriptor(event.getFileDescriptors()[0]);
3035 } else {
3036 mDeviceFd = null;
3037 }
3038 }
3039
3040 @Override
3041 public void close() throws NativeDaemonConnectorException {
3042 try {
3043 IoUtils.closeQuietly(mDeviceFd);
3044 mConnector.execute(
3045 "appfuse", "unmount", mUid, Process.myPid(), mName);
3046 } finally {
3047 synchronized (mLock) {
3048 mAppFusePids.delete(mName);
3049 }
3050 }
3051 }
3052
3053 @Override
3054 public ParcelFileDescriptor getDeviceFileDescriptor() {
3055 return mDeviceFd;
3056 }
3057 }
3058
3059 @Override
3060 public AppFuseMount mountProxyFileDescriptorBridge() throws RemoteException {
3061 final int uid = Binder.getCallingUid();
3062 final int pid = Binder.getCallingPid();
3063 final int name;
3064 synchronized (mAppFuseLock) {
3065 name = mNextAppFuseName++;
3066 }
3067 try (CloseableHolder<AppFuseMountScope> mountScope =
3068 new CloseableHolder<>(new AppFuseMountScope(uid, pid, name))) {
3069 if (mountScope.get().getDeviceFileDescriptor() == null) {
3070 throw new RemoteException("Failed to obtain device FD");
3071 }
3072
3073 // Create communication channel.
3074 final ArrayBlockingQueue<Boolean> channel = new ArrayBlockingQueue<>(1);
3075 final ParcelFileDescriptor[] fds = ParcelFileDescriptor.createSocketPair();
3076 try (CloseableHolder<ParcelFileDescriptor> remote = new CloseableHolder<>(fds[0])) {
3077 new Thread(
3078 new AppFuseBridge(mountScope.release(), fds[1], channel),
3079 AppFuseBridge.TAG).start();
3080 if (!channel.take()) {
3081 throw new RemoteException("Failed to init AppFuse mount point");
3082 }
3083
3084 return new AppFuseMount(name, remote.release());
3085 }
3086 } catch (NativeDaemonConnectorException e){
3087 throw e.rethrowAsParcelableException();
3088 } catch (IOException | InterruptedException error) {
3089 throw new RemoteException(error.getMessage());
3090 }
3091 }
3092
3093 @Override
3094 public ParcelFileDescriptor openProxyFileDescriptor(int mountId, int fileId, int mode) {
3095 final int uid = Binder.getCallingUid();
3096 final int pid = Binder.getCallingPid();
3097 try {
3098 synchronized (mAppFuseLock) {
3099 final int expectedPid = mAppFusePids.get(mountId, -1);
3100 if (expectedPid == -1) {
3101 Slog.i(TAG, "The mount point has already been unmounted");
3102 return null;
3103 }
3104 if (expectedPid != pid) {
3105 throw new SecurityException("Mount point was not created by this process.");
3106 }
3107 }
3108 return AppFuseBridge.openFile(uid, mountId, fileId, mode);
3109 } catch (FileNotFoundException error) {
3110 Slog.e(TAG, "Failed to openProxyFileDescriptor", error);
3111 return null;
3112 }
3113 }
3114
Daichi Hirono9e8d9e22015-11-13 14:37:00 +09003115 @Override
Jeff Sharkey2d8b4e82013-09-17 17:30:33 -07003116 public int mkdirs(String callingPkg, String appPath) {
3117 final int userId = UserHandle.getUserId(Binder.getCallingUid());
3118 final UserEnvironment userEnv = new UserEnvironment(userId);
3119
3120 // Validate that reported package name belongs to caller
3121 final AppOpsManager appOps = (AppOpsManager) mContext.getSystemService(
3122 Context.APP_OPS_SERVICE);
3123 appOps.checkPackage(Binder.getCallingUid(), callingPkg);
3124
Jeff Sharkey48877892015-03-18 11:27:19 -07003125 File appFile = null;
Jeff Sharkey2d8b4e82013-09-17 17:30:33 -07003126 try {
Jeff Sharkey48877892015-03-18 11:27:19 -07003127 appFile = new File(appPath).getCanonicalFile();
Jeff Sharkey2d8b4e82013-09-17 17:30:33 -07003128 } catch (IOException e) {
3129 Slog.e(TAG, "Failed to resolve " + appPath + ": " + e);
3130 return -1;
3131 }
3132
3133 // Try translating the app path into a vold path, but require that it
3134 // belong to the calling package.
Jeff Sharkey48877892015-03-18 11:27:19 -07003135 if (FileUtils.contains(userEnv.buildExternalStorageAppDataDirs(callingPkg), appFile) ||
3136 FileUtils.contains(userEnv.buildExternalStorageAppObbDirs(callingPkg), appFile) ||
3137 FileUtils.contains(userEnv.buildExternalStorageAppMediaDirs(callingPkg), appFile)) {
3138 appPath = appFile.getAbsolutePath();
3139 if (!appPath.endsWith("/")) {
3140 appPath = appPath + "/";
3141 }
3142
Jeff Sharkey2d8b4e82013-09-17 17:30:33 -07003143 try {
Jeff Sharkey48877892015-03-18 11:27:19 -07003144 mConnector.execute("volume", "mkdirs", appPath);
Jeff Sharkey2d8b4e82013-09-17 17:30:33 -07003145 return 0;
3146 } catch (NativeDaemonConnectorException e) {
3147 return e.getCode();
3148 }
3149 }
3150
Jeff Sharkey48877892015-03-18 11:27:19 -07003151 throw new SecurityException("Invalid mkdirs path: " + appFile);
Jeff Sharkey2d8b4e82013-09-17 17:30:33 -07003152 }
3153
3154 @Override
Jeff Sharkey46349872015-07-28 10:49:47 -07003155 public StorageVolume[] getVolumeList(int uid, String packageName, int flags) {
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07003156 final int userId = UserHandle.getUserId(uid);
Jeff Sharkeyc02bfae2016-03-27 15:06:53 -06003157
Jeff Sharkey46349872015-07-28 10:49:47 -07003158 final boolean forWrite = (flags & StorageManager.FLAG_FOR_WRITE) != 0;
Jeff Sharkeyc02bfae2016-03-27 15:06:53 -06003159 final boolean realState = (flags & StorageManager.FLAG_REAL_STATE) != 0;
3160 final boolean includeInvisible = (flags & StorageManager.FLAG_INCLUDE_INVISIBLE) != 0;
Jeff Sharkey46349872015-07-28 10:49:47 -07003161
Jeff Sharkeyc02bfae2016-03-27 15:06:53 -06003162 final boolean userKeyUnlocked;
3163 final boolean storagePermission;
3164 final long token = Binder.clearCallingIdentity();
Svetoslav38c3dbb2015-07-14 11:27:06 -07003165 try {
Jeff Sharkeyc02bfae2016-03-27 15:06:53 -06003166 userKeyUnlocked = isUserKeyUnlocked(userId);
Sudheer Shanka2250d562016-11-07 15:41:02 -08003167 storagePermission = mStorageManagerInternal.hasExternalStorage(uid, packageName);
Svetoslav38c3dbb2015-07-14 11:27:06 -07003168 } finally {
Jeff Sharkeyc02bfae2016-03-27 15:06:53 -06003169 Binder.restoreCallingIdentity(token);
Svetoslav38c3dbb2015-07-14 11:27:06 -07003170 }
Svet Ganov6ee871e2015-07-10 14:29:33 -07003171
Jeff Sharkeyc02bfae2016-03-27 15:06:53 -06003172 boolean foundPrimary = false;
3173
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07003174 final ArrayList<StorageVolume> res = new ArrayList<>();
Jeff Sharkey48877892015-03-18 11:27:19 -07003175 synchronized (mLock) {
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07003176 for (int i = 0; i < mVolumes.size(); i++) {
3177 final VolumeInfo vol = mVolumes.valueAt(i);
Jeff Sharkeyc02bfae2016-03-27 15:06:53 -06003178 switch (vol.getType()) {
3179 case VolumeInfo.TYPE_PUBLIC:
3180 case VolumeInfo.TYPE_EMULATED:
3181 break;
3182 default:
3183 continue;
3184 }
3185
3186 boolean match = false;
3187 if (forWrite) {
3188 match = vol.isVisibleForWrite(userId);
3189 } else {
Felipe Leme123a0e72016-06-10 11:09:11 -07003190 match = vol.isVisibleForRead(userId)
3191 || (includeInvisible && vol.getPath() != null);
Jeff Sharkeyc02bfae2016-03-27 15:06:53 -06003192 }
3193 if (!match) continue;
3194
3195 boolean reportUnmounted = false;
3196 if ((vol.getType() == VolumeInfo.TYPE_EMULATED) && !userKeyUnlocked) {
3197 reportUnmounted = true;
3198 } else if (!storagePermission && !realState) {
3199 reportUnmounted = true;
3200 }
3201
3202 final StorageVolume userVol = vol.buildStorageVolume(mContext, userId,
3203 reportUnmounted);
3204 if (vol.isPrimary()) {
3205 res.add(0, userVol);
3206 foundPrimary = true;
3207 } else {
3208 res.add(userVol);
Jeff Sharkeyb049e212012-09-07 23:16:01 -07003209 }
Mike Lockwood8fa5f802011-03-24 08:12:30 -07003210 }
Mike Lockwood8fa5f802011-03-24 08:12:30 -07003211 }
Jeff Sharkey48877892015-03-18 11:27:19 -07003212
3213 if (!foundPrimary) {
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07003214 Log.w(TAG, "No primary storage defined yet; hacking together a stub");
Jeff Sharkey48877892015-03-18 11:27:19 -07003215
3216 final boolean primaryPhysical = SystemProperties.getBoolean(
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07003217 StorageManager.PROP_PRIMARY_PHYSICAL, false);
Jeff Sharkey48877892015-03-18 11:27:19 -07003218
3219 final String id = "stub_primary";
3220 final File path = Environment.getLegacyExternalStorageDirectory();
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07003221 final String description = mContext.getString(android.R.string.unknownName);
Jeff Sharkey48877892015-03-18 11:27:19 -07003222 final boolean primary = true;
3223 final boolean removable = primaryPhysical;
3224 final boolean emulated = !primaryPhysical;
3225 final long mtpReserveSize = 0L;
3226 final boolean allowMassStorage = false;
3227 final long maxFileSize = 0L;
3228 final UserHandle owner = new UserHandle(userId);
3229 final String uuid = null;
Jeff Sharkey48877892015-03-18 11:27:19 -07003230 final String state = Environment.MEDIA_REMOVED;
3231
Jeff Sharkey5af1835d2015-07-07 17:26:59 -07003232 res.add(0, new StorageVolume(id, StorageVolume.STORAGE_ID_INVALID, path,
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07003233 description, primary, removable, emulated, mtpReserveSize,
3234 allowMassStorage, maxFileSize, owner, uuid, state));
Jeff Sharkey48877892015-03-18 11:27:19 -07003235 }
3236
3237 return res.toArray(new StorageVolume[res.size()]);
Mike Lockwood8fa5f802011-03-24 08:12:30 -07003238 }
3239
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07003240 @Override
3241 public DiskInfo[] getDisks() {
3242 synchronized (mLock) {
3243 final DiskInfo[] res = new DiskInfo[mDisks.size()];
3244 for (int i = 0; i < mDisks.size(); i++) {
3245 res[i] = mDisks.valueAt(i);
3246 }
3247 return res;
3248 }
3249 }
3250
3251 @Override
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07003252 public VolumeInfo[] getVolumes(int flags) {
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -07003253 synchronized (mLock) {
3254 final VolumeInfo[] res = new VolumeInfo[mVolumes.size()];
3255 for (int i = 0; i < mVolumes.size(); i++) {
3256 res[i] = mVolumes.valueAt(i);
3257 }
3258 return res;
3259 }
3260 }
3261
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07003262 @Override
3263 public VolumeRecord[] getVolumeRecords(int flags) {
3264 synchronized (mLock) {
3265 final VolumeRecord[] res = new VolumeRecord[mRecords.size()];
3266 for (int i = 0; i < mRecords.size(); i++) {
3267 res[i] = mRecords.valueAt(i);
3268 }
3269 return res;
3270 }
3271 }
3272
Kenny Rootaf9d6672010-10-08 09:21:39 -07003273 private void addObbStateLocked(ObbState obbState) throws RemoteException {
3274 final IBinder binder = obbState.getBinder();
3275 List<ObbState> obbStates = mObbMounts.get(binder);
Kenny Root5919ac62010-10-05 09:49:40 -07003276
Kenny Rootaf9d6672010-10-08 09:21:39 -07003277 if (obbStates == null) {
3278 obbStates = new ArrayList<ObbState>();
3279 mObbMounts.put(binder, obbStates);
3280 } else {
3281 for (final ObbState o : obbStates) {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003282 if (o.rawPath.equals(obbState.rawPath)) {
Kenny Rootaf9d6672010-10-08 09:21:39 -07003283 throw new IllegalStateException("Attempt to add ObbState twice. "
Sudheer Shanka2250d562016-11-07 15:41:02 -08003284 + "This indicates an error in the StorageManagerService logic.");
Kenny Root5919ac62010-10-05 09:49:40 -07003285 }
3286 }
Kenny Roota02b8b02010-08-05 16:14:17 -07003287 }
Kenny Rootaf9d6672010-10-08 09:21:39 -07003288
3289 obbStates.add(obbState);
3290 try {
3291 obbState.link();
3292 } catch (RemoteException e) {
3293 /*
3294 * The binder died before we could link it, so clean up our state
3295 * and return failure.
3296 */
3297 obbStates.remove(obbState);
3298 if (obbStates.isEmpty()) {
3299 mObbMounts.remove(binder);
3300 }
3301
3302 // Rethrow the error so mountObb can get it
3303 throw e;
3304 }
3305
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003306 mObbPathToStateMap.put(obbState.rawPath, obbState);
Kenny Roota02b8b02010-08-05 16:14:17 -07003307 }
3308
Kenny Rootaf9d6672010-10-08 09:21:39 -07003309 private void removeObbStateLocked(ObbState obbState) {
3310 final IBinder binder = obbState.getBinder();
3311 final List<ObbState> obbStates = mObbMounts.get(binder);
3312 if (obbStates != null) {
3313 if (obbStates.remove(obbState)) {
3314 obbState.unlink();
Kenny Root05105f72010-09-22 17:29:43 -07003315 }
Kenny Rootaf9d6672010-10-08 09:21:39 -07003316 if (obbStates.isEmpty()) {
3317 mObbMounts.remove(binder);
3318 }
Kenny Roota02b8b02010-08-05 16:14:17 -07003319 }
Kenny Roota02b8b02010-08-05 16:14:17 -07003320
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003321 mObbPathToStateMap.remove(obbState.rawPath);
Kenny Root38cf8862010-09-26 14:18:51 -07003322 }
3323
Kenny Roota02b8b02010-08-05 16:14:17 -07003324 private class ObbActionHandler extends Handler {
3325 private boolean mBound = false;
Kenny Root480afe72010-10-07 10:17:50 -07003326 private final List<ObbAction> mActions = new LinkedList<ObbAction>();
Kenny Roota02b8b02010-08-05 16:14:17 -07003327
3328 ObbActionHandler(Looper l) {
3329 super(l);
3330 }
3331
3332 @Override
3333 public void handleMessage(Message msg) {
3334 switch (msg.what) {
3335 case OBB_RUN_ACTION: {
Kenny Root480afe72010-10-07 10:17:50 -07003336 final ObbAction action = (ObbAction) msg.obj;
Kenny Roota02b8b02010-08-05 16:14:17 -07003337
3338 if (DEBUG_OBB)
3339 Slog.i(TAG, "OBB_RUN_ACTION: " + action.toString());
3340
3341 // If a bind was already initiated we don't really
3342 // need to do anything. The pending install
3343 // will be processed later on.
3344 if (!mBound) {
3345 // If this is the only one pending we might
3346 // have to bind to the service again.
3347 if (!connectToService()) {
3348 Slog.e(TAG, "Failed to bind to media container service");
3349 action.handleError();
3350 return;
Kenny Roota02b8b02010-08-05 16:14:17 -07003351 }
Kenny Roota02b8b02010-08-05 16:14:17 -07003352 }
Kenny Root735de3b2010-09-30 14:11:39 -07003353
Kenny Root735de3b2010-09-30 14:11:39 -07003354 mActions.add(action);
Kenny Roota02b8b02010-08-05 16:14:17 -07003355 break;
3356 }
3357 case OBB_MCS_BOUND: {
3358 if (DEBUG_OBB)
3359 Slog.i(TAG, "OBB_MCS_BOUND");
3360 if (msg.obj != null) {
3361 mContainerService = (IMediaContainerService) msg.obj;
3362 }
3363 if (mContainerService == null) {
3364 // Something seriously wrong. Bail out
3365 Slog.e(TAG, "Cannot bind to media container service");
3366 for (ObbAction action : mActions) {
3367 // Indicate service bind error
3368 action.handleError();
3369 }
3370 mActions.clear();
3371 } else if (mActions.size() > 0) {
Kenny Root480afe72010-10-07 10:17:50 -07003372 final ObbAction action = mActions.get(0);
Kenny Roota02b8b02010-08-05 16:14:17 -07003373 if (action != null) {
3374 action.execute(this);
3375 }
3376 } else {
3377 // Should never happen ideally.
3378 Slog.w(TAG, "Empty queue");
3379 }
3380 break;
3381 }
3382 case OBB_MCS_RECONNECT: {
3383 if (DEBUG_OBB)
3384 Slog.i(TAG, "OBB_MCS_RECONNECT");
3385 if (mActions.size() > 0) {
3386 if (mBound) {
3387 disconnectService();
3388 }
3389 if (!connectToService()) {
3390 Slog.e(TAG, "Failed to bind to media container service");
3391 for (ObbAction action : mActions) {
3392 // Indicate service bind error
3393 action.handleError();
3394 }
3395 mActions.clear();
3396 }
3397 }
3398 break;
3399 }
3400 case OBB_MCS_UNBIND: {
3401 if (DEBUG_OBB)
3402 Slog.i(TAG, "OBB_MCS_UNBIND");
3403
3404 // Delete pending install
3405 if (mActions.size() > 0) {
3406 mActions.remove(0);
3407 }
3408 if (mActions.size() == 0) {
3409 if (mBound) {
3410 disconnectService();
3411 }
3412 } else {
3413 // There are more pending requests in queue.
3414 // Just post MCS_BOUND message to trigger processing
3415 // of next pending install.
3416 mObbActionHandler.sendEmptyMessage(OBB_MCS_BOUND);
3417 }
3418 break;
3419 }
Kenny Rootaf9d6672010-10-08 09:21:39 -07003420 case OBB_FLUSH_MOUNT_STATE: {
3421 final String path = (String) msg.obj;
3422
3423 if (DEBUG_OBB)
3424 Slog.i(TAG, "Flushing all OBB state for path " + path);
3425
3426 synchronized (mObbMounts) {
3427 final List<ObbState> obbStatesToRemove = new LinkedList<ObbState>();
3428
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003429 final Iterator<ObbState> i = mObbPathToStateMap.values().iterator();
Kenny Rootaf9d6672010-10-08 09:21:39 -07003430 while (i.hasNext()) {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003431 final ObbState state = i.next();
Kenny Rootaf9d6672010-10-08 09:21:39 -07003432
3433 /*
3434 * If this entry's source file is in the volume path
3435 * that got unmounted, remove it because it's no
3436 * longer valid.
3437 */
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003438 if (state.canonicalPath.startsWith(path)) {
3439 obbStatesToRemove.add(state);
Kenny Rootaf9d6672010-10-08 09:21:39 -07003440 }
3441 }
3442
3443 for (final ObbState obbState : obbStatesToRemove) {
3444 if (DEBUG_OBB)
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003445 Slog.i(TAG, "Removing state for " + obbState.rawPath);
Kenny Rootaf9d6672010-10-08 09:21:39 -07003446
3447 removeObbStateLocked(obbState);
3448
3449 try {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003450 obbState.token.onObbResult(obbState.rawPath, obbState.nonce,
Kenny Rootaf9d6672010-10-08 09:21:39 -07003451 OnObbStateChangeListener.UNMOUNTED);
3452 } catch (RemoteException e) {
3453 Slog.i(TAG, "Couldn't send unmount notification for OBB: "
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003454 + obbState.rawPath);
Kenny Rootaf9d6672010-10-08 09:21:39 -07003455 }
3456 }
3457 }
3458 break;
3459 }
Kenny Roota02b8b02010-08-05 16:14:17 -07003460 }
3461 }
3462
3463 private boolean connectToService() {
3464 if (DEBUG_OBB)
3465 Slog.i(TAG, "Trying to bind to DefaultContainerService");
3466
3467 Intent service = new Intent().setComponent(DEFAULT_CONTAINER_COMPONENT);
Jeff Sharkey6dce4962015-07-03 18:08:41 -07003468 if (mContext.bindServiceAsUser(service, mDefContainerConn, Context.BIND_AUTO_CREATE,
Xiaohui Chene4de5a02015-09-22 15:33:31 -07003469 UserHandle.SYSTEM)) {
Kenny Roota02b8b02010-08-05 16:14:17 -07003470 mBound = true;
3471 return true;
3472 }
3473 return false;
3474 }
3475
3476 private void disconnectService() {
3477 mContainerService = null;
3478 mBound = false;
3479 mContext.unbindService(mDefContainerConn);
3480 }
3481 }
3482
3483 abstract class ObbAction {
3484 private static final int MAX_RETRIES = 3;
3485 private int mRetries;
3486
3487 ObbState mObbState;
3488
3489 ObbAction(ObbState obbState) {
3490 mObbState = obbState;
3491 }
3492
3493 public void execute(ObbActionHandler handler) {
3494 try {
3495 if (DEBUG_OBB)
Ben Komalo444eca22011-09-01 15:17:44 -07003496 Slog.i(TAG, "Starting to execute action: " + toString());
Kenny Roota02b8b02010-08-05 16:14:17 -07003497 mRetries++;
3498 if (mRetries > MAX_RETRIES) {
3499 Slog.w(TAG, "Failed to invoke remote methods on default container service. Giving up");
Kenny Root480afe72010-10-07 10:17:50 -07003500 mObbActionHandler.sendEmptyMessage(OBB_MCS_UNBIND);
Kenny Roota02b8b02010-08-05 16:14:17 -07003501 handleError();
Kenny Roota02b8b02010-08-05 16:14:17 -07003502 } else {
3503 handleExecute();
3504 if (DEBUG_OBB)
3505 Slog.i(TAG, "Posting install MCS_UNBIND");
3506 mObbActionHandler.sendEmptyMessage(OBB_MCS_UNBIND);
3507 }
3508 } catch (RemoteException e) {
3509 if (DEBUG_OBB)
3510 Slog.i(TAG, "Posting install MCS_RECONNECT");
3511 mObbActionHandler.sendEmptyMessage(OBB_MCS_RECONNECT);
3512 } catch (Exception e) {
3513 if (DEBUG_OBB)
3514 Slog.d(TAG, "Error handling OBB action", e);
3515 handleError();
Kenny Root17eb6fb2010-10-06 15:02:52 -07003516 mObbActionHandler.sendEmptyMessage(OBB_MCS_UNBIND);
Kenny Roota02b8b02010-08-05 16:14:17 -07003517 }
3518 }
3519
Kenny Root05105f72010-09-22 17:29:43 -07003520 abstract void handleExecute() throws RemoteException, IOException;
Kenny Roota02b8b02010-08-05 16:14:17 -07003521 abstract void handleError();
Kenny Root38cf8862010-09-26 14:18:51 -07003522
3523 protected ObbInfo getObbInfo() throws IOException {
3524 ObbInfo obbInfo;
3525 try {
Xiaohui Chen621b3fc2015-10-02 14:41:42 -07003526 obbInfo = mContainerService.getObbInfo(mObbState.canonicalPath);
Kenny Root38cf8862010-09-26 14:18:51 -07003527 } catch (RemoteException e) {
3528 Slog.d(TAG, "Couldn't call DefaultContainerService to fetch OBB info for "
Xiaohui Chen621b3fc2015-10-02 14:41:42 -07003529 + mObbState.canonicalPath);
Kenny Root38cf8862010-09-26 14:18:51 -07003530 obbInfo = null;
3531 }
3532 if (obbInfo == null) {
Xiaohui Chen621b3fc2015-10-02 14:41:42 -07003533 throw new IOException("Couldn't read OBB file: " + mObbState.canonicalPath);
Kenny Root38cf8862010-09-26 14:18:51 -07003534 }
3535 return obbInfo;
3536 }
3537
Kenny Rootaf9d6672010-10-08 09:21:39 -07003538 protected void sendNewStatusOrIgnore(int status) {
3539 if (mObbState == null || mObbState.token == null) {
3540 return;
3541 }
3542
Kenny Root38cf8862010-09-26 14:18:51 -07003543 try {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003544 mObbState.token.onObbResult(mObbState.rawPath, mObbState.nonce, status);
Kenny Root38cf8862010-09-26 14:18:51 -07003545 } catch (RemoteException e) {
Sudheer Shanka2250d562016-11-07 15:41:02 -08003546 Slog.w(TAG, "StorageEventListener went away while calling onObbStateChanged");
Kenny Root38cf8862010-09-26 14:18:51 -07003547 }
3548 }
Kenny Roota02b8b02010-08-05 16:14:17 -07003549 }
3550
3551 class MountObbAction extends ObbAction {
Ben Komalo444eca22011-09-01 15:17:44 -07003552 private final String mKey;
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003553 private final int mCallingUid;
Kenny Roota02b8b02010-08-05 16:14:17 -07003554
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003555 MountObbAction(ObbState obbState, String key, int callingUid) {
Kenny Roota02b8b02010-08-05 16:14:17 -07003556 super(obbState);
3557 mKey = key;
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003558 mCallingUid = callingUid;
Kenny Roota02b8b02010-08-05 16:14:17 -07003559 }
3560
Jason parks5af0b912010-11-29 09:05:25 -06003561 @Override
Kenny Root735de3b2010-09-30 14:11:39 -07003562 public void handleExecute() throws IOException, RemoteException {
Kenny Rootaf9d6672010-10-08 09:21:39 -07003563 waitForReady();
3564 warnOnNotMounted();
3565
Kenny Root38cf8862010-09-26 14:18:51 -07003566 final ObbInfo obbInfo = getObbInfo();
3567
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003568 if (!isUidOwnerOfPackageOrSystem(obbInfo.packageName, mCallingUid)) {
Kenny Rootaf9d6672010-10-08 09:21:39 -07003569 Slog.w(TAG, "Denied attempt to mount OBB " + obbInfo.filename
3570 + " which is owned by " + obbInfo.packageName);
3571 sendNewStatusOrIgnore(OnObbStateChangeListener.ERROR_PERMISSION_DENIED);
3572 return;
Kenny Roota02b8b02010-08-05 16:14:17 -07003573 }
3574
Kenny Rootaf9d6672010-10-08 09:21:39 -07003575 final boolean isMounted;
3576 synchronized (mObbMounts) {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003577 isMounted = mObbPathToStateMap.containsKey(mObbState.rawPath);
Kenny Rootaf9d6672010-10-08 09:21:39 -07003578 }
3579 if (isMounted) {
3580 Slog.w(TAG, "Attempt to mount OBB which is already mounted: " + obbInfo.filename);
3581 sendNewStatusOrIgnore(OnObbStateChangeListener.ERROR_ALREADY_MOUNTED);
3582 return;
3583 }
3584
Kenny Rootaf9d6672010-10-08 09:21:39 -07003585 final String hashedKey;
3586 if (mKey == null) {
3587 hashedKey = "none";
3588 } else {
Kenny Rootaf9d6672010-10-08 09:21:39 -07003589 try {
Kenny Root3b1abba2010-10-13 15:00:07 -07003590 SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
3591
3592 KeySpec ks = new PBEKeySpec(mKey.toCharArray(), obbInfo.salt,
3593 PBKDF2_HASH_ROUNDS, CRYPTO_ALGORITHM_KEY_SIZE);
3594 SecretKey key = factory.generateSecret(ks);
3595 BigInteger bi = new BigInteger(key.getEncoded());
3596 hashedKey = bi.toString(16);
Kenny Rootaf9d6672010-10-08 09:21:39 -07003597 } catch (NoSuchAlgorithmException e) {
Kenny Root3b1abba2010-10-13 15:00:07 -07003598 Slog.e(TAG, "Could not load PBKDF2 algorithm", e);
3599 sendNewStatusOrIgnore(OnObbStateChangeListener.ERROR_INTERNAL);
3600 return;
3601 } catch (InvalidKeySpecException e) {
3602 Slog.e(TAG, "Invalid key spec when loading PBKDF2 algorithm", e);
3603 sendNewStatusOrIgnore(OnObbStateChangeListener.ERROR_INTERNAL);
Kenny Root38cf8862010-09-26 14:18:51 -07003604 return;
3605 }
Kenny Rootaf9d6672010-10-08 09:21:39 -07003606 }
Kenny Root38cf8862010-09-26 14:18:51 -07003607
Kenny Rootaf9d6672010-10-08 09:21:39 -07003608 int rc = StorageResultCode.OperationSucceeded;
Kenny Rootaf9d6672010-10-08 09:21:39 -07003609 try {
Xiaohui Chen621b3fc2015-10-02 14:41:42 -07003610 mConnector.execute("obb", "mount", mObbState.canonicalPath, new SensitiveArg(hashedKey),
Jeff Sharkey56cd6462013-06-07 15:09:15 -07003611 mObbState.ownerGid);
Kenny Rootaf9d6672010-10-08 09:21:39 -07003612 } catch (NativeDaemonConnectorException e) {
3613 int code = e.getCode();
3614 if (code != VoldResponseCode.OpFailedStorageBusy) {
3615 rc = StorageResultCode.OperationFailedInternalError;
Kenny Roota02b8b02010-08-05 16:14:17 -07003616 }
3617 }
3618
Kenny Rootaf9d6672010-10-08 09:21:39 -07003619 if (rc == StorageResultCode.OperationSucceeded) {
3620 if (DEBUG_OBB)
Xiaohui Chen621b3fc2015-10-02 14:41:42 -07003621 Slog.d(TAG, "Successfully mounted OBB " + mObbState.canonicalPath);
Kenny Rootaf9d6672010-10-08 09:21:39 -07003622
3623 synchronized (mObbMounts) {
3624 addObbStateLocked(mObbState);
3625 }
3626
3627 sendNewStatusOrIgnore(OnObbStateChangeListener.MOUNTED);
Kenny Root02c87302010-07-01 08:10:18 -07003628 } else {
Kenny Root05105f72010-09-22 17:29:43 -07003629 Slog.e(TAG, "Couldn't mount OBB file: " + rc);
Kenny Roota02b8b02010-08-05 16:14:17 -07003630
Kenny Rootaf9d6672010-10-08 09:21:39 -07003631 sendNewStatusOrIgnore(OnObbStateChangeListener.ERROR_COULD_NOT_MOUNT);
Kenny Root02c87302010-07-01 08:10:18 -07003632 }
3633 }
3634
Jason parks5af0b912010-11-29 09:05:25 -06003635 @Override
Kenny Roota02b8b02010-08-05 16:14:17 -07003636 public void handleError() {
Kenny Rootaf9d6672010-10-08 09:21:39 -07003637 sendNewStatusOrIgnore(OnObbStateChangeListener.ERROR_INTERNAL);
Kenny Root02c87302010-07-01 08:10:18 -07003638 }
Kenny Roota02b8b02010-08-05 16:14:17 -07003639
3640 @Override
3641 public String toString() {
3642 StringBuilder sb = new StringBuilder();
3643 sb.append("MountObbAction{");
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003644 sb.append(mObbState);
Kenny Roota02b8b02010-08-05 16:14:17 -07003645 sb.append('}');
3646 return sb.toString();
3647 }
3648 }
3649
3650 class UnmountObbAction extends ObbAction {
Ben Komalo444eca22011-09-01 15:17:44 -07003651 private final boolean mForceUnmount;
Kenny Roota02b8b02010-08-05 16:14:17 -07003652
3653 UnmountObbAction(ObbState obbState, boolean force) {
3654 super(obbState);
3655 mForceUnmount = force;
3656 }
3657
Jason parks5af0b912010-11-29 09:05:25 -06003658 @Override
Kenny Root38cf8862010-09-26 14:18:51 -07003659 public void handleExecute() throws IOException {
Kenny Rootaf9d6672010-10-08 09:21:39 -07003660 waitForReady();
3661 warnOnNotMounted();
3662
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003663 final ObbState existingState;
Kenny Root38cf8862010-09-26 14:18:51 -07003664 synchronized (mObbMounts) {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003665 existingState = mObbPathToStateMap.get(mObbState.rawPath);
Kenny Rootaf9d6672010-10-08 09:21:39 -07003666 }
Kenny Root38cf8862010-09-26 14:18:51 -07003667
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003668 if (existingState == null) {
Kenny Rootaf9d6672010-10-08 09:21:39 -07003669 sendNewStatusOrIgnore(OnObbStateChangeListener.ERROR_NOT_MOUNTED);
3670 return;
3671 }
3672
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003673 if (existingState.ownerGid != mObbState.ownerGid) {
3674 Slog.w(TAG, "Permission denied attempting to unmount OBB " + existingState.rawPath
3675 + " (owned by GID " + existingState.ownerGid + ")");
Kenny Rootaf9d6672010-10-08 09:21:39 -07003676 sendNewStatusOrIgnore(OnObbStateChangeListener.ERROR_PERMISSION_DENIED);
3677 return;
3678 }
3679
Kenny Rootaf9d6672010-10-08 09:21:39 -07003680 int rc = StorageResultCode.OperationSucceeded;
Kenny Rootaf9d6672010-10-08 09:21:39 -07003681 try {
Xiaohui Chen621b3fc2015-10-02 14:41:42 -07003682 final Command cmd = new Command("obb", "unmount", mObbState.canonicalPath);
Jeff Sharkeydd519fa2011-12-02 14:11:21 -08003683 if (mForceUnmount) {
3684 cmd.appendArg("force");
3685 }
3686 mConnector.execute(cmd);
Kenny Rootaf9d6672010-10-08 09:21:39 -07003687 } catch (NativeDaemonConnectorException e) {
3688 int code = e.getCode();
3689 if (code == VoldResponseCode.OpFailedStorageBusy) {
3690 rc = StorageResultCode.OperationFailedStorageBusy;
3691 } else if (code == VoldResponseCode.OpFailedStorageNotFound) {
3692 // If it's not mounted then we've already won.
3693 rc = StorageResultCode.OperationSucceeded;
3694 } else {
3695 rc = StorageResultCode.OperationFailedInternalError;
Kenny Roota02b8b02010-08-05 16:14:17 -07003696 }
3697 }
3698
Kenny Rootaf9d6672010-10-08 09:21:39 -07003699 if (rc == StorageResultCode.OperationSucceeded) {
3700 synchronized (mObbMounts) {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003701 removeObbStateLocked(existingState);
Kenny Root38cf8862010-09-26 14:18:51 -07003702 }
3703
Kenny Rootaf9d6672010-10-08 09:21:39 -07003704 sendNewStatusOrIgnore(OnObbStateChangeListener.UNMOUNTED);
Kenny Roota02b8b02010-08-05 16:14:17 -07003705 } else {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003706 Slog.w(TAG, "Could not unmount OBB: " + existingState);
Kenny Rootaf9d6672010-10-08 09:21:39 -07003707 sendNewStatusOrIgnore(OnObbStateChangeListener.ERROR_COULD_NOT_UNMOUNT);
Kenny Roota02b8b02010-08-05 16:14:17 -07003708 }
3709 }
3710
Jason parks5af0b912010-11-29 09:05:25 -06003711 @Override
Kenny Roota02b8b02010-08-05 16:14:17 -07003712 public void handleError() {
Kenny Rootaf9d6672010-10-08 09:21:39 -07003713 sendNewStatusOrIgnore(OnObbStateChangeListener.ERROR_INTERNAL);
Kenny Roota02b8b02010-08-05 16:14:17 -07003714 }
3715
3716 @Override
3717 public String toString() {
3718 StringBuilder sb = new StringBuilder();
3719 sb.append("UnmountObbAction{");
Jeff Sharkey4fbbda42012-09-24 18:34:07 -07003720 sb.append(mObbState);
Kenny Roota02b8b02010-08-05 16:14:17 -07003721 sb.append(",force=");
3722 sb.append(mForceUnmount);
Kenny Roota02b8b02010-08-05 16:14:17 -07003723 sb.append('}');
3724 return sb.toString();
3725 }
Kenny Root02c87302010-07-01 08:10:18 -07003726 }
Kenny Root38cf8862010-09-26 14:18:51 -07003727
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07003728 private static class Callbacks extends Handler {
3729 private static final int MSG_STORAGE_STATE_CHANGED = 1;
3730 private static final int MSG_VOLUME_STATE_CHANGED = 2;
Jeff Sharkey50a05452015-04-29 11:24:52 -07003731 private static final int MSG_VOLUME_RECORD_CHANGED = 3;
3732 private static final int MSG_VOLUME_FORGOTTEN = 4;
3733 private static final int MSG_DISK_SCANNED = 5;
Makoto Onuki9dc575d2015-06-12 16:10:25 -07003734 private static final int MSG_DISK_DESTROYED = 6;
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07003735
Sudheer Shanka2250d562016-11-07 15:41:02 -08003736 private final RemoteCallbackList<IStorageEventListener>
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07003737 mCallbacks = new RemoteCallbackList<>();
3738
3739 public Callbacks(Looper looper) {
3740 super(looper);
3741 }
3742
Sudheer Shanka2250d562016-11-07 15:41:02 -08003743 public void register(IStorageEventListener callback) {
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07003744 mCallbacks.register(callback);
3745 }
3746
Sudheer Shanka2250d562016-11-07 15:41:02 -08003747 public void unregister(IStorageEventListener callback) {
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07003748 mCallbacks.unregister(callback);
3749 }
3750
3751 @Override
3752 public void handleMessage(Message msg) {
3753 final SomeArgs args = (SomeArgs) msg.obj;
3754 final int n = mCallbacks.beginBroadcast();
3755 for (int i = 0; i < n; i++) {
Sudheer Shanka2250d562016-11-07 15:41:02 -08003756 final IStorageEventListener callback = mCallbacks.getBroadcastItem(i);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07003757 try {
3758 invokeCallback(callback, msg.what, args);
3759 } catch (RemoteException ignored) {
3760 }
3761 }
3762 mCallbacks.finishBroadcast();
3763 args.recycle();
3764 }
3765
Sudheer Shanka2250d562016-11-07 15:41:02 -08003766 private void invokeCallback(IStorageEventListener callback, int what, SomeArgs args)
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07003767 throws RemoteException {
3768 switch (what) {
3769 case MSG_STORAGE_STATE_CHANGED: {
3770 callback.onStorageStateChanged((String) args.arg1, (String) args.arg2,
3771 (String) args.arg3);
3772 break;
3773 }
3774 case MSG_VOLUME_STATE_CHANGED: {
3775 callback.onVolumeStateChanged((VolumeInfo) args.arg1, args.argi2, args.argi3);
3776 break;
3777 }
Jeff Sharkey50a05452015-04-29 11:24:52 -07003778 case MSG_VOLUME_RECORD_CHANGED: {
3779 callback.onVolumeRecordChanged((VolumeRecord) args.arg1);
3780 break;
3781 }
3782 case MSG_VOLUME_FORGOTTEN: {
3783 callback.onVolumeForgotten((String) args.arg1);
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07003784 break;
3785 }
Jeff Sharkey620b32b2015-04-23 19:36:02 -07003786 case MSG_DISK_SCANNED: {
3787 callback.onDiskScanned((DiskInfo) args.arg1, args.argi2);
Jeff Sharkey7e92ef32015-04-17 17:35:07 -07003788 break;
3789 }
Makoto Onuki9dc575d2015-06-12 16:10:25 -07003790 case MSG_DISK_DESTROYED: {
3791 callback.onDiskDestroyed((DiskInfo) args.arg1);
3792 break;
3793 }
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07003794 }
3795 }
3796
3797 private void notifyStorageStateChanged(String path, String oldState, String newState) {
3798 final SomeArgs args = SomeArgs.obtain();
3799 args.arg1 = path;
3800 args.arg2 = oldState;
3801 args.arg3 = newState;
3802 obtainMessage(MSG_STORAGE_STATE_CHANGED, args).sendToTarget();
3803 }
3804
3805 private void notifyVolumeStateChanged(VolumeInfo vol, int oldState, int newState) {
3806 final SomeArgs args = SomeArgs.obtain();
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07003807 args.arg1 = vol.clone();
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07003808 args.argi2 = oldState;
3809 args.argi3 = newState;
3810 obtainMessage(MSG_VOLUME_STATE_CHANGED, args).sendToTarget();
3811 }
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07003812
Jeff Sharkey50a05452015-04-29 11:24:52 -07003813 private void notifyVolumeRecordChanged(VolumeRecord rec) {
3814 final SomeArgs args = SomeArgs.obtain();
3815 args.arg1 = rec.clone();
3816 obtainMessage(MSG_VOLUME_RECORD_CHANGED, args).sendToTarget();
3817 }
3818
3819 private void notifyVolumeForgotten(String fsUuid) {
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07003820 final SomeArgs args = SomeArgs.obtain();
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07003821 args.arg1 = fsUuid;
Jeff Sharkey50a05452015-04-29 11:24:52 -07003822 obtainMessage(MSG_VOLUME_FORGOTTEN, args).sendToTarget();
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -07003823 }
Jeff Sharkey7e92ef32015-04-17 17:35:07 -07003824
Jeff Sharkey620b32b2015-04-23 19:36:02 -07003825 private void notifyDiskScanned(DiskInfo disk, int volumeCount) {
Jeff Sharkey7e92ef32015-04-17 17:35:07 -07003826 final SomeArgs args = SomeArgs.obtain();
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07003827 args.arg1 = disk.clone();
Jeff Sharkey620b32b2015-04-23 19:36:02 -07003828 args.argi2 = volumeCount;
3829 obtainMessage(MSG_DISK_SCANNED, args).sendToTarget();
Jeff Sharkey7e92ef32015-04-17 17:35:07 -07003830 }
Makoto Onuki9dc575d2015-06-12 16:10:25 -07003831
3832 private void notifyDiskDestroyed(DiskInfo disk) {
3833 final SomeArgs args = SomeArgs.obtain();
3834 args.arg1 = disk.clone();
3835 obtainMessage(MSG_DISK_DESTROYED, args).sendToTarget();
3836 }
Jeff Sharkey7151a9a2015-04-04 15:22:37 -07003837 }
3838
Kenny Root38cf8862010-09-26 14:18:51 -07003839 @Override
Jeff Sharkey5aca2b82013-10-16 16:21:54 -07003840 protected void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
3841 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, TAG);
3842
3843 final IndentingPrintWriter pw = new IndentingPrintWriter(writer, " ", 160);
Jeff Sharkey27de30d2015-04-18 16:20:27 -07003844 synchronized (mLock) {
3845 pw.println("Disks:");
3846 pw.increaseIndent();
3847 for (int i = 0; i < mDisks.size(); i++) {
3848 final DiskInfo disk = mDisks.valueAt(i);
3849 disk.dump(pw);
3850 }
3851 pw.decreaseIndent();
3852
3853 pw.println();
3854 pw.println("Volumes:");
3855 pw.increaseIndent();
3856 for (int i = 0; i < mVolumes.size(); i++) {
3857 final VolumeInfo vol = mVolumes.valueAt(i);
3858 if (VolumeInfo.ID_PRIVATE_INTERNAL.equals(vol.id)) continue;
3859 vol.dump(pw);
3860 }
3861 pw.decreaseIndent();
3862
3863 pw.println();
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07003864 pw.println("Records:");
Jeff Sharkey27de30d2015-04-18 16:20:27 -07003865 pw.increaseIndent();
Jeff Sharkeyb36586a2015-04-27 08:42:28 -07003866 for (int i = 0; i < mRecords.size(); i++) {
3867 final VolumeRecord note = mRecords.valueAt(i);
3868 note.dump(pw);
Jeff Sharkey27de30d2015-04-18 16:20:27 -07003869 }
3870 pw.decreaseIndent();
Jeff Sharkey275e3e42015-04-24 16:10:32 -07003871
3872 pw.println();
3873 pw.println("Primary storage UUID: " + mPrimaryStorageUuid);
Felipe Leme281389a2016-10-10 17:12:20 -07003874 final Pair<String, Long> pair = StorageManager.getPrimaryStoragePathAndSize();
3875 if (pair == null) {
3876 pw.println("Internal storage total size: N/A");
3877 } else {
3878 pw.print("Internal storage (");
3879 pw.print(pair.first);
3880 pw.print(") total size: ");
3881 pw.print(pair.second);
3882 pw.print(" (");
3883 pw.print((float) pair.second / TrafficStats.GB_IN_BYTES);
3884 pw.println(" GB)");
3885 }
Jeff Sharkey4c099d02015-05-15 13:45:00 -07003886 pw.println("Force adoptable: " + mForceAdoptable);
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08003887 pw.println();
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07003888 pw.println("Local unlocked users: " + Arrays.toString(mLocalUnlockedUsers));
3889 pw.println("System unlocked users: " + Arrays.toString(mSystemUnlockedUsers));
Jeff Sharkey27de30d2015-04-18 16:20:27 -07003890 }
Kenny Root38cf8862010-09-26 14:18:51 -07003891
Kenny Root38cf8862010-09-26 14:18:51 -07003892 synchronized (mObbMounts) {
Jeff Sharkey27de30d2015-04-18 16:20:27 -07003893 pw.println();
Jeff Sharkey5aca2b82013-10-16 16:21:54 -07003894 pw.println("mObbMounts:");
3895 pw.increaseIndent();
3896 final Iterator<Entry<IBinder, List<ObbState>>> binders = mObbMounts.entrySet()
3897 .iterator();
Kenny Rootaf9d6672010-10-08 09:21:39 -07003898 while (binders.hasNext()) {
3899 Entry<IBinder, List<ObbState>> e = binders.next();
Jeff Sharkey5aca2b82013-10-16 16:21:54 -07003900 pw.println(e.getKey() + ":");
3901 pw.increaseIndent();
Kenny Rootaf9d6672010-10-08 09:21:39 -07003902 final List<ObbState> obbStates = e.getValue();
Kenny Root38cf8862010-09-26 14:18:51 -07003903 for (final ObbState obbState : obbStates) {
Jeff Sharkey5aca2b82013-10-16 16:21:54 -07003904 pw.println(obbState);
Kenny Root38cf8862010-09-26 14:18:51 -07003905 }
Jeff Sharkey5aca2b82013-10-16 16:21:54 -07003906 pw.decreaseIndent();
Kenny Root38cf8862010-09-26 14:18:51 -07003907 }
Jeff Sharkey5aca2b82013-10-16 16:21:54 -07003908 pw.decreaseIndent();
Kenny Rootaf9d6672010-10-08 09:21:39 -07003909
Jeff Sharkey5aca2b82013-10-16 16:21:54 -07003910 pw.println();
3911 pw.println("mObbPathToStateMap:");
3912 pw.increaseIndent();
Kenny Rootaf9d6672010-10-08 09:21:39 -07003913 final Iterator<Entry<String, ObbState>> maps = mObbPathToStateMap.entrySet().iterator();
3914 while (maps.hasNext()) {
3915 final Entry<String, ObbState> e = maps.next();
Jeff Sharkey5aca2b82013-10-16 16:21:54 -07003916 pw.print(e.getKey());
3917 pw.print(" -> ");
3918 pw.println(e.getValue());
Kenny Rootaf9d6672010-10-08 09:21:39 -07003919 }
Jeff Sharkey5aca2b82013-10-16 16:21:54 -07003920 pw.decreaseIndent();
Kenny Root38cf8862010-09-26 14:18:51 -07003921 }
Kenny Root4161f9b2011-07-13 09:48:33 -07003922
Robert Greenwalt470fd722012-01-18 12:51:15 -08003923 pw.println();
Jeff Sharkey5b0e5202015-12-18 17:18:09 -07003924 pw.println("mConnector:");
Jeff Sharkey5aca2b82013-10-16 16:21:54 -07003925 pw.increaseIndent();
Robert Greenwalt470fd722012-01-18 12:51:15 -08003926 mConnector.dump(fd, pw, args);
Jeff Sharkey5aca2b82013-10-16 16:21:54 -07003927 pw.decreaseIndent();
Christopher Tate7265abe2014-11-21 13:54:45 -08003928
Christopher Tate7265abe2014-11-21 13:54:45 -08003929 pw.println();
Jeff Sharkey5b0e5202015-12-18 17:18:09 -07003930 pw.println("mCryptConnector:");
3931 pw.increaseIndent();
3932 mCryptConnector.dump(fd, pw, args);
3933 pw.decreaseIndent();
3934
3935 pw.println();
Christopher Tate7265abe2014-11-21 13:54:45 -08003936 pw.print("Last maintenance: ");
Jeff Sharkeye8a4b662015-06-27 15:43:45 -07003937 pw.println(TimeUtils.formatForLogging(mLastMaintenance));
Kenny Root38cf8862010-09-26 14:18:51 -07003938 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003939
Jeff Sharkeyfa23c5a2011-08-09 21:44:24 -07003940 /** {@inheritDoc} */
Jeff Sharkey48877892015-03-18 11:27:19 -07003941 @Override
Jeff Sharkeyfa23c5a2011-08-09 21:44:24 -07003942 public void monitor() {
3943 if (mConnector != null) {
3944 mConnector.monitor();
3945 }
Paul Lawrence1c62cbb2015-06-03 14:14:52 -07003946 if (mCryptConnector != null) {
3947 mCryptConnector.monitor();
3948 }
Jeff Sharkeyfa23c5a2011-08-09 21:44:24 -07003949 }
Svet Ganov6ee871e2015-07-10 14:29:33 -07003950
Sudheer Shanka2250d562016-11-07 15:41:02 -08003951 private final class StorageManagerInternalImpl extends StorageManagerInternal {
Svet Ganov6ee871e2015-07-10 14:29:33 -07003952 // Not guarded by a lock.
3953 private final CopyOnWriteArrayList<ExternalStorageMountPolicy> mPolicies =
3954 new CopyOnWriteArrayList<>();
3955
3956 @Override
3957 public void addExternalStoragePolicy(ExternalStorageMountPolicy policy) {
3958 // No locking - CopyOnWriteArrayList
3959 mPolicies.add(policy);
3960 }
3961
3962 @Override
3963 public void onExternalStoragePolicyChanged(int uid, String packageName) {
3964 final int mountMode = getExternalStorageMountMode(uid, packageName);
3965 remountUidExternalStorage(uid, mountMode);
3966 }
3967
3968 @Override
3969 public int getExternalStorageMountMode(int uid, String packageName) {
3970 // No locking - CopyOnWriteArrayList
3971 int mountMode = Integer.MAX_VALUE;
3972 for (ExternalStorageMountPolicy policy : mPolicies) {
3973 final int policyMode = policy.getMountMode(uid, packageName);
3974 if (policyMode == Zygote.MOUNT_EXTERNAL_NONE) {
3975 return Zygote.MOUNT_EXTERNAL_NONE;
3976 }
3977 mountMode = Math.min(mountMode, policyMode);
3978 }
3979 if (mountMode == Integer.MAX_VALUE) {
3980 return Zygote.MOUNT_EXTERNAL_NONE;
3981 }
3982 return mountMode;
3983 }
3984
3985 public boolean hasExternalStorage(int uid, String packageName) {
Amith Yamasani2bd5cff2015-07-22 14:42:31 -07003986 // No need to check for system uid. This avoids a deadlock between
3987 // PackageManagerService and AppOpsService.
3988 if (uid == Process.SYSTEM_UID) {
3989 return true;
3990 }
Svet Ganov6ee871e2015-07-10 14:29:33 -07003991 // No locking - CopyOnWriteArrayList
3992 for (ExternalStorageMountPolicy policy : mPolicies) {
3993 final boolean policyHasStorage = policy.hasExternalStorage(uid, packageName);
3994 if (!policyHasStorage) {
3995 return false;
3996 }
3997 }
3998 return true;
3999 }
4000 }
Jeff Sharkeyfa23c5a2011-08-09 21:44:24 -07004001}