blob: 17df7080acf186410576b4e3465812e9561241db [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 Sharkey59d577a2015-04-11 21:27:21 -070038import android.text.TextUtils;
San Mehatb1043402010-02-05 08:26:50 -080039import android.util.Log;
Jeff Sharkeyb42d6942015-04-28 22:25:26 -070040import android.util.Slog;
Kenny Rootaf9d6672010-10-08 09:21:39 -070041import android.util.SparseArray;
San Mehatb1043402010-02-05 08:26:50 -080042
Jeff Sharkey7151a9a2015-04-04 15:22:37 -070043import com.android.internal.os.SomeArgs;
Jeff Sharkey4fbbda42012-09-24 18:34:07 -070044import com.android.internal.util.Preconditions;
45
46import java.io.File;
47import java.io.IOException;
Kenny Root05105f72010-09-22 17:29:43 -070048import java.lang.ref.WeakReference;
San Mehatb1043402010-02-05 08:26:50 -080049import java.util.ArrayList;
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -070050import java.util.Arrays;
Jeff Sharkey7151a9a2015-04-04 15:22:37 -070051import java.util.Iterator;
Kenny Root05105f72010-09-22 17:29:43 -070052import java.util.List;
Jeff Sharkeyb2b9ab82015-04-05 21:10:42 -070053import java.util.Objects;
Kenny Rootaf9d6672010-10-08 09:21:39 -070054import java.util.concurrent.atomic.AtomicInteger;
San Mehatb1043402010-02-05 08:26:50 -080055
56/**
Kenny Root05105f72010-09-22 17:29:43 -070057 * StorageManager is the interface to the systems storage service. The storage
58 * manager handles storage-related items such as Opaque Binary Blobs (OBBs).
59 * <p>
60 * OBBs contain a filesystem that maybe be encrypted on disk and mounted
61 * on-demand from an application. OBBs are a good way of providing large amounts
62 * of binary assets without packaging them into APKs as they may be multiple
63 * gigabytes in size. However, due to their size, they're most likely stored in
64 * a shared storage pool accessible from all programs. The system does not
65 * guarantee the security of the OBB file itself: if any program modifies the
66 * OBB, there is no guarantee that a read from that OBB will produce the
67 * expected output.
68 * <p>
San Mehatb1043402010-02-05 08:26:50 -080069 * Get an instance of this class by calling
Kenny Root05105f72010-09-22 17:29:43 -070070 * {@link android.content.Context#getSystemService(java.lang.String)} with an
71 * argument of {@link android.content.Context#STORAGE_SERVICE}.
San Mehatb1043402010-02-05 08:26:50 -080072 */
Jeff Sharkeybe722152013-02-15 16:56:38 -080073public class StorageManager {
San Mehatb1043402010-02-05 08:26:50 -080074 private static final String TAG = "StorageManager";
75
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -070076 /** {@hide} */
77 public static final String PROP_PRIMARY_PHYSICAL = "ro.vold.primary_physical";
Jeff Sharkey74acbbb2015-04-21 12:14:03 -070078 /** {@hide} */
Jeff Sharkey0d838a02015-05-13 13:54:30 -070079 public static final String PROP_HAS_ADOPTABLE = "vold.has_adoptable";
80 /** {@hide} */
Jeff Sharkey74acbbb2015-04-21 12:14:03 -070081 public static final String PROP_FORCE_ADOPTABLE = "persist.fw.force_adoptable";
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -080082 /** {@hide} */
Jeff Sharkeyba512352015-11-12 20:17:45 -080083 public static final String PROP_EMULATE_FBE = "persist.sys.emulate_fbe";
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -070084
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -070085 /** {@hide} */
Jeff Sharkey620b32b2015-04-23 19:36:02 -070086 public static final String UUID_PRIVATE_INTERNAL = null;
87 /** {@hide} */
88 public static final String UUID_PRIMARY_PHYSICAL = "primary_physical";
89
Jeff Sharkey4c099d02015-05-15 13:45:00 -070090 /** {@hide} */
91 public static final int DEBUG_FORCE_ADOPTABLE = 1 << 0;
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -080092 /** {@hide} */
93 public static final int DEBUG_EMULATE_FBE = 1 << 1;
Jeff Sharkey4c099d02015-05-15 13:45:00 -070094
Jeff Sharkey47f71082016-02-01 17:03:54 -070095 // NOTE: keep in sync with installd
Jeff Sharkey46349872015-07-28 10:49:47 -070096 /** {@hide} */
Jeff Sharkey47f71082016-02-01 17:03:54 -070097 public static final int FLAG_STORAGE_DE = 1 << 0;
98 /** {@hide} */
99 public static final int FLAG_STORAGE_CE = 1 << 1;
100
101 /** {@hide} */
102 public static final int FLAG_FOR_WRITE = 1 << 8;
Jeff Sharkey46349872015-07-28 10:49:47 -0700103
Jeff Sharkey48877892015-03-18 11:27:19 -0700104 private final Context mContext;
Jeff Sharkeybe722152013-02-15 16:56:38 -0800105 private final ContentResolver mResolver;
106
Jeff Sharkeybe722152013-02-15 16:56:38 -0800107 private final IMountService mMountService;
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700108 private final Looper mLooper;
109 private final AtomicInteger mNextNonce = new AtomicInteger(0);
San Mehatb1043402010-02-05 08:26:50 -0800110
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700111 private final ArrayList<StorageEventListenerDelegate> mDelegates = new ArrayList<>();
San Mehatb1043402010-02-05 08:26:50 -0800112
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700113 private static class StorageEventListenerDelegate extends IMountServiceListener.Stub implements
114 Handler.Callback {
115 private static final int MSG_STORAGE_STATE_CHANGED = 1;
116 private static final int MSG_VOLUME_STATE_CHANGED = 2;
Jeff Sharkey50a05452015-04-29 11:24:52 -0700117 private static final int MSG_VOLUME_RECORD_CHANGED = 3;
118 private static final int MSG_VOLUME_FORGOTTEN = 4;
119 private static final int MSG_DISK_SCANNED = 5;
Makoto Onuki9dc575d2015-06-12 16:10:25 -0700120 private static final int MSG_DISK_DESTROYED = 6;
San Mehatb1043402010-02-05 08:26:50 -0800121
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700122 final StorageEventListener mCallback;
123 final Handler mHandler;
Kenny Rootaf9d6672010-10-08 09:21:39 -0700124
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700125 public StorageEventListenerDelegate(StorageEventListener callback, Looper looper) {
126 mCallback = callback;
127 mHandler = new Handler(looper, this);
San Mehatb1043402010-02-05 08:26:50 -0800128 }
129
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700130 @Override
131 public boolean handleMessage(Message msg) {
132 final SomeArgs args = (SomeArgs) msg.obj;
133 switch (msg.what) {
134 case MSG_STORAGE_STATE_CHANGED:
135 mCallback.onStorageStateChanged((String) args.arg1, (String) args.arg2,
136 (String) args.arg3);
137 args.recycle();
138 return true;
139 case MSG_VOLUME_STATE_CHANGED:
140 mCallback.onVolumeStateChanged((VolumeInfo) args.arg1, args.argi2, args.argi3);
141 args.recycle();
142 return true;
Jeff Sharkey50a05452015-04-29 11:24:52 -0700143 case MSG_VOLUME_RECORD_CHANGED:
144 mCallback.onVolumeRecordChanged((VolumeRecord) args.arg1);
145 args.recycle();
146 return true;
147 case MSG_VOLUME_FORGOTTEN:
148 mCallback.onVolumeForgotten((String) args.arg1);
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700149 args.recycle();
150 return true;
Jeff Sharkey620b32b2015-04-23 19:36:02 -0700151 case MSG_DISK_SCANNED:
152 mCallback.onDiskScanned((DiskInfo) args.arg1, args.argi2);
Jeff Sharkey7e92ef32015-04-17 17:35:07 -0700153 args.recycle();
154 return true;
Makoto Onuki9dc575d2015-06-12 16:10:25 -0700155 case MSG_DISK_DESTROYED:
156 mCallback.onDiskDestroyed((DiskInfo) args.arg1);
157 args.recycle();
158 return true;
San Mehatb1043402010-02-05 08:26:50 -0800159 }
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700160 args.recycle();
161 return false;
162 }
163
164 @Override
165 public void onUsbMassStorageConnectionChanged(boolean connected) throws RemoteException {
166 // Ignored
167 }
168
169 @Override
170 public void onStorageStateChanged(String path, String oldState, String newState) {
171 final SomeArgs args = SomeArgs.obtain();
172 args.arg1 = path;
173 args.arg2 = oldState;
174 args.arg3 = newState;
175 mHandler.obtainMessage(MSG_STORAGE_STATE_CHANGED, args).sendToTarget();
176 }
177
178 @Override
179 public void onVolumeStateChanged(VolumeInfo vol, int oldState, int newState) {
180 final SomeArgs args = SomeArgs.obtain();
181 args.arg1 = vol;
182 args.argi2 = oldState;
183 args.argi3 = newState;
184 mHandler.obtainMessage(MSG_VOLUME_STATE_CHANGED, args).sendToTarget();
San Mehatb1043402010-02-05 08:26:50 -0800185 }
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700186
187 @Override
Jeff Sharkey50a05452015-04-29 11:24:52 -0700188 public void onVolumeRecordChanged(VolumeRecord rec) {
189 final SomeArgs args = SomeArgs.obtain();
190 args.arg1 = rec;
191 mHandler.obtainMessage(MSG_VOLUME_RECORD_CHANGED, args).sendToTarget();
192 }
193
194 @Override
195 public void onVolumeForgotten(String fsUuid) {
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700196 final SomeArgs args = SomeArgs.obtain();
Jeff Sharkeyb36586a2015-04-27 08:42:28 -0700197 args.arg1 = fsUuid;
Jeff Sharkey50a05452015-04-29 11:24:52 -0700198 mHandler.obtainMessage(MSG_VOLUME_FORGOTTEN, args).sendToTarget();
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700199 }
Jeff Sharkey7e92ef32015-04-17 17:35:07 -0700200
201 @Override
Jeff Sharkey620b32b2015-04-23 19:36:02 -0700202 public void onDiskScanned(DiskInfo disk, int volumeCount) {
Jeff Sharkey7e92ef32015-04-17 17:35:07 -0700203 final SomeArgs args = SomeArgs.obtain();
204 args.arg1 = disk;
Jeff Sharkey620b32b2015-04-23 19:36:02 -0700205 args.argi2 = volumeCount;
206 mHandler.obtainMessage(MSG_DISK_SCANNED, args).sendToTarget();
Jeff Sharkey7e92ef32015-04-17 17:35:07 -0700207 }
Makoto Onuki9dc575d2015-06-12 16:10:25 -0700208
209 @Override
210 public void onDiskDestroyed(DiskInfo disk) throws RemoteException {
211 final SomeArgs args = SomeArgs.obtain();
212 args.arg1 = disk;
213 mHandler.obtainMessage(MSG_DISK_DESTROYED, args).sendToTarget();
214 }
San Mehatb1043402010-02-05 08:26:50 -0800215 }
216
217 /**
Kenny Roota02b8b02010-08-05 16:14:17 -0700218 * Binder listener for OBB action results.
219 */
Kenny Root05105f72010-09-22 17:29:43 -0700220 private final ObbActionListener mObbActionListener = new ObbActionListener();
221
222 private class ObbActionListener extends IObbActionListener.Stub {
Gilles Debunne37051cd2011-05-25 16:27:13 -0700223 @SuppressWarnings("hiding")
Kenny Rootaf9d6672010-10-08 09:21:39 -0700224 private SparseArray<ObbListenerDelegate> mListeners = new SparseArray<ObbListenerDelegate>();
Kenny Root05105f72010-09-22 17:29:43 -0700225
Kenny Roota02b8b02010-08-05 16:14:17 -0700226 @Override
Gilles Debunne37051cd2011-05-25 16:27:13 -0700227 public void onObbResult(String filename, int nonce, int status) {
Kenny Rootaf9d6672010-10-08 09:21:39 -0700228 final ObbListenerDelegate delegate;
Kenny Root05105f72010-09-22 17:29:43 -0700229 synchronized (mListeners) {
Kenny Rootaf9d6672010-10-08 09:21:39 -0700230 delegate = mListeners.get(nonce);
231 if (delegate != null) {
232 mListeners.remove(nonce);
Kenny Root05105f72010-09-22 17:29:43 -0700233 }
234 }
Kenny Rootaf9d6672010-10-08 09:21:39 -0700235
236 if (delegate != null) {
237 delegate.sendObbStateChanged(filename, status);
238 }
Kenny Root05105f72010-09-22 17:29:43 -0700239 }
240
Kenny Rootaf9d6672010-10-08 09:21:39 -0700241 public int addListener(OnObbStateChangeListener listener) {
242 final ObbListenerDelegate delegate = new ObbListenerDelegate(listener);
Kenny Root05105f72010-09-22 17:29:43 -0700243
244 synchronized (mListeners) {
Kenny Rootaf9d6672010-10-08 09:21:39 -0700245 mListeners.put(delegate.nonce, delegate);
Kenny Root05105f72010-09-22 17:29:43 -0700246 }
Kenny Rootaf9d6672010-10-08 09:21:39 -0700247
248 return delegate.nonce;
Kenny Root05105f72010-09-22 17:29:43 -0700249 }
250 }
251
Kenny Rootaf9d6672010-10-08 09:21:39 -0700252 private int getNextNonce() {
253 return mNextNonce.getAndIncrement();
254 }
255
Kenny Root05105f72010-09-22 17:29:43 -0700256 /**
257 * Private class containing sender and receiver code for StorageEvents.
258 */
259 private class ObbListenerDelegate {
260 private final WeakReference<OnObbStateChangeListener> mObbEventListenerRef;
261 private final Handler mHandler;
262
Kenny Rootaf9d6672010-10-08 09:21:39 -0700263 private final int nonce;
264
Kenny Root05105f72010-09-22 17:29:43 -0700265 ObbListenerDelegate(OnObbStateChangeListener listener) {
Kenny Rootaf9d6672010-10-08 09:21:39 -0700266 nonce = getNextNonce();
Kenny Root05105f72010-09-22 17:29:43 -0700267 mObbEventListenerRef = new WeakReference<OnObbStateChangeListener>(listener);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700268 mHandler = new Handler(mLooper) {
Kenny Root05105f72010-09-22 17:29:43 -0700269 @Override
270 public void handleMessage(Message msg) {
Gilles Debunne37051cd2011-05-25 16:27:13 -0700271 final OnObbStateChangeListener changeListener = getListener();
272 if (changeListener == null) {
Kenny Root05105f72010-09-22 17:29:43 -0700273 return;
274 }
275
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700276 changeListener.onObbStateChange((String) msg.obj, msg.arg1);
Kenny Root05105f72010-09-22 17:29:43 -0700277 }
278 };
279 }
280
281 OnObbStateChangeListener getListener() {
282 if (mObbEventListenerRef == null) {
283 return null;
284 }
285 return mObbEventListenerRef.get();
286 }
287
Kenny Rootaf9d6672010-10-08 09:21:39 -0700288 void sendObbStateChanged(String path, int state) {
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700289 mHandler.obtainMessage(0, state, 0, path).sendToTarget();
San Mehatb1043402010-02-05 08:26:50 -0800290 }
291 }
292
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700293 /** {@hide} */
Jeff Sharkey50a05452015-04-29 11:24:52 -0700294 @Deprecated
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700295 public static StorageManager from(Context context) {
Jeff Sharkey50a05452015-04-29 11:24:52 -0700296 return context.getSystemService(StorageManager.class);
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700297 }
298
San Mehatb1043402010-02-05 08:26:50 -0800299 /**
300 * Constructs a StorageManager object through which an application can
301 * can communicate with the systems mount service.
Daichi Hirono9e8d9e22015-11-13 14:37:00 +0900302 *
Jeff Smitha45746e2012-07-19 14:19:24 -0500303 * @param tgtLooper The {@link android.os.Looper} which events will be received on.
San Mehatb1043402010-02-05 08:26:50 -0800304 *
305 * <p>Applications can get instance of this class by calling
306 * {@link android.content.Context#getSystemService(java.lang.String)} with an argument
307 * of {@link android.content.Context#STORAGE_SERVICE}.
308 *
309 * @hide
310 */
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700311 public StorageManager(Context context, Looper looper) {
Jeff Sharkey48877892015-03-18 11:27:19 -0700312 mContext = context;
313 mResolver = context.getContentResolver();
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700314 mLooper = looper;
San Mehatb1043402010-02-05 08:26:50 -0800315 mMountService = IMountService.Stub.asInterface(ServiceManager.getService("mount"));
316 if (mMountService == null) {
Jeff Sharkeyb2b9ab82015-04-05 21:10:42 -0700317 throw new IllegalStateException("Failed to find running mount service");
San Mehatb1043402010-02-05 08:26:50 -0800318 }
San Mehatb1043402010-02-05 08:26:50 -0800319 }
320
San Mehatb1043402010-02-05 08:26:50 -0800321 /**
322 * Registers a {@link android.os.storage.StorageEventListener StorageEventListener}.
323 *
324 * @param listener A {@link android.os.storage.StorageEventListener StorageEventListener} object.
325 *
Kenny Rootec7c9ff2011-01-17 09:11:21 -0800326 * @hide
San Mehatb1043402010-02-05 08:26:50 -0800327 */
328 public void registerListener(StorageEventListener listener) {
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700329 synchronized (mDelegates) {
330 final StorageEventListenerDelegate delegate = new StorageEventListenerDelegate(listener,
331 mLooper);
332 try {
333 mMountService.registerListener(delegate);
334 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700335 throw e.rethrowFromSystemServer();
Chuanxia Dong6614bb62012-05-29 12:28:24 +0800336 }
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700337 mDelegates.add(delegate);
San Mehatb1043402010-02-05 08:26:50 -0800338 }
339 }
340
341 /**
342 * Unregisters a {@link android.os.storage.StorageEventListener StorageEventListener}.
343 *
344 * @param listener A {@link android.os.storage.StorageEventListener StorageEventListener} object.
345 *
Kenny Rootec7c9ff2011-01-17 09:11:21 -0800346 * @hide
San Mehatb1043402010-02-05 08:26:50 -0800347 */
348 public void unregisterListener(StorageEventListener listener) {
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700349 synchronized (mDelegates) {
350 for (Iterator<StorageEventListenerDelegate> i = mDelegates.iterator(); i.hasNext();) {
351 final StorageEventListenerDelegate delegate = i.next();
352 if (delegate.mCallback == listener) {
353 try {
354 mMountService.unregisterListener(delegate);
355 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700356 throw e.rethrowFromSystemServer();
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700357 }
358 i.remove();
359 }
360 }
San Mehatb1043402010-02-05 08:26:50 -0800361 }
San Mehatb1043402010-02-05 08:26:50 -0800362 }
363
364 /**
365 * Enables USB Mass Storage (UMS) on the device.
Kenny Rootec7c9ff2011-01-17 09:11:21 -0800366 *
367 * @hide
San Mehatb1043402010-02-05 08:26:50 -0800368 */
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700369 @Deprecated
Suchi Amalapurapu0eec21d2010-02-25 17:07:14 -0800370 public void enableUsbMassStorage() {
San Mehatb1043402010-02-05 08:26:50 -0800371 }
372
373 /**
374 * Disables USB Mass Storage (UMS) on the device.
Kenny Rootec7c9ff2011-01-17 09:11:21 -0800375 *
376 * @hide
San Mehatb1043402010-02-05 08:26:50 -0800377 */
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700378 @Deprecated
Suchi Amalapurapu0eec21d2010-02-25 17:07:14 -0800379 public void disableUsbMassStorage() {
San Mehatb1043402010-02-05 08:26:50 -0800380 }
381
382 /**
383 * Query if a USB Mass Storage (UMS) host is connected.
384 * @return true if UMS host is connected.
Kenny Rootec7c9ff2011-01-17 09:11:21 -0800385 *
386 * @hide
San Mehatb1043402010-02-05 08:26:50 -0800387 */
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700388 @Deprecated
San Mehatb1043402010-02-05 08:26:50 -0800389 public boolean isUsbMassStorageConnected() {
San Mehatb1043402010-02-05 08:26:50 -0800390 return false;
391 }
392
393 /**
394 * Query if a USB Mass Storage (UMS) is enabled on the device.
395 * @return true if UMS host is enabled.
Kenny Rootec7c9ff2011-01-17 09:11:21 -0800396 *
397 * @hide
San Mehatb1043402010-02-05 08:26:50 -0800398 */
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700399 @Deprecated
San Mehatb1043402010-02-05 08:26:50 -0800400 public boolean isUsbMassStorageEnabled() {
San Mehatb1043402010-02-05 08:26:50 -0800401 return false;
402 }
Kenny Root02c87302010-07-01 08:10:18 -0700403
404 /**
Kenny Roota02b8b02010-08-05 16:14:17 -0700405 * Mount an Opaque Binary Blob (OBB) file. If a <code>key</code> is
406 * specified, it is supplied to the mounting process to be used in any
407 * encryption used in the OBB.
408 * <p>
Kenny Root05105f72010-09-22 17:29:43 -0700409 * The OBB will remain mounted for as long as the StorageManager reference
410 * is held by the application. As soon as this reference is lost, the OBBs
Kenny Rootaf9d6672010-10-08 09:21:39 -0700411 * in use will be unmounted. The {@link OnObbStateChangeListener} registered
412 * with this call will receive the success or failure of this operation.
Kenny Root05105f72010-09-22 17:29:43 -0700413 * <p>
Kenny Roota02b8b02010-08-05 16:14:17 -0700414 * <em>Note:</em> you can only mount OBB files for which the OBB tag on the
415 * file matches a package ID that is owned by the calling program's UID.
Kenny Root05105f72010-09-22 17:29:43 -0700416 * That is, shared UID applications can attempt to mount any other
Kenny Roota02b8b02010-08-05 16:14:17 -0700417 * application's OBB that shares its UID.
Daichi Hirono9e8d9e22015-11-13 14:37:00 +0900418 *
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700419 * @param rawPath the path to the OBB file
Kenny Root05105f72010-09-22 17:29:43 -0700420 * @param key secret used to encrypt the OBB; may be <code>null</code> if no
421 * encryption was used on the OBB.
Kenny Rootaf9d6672010-10-08 09:21:39 -0700422 * @param listener will receive the success or failure of the operation
Kenny Roota02b8b02010-08-05 16:14:17 -0700423 * @return whether the mount call was successfully queued or not
Kenny Root02c87302010-07-01 08:10:18 -0700424 */
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700425 public boolean mountObb(String rawPath, String key, OnObbStateChangeListener listener) {
426 Preconditions.checkNotNull(rawPath, "rawPath cannot be null");
427 Preconditions.checkNotNull(listener, "listener cannot be null");
Kenny Rootaf9d6672010-10-08 09:21:39 -0700428
Kenny Root02c87302010-07-01 08:10:18 -0700429 try {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700430 final String canonicalPath = new File(rawPath).getCanonicalPath();
Kenny Rootaf9d6672010-10-08 09:21:39 -0700431 final int nonce = mObbActionListener.addListener(listener);
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700432 mMountService.mountObb(rawPath, canonicalPath, key, mObbActionListener, nonce);
Kenny Roota02b8b02010-08-05 16:14:17 -0700433 return true;
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700434 } catch (IOException e) {
435 throw new IllegalArgumentException("Failed to resolve path: " + rawPath, e);
Kenny Root02c87302010-07-01 08:10:18 -0700436 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700437 throw e.rethrowFromSystemServer();
Kenny Root02c87302010-07-01 08:10:18 -0700438 }
Kenny Root02c87302010-07-01 08:10:18 -0700439 }
440
441 /**
Kenny Root05105f72010-09-22 17:29:43 -0700442 * Unmount an Opaque Binary Blob (OBB) file asynchronously. If the
443 * <code>force</code> flag is true, it will kill any application needed to
444 * unmount the given OBB (even the calling application).
445 * <p>
Kenny Rootaf9d6672010-10-08 09:21:39 -0700446 * The {@link OnObbStateChangeListener} registered with this call will
447 * receive the success or failure of this operation.
Kenny Roota02b8b02010-08-05 16:14:17 -0700448 * <p>
449 * <em>Note:</em> you can only mount OBB files for which the OBB tag on the
450 * file matches a package ID that is owned by the calling program's UID.
451 * That is, shared UID applications can obtain access to any other
452 * application's OBB that shares its UID.
Kenny Root02ca31f2010-08-12 07:36:02 -0700453 * <p>
Daichi Hirono9e8d9e22015-11-13 14:37:00 +0900454 *
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700455 * @param rawPath path to the OBB file
Kenny Roota02b8b02010-08-05 16:14:17 -0700456 * @param force whether to kill any programs using this in order to unmount
457 * it
Kenny Rootaf9d6672010-10-08 09:21:39 -0700458 * @param listener will receive the success or failure of the operation
Kenny Roota02b8b02010-08-05 16:14:17 -0700459 * @return whether the unmount call was successfully queued or not
Kenny Root02c87302010-07-01 08:10:18 -0700460 */
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700461 public boolean unmountObb(String rawPath, boolean force, OnObbStateChangeListener listener) {
462 Preconditions.checkNotNull(rawPath, "rawPath cannot be null");
463 Preconditions.checkNotNull(listener, "listener cannot be null");
Kenny Rootaf9d6672010-10-08 09:21:39 -0700464
Kenny Root02c87302010-07-01 08:10:18 -0700465 try {
Kenny Rootaf9d6672010-10-08 09:21:39 -0700466 final int nonce = mObbActionListener.addListener(listener);
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700467 mMountService.unmountObb(rawPath, force, mObbActionListener, nonce);
Kenny Roota02b8b02010-08-05 16:14:17 -0700468 return true;
Kenny Root02c87302010-07-01 08:10:18 -0700469 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700470 throw e.rethrowFromSystemServer();
Kenny Root02c87302010-07-01 08:10:18 -0700471 }
Kenny Root02c87302010-07-01 08:10:18 -0700472 }
473
Kenny Roota02b8b02010-08-05 16:14:17 -0700474 /**
475 * Check whether an Opaque Binary Blob (OBB) is mounted or not.
Daichi Hirono9e8d9e22015-11-13 14:37:00 +0900476 *
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700477 * @param rawPath path to OBB image
Kenny Roota02b8b02010-08-05 16:14:17 -0700478 * @return true if OBB is mounted; false if not mounted or on error
479 */
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700480 public boolean isObbMounted(String rawPath) {
481 Preconditions.checkNotNull(rawPath, "rawPath cannot be null");
Kenny Rootaf9d6672010-10-08 09:21:39 -0700482
Kenny Root02c87302010-07-01 08:10:18 -0700483 try {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700484 return mMountService.isObbMounted(rawPath);
Kenny Root02c87302010-07-01 08:10:18 -0700485 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700486 throw e.rethrowFromSystemServer();
Kenny Root02c87302010-07-01 08:10:18 -0700487 }
Kenny Root02c87302010-07-01 08:10:18 -0700488 }
489
490 /**
Kenny Roota02b8b02010-08-05 16:14:17 -0700491 * Check the mounted path of an Opaque Binary Blob (OBB) file. This will
492 * give you the path to where you can obtain access to the internals of the
493 * OBB.
Daichi Hirono9e8d9e22015-11-13 14:37:00 +0900494 *
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700495 * @param rawPath path to OBB image
Kenny Roota02b8b02010-08-05 16:14:17 -0700496 * @return absolute path to mounted OBB image data or <code>null</code> if
497 * not mounted or exception encountered trying to read status
Kenny Root02c87302010-07-01 08:10:18 -0700498 */
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700499 public String getMountedObbPath(String rawPath) {
500 Preconditions.checkNotNull(rawPath, "rawPath cannot be null");
Kenny Rootaf9d6672010-10-08 09:21:39 -0700501
Kenny Root02c87302010-07-01 08:10:18 -0700502 try {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700503 return mMountService.getMountedObbPath(rawPath);
Kenny Root02c87302010-07-01 08:10:18 -0700504 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700505 throw e.rethrowFromSystemServer();
Kenny Root02c87302010-07-01 08:10:18 -0700506 }
Kenny Root02c87302010-07-01 08:10:18 -0700507 }
Mike Lockwoodd967f462011-03-24 08:12:30 -0700508
Jeff Sharkey48877892015-03-18 11:27:19 -0700509 /** {@hide} */
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -0700510 public @NonNull List<DiskInfo> getDisks() {
511 try {
512 return Arrays.asList(mMountService.getDisks());
513 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700514 throw e.rethrowFromSystemServer();
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -0700515 }
516 }
517
518 /** {@hide} */
Jeff Sharkeyb2b9ab82015-04-05 21:10:42 -0700519 public @Nullable DiskInfo findDiskById(String id) {
520 Preconditions.checkNotNull(id);
521 // TODO; go directly to service to make this faster
522 for (DiskInfo disk : getDisks()) {
523 if (Objects.equals(disk.id, id)) {
524 return disk;
525 }
526 }
527 return null;
528 }
529
530 /** {@hide} */
531 public @Nullable VolumeInfo findVolumeById(String id) {
532 Preconditions.checkNotNull(id);
533 // TODO; go directly to service to make this faster
534 for (VolumeInfo vol : getVolumes()) {
535 if (Objects.equals(vol.id, id)) {
536 return vol;
537 }
538 }
539 return null;
540 }
541
542 /** {@hide} */
543 public @Nullable VolumeInfo findVolumeByUuid(String fsUuid) {
544 Preconditions.checkNotNull(fsUuid);
545 // TODO; go directly to service to make this faster
546 for (VolumeInfo vol : getVolumes()) {
547 if (Objects.equals(vol.fsUuid, fsUuid)) {
548 return vol;
549 }
550 }
551 return null;
552 }
553
554 /** {@hide} */
Jeff Sharkeyb36586a2015-04-27 08:42:28 -0700555 public @Nullable VolumeRecord findRecordByUuid(String fsUuid) {
556 Preconditions.checkNotNull(fsUuid);
557 // TODO; go directly to service to make this faster
558 for (VolumeRecord rec : getVolumeRecords()) {
559 if (Objects.equals(rec.fsUuid, fsUuid)) {
560 return rec;
561 }
562 }
563 return null;
564 }
565
566 /** {@hide} */
Jeff Sharkey27de30d2015-04-18 16:20:27 -0700567 public @Nullable VolumeInfo findPrivateForEmulated(VolumeInfo emulatedVol) {
Jeff Sharkeyef10ee02015-07-05 14:17:27 -0700568 if (emulatedVol != null) {
569 return findVolumeById(emulatedVol.getId().replace("emulated", "private"));
570 } else {
571 return null;
572 }
Jeff Sharkey27de30d2015-04-18 16:20:27 -0700573 }
574
575 /** {@hide} */
576 public @Nullable VolumeInfo findEmulatedForPrivate(VolumeInfo privateVol) {
Jeff Sharkeyef10ee02015-07-05 14:17:27 -0700577 if (privateVol != null) {
578 return findVolumeById(privateVol.getId().replace("private", "emulated"));
579 } else {
580 return null;
581 }
Jeff Sharkey27de30d2015-04-18 16:20:27 -0700582 }
583
584 /** {@hide} */
Jeff Sharkey50a05452015-04-29 11:24:52 -0700585 public @Nullable VolumeInfo findVolumeByQualifiedUuid(String volumeUuid) {
586 if (Objects.equals(StorageManager.UUID_PRIVATE_INTERNAL, volumeUuid)) {
587 return findVolumeById(VolumeInfo.ID_PRIVATE_INTERNAL);
588 } else if (Objects.equals(StorageManager.UUID_PRIMARY_PHYSICAL, volumeUuid)) {
589 return getPrimaryPhysicalVolume();
590 } else {
591 return findVolumeByUuid(volumeUuid);
592 }
593 }
594
595 /** {@hide} */
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -0700596 public @NonNull List<VolumeInfo> getVolumes() {
Jeff Sharkeyb36586a2015-04-27 08:42:28 -0700597 try {
598 return Arrays.asList(mMountService.getVolumes(0));
599 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700600 throw e.rethrowFromSystemServer();
Jeff Sharkeyb36586a2015-04-27 08:42:28 -0700601 }
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700602 }
603
604 /** {@hide} */
Jeff Sharkey6dce4962015-07-03 18:08:41 -0700605 public @NonNull List<VolumeInfo> getWritablePrivateVolumes() {
606 try {
607 final ArrayList<VolumeInfo> res = new ArrayList<>();
608 for (VolumeInfo vol : mMountService.getVolumes(0)) {
609 if (vol.getType() == VolumeInfo.TYPE_PRIVATE && vol.isMountedWritable()) {
610 res.add(vol);
611 }
612 }
613 return res;
614 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700615 throw e.rethrowFromSystemServer();
Jeff Sharkey6dce4962015-07-03 18:08:41 -0700616 }
617 }
618
619 /** {@hide} */
Jeff Sharkeyb36586a2015-04-27 08:42:28 -0700620 public @NonNull List<VolumeRecord> getVolumeRecords() {
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -0700621 try {
Jeff Sharkeyb36586a2015-04-27 08:42:28 -0700622 return Arrays.asList(mMountService.getVolumeRecords(0));
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -0700623 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700624 throw e.rethrowFromSystemServer();
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -0700625 }
626 }
627
628 /** {@hide} */
Jeff Sharkey56bd3122015-04-14 10:30:34 -0700629 public @Nullable String getBestVolumeDescription(VolumeInfo vol) {
Jeff Sharkey50a05452015-04-29 11:24:52 -0700630 if (vol == null) return null;
631
Jeff Sharkeyb36586a2015-04-27 08:42:28 -0700632 // Nickname always takes precedence when defined
633 if (!TextUtils.isEmpty(vol.fsUuid)) {
634 final VolumeRecord rec = findRecordByUuid(vol.fsUuid);
Jeff Sharkeyc8406812015-05-04 12:04:09 -0700635 if (rec != null && !TextUtils.isEmpty(rec.nickname)) {
Jeff Sharkeyb36586a2015-04-27 08:42:28 -0700636 return rec.nickname;
Jeff Sharkey56bd3122015-04-14 10:30:34 -0700637 }
Jeff Sharkey59d577a2015-04-11 21:27:21 -0700638 }
Jeff Sharkeyb36586a2015-04-27 08:42:28 -0700639
640 if (!TextUtils.isEmpty(vol.getDescription())) {
641 return vol.getDescription();
642 }
643
644 if (vol.disk != null) {
645 return vol.disk.getDescription();
646 }
647
648 return null;
Jeff Sharkey59d577a2015-04-11 21:27:21 -0700649 }
650
651 /** {@hide} */
Jeff Sharkey620b32b2015-04-23 19:36:02 -0700652 public @Nullable VolumeInfo getPrimaryPhysicalVolume() {
653 final List<VolumeInfo> vols = getVolumes();
654 for (VolumeInfo vol : vols) {
655 if (vol.isPrimaryPhysical()) {
656 return vol;
657 }
658 }
659 return null;
660 }
661
662 /** {@hide} */
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700663 public void mount(String volId) {
664 try {
665 mMountService.mount(volId);
666 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700667 throw e.rethrowFromSystemServer();
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700668 }
669 }
670
671 /** {@hide} */
672 public void unmount(String volId) {
673 try {
674 mMountService.unmount(volId);
675 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700676 throw e.rethrowFromSystemServer();
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700677 }
678 }
679
680 /** {@hide} */
681 public void format(String volId) {
682 try {
683 mMountService.format(volId);
684 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700685 throw e.rethrowFromSystemServer();
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700686 }
687 }
688
689 /** {@hide} */
Jeff Sharkey9756d752015-05-14 21:07:42 -0700690 public long benchmark(String volId) {
691 try {
692 return mMountService.benchmark(volId);
693 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700694 throw e.rethrowFromSystemServer();
Jeff Sharkey9756d752015-05-14 21:07:42 -0700695 }
696 }
697
698 /** {@hide} */
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700699 public void partitionPublic(String diskId) {
700 try {
701 mMountService.partitionPublic(diskId);
702 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700703 throw e.rethrowFromSystemServer();
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700704 }
705 }
706
707 /** {@hide} */
708 public void partitionPrivate(String diskId) {
709 try {
710 mMountService.partitionPrivate(diskId);
711 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700712 throw e.rethrowFromSystemServer();
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700713 }
714 }
715
716 /** {@hide} */
717 public void partitionMixed(String diskId, int ratio) {
718 try {
719 mMountService.partitionMixed(diskId, ratio);
720 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700721 throw e.rethrowFromSystemServer();
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700722 }
723 }
724
725 /** {@hide} */
Jeff Sharkeyb42d6942015-04-28 22:25:26 -0700726 public void wipeAdoptableDisks() {
727 // We only wipe devices in "adoptable" locations, which are in a
728 // long-term stable slot/location on the device, where apps have a
729 // reasonable chance of storing sensitive data. (Apps need to go through
730 // SAF to write to transient volumes.)
731 final List<DiskInfo> disks = getDisks();
732 for (DiskInfo disk : disks) {
733 final String diskId = disk.getId();
734 if (disk.isAdoptable()) {
735 Slog.d(TAG, "Found adoptable " + diskId + "; wiping");
736 try {
737 // TODO: switch to explicit wipe command when we have it,
738 // for now rely on the fact that vfat format does a wipe
739 mMountService.partitionPublic(diskId);
740 } catch (Exception e) {
741 Slog.w(TAG, "Failed to wipe " + diskId + ", but soldiering onward", e);
742 }
743 } else {
744 Slog.d(TAG, "Ignorning non-adoptable disk " + disk.getId());
745 }
746 }
747 }
748
749 /** {@hide} */
Jeff Sharkeyb36586a2015-04-27 08:42:28 -0700750 public void setVolumeNickname(String fsUuid, String nickname) {
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700751 try {
Jeff Sharkeyb36586a2015-04-27 08:42:28 -0700752 mMountService.setVolumeNickname(fsUuid, nickname);
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700753 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700754 throw e.rethrowFromSystemServer();
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700755 }
756 }
757
758 /** {@hide} */
Jeff Sharkeyb36586a2015-04-27 08:42:28 -0700759 public void setVolumeInited(String fsUuid, boolean inited) {
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700760 try {
Jeff Sharkeyb36586a2015-04-27 08:42:28 -0700761 mMountService.setVolumeUserFlags(fsUuid, inited ? VolumeRecord.USER_FLAG_INITED : 0,
762 VolumeRecord.USER_FLAG_INITED);
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700763 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700764 throw e.rethrowFromSystemServer();
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700765 }
766 }
767
768 /** {@hide} */
Jeff Sharkeyb36586a2015-04-27 08:42:28 -0700769 public void setVolumeSnoozed(String fsUuid, boolean snoozed) {
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700770 try {
Jeff Sharkeyb36586a2015-04-27 08:42:28 -0700771 mMountService.setVolumeUserFlags(fsUuid, snoozed ? VolumeRecord.USER_FLAG_SNOOZED : 0,
772 VolumeRecord.USER_FLAG_SNOOZED);
773 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700774 throw e.rethrowFromSystemServer();
Jeff Sharkeyb36586a2015-04-27 08:42:28 -0700775 }
776 }
777
778 /** {@hide} */
779 public void forgetVolume(String fsUuid) {
780 try {
781 mMountService.forgetVolume(fsUuid);
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700782 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700783 throw e.rethrowFromSystemServer();
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700784 }
785 }
786
Jeff Sharkey275e3e42015-04-24 16:10:32 -0700787 /**
788 * This is not the API you're looking for.
789 *
790 * @see PackageManager#getPrimaryStorageCurrentVolume()
791 * @hide
792 */
Jeff Sharkey620b32b2015-04-23 19:36:02 -0700793 public String getPrimaryStorageUuid() {
794 try {
795 return mMountService.getPrimaryStorageUuid();
796 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700797 throw e.rethrowFromSystemServer();
Jeff Sharkey620b32b2015-04-23 19:36:02 -0700798 }
799 }
800
Jeff Sharkey275e3e42015-04-24 16:10:32 -0700801 /**
802 * This is not the API you're looking for.
803 *
804 * @see PackageManager#movePrimaryStorage(VolumeInfo)
805 * @hide
806 */
807 public void setPrimaryStorageUuid(String volumeUuid, IPackageMoveObserver callback) {
Jeff Sharkey620b32b2015-04-23 19:36:02 -0700808 try {
Jeff Sharkey275e3e42015-04-24 16:10:32 -0700809 mMountService.setPrimaryStorageUuid(volumeUuid, callback);
Jeff Sharkey620b32b2015-04-23 19:36:02 -0700810 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700811 throw e.rethrowFromSystemServer();
Jeff Sharkey620b32b2015-04-23 19:36:02 -0700812 }
813 }
814
815 /** {@hide} */
Jeff Sharkey48877892015-03-18 11:27:19 -0700816 public @Nullable StorageVolume getStorageVolume(File file) {
817 return getStorageVolume(getVolumeList(), file);
818 }
819
820 /** {@hide} */
821 public static @Nullable StorageVolume getStorageVolume(File file, int userId) {
Jeff Sharkey46349872015-07-28 10:49:47 -0700822 return getStorageVolume(getVolumeList(userId, 0), file);
Jeff Sharkey48877892015-03-18 11:27:19 -0700823 }
824
825 /** {@hide} */
826 private static @Nullable StorageVolume getStorageVolume(StorageVolume[] volumes, File file) {
Jeff Sharkey48877892015-03-18 11:27:19 -0700827 try {
Jeff Sharkey983294592015-07-13 10:25:31 -0700828 file = file.getCanonicalFile();
Jeff Sharkey48877892015-03-18 11:27:19 -0700829 } catch (IOException ignored) {
Jeff Sharkey983294592015-07-13 10:25:31 -0700830 return null;
Jeff Sharkey48877892015-03-18 11:27:19 -0700831 }
832 for (StorageVolume volume : volumes) {
Jeff Sharkey983294592015-07-13 10:25:31 -0700833 File volumeFile = volume.getPathFile();
834 try {
835 volumeFile = volumeFile.getCanonicalFile();
836 } catch (IOException ignored) {
837 continue;
Jeff Sharkey48877892015-03-18 11:27:19 -0700838 }
Jeff Sharkey983294592015-07-13 10:25:31 -0700839 if (FileUtils.contains(volumeFile, file)) {
Jeff Sharkey48877892015-03-18 11:27:19 -0700840 return volume;
841 }
842 }
843 return null;
844 }
845
Mike Lockwoodd967f462011-03-24 08:12:30 -0700846 /**
847 * Gets the state of a volume via its mountpoint.
848 * @hide
849 */
Jeff Sharkey48877892015-03-18 11:27:19 -0700850 @Deprecated
851 public @NonNull String getVolumeState(String mountPoint) {
852 final StorageVolume vol = getStorageVolume(new File(mountPoint));
853 if (vol != null) {
854 return vol.getState();
855 } else {
856 return Environment.MEDIA_UNKNOWN;
Mike Lockwoodd967f462011-03-24 08:12:30 -0700857 }
858 }
859
Felipe Leme04a5d402016-02-08 16:44:06 -0800860 /**
861 * Gets the list of shared/external storage volumes available to the current user.
862 *
863 * <p>It always contains the primary storage volume, plus any additional external volume(s)
864 * available in the device, such as SD cards or attached USB drives.
865 */
Jeff Sharkey48877892015-03-18 11:27:19 -0700866 public @NonNull StorageVolume[] getVolumeList() {
Jeff Sharkey46349872015-07-28 10:49:47 -0700867 return getVolumeList(mContext.getUserId(), 0);
Jeff Sharkey48877892015-03-18 11:27:19 -0700868 }
869
870 /** {@hide} */
Jeff Sharkey46349872015-07-28 10:49:47 -0700871 public static @NonNull StorageVolume[] getVolumeList(int userId, int flags) {
Jeff Sharkey48877892015-03-18 11:27:19 -0700872 final IMountService mountService = IMountService.Stub.asInterface(
873 ServiceManager.getService("mount"));
874 try {
Svetoslav7395cbf2015-07-15 15:58:01 -0700875 String packageName = ActivityThread.currentOpPackageName();
876 if (packageName == null) {
877 // Package name can be null if the activity thread is running but the app
878 // hasn't bound yet. In this case we fall back to the first package in the
879 // current UID. This works for runtime permissions as permission state is
880 // per UID and permission realted app ops are updated for all UID packages.
881 String[] packageNames = ActivityThread.getPackageManager().getPackagesForUid(
882 android.os.Process.myUid());
883 if (packageNames == null || packageNames.length <= 0) {
884 return new StorageVolume[0];
885 }
886 packageName = packageNames[0];
887 }
Jeff Sharkeycd654482016-01-08 17:42:11 -0700888 final int uid = ActivityThread.getPackageManager().getPackageUid(packageName,
Jeff Sharkeyc5967e92016-01-07 18:50:29 -0700889 PackageManager.MATCH_DEBUG_TRIAGED_MISSING, userId);
Svetoslav7395cbf2015-07-15 15:58:01 -0700890 if (uid <= 0) {
891 return new StorageVolume[0];
892 }
Jeff Sharkey46349872015-07-28 10:49:47 -0700893 return mountService.getVolumeList(uid, packageName, flags);
Jeff Sharkey48877892015-03-18 11:27:19 -0700894 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700895 throw e.rethrowFromSystemServer();
Mike Lockwoodd967f462011-03-24 08:12:30 -0700896 }
897 }
Mike Lockwood2f6a3882011-05-09 19:08:06 -0700898
899 /**
900 * Returns list of paths for all mountable volumes.
901 * @hide
902 */
Jeff Sharkey48877892015-03-18 11:27:19 -0700903 @Deprecated
904 public @NonNull String[] getVolumePaths() {
Mike Lockwood2f6a3882011-05-09 19:08:06 -0700905 StorageVolume[] volumes = getVolumeList();
Mike Lockwood2f6a3882011-05-09 19:08:06 -0700906 int count = volumes.length;
907 String[] paths = new String[count];
908 for (int i = 0; i < count; i++) {
909 paths[i] = volumes[i].getPath();
910 }
911 return paths;
912 }
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700913
Felipe Leme04a5d402016-02-08 16:44:06 -0800914 /**
915 * Gets the primary shared/external storage volume available to the current user.
916 */
Jeff Sharkey48877892015-03-18 11:27:19 -0700917 public @NonNull StorageVolume getPrimaryVolume() {
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700918 return getPrimaryVolume(getVolumeList());
919 }
920
921 /** {@hide} */
Jeff Sharkey48877892015-03-18 11:27:19 -0700922 public static @NonNull StorageVolume getPrimaryVolume(StorageVolume[] volumes) {
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700923 for (StorageVolume volume : volumes) {
924 if (volume.isPrimary()) {
925 return volume;
926 }
927 }
Jeff Sharkey48877892015-03-18 11:27:19 -0700928 throw new IllegalStateException("Missing primary storage");
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700929 }
Jeff Sharkeybe722152013-02-15 16:56:38 -0800930
Jeff Sharkey48877892015-03-18 11:27:19 -0700931 /** {@hide} */
Jeff Sharkeybe722152013-02-15 16:56:38 -0800932 private static final int DEFAULT_THRESHOLD_PERCENTAGE = 10;
933 private static final long DEFAULT_THRESHOLD_MAX_BYTES = 500 * MB_IN_BYTES;
934 private static final long DEFAULT_FULL_THRESHOLD_BYTES = MB_IN_BYTES;
935
936 /**
Jeff Sharkey742e7902014-08-16 19:09:13 -0700937 * Return the number of available bytes until the given path is considered
938 * running low on storage.
939 *
940 * @hide
941 */
942 public long getStorageBytesUntilLow(File path) {
943 return path.getUsableSpace() - getStorageFullBytes(path);
944 }
945
946 /**
Jeff Sharkeybe722152013-02-15 16:56:38 -0800947 * Return the number of available bytes at which the given path is
948 * considered running low on storage.
949 *
950 * @hide
951 */
952 public long getStorageLowBytes(File path) {
953 final long lowPercent = Settings.Global.getInt(mResolver,
954 Settings.Global.SYS_STORAGE_THRESHOLD_PERCENTAGE, DEFAULT_THRESHOLD_PERCENTAGE);
955 final long lowBytes = (path.getTotalSpace() * lowPercent) / 100;
956
957 final long maxLowBytes = Settings.Global.getLong(mResolver,
958 Settings.Global.SYS_STORAGE_THRESHOLD_MAX_BYTES, DEFAULT_THRESHOLD_MAX_BYTES);
959
960 return Math.min(lowBytes, maxLowBytes);
961 }
962
963 /**
964 * Return the number of available bytes at which the given path is
965 * considered full.
966 *
967 * @hide
968 */
969 public long getStorageFullBytes(File path) {
970 return Settings.Global.getLong(mResolver, Settings.Global.SYS_STORAGE_FULL_THRESHOLD_BYTES,
971 DEFAULT_FULL_THRESHOLD_BYTES);
972 }
Paul Lawrencee8fdc542014-05-28 07:14:17 -0700973
Jeff Sharkey50a05452015-04-29 11:24:52 -0700974 /** {@hide} */
Lenka Trochtovac4dd0212015-11-18 12:22:06 +0100975 public void createUserKey(int userId, int serialNumber, boolean ephemeral) {
Paul Crowleybcf48ed2015-04-22 13:36:59 +0100976 try {
Lenka Trochtovac4dd0212015-11-18 12:22:06 +0100977 mMountService.createUserKey(userId, serialNumber, ephemeral);
Paul Crowleybcf48ed2015-04-22 13:36:59 +0100978 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700979 throw e.rethrowFromSystemServer();
Paul Crowleybcf48ed2015-04-22 13:36:59 +0100980 }
981 }
982
983 /** {@hide} */
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -0800984 public void destroyUserKey(int userId) {
Paul Crowley7ec733f2015-05-19 12:42:00 +0100985 try {
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -0800986 mMountService.destroyUserKey(userId);
987 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700988 throw e.rethrowFromSystemServer();
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -0800989 }
990 }
991
992 /** {@hide} */
Paul Crowleyfaeb3eb2016-02-08 15:58:29 +0000993 public void unlockUserKey(int userId, int serialNumber, byte[] token, byte[] secret) {
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -0800994 try {
Paul Crowleyfaeb3eb2016-02-08 15:58:29 +0000995 mMountService.unlockUserKey(userId, serialNumber, token, secret);
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -0800996 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700997 throw e.rethrowFromSystemServer();
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -0800998 }
999 }
1000
1001 /** {@hide} */
1002 public void lockUserKey(int userId) {
1003 try {
1004 mMountService.lockUserKey(userId);
1005 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -07001006 throw e.rethrowFromSystemServer();
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08001007 }
1008 }
1009
1010 /** {@hide} */
Jeff Sharkey47f71082016-02-01 17:03:54 -07001011 public void prepareUserStorage(String volumeUuid, int userId, int serialNumber, int flags) {
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08001012 try {
Jeff Sharkey47f71082016-02-01 17:03:54 -07001013 mMountService.prepareUserStorage(volumeUuid, userId, serialNumber, flags);
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08001014 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -07001015 throw e.rethrowFromSystemServer();
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08001016 }
1017 }
1018
1019 /** {@hide} */
1020 public boolean isUserKeyUnlocked(int userId) {
1021 try {
1022 return mMountService.isUserKeyUnlocked(userId);
Paul Crowley7ec733f2015-05-19 12:42:00 +01001023 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -07001024 throw e.rethrowFromSystemServer();
Paul Crowley7ec733f2015-05-19 12:42:00 +01001025 }
1026 }
1027
1028 /** {@hide} */
Jeff Sharkeyba512352015-11-12 20:17:45 -08001029 public static boolean isFileBasedEncryptionEnabled() {
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07001030 return isNativeFileBasedEncryptionEnabled() || isEmulatedFileBasedEncryptionEnabled();
1031 }
1032
1033 /** {@hide} */
1034 public static boolean isNativeFileBasedEncryptionEnabled() {
1035 return "file".equals(SystemProperties.get("ro.crypto.type", "none"));
1036 }
1037
1038 /** {@hide} */
1039 public static boolean isEmulatedFileBasedEncryptionEnabled() {
1040 return SystemProperties.getBoolean(StorageManager.PROP_EMULATE_FBE, false);
Clara Bayarri965da392015-10-28 17:53:53 +00001041 }
1042
1043 /** {@hide} */
Jeff Sharkey50a05452015-04-29 11:24:52 -07001044 public static File maybeTranslateEmulatedPathToInternal(File path) {
1045 final IMountService mountService = IMountService.Stub.asInterface(
1046 ServiceManager.getService("mount"));
1047 try {
1048 final VolumeInfo[] vols = mountService.getVolumes(0);
1049 for (VolumeInfo vol : vols) {
1050 if ((vol.getType() == VolumeInfo.TYPE_EMULATED
1051 || vol.getType() == VolumeInfo.TYPE_PUBLIC) && vol.isMountedReadable()) {
1052 final File internalPath = FileUtils.rewriteAfterRename(vol.getPath(),
1053 vol.getInternalPath(), path);
Marco Nelissenaa411032015-07-14 08:22:47 -07001054 if (internalPath != null && internalPath.exists()) {
Jeff Sharkey50a05452015-04-29 11:24:52 -07001055 return internalPath;
1056 }
1057 }
1058 }
Jeff Sharkeyf8880562016-02-26 13:03:01 -07001059 } catch (RemoteException e) {
1060 throw e.rethrowFromSystemServer();
Jeff Sharkey50a05452015-04-29 11:24:52 -07001061 }
1062 return path;
1063 }
1064
Daichi Hirono9e8d9e22015-11-13 14:37:00 +09001065 /** {@hide} */
1066 public ParcelFileDescriptor mountAppFuse(String name) {
1067 try {
1068 return mMountService.mountAppFuse(name);
1069 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -07001070 throw e.rethrowFromSystemServer();
Daichi Hirono9e8d9e22015-11-13 14:37:00 +09001071 }
1072 }
1073
Paul Lawrencee8fdc542014-05-28 07:14:17 -07001074 /// Consts to match the password types in cryptfs.h
1075 /** @hide */
1076 public static final int CRYPT_TYPE_PASSWORD = 0;
1077 /** @hide */
1078 public static final int CRYPT_TYPE_DEFAULT = 1;
1079 /** @hide */
1080 public static final int CRYPT_TYPE_PATTERN = 2;
1081 /** @hide */
1082 public static final int CRYPT_TYPE_PIN = 3;
Elliott Hughesf839b4f2014-09-26 12:30:47 -07001083
1084 // Constants for the data available via MountService.getField.
1085 /** @hide */
1086 public static final String SYSTEM_LOCALE_KEY = "SystemLocale";
1087 /** @hide */
1088 public static final String OWNER_INFO_KEY = "OwnerInfo";
1089 /** @hide */
1090 public static final String PATTERN_VISIBLE_KEY = "PatternVisible";
Paul Lawrenced8fdb332015-05-18 13:26:11 -07001091 /** @hide */
1092 public static final String PASSWORD_VISIBLE_KEY = "PasswordVisible";
San Mehatb1043402010-02-05 08:26:50 -08001093}