blob: 22aec63a76a23e3da39103e154250f053dbcb6a5 [file] [log] [blame]
San Mehatb1043402010-02-05 08:26:50 -08001/*
2 * Copyright (C) 2008 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 android.os.storage;
18
Jeff Sharkeybe722152013-02-15 16:56:38 -080019import static android.net.TrafficStats.MB_IN_BYTES;
20
Jeff Sharkey48877892015-03-18 11:27:19 -070021import android.annotation.NonNull;
22import android.annotation.Nullable;
Svet Ganov6ee871e2015-07-10 14:29:33 -070023import android.app.ActivityThread;
Jeff Sharkeybe722152013-02-15 16:56:38 -080024import android.content.ContentResolver;
Jeff Sharkeyb049e212012-09-07 23:16:01 -070025import android.content.Context;
Jeff Sharkey275e3e42015-04-24 16:10:32 -070026import android.content.pm.IPackageMoveObserver;
27import android.content.pm.PackageManager;
Mike Lockwoodcba928c2011-08-17 15:58:52 -070028import android.os.Environment;
Jeff Sharkey48877892015-03-18 11:27:19 -070029import android.os.FileUtils;
San Mehatb1043402010-02-05 08:26:50 -080030import android.os.Handler;
Kenny Roota02b8b02010-08-05 16:14:17 -070031import android.os.Looper;
San Mehatb1043402010-02-05 08:26:50 -080032import android.os.Message;
Daichi Hirono9e8d9e22015-11-13 14:37:00 +090033import android.os.ParcelFileDescriptor;
Kenny Roota02b8b02010-08-05 16:14:17 -070034import android.os.RemoteException;
San Mehatb1043402010-02-05 08:26:50 -080035import android.os.ServiceManager;
Jeff Sharkeyba512352015-11-12 20:17:45 -080036import android.os.SystemProperties;
Jeff Sharkeybe722152013-02-15 16:56:38 -080037import android.provider.Settings;
Jeff Sharkeycf3f0a12016-03-17 19:57:58 -060038import android.security.KeyStore;
Jeff Sharkey59d577a2015-04-11 21:27:21 -070039import android.text.TextUtils;
San Mehatb1043402010-02-05 08:26:50 -080040import android.util.Log;
Jeff Sharkeyb42d6942015-04-28 22:25:26 -070041import android.util.Slog;
Kenny Rootaf9d6672010-10-08 09:21:39 -070042import android.util.SparseArray;
San Mehatb1043402010-02-05 08:26:50 -080043
Jeff Sharkey7151a9a2015-04-04 15:22:37 -070044import com.android.internal.os.SomeArgs;
Jeff Sharkey4fbbda42012-09-24 18:34:07 -070045import com.android.internal.util.Preconditions;
46
47import java.io.File;
48import java.io.IOException;
Kenny Root05105f72010-09-22 17:29:43 -070049import java.lang.ref.WeakReference;
San Mehatb1043402010-02-05 08:26:50 -080050import java.util.ArrayList;
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -070051import java.util.Arrays;
Jeff Sharkey7151a9a2015-04-04 15:22:37 -070052import java.util.Iterator;
Kenny Root05105f72010-09-22 17:29:43 -070053import java.util.List;
Jeff Sharkeyb2b9ab82015-04-05 21:10:42 -070054import java.util.Objects;
Kenny Rootaf9d6672010-10-08 09:21:39 -070055import java.util.concurrent.atomic.AtomicInteger;
San Mehatb1043402010-02-05 08:26:50 -080056
57/**
Kenny Root05105f72010-09-22 17:29:43 -070058 * StorageManager is the interface to the systems storage service. The storage
59 * manager handles storage-related items such as Opaque Binary Blobs (OBBs).
60 * <p>
61 * OBBs contain a filesystem that maybe be encrypted on disk and mounted
62 * on-demand from an application. OBBs are a good way of providing large amounts
63 * of binary assets without packaging them into APKs as they may be multiple
64 * gigabytes in size. However, due to their size, they're most likely stored in
65 * a shared storage pool accessible from all programs. The system does not
66 * guarantee the security of the OBB file itself: if any program modifies the
67 * OBB, there is no guarantee that a read from that OBB will produce the
68 * expected output.
69 * <p>
San Mehatb1043402010-02-05 08:26:50 -080070 * Get an instance of this class by calling
Kenny Root05105f72010-09-22 17:29:43 -070071 * {@link android.content.Context#getSystemService(java.lang.String)} with an
72 * argument of {@link android.content.Context#STORAGE_SERVICE}.
San Mehatb1043402010-02-05 08:26:50 -080073 */
Jeff Sharkeybe722152013-02-15 16:56:38 -080074public class StorageManager {
San Mehatb1043402010-02-05 08:26:50 -080075 private static final String TAG = "StorageManager";
76
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -070077 /** {@hide} */
78 public static final String PROP_PRIMARY_PHYSICAL = "ro.vold.primary_physical";
Jeff Sharkey74acbbb2015-04-21 12:14:03 -070079 /** {@hide} */
Jeff Sharkey0d838a02015-05-13 13:54:30 -070080 public static final String PROP_HAS_ADOPTABLE = "vold.has_adoptable";
81 /** {@hide} */
Jeff Sharkey74acbbb2015-04-21 12:14:03 -070082 public static final String PROP_FORCE_ADOPTABLE = "persist.fw.force_adoptable";
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -080083 /** {@hide} */
Jeff Sharkeyba512352015-11-12 20:17:45 -080084 public static final String PROP_EMULATE_FBE = "persist.sys.emulate_fbe";
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -070085
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -070086 /** {@hide} */
Jeff Sharkey620b32b2015-04-23 19:36:02 -070087 public static final String UUID_PRIVATE_INTERNAL = null;
88 /** {@hide} */
89 public static final String UUID_PRIMARY_PHYSICAL = "primary_physical";
90
Jeff Sharkey4c099d02015-05-15 13:45:00 -070091 /** {@hide} */
92 public static final int DEBUG_FORCE_ADOPTABLE = 1 << 0;
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -080093 /** {@hide} */
94 public static final int DEBUG_EMULATE_FBE = 1 << 1;
Jeff Sharkey4c099d02015-05-15 13:45:00 -070095
Jeff Sharkey47f71082016-02-01 17:03:54 -070096 // NOTE: keep in sync with installd
Jeff Sharkey46349872015-07-28 10:49:47 -070097 /** {@hide} */
Jeff Sharkey47f71082016-02-01 17:03:54 -070098 public static final int FLAG_STORAGE_DE = 1 << 0;
99 /** {@hide} */
100 public static final int FLAG_STORAGE_CE = 1 << 1;
101
102 /** {@hide} */
103 public static final int FLAG_FOR_WRITE = 1 << 8;
Jeff Sharkey46349872015-07-28 10:49:47 -0700104
Jeff Sharkey48877892015-03-18 11:27:19 -0700105 private final Context mContext;
Jeff Sharkeybe722152013-02-15 16:56:38 -0800106 private final ContentResolver mResolver;
107
Jeff Sharkeybe722152013-02-15 16:56:38 -0800108 private final IMountService mMountService;
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700109 private final Looper mLooper;
110 private final AtomicInteger mNextNonce = new AtomicInteger(0);
San Mehatb1043402010-02-05 08:26:50 -0800111
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700112 private final ArrayList<StorageEventListenerDelegate> mDelegates = new ArrayList<>();
San Mehatb1043402010-02-05 08:26:50 -0800113
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700114 private static class StorageEventListenerDelegate extends IMountServiceListener.Stub implements
115 Handler.Callback {
116 private static final int MSG_STORAGE_STATE_CHANGED = 1;
117 private static final int MSG_VOLUME_STATE_CHANGED = 2;
Jeff Sharkey50a05452015-04-29 11:24:52 -0700118 private static final int MSG_VOLUME_RECORD_CHANGED = 3;
119 private static final int MSG_VOLUME_FORGOTTEN = 4;
120 private static final int MSG_DISK_SCANNED = 5;
Makoto Onuki9dc575d2015-06-12 16:10:25 -0700121 private static final int MSG_DISK_DESTROYED = 6;
San Mehatb1043402010-02-05 08:26:50 -0800122
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700123 final StorageEventListener mCallback;
124 final Handler mHandler;
Kenny Rootaf9d6672010-10-08 09:21:39 -0700125
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700126 public StorageEventListenerDelegate(StorageEventListener callback, Looper looper) {
127 mCallback = callback;
128 mHandler = new Handler(looper, this);
San Mehatb1043402010-02-05 08:26:50 -0800129 }
130
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700131 @Override
132 public boolean handleMessage(Message msg) {
133 final SomeArgs args = (SomeArgs) msg.obj;
134 switch (msg.what) {
135 case MSG_STORAGE_STATE_CHANGED:
136 mCallback.onStorageStateChanged((String) args.arg1, (String) args.arg2,
137 (String) args.arg3);
138 args.recycle();
139 return true;
140 case MSG_VOLUME_STATE_CHANGED:
141 mCallback.onVolumeStateChanged((VolumeInfo) args.arg1, args.argi2, args.argi3);
142 args.recycle();
143 return true;
Jeff Sharkey50a05452015-04-29 11:24:52 -0700144 case MSG_VOLUME_RECORD_CHANGED:
145 mCallback.onVolumeRecordChanged((VolumeRecord) args.arg1);
146 args.recycle();
147 return true;
148 case MSG_VOLUME_FORGOTTEN:
149 mCallback.onVolumeForgotten((String) args.arg1);
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700150 args.recycle();
151 return true;
Jeff Sharkey620b32b2015-04-23 19:36:02 -0700152 case MSG_DISK_SCANNED:
153 mCallback.onDiskScanned((DiskInfo) args.arg1, args.argi2);
Jeff Sharkey7e92ef32015-04-17 17:35:07 -0700154 args.recycle();
155 return true;
Makoto Onuki9dc575d2015-06-12 16:10:25 -0700156 case MSG_DISK_DESTROYED:
157 mCallback.onDiskDestroyed((DiskInfo) args.arg1);
158 args.recycle();
159 return true;
San Mehatb1043402010-02-05 08:26:50 -0800160 }
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700161 args.recycle();
162 return false;
163 }
164
165 @Override
166 public void onUsbMassStorageConnectionChanged(boolean connected) throws RemoteException {
167 // Ignored
168 }
169
170 @Override
171 public void onStorageStateChanged(String path, String oldState, String newState) {
172 final SomeArgs args = SomeArgs.obtain();
173 args.arg1 = path;
174 args.arg2 = oldState;
175 args.arg3 = newState;
176 mHandler.obtainMessage(MSG_STORAGE_STATE_CHANGED, args).sendToTarget();
177 }
178
179 @Override
180 public void onVolumeStateChanged(VolumeInfo vol, int oldState, int newState) {
181 final SomeArgs args = SomeArgs.obtain();
182 args.arg1 = vol;
183 args.argi2 = oldState;
184 args.argi3 = newState;
185 mHandler.obtainMessage(MSG_VOLUME_STATE_CHANGED, args).sendToTarget();
San Mehatb1043402010-02-05 08:26:50 -0800186 }
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700187
188 @Override
Jeff Sharkey50a05452015-04-29 11:24:52 -0700189 public void onVolumeRecordChanged(VolumeRecord rec) {
190 final SomeArgs args = SomeArgs.obtain();
191 args.arg1 = rec;
192 mHandler.obtainMessage(MSG_VOLUME_RECORD_CHANGED, args).sendToTarget();
193 }
194
195 @Override
196 public void onVolumeForgotten(String fsUuid) {
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700197 final SomeArgs args = SomeArgs.obtain();
Jeff Sharkeyb36586a2015-04-27 08:42:28 -0700198 args.arg1 = fsUuid;
Jeff Sharkey50a05452015-04-29 11:24:52 -0700199 mHandler.obtainMessage(MSG_VOLUME_FORGOTTEN, args).sendToTarget();
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700200 }
Jeff Sharkey7e92ef32015-04-17 17:35:07 -0700201
202 @Override
Jeff Sharkey620b32b2015-04-23 19:36:02 -0700203 public void onDiskScanned(DiskInfo disk, int volumeCount) {
Jeff Sharkey7e92ef32015-04-17 17:35:07 -0700204 final SomeArgs args = SomeArgs.obtain();
205 args.arg1 = disk;
Jeff Sharkey620b32b2015-04-23 19:36:02 -0700206 args.argi2 = volumeCount;
207 mHandler.obtainMessage(MSG_DISK_SCANNED, args).sendToTarget();
Jeff Sharkey7e92ef32015-04-17 17:35:07 -0700208 }
Makoto Onuki9dc575d2015-06-12 16:10:25 -0700209
210 @Override
211 public void onDiskDestroyed(DiskInfo disk) throws RemoteException {
212 final SomeArgs args = SomeArgs.obtain();
213 args.arg1 = disk;
214 mHandler.obtainMessage(MSG_DISK_DESTROYED, args).sendToTarget();
215 }
San Mehatb1043402010-02-05 08:26:50 -0800216 }
217
218 /**
Kenny Roota02b8b02010-08-05 16:14:17 -0700219 * Binder listener for OBB action results.
220 */
Kenny Root05105f72010-09-22 17:29:43 -0700221 private final ObbActionListener mObbActionListener = new ObbActionListener();
222
223 private class ObbActionListener extends IObbActionListener.Stub {
Gilles Debunne37051cd2011-05-25 16:27:13 -0700224 @SuppressWarnings("hiding")
Kenny Rootaf9d6672010-10-08 09:21:39 -0700225 private SparseArray<ObbListenerDelegate> mListeners = new SparseArray<ObbListenerDelegate>();
Kenny Root05105f72010-09-22 17:29:43 -0700226
Kenny Roota02b8b02010-08-05 16:14:17 -0700227 @Override
Gilles Debunne37051cd2011-05-25 16:27:13 -0700228 public void onObbResult(String filename, int nonce, int status) {
Kenny Rootaf9d6672010-10-08 09:21:39 -0700229 final ObbListenerDelegate delegate;
Kenny Root05105f72010-09-22 17:29:43 -0700230 synchronized (mListeners) {
Kenny Rootaf9d6672010-10-08 09:21:39 -0700231 delegate = mListeners.get(nonce);
232 if (delegate != null) {
233 mListeners.remove(nonce);
Kenny Root05105f72010-09-22 17:29:43 -0700234 }
235 }
Kenny Rootaf9d6672010-10-08 09:21:39 -0700236
237 if (delegate != null) {
238 delegate.sendObbStateChanged(filename, status);
239 }
Kenny Root05105f72010-09-22 17:29:43 -0700240 }
241
Kenny Rootaf9d6672010-10-08 09:21:39 -0700242 public int addListener(OnObbStateChangeListener listener) {
243 final ObbListenerDelegate delegate = new ObbListenerDelegate(listener);
Kenny Root05105f72010-09-22 17:29:43 -0700244
245 synchronized (mListeners) {
Kenny Rootaf9d6672010-10-08 09:21:39 -0700246 mListeners.put(delegate.nonce, delegate);
Kenny Root05105f72010-09-22 17:29:43 -0700247 }
Kenny Rootaf9d6672010-10-08 09:21:39 -0700248
249 return delegate.nonce;
Kenny Root05105f72010-09-22 17:29:43 -0700250 }
251 }
252
Kenny Rootaf9d6672010-10-08 09:21:39 -0700253 private int getNextNonce() {
254 return mNextNonce.getAndIncrement();
255 }
256
Kenny Root05105f72010-09-22 17:29:43 -0700257 /**
258 * Private class containing sender and receiver code for StorageEvents.
259 */
260 private class ObbListenerDelegate {
261 private final WeakReference<OnObbStateChangeListener> mObbEventListenerRef;
262 private final Handler mHandler;
263
Kenny Rootaf9d6672010-10-08 09:21:39 -0700264 private final int nonce;
265
Kenny Root05105f72010-09-22 17:29:43 -0700266 ObbListenerDelegate(OnObbStateChangeListener listener) {
Kenny Rootaf9d6672010-10-08 09:21:39 -0700267 nonce = getNextNonce();
Kenny Root05105f72010-09-22 17:29:43 -0700268 mObbEventListenerRef = new WeakReference<OnObbStateChangeListener>(listener);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700269 mHandler = new Handler(mLooper) {
Kenny Root05105f72010-09-22 17:29:43 -0700270 @Override
271 public void handleMessage(Message msg) {
Gilles Debunne37051cd2011-05-25 16:27:13 -0700272 final OnObbStateChangeListener changeListener = getListener();
273 if (changeListener == null) {
Kenny Root05105f72010-09-22 17:29:43 -0700274 return;
275 }
276
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700277 changeListener.onObbStateChange((String) msg.obj, msg.arg1);
Kenny Root05105f72010-09-22 17:29:43 -0700278 }
279 };
280 }
281
282 OnObbStateChangeListener getListener() {
283 if (mObbEventListenerRef == null) {
284 return null;
285 }
286 return mObbEventListenerRef.get();
287 }
288
Kenny Rootaf9d6672010-10-08 09:21:39 -0700289 void sendObbStateChanged(String path, int state) {
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700290 mHandler.obtainMessage(0, state, 0, path).sendToTarget();
San Mehatb1043402010-02-05 08:26:50 -0800291 }
292 }
293
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700294 /** {@hide} */
Jeff Sharkey50a05452015-04-29 11:24:52 -0700295 @Deprecated
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700296 public static StorageManager from(Context context) {
Jeff Sharkey50a05452015-04-29 11:24:52 -0700297 return context.getSystemService(StorageManager.class);
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700298 }
299
San Mehatb1043402010-02-05 08:26:50 -0800300 /**
301 * Constructs a StorageManager object through which an application can
302 * can communicate with the systems mount service.
Daichi Hirono9e8d9e22015-11-13 14:37:00 +0900303 *
Jeff Smitha45746e2012-07-19 14:19:24 -0500304 * @param tgtLooper The {@link android.os.Looper} which events will be received on.
San Mehatb1043402010-02-05 08:26:50 -0800305 *
306 * <p>Applications can get instance of this class by calling
307 * {@link android.content.Context#getSystemService(java.lang.String)} with an argument
308 * of {@link android.content.Context#STORAGE_SERVICE}.
309 *
310 * @hide
311 */
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700312 public StorageManager(Context context, Looper looper) {
Jeff Sharkey48877892015-03-18 11:27:19 -0700313 mContext = context;
314 mResolver = context.getContentResolver();
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700315 mLooper = looper;
San Mehatb1043402010-02-05 08:26:50 -0800316 mMountService = IMountService.Stub.asInterface(ServiceManager.getService("mount"));
317 if (mMountService == null) {
Jeff Sharkeyb2b9ab82015-04-05 21:10:42 -0700318 throw new IllegalStateException("Failed to find running mount service");
San Mehatb1043402010-02-05 08:26:50 -0800319 }
San Mehatb1043402010-02-05 08:26:50 -0800320 }
321
San Mehatb1043402010-02-05 08:26:50 -0800322 /**
323 * Registers a {@link android.os.storage.StorageEventListener StorageEventListener}.
324 *
325 * @param listener A {@link android.os.storage.StorageEventListener StorageEventListener} object.
326 *
Kenny Rootec7c9ff2011-01-17 09:11:21 -0800327 * @hide
San Mehatb1043402010-02-05 08:26:50 -0800328 */
329 public void registerListener(StorageEventListener listener) {
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700330 synchronized (mDelegates) {
331 final StorageEventListenerDelegate delegate = new StorageEventListenerDelegate(listener,
332 mLooper);
333 try {
334 mMountService.registerListener(delegate);
335 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700336 throw e.rethrowFromSystemServer();
Chuanxia Dong6614bb62012-05-29 12:28:24 +0800337 }
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700338 mDelegates.add(delegate);
San Mehatb1043402010-02-05 08:26:50 -0800339 }
340 }
341
342 /**
343 * Unregisters a {@link android.os.storage.StorageEventListener StorageEventListener}.
344 *
345 * @param listener A {@link android.os.storage.StorageEventListener StorageEventListener} object.
346 *
Kenny Rootec7c9ff2011-01-17 09:11:21 -0800347 * @hide
San Mehatb1043402010-02-05 08:26:50 -0800348 */
349 public void unregisterListener(StorageEventListener listener) {
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700350 synchronized (mDelegates) {
351 for (Iterator<StorageEventListenerDelegate> i = mDelegates.iterator(); i.hasNext();) {
352 final StorageEventListenerDelegate delegate = i.next();
353 if (delegate.mCallback == listener) {
354 try {
355 mMountService.unregisterListener(delegate);
356 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700357 throw e.rethrowFromSystemServer();
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700358 }
359 i.remove();
360 }
361 }
San Mehatb1043402010-02-05 08:26:50 -0800362 }
San Mehatb1043402010-02-05 08:26:50 -0800363 }
364
365 /**
366 * Enables USB Mass Storage (UMS) on the device.
Kenny Rootec7c9ff2011-01-17 09:11:21 -0800367 *
368 * @hide
San Mehatb1043402010-02-05 08:26:50 -0800369 */
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700370 @Deprecated
Suchi Amalapurapu0eec21d2010-02-25 17:07:14 -0800371 public void enableUsbMassStorage() {
San Mehatb1043402010-02-05 08:26:50 -0800372 }
373
374 /**
375 * Disables USB Mass Storage (UMS) on the device.
Kenny Rootec7c9ff2011-01-17 09:11:21 -0800376 *
377 * @hide
San Mehatb1043402010-02-05 08:26:50 -0800378 */
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700379 @Deprecated
Suchi Amalapurapu0eec21d2010-02-25 17:07:14 -0800380 public void disableUsbMassStorage() {
San Mehatb1043402010-02-05 08:26:50 -0800381 }
382
383 /**
384 * Query if a USB Mass Storage (UMS) host is connected.
385 * @return true if UMS host is connected.
Kenny Rootec7c9ff2011-01-17 09:11:21 -0800386 *
387 * @hide
San Mehatb1043402010-02-05 08:26:50 -0800388 */
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700389 @Deprecated
San Mehatb1043402010-02-05 08:26:50 -0800390 public boolean isUsbMassStorageConnected() {
San Mehatb1043402010-02-05 08:26:50 -0800391 return false;
392 }
393
394 /**
395 * Query if a USB Mass Storage (UMS) is enabled on the device.
396 * @return true if UMS host is enabled.
Kenny Rootec7c9ff2011-01-17 09:11:21 -0800397 *
398 * @hide
San Mehatb1043402010-02-05 08:26:50 -0800399 */
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700400 @Deprecated
San Mehatb1043402010-02-05 08:26:50 -0800401 public boolean isUsbMassStorageEnabled() {
San Mehatb1043402010-02-05 08:26:50 -0800402 return false;
403 }
Kenny Root02c87302010-07-01 08:10:18 -0700404
405 /**
Kenny Roota02b8b02010-08-05 16:14:17 -0700406 * Mount an Opaque Binary Blob (OBB) file. If a <code>key</code> is
407 * specified, it is supplied to the mounting process to be used in any
408 * encryption used in the OBB.
409 * <p>
Kenny Root05105f72010-09-22 17:29:43 -0700410 * The OBB will remain mounted for as long as the StorageManager reference
411 * is held by the application. As soon as this reference is lost, the OBBs
Kenny Rootaf9d6672010-10-08 09:21:39 -0700412 * in use will be unmounted. The {@link OnObbStateChangeListener} registered
413 * with this call will receive the success or failure of this operation.
Kenny Root05105f72010-09-22 17:29:43 -0700414 * <p>
Kenny Roota02b8b02010-08-05 16:14:17 -0700415 * <em>Note:</em> you can only mount OBB files for which the OBB tag on the
416 * file matches a package ID that is owned by the calling program's UID.
Kenny Root05105f72010-09-22 17:29:43 -0700417 * That is, shared UID applications can attempt to mount any other
Kenny Roota02b8b02010-08-05 16:14:17 -0700418 * application's OBB that shares its UID.
Daichi Hirono9e8d9e22015-11-13 14:37:00 +0900419 *
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700420 * @param rawPath the path to the OBB file
Kenny Root05105f72010-09-22 17:29:43 -0700421 * @param key secret used to encrypt the OBB; may be <code>null</code> if no
422 * encryption was used on the OBB.
Kenny Rootaf9d6672010-10-08 09:21:39 -0700423 * @param listener will receive the success or failure of the operation
Kenny Roota02b8b02010-08-05 16:14:17 -0700424 * @return whether the mount call was successfully queued or not
Kenny Root02c87302010-07-01 08:10:18 -0700425 */
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700426 public boolean mountObb(String rawPath, String key, OnObbStateChangeListener listener) {
427 Preconditions.checkNotNull(rawPath, "rawPath cannot be null");
428 Preconditions.checkNotNull(listener, "listener cannot be null");
Kenny Rootaf9d6672010-10-08 09:21:39 -0700429
Kenny Root02c87302010-07-01 08:10:18 -0700430 try {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700431 final String canonicalPath = new File(rawPath).getCanonicalPath();
Kenny Rootaf9d6672010-10-08 09:21:39 -0700432 final int nonce = mObbActionListener.addListener(listener);
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700433 mMountService.mountObb(rawPath, canonicalPath, key, mObbActionListener, nonce);
Kenny Roota02b8b02010-08-05 16:14:17 -0700434 return true;
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700435 } catch (IOException e) {
436 throw new IllegalArgumentException("Failed to resolve path: " + rawPath, e);
Kenny Root02c87302010-07-01 08:10:18 -0700437 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700438 throw e.rethrowFromSystemServer();
Kenny Root02c87302010-07-01 08:10:18 -0700439 }
Kenny Root02c87302010-07-01 08:10:18 -0700440 }
441
442 /**
Kenny Root05105f72010-09-22 17:29:43 -0700443 * Unmount an Opaque Binary Blob (OBB) file asynchronously. If the
444 * <code>force</code> flag is true, it will kill any application needed to
445 * unmount the given OBB (even the calling application).
446 * <p>
Kenny Rootaf9d6672010-10-08 09:21:39 -0700447 * The {@link OnObbStateChangeListener} registered with this call will
448 * receive the success or failure of this operation.
Kenny Roota02b8b02010-08-05 16:14:17 -0700449 * <p>
450 * <em>Note:</em> you can only mount OBB files for which the OBB tag on the
451 * file matches a package ID that is owned by the calling program's UID.
452 * That is, shared UID applications can obtain access to any other
453 * application's OBB that shares its UID.
Kenny Root02ca31f2010-08-12 07:36:02 -0700454 * <p>
Daichi Hirono9e8d9e22015-11-13 14:37:00 +0900455 *
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700456 * @param rawPath path to the OBB file
Kenny Roota02b8b02010-08-05 16:14:17 -0700457 * @param force whether to kill any programs using this in order to unmount
458 * it
Kenny Rootaf9d6672010-10-08 09:21:39 -0700459 * @param listener will receive the success or failure of the operation
Kenny Roota02b8b02010-08-05 16:14:17 -0700460 * @return whether the unmount call was successfully queued or not
Kenny Root02c87302010-07-01 08:10:18 -0700461 */
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700462 public boolean unmountObb(String rawPath, boolean force, OnObbStateChangeListener listener) {
463 Preconditions.checkNotNull(rawPath, "rawPath cannot be null");
464 Preconditions.checkNotNull(listener, "listener cannot be null");
Kenny Rootaf9d6672010-10-08 09:21:39 -0700465
Kenny Root02c87302010-07-01 08:10:18 -0700466 try {
Kenny Rootaf9d6672010-10-08 09:21:39 -0700467 final int nonce = mObbActionListener.addListener(listener);
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700468 mMountService.unmountObb(rawPath, force, mObbActionListener, nonce);
Kenny Roota02b8b02010-08-05 16:14:17 -0700469 return true;
Kenny Root02c87302010-07-01 08:10:18 -0700470 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700471 throw e.rethrowFromSystemServer();
Kenny Root02c87302010-07-01 08:10:18 -0700472 }
Kenny Root02c87302010-07-01 08:10:18 -0700473 }
474
Kenny Roota02b8b02010-08-05 16:14:17 -0700475 /**
476 * Check whether an Opaque Binary Blob (OBB) is mounted or not.
Daichi Hirono9e8d9e22015-11-13 14:37:00 +0900477 *
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700478 * @param rawPath path to OBB image
Kenny Roota02b8b02010-08-05 16:14:17 -0700479 * @return true if OBB is mounted; false if not mounted or on error
480 */
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700481 public boolean isObbMounted(String rawPath) {
482 Preconditions.checkNotNull(rawPath, "rawPath cannot be null");
Kenny Rootaf9d6672010-10-08 09:21:39 -0700483
Kenny Root02c87302010-07-01 08:10:18 -0700484 try {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700485 return mMountService.isObbMounted(rawPath);
Kenny Root02c87302010-07-01 08:10:18 -0700486 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700487 throw e.rethrowFromSystemServer();
Kenny Root02c87302010-07-01 08:10:18 -0700488 }
Kenny Root02c87302010-07-01 08:10:18 -0700489 }
490
491 /**
Kenny Roota02b8b02010-08-05 16:14:17 -0700492 * Check the mounted path of an Opaque Binary Blob (OBB) file. This will
493 * give you the path to where you can obtain access to the internals of the
494 * OBB.
Daichi Hirono9e8d9e22015-11-13 14:37:00 +0900495 *
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700496 * @param rawPath path to OBB image
Kenny Roota02b8b02010-08-05 16:14:17 -0700497 * @return absolute path to mounted OBB image data or <code>null</code> if
498 * not mounted or exception encountered trying to read status
Kenny Root02c87302010-07-01 08:10:18 -0700499 */
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700500 public String getMountedObbPath(String rawPath) {
501 Preconditions.checkNotNull(rawPath, "rawPath cannot be null");
Kenny Rootaf9d6672010-10-08 09:21:39 -0700502
Kenny Root02c87302010-07-01 08:10:18 -0700503 try {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700504 return mMountService.getMountedObbPath(rawPath);
Kenny Root02c87302010-07-01 08:10:18 -0700505 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700506 throw e.rethrowFromSystemServer();
Kenny Root02c87302010-07-01 08:10:18 -0700507 }
Kenny Root02c87302010-07-01 08:10:18 -0700508 }
Mike Lockwoodd967f462011-03-24 08:12:30 -0700509
Jeff Sharkey48877892015-03-18 11:27:19 -0700510 /** {@hide} */
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -0700511 public @NonNull List<DiskInfo> getDisks() {
512 try {
513 return Arrays.asList(mMountService.getDisks());
514 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700515 throw e.rethrowFromSystemServer();
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -0700516 }
517 }
518
519 /** {@hide} */
Jeff Sharkeyb2b9ab82015-04-05 21:10:42 -0700520 public @Nullable DiskInfo findDiskById(String id) {
521 Preconditions.checkNotNull(id);
522 // TODO; go directly to service to make this faster
523 for (DiskInfo disk : getDisks()) {
524 if (Objects.equals(disk.id, id)) {
525 return disk;
526 }
527 }
528 return null;
529 }
530
531 /** {@hide} */
532 public @Nullable VolumeInfo findVolumeById(String id) {
533 Preconditions.checkNotNull(id);
534 // TODO; go directly to service to make this faster
535 for (VolumeInfo vol : getVolumes()) {
536 if (Objects.equals(vol.id, id)) {
537 return vol;
538 }
539 }
540 return null;
541 }
542
543 /** {@hide} */
544 public @Nullable VolumeInfo findVolumeByUuid(String fsUuid) {
545 Preconditions.checkNotNull(fsUuid);
546 // TODO; go directly to service to make this faster
547 for (VolumeInfo vol : getVolumes()) {
548 if (Objects.equals(vol.fsUuid, fsUuid)) {
549 return vol;
550 }
551 }
552 return null;
553 }
554
555 /** {@hide} */
Jeff Sharkeyb36586a2015-04-27 08:42:28 -0700556 public @Nullable VolumeRecord findRecordByUuid(String fsUuid) {
557 Preconditions.checkNotNull(fsUuid);
558 // TODO; go directly to service to make this faster
559 for (VolumeRecord rec : getVolumeRecords()) {
560 if (Objects.equals(rec.fsUuid, fsUuid)) {
561 return rec;
562 }
563 }
564 return null;
565 }
566
567 /** {@hide} */
Jeff Sharkey27de30d2015-04-18 16:20:27 -0700568 public @Nullable VolumeInfo findPrivateForEmulated(VolumeInfo emulatedVol) {
Jeff Sharkeyef10ee02015-07-05 14:17:27 -0700569 if (emulatedVol != null) {
570 return findVolumeById(emulatedVol.getId().replace("emulated", "private"));
571 } else {
572 return null;
573 }
Jeff Sharkey27de30d2015-04-18 16:20:27 -0700574 }
575
576 /** {@hide} */
577 public @Nullable VolumeInfo findEmulatedForPrivate(VolumeInfo privateVol) {
Jeff Sharkeyef10ee02015-07-05 14:17:27 -0700578 if (privateVol != null) {
579 return findVolumeById(privateVol.getId().replace("private", "emulated"));
580 } else {
581 return null;
582 }
Jeff Sharkey27de30d2015-04-18 16:20:27 -0700583 }
584
585 /** {@hide} */
Jeff Sharkey50a05452015-04-29 11:24:52 -0700586 public @Nullable VolumeInfo findVolumeByQualifiedUuid(String volumeUuid) {
587 if (Objects.equals(StorageManager.UUID_PRIVATE_INTERNAL, volumeUuid)) {
588 return findVolumeById(VolumeInfo.ID_PRIVATE_INTERNAL);
589 } else if (Objects.equals(StorageManager.UUID_PRIMARY_PHYSICAL, volumeUuid)) {
590 return getPrimaryPhysicalVolume();
591 } else {
592 return findVolumeByUuid(volumeUuid);
593 }
594 }
595
596 /** {@hide} */
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -0700597 public @NonNull List<VolumeInfo> getVolumes() {
Jeff Sharkeyb36586a2015-04-27 08:42:28 -0700598 try {
599 return Arrays.asList(mMountService.getVolumes(0));
600 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700601 throw e.rethrowFromSystemServer();
Jeff Sharkeyb36586a2015-04-27 08:42:28 -0700602 }
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700603 }
604
605 /** {@hide} */
Jeff Sharkey6dce4962015-07-03 18:08:41 -0700606 public @NonNull List<VolumeInfo> getWritablePrivateVolumes() {
607 try {
608 final ArrayList<VolumeInfo> res = new ArrayList<>();
609 for (VolumeInfo vol : mMountService.getVolumes(0)) {
610 if (vol.getType() == VolumeInfo.TYPE_PRIVATE && vol.isMountedWritable()) {
611 res.add(vol);
612 }
613 }
614 return res;
615 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700616 throw e.rethrowFromSystemServer();
Jeff Sharkey6dce4962015-07-03 18:08:41 -0700617 }
618 }
619
620 /** {@hide} */
Jeff Sharkeyb36586a2015-04-27 08:42:28 -0700621 public @NonNull List<VolumeRecord> getVolumeRecords() {
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -0700622 try {
Jeff Sharkeyb36586a2015-04-27 08:42:28 -0700623 return Arrays.asList(mMountService.getVolumeRecords(0));
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -0700624 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700625 throw e.rethrowFromSystemServer();
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -0700626 }
627 }
628
629 /** {@hide} */
Jeff Sharkey56bd3122015-04-14 10:30:34 -0700630 public @Nullable String getBestVolumeDescription(VolumeInfo vol) {
Jeff Sharkey50a05452015-04-29 11:24:52 -0700631 if (vol == null) return null;
632
Jeff Sharkeyb36586a2015-04-27 08:42:28 -0700633 // Nickname always takes precedence when defined
634 if (!TextUtils.isEmpty(vol.fsUuid)) {
635 final VolumeRecord rec = findRecordByUuid(vol.fsUuid);
Jeff Sharkeyc8406812015-05-04 12:04:09 -0700636 if (rec != null && !TextUtils.isEmpty(rec.nickname)) {
Jeff Sharkeyb36586a2015-04-27 08:42:28 -0700637 return rec.nickname;
Jeff Sharkey56bd3122015-04-14 10:30:34 -0700638 }
Jeff Sharkey59d577a2015-04-11 21:27:21 -0700639 }
Jeff Sharkeyb36586a2015-04-27 08:42:28 -0700640
641 if (!TextUtils.isEmpty(vol.getDescription())) {
642 return vol.getDescription();
643 }
644
645 if (vol.disk != null) {
646 return vol.disk.getDescription();
647 }
648
649 return null;
Jeff Sharkey59d577a2015-04-11 21:27:21 -0700650 }
651
652 /** {@hide} */
Jeff Sharkey620b32b2015-04-23 19:36:02 -0700653 public @Nullable VolumeInfo getPrimaryPhysicalVolume() {
654 final List<VolumeInfo> vols = getVolumes();
655 for (VolumeInfo vol : vols) {
656 if (vol.isPrimaryPhysical()) {
657 return vol;
658 }
659 }
660 return null;
661 }
662
663 /** {@hide} */
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700664 public void mount(String volId) {
665 try {
666 mMountService.mount(volId);
667 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700668 throw e.rethrowFromSystemServer();
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700669 }
670 }
671
672 /** {@hide} */
673 public void unmount(String volId) {
674 try {
675 mMountService.unmount(volId);
676 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700677 throw e.rethrowFromSystemServer();
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700678 }
679 }
680
681 /** {@hide} */
682 public void format(String volId) {
683 try {
684 mMountService.format(volId);
685 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700686 throw e.rethrowFromSystemServer();
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700687 }
688 }
689
690 /** {@hide} */
Jeff Sharkey9756d752015-05-14 21:07:42 -0700691 public long benchmark(String volId) {
692 try {
693 return mMountService.benchmark(volId);
694 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700695 throw e.rethrowFromSystemServer();
Jeff Sharkey9756d752015-05-14 21:07:42 -0700696 }
697 }
698
699 /** {@hide} */
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700700 public void partitionPublic(String diskId) {
701 try {
702 mMountService.partitionPublic(diskId);
703 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700704 throw e.rethrowFromSystemServer();
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700705 }
706 }
707
708 /** {@hide} */
709 public void partitionPrivate(String diskId) {
710 try {
711 mMountService.partitionPrivate(diskId);
712 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700713 throw e.rethrowFromSystemServer();
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700714 }
715 }
716
717 /** {@hide} */
718 public void partitionMixed(String diskId, int ratio) {
719 try {
720 mMountService.partitionMixed(diskId, ratio);
721 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700722 throw e.rethrowFromSystemServer();
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700723 }
724 }
725
726 /** {@hide} */
Jeff Sharkeyb42d6942015-04-28 22:25:26 -0700727 public void wipeAdoptableDisks() {
728 // We only wipe devices in "adoptable" locations, which are in a
729 // long-term stable slot/location on the device, where apps have a
730 // reasonable chance of storing sensitive data. (Apps need to go through
731 // SAF to write to transient volumes.)
732 final List<DiskInfo> disks = getDisks();
733 for (DiskInfo disk : disks) {
734 final String diskId = disk.getId();
735 if (disk.isAdoptable()) {
736 Slog.d(TAG, "Found adoptable " + diskId + "; wiping");
737 try {
738 // TODO: switch to explicit wipe command when we have it,
739 // for now rely on the fact that vfat format does a wipe
740 mMountService.partitionPublic(diskId);
741 } catch (Exception e) {
742 Slog.w(TAG, "Failed to wipe " + diskId + ", but soldiering onward", e);
743 }
744 } else {
745 Slog.d(TAG, "Ignorning non-adoptable disk " + disk.getId());
746 }
747 }
748 }
749
750 /** {@hide} */
Jeff Sharkeyb36586a2015-04-27 08:42:28 -0700751 public void setVolumeNickname(String fsUuid, String nickname) {
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700752 try {
Jeff Sharkeyb36586a2015-04-27 08:42:28 -0700753 mMountService.setVolumeNickname(fsUuid, nickname);
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700754 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700755 throw e.rethrowFromSystemServer();
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700756 }
757 }
758
759 /** {@hide} */
Jeff Sharkeyb36586a2015-04-27 08:42:28 -0700760 public void setVolumeInited(String fsUuid, boolean inited) {
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700761 try {
Jeff Sharkeyb36586a2015-04-27 08:42:28 -0700762 mMountService.setVolumeUserFlags(fsUuid, inited ? VolumeRecord.USER_FLAG_INITED : 0,
763 VolumeRecord.USER_FLAG_INITED);
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700764 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700765 throw e.rethrowFromSystemServer();
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700766 }
767 }
768
769 /** {@hide} */
Jeff Sharkeyb36586a2015-04-27 08:42:28 -0700770 public void setVolumeSnoozed(String fsUuid, boolean snoozed) {
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700771 try {
Jeff Sharkeyb36586a2015-04-27 08:42:28 -0700772 mMountService.setVolumeUserFlags(fsUuid, snoozed ? VolumeRecord.USER_FLAG_SNOOZED : 0,
773 VolumeRecord.USER_FLAG_SNOOZED);
774 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700775 throw e.rethrowFromSystemServer();
Jeff Sharkeyb36586a2015-04-27 08:42:28 -0700776 }
777 }
778
779 /** {@hide} */
780 public void forgetVolume(String fsUuid) {
781 try {
782 mMountService.forgetVolume(fsUuid);
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700783 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700784 throw e.rethrowFromSystemServer();
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700785 }
786 }
787
Jeff Sharkey275e3e42015-04-24 16:10:32 -0700788 /**
789 * This is not the API you're looking for.
790 *
791 * @see PackageManager#getPrimaryStorageCurrentVolume()
792 * @hide
793 */
Jeff Sharkey620b32b2015-04-23 19:36:02 -0700794 public String getPrimaryStorageUuid() {
795 try {
796 return mMountService.getPrimaryStorageUuid();
797 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700798 throw e.rethrowFromSystemServer();
Jeff Sharkey620b32b2015-04-23 19:36:02 -0700799 }
800 }
801
Jeff Sharkey275e3e42015-04-24 16:10:32 -0700802 /**
803 * This is not the API you're looking for.
804 *
805 * @see PackageManager#movePrimaryStorage(VolumeInfo)
806 * @hide
807 */
808 public void setPrimaryStorageUuid(String volumeUuid, IPackageMoveObserver callback) {
Jeff Sharkey620b32b2015-04-23 19:36:02 -0700809 try {
Jeff Sharkey275e3e42015-04-24 16:10:32 -0700810 mMountService.setPrimaryStorageUuid(volumeUuid, callback);
Jeff Sharkey620b32b2015-04-23 19:36:02 -0700811 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700812 throw e.rethrowFromSystemServer();
Jeff Sharkey620b32b2015-04-23 19:36:02 -0700813 }
814 }
815
816 /** {@hide} */
Jeff Sharkey48877892015-03-18 11:27:19 -0700817 public @Nullable StorageVolume getStorageVolume(File file) {
818 return getStorageVolume(getVolumeList(), file);
819 }
820
821 /** {@hide} */
822 public static @Nullable StorageVolume getStorageVolume(File file, int userId) {
Jeff Sharkey46349872015-07-28 10:49:47 -0700823 return getStorageVolume(getVolumeList(userId, 0), file);
Jeff Sharkey48877892015-03-18 11:27:19 -0700824 }
825
826 /** {@hide} */
827 private static @Nullable StorageVolume getStorageVolume(StorageVolume[] volumes, File file) {
Jeff Sharkey48877892015-03-18 11:27:19 -0700828 try {
Jeff Sharkey983294592015-07-13 10:25:31 -0700829 file = file.getCanonicalFile();
Jeff Sharkey48877892015-03-18 11:27:19 -0700830 } catch (IOException ignored) {
Jeff Sharkey983294592015-07-13 10:25:31 -0700831 return null;
Jeff Sharkey48877892015-03-18 11:27:19 -0700832 }
833 for (StorageVolume volume : volumes) {
Jeff Sharkey983294592015-07-13 10:25:31 -0700834 File volumeFile = volume.getPathFile();
835 try {
836 volumeFile = volumeFile.getCanonicalFile();
837 } catch (IOException ignored) {
838 continue;
Jeff Sharkey48877892015-03-18 11:27:19 -0700839 }
Jeff Sharkey983294592015-07-13 10:25:31 -0700840 if (FileUtils.contains(volumeFile, file)) {
Jeff Sharkey48877892015-03-18 11:27:19 -0700841 return volume;
842 }
843 }
844 return null;
845 }
846
Mike Lockwoodd967f462011-03-24 08:12:30 -0700847 /**
848 * Gets the state of a volume via its mountpoint.
849 * @hide
850 */
Jeff Sharkey48877892015-03-18 11:27:19 -0700851 @Deprecated
852 public @NonNull String getVolumeState(String mountPoint) {
853 final StorageVolume vol = getStorageVolume(new File(mountPoint));
854 if (vol != null) {
855 return vol.getState();
856 } else {
857 return Environment.MEDIA_UNKNOWN;
Mike Lockwoodd967f462011-03-24 08:12:30 -0700858 }
859 }
860
Felipe Leme04a5d402016-02-08 16:44:06 -0800861 /**
862 * Gets the list of shared/external storage volumes available to the current user.
863 *
864 * <p>It always contains the primary storage volume, plus any additional external volume(s)
865 * available in the device, such as SD cards or attached USB drives.
866 */
Jeff Sharkey48877892015-03-18 11:27:19 -0700867 public @NonNull StorageVolume[] getVolumeList() {
Jeff Sharkey46349872015-07-28 10:49:47 -0700868 return getVolumeList(mContext.getUserId(), 0);
Jeff Sharkey48877892015-03-18 11:27:19 -0700869 }
870
871 /** {@hide} */
Jeff Sharkey46349872015-07-28 10:49:47 -0700872 public static @NonNull StorageVolume[] getVolumeList(int userId, int flags) {
Jeff Sharkey48877892015-03-18 11:27:19 -0700873 final IMountService mountService = IMountService.Stub.asInterface(
874 ServiceManager.getService("mount"));
875 try {
Svetoslav7395cbf2015-07-15 15:58:01 -0700876 String packageName = ActivityThread.currentOpPackageName();
877 if (packageName == null) {
878 // Package name can be null if the activity thread is running but the app
879 // hasn't bound yet. In this case we fall back to the first package in the
880 // current UID. This works for runtime permissions as permission state is
881 // per UID and permission realted app ops are updated for all UID packages.
882 String[] packageNames = ActivityThread.getPackageManager().getPackagesForUid(
883 android.os.Process.myUid());
884 if (packageNames == null || packageNames.length <= 0) {
885 return new StorageVolume[0];
886 }
887 packageName = packageNames[0];
888 }
Jeff Sharkeycd654482016-01-08 17:42:11 -0700889 final int uid = ActivityThread.getPackageManager().getPackageUid(packageName,
Jeff Sharkeyc5967e92016-01-07 18:50:29 -0700890 PackageManager.MATCH_DEBUG_TRIAGED_MISSING, userId);
Svetoslav7395cbf2015-07-15 15:58:01 -0700891 if (uid <= 0) {
892 return new StorageVolume[0];
893 }
Jeff Sharkey46349872015-07-28 10:49:47 -0700894 return mountService.getVolumeList(uid, packageName, flags);
Jeff Sharkey48877892015-03-18 11:27:19 -0700895 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700896 throw e.rethrowFromSystemServer();
Mike Lockwoodd967f462011-03-24 08:12:30 -0700897 }
898 }
Mike Lockwood2f6a3882011-05-09 19:08:06 -0700899
900 /**
901 * Returns list of paths for all mountable volumes.
902 * @hide
903 */
Jeff Sharkey48877892015-03-18 11:27:19 -0700904 @Deprecated
905 public @NonNull String[] getVolumePaths() {
Mike Lockwood2f6a3882011-05-09 19:08:06 -0700906 StorageVolume[] volumes = getVolumeList();
Mike Lockwood2f6a3882011-05-09 19:08:06 -0700907 int count = volumes.length;
908 String[] paths = new String[count];
909 for (int i = 0; i < count; i++) {
910 paths[i] = volumes[i].getPath();
911 }
912 return paths;
913 }
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700914
Felipe Leme04a5d402016-02-08 16:44:06 -0800915 /**
916 * Gets the primary shared/external storage volume available to the current user.
917 */
Jeff Sharkey48877892015-03-18 11:27:19 -0700918 public @NonNull StorageVolume getPrimaryVolume() {
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700919 return getPrimaryVolume(getVolumeList());
920 }
921
922 /** {@hide} */
Jeff Sharkey48877892015-03-18 11:27:19 -0700923 public static @NonNull StorageVolume getPrimaryVolume(StorageVolume[] volumes) {
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700924 for (StorageVolume volume : volumes) {
925 if (volume.isPrimary()) {
926 return volume;
927 }
928 }
Jeff Sharkey48877892015-03-18 11:27:19 -0700929 throw new IllegalStateException("Missing primary storage");
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700930 }
Jeff Sharkeybe722152013-02-15 16:56:38 -0800931
Jeff Sharkey48877892015-03-18 11:27:19 -0700932 /** {@hide} */
Jeff Sharkeybe722152013-02-15 16:56:38 -0800933 private static final int DEFAULT_THRESHOLD_PERCENTAGE = 10;
934 private static final long DEFAULT_THRESHOLD_MAX_BYTES = 500 * MB_IN_BYTES;
935 private static final long DEFAULT_FULL_THRESHOLD_BYTES = MB_IN_BYTES;
936
937 /**
Jeff Sharkey742e7902014-08-16 19:09:13 -0700938 * Return the number of available bytes until the given path is considered
939 * running low on storage.
940 *
941 * @hide
942 */
943 public long getStorageBytesUntilLow(File path) {
944 return path.getUsableSpace() - getStorageFullBytes(path);
945 }
946
947 /**
Jeff Sharkeybe722152013-02-15 16:56:38 -0800948 * Return the number of available bytes at which the given path is
949 * considered running low on storage.
950 *
951 * @hide
952 */
953 public long getStorageLowBytes(File path) {
954 final long lowPercent = Settings.Global.getInt(mResolver,
955 Settings.Global.SYS_STORAGE_THRESHOLD_PERCENTAGE, DEFAULT_THRESHOLD_PERCENTAGE);
956 final long lowBytes = (path.getTotalSpace() * lowPercent) / 100;
957
958 final long maxLowBytes = Settings.Global.getLong(mResolver,
959 Settings.Global.SYS_STORAGE_THRESHOLD_MAX_BYTES, DEFAULT_THRESHOLD_MAX_BYTES);
960
961 return Math.min(lowBytes, maxLowBytes);
962 }
963
964 /**
965 * Return the number of available bytes at which the given path is
966 * considered full.
967 *
968 * @hide
969 */
970 public long getStorageFullBytes(File path) {
971 return Settings.Global.getLong(mResolver, Settings.Global.SYS_STORAGE_FULL_THRESHOLD_BYTES,
972 DEFAULT_FULL_THRESHOLD_BYTES);
973 }
Paul Lawrencee8fdc542014-05-28 07:14:17 -0700974
Jeff Sharkey50a05452015-04-29 11:24:52 -0700975 /** {@hide} */
Lenka Trochtovac4dd0212015-11-18 12:22:06 +0100976 public void createUserKey(int userId, int serialNumber, boolean ephemeral) {
Paul Crowleybcf48ed2015-04-22 13:36:59 +0100977 try {
Lenka Trochtovac4dd0212015-11-18 12:22:06 +0100978 mMountService.createUserKey(userId, serialNumber, ephemeral);
Paul Crowleybcf48ed2015-04-22 13:36:59 +0100979 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700980 throw e.rethrowFromSystemServer();
Paul Crowleybcf48ed2015-04-22 13:36:59 +0100981 }
982 }
983
984 /** {@hide} */
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -0800985 public void destroyUserKey(int userId) {
Paul Crowley7ec733f2015-05-19 12:42:00 +0100986 try {
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -0800987 mMountService.destroyUserKey(userId);
988 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700989 throw e.rethrowFromSystemServer();
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -0800990 }
991 }
992
993 /** {@hide} */
Paul Crowleyfaeb3eb2016-02-08 15:58:29 +0000994 public void unlockUserKey(int userId, int serialNumber, byte[] token, byte[] secret) {
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -0800995 try {
Paul Crowleyfaeb3eb2016-02-08 15:58:29 +0000996 mMountService.unlockUserKey(userId, serialNumber, token, secret);
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -0800997 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700998 throw e.rethrowFromSystemServer();
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -0800999 }
1000 }
1001
1002 /** {@hide} */
1003 public void lockUserKey(int userId) {
1004 try {
1005 mMountService.lockUserKey(userId);
1006 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -07001007 throw e.rethrowFromSystemServer();
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08001008 }
1009 }
1010
1011 /** {@hide} */
Jeff Sharkey47f71082016-02-01 17:03:54 -07001012 public void prepareUserStorage(String volumeUuid, int userId, int serialNumber, int flags) {
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08001013 try {
Jeff Sharkey47f71082016-02-01 17:03:54 -07001014 mMountService.prepareUserStorage(volumeUuid, userId, serialNumber, flags);
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08001015 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -07001016 throw e.rethrowFromSystemServer();
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08001017 }
1018 }
1019
1020 /** {@hide} */
1021 public boolean isUserKeyUnlocked(int userId) {
1022 try {
1023 return mMountService.isUserKeyUnlocked(userId);
Paul Crowley7ec733f2015-05-19 12:42:00 +01001024 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -07001025 throw e.rethrowFromSystemServer();
Paul Crowley7ec733f2015-05-19 12:42:00 +01001026 }
1027 }
1028
Jeff Sharkeycf3f0a12016-03-17 19:57:58 -06001029 /**
1030 * Return if data stored at the given path will be encrypted while at rest.
1031 * This can help apps avoid the overhead of double-encrypting data.
1032 */
1033 public boolean isEncrypted(File file) {
1034 if (FileUtils.contains(Environment.getDataDirectory(), file)) {
1035 return isEncrypted();
1036 } else if (FileUtils.contains(Environment.getExpandDirectory(), file)) {
1037 return true;
1038 }
1039 // TODO: extend to support shared storage
1040 return false;
1041 }
1042
Paul Lawrence20be5d62016-02-26 13:51:17 -08001043 /** {@hide}
1044 * Is this device encryptable or already encrypted?
1045 * @return true for encryptable or encrypted
1046 * false not encrypted and not encryptable
1047 */
1048 public static boolean isEncryptable() {
1049 final String state = SystemProperties.get("ro.crypto.state", "unsupported");
1050 return !"unsupported".equalsIgnoreCase(state);
1051 }
1052
1053 /** {@hide}
1054 * Is this device already encrypted?
1055 * @return true for encrypted. (Implies isEncryptable() == true)
1056 * false not encrypted
1057 */
1058 public static boolean isEncrypted() {
1059 final String state = SystemProperties.get("ro.crypto.state", "");
1060 return "encrypted".equalsIgnoreCase(state);
1061 }
1062
1063 /** {@hide}
1064 * Is this device file encrypted?
1065 * @return true for file encrypted. (Implies isEncrypted() == true)
1066 * false not encrypted or block encrypted
1067 */
1068 public static boolean isFileEncryptedNativeOnly() {
1069 if (!isEncrypted()) {
1070 return false;
1071 }
1072
1073 final String status = SystemProperties.get("ro.crypto.type", "");
1074 return "file".equalsIgnoreCase(status);
1075 }
1076
1077 /** {@hide}
1078 * Is this device block encrypted?
1079 * @return true for block encrypted. (Implies isEncrypted() == true)
1080 * false not encrypted or file encrypted
1081 */
1082 public static boolean isBlockEncrypted() {
1083 if (!isEncrypted()) {
1084 return false;
1085 }
1086 final String status = SystemProperties.get("ro.crypto.type", "");
1087 return "block".equalsIgnoreCase(status);
1088 }
1089
1090 /** {@hide}
1091 * Is this device block encrypted with credentials?
1092 * @return true for crediential block encrypted.
1093 * (Implies isBlockEncrypted() == true)
1094 * false not encrypted, file encrypted or default block encrypted
1095 */
1096 public static boolean isNonDefaultBlockEncrypted() {
1097 if (!isBlockEncrypted()) {
1098 return false;
1099 }
1100
1101 try {
1102 IMountService mountService = IMountService.Stub.asInterface(
1103 ServiceManager.getService("mount"));
1104 return mountService.getPasswordType() != CRYPT_TYPE_DEFAULT;
1105 } catch (RemoteException e) {
1106 Log.e(TAG, "Error getting encryption type");
1107 return false;
1108 }
1109 }
1110
1111 /** {@hide}
1112 * Is this device in the process of being block encrypted?
1113 * @return true for encrypting.
1114 * false otherwise
1115 * Whether device isEncrypted at this point is undefined
1116 * Note that only system services and CryptKeeper will ever see this return
1117 * true - no app will ever be launched in this state.
1118 * Also note that this state will not change without a teardown of the
1119 * framework, so no service needs to check for changes during their lifespan
1120 */
1121 public static boolean isBlockEncrypting() {
1122 final String state = SystemProperties.get("vold.encrypt_progress", "");
1123 return !"".equalsIgnoreCase(state);
1124 }
1125
1126 /** {@hide}
1127 * Is this device non default block encrypted and in the process of
1128 * prompting for credentials?
1129 * @return true for prompting for credentials.
1130 * (Implies isNonDefaultBlockEncrypted() == true)
1131 * false otherwise
1132 * Note that only system services and CryptKeeper will ever see this return
1133 * true - no app will ever be launched in this state.
1134 * Also note that this state will not change without a teardown of the
1135 * framework, so no service needs to check for changes during their lifespan
1136 */
1137 public static boolean inCryptKeeperBounce() {
1138 final String status = SystemProperties.get("vold.decrypt");
1139 return "trigger_restart_min_framework".equals(status);
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07001140 }
1141
1142 /** {@hide} */
Paul Lawrence20be5d62016-02-26 13:51:17 -08001143 public static boolean isFileEncryptedEmulatedOnly() {
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07001144 return SystemProperties.getBoolean(StorageManager.PROP_EMULATE_FBE, false);
Clara Bayarri965da392015-10-28 17:53:53 +00001145 }
1146
Paul Lawrence20be5d62016-02-26 13:51:17 -08001147 /** {@hide}
1148 * Is this device running in a file encrypted mode, either native or emulated?
1149 * @return true for file encrypted, false otherwise
1150 */
1151 public static boolean isFileEncryptedNativeOrEmulated() {
1152 return isFileEncryptedNativeOnly()
1153 || isFileEncryptedEmulatedOnly();
1154 }
1155
Clara Bayarri965da392015-10-28 17:53:53 +00001156 /** {@hide} */
Jeff Sharkey50a05452015-04-29 11:24:52 -07001157 public static File maybeTranslateEmulatedPathToInternal(File path) {
1158 final IMountService mountService = IMountService.Stub.asInterface(
1159 ServiceManager.getService("mount"));
1160 try {
1161 final VolumeInfo[] vols = mountService.getVolumes(0);
1162 for (VolumeInfo vol : vols) {
1163 if ((vol.getType() == VolumeInfo.TYPE_EMULATED
1164 || vol.getType() == VolumeInfo.TYPE_PUBLIC) && vol.isMountedReadable()) {
1165 final File internalPath = FileUtils.rewriteAfterRename(vol.getPath(),
1166 vol.getInternalPath(), path);
Marco Nelissenaa411032015-07-14 08:22:47 -07001167 if (internalPath != null && internalPath.exists()) {
Jeff Sharkey50a05452015-04-29 11:24:52 -07001168 return internalPath;
1169 }
1170 }
1171 }
Jeff Sharkeyf8880562016-02-26 13:03:01 -07001172 } catch (RemoteException e) {
1173 throw e.rethrowFromSystemServer();
Jeff Sharkey50a05452015-04-29 11:24:52 -07001174 }
1175 return path;
1176 }
1177
Daichi Hirono9e8d9e22015-11-13 14:37:00 +09001178 /** {@hide} */
1179 public ParcelFileDescriptor mountAppFuse(String name) {
1180 try {
1181 return mMountService.mountAppFuse(name);
1182 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -07001183 throw e.rethrowFromSystemServer();
Daichi Hirono9e8d9e22015-11-13 14:37:00 +09001184 }
1185 }
1186
Paul Lawrencee8fdc542014-05-28 07:14:17 -07001187 /// Consts to match the password types in cryptfs.h
1188 /** @hide */
1189 public static final int CRYPT_TYPE_PASSWORD = 0;
1190 /** @hide */
1191 public static final int CRYPT_TYPE_DEFAULT = 1;
1192 /** @hide */
1193 public static final int CRYPT_TYPE_PATTERN = 2;
1194 /** @hide */
1195 public static final int CRYPT_TYPE_PIN = 3;
Elliott Hughesf839b4f2014-09-26 12:30:47 -07001196
1197 // Constants for the data available via MountService.getField.
1198 /** @hide */
1199 public static final String SYSTEM_LOCALE_KEY = "SystemLocale";
1200 /** @hide */
1201 public static final String OWNER_INFO_KEY = "OwnerInfo";
1202 /** @hide */
1203 public static final String PATTERN_VISIBLE_KEY = "PatternVisible";
Paul Lawrenced8fdb332015-05-18 13:26:11 -07001204 /** @hide */
1205 public static final String PASSWORD_VISIBLE_KEY = "PasswordVisible";
San Mehatb1043402010-02-05 08:26:50 -08001206}