blob: c5507b9841bc6b2694ff885dc1350a9db7d5d988 [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;
Daniel Nishi690346b2016-06-17 10:21:48 -070023import android.annotation.SdkConstant;
Svet Ganov6ee871e2015-07-10 14:29:33 -070024import android.app.ActivityThread;
Jeff Sharkeybe722152013-02-15 16:56:38 -080025import android.content.ContentResolver;
Jeff Sharkeyb049e212012-09-07 23:16:01 -070026import android.content.Context;
Jeff Sharkey275e3e42015-04-24 16:10:32 -070027import android.content.pm.IPackageMoveObserver;
28import android.content.pm.PackageManager;
Jeff Sharkeyce18c812016-04-27 16:00:41 -060029import android.os.Binder;
Mike Lockwoodcba928c2011-08-17 15:58:52 -070030import android.os.Environment;
Jeff Sharkey48877892015-03-18 11:27:19 -070031import android.os.FileUtils;
San Mehatb1043402010-02-05 08:26:50 -080032import android.os.Handler;
Kenny Roota02b8b02010-08-05 16:14:17 -070033import android.os.Looper;
San Mehatb1043402010-02-05 08:26:50 -080034import android.os.Message;
Daichi Hirono9e8d9e22015-11-13 14:37:00 +090035import android.os.ParcelFileDescriptor;
Kenny Roota02b8b02010-08-05 16:14:17 -070036import android.os.RemoteException;
San Mehatb1043402010-02-05 08:26:50 -080037import android.os.ServiceManager;
Jeff Sharkeyba512352015-11-12 20:17:45 -080038import android.os.SystemProperties;
Jeff Sharkeyc02bfae2016-03-27 15:06:53 -060039import android.os.UserHandle;
Jeff Sharkeybe722152013-02-15 16:56:38 -080040import android.provider.Settings;
Jeff Sharkey59d577a2015-04-11 21:27:21 -070041import android.text.TextUtils;
San Mehatb1043402010-02-05 08:26:50 -080042import android.util.Log;
Jeff Sharkeyb42d6942015-04-28 22:25:26 -070043import android.util.Slog;
Kenny Rootaf9d6672010-10-08 09:21:39 -070044import android.util.SparseArray;
San Mehatb1043402010-02-05 08:26:50 -080045
Jeff Sharkey7151a9a2015-04-04 15:22:37 -070046import com.android.internal.os.SomeArgs;
Jeff Sharkey4fbbda42012-09-24 18:34:07 -070047import com.android.internal.util.Preconditions;
48
Felipe Leme18202e00b2016-05-12 12:56:28 -070049import java.io.BufferedReader;
Jeff Sharkey4fbbda42012-09-24 18:34:07 -070050import java.io.File;
Felipe Leme18202e00b2016-05-12 12:56:28 -070051import java.io.FileInputStream;
Jeff Sharkey4fbbda42012-09-24 18:34:07 -070052import java.io.IOException;
Felipe Leme18202e00b2016-05-12 12:56:28 -070053import java.io.InputStreamReader;
Kenny Root05105f72010-09-22 17:29:43 -070054import java.lang.ref.WeakReference;
San Mehatb1043402010-02-05 08:26:50 -080055import java.util.ArrayList;
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -070056import java.util.Arrays;
Jeff Sharkeyc02bfae2016-03-27 15:06:53 -060057import java.util.Collections;
Jeff Sharkey7151a9a2015-04-04 15:22:37 -070058import java.util.Iterator;
Kenny Root05105f72010-09-22 17:29:43 -070059import java.util.List;
Jeff Sharkeyb2b9ab82015-04-05 21:10:42 -070060import java.util.Objects;
Kenny Rootaf9d6672010-10-08 09:21:39 -070061import java.util.concurrent.atomic.AtomicInteger;
San Mehatb1043402010-02-05 08:26:50 -080062
63/**
Kenny Root05105f72010-09-22 17:29:43 -070064 * StorageManager is the interface to the systems storage service. The storage
65 * manager handles storage-related items such as Opaque Binary Blobs (OBBs).
66 * <p>
67 * OBBs contain a filesystem that maybe be encrypted on disk and mounted
68 * on-demand from an application. OBBs are a good way of providing large amounts
69 * of binary assets without packaging them into APKs as they may be multiple
70 * gigabytes in size. However, due to their size, they're most likely stored in
71 * a shared storage pool accessible from all programs. The system does not
72 * guarantee the security of the OBB file itself: if any program modifies the
73 * OBB, there is no guarantee that a read from that OBB will produce the
74 * expected output.
75 * <p>
San Mehatb1043402010-02-05 08:26:50 -080076 * Get an instance of this class by calling
Kenny Root05105f72010-09-22 17:29:43 -070077 * {@link android.content.Context#getSystemService(java.lang.String)} with an
78 * argument of {@link android.content.Context#STORAGE_SERVICE}.
San Mehatb1043402010-02-05 08:26:50 -080079 */
Jeff Sharkeybe722152013-02-15 16:56:38 -080080public class StorageManager {
San Mehatb1043402010-02-05 08:26:50 -080081 private static final String TAG = "StorageManager";
82
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -070083 /** {@hide} */
84 public static final String PROP_PRIMARY_PHYSICAL = "ro.vold.primary_physical";
Jeff Sharkey74acbbb2015-04-21 12:14:03 -070085 /** {@hide} */
Jeff Sharkey0d838a02015-05-13 13:54:30 -070086 public static final String PROP_HAS_ADOPTABLE = "vold.has_adoptable";
87 /** {@hide} */
Jeff Sharkey74acbbb2015-04-21 12:14:03 -070088 public static final String PROP_FORCE_ADOPTABLE = "persist.fw.force_adoptable";
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -080089 /** {@hide} */
Jeff Sharkeyba512352015-11-12 20:17:45 -080090 public static final String PROP_EMULATE_FBE = "persist.sys.emulate_fbe";
Jeff Sharkey33dd1562016-04-07 11:05:33 -060091 /** {@hide} */
92 public static final String PROP_SDCARDFS = "persist.sys.sdcardfs";
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -070093
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -070094 /** {@hide} */
Jeff Sharkey620b32b2015-04-23 19:36:02 -070095 public static final String UUID_PRIVATE_INTERNAL = null;
96 /** {@hide} */
97 public static final String UUID_PRIMARY_PHYSICAL = "primary_physical";
98
Daniel Nishi690346b2016-06-17 10:21:48 -070099
100 /**
101 * Activity Action: Allows the user to manage their storage. This activity provides the ability
102 * to free up space on the device by deleting data such as apps.
103 * <p>
104 * Input: Nothing.
105 * <p>
106 * Output: Nothing.
107 */
108 @SdkConstant(SdkConstant.SdkConstantType.ACTIVITY_INTENT_ACTION)
109 public static final String ACTION_MANAGE_STORAGE
110 = "android.os.storage.action.MANAGE_STORAGE";
111
Jeff Sharkey4c099d02015-05-15 13:45:00 -0700112 /** {@hide} */
113 public static final int DEBUG_FORCE_ADOPTABLE = 1 << 0;
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -0800114 /** {@hide} */
115 public static final int DEBUG_EMULATE_FBE = 1 << 1;
Jeff Sharkey33dd1562016-04-07 11:05:33 -0600116 /** {@hide} */
117 public static final int DEBUG_SDCARDFS_FORCE_ON = 1 << 2;
118 /** {@hide} */
119 public static final int DEBUG_SDCARDFS_FORCE_OFF = 1 << 3;
Jeff Sharkey4c099d02015-05-15 13:45:00 -0700120
Jeff Sharkey47f71082016-02-01 17:03:54 -0700121 // NOTE: keep in sync with installd
Jeff Sharkey46349872015-07-28 10:49:47 -0700122 /** {@hide} */
Jeff Sharkey47f71082016-02-01 17:03:54 -0700123 public static final int FLAG_STORAGE_DE = 1 << 0;
124 /** {@hide} */
125 public static final int FLAG_STORAGE_CE = 1 << 1;
126
127 /** {@hide} */
128 public static final int FLAG_FOR_WRITE = 1 << 8;
Jeff Sharkeyc02bfae2016-03-27 15:06:53 -0600129 /** {@hide} */
130 public static final int FLAG_REAL_STATE = 1 << 9;
131 /** {@hide} */
132 public static final int FLAG_INCLUDE_INVISIBLE = 1 << 10;
Jeff Sharkey46349872015-07-28 10:49:47 -0700133
Jeff Sharkey4815ed42016-05-26 09:31:04 -0600134 private static volatile IMountService sMountService = null;
Felipe Leme179923a2016-07-19 09:33:31 -0700135
136 // TODO: the location of the primary storage block varies from device to device, so we need to
137 // try the most likely candidates - a long-term solution would be a device-specific vold
138 // function that returns the calculated size.
139 private static final String[] INTERNAL_STORAGE_SIZE_PATHS = {
140 "/sys/block/mmcblk0/size",
141 "/sys/block/sda/size"
142 };
143 private static final int INTERNAL_STORAGE_SECTOR_SIZE = 512;
Jeff Sharkey4815ed42016-05-26 09:31:04 -0600144
Jeff Sharkey48877892015-03-18 11:27:19 -0700145 private final Context mContext;
Jeff Sharkeybe722152013-02-15 16:56:38 -0800146 private final ContentResolver mResolver;
147
Jeff Sharkeybe722152013-02-15 16:56:38 -0800148 private final IMountService mMountService;
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700149 private final Looper mLooper;
150 private final AtomicInteger mNextNonce = new AtomicInteger(0);
San Mehatb1043402010-02-05 08:26:50 -0800151
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700152 private final ArrayList<StorageEventListenerDelegate> mDelegates = new ArrayList<>();
San Mehatb1043402010-02-05 08:26:50 -0800153
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700154 private static class StorageEventListenerDelegate extends IMountServiceListener.Stub implements
155 Handler.Callback {
156 private static final int MSG_STORAGE_STATE_CHANGED = 1;
157 private static final int MSG_VOLUME_STATE_CHANGED = 2;
Jeff Sharkey50a05452015-04-29 11:24:52 -0700158 private static final int MSG_VOLUME_RECORD_CHANGED = 3;
159 private static final int MSG_VOLUME_FORGOTTEN = 4;
160 private static final int MSG_DISK_SCANNED = 5;
Makoto Onuki9dc575d2015-06-12 16:10:25 -0700161 private static final int MSG_DISK_DESTROYED = 6;
San Mehatb1043402010-02-05 08:26:50 -0800162
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700163 final StorageEventListener mCallback;
164 final Handler mHandler;
Kenny Rootaf9d6672010-10-08 09:21:39 -0700165
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700166 public StorageEventListenerDelegate(StorageEventListener callback, Looper looper) {
167 mCallback = callback;
168 mHandler = new Handler(looper, this);
San Mehatb1043402010-02-05 08:26:50 -0800169 }
170
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700171 @Override
172 public boolean handleMessage(Message msg) {
173 final SomeArgs args = (SomeArgs) msg.obj;
174 switch (msg.what) {
175 case MSG_STORAGE_STATE_CHANGED:
176 mCallback.onStorageStateChanged((String) args.arg1, (String) args.arg2,
177 (String) args.arg3);
178 args.recycle();
179 return true;
180 case MSG_VOLUME_STATE_CHANGED:
181 mCallback.onVolumeStateChanged((VolumeInfo) args.arg1, args.argi2, args.argi3);
182 args.recycle();
183 return true;
Jeff Sharkey50a05452015-04-29 11:24:52 -0700184 case MSG_VOLUME_RECORD_CHANGED:
185 mCallback.onVolumeRecordChanged((VolumeRecord) args.arg1);
186 args.recycle();
187 return true;
188 case MSG_VOLUME_FORGOTTEN:
189 mCallback.onVolumeForgotten((String) args.arg1);
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700190 args.recycle();
191 return true;
Jeff Sharkey620b32b2015-04-23 19:36:02 -0700192 case MSG_DISK_SCANNED:
193 mCallback.onDiskScanned((DiskInfo) args.arg1, args.argi2);
Jeff Sharkey7e92ef32015-04-17 17:35:07 -0700194 args.recycle();
195 return true;
Makoto Onuki9dc575d2015-06-12 16:10:25 -0700196 case MSG_DISK_DESTROYED:
197 mCallback.onDiskDestroyed((DiskInfo) args.arg1);
198 args.recycle();
199 return true;
San Mehatb1043402010-02-05 08:26:50 -0800200 }
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700201 args.recycle();
202 return false;
203 }
204
205 @Override
206 public void onUsbMassStorageConnectionChanged(boolean connected) throws RemoteException {
207 // Ignored
208 }
209
210 @Override
211 public void onStorageStateChanged(String path, String oldState, String newState) {
212 final SomeArgs args = SomeArgs.obtain();
213 args.arg1 = path;
214 args.arg2 = oldState;
215 args.arg3 = newState;
216 mHandler.obtainMessage(MSG_STORAGE_STATE_CHANGED, args).sendToTarget();
217 }
218
219 @Override
220 public void onVolumeStateChanged(VolumeInfo vol, int oldState, int newState) {
221 final SomeArgs args = SomeArgs.obtain();
222 args.arg1 = vol;
223 args.argi2 = oldState;
224 args.argi3 = newState;
225 mHandler.obtainMessage(MSG_VOLUME_STATE_CHANGED, args).sendToTarget();
San Mehatb1043402010-02-05 08:26:50 -0800226 }
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700227
228 @Override
Jeff Sharkey50a05452015-04-29 11:24:52 -0700229 public void onVolumeRecordChanged(VolumeRecord rec) {
230 final SomeArgs args = SomeArgs.obtain();
231 args.arg1 = rec;
232 mHandler.obtainMessage(MSG_VOLUME_RECORD_CHANGED, args).sendToTarget();
233 }
234
235 @Override
236 public void onVolumeForgotten(String fsUuid) {
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700237 final SomeArgs args = SomeArgs.obtain();
Jeff Sharkeyb36586a2015-04-27 08:42:28 -0700238 args.arg1 = fsUuid;
Jeff Sharkey50a05452015-04-29 11:24:52 -0700239 mHandler.obtainMessage(MSG_VOLUME_FORGOTTEN, args).sendToTarget();
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700240 }
Jeff Sharkey7e92ef32015-04-17 17:35:07 -0700241
242 @Override
Jeff Sharkey620b32b2015-04-23 19:36:02 -0700243 public void onDiskScanned(DiskInfo disk, int volumeCount) {
Jeff Sharkey7e92ef32015-04-17 17:35:07 -0700244 final SomeArgs args = SomeArgs.obtain();
245 args.arg1 = disk;
Jeff Sharkey620b32b2015-04-23 19:36:02 -0700246 args.argi2 = volumeCount;
247 mHandler.obtainMessage(MSG_DISK_SCANNED, args).sendToTarget();
Jeff Sharkey7e92ef32015-04-17 17:35:07 -0700248 }
Makoto Onuki9dc575d2015-06-12 16:10:25 -0700249
250 @Override
251 public void onDiskDestroyed(DiskInfo disk) throws RemoteException {
252 final SomeArgs args = SomeArgs.obtain();
253 args.arg1 = disk;
254 mHandler.obtainMessage(MSG_DISK_DESTROYED, args).sendToTarget();
255 }
San Mehatb1043402010-02-05 08:26:50 -0800256 }
257
258 /**
Kenny Roota02b8b02010-08-05 16:14:17 -0700259 * Binder listener for OBB action results.
260 */
Kenny Root05105f72010-09-22 17:29:43 -0700261 private final ObbActionListener mObbActionListener = new ObbActionListener();
262
263 private class ObbActionListener extends IObbActionListener.Stub {
Gilles Debunne37051cd2011-05-25 16:27:13 -0700264 @SuppressWarnings("hiding")
Kenny Rootaf9d6672010-10-08 09:21:39 -0700265 private SparseArray<ObbListenerDelegate> mListeners = new SparseArray<ObbListenerDelegate>();
Kenny Root05105f72010-09-22 17:29:43 -0700266
Kenny Roota02b8b02010-08-05 16:14:17 -0700267 @Override
Gilles Debunne37051cd2011-05-25 16:27:13 -0700268 public void onObbResult(String filename, int nonce, int status) {
Kenny Rootaf9d6672010-10-08 09:21:39 -0700269 final ObbListenerDelegate delegate;
Kenny Root05105f72010-09-22 17:29:43 -0700270 synchronized (mListeners) {
Kenny Rootaf9d6672010-10-08 09:21:39 -0700271 delegate = mListeners.get(nonce);
272 if (delegate != null) {
273 mListeners.remove(nonce);
Kenny Root05105f72010-09-22 17:29:43 -0700274 }
275 }
Kenny Rootaf9d6672010-10-08 09:21:39 -0700276
277 if (delegate != null) {
278 delegate.sendObbStateChanged(filename, status);
279 }
Kenny Root05105f72010-09-22 17:29:43 -0700280 }
281
Kenny Rootaf9d6672010-10-08 09:21:39 -0700282 public int addListener(OnObbStateChangeListener listener) {
283 final ObbListenerDelegate delegate = new ObbListenerDelegate(listener);
Kenny Root05105f72010-09-22 17:29:43 -0700284
285 synchronized (mListeners) {
Kenny Rootaf9d6672010-10-08 09:21:39 -0700286 mListeners.put(delegate.nonce, delegate);
Kenny Root05105f72010-09-22 17:29:43 -0700287 }
Kenny Rootaf9d6672010-10-08 09:21:39 -0700288
289 return delegate.nonce;
Kenny Root05105f72010-09-22 17:29:43 -0700290 }
291 }
292
Kenny Rootaf9d6672010-10-08 09:21:39 -0700293 private int getNextNonce() {
294 return mNextNonce.getAndIncrement();
295 }
296
Kenny Root05105f72010-09-22 17:29:43 -0700297 /**
298 * Private class containing sender and receiver code for StorageEvents.
299 */
300 private class ObbListenerDelegate {
301 private final WeakReference<OnObbStateChangeListener> mObbEventListenerRef;
302 private final Handler mHandler;
303
Kenny Rootaf9d6672010-10-08 09:21:39 -0700304 private final int nonce;
305
Kenny Root05105f72010-09-22 17:29:43 -0700306 ObbListenerDelegate(OnObbStateChangeListener listener) {
Kenny Rootaf9d6672010-10-08 09:21:39 -0700307 nonce = getNextNonce();
Kenny Root05105f72010-09-22 17:29:43 -0700308 mObbEventListenerRef = new WeakReference<OnObbStateChangeListener>(listener);
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700309 mHandler = new Handler(mLooper) {
Kenny Root05105f72010-09-22 17:29:43 -0700310 @Override
311 public void handleMessage(Message msg) {
Gilles Debunne37051cd2011-05-25 16:27:13 -0700312 final OnObbStateChangeListener changeListener = getListener();
313 if (changeListener == null) {
Kenny Root05105f72010-09-22 17:29:43 -0700314 return;
315 }
316
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700317 changeListener.onObbStateChange((String) msg.obj, msg.arg1);
Kenny Root05105f72010-09-22 17:29:43 -0700318 }
319 };
320 }
321
322 OnObbStateChangeListener getListener() {
323 if (mObbEventListenerRef == null) {
324 return null;
325 }
326 return mObbEventListenerRef.get();
327 }
328
Kenny Rootaf9d6672010-10-08 09:21:39 -0700329 void sendObbStateChanged(String path, int state) {
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700330 mHandler.obtainMessage(0, state, 0, path).sendToTarget();
San Mehatb1043402010-02-05 08:26:50 -0800331 }
332 }
333
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700334 /** {@hide} */
Jeff Sharkey50a05452015-04-29 11:24:52 -0700335 @Deprecated
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700336 public static StorageManager from(Context context) {
Jeff Sharkey50a05452015-04-29 11:24:52 -0700337 return context.getSystemService(StorageManager.class);
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700338 }
339
San Mehatb1043402010-02-05 08:26:50 -0800340 /**
341 * Constructs a StorageManager object through which an application can
342 * can communicate with the systems mount service.
Daichi Hirono9e8d9e22015-11-13 14:37:00 +0900343 *
Jeff Smitha45746e2012-07-19 14:19:24 -0500344 * @param tgtLooper The {@link android.os.Looper} which events will be received on.
San Mehatb1043402010-02-05 08:26:50 -0800345 *
346 * <p>Applications can get instance of this class by calling
347 * {@link android.content.Context#getSystemService(java.lang.String)} with an argument
348 * of {@link android.content.Context#STORAGE_SERVICE}.
349 *
350 * @hide
351 */
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700352 public StorageManager(Context context, Looper looper) {
Jeff Sharkey48877892015-03-18 11:27:19 -0700353 mContext = context;
354 mResolver = context.getContentResolver();
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700355 mLooper = looper;
San Mehatb1043402010-02-05 08:26:50 -0800356 mMountService = IMountService.Stub.asInterface(ServiceManager.getService("mount"));
357 if (mMountService == null) {
Jeff Sharkeyb2b9ab82015-04-05 21:10:42 -0700358 throw new IllegalStateException("Failed to find running mount service");
San Mehatb1043402010-02-05 08:26:50 -0800359 }
San Mehatb1043402010-02-05 08:26:50 -0800360 }
361
San Mehatb1043402010-02-05 08:26:50 -0800362 /**
363 * Registers a {@link android.os.storage.StorageEventListener StorageEventListener}.
364 *
365 * @param listener A {@link android.os.storage.StorageEventListener StorageEventListener} object.
366 *
Kenny Rootec7c9ff2011-01-17 09:11:21 -0800367 * @hide
San Mehatb1043402010-02-05 08:26:50 -0800368 */
369 public void registerListener(StorageEventListener listener) {
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700370 synchronized (mDelegates) {
371 final StorageEventListenerDelegate delegate = new StorageEventListenerDelegate(listener,
372 mLooper);
373 try {
374 mMountService.registerListener(delegate);
375 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700376 throw e.rethrowFromSystemServer();
Chuanxia Dong6614bb62012-05-29 12:28:24 +0800377 }
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700378 mDelegates.add(delegate);
San Mehatb1043402010-02-05 08:26:50 -0800379 }
380 }
381
382 /**
383 * Unregisters a {@link android.os.storage.StorageEventListener StorageEventListener}.
384 *
385 * @param listener A {@link android.os.storage.StorageEventListener StorageEventListener} object.
386 *
Kenny Rootec7c9ff2011-01-17 09:11:21 -0800387 * @hide
San Mehatb1043402010-02-05 08:26:50 -0800388 */
389 public void unregisterListener(StorageEventListener listener) {
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700390 synchronized (mDelegates) {
391 for (Iterator<StorageEventListenerDelegate> i = mDelegates.iterator(); i.hasNext();) {
392 final StorageEventListenerDelegate delegate = i.next();
393 if (delegate.mCallback == listener) {
394 try {
395 mMountService.unregisterListener(delegate);
396 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700397 throw e.rethrowFromSystemServer();
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700398 }
399 i.remove();
400 }
401 }
San Mehatb1043402010-02-05 08:26:50 -0800402 }
San Mehatb1043402010-02-05 08:26:50 -0800403 }
404
405 /**
406 * Enables USB Mass Storage (UMS) on the device.
Kenny Rootec7c9ff2011-01-17 09:11:21 -0800407 *
408 * @hide
San Mehatb1043402010-02-05 08:26:50 -0800409 */
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700410 @Deprecated
Suchi Amalapurapu0eec21d2010-02-25 17:07:14 -0800411 public void enableUsbMassStorage() {
San Mehatb1043402010-02-05 08:26:50 -0800412 }
413
414 /**
415 * Disables USB Mass Storage (UMS) on the device.
Kenny Rootec7c9ff2011-01-17 09:11:21 -0800416 *
417 * @hide
San Mehatb1043402010-02-05 08:26:50 -0800418 */
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700419 @Deprecated
Suchi Amalapurapu0eec21d2010-02-25 17:07:14 -0800420 public void disableUsbMassStorage() {
San Mehatb1043402010-02-05 08:26:50 -0800421 }
422
423 /**
424 * Query if a USB Mass Storage (UMS) host is connected.
425 * @return true if UMS host is connected.
Kenny Rootec7c9ff2011-01-17 09:11:21 -0800426 *
427 * @hide
San Mehatb1043402010-02-05 08:26:50 -0800428 */
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700429 @Deprecated
San Mehatb1043402010-02-05 08:26:50 -0800430 public boolean isUsbMassStorageConnected() {
San Mehatb1043402010-02-05 08:26:50 -0800431 return false;
432 }
433
434 /**
435 * Query if a USB Mass Storage (UMS) is enabled on the device.
436 * @return true if UMS host is enabled.
Kenny Rootec7c9ff2011-01-17 09:11:21 -0800437 *
438 * @hide
San Mehatb1043402010-02-05 08:26:50 -0800439 */
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700440 @Deprecated
San Mehatb1043402010-02-05 08:26:50 -0800441 public boolean isUsbMassStorageEnabled() {
San Mehatb1043402010-02-05 08:26:50 -0800442 return false;
443 }
Kenny Root02c87302010-07-01 08:10:18 -0700444
445 /**
Kenny Roota02b8b02010-08-05 16:14:17 -0700446 * Mount an Opaque Binary Blob (OBB) file. If a <code>key</code> is
447 * specified, it is supplied to the mounting process to be used in any
448 * encryption used in the OBB.
449 * <p>
Kenny Root05105f72010-09-22 17:29:43 -0700450 * The OBB will remain mounted for as long as the StorageManager reference
451 * is held by the application. As soon as this reference is lost, the OBBs
Kenny Rootaf9d6672010-10-08 09:21:39 -0700452 * in use will be unmounted. The {@link OnObbStateChangeListener} registered
453 * with this call will receive the success or failure of this operation.
Kenny Root05105f72010-09-22 17:29:43 -0700454 * <p>
Kenny Roota02b8b02010-08-05 16:14:17 -0700455 * <em>Note:</em> you can only mount OBB files for which the OBB tag on the
456 * file matches a package ID that is owned by the calling program's UID.
Kenny Root05105f72010-09-22 17:29:43 -0700457 * That is, shared UID applications can attempt to mount any other
Kenny Roota02b8b02010-08-05 16:14:17 -0700458 * application's OBB that shares its UID.
Daichi Hirono9e8d9e22015-11-13 14:37:00 +0900459 *
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700460 * @param rawPath the path to the OBB file
Kenny Root05105f72010-09-22 17:29:43 -0700461 * @param key secret used to encrypt the OBB; may be <code>null</code> if no
462 * encryption was used on the OBB.
Kenny Rootaf9d6672010-10-08 09:21:39 -0700463 * @param listener will receive the success or failure of the operation
Kenny Roota02b8b02010-08-05 16:14:17 -0700464 * @return whether the mount call was successfully queued or not
Kenny Root02c87302010-07-01 08:10:18 -0700465 */
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700466 public boolean mountObb(String rawPath, String key, OnObbStateChangeListener listener) {
467 Preconditions.checkNotNull(rawPath, "rawPath cannot be null");
468 Preconditions.checkNotNull(listener, "listener cannot be null");
Kenny Rootaf9d6672010-10-08 09:21:39 -0700469
Kenny Root02c87302010-07-01 08:10:18 -0700470 try {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700471 final String canonicalPath = new File(rawPath).getCanonicalPath();
Kenny Rootaf9d6672010-10-08 09:21:39 -0700472 final int nonce = mObbActionListener.addListener(listener);
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700473 mMountService.mountObb(rawPath, canonicalPath, key, mObbActionListener, nonce);
Kenny Roota02b8b02010-08-05 16:14:17 -0700474 return true;
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700475 } catch (IOException e) {
476 throw new IllegalArgumentException("Failed to resolve path: " + rawPath, e);
Kenny Root02c87302010-07-01 08:10:18 -0700477 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700478 throw e.rethrowFromSystemServer();
Kenny Root02c87302010-07-01 08:10:18 -0700479 }
Kenny Root02c87302010-07-01 08:10:18 -0700480 }
481
482 /**
Kenny Root05105f72010-09-22 17:29:43 -0700483 * Unmount an Opaque Binary Blob (OBB) file asynchronously. If the
484 * <code>force</code> flag is true, it will kill any application needed to
485 * unmount the given OBB (even the calling application).
486 * <p>
Kenny Rootaf9d6672010-10-08 09:21:39 -0700487 * The {@link OnObbStateChangeListener} registered with this call will
488 * receive the success or failure of this operation.
Kenny Roota02b8b02010-08-05 16:14:17 -0700489 * <p>
490 * <em>Note:</em> you can only mount OBB files for which the OBB tag on the
491 * file matches a package ID that is owned by the calling program's UID.
492 * That is, shared UID applications can obtain access to any other
493 * application's OBB that shares its UID.
Kenny Root02ca31f2010-08-12 07:36:02 -0700494 * <p>
Daichi Hirono9e8d9e22015-11-13 14:37:00 +0900495 *
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700496 * @param rawPath path to the OBB file
Kenny Roota02b8b02010-08-05 16:14:17 -0700497 * @param force whether to kill any programs using this in order to unmount
498 * it
Kenny Rootaf9d6672010-10-08 09:21:39 -0700499 * @param listener will receive the success or failure of the operation
Kenny Roota02b8b02010-08-05 16:14:17 -0700500 * @return whether the unmount call was successfully queued or not
Kenny Root02c87302010-07-01 08:10:18 -0700501 */
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700502 public boolean unmountObb(String rawPath, boolean force, OnObbStateChangeListener listener) {
503 Preconditions.checkNotNull(rawPath, "rawPath cannot be null");
504 Preconditions.checkNotNull(listener, "listener cannot be null");
Kenny Rootaf9d6672010-10-08 09:21:39 -0700505
Kenny Root02c87302010-07-01 08:10:18 -0700506 try {
Kenny Rootaf9d6672010-10-08 09:21:39 -0700507 final int nonce = mObbActionListener.addListener(listener);
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700508 mMountService.unmountObb(rawPath, force, mObbActionListener, nonce);
Kenny Roota02b8b02010-08-05 16:14:17 -0700509 return true;
Kenny Root02c87302010-07-01 08:10:18 -0700510 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700511 throw e.rethrowFromSystemServer();
Kenny Root02c87302010-07-01 08:10:18 -0700512 }
Kenny Root02c87302010-07-01 08:10:18 -0700513 }
514
Kenny Roota02b8b02010-08-05 16:14:17 -0700515 /**
516 * Check whether an Opaque Binary Blob (OBB) is mounted or not.
Daichi Hirono9e8d9e22015-11-13 14:37:00 +0900517 *
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700518 * @param rawPath path to OBB image
Kenny Roota02b8b02010-08-05 16:14:17 -0700519 * @return true if OBB is mounted; false if not mounted or on error
520 */
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700521 public boolean isObbMounted(String rawPath) {
522 Preconditions.checkNotNull(rawPath, "rawPath cannot be null");
Kenny Rootaf9d6672010-10-08 09:21:39 -0700523
Kenny Root02c87302010-07-01 08:10:18 -0700524 try {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700525 return mMountService.isObbMounted(rawPath);
Kenny Root02c87302010-07-01 08:10:18 -0700526 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700527 throw e.rethrowFromSystemServer();
Kenny Root02c87302010-07-01 08:10:18 -0700528 }
Kenny Root02c87302010-07-01 08:10:18 -0700529 }
530
531 /**
Kenny Roota02b8b02010-08-05 16:14:17 -0700532 * Check the mounted path of an Opaque Binary Blob (OBB) file. This will
533 * give you the path to where you can obtain access to the internals of the
534 * OBB.
Daichi Hirono9e8d9e22015-11-13 14:37:00 +0900535 *
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700536 * @param rawPath path to OBB image
Kenny Roota02b8b02010-08-05 16:14:17 -0700537 * @return absolute path to mounted OBB image data or <code>null</code> if
538 * not mounted or exception encountered trying to read status
Kenny Root02c87302010-07-01 08:10:18 -0700539 */
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700540 public String getMountedObbPath(String rawPath) {
541 Preconditions.checkNotNull(rawPath, "rawPath cannot be null");
Kenny Rootaf9d6672010-10-08 09:21:39 -0700542
Kenny Root02c87302010-07-01 08:10:18 -0700543 try {
Jeff Sharkey4fbbda42012-09-24 18:34:07 -0700544 return mMountService.getMountedObbPath(rawPath);
Kenny Root02c87302010-07-01 08:10:18 -0700545 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700546 throw e.rethrowFromSystemServer();
Kenny Root02c87302010-07-01 08:10:18 -0700547 }
Kenny Root02c87302010-07-01 08:10:18 -0700548 }
Mike Lockwoodd967f462011-03-24 08:12:30 -0700549
Jeff Sharkey48877892015-03-18 11:27:19 -0700550 /** {@hide} */
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -0700551 public @NonNull List<DiskInfo> getDisks() {
552 try {
553 return Arrays.asList(mMountService.getDisks());
554 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700555 throw e.rethrowFromSystemServer();
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -0700556 }
557 }
558
559 /** {@hide} */
Jeff Sharkeyb2b9ab82015-04-05 21:10:42 -0700560 public @Nullable DiskInfo findDiskById(String id) {
561 Preconditions.checkNotNull(id);
562 // TODO; go directly to service to make this faster
563 for (DiskInfo disk : getDisks()) {
564 if (Objects.equals(disk.id, id)) {
565 return disk;
566 }
567 }
568 return null;
569 }
570
571 /** {@hide} */
572 public @Nullable VolumeInfo findVolumeById(String id) {
573 Preconditions.checkNotNull(id);
574 // TODO; go directly to service to make this faster
575 for (VolumeInfo vol : getVolumes()) {
576 if (Objects.equals(vol.id, id)) {
577 return vol;
578 }
579 }
580 return null;
581 }
582
583 /** {@hide} */
584 public @Nullable VolumeInfo findVolumeByUuid(String fsUuid) {
585 Preconditions.checkNotNull(fsUuid);
586 // TODO; go directly to service to make this faster
587 for (VolumeInfo vol : getVolumes()) {
588 if (Objects.equals(vol.fsUuid, fsUuid)) {
589 return vol;
590 }
591 }
592 return null;
593 }
594
595 /** {@hide} */
Jeff Sharkeyb36586a2015-04-27 08:42:28 -0700596 public @Nullable VolumeRecord findRecordByUuid(String fsUuid) {
597 Preconditions.checkNotNull(fsUuid);
598 // TODO; go directly to service to make this faster
599 for (VolumeRecord rec : getVolumeRecords()) {
600 if (Objects.equals(rec.fsUuid, fsUuid)) {
601 return rec;
602 }
603 }
604 return null;
605 }
606
607 /** {@hide} */
Jeff Sharkey27de30d2015-04-18 16:20:27 -0700608 public @Nullable VolumeInfo findPrivateForEmulated(VolumeInfo emulatedVol) {
Jeff Sharkeyef10ee02015-07-05 14:17:27 -0700609 if (emulatedVol != null) {
610 return findVolumeById(emulatedVol.getId().replace("emulated", "private"));
611 } else {
612 return null;
613 }
Jeff Sharkey27de30d2015-04-18 16:20:27 -0700614 }
615
616 /** {@hide} */
617 public @Nullable VolumeInfo findEmulatedForPrivate(VolumeInfo privateVol) {
Jeff Sharkeyef10ee02015-07-05 14:17:27 -0700618 if (privateVol != null) {
619 return findVolumeById(privateVol.getId().replace("private", "emulated"));
620 } else {
621 return null;
622 }
Jeff Sharkey27de30d2015-04-18 16:20:27 -0700623 }
624
625 /** {@hide} */
Jeff Sharkey50a05452015-04-29 11:24:52 -0700626 public @Nullable VolumeInfo findVolumeByQualifiedUuid(String volumeUuid) {
627 if (Objects.equals(StorageManager.UUID_PRIVATE_INTERNAL, volumeUuid)) {
628 return findVolumeById(VolumeInfo.ID_PRIVATE_INTERNAL);
629 } else if (Objects.equals(StorageManager.UUID_PRIMARY_PHYSICAL, volumeUuid)) {
630 return getPrimaryPhysicalVolume();
631 } else {
632 return findVolumeByUuid(volumeUuid);
633 }
634 }
635
636 /** {@hide} */
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -0700637 public @NonNull List<VolumeInfo> getVolumes() {
Jeff Sharkeyb36586a2015-04-27 08:42:28 -0700638 try {
639 return Arrays.asList(mMountService.getVolumes(0));
640 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700641 throw e.rethrowFromSystemServer();
Jeff Sharkeyb36586a2015-04-27 08:42:28 -0700642 }
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700643 }
644
645 /** {@hide} */
Jeff Sharkey6dce4962015-07-03 18:08:41 -0700646 public @NonNull List<VolumeInfo> getWritablePrivateVolumes() {
647 try {
648 final ArrayList<VolumeInfo> res = new ArrayList<>();
649 for (VolumeInfo vol : mMountService.getVolumes(0)) {
650 if (vol.getType() == VolumeInfo.TYPE_PRIVATE && vol.isMountedWritable()) {
651 res.add(vol);
652 }
653 }
654 return res;
655 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700656 throw e.rethrowFromSystemServer();
Jeff Sharkey6dce4962015-07-03 18:08:41 -0700657 }
658 }
659
660 /** {@hide} */
Jeff Sharkeyb36586a2015-04-27 08:42:28 -0700661 public @NonNull List<VolumeRecord> getVolumeRecords() {
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -0700662 try {
Jeff Sharkeyb36586a2015-04-27 08:42:28 -0700663 return Arrays.asList(mMountService.getVolumeRecords(0));
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -0700664 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700665 throw e.rethrowFromSystemServer();
Jeff Sharkey1b8ef7e2015-04-03 17:14:45 -0700666 }
667 }
668
669 /** {@hide} */
Jeff Sharkey56bd3122015-04-14 10:30:34 -0700670 public @Nullable String getBestVolumeDescription(VolumeInfo vol) {
Jeff Sharkey50a05452015-04-29 11:24:52 -0700671 if (vol == null) return null;
672
Jeff Sharkeyb36586a2015-04-27 08:42:28 -0700673 // Nickname always takes precedence when defined
674 if (!TextUtils.isEmpty(vol.fsUuid)) {
675 final VolumeRecord rec = findRecordByUuid(vol.fsUuid);
Jeff Sharkeyc8406812015-05-04 12:04:09 -0700676 if (rec != null && !TextUtils.isEmpty(rec.nickname)) {
Jeff Sharkeyb36586a2015-04-27 08:42:28 -0700677 return rec.nickname;
Jeff Sharkey56bd3122015-04-14 10:30:34 -0700678 }
Jeff Sharkey59d577a2015-04-11 21:27:21 -0700679 }
Jeff Sharkeyb36586a2015-04-27 08:42:28 -0700680
681 if (!TextUtils.isEmpty(vol.getDescription())) {
682 return vol.getDescription();
683 }
684
685 if (vol.disk != null) {
686 return vol.disk.getDescription();
687 }
688
689 return null;
Jeff Sharkey59d577a2015-04-11 21:27:21 -0700690 }
691
692 /** {@hide} */
Jeff Sharkey620b32b2015-04-23 19:36:02 -0700693 public @Nullable VolumeInfo getPrimaryPhysicalVolume() {
694 final List<VolumeInfo> vols = getVolumes();
695 for (VolumeInfo vol : vols) {
696 if (vol.isPrimaryPhysical()) {
697 return vol;
698 }
699 }
700 return null;
701 }
702
703 /** {@hide} */
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700704 public void mount(String volId) {
705 try {
706 mMountService.mount(volId);
707 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700708 throw e.rethrowFromSystemServer();
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700709 }
710 }
711
712 /** {@hide} */
713 public void unmount(String volId) {
714 try {
715 mMountService.unmount(volId);
716 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700717 throw e.rethrowFromSystemServer();
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700718 }
719 }
720
721 /** {@hide} */
722 public void format(String volId) {
723 try {
724 mMountService.format(volId);
725 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700726 throw e.rethrowFromSystemServer();
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700727 }
728 }
729
730 /** {@hide} */
Jeff Sharkey9756d752015-05-14 21:07:42 -0700731 public long benchmark(String volId) {
732 try {
733 return mMountService.benchmark(volId);
734 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700735 throw e.rethrowFromSystemServer();
Jeff Sharkey9756d752015-05-14 21:07:42 -0700736 }
737 }
738
739 /** {@hide} */
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700740 public void partitionPublic(String diskId) {
741 try {
742 mMountService.partitionPublic(diskId);
743 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700744 throw e.rethrowFromSystemServer();
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700745 }
746 }
747
748 /** {@hide} */
749 public void partitionPrivate(String diskId) {
750 try {
751 mMountService.partitionPrivate(diskId);
752 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700753 throw e.rethrowFromSystemServer();
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700754 }
755 }
756
757 /** {@hide} */
758 public void partitionMixed(String diskId, int ratio) {
759 try {
760 mMountService.partitionMixed(diskId, ratio);
761 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700762 throw e.rethrowFromSystemServer();
Jeff Sharkey7151a9a2015-04-04 15:22:37 -0700763 }
764 }
765
766 /** {@hide} */
Jeff Sharkeyb42d6942015-04-28 22:25:26 -0700767 public void wipeAdoptableDisks() {
768 // We only wipe devices in "adoptable" locations, which are in a
769 // long-term stable slot/location on the device, where apps have a
770 // reasonable chance of storing sensitive data. (Apps need to go through
771 // SAF to write to transient volumes.)
772 final List<DiskInfo> disks = getDisks();
773 for (DiskInfo disk : disks) {
774 final String diskId = disk.getId();
775 if (disk.isAdoptable()) {
776 Slog.d(TAG, "Found adoptable " + diskId + "; wiping");
777 try {
778 // TODO: switch to explicit wipe command when we have it,
779 // for now rely on the fact that vfat format does a wipe
780 mMountService.partitionPublic(diskId);
781 } catch (Exception e) {
782 Slog.w(TAG, "Failed to wipe " + diskId + ", but soldiering onward", e);
783 }
784 } else {
785 Slog.d(TAG, "Ignorning non-adoptable disk " + disk.getId());
786 }
787 }
788 }
789
790 /** {@hide} */
Jeff Sharkeyb36586a2015-04-27 08:42:28 -0700791 public void setVolumeNickname(String fsUuid, String nickname) {
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700792 try {
Jeff Sharkeyb36586a2015-04-27 08:42:28 -0700793 mMountService.setVolumeNickname(fsUuid, nickname);
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700794 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700795 throw e.rethrowFromSystemServer();
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700796 }
797 }
798
799 /** {@hide} */
Jeff Sharkeyb36586a2015-04-27 08:42:28 -0700800 public void setVolumeInited(String fsUuid, boolean inited) {
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700801 try {
Jeff Sharkeyb36586a2015-04-27 08:42:28 -0700802 mMountService.setVolumeUserFlags(fsUuid, inited ? VolumeRecord.USER_FLAG_INITED : 0,
803 VolumeRecord.USER_FLAG_INITED);
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700804 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700805 throw e.rethrowFromSystemServer();
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700806 }
807 }
808
809 /** {@hide} */
Jeff Sharkeyb36586a2015-04-27 08:42:28 -0700810 public void setVolumeSnoozed(String fsUuid, boolean snoozed) {
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700811 try {
Jeff Sharkeyb36586a2015-04-27 08:42:28 -0700812 mMountService.setVolumeUserFlags(fsUuid, snoozed ? VolumeRecord.USER_FLAG_SNOOZED : 0,
813 VolumeRecord.USER_FLAG_SNOOZED);
814 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700815 throw e.rethrowFromSystemServer();
Jeff Sharkeyb36586a2015-04-27 08:42:28 -0700816 }
817 }
818
819 /** {@hide} */
820 public void forgetVolume(String fsUuid) {
821 try {
822 mMountService.forgetVolume(fsUuid);
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700823 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700824 throw e.rethrowFromSystemServer();
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700825 }
826 }
827
Jeff Sharkey275e3e42015-04-24 16:10:32 -0700828 /**
829 * This is not the API you're looking for.
830 *
831 * @see PackageManager#getPrimaryStorageCurrentVolume()
832 * @hide
833 */
Jeff Sharkey620b32b2015-04-23 19:36:02 -0700834 public String getPrimaryStorageUuid() {
835 try {
836 return mMountService.getPrimaryStorageUuid();
837 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700838 throw e.rethrowFromSystemServer();
Jeff Sharkey620b32b2015-04-23 19:36:02 -0700839 }
840 }
841
Jeff Sharkey275e3e42015-04-24 16:10:32 -0700842 /**
843 * This is not the API you're looking for.
844 *
845 * @see PackageManager#movePrimaryStorage(VolumeInfo)
846 * @hide
847 */
848 public void setPrimaryStorageUuid(String volumeUuid, IPackageMoveObserver callback) {
Jeff Sharkey620b32b2015-04-23 19:36:02 -0700849 try {
Jeff Sharkey275e3e42015-04-24 16:10:32 -0700850 mMountService.setPrimaryStorageUuid(volumeUuid, callback);
Jeff Sharkey620b32b2015-04-23 19:36:02 -0700851 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700852 throw e.rethrowFromSystemServer();
Jeff Sharkey620b32b2015-04-23 19:36:02 -0700853 }
854 }
855
Felipe Lemec250e452016-04-11 18:44:33 -0700856 /**
857 * Return the {@link StorageVolume} that contains the given file, or {@code null} if none.
858 */
Jeff Sharkey48877892015-03-18 11:27:19 -0700859 public @Nullable StorageVolume getStorageVolume(File file) {
860 return getStorageVolume(getVolumeList(), file);
861 }
862
863 /** {@hide} */
864 public static @Nullable StorageVolume getStorageVolume(File file, int userId) {
Jeff Sharkey46349872015-07-28 10:49:47 -0700865 return getStorageVolume(getVolumeList(userId, 0), file);
Jeff Sharkey48877892015-03-18 11:27:19 -0700866 }
867
868 /** {@hide} */
869 private static @Nullable StorageVolume getStorageVolume(StorageVolume[] volumes, File file) {
Felipe Lemec250e452016-04-11 18:44:33 -0700870 if (file == null) {
871 return null;
872 }
Jeff Sharkey48877892015-03-18 11:27:19 -0700873 try {
Jeff Sharkey983294592015-07-13 10:25:31 -0700874 file = file.getCanonicalFile();
Jeff Sharkey48877892015-03-18 11:27:19 -0700875 } catch (IOException ignored) {
Felipe Lemec250e452016-04-11 18:44:33 -0700876 Slog.d(TAG, "Could not get canonical path for " + file);
Jeff Sharkey983294592015-07-13 10:25:31 -0700877 return null;
Jeff Sharkey48877892015-03-18 11:27:19 -0700878 }
879 for (StorageVolume volume : volumes) {
Jeff Sharkey983294592015-07-13 10:25:31 -0700880 File volumeFile = volume.getPathFile();
881 try {
882 volumeFile = volumeFile.getCanonicalFile();
883 } catch (IOException ignored) {
884 continue;
Jeff Sharkey48877892015-03-18 11:27:19 -0700885 }
Jeff Sharkey983294592015-07-13 10:25:31 -0700886 if (FileUtils.contains(volumeFile, file)) {
Jeff Sharkey48877892015-03-18 11:27:19 -0700887 return volume;
888 }
889 }
890 return null;
891 }
892
Mike Lockwoodd967f462011-03-24 08:12:30 -0700893 /**
894 * Gets the state of a volume via its mountpoint.
895 * @hide
896 */
Jeff Sharkey48877892015-03-18 11:27:19 -0700897 @Deprecated
898 public @NonNull String getVolumeState(String mountPoint) {
899 final StorageVolume vol = getStorageVolume(new File(mountPoint));
900 if (vol != null) {
901 return vol.getState();
902 } else {
903 return Environment.MEDIA_UNKNOWN;
Mike Lockwoodd967f462011-03-24 08:12:30 -0700904 }
905 }
906
Felipe Leme04a5d402016-02-08 16:44:06 -0800907 /**
Jeff Sharkeyc02bfae2016-03-27 15:06:53 -0600908 * Return the list of shared/external storage volumes available to the
909 * current user. This includes both the primary shared storage device and
910 * any attached external volumes including SD cards and USB drives.
Felipe Leme04a5d402016-02-08 16:44:06 -0800911 *
Jeff Sharkeyc02bfae2016-03-27 15:06:53 -0600912 * @see Environment#getExternalStorageDirectory()
913 * @see StorageVolume#createAccessIntent(String)
Felipe Leme04a5d402016-02-08 16:44:06 -0800914 */
Jeff Sharkeyc02bfae2016-03-27 15:06:53 -0600915 public @NonNull List<StorageVolume> getStorageVolumes() {
916 final ArrayList<StorageVolume> res = new ArrayList<>();
917 Collections.addAll(res,
918 getVolumeList(UserHandle.myUserId(), FLAG_REAL_STATE | FLAG_INCLUDE_INVISIBLE));
919 return res;
920 }
921
922 /**
923 * Return the primary shared/external storage volume available to the
924 * current user. This volume is the same storage device returned by
925 * {@link Environment#getExternalStorageDirectory()} and
926 * {@link Context#getExternalFilesDir(String)}.
927 */
928 public @NonNull StorageVolume getPrimaryStorageVolume() {
929 return getVolumeList(UserHandle.myUserId(), FLAG_REAL_STATE | FLAG_INCLUDE_INVISIBLE)[0];
930 }
931
Felipe Leme18202e00b2016-05-12 12:56:28 -0700932 /** {@hide} */
933 public long getPrimaryStorageSize() {
Felipe Leme179923a2016-07-19 09:33:31 -0700934 for (String path : INTERNAL_STORAGE_SIZE_PATHS) {
935 final long numberBlocks = readLong(path);
936 if (numberBlocks > 0) {
937 return numberBlocks * INTERNAL_STORAGE_SECTOR_SIZE;
938 }
939 }
940 return 0;
Felipe Leme18202e00b2016-05-12 12:56:28 -0700941 }
942
943 private long readLong(String path) {
944 try (final FileInputStream fis = new FileInputStream(path);
945 final BufferedReader reader = new BufferedReader(new InputStreamReader(fis));) {
946 return Long.parseLong(reader.readLine());
947 } catch (Exception e) {
Felipe Leme179923a2016-07-19 09:33:31 -0700948 Slog.w(TAG, "Could not read " + path, e);
Felipe Leme18202e00b2016-05-12 12:56:28 -0700949 return 0;
950 }
951 }
952
Jeff Sharkeyc02bfae2016-03-27 15:06:53 -0600953 /** @removed */
Jeff Sharkey48877892015-03-18 11:27:19 -0700954 public @NonNull StorageVolume[] getVolumeList() {
Jeff Sharkey46349872015-07-28 10:49:47 -0700955 return getVolumeList(mContext.getUserId(), 0);
Jeff Sharkey48877892015-03-18 11:27:19 -0700956 }
957
958 /** {@hide} */
Jeff Sharkey46349872015-07-28 10:49:47 -0700959 public static @NonNull StorageVolume[] getVolumeList(int userId, int flags) {
Jeff Sharkey48877892015-03-18 11:27:19 -0700960 final IMountService mountService = IMountService.Stub.asInterface(
961 ServiceManager.getService("mount"));
962 try {
Svetoslav7395cbf2015-07-15 15:58:01 -0700963 String packageName = ActivityThread.currentOpPackageName();
964 if (packageName == null) {
965 // Package name can be null if the activity thread is running but the app
966 // hasn't bound yet. In this case we fall back to the first package in the
967 // current UID. This works for runtime permissions as permission state is
968 // per UID and permission realted app ops are updated for all UID packages.
969 String[] packageNames = ActivityThread.getPackageManager().getPackagesForUid(
970 android.os.Process.myUid());
971 if (packageNames == null || packageNames.length <= 0) {
972 return new StorageVolume[0];
973 }
974 packageName = packageNames[0];
975 }
Jeff Sharkeycd654482016-01-08 17:42:11 -0700976 final int uid = ActivityThread.getPackageManager().getPackageUid(packageName,
Jeff Sharkeyc5967e92016-01-07 18:50:29 -0700977 PackageManager.MATCH_DEBUG_TRIAGED_MISSING, userId);
Svetoslav7395cbf2015-07-15 15:58:01 -0700978 if (uid <= 0) {
979 return new StorageVolume[0];
980 }
Jeff Sharkey46349872015-07-28 10:49:47 -0700981 return mountService.getVolumeList(uid, packageName, flags);
Jeff Sharkey48877892015-03-18 11:27:19 -0700982 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700983 throw e.rethrowFromSystemServer();
Mike Lockwoodd967f462011-03-24 08:12:30 -0700984 }
985 }
Mike Lockwood2f6a3882011-05-09 19:08:06 -0700986
987 /**
988 * Returns list of paths for all mountable volumes.
989 * @hide
990 */
Jeff Sharkey48877892015-03-18 11:27:19 -0700991 @Deprecated
992 public @NonNull String[] getVolumePaths() {
Mike Lockwood2f6a3882011-05-09 19:08:06 -0700993 StorageVolume[] volumes = getVolumeList();
Mike Lockwood2f6a3882011-05-09 19:08:06 -0700994 int count = volumes.length;
995 String[] paths = new String[count];
996 for (int i = 0; i < count; i++) {
997 paths[i] = volumes[i].getPath();
998 }
999 return paths;
1000 }
Jeff Sharkeyb049e212012-09-07 23:16:01 -07001001
Jeff Sharkeyc02bfae2016-03-27 15:06:53 -06001002 /** @removed */
Jeff Sharkey48877892015-03-18 11:27:19 -07001003 public @NonNull StorageVolume getPrimaryVolume() {
Jeff Sharkeyb049e212012-09-07 23:16:01 -07001004 return getPrimaryVolume(getVolumeList());
1005 }
1006
1007 /** {@hide} */
Jeff Sharkey48877892015-03-18 11:27:19 -07001008 public static @NonNull StorageVolume getPrimaryVolume(StorageVolume[] volumes) {
Jeff Sharkeyb049e212012-09-07 23:16:01 -07001009 for (StorageVolume volume : volumes) {
1010 if (volume.isPrimary()) {
1011 return volume;
1012 }
1013 }
Jeff Sharkey48877892015-03-18 11:27:19 -07001014 throw new IllegalStateException("Missing primary storage");
Jeff Sharkeyb049e212012-09-07 23:16:01 -07001015 }
Jeff Sharkeybe722152013-02-15 16:56:38 -08001016
Jeff Sharkey48877892015-03-18 11:27:19 -07001017 /** {@hide} */
Jeff Sharkeybe722152013-02-15 16:56:38 -08001018 private static final int DEFAULT_THRESHOLD_PERCENTAGE = 10;
1019 private static final long DEFAULT_THRESHOLD_MAX_BYTES = 500 * MB_IN_BYTES;
1020 private static final long DEFAULT_FULL_THRESHOLD_BYTES = MB_IN_BYTES;
1021
1022 /**
Jeff Sharkey742e7902014-08-16 19:09:13 -07001023 * Return the number of available bytes until the given path is considered
1024 * running low on storage.
1025 *
1026 * @hide
1027 */
1028 public long getStorageBytesUntilLow(File path) {
1029 return path.getUsableSpace() - getStorageFullBytes(path);
1030 }
1031
1032 /**
Jeff Sharkeybe722152013-02-15 16:56:38 -08001033 * Return the number of available bytes at which the given path is
1034 * considered running low on storage.
1035 *
1036 * @hide
1037 */
1038 public long getStorageLowBytes(File path) {
1039 final long lowPercent = Settings.Global.getInt(mResolver,
1040 Settings.Global.SYS_STORAGE_THRESHOLD_PERCENTAGE, DEFAULT_THRESHOLD_PERCENTAGE);
1041 final long lowBytes = (path.getTotalSpace() * lowPercent) / 100;
1042
1043 final long maxLowBytes = Settings.Global.getLong(mResolver,
1044 Settings.Global.SYS_STORAGE_THRESHOLD_MAX_BYTES, DEFAULT_THRESHOLD_MAX_BYTES);
1045
1046 return Math.min(lowBytes, maxLowBytes);
1047 }
1048
1049 /**
1050 * Return the number of available bytes at which the given path is
1051 * considered full.
1052 *
1053 * @hide
1054 */
1055 public long getStorageFullBytes(File path) {
1056 return Settings.Global.getLong(mResolver, Settings.Global.SYS_STORAGE_FULL_THRESHOLD_BYTES,
1057 DEFAULT_FULL_THRESHOLD_BYTES);
1058 }
Paul Lawrencee8fdc542014-05-28 07:14:17 -07001059
Jeff Sharkey50a05452015-04-29 11:24:52 -07001060 /** {@hide} */
Lenka Trochtovac4dd0212015-11-18 12:22:06 +01001061 public void createUserKey(int userId, int serialNumber, boolean ephemeral) {
Paul Crowleybcf48ed2015-04-22 13:36:59 +01001062 try {
Lenka Trochtovac4dd0212015-11-18 12:22:06 +01001063 mMountService.createUserKey(userId, serialNumber, ephemeral);
Paul Crowleybcf48ed2015-04-22 13:36:59 +01001064 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -07001065 throw e.rethrowFromSystemServer();
Paul Crowleybcf48ed2015-04-22 13:36:59 +01001066 }
1067 }
1068
1069 /** {@hide} */
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08001070 public void destroyUserKey(int userId) {
Paul Crowley7ec733f2015-05-19 12:42:00 +01001071 try {
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08001072 mMountService.destroyUserKey(userId);
1073 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -07001074 throw e.rethrowFromSystemServer();
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08001075 }
1076 }
1077
1078 /** {@hide} */
Paul Crowleyfaeb3eb2016-02-08 15:58:29 +00001079 public void unlockUserKey(int userId, int serialNumber, byte[] token, byte[] secret) {
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08001080 try {
Paul Crowleyfaeb3eb2016-02-08 15:58:29 +00001081 mMountService.unlockUserKey(userId, serialNumber, token, secret);
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08001082 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -07001083 throw e.rethrowFromSystemServer();
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08001084 }
1085 }
1086
1087 /** {@hide} */
1088 public void lockUserKey(int userId) {
1089 try {
1090 mMountService.lockUserKey(userId);
1091 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -07001092 throw e.rethrowFromSystemServer();
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08001093 }
1094 }
1095
1096 /** {@hide} */
Jeff Sharkey47f71082016-02-01 17:03:54 -07001097 public void prepareUserStorage(String volumeUuid, int userId, int serialNumber, int flags) {
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08001098 try {
Jeff Sharkey47f71082016-02-01 17:03:54 -07001099 mMountService.prepareUserStorage(volumeUuid, userId, serialNumber, flags);
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08001100 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -07001101 throw e.rethrowFromSystemServer();
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08001102 }
1103 }
1104
1105 /** {@hide} */
Jeff Sharkeyfcf1e552016-04-14 20:44:58 -06001106 public void destroyUserStorage(String volumeUuid, int userId, int flags) {
1107 try {
1108 mMountService.destroyUserStorage(volumeUuid, userId, flags);
1109 } catch (RemoteException e) {
1110 throw e.rethrowFromSystemServer();
1111 }
1112 }
1113
1114 /** {@hide} */
Jeff Sharkeyce18c812016-04-27 16:00:41 -06001115 public static boolean isUserKeyUnlocked(int userId) {
Jeff Sharkey4815ed42016-05-26 09:31:04 -06001116 if (sMountService == null) {
1117 sMountService = IMountService.Stub
1118 .asInterface(ServiceManager.getService("mount"));
1119 }
1120 if (sMountService == null) {
Jeff Sharkeyce18c812016-04-27 16:00:41 -06001121 Slog.w(TAG, "Early during boot, assuming locked");
1122 return false;
1123 }
1124 final long token = Binder.clearCallingIdentity();
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08001125 try {
Jeff Sharkey4815ed42016-05-26 09:31:04 -06001126 return sMountService.isUserKeyUnlocked(userId);
Paul Crowley7ec733f2015-05-19 12:42:00 +01001127 } catch (RemoteException e) {
Jeff Sharkeyce18c812016-04-27 16:00:41 -06001128 throw e.rethrowAsRuntimeException();
1129 } finally {
1130 Binder.restoreCallingIdentity(token);
Paul Crowley7ec733f2015-05-19 12:42:00 +01001131 }
1132 }
1133
Jeff Sharkeycf3f0a12016-03-17 19:57:58 -06001134 /**
Jeff Sharkeyf82c2f02016-04-12 15:19:10 -06001135 * Return if data stored at or under the given path will be encrypted while
1136 * at rest. This can help apps avoid the overhead of double-encrypting data.
Jeff Sharkeycf3f0a12016-03-17 19:57:58 -06001137 */
1138 public boolean isEncrypted(File file) {
1139 if (FileUtils.contains(Environment.getDataDirectory(), file)) {
1140 return isEncrypted();
1141 } else if (FileUtils.contains(Environment.getExpandDirectory(), file)) {
1142 return true;
1143 }
1144 // TODO: extend to support shared storage
1145 return false;
1146 }
1147
Paul Lawrence20be5d62016-02-26 13:51:17 -08001148 /** {@hide}
1149 * Is this device encryptable or already encrypted?
1150 * @return true for encryptable or encrypted
1151 * false not encrypted and not encryptable
1152 */
1153 public static boolean isEncryptable() {
1154 final String state = SystemProperties.get("ro.crypto.state", "unsupported");
1155 return !"unsupported".equalsIgnoreCase(state);
1156 }
1157
1158 /** {@hide}
1159 * Is this device already encrypted?
1160 * @return true for encrypted. (Implies isEncryptable() == true)
1161 * false not encrypted
1162 */
1163 public static boolean isEncrypted() {
1164 final String state = SystemProperties.get("ro.crypto.state", "");
1165 return "encrypted".equalsIgnoreCase(state);
1166 }
1167
1168 /** {@hide}
1169 * Is this device file encrypted?
1170 * @return true for file encrypted. (Implies isEncrypted() == true)
1171 * false not encrypted or block encrypted
1172 */
1173 public static boolean isFileEncryptedNativeOnly() {
1174 if (!isEncrypted()) {
1175 return false;
1176 }
1177
1178 final String status = SystemProperties.get("ro.crypto.type", "");
1179 return "file".equalsIgnoreCase(status);
1180 }
1181
1182 /** {@hide}
1183 * Is this device block encrypted?
1184 * @return true for block encrypted. (Implies isEncrypted() == true)
1185 * false not encrypted or file encrypted
1186 */
1187 public static boolean isBlockEncrypted() {
1188 if (!isEncrypted()) {
1189 return false;
1190 }
1191 final String status = SystemProperties.get("ro.crypto.type", "");
1192 return "block".equalsIgnoreCase(status);
1193 }
1194
1195 /** {@hide}
1196 * Is this device block encrypted with credentials?
1197 * @return true for crediential block encrypted.
1198 * (Implies isBlockEncrypted() == true)
1199 * false not encrypted, file encrypted or default block encrypted
1200 */
1201 public static boolean isNonDefaultBlockEncrypted() {
1202 if (!isBlockEncrypted()) {
1203 return false;
1204 }
1205
1206 try {
1207 IMountService mountService = IMountService.Stub.asInterface(
1208 ServiceManager.getService("mount"));
1209 return mountService.getPasswordType() != CRYPT_TYPE_DEFAULT;
1210 } catch (RemoteException e) {
1211 Log.e(TAG, "Error getting encryption type");
1212 return false;
1213 }
1214 }
1215
1216 /** {@hide}
1217 * Is this device in the process of being block encrypted?
1218 * @return true for encrypting.
1219 * false otherwise
1220 * Whether device isEncrypted at this point is undefined
1221 * Note that only system services and CryptKeeper will ever see this return
1222 * true - no app will ever be launched in this state.
1223 * Also note that this state will not change without a teardown of the
1224 * framework, so no service needs to check for changes during their lifespan
1225 */
1226 public static boolean isBlockEncrypting() {
1227 final String state = SystemProperties.get("vold.encrypt_progress", "");
1228 return !"".equalsIgnoreCase(state);
1229 }
1230
1231 /** {@hide}
1232 * Is this device non default block encrypted and in the process of
1233 * prompting for credentials?
1234 * @return true for prompting for credentials.
1235 * (Implies isNonDefaultBlockEncrypted() == true)
1236 * false otherwise
1237 * Note that only system services and CryptKeeper will ever see this return
1238 * true - no app will ever be launched in this state.
1239 * Also note that this state will not change without a teardown of the
1240 * framework, so no service needs to check for changes during their lifespan
1241 */
1242 public static boolean inCryptKeeperBounce() {
1243 final String status = SystemProperties.get("vold.decrypt");
1244 return "trigger_restart_min_framework".equals(status);
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07001245 }
1246
1247 /** {@hide} */
Paul Lawrence20be5d62016-02-26 13:51:17 -08001248 public static boolean isFileEncryptedEmulatedOnly() {
Jeff Sharkeyce14cd02015-12-07 15:35:42 -07001249 return SystemProperties.getBoolean(StorageManager.PROP_EMULATE_FBE, false);
Clara Bayarri965da392015-10-28 17:53:53 +00001250 }
1251
Paul Lawrence20be5d62016-02-26 13:51:17 -08001252 /** {@hide}
1253 * Is this device running in a file encrypted mode, either native or emulated?
1254 * @return true for file encrypted, false otherwise
1255 */
1256 public static boolean isFileEncryptedNativeOrEmulated() {
1257 return isFileEncryptedNativeOnly()
1258 || isFileEncryptedEmulatedOnly();
1259 }
1260
Clara Bayarri965da392015-10-28 17:53:53 +00001261 /** {@hide} */
Jeff Sharkey50a05452015-04-29 11:24:52 -07001262 public static File maybeTranslateEmulatedPathToInternal(File path) {
Jeff Sharkey8575da12016-04-07 17:56:06 +00001263 final IMountService mountService = IMountService.Stub.asInterface(
1264 ServiceManager.getService("mount"));
1265 try {
1266 final VolumeInfo[] vols = mountService.getVolumes(0);
1267 for (VolumeInfo vol : vols) {
1268 if ((vol.getType() == VolumeInfo.TYPE_EMULATED
1269 || vol.getType() == VolumeInfo.TYPE_PUBLIC) && vol.isMountedReadable()) {
1270 final File internalPath = FileUtils.rewriteAfterRename(vol.getPath(),
1271 vol.getInternalPath(), path);
1272 if (internalPath != null && internalPath.exists()) {
1273 return internalPath;
1274 }
1275 }
1276 }
1277 } catch (RemoteException e) {
1278 throw e.rethrowFromSystemServer();
1279 }
Jeff Sharkey50a05452015-04-29 11:24:52 -07001280 return path;
1281 }
1282
Daichi Hirono9e8d9e22015-11-13 14:37:00 +09001283 /** {@hide} */
1284 public ParcelFileDescriptor mountAppFuse(String name) {
1285 try {
1286 return mMountService.mountAppFuse(name);
1287 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -07001288 throw e.rethrowFromSystemServer();
Daichi Hirono9e8d9e22015-11-13 14:37:00 +09001289 }
1290 }
1291
Paul Lawrencee8fdc542014-05-28 07:14:17 -07001292 /// Consts to match the password types in cryptfs.h
1293 /** @hide */
1294 public static final int CRYPT_TYPE_PASSWORD = 0;
1295 /** @hide */
1296 public static final int CRYPT_TYPE_DEFAULT = 1;
1297 /** @hide */
1298 public static final int CRYPT_TYPE_PATTERN = 2;
1299 /** @hide */
1300 public static final int CRYPT_TYPE_PIN = 3;
Elliott Hughesf839b4f2014-09-26 12:30:47 -07001301
1302 // Constants for the data available via MountService.getField.
1303 /** @hide */
1304 public static final String SYSTEM_LOCALE_KEY = "SystemLocale";
1305 /** @hide */
1306 public static final String OWNER_INFO_KEY = "OwnerInfo";
1307 /** @hide */
1308 public static final String PATTERN_VISIBLE_KEY = "PatternVisible";
Paul Lawrenced8fdb332015-05-18 13:26:11 -07001309 /** @hide */
1310 public static final String PASSWORD_VISIBLE_KEY = "PasswordVisible";
San Mehatb1043402010-02-05 08:26:50 -08001311}