StorageManager.java revision a45746efadd11bb7dfab026fb3c81a25fae74ca4
1b104340496e3a531e26c8f428c808eca0e039f50San Mehat/* 2b104340496e3a531e26c8f428c808eca0e039f50San Mehat * Copyright (C) 2008 The Android Open Source Project 3b104340496e3a531e26c8f428c808eca0e039f50San Mehat * 4b104340496e3a531e26c8f428c808eca0e039f50San Mehat * Licensed under the Apache License, Version 2.0 (the "License"); 5b104340496e3a531e26c8f428c808eca0e039f50San Mehat * you may not use this file except in compliance with the License. 6b104340496e3a531e26c8f428c808eca0e039f50San Mehat * You may obtain a copy of the License at 7b104340496e3a531e26c8f428c808eca0e039f50San Mehat * 8b104340496e3a531e26c8f428c808eca0e039f50San Mehat * http://www.apache.org/licenses/LICENSE-2.0 9b104340496e3a531e26c8f428c808eca0e039f50San Mehat * 10b104340496e3a531e26c8f428c808eca0e039f50San Mehat * Unless required by applicable law or agreed to in writing, software 11b104340496e3a531e26c8f428c808eca0e039f50San Mehat * distributed under the License is distributed on an "AS IS" BASIS, 12b104340496e3a531e26c8f428c808eca0e039f50San Mehat * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13b104340496e3a531e26c8f428c808eca0e039f50San Mehat * See the License for the specific language governing permissions and 14b104340496e3a531e26c8f428c808eca0e039f50San Mehat * limitations under the License. 15b104340496e3a531e26c8f428c808eca0e039f50San Mehat */ 16b104340496e3a531e26c8f428c808eca0e039f50San Mehat 17b104340496e3a531e26c8f428c808eca0e039f50San Mehatpackage android.os.storage; 18b104340496e3a531e26c8f428c808eca0e039f50San Mehat 19cba928cef7d614d375253246f014c4a52bb8b913Mike Lockwoodimport android.os.Environment; 20b104340496e3a531e26c8f428c808eca0e039f50San Mehatimport android.os.Handler; 21a02b8b05dd1e8b8cf169e1f89542ef835b11fc13Kenny Rootimport android.os.Looper; 22b104340496e3a531e26c8f428c808eca0e039f50San Mehatimport android.os.Message; 232f6a3885533a52758c2cd4f81f6123a712be8ae6Mike Lockwoodimport android.os.Parcelable; 24a02b8b05dd1e8b8cf169e1f89542ef835b11fc13Kenny Rootimport android.os.RemoteException; 25b104340496e3a531e26c8f428c808eca0e039f50San Mehatimport android.os.ServiceManager; 26b104340496e3a531e26c8f428c808eca0e039f50San Mehatimport android.util.Log; 27af9d667ccf3e24058214cf4cc0a8aa8bc5100e3cKenny Rootimport android.util.SparseArray; 28b104340496e3a531e26c8f428c808eca0e039f50San Mehat 2905105f7abe02b2dff91d6260b3628c8b97816babKenny Rootimport java.lang.ref.WeakReference; 30b104340496e3a531e26c8f428c808eca0e039f50San Mehatimport java.util.ArrayList; 3105105f7abe02b2dff91d6260b3628c8b97816babKenny Rootimport java.util.List; 32af9d667ccf3e24058214cf4cc0a8aa8bc5100e3cKenny Rootimport java.util.concurrent.atomic.AtomicInteger; 33b104340496e3a531e26c8f428c808eca0e039f50San Mehat 34b104340496e3a531e26c8f428c808eca0e039f50San Mehat/** 3505105f7abe02b2dff91d6260b3628c8b97816babKenny Root * StorageManager is the interface to the systems storage service. The storage 3605105f7abe02b2dff91d6260b3628c8b97816babKenny Root * manager handles storage-related items such as Opaque Binary Blobs (OBBs). 3705105f7abe02b2dff91d6260b3628c8b97816babKenny Root * <p> 3805105f7abe02b2dff91d6260b3628c8b97816babKenny Root * OBBs contain a filesystem that maybe be encrypted on disk and mounted 3905105f7abe02b2dff91d6260b3628c8b97816babKenny Root * on-demand from an application. OBBs are a good way of providing large amounts 4005105f7abe02b2dff91d6260b3628c8b97816babKenny Root * of binary assets without packaging them into APKs as they may be multiple 4105105f7abe02b2dff91d6260b3628c8b97816babKenny Root * gigabytes in size. However, due to their size, they're most likely stored in 4205105f7abe02b2dff91d6260b3628c8b97816babKenny Root * a shared storage pool accessible from all programs. The system does not 4305105f7abe02b2dff91d6260b3628c8b97816babKenny Root * guarantee the security of the OBB file itself: if any program modifies the 4405105f7abe02b2dff91d6260b3628c8b97816babKenny Root * OBB, there is no guarantee that a read from that OBB will produce the 4505105f7abe02b2dff91d6260b3628c8b97816babKenny Root * expected output. 4605105f7abe02b2dff91d6260b3628c8b97816babKenny Root * <p> 47b104340496e3a531e26c8f428c808eca0e039f50San Mehat * Get an instance of this class by calling 4805105f7abe02b2dff91d6260b3628c8b97816babKenny Root * {@link android.content.Context#getSystemService(java.lang.String)} with an 4905105f7abe02b2dff91d6260b3628c8b97816babKenny Root * argument of {@link android.content.Context#STORAGE_SERVICE}. 50b104340496e3a531e26c8f428c808eca0e039f50San Mehat */ 51b104340496e3a531e26c8f428c808eca0e039f50San Mehat 52b104340496e3a531e26c8f428c808eca0e039f50San Mehatpublic class StorageManager 53b104340496e3a531e26c8f428c808eca0e039f50San Mehat{ 54b104340496e3a531e26c8f428c808eca0e039f50San Mehat private static final String TAG = "StorageManager"; 55b104340496e3a531e26c8f428c808eca0e039f50San Mehat 56b104340496e3a531e26c8f428c808eca0e039f50San Mehat /* 57b104340496e3a531e26c8f428c808eca0e039f50San Mehat * Our internal MountService binder reference 58b104340496e3a531e26c8f428c808eca0e039f50San Mehat */ 59b104340496e3a531e26c8f428c808eca0e039f50San Mehat private IMountService mMountService; 60b104340496e3a531e26c8f428c808eca0e039f50San Mehat 61b104340496e3a531e26c8f428c808eca0e039f50San Mehat /* 62b104340496e3a531e26c8f428c808eca0e039f50San Mehat * The looper target for callbacks 63b104340496e3a531e26c8f428c808eca0e039f50San Mehat */ 64b104340496e3a531e26c8f428c808eca0e039f50San Mehat Looper mTgtLooper; 65b104340496e3a531e26c8f428c808eca0e039f50San Mehat 66b104340496e3a531e26c8f428c808eca0e039f50San Mehat /* 67b104340496e3a531e26c8f428c808eca0e039f50San Mehat * Target listener for binder callbacks 68b104340496e3a531e26c8f428c808eca0e039f50San Mehat */ 69b104340496e3a531e26c8f428c808eca0e039f50San Mehat private MountServiceBinderListener mBinderListener; 70b104340496e3a531e26c8f428c808eca0e039f50San Mehat 71b104340496e3a531e26c8f428c808eca0e039f50San Mehat /* 72b104340496e3a531e26c8f428c808eca0e039f50San Mehat * List of our listeners 73b104340496e3a531e26c8f428c808eca0e039f50San Mehat */ 74af9d667ccf3e24058214cf4cc0a8aa8bc5100e3cKenny Root private List<ListenerDelegate> mListeners = new ArrayList<ListenerDelegate>(); 75af9d667ccf3e24058214cf4cc0a8aa8bc5100e3cKenny Root 76af9d667ccf3e24058214cf4cc0a8aa8bc5100e3cKenny Root /* 77af9d667ccf3e24058214cf4cc0a8aa8bc5100e3cKenny Root * Next available nonce 78af9d667ccf3e24058214cf4cc0a8aa8bc5100e3cKenny Root */ 79af9d667ccf3e24058214cf4cc0a8aa8bc5100e3cKenny Root final private AtomicInteger mNextNonce = new AtomicInteger(0); 80b104340496e3a531e26c8f428c808eca0e039f50San Mehat 81b104340496e3a531e26c8f428c808eca0e039f50San Mehat private class MountServiceBinderListener extends IMountServiceListener.Stub { 82b104340496e3a531e26c8f428c808eca0e039f50San Mehat public void onUsbMassStorageConnectionChanged(boolean available) { 83b104340496e3a531e26c8f428c808eca0e039f50San Mehat final int size = mListeners.size(); 84b104340496e3a531e26c8f428c808eca0e039f50San Mehat for (int i = 0; i < size; i++) { 85b104340496e3a531e26c8f428c808eca0e039f50San Mehat mListeners.get(i).sendShareAvailabilityChanged(available); 86b104340496e3a531e26c8f428c808eca0e039f50San Mehat } 87b104340496e3a531e26c8f428c808eca0e039f50San Mehat } 88b104340496e3a531e26c8f428c808eca0e039f50San Mehat 89b104340496e3a531e26c8f428c808eca0e039f50San Mehat public void onStorageStateChanged(String path, String oldState, String newState) { 90b104340496e3a531e26c8f428c808eca0e039f50San Mehat final int size = mListeners.size(); 91b104340496e3a531e26c8f428c808eca0e039f50San Mehat for (int i = 0; i < size; i++) { 92b104340496e3a531e26c8f428c808eca0e039f50San Mehat mListeners.get(i).sendStorageStateChanged(path, oldState, newState); 93b104340496e3a531e26c8f428c808eca0e039f50San Mehat } 94b104340496e3a531e26c8f428c808eca0e039f50San Mehat } 95b104340496e3a531e26c8f428c808eca0e039f50San Mehat } 96b104340496e3a531e26c8f428c808eca0e039f50San Mehat 97b104340496e3a531e26c8f428c808eca0e039f50San Mehat /** 98a02b8b05dd1e8b8cf169e1f89542ef835b11fc13Kenny Root * Binder listener for OBB action results. 99a02b8b05dd1e8b8cf169e1f89542ef835b11fc13Kenny Root */ 10005105f7abe02b2dff91d6260b3628c8b97816babKenny Root private final ObbActionListener mObbActionListener = new ObbActionListener(); 10105105f7abe02b2dff91d6260b3628c8b97816babKenny Root 10205105f7abe02b2dff91d6260b3628c8b97816babKenny Root private class ObbActionListener extends IObbActionListener.Stub { 10337051cdd8624c4821bb68169be427061c48ad837Gilles Debunne @SuppressWarnings("hiding") 104af9d667ccf3e24058214cf4cc0a8aa8bc5100e3cKenny Root private SparseArray<ObbListenerDelegate> mListeners = new SparseArray<ObbListenerDelegate>(); 10505105f7abe02b2dff91d6260b3628c8b97816babKenny Root 106a02b8b05dd1e8b8cf169e1f89542ef835b11fc13Kenny Root @Override 10737051cdd8624c4821bb68169be427061c48ad837Gilles Debunne public void onObbResult(String filename, int nonce, int status) { 108af9d667ccf3e24058214cf4cc0a8aa8bc5100e3cKenny Root final ObbListenerDelegate delegate; 10905105f7abe02b2dff91d6260b3628c8b97816babKenny Root synchronized (mListeners) { 110af9d667ccf3e24058214cf4cc0a8aa8bc5100e3cKenny Root delegate = mListeners.get(nonce); 111af9d667ccf3e24058214cf4cc0a8aa8bc5100e3cKenny Root if (delegate != null) { 112af9d667ccf3e24058214cf4cc0a8aa8bc5100e3cKenny Root mListeners.remove(nonce); 11305105f7abe02b2dff91d6260b3628c8b97816babKenny Root } 11405105f7abe02b2dff91d6260b3628c8b97816babKenny Root } 11505105f7abe02b2dff91d6260b3628c8b97816babKenny Root 116af9d667ccf3e24058214cf4cc0a8aa8bc5100e3cKenny Root if (delegate != null) { 117af9d667ccf3e24058214cf4cc0a8aa8bc5100e3cKenny Root delegate.sendObbStateChanged(filename, status); 11805105f7abe02b2dff91d6260b3628c8b97816babKenny Root } 119af9d667ccf3e24058214cf4cc0a8aa8bc5100e3cKenny Root } 12005105f7abe02b2dff91d6260b3628c8b97816babKenny Root 121af9d667ccf3e24058214cf4cc0a8aa8bc5100e3cKenny Root public int addListener(OnObbStateChangeListener listener) { 122af9d667ccf3e24058214cf4cc0a8aa8bc5100e3cKenny Root final ObbListenerDelegate delegate = new ObbListenerDelegate(listener); 12305105f7abe02b2dff91d6260b3628c8b97816babKenny Root 124af9d667ccf3e24058214cf4cc0a8aa8bc5100e3cKenny Root synchronized (mListeners) { 125af9d667ccf3e24058214cf4cc0a8aa8bc5100e3cKenny Root mListeners.put(delegate.nonce, delegate); 12605105f7abe02b2dff91d6260b3628c8b97816babKenny Root } 127af9d667ccf3e24058214cf4cc0a8aa8bc5100e3cKenny Root 128af9d667ccf3e24058214cf4cc0a8aa8bc5100e3cKenny Root return delegate.nonce; 12905105f7abe02b2dff91d6260b3628c8b97816babKenny Root } 13005105f7abe02b2dff91d6260b3628c8b97816babKenny Root } 13105105f7abe02b2dff91d6260b3628c8b97816babKenny Root 132af9d667ccf3e24058214cf4cc0a8aa8bc5100e3cKenny Root private int getNextNonce() { 133af9d667ccf3e24058214cf4cc0a8aa8bc5100e3cKenny Root return mNextNonce.getAndIncrement(); 134af9d667ccf3e24058214cf4cc0a8aa8bc5100e3cKenny Root } 135af9d667ccf3e24058214cf4cc0a8aa8bc5100e3cKenny Root 13605105f7abe02b2dff91d6260b3628c8b97816babKenny Root /** 13705105f7abe02b2dff91d6260b3628c8b97816babKenny Root * Private class containing sender and receiver code for StorageEvents. 13805105f7abe02b2dff91d6260b3628c8b97816babKenny Root */ 13905105f7abe02b2dff91d6260b3628c8b97816babKenny Root private class ObbListenerDelegate { 14005105f7abe02b2dff91d6260b3628c8b97816babKenny Root private final WeakReference<OnObbStateChangeListener> mObbEventListenerRef; 14105105f7abe02b2dff91d6260b3628c8b97816babKenny Root private final Handler mHandler; 14205105f7abe02b2dff91d6260b3628c8b97816babKenny Root 143af9d667ccf3e24058214cf4cc0a8aa8bc5100e3cKenny Root private final int nonce; 144af9d667ccf3e24058214cf4cc0a8aa8bc5100e3cKenny Root 14505105f7abe02b2dff91d6260b3628c8b97816babKenny Root ObbListenerDelegate(OnObbStateChangeListener listener) { 146af9d667ccf3e24058214cf4cc0a8aa8bc5100e3cKenny Root nonce = getNextNonce(); 14705105f7abe02b2dff91d6260b3628c8b97816babKenny Root mObbEventListenerRef = new WeakReference<OnObbStateChangeListener>(listener); 14805105f7abe02b2dff91d6260b3628c8b97816babKenny Root mHandler = new Handler(mTgtLooper) { 14905105f7abe02b2dff91d6260b3628c8b97816babKenny Root @Override 15005105f7abe02b2dff91d6260b3628c8b97816babKenny Root public void handleMessage(Message msg) { 15137051cdd8624c4821bb68169be427061c48ad837Gilles Debunne final OnObbStateChangeListener changeListener = getListener(); 15237051cdd8624c4821bb68169be427061c48ad837Gilles Debunne if (changeListener == null) { 15305105f7abe02b2dff91d6260b3628c8b97816babKenny Root return; 15405105f7abe02b2dff91d6260b3628c8b97816babKenny Root } 15505105f7abe02b2dff91d6260b3628c8b97816babKenny Root 15605105f7abe02b2dff91d6260b3628c8b97816babKenny Root StorageEvent e = (StorageEvent) msg.obj; 15705105f7abe02b2dff91d6260b3628c8b97816babKenny Root 15805105f7abe02b2dff91d6260b3628c8b97816babKenny Root if (msg.what == StorageEvent.EVENT_OBB_STATE_CHANGED) { 15905105f7abe02b2dff91d6260b3628c8b97816babKenny Root ObbStateChangedStorageEvent ev = (ObbStateChangedStorageEvent) e; 16037051cdd8624c4821bb68169be427061c48ad837Gilles Debunne changeListener.onObbStateChange(ev.path, ev.state); 16105105f7abe02b2dff91d6260b3628c8b97816babKenny Root } else { 16205105f7abe02b2dff91d6260b3628c8b97816babKenny Root Log.e(TAG, "Unsupported event " + msg.what); 16305105f7abe02b2dff91d6260b3628c8b97816babKenny Root } 16405105f7abe02b2dff91d6260b3628c8b97816babKenny Root } 16505105f7abe02b2dff91d6260b3628c8b97816babKenny Root }; 16605105f7abe02b2dff91d6260b3628c8b97816babKenny Root } 16705105f7abe02b2dff91d6260b3628c8b97816babKenny Root 16805105f7abe02b2dff91d6260b3628c8b97816babKenny Root OnObbStateChangeListener getListener() { 16905105f7abe02b2dff91d6260b3628c8b97816babKenny Root if (mObbEventListenerRef == null) { 17005105f7abe02b2dff91d6260b3628c8b97816babKenny Root return null; 17105105f7abe02b2dff91d6260b3628c8b97816babKenny Root } 17205105f7abe02b2dff91d6260b3628c8b97816babKenny Root return mObbEventListenerRef.get(); 17305105f7abe02b2dff91d6260b3628c8b97816babKenny Root } 17405105f7abe02b2dff91d6260b3628c8b97816babKenny Root 175af9d667ccf3e24058214cf4cc0a8aa8bc5100e3cKenny Root void sendObbStateChanged(String path, int state) { 17605105f7abe02b2dff91d6260b3628c8b97816babKenny Root ObbStateChangedStorageEvent e = new ObbStateChangedStorageEvent(path, state); 17705105f7abe02b2dff91d6260b3628c8b97816babKenny Root mHandler.sendMessage(e.getMessage()); 17805105f7abe02b2dff91d6260b3628c8b97816babKenny Root } 17905105f7abe02b2dff91d6260b3628c8b97816babKenny Root } 18005105f7abe02b2dff91d6260b3628c8b97816babKenny Root 18105105f7abe02b2dff91d6260b3628c8b97816babKenny Root /** 18205105f7abe02b2dff91d6260b3628c8b97816babKenny Root * Message sent during an OBB status change event. 18305105f7abe02b2dff91d6260b3628c8b97816babKenny Root */ 18405105f7abe02b2dff91d6260b3628c8b97816babKenny Root private class ObbStateChangedStorageEvent extends StorageEvent { 18505105f7abe02b2dff91d6260b3628c8b97816babKenny Root public final String path; 18605105f7abe02b2dff91d6260b3628c8b97816babKenny Root 187af9d667ccf3e24058214cf4cc0a8aa8bc5100e3cKenny Root public final int state; 188af9d667ccf3e24058214cf4cc0a8aa8bc5100e3cKenny Root 189af9d667ccf3e24058214cf4cc0a8aa8bc5100e3cKenny Root public ObbStateChangedStorageEvent(String path, int state) { 19005105f7abe02b2dff91d6260b3628c8b97816babKenny Root super(EVENT_OBB_STATE_CHANGED); 19105105f7abe02b2dff91d6260b3628c8b97816babKenny Root this.path = path; 19205105f7abe02b2dff91d6260b3628c8b97816babKenny Root this.state = state; 193a02b8b05dd1e8b8cf169e1f89542ef835b11fc13Kenny Root } 194a02b8b05dd1e8b8cf169e1f89542ef835b11fc13Kenny Root } 195a02b8b05dd1e8b8cf169e1f89542ef835b11fc13Kenny Root 196a02b8b05dd1e8b8cf169e1f89542ef835b11fc13Kenny Root /** 197b104340496e3a531e26c8f428c808eca0e039f50San Mehat * Private base class for messages sent between the callback thread 198b104340496e3a531e26c8f428c808eca0e039f50San Mehat * and the target looper handler. 199b104340496e3a531e26c8f428c808eca0e039f50San Mehat */ 200b104340496e3a531e26c8f428c808eca0e039f50San Mehat private class StorageEvent { 20105105f7abe02b2dff91d6260b3628c8b97816babKenny Root static final int EVENT_UMS_CONNECTION_CHANGED = 1; 20205105f7abe02b2dff91d6260b3628c8b97816babKenny Root static final int EVENT_STORAGE_STATE_CHANGED = 2; 20305105f7abe02b2dff91d6260b3628c8b97816babKenny Root static final int EVENT_OBB_STATE_CHANGED = 3; 204b104340496e3a531e26c8f428c808eca0e039f50San Mehat 205b104340496e3a531e26c8f428c808eca0e039f50San Mehat private Message mMessage; 206b104340496e3a531e26c8f428c808eca0e039f50San Mehat 207b104340496e3a531e26c8f428c808eca0e039f50San Mehat public StorageEvent(int what) { 208b104340496e3a531e26c8f428c808eca0e039f50San Mehat mMessage = Message.obtain(); 209b104340496e3a531e26c8f428c808eca0e039f50San Mehat mMessage.what = what; 210b104340496e3a531e26c8f428c808eca0e039f50San Mehat mMessage.obj = this; 211b104340496e3a531e26c8f428c808eca0e039f50San Mehat } 212b104340496e3a531e26c8f428c808eca0e039f50San Mehat 213b104340496e3a531e26c8f428c808eca0e039f50San Mehat public Message getMessage() { 214b104340496e3a531e26c8f428c808eca0e039f50San Mehat return mMessage; 215b104340496e3a531e26c8f428c808eca0e039f50San Mehat } 216b104340496e3a531e26c8f428c808eca0e039f50San Mehat } 217b104340496e3a531e26c8f428c808eca0e039f50San Mehat 218b104340496e3a531e26c8f428c808eca0e039f50San Mehat /** 219b104340496e3a531e26c8f428c808eca0e039f50San Mehat * Message sent on a USB mass storage connection change. 220b104340496e3a531e26c8f428c808eca0e039f50San Mehat */ 221b104340496e3a531e26c8f428c808eca0e039f50San Mehat private class UmsConnectionChangedStorageEvent extends StorageEvent { 222b104340496e3a531e26c8f428c808eca0e039f50San Mehat public boolean available; 223b104340496e3a531e26c8f428c808eca0e039f50San Mehat 224b104340496e3a531e26c8f428c808eca0e039f50San Mehat public UmsConnectionChangedStorageEvent(boolean a) { 225b104340496e3a531e26c8f428c808eca0e039f50San Mehat super(EVENT_UMS_CONNECTION_CHANGED); 226b104340496e3a531e26c8f428c808eca0e039f50San Mehat available = a; 227b104340496e3a531e26c8f428c808eca0e039f50San Mehat } 228b104340496e3a531e26c8f428c808eca0e039f50San Mehat } 229b104340496e3a531e26c8f428c808eca0e039f50San Mehat 230b104340496e3a531e26c8f428c808eca0e039f50San Mehat /** 231b104340496e3a531e26c8f428c808eca0e039f50San Mehat * Message sent on volume state change. 232b104340496e3a531e26c8f428c808eca0e039f50San Mehat */ 233b104340496e3a531e26c8f428c808eca0e039f50San Mehat private class StorageStateChangedStorageEvent extends StorageEvent { 234b104340496e3a531e26c8f428c808eca0e039f50San Mehat public String path; 235b104340496e3a531e26c8f428c808eca0e039f50San Mehat public String oldState; 236b104340496e3a531e26c8f428c808eca0e039f50San Mehat public String newState; 237b104340496e3a531e26c8f428c808eca0e039f50San Mehat 238b104340496e3a531e26c8f428c808eca0e039f50San Mehat public StorageStateChangedStorageEvent(String p, String oldS, String newS) { 239b104340496e3a531e26c8f428c808eca0e039f50San Mehat super(EVENT_STORAGE_STATE_CHANGED); 240b104340496e3a531e26c8f428c808eca0e039f50San Mehat path = p; 241b104340496e3a531e26c8f428c808eca0e039f50San Mehat oldState = oldS; 242b104340496e3a531e26c8f428c808eca0e039f50San Mehat newState = newS; 243b104340496e3a531e26c8f428c808eca0e039f50San Mehat } 244b104340496e3a531e26c8f428c808eca0e039f50San Mehat } 245b104340496e3a531e26c8f428c808eca0e039f50San Mehat 246b104340496e3a531e26c8f428c808eca0e039f50San Mehat /** 247b104340496e3a531e26c8f428c808eca0e039f50San Mehat * Private class containing sender and receiver code for StorageEvents. 248b104340496e3a531e26c8f428c808eca0e039f50San Mehat */ 249b104340496e3a531e26c8f428c808eca0e039f50San Mehat private class ListenerDelegate { 250b104340496e3a531e26c8f428c808eca0e039f50San Mehat final StorageEventListener mStorageEventListener; 251b104340496e3a531e26c8f428c808eca0e039f50San Mehat private final Handler mHandler; 252b104340496e3a531e26c8f428c808eca0e039f50San Mehat 253b104340496e3a531e26c8f428c808eca0e039f50San Mehat ListenerDelegate(StorageEventListener listener) { 254b104340496e3a531e26c8f428c808eca0e039f50San Mehat mStorageEventListener = listener; 255b104340496e3a531e26c8f428c808eca0e039f50San Mehat mHandler = new Handler(mTgtLooper) { 256b104340496e3a531e26c8f428c808eca0e039f50San Mehat @Override 257b104340496e3a531e26c8f428c808eca0e039f50San Mehat public void handleMessage(Message msg) { 258b104340496e3a531e26c8f428c808eca0e039f50San Mehat StorageEvent e = (StorageEvent) msg.obj; 259b104340496e3a531e26c8f428c808eca0e039f50San Mehat 260b104340496e3a531e26c8f428c808eca0e039f50San Mehat if (msg.what == StorageEvent.EVENT_UMS_CONNECTION_CHANGED) { 261b104340496e3a531e26c8f428c808eca0e039f50San Mehat UmsConnectionChangedStorageEvent ev = (UmsConnectionChangedStorageEvent) e; 262b104340496e3a531e26c8f428c808eca0e039f50San Mehat mStorageEventListener.onUsbMassStorageConnectionChanged(ev.available); 263b104340496e3a531e26c8f428c808eca0e039f50San Mehat } else if (msg.what == StorageEvent.EVENT_STORAGE_STATE_CHANGED) { 264b104340496e3a531e26c8f428c808eca0e039f50San Mehat StorageStateChangedStorageEvent ev = (StorageStateChangedStorageEvent) e; 265b104340496e3a531e26c8f428c808eca0e039f50San Mehat mStorageEventListener.onStorageStateChanged(ev.path, ev.oldState, ev.newState); 266b104340496e3a531e26c8f428c808eca0e039f50San Mehat } else { 267b104340496e3a531e26c8f428c808eca0e039f50San Mehat Log.e(TAG, "Unsupported event " + msg.what); 268b104340496e3a531e26c8f428c808eca0e039f50San Mehat } 269b104340496e3a531e26c8f428c808eca0e039f50San Mehat } 270b104340496e3a531e26c8f428c808eca0e039f50San Mehat }; 271b104340496e3a531e26c8f428c808eca0e039f50San Mehat } 272b104340496e3a531e26c8f428c808eca0e039f50San Mehat 273b104340496e3a531e26c8f428c808eca0e039f50San Mehat StorageEventListener getListener() { 274b104340496e3a531e26c8f428c808eca0e039f50San Mehat return mStorageEventListener; 275b104340496e3a531e26c8f428c808eca0e039f50San Mehat } 276b104340496e3a531e26c8f428c808eca0e039f50San Mehat 277b104340496e3a531e26c8f428c808eca0e039f50San Mehat void sendShareAvailabilityChanged(boolean available) { 278b104340496e3a531e26c8f428c808eca0e039f50San Mehat UmsConnectionChangedStorageEvent e = new UmsConnectionChangedStorageEvent(available); 279b104340496e3a531e26c8f428c808eca0e039f50San Mehat mHandler.sendMessage(e.getMessage()); 280b104340496e3a531e26c8f428c808eca0e039f50San Mehat } 281b104340496e3a531e26c8f428c808eca0e039f50San Mehat 282b104340496e3a531e26c8f428c808eca0e039f50San Mehat void sendStorageStateChanged(String path, String oldState, String newState) { 283b104340496e3a531e26c8f428c808eca0e039f50San Mehat StorageStateChangedStorageEvent e = new StorageStateChangedStorageEvent(path, oldState, newState); 284b104340496e3a531e26c8f428c808eca0e039f50San Mehat mHandler.sendMessage(e.getMessage()); 285b104340496e3a531e26c8f428c808eca0e039f50San Mehat } 286b104340496e3a531e26c8f428c808eca0e039f50San Mehat } 287b104340496e3a531e26c8f428c808eca0e039f50San Mehat 288b104340496e3a531e26c8f428c808eca0e039f50San Mehat /** 289b104340496e3a531e26c8f428c808eca0e039f50San Mehat * Constructs a StorageManager object through which an application can 290b104340496e3a531e26c8f428c808eca0e039f50San Mehat * can communicate with the systems mount service. 291b104340496e3a531e26c8f428c808eca0e039f50San Mehat * 292a45746efadd11bb7dfab026fb3c81a25fae74ca4Jeff Smith * @param tgtLooper The {@link android.os.Looper} which events will be received on. 293b104340496e3a531e26c8f428c808eca0e039f50San Mehat * 294b104340496e3a531e26c8f428c808eca0e039f50San Mehat * <p>Applications can get instance of this class by calling 295b104340496e3a531e26c8f428c808eca0e039f50San Mehat * {@link android.content.Context#getSystemService(java.lang.String)} with an argument 296b104340496e3a531e26c8f428c808eca0e039f50San Mehat * of {@link android.content.Context#STORAGE_SERVICE}. 297b104340496e3a531e26c8f428c808eca0e039f50San Mehat * 298b104340496e3a531e26c8f428c808eca0e039f50San Mehat * @hide 299b104340496e3a531e26c8f428c808eca0e039f50San Mehat */ 300b104340496e3a531e26c8f428c808eca0e039f50San Mehat public StorageManager(Looper tgtLooper) throws RemoteException { 301b104340496e3a531e26c8f428c808eca0e039f50San Mehat mMountService = IMountService.Stub.asInterface(ServiceManager.getService("mount")); 302b104340496e3a531e26c8f428c808eca0e039f50San Mehat if (mMountService == null) { 303b104340496e3a531e26c8f428c808eca0e039f50San Mehat Log.e(TAG, "Unable to connect to mount service! - is it running yet?"); 304b104340496e3a531e26c8f428c808eca0e039f50San Mehat return; 305b104340496e3a531e26c8f428c808eca0e039f50San Mehat } 306b104340496e3a531e26c8f428c808eca0e039f50San Mehat mTgtLooper = tgtLooper; 307b104340496e3a531e26c8f428c808eca0e039f50San Mehat mBinderListener = new MountServiceBinderListener(); 308b104340496e3a531e26c8f428c808eca0e039f50San Mehat mMountService.registerListener(mBinderListener); 309b104340496e3a531e26c8f428c808eca0e039f50San Mehat } 310b104340496e3a531e26c8f428c808eca0e039f50San Mehat 311b104340496e3a531e26c8f428c808eca0e039f50San Mehat 312b104340496e3a531e26c8f428c808eca0e039f50San Mehat /** 313b104340496e3a531e26c8f428c808eca0e039f50San Mehat * Registers a {@link android.os.storage.StorageEventListener StorageEventListener}. 314b104340496e3a531e26c8f428c808eca0e039f50San Mehat * 315b104340496e3a531e26c8f428c808eca0e039f50San Mehat * @param listener A {@link android.os.storage.StorageEventListener StorageEventListener} object. 316b104340496e3a531e26c8f428c808eca0e039f50San Mehat * 317ec7c9ff0bb1c98cb8bec3ec7bdacbae3a434fa53Kenny Root * @hide 318b104340496e3a531e26c8f428c808eca0e039f50San Mehat */ 319b104340496e3a531e26c8f428c808eca0e039f50San Mehat public void registerListener(StorageEventListener listener) { 320b104340496e3a531e26c8f428c808eca0e039f50San Mehat if (listener == null) { 321b104340496e3a531e26c8f428c808eca0e039f50San Mehat return; 322b104340496e3a531e26c8f428c808eca0e039f50San Mehat } 323b104340496e3a531e26c8f428c808eca0e039f50San Mehat 324b104340496e3a531e26c8f428c808eca0e039f50San Mehat synchronized (mListeners) { 325b104340496e3a531e26c8f428c808eca0e039f50San Mehat mListeners.add(new ListenerDelegate(listener)); 326b104340496e3a531e26c8f428c808eca0e039f50San Mehat } 327b104340496e3a531e26c8f428c808eca0e039f50San Mehat } 328b104340496e3a531e26c8f428c808eca0e039f50San Mehat 329b104340496e3a531e26c8f428c808eca0e039f50San Mehat /** 330b104340496e3a531e26c8f428c808eca0e039f50San Mehat * Unregisters a {@link android.os.storage.StorageEventListener StorageEventListener}. 331b104340496e3a531e26c8f428c808eca0e039f50San Mehat * 332b104340496e3a531e26c8f428c808eca0e039f50San Mehat * @param listener A {@link android.os.storage.StorageEventListener StorageEventListener} object. 333b104340496e3a531e26c8f428c808eca0e039f50San Mehat * 334ec7c9ff0bb1c98cb8bec3ec7bdacbae3a434fa53Kenny Root * @hide 335b104340496e3a531e26c8f428c808eca0e039f50San Mehat */ 336b104340496e3a531e26c8f428c808eca0e039f50San Mehat public void unregisterListener(StorageEventListener listener) { 337b104340496e3a531e26c8f428c808eca0e039f50San Mehat if (listener == null) { 338b104340496e3a531e26c8f428c808eca0e039f50San Mehat return; 339b104340496e3a531e26c8f428c808eca0e039f50San Mehat } 340b104340496e3a531e26c8f428c808eca0e039f50San Mehat 341b104340496e3a531e26c8f428c808eca0e039f50San Mehat synchronized (mListeners) { 342b104340496e3a531e26c8f428c808eca0e039f50San Mehat final int size = mListeners.size(); 343b104340496e3a531e26c8f428c808eca0e039f50San Mehat for (int i=0 ; i<size ; i++) { 344b104340496e3a531e26c8f428c808eca0e039f50San Mehat ListenerDelegate l = mListeners.get(i); 345b104340496e3a531e26c8f428c808eca0e039f50San Mehat if (l.getListener() == listener) { 346b104340496e3a531e26c8f428c808eca0e039f50San Mehat mListeners.remove(i); 347b104340496e3a531e26c8f428c808eca0e039f50San Mehat break; 348b104340496e3a531e26c8f428c808eca0e039f50San Mehat } 349b104340496e3a531e26c8f428c808eca0e039f50San Mehat } 350b104340496e3a531e26c8f428c808eca0e039f50San Mehat } 351b104340496e3a531e26c8f428c808eca0e039f50San Mehat } 352b104340496e3a531e26c8f428c808eca0e039f50San Mehat 353b104340496e3a531e26c8f428c808eca0e039f50San Mehat /** 354b104340496e3a531e26c8f428c808eca0e039f50San Mehat * Enables USB Mass Storage (UMS) on the device. 355ec7c9ff0bb1c98cb8bec3ec7bdacbae3a434fa53Kenny Root * 356ec7c9ff0bb1c98cb8bec3ec7bdacbae3a434fa53Kenny Root * @hide 357b104340496e3a531e26c8f428c808eca0e039f50San Mehat */ 3580eec21d97d9dc4eb4fdbad0e4c0fc53703452d02Suchi Amalapurapu public void enableUsbMassStorage() { 359b104340496e3a531e26c8f428c808eca0e039f50San Mehat try { 3600eec21d97d9dc4eb4fdbad0e4c0fc53703452d02Suchi Amalapurapu mMountService.setUsbMassStorageEnabled(true); 361b104340496e3a531e26c8f428c808eca0e039f50San Mehat } catch (Exception ex) { 362b104340496e3a531e26c8f428c808eca0e039f50San Mehat Log.e(TAG, "Failed to enable UMS", ex); 363b104340496e3a531e26c8f428c808eca0e039f50San Mehat } 364b104340496e3a531e26c8f428c808eca0e039f50San Mehat } 365b104340496e3a531e26c8f428c808eca0e039f50San Mehat 366b104340496e3a531e26c8f428c808eca0e039f50San Mehat /** 367b104340496e3a531e26c8f428c808eca0e039f50San Mehat * Disables USB Mass Storage (UMS) on the device. 368ec7c9ff0bb1c98cb8bec3ec7bdacbae3a434fa53Kenny Root * 369ec7c9ff0bb1c98cb8bec3ec7bdacbae3a434fa53Kenny Root * @hide 370b104340496e3a531e26c8f428c808eca0e039f50San Mehat */ 3710eec21d97d9dc4eb4fdbad0e4c0fc53703452d02Suchi Amalapurapu public void disableUsbMassStorage() { 372b104340496e3a531e26c8f428c808eca0e039f50San Mehat try { 3730eec21d97d9dc4eb4fdbad0e4c0fc53703452d02Suchi Amalapurapu mMountService.setUsbMassStorageEnabled(false); 374b104340496e3a531e26c8f428c808eca0e039f50San Mehat } catch (Exception ex) { 375b104340496e3a531e26c8f428c808eca0e039f50San Mehat Log.e(TAG, "Failed to disable UMS", ex); 376b104340496e3a531e26c8f428c808eca0e039f50San Mehat } 377b104340496e3a531e26c8f428c808eca0e039f50San Mehat } 378b104340496e3a531e26c8f428c808eca0e039f50San Mehat 379b104340496e3a531e26c8f428c808eca0e039f50San Mehat /** 380b104340496e3a531e26c8f428c808eca0e039f50San Mehat * Query if a USB Mass Storage (UMS) host is connected. 381b104340496e3a531e26c8f428c808eca0e039f50San Mehat * @return true if UMS host is connected. 382ec7c9ff0bb1c98cb8bec3ec7bdacbae3a434fa53Kenny Root * 383ec7c9ff0bb1c98cb8bec3ec7bdacbae3a434fa53Kenny Root * @hide 384b104340496e3a531e26c8f428c808eca0e039f50San Mehat */ 385b104340496e3a531e26c8f428c808eca0e039f50San Mehat public boolean isUsbMassStorageConnected() { 386b104340496e3a531e26c8f428c808eca0e039f50San Mehat try { 387b104340496e3a531e26c8f428c808eca0e039f50San Mehat return mMountService.isUsbMassStorageConnected(); 388b104340496e3a531e26c8f428c808eca0e039f50San Mehat } catch (Exception ex) { 389b104340496e3a531e26c8f428c808eca0e039f50San Mehat Log.e(TAG, "Failed to get UMS connection state", ex); 390b104340496e3a531e26c8f428c808eca0e039f50San Mehat } 391b104340496e3a531e26c8f428c808eca0e039f50San Mehat return false; 392b104340496e3a531e26c8f428c808eca0e039f50San Mehat } 393b104340496e3a531e26c8f428c808eca0e039f50San Mehat 394b104340496e3a531e26c8f428c808eca0e039f50San Mehat /** 395b104340496e3a531e26c8f428c808eca0e039f50San Mehat * Query if a USB Mass Storage (UMS) is enabled on the device. 396b104340496e3a531e26c8f428c808eca0e039f50San Mehat * @return true if UMS host is enabled. 397ec7c9ff0bb1c98cb8bec3ec7bdacbae3a434fa53Kenny Root * 398ec7c9ff0bb1c98cb8bec3ec7bdacbae3a434fa53Kenny Root * @hide 399b104340496e3a531e26c8f428c808eca0e039f50San Mehat */ 400b104340496e3a531e26c8f428c808eca0e039f50San Mehat public boolean isUsbMassStorageEnabled() { 401b104340496e3a531e26c8f428c808eca0e039f50San Mehat try { 402b104340496e3a531e26c8f428c808eca0e039f50San Mehat return mMountService.isUsbMassStorageEnabled(); 403b104340496e3a531e26c8f428c808eca0e039f50San Mehat } catch (RemoteException rex) { 404b104340496e3a531e26c8f428c808eca0e039f50San Mehat Log.e(TAG, "Failed to get UMS enable state", rex); 405b104340496e3a531e26c8f428c808eca0e039f50San Mehat } 406b104340496e3a531e26c8f428c808eca0e039f50San Mehat return false; 407b104340496e3a531e26c8f428c808eca0e039f50San Mehat } 40802c8730c1bf19daf48bec8c6995df676a00a73b1Kenny Root 40902c8730c1bf19daf48bec8c6995df676a00a73b1Kenny Root /** 410a02b8b05dd1e8b8cf169e1f89542ef835b11fc13Kenny Root * Mount an Opaque Binary Blob (OBB) file. If a <code>key</code> is 411a02b8b05dd1e8b8cf169e1f89542ef835b11fc13Kenny Root * specified, it is supplied to the mounting process to be used in any 412a02b8b05dd1e8b8cf169e1f89542ef835b11fc13Kenny Root * encryption used in the OBB. 413a02b8b05dd1e8b8cf169e1f89542ef835b11fc13Kenny Root * <p> 41405105f7abe02b2dff91d6260b3628c8b97816babKenny Root * The OBB will remain mounted for as long as the StorageManager reference 41505105f7abe02b2dff91d6260b3628c8b97816babKenny Root * is held by the application. As soon as this reference is lost, the OBBs 416af9d667ccf3e24058214cf4cc0a8aa8bc5100e3cKenny Root * in use will be unmounted. The {@link OnObbStateChangeListener} registered 417af9d667ccf3e24058214cf4cc0a8aa8bc5100e3cKenny Root * with this call will receive the success or failure of this operation. 41805105f7abe02b2dff91d6260b3628c8b97816babKenny Root * <p> 419a02b8b05dd1e8b8cf169e1f89542ef835b11fc13Kenny Root * <em>Note:</em> you can only mount OBB files for which the OBB tag on the 420a02b8b05dd1e8b8cf169e1f89542ef835b11fc13Kenny Root * file matches a package ID that is owned by the calling program's UID. 42105105f7abe02b2dff91d6260b3628c8b97816babKenny Root * That is, shared UID applications can attempt to mount any other 422a02b8b05dd1e8b8cf169e1f89542ef835b11fc13Kenny Root * application's OBB that shares its UID. 423a02b8b05dd1e8b8cf169e1f89542ef835b11fc13Kenny Root * 424a02b8b05dd1e8b8cf169e1f89542ef835b11fc13Kenny Root * @param filename the path to the OBB file 42505105f7abe02b2dff91d6260b3628c8b97816babKenny Root * @param key secret used to encrypt the OBB; may be <code>null</code> if no 42605105f7abe02b2dff91d6260b3628c8b97816babKenny Root * encryption was used on the OBB. 427af9d667ccf3e24058214cf4cc0a8aa8bc5100e3cKenny Root * @param listener will receive the success or failure of the operation 428a02b8b05dd1e8b8cf169e1f89542ef835b11fc13Kenny Root * @return whether the mount call was successfully queued or not 42902c8730c1bf19daf48bec8c6995df676a00a73b1Kenny Root */ 43005105f7abe02b2dff91d6260b3628c8b97816babKenny Root public boolean mountObb(String filename, String key, OnObbStateChangeListener listener) { 431af9d667ccf3e24058214cf4cc0a8aa8bc5100e3cKenny Root if (filename == null) { 432af9d667ccf3e24058214cf4cc0a8aa8bc5100e3cKenny Root throw new IllegalArgumentException("filename cannot be null"); 433af9d667ccf3e24058214cf4cc0a8aa8bc5100e3cKenny Root } 434af9d667ccf3e24058214cf4cc0a8aa8bc5100e3cKenny Root 435af9d667ccf3e24058214cf4cc0a8aa8bc5100e3cKenny Root if (listener == null) { 436af9d667ccf3e24058214cf4cc0a8aa8bc5100e3cKenny Root throw new IllegalArgumentException("listener cannot be null"); 437af9d667ccf3e24058214cf4cc0a8aa8bc5100e3cKenny Root } 438af9d667ccf3e24058214cf4cc0a8aa8bc5100e3cKenny Root 43902c8730c1bf19daf48bec8c6995df676a00a73b1Kenny Root try { 440af9d667ccf3e24058214cf4cc0a8aa8bc5100e3cKenny Root final int nonce = mObbActionListener.addListener(listener); 441af9d667ccf3e24058214cf4cc0a8aa8bc5100e3cKenny Root mMountService.mountObb(filename, key, mObbActionListener, nonce); 442a02b8b05dd1e8b8cf169e1f89542ef835b11fc13Kenny Root return true; 44302c8730c1bf19daf48bec8c6995df676a00a73b1Kenny Root } catch (RemoteException e) { 44402c8730c1bf19daf48bec8c6995df676a00a73b1Kenny Root Log.e(TAG, "Failed to mount OBB", e); 44502c8730c1bf19daf48bec8c6995df676a00a73b1Kenny Root } 44602c8730c1bf19daf48bec8c6995df676a00a73b1Kenny Root 44702c8730c1bf19daf48bec8c6995df676a00a73b1Kenny Root return false; 44802c8730c1bf19daf48bec8c6995df676a00a73b1Kenny Root } 44902c8730c1bf19daf48bec8c6995df676a00a73b1Kenny Root 45002c8730c1bf19daf48bec8c6995df676a00a73b1Kenny Root /** 45105105f7abe02b2dff91d6260b3628c8b97816babKenny Root * Unmount an Opaque Binary Blob (OBB) file asynchronously. If the 45205105f7abe02b2dff91d6260b3628c8b97816babKenny Root * <code>force</code> flag is true, it will kill any application needed to 45305105f7abe02b2dff91d6260b3628c8b97816babKenny Root * unmount the given OBB (even the calling application). 45405105f7abe02b2dff91d6260b3628c8b97816babKenny Root * <p> 455af9d667ccf3e24058214cf4cc0a8aa8bc5100e3cKenny Root * The {@link OnObbStateChangeListener} registered with this call will 456af9d667ccf3e24058214cf4cc0a8aa8bc5100e3cKenny Root * receive the success or failure of this operation. 457a02b8b05dd1e8b8cf169e1f89542ef835b11fc13Kenny Root * <p> 458a02b8b05dd1e8b8cf169e1f89542ef835b11fc13Kenny Root * <em>Note:</em> you can only mount OBB files for which the OBB tag on the 459a02b8b05dd1e8b8cf169e1f89542ef835b11fc13Kenny Root * file matches a package ID that is owned by the calling program's UID. 460a02b8b05dd1e8b8cf169e1f89542ef835b11fc13Kenny Root * That is, shared UID applications can obtain access to any other 461a02b8b05dd1e8b8cf169e1f89542ef835b11fc13Kenny Root * application's OBB that shares its UID. 46202ca31fbae9f35dd30f79de6927fae11b549391aKenny Root * <p> 463a02b8b05dd1e8b8cf169e1f89542ef835b11fc13Kenny Root * 464a02b8b05dd1e8b8cf169e1f89542ef835b11fc13Kenny Root * @param filename path to the OBB file 465a02b8b05dd1e8b8cf169e1f89542ef835b11fc13Kenny Root * @param force whether to kill any programs using this in order to unmount 466a02b8b05dd1e8b8cf169e1f89542ef835b11fc13Kenny Root * it 467af9d667ccf3e24058214cf4cc0a8aa8bc5100e3cKenny Root * @param listener will receive the success or failure of the operation 468a02b8b05dd1e8b8cf169e1f89542ef835b11fc13Kenny Root * @return whether the unmount call was successfully queued or not 46902c8730c1bf19daf48bec8c6995df676a00a73b1Kenny Root */ 47038cf8867a8d3e8d5159abd0bd0e6a3b0b8348b94Kenny Root public boolean unmountObb(String filename, boolean force, OnObbStateChangeListener listener) { 471af9d667ccf3e24058214cf4cc0a8aa8bc5100e3cKenny Root if (filename == null) { 472af9d667ccf3e24058214cf4cc0a8aa8bc5100e3cKenny Root throw new IllegalArgumentException("filename cannot be null"); 473af9d667ccf3e24058214cf4cc0a8aa8bc5100e3cKenny Root } 474af9d667ccf3e24058214cf4cc0a8aa8bc5100e3cKenny Root 475af9d667ccf3e24058214cf4cc0a8aa8bc5100e3cKenny Root if (listener == null) { 476af9d667ccf3e24058214cf4cc0a8aa8bc5100e3cKenny Root throw new IllegalArgumentException("listener cannot be null"); 477af9d667ccf3e24058214cf4cc0a8aa8bc5100e3cKenny Root } 478af9d667ccf3e24058214cf4cc0a8aa8bc5100e3cKenny Root 47902c8730c1bf19daf48bec8c6995df676a00a73b1Kenny Root try { 480af9d667ccf3e24058214cf4cc0a8aa8bc5100e3cKenny Root final int nonce = mObbActionListener.addListener(listener); 481af9d667ccf3e24058214cf4cc0a8aa8bc5100e3cKenny Root mMountService.unmountObb(filename, force, mObbActionListener, nonce); 482a02b8b05dd1e8b8cf169e1f89542ef835b11fc13Kenny Root return true; 48302c8730c1bf19daf48bec8c6995df676a00a73b1Kenny Root } catch (RemoteException e) { 48402c8730c1bf19daf48bec8c6995df676a00a73b1Kenny Root Log.e(TAG, "Failed to mount OBB", e); 48502c8730c1bf19daf48bec8c6995df676a00a73b1Kenny Root } 48602c8730c1bf19daf48bec8c6995df676a00a73b1Kenny Root 48702c8730c1bf19daf48bec8c6995df676a00a73b1Kenny Root return false; 48802c8730c1bf19daf48bec8c6995df676a00a73b1Kenny Root } 48902c8730c1bf19daf48bec8c6995df676a00a73b1Kenny Root 490a02b8b05dd1e8b8cf169e1f89542ef835b11fc13Kenny Root /** 491a02b8b05dd1e8b8cf169e1f89542ef835b11fc13Kenny Root * Check whether an Opaque Binary Blob (OBB) is mounted or not. 492a02b8b05dd1e8b8cf169e1f89542ef835b11fc13Kenny Root * 493a02b8b05dd1e8b8cf169e1f89542ef835b11fc13Kenny Root * @param filename path to OBB image 494a02b8b05dd1e8b8cf169e1f89542ef835b11fc13Kenny Root * @return true if OBB is mounted; false if not mounted or on error 495a02b8b05dd1e8b8cf169e1f89542ef835b11fc13Kenny Root */ 496af9d667ccf3e24058214cf4cc0a8aa8bc5100e3cKenny Root public boolean isObbMounted(String filename) { 497af9d667ccf3e24058214cf4cc0a8aa8bc5100e3cKenny Root if (filename == null) { 498af9d667ccf3e24058214cf4cc0a8aa8bc5100e3cKenny Root throw new IllegalArgumentException("filename cannot be null"); 499af9d667ccf3e24058214cf4cc0a8aa8bc5100e3cKenny Root } 500af9d667ccf3e24058214cf4cc0a8aa8bc5100e3cKenny Root 50102c8730c1bf19daf48bec8c6995df676a00a73b1Kenny Root try { 50202c8730c1bf19daf48bec8c6995df676a00a73b1Kenny Root return mMountService.isObbMounted(filename); 50302c8730c1bf19daf48bec8c6995df676a00a73b1Kenny Root } catch (RemoteException e) { 50402c8730c1bf19daf48bec8c6995df676a00a73b1Kenny Root Log.e(TAG, "Failed to check if OBB is mounted", e); 50502c8730c1bf19daf48bec8c6995df676a00a73b1Kenny Root } 50602c8730c1bf19daf48bec8c6995df676a00a73b1Kenny Root 50702c8730c1bf19daf48bec8c6995df676a00a73b1Kenny Root return false; 50802c8730c1bf19daf48bec8c6995df676a00a73b1Kenny Root } 50902c8730c1bf19daf48bec8c6995df676a00a73b1Kenny Root 51002c8730c1bf19daf48bec8c6995df676a00a73b1Kenny Root /** 511a02b8b05dd1e8b8cf169e1f89542ef835b11fc13Kenny Root * Check the mounted path of an Opaque Binary Blob (OBB) file. This will 512a02b8b05dd1e8b8cf169e1f89542ef835b11fc13Kenny Root * give you the path to where you can obtain access to the internals of the 513a02b8b05dd1e8b8cf169e1f89542ef835b11fc13Kenny Root * OBB. 514a02b8b05dd1e8b8cf169e1f89542ef835b11fc13Kenny Root * 515a02b8b05dd1e8b8cf169e1f89542ef835b11fc13Kenny Root * @param filename path to OBB image 516a02b8b05dd1e8b8cf169e1f89542ef835b11fc13Kenny Root * @return absolute path to mounted OBB image data or <code>null</code> if 517a02b8b05dd1e8b8cf169e1f89542ef835b11fc13Kenny Root * not mounted or exception encountered trying to read status 51802c8730c1bf19daf48bec8c6995df676a00a73b1Kenny Root */ 51902c8730c1bf19daf48bec8c6995df676a00a73b1Kenny Root public String getMountedObbPath(String filename) { 520af9d667ccf3e24058214cf4cc0a8aa8bc5100e3cKenny Root if (filename == null) { 521af9d667ccf3e24058214cf4cc0a8aa8bc5100e3cKenny Root throw new IllegalArgumentException("filename cannot be null"); 522af9d667ccf3e24058214cf4cc0a8aa8bc5100e3cKenny Root } 523af9d667ccf3e24058214cf4cc0a8aa8bc5100e3cKenny Root 52402c8730c1bf19daf48bec8c6995df676a00a73b1Kenny Root try { 52502c8730c1bf19daf48bec8c6995df676a00a73b1Kenny Root return mMountService.getMountedObbPath(filename); 52602c8730c1bf19daf48bec8c6995df676a00a73b1Kenny Root } catch (RemoteException e) { 52702c8730c1bf19daf48bec8c6995df676a00a73b1Kenny Root Log.e(TAG, "Failed to find mounted path for OBB", e); 52802c8730c1bf19daf48bec8c6995df676a00a73b1Kenny Root } 52902c8730c1bf19daf48bec8c6995df676a00a73b1Kenny Root 53002c8730c1bf19daf48bec8c6995df676a00a73b1Kenny Root return null; 53102c8730c1bf19daf48bec8c6995df676a00a73b1Kenny Root } 532d967f4664f40f9a4c5262a44b19df9bbdf457d8aMike Lockwood 533d967f4664f40f9a4c5262a44b19df9bbdf457d8aMike Lockwood /** 534d967f4664f40f9a4c5262a44b19df9bbdf457d8aMike Lockwood * Gets the state of a volume via its mountpoint. 535d967f4664f40f9a4c5262a44b19df9bbdf457d8aMike Lockwood * @hide 536d967f4664f40f9a4c5262a44b19df9bbdf457d8aMike Lockwood */ 537d967f4664f40f9a4c5262a44b19df9bbdf457d8aMike Lockwood public String getVolumeState(String mountPoint) { 538cba928cef7d614d375253246f014c4a52bb8b913Mike Lockwood if (mMountService == null) return Environment.MEDIA_REMOVED; 539d967f4664f40f9a4c5262a44b19df9bbdf457d8aMike Lockwood try { 540d967f4664f40f9a4c5262a44b19df9bbdf457d8aMike Lockwood return mMountService.getVolumeState(mountPoint); 541d967f4664f40f9a4c5262a44b19df9bbdf457d8aMike Lockwood } catch (RemoteException e) { 542d967f4664f40f9a4c5262a44b19df9bbdf457d8aMike Lockwood Log.e(TAG, "Failed to get volume state", e); 543d967f4664f40f9a4c5262a44b19df9bbdf457d8aMike Lockwood return null; 544d967f4664f40f9a4c5262a44b19df9bbdf457d8aMike Lockwood } 545d967f4664f40f9a4c5262a44b19df9bbdf457d8aMike Lockwood } 546d967f4664f40f9a4c5262a44b19df9bbdf457d8aMike Lockwood 547d967f4664f40f9a4c5262a44b19df9bbdf457d8aMike Lockwood /** 548d967f4664f40f9a4c5262a44b19df9bbdf457d8aMike Lockwood * Returns list of all mountable volumes. 549d967f4664f40f9a4c5262a44b19df9bbdf457d8aMike Lockwood * @hide 550d967f4664f40f9a4c5262a44b19df9bbdf457d8aMike Lockwood */ 5512f6a3885533a52758c2cd4f81f6123a712be8ae6Mike Lockwood public StorageVolume[] getVolumeList() { 552cba928cef7d614d375253246f014c4a52bb8b913Mike Lockwood if (mMountService == null) return new StorageVolume[0]; 553d967f4664f40f9a4c5262a44b19df9bbdf457d8aMike Lockwood try { 5542f6a3885533a52758c2cd4f81f6123a712be8ae6Mike Lockwood Parcelable[] list = mMountService.getVolumeList(); 5552f6a3885533a52758c2cd4f81f6123a712be8ae6Mike Lockwood if (list == null) return new StorageVolume[0]; 5562f6a3885533a52758c2cd4f81f6123a712be8ae6Mike Lockwood int length = list.length; 5572f6a3885533a52758c2cd4f81f6123a712be8ae6Mike Lockwood StorageVolume[] result = new StorageVolume[length]; 5582f6a3885533a52758c2cd4f81f6123a712be8ae6Mike Lockwood for (int i = 0; i < length; i++) { 5592f6a3885533a52758c2cd4f81f6123a712be8ae6Mike Lockwood result[i] = (StorageVolume)list[i]; 5602f6a3885533a52758c2cd4f81f6123a712be8ae6Mike Lockwood } 5612f6a3885533a52758c2cd4f81f6123a712be8ae6Mike Lockwood return result; 562d967f4664f40f9a4c5262a44b19df9bbdf457d8aMike Lockwood } catch (RemoteException e) { 563d967f4664f40f9a4c5262a44b19df9bbdf457d8aMike Lockwood Log.e(TAG, "Failed to get volume list", e); 564d967f4664f40f9a4c5262a44b19df9bbdf457d8aMike Lockwood return null; 565d967f4664f40f9a4c5262a44b19df9bbdf457d8aMike Lockwood } 566d967f4664f40f9a4c5262a44b19df9bbdf457d8aMike Lockwood } 5672f6a3885533a52758c2cd4f81f6123a712be8ae6Mike Lockwood 5682f6a3885533a52758c2cd4f81f6123a712be8ae6Mike Lockwood /** 5692f6a3885533a52758c2cd4f81f6123a712be8ae6Mike Lockwood * Returns list of paths for all mountable volumes. 5702f6a3885533a52758c2cd4f81f6123a712be8ae6Mike Lockwood * @hide 5712f6a3885533a52758c2cd4f81f6123a712be8ae6Mike Lockwood */ 5722f6a3885533a52758c2cd4f81f6123a712be8ae6Mike Lockwood public String[] getVolumePaths() { 5732f6a3885533a52758c2cd4f81f6123a712be8ae6Mike Lockwood StorageVolume[] volumes = getVolumeList(); 5742f6a3885533a52758c2cd4f81f6123a712be8ae6Mike Lockwood if (volumes == null) return null; 5752f6a3885533a52758c2cd4f81f6123a712be8ae6Mike Lockwood int count = volumes.length; 5762f6a3885533a52758c2cd4f81f6123a712be8ae6Mike Lockwood String[] paths = new String[count]; 5772f6a3885533a52758c2cd4f81f6123a712be8ae6Mike Lockwood for (int i = 0; i < count; i++) { 5782f6a3885533a52758c2cd4f81f6123a712be8ae6Mike Lockwood paths[i] = volumes[i].getPath(); 5792f6a3885533a52758c2cd4f81f6123a712be8ae6Mike Lockwood } 5802f6a3885533a52758c2cd4f81f6123a712be8ae6Mike Lockwood return paths; 5812f6a3885533a52758c2cd4f81f6123a712be8ae6Mike Lockwood } 582b104340496e3a531e26c8f428c808eca0e039f50San Mehat} 583