StorageManager.java revision 38cf8867a8d3e8d5159abd0bd0e6a3b0b8348b94
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
19b104340496e3a531e26c8f428c808eca0e039f50San Mehatimport android.os.Handler;
20a02b8b05dd1e8b8cf169e1f89542ef835b11fc13Kenny Rootimport android.os.Looper;
21b104340496e3a531e26c8f428c808eca0e039f50San Mehatimport android.os.Message;
22a02b8b05dd1e8b8cf169e1f89542ef835b11fc13Kenny Rootimport android.os.RemoteException;
23b104340496e3a531e26c8f428c808eca0e039f50San Mehatimport android.os.ServiceManager;
24b104340496e3a531e26c8f428c808eca0e039f50San Mehatimport android.util.Log;
25b104340496e3a531e26c8f428c808eca0e039f50San Mehat
2605105f7abe02b2dff91d6260b3628c8b97816babKenny Rootimport java.lang.ref.WeakReference;
27b104340496e3a531e26c8f428c808eca0e039f50San Mehatimport java.util.ArrayList;
2805105f7abe02b2dff91d6260b3628c8b97816babKenny Rootimport java.util.Iterator;
2905105f7abe02b2dff91d6260b3628c8b97816babKenny Rootimport java.util.LinkedList;
3005105f7abe02b2dff91d6260b3628c8b97816babKenny Rootimport java.util.List;
31b104340496e3a531e26c8f428c808eca0e039f50San Mehat
32b104340496e3a531e26c8f428c808eca0e039f50San Mehat/**
3305105f7abe02b2dff91d6260b3628c8b97816babKenny Root * StorageManager is the interface to the systems storage service. The storage
3405105f7abe02b2dff91d6260b3628c8b97816babKenny Root * manager handles storage-related items such as Opaque Binary Blobs (OBBs).
3505105f7abe02b2dff91d6260b3628c8b97816babKenny Root * <p>
3605105f7abe02b2dff91d6260b3628c8b97816babKenny Root * OBBs contain a filesystem that maybe be encrypted on disk and mounted
3705105f7abe02b2dff91d6260b3628c8b97816babKenny Root * on-demand from an application. OBBs are a good way of providing large amounts
3805105f7abe02b2dff91d6260b3628c8b97816babKenny Root * of binary assets without packaging them into APKs as they may be multiple
3905105f7abe02b2dff91d6260b3628c8b97816babKenny Root * gigabytes in size. However, due to their size, they're most likely stored in
4005105f7abe02b2dff91d6260b3628c8b97816babKenny Root * a shared storage pool accessible from all programs. The system does not
4105105f7abe02b2dff91d6260b3628c8b97816babKenny Root * guarantee the security of the OBB file itself: if any program modifies the
4205105f7abe02b2dff91d6260b3628c8b97816babKenny Root * OBB, there is no guarantee that a read from that OBB will produce the
4305105f7abe02b2dff91d6260b3628c8b97816babKenny Root * expected output.
4405105f7abe02b2dff91d6260b3628c8b97816babKenny Root * <p>
45b104340496e3a531e26c8f428c808eca0e039f50San Mehat * Get an instance of this class by calling
4605105f7abe02b2dff91d6260b3628c8b97816babKenny Root * {@link android.content.Context#getSystemService(java.lang.String)} with an
4705105f7abe02b2dff91d6260b3628c8b97816babKenny Root * argument of {@link android.content.Context#STORAGE_SERVICE}.
48b104340496e3a531e26c8f428c808eca0e039f50San Mehat */
49b104340496e3a531e26c8f428c808eca0e039f50San Mehat
50b104340496e3a531e26c8f428c808eca0e039f50San Mehatpublic class StorageManager
51b104340496e3a531e26c8f428c808eca0e039f50San Mehat{
52b104340496e3a531e26c8f428c808eca0e039f50San Mehat    private static final String TAG = "StorageManager";
53b104340496e3a531e26c8f428c808eca0e039f50San Mehat
54b104340496e3a531e26c8f428c808eca0e039f50San Mehat    /*
55b104340496e3a531e26c8f428c808eca0e039f50San Mehat     * Our internal MountService binder reference
56b104340496e3a531e26c8f428c808eca0e039f50San Mehat     */
57b104340496e3a531e26c8f428c808eca0e039f50San Mehat    private IMountService mMountService;
58b104340496e3a531e26c8f428c808eca0e039f50San Mehat
59b104340496e3a531e26c8f428c808eca0e039f50San Mehat    /*
60b104340496e3a531e26c8f428c808eca0e039f50San Mehat     * The looper target for callbacks
61b104340496e3a531e26c8f428c808eca0e039f50San Mehat     */
62b104340496e3a531e26c8f428c808eca0e039f50San Mehat    Looper mTgtLooper;
63b104340496e3a531e26c8f428c808eca0e039f50San Mehat
64b104340496e3a531e26c8f428c808eca0e039f50San Mehat    /*
65b104340496e3a531e26c8f428c808eca0e039f50San Mehat     * Target listener for binder callbacks
66b104340496e3a531e26c8f428c808eca0e039f50San Mehat     */
67b104340496e3a531e26c8f428c808eca0e039f50San Mehat    private MountServiceBinderListener mBinderListener;
68b104340496e3a531e26c8f428c808eca0e039f50San Mehat
69b104340496e3a531e26c8f428c808eca0e039f50San Mehat    /*
70b104340496e3a531e26c8f428c808eca0e039f50San Mehat     * List of our listeners
71b104340496e3a531e26c8f428c808eca0e039f50San Mehat     */
72b104340496e3a531e26c8f428c808eca0e039f50San Mehat    private ArrayList<ListenerDelegate> mListeners = new ArrayList<ListenerDelegate>();
73b104340496e3a531e26c8f428c808eca0e039f50San Mehat
74b104340496e3a531e26c8f428c808eca0e039f50San Mehat    private class MountServiceBinderListener extends IMountServiceListener.Stub {
75b104340496e3a531e26c8f428c808eca0e039f50San Mehat        public void onUsbMassStorageConnectionChanged(boolean available) {
76b104340496e3a531e26c8f428c808eca0e039f50San Mehat            final int size = mListeners.size();
77b104340496e3a531e26c8f428c808eca0e039f50San Mehat            for (int i = 0; i < size; i++) {
78b104340496e3a531e26c8f428c808eca0e039f50San Mehat                mListeners.get(i).sendShareAvailabilityChanged(available);
79b104340496e3a531e26c8f428c808eca0e039f50San Mehat            }
80b104340496e3a531e26c8f428c808eca0e039f50San Mehat        }
81b104340496e3a531e26c8f428c808eca0e039f50San Mehat
82b104340496e3a531e26c8f428c808eca0e039f50San Mehat        public void onStorageStateChanged(String path, String oldState, String newState) {
83b104340496e3a531e26c8f428c808eca0e039f50San Mehat            final int size = mListeners.size();
84b104340496e3a531e26c8f428c808eca0e039f50San Mehat            for (int i = 0; i < size; i++) {
85b104340496e3a531e26c8f428c808eca0e039f50San Mehat                mListeners.get(i).sendStorageStateChanged(path, oldState, newState);
86b104340496e3a531e26c8f428c808eca0e039f50San Mehat            }
87b104340496e3a531e26c8f428c808eca0e039f50San Mehat        }
88b104340496e3a531e26c8f428c808eca0e039f50San Mehat    }
89b104340496e3a531e26c8f428c808eca0e039f50San Mehat
90b104340496e3a531e26c8f428c808eca0e039f50San Mehat    /**
91a02b8b05dd1e8b8cf169e1f89542ef835b11fc13Kenny Root     * Binder listener for OBB action results.
92a02b8b05dd1e8b8cf169e1f89542ef835b11fc13Kenny Root     */
9305105f7abe02b2dff91d6260b3628c8b97816babKenny Root    private final ObbActionListener mObbActionListener = new ObbActionListener();
9405105f7abe02b2dff91d6260b3628c8b97816babKenny Root
9505105f7abe02b2dff91d6260b3628c8b97816babKenny Root    private class ObbActionListener extends IObbActionListener.Stub {
9605105f7abe02b2dff91d6260b3628c8b97816babKenny Root        private List<WeakReference<ObbListenerDelegate>> mListeners = new LinkedList<WeakReference<ObbListenerDelegate>>();
9705105f7abe02b2dff91d6260b3628c8b97816babKenny Root
98a02b8b05dd1e8b8cf169e1f89542ef835b11fc13Kenny Root        @Override
99a02b8b05dd1e8b8cf169e1f89542ef835b11fc13Kenny Root        public void onObbResult(String filename, String status) throws RemoteException {
10005105f7abe02b2dff91d6260b3628c8b97816babKenny Root            synchronized (mListeners) {
10105105f7abe02b2dff91d6260b3628c8b97816babKenny Root                final Iterator<WeakReference<ObbListenerDelegate>> iter = mListeners.iterator();
10205105f7abe02b2dff91d6260b3628c8b97816babKenny Root                while (iter.hasNext()) {
10305105f7abe02b2dff91d6260b3628c8b97816babKenny Root                    final WeakReference<ObbListenerDelegate> ref = iter.next();
10405105f7abe02b2dff91d6260b3628c8b97816babKenny Root
10505105f7abe02b2dff91d6260b3628c8b97816babKenny Root                    final ObbListenerDelegate delegate = (ref == null) ? null : ref.get();
10605105f7abe02b2dff91d6260b3628c8b97816babKenny Root                    if (delegate == null) {
10705105f7abe02b2dff91d6260b3628c8b97816babKenny Root                        iter.remove();
10805105f7abe02b2dff91d6260b3628c8b97816babKenny Root                        continue;
10905105f7abe02b2dff91d6260b3628c8b97816babKenny Root                    }
11005105f7abe02b2dff91d6260b3628c8b97816babKenny Root
11105105f7abe02b2dff91d6260b3628c8b97816babKenny Root                    delegate.sendObbStateChanged(filename, status);
11205105f7abe02b2dff91d6260b3628c8b97816babKenny Root                }
11305105f7abe02b2dff91d6260b3628c8b97816babKenny Root            }
11405105f7abe02b2dff91d6260b3628c8b97816babKenny Root        }
11505105f7abe02b2dff91d6260b3628c8b97816babKenny Root
11605105f7abe02b2dff91d6260b3628c8b97816babKenny Root        public void addListener(OnObbStateChangeListener listener) {
11705105f7abe02b2dff91d6260b3628c8b97816babKenny Root            if (listener == null) {
11805105f7abe02b2dff91d6260b3628c8b97816babKenny Root                return;
11905105f7abe02b2dff91d6260b3628c8b97816babKenny Root            }
12005105f7abe02b2dff91d6260b3628c8b97816babKenny Root
12105105f7abe02b2dff91d6260b3628c8b97816babKenny Root            synchronized (mListeners) {
12205105f7abe02b2dff91d6260b3628c8b97816babKenny Root                final Iterator<WeakReference<ObbListenerDelegate>> iter = mListeners.iterator();
12305105f7abe02b2dff91d6260b3628c8b97816babKenny Root                while (iter.hasNext()) {
12405105f7abe02b2dff91d6260b3628c8b97816babKenny Root                    final WeakReference<ObbListenerDelegate> ref = iter.next();
12505105f7abe02b2dff91d6260b3628c8b97816babKenny Root
12605105f7abe02b2dff91d6260b3628c8b97816babKenny Root                    final ObbListenerDelegate delegate = (ref == null) ? null : ref.get();
12705105f7abe02b2dff91d6260b3628c8b97816babKenny Root                    if (delegate == null) {
12805105f7abe02b2dff91d6260b3628c8b97816babKenny Root                        iter.remove();
12905105f7abe02b2dff91d6260b3628c8b97816babKenny Root                        continue;
13005105f7abe02b2dff91d6260b3628c8b97816babKenny Root                    }
13105105f7abe02b2dff91d6260b3628c8b97816babKenny Root
13205105f7abe02b2dff91d6260b3628c8b97816babKenny Root                    /*
13305105f7abe02b2dff91d6260b3628c8b97816babKenny Root                     * If we're already in the listeners, we don't need to be in
13405105f7abe02b2dff91d6260b3628c8b97816babKenny Root                     * there again.
13505105f7abe02b2dff91d6260b3628c8b97816babKenny Root                     */
13605105f7abe02b2dff91d6260b3628c8b97816babKenny Root                    if (listener.equals(delegate.getListener())) {
13705105f7abe02b2dff91d6260b3628c8b97816babKenny Root                        return;
13805105f7abe02b2dff91d6260b3628c8b97816babKenny Root                    }
13905105f7abe02b2dff91d6260b3628c8b97816babKenny Root                }
14005105f7abe02b2dff91d6260b3628c8b97816babKenny Root
14105105f7abe02b2dff91d6260b3628c8b97816babKenny Root                final ObbListenerDelegate delegate = new ObbListenerDelegate(listener);
14205105f7abe02b2dff91d6260b3628c8b97816babKenny Root                mListeners.add(new WeakReference<ObbListenerDelegate>(delegate));
14305105f7abe02b2dff91d6260b3628c8b97816babKenny Root            }
14405105f7abe02b2dff91d6260b3628c8b97816babKenny Root        }
14505105f7abe02b2dff91d6260b3628c8b97816babKenny Root    }
14605105f7abe02b2dff91d6260b3628c8b97816babKenny Root
14705105f7abe02b2dff91d6260b3628c8b97816babKenny Root    /**
14805105f7abe02b2dff91d6260b3628c8b97816babKenny Root     * Private class containing sender and receiver code for StorageEvents.
14905105f7abe02b2dff91d6260b3628c8b97816babKenny Root     */
15005105f7abe02b2dff91d6260b3628c8b97816babKenny Root    private class ObbListenerDelegate {
15105105f7abe02b2dff91d6260b3628c8b97816babKenny Root        private final WeakReference<OnObbStateChangeListener> mObbEventListenerRef;
15205105f7abe02b2dff91d6260b3628c8b97816babKenny Root        private final Handler mHandler;
15305105f7abe02b2dff91d6260b3628c8b97816babKenny Root
15405105f7abe02b2dff91d6260b3628c8b97816babKenny Root        ObbListenerDelegate(OnObbStateChangeListener listener) {
15505105f7abe02b2dff91d6260b3628c8b97816babKenny Root            mObbEventListenerRef = new WeakReference<OnObbStateChangeListener>(listener);
15605105f7abe02b2dff91d6260b3628c8b97816babKenny Root            mHandler = new Handler(mTgtLooper) {
15705105f7abe02b2dff91d6260b3628c8b97816babKenny Root                @Override
15805105f7abe02b2dff91d6260b3628c8b97816babKenny Root                public void handleMessage(Message msg) {
15905105f7abe02b2dff91d6260b3628c8b97816babKenny Root                    final OnObbStateChangeListener listener = getListener();
16005105f7abe02b2dff91d6260b3628c8b97816babKenny Root                    if (listener == null) {
16105105f7abe02b2dff91d6260b3628c8b97816babKenny Root                        return;
16205105f7abe02b2dff91d6260b3628c8b97816babKenny Root                    }
16305105f7abe02b2dff91d6260b3628c8b97816babKenny Root
16405105f7abe02b2dff91d6260b3628c8b97816babKenny Root                    StorageEvent e = (StorageEvent) msg.obj;
16505105f7abe02b2dff91d6260b3628c8b97816babKenny Root
16605105f7abe02b2dff91d6260b3628c8b97816babKenny Root                    if (msg.what == StorageEvent.EVENT_OBB_STATE_CHANGED) {
16705105f7abe02b2dff91d6260b3628c8b97816babKenny Root                        ObbStateChangedStorageEvent ev = (ObbStateChangedStorageEvent) e;
16805105f7abe02b2dff91d6260b3628c8b97816babKenny Root                        listener.onObbStateChange(ev.path, ev.state);
16905105f7abe02b2dff91d6260b3628c8b97816babKenny Root                    } else {
17005105f7abe02b2dff91d6260b3628c8b97816babKenny Root                        Log.e(TAG, "Unsupported event " + msg.what);
17105105f7abe02b2dff91d6260b3628c8b97816babKenny Root                    }
17205105f7abe02b2dff91d6260b3628c8b97816babKenny Root                }
17305105f7abe02b2dff91d6260b3628c8b97816babKenny Root            };
17405105f7abe02b2dff91d6260b3628c8b97816babKenny Root        }
17505105f7abe02b2dff91d6260b3628c8b97816babKenny Root
17605105f7abe02b2dff91d6260b3628c8b97816babKenny Root        OnObbStateChangeListener getListener() {
17705105f7abe02b2dff91d6260b3628c8b97816babKenny Root            if (mObbEventListenerRef == null) {
17805105f7abe02b2dff91d6260b3628c8b97816babKenny Root                return null;
17905105f7abe02b2dff91d6260b3628c8b97816babKenny Root            }
18005105f7abe02b2dff91d6260b3628c8b97816babKenny Root            return mObbEventListenerRef.get();
18105105f7abe02b2dff91d6260b3628c8b97816babKenny Root        }
18205105f7abe02b2dff91d6260b3628c8b97816babKenny Root
18305105f7abe02b2dff91d6260b3628c8b97816babKenny Root        void sendObbStateChanged(String path, String state) {
18405105f7abe02b2dff91d6260b3628c8b97816babKenny Root            ObbStateChangedStorageEvent e = new ObbStateChangedStorageEvent(path, state);
18505105f7abe02b2dff91d6260b3628c8b97816babKenny Root            mHandler.sendMessage(e.getMessage());
18605105f7abe02b2dff91d6260b3628c8b97816babKenny Root        }
18705105f7abe02b2dff91d6260b3628c8b97816babKenny Root    }
18805105f7abe02b2dff91d6260b3628c8b97816babKenny Root
18905105f7abe02b2dff91d6260b3628c8b97816babKenny Root    /**
19005105f7abe02b2dff91d6260b3628c8b97816babKenny Root     * Message sent during an OBB status change event.
19105105f7abe02b2dff91d6260b3628c8b97816babKenny Root     */
19205105f7abe02b2dff91d6260b3628c8b97816babKenny Root    private class ObbStateChangedStorageEvent extends StorageEvent {
19305105f7abe02b2dff91d6260b3628c8b97816babKenny Root        public final String path;
19405105f7abe02b2dff91d6260b3628c8b97816babKenny Root        public final String state;
19505105f7abe02b2dff91d6260b3628c8b97816babKenny Root
19605105f7abe02b2dff91d6260b3628c8b97816babKenny Root        public ObbStateChangedStorageEvent(String path, String state) {
19705105f7abe02b2dff91d6260b3628c8b97816babKenny Root            super(EVENT_OBB_STATE_CHANGED);
19805105f7abe02b2dff91d6260b3628c8b97816babKenny Root            this.path = path;
19905105f7abe02b2dff91d6260b3628c8b97816babKenny Root            this.state = state;
200a02b8b05dd1e8b8cf169e1f89542ef835b11fc13Kenny Root        }
201a02b8b05dd1e8b8cf169e1f89542ef835b11fc13Kenny Root    }
202a02b8b05dd1e8b8cf169e1f89542ef835b11fc13Kenny Root
203a02b8b05dd1e8b8cf169e1f89542ef835b11fc13Kenny Root    /**
204b104340496e3a531e26c8f428c808eca0e039f50San Mehat     * Private base class for messages sent between the callback thread
205b104340496e3a531e26c8f428c808eca0e039f50San Mehat     * and the target looper handler.
206b104340496e3a531e26c8f428c808eca0e039f50San Mehat     */
207b104340496e3a531e26c8f428c808eca0e039f50San Mehat    private class StorageEvent {
20805105f7abe02b2dff91d6260b3628c8b97816babKenny Root        static final int EVENT_UMS_CONNECTION_CHANGED = 1;
20905105f7abe02b2dff91d6260b3628c8b97816babKenny Root        static final int EVENT_STORAGE_STATE_CHANGED = 2;
21005105f7abe02b2dff91d6260b3628c8b97816babKenny Root        static final int EVENT_OBB_STATE_CHANGED = 3;
211b104340496e3a531e26c8f428c808eca0e039f50San Mehat
212b104340496e3a531e26c8f428c808eca0e039f50San Mehat        private Message mMessage;
213b104340496e3a531e26c8f428c808eca0e039f50San Mehat
214b104340496e3a531e26c8f428c808eca0e039f50San Mehat        public StorageEvent(int what) {
215b104340496e3a531e26c8f428c808eca0e039f50San Mehat            mMessage = Message.obtain();
216b104340496e3a531e26c8f428c808eca0e039f50San Mehat            mMessage.what = what;
217b104340496e3a531e26c8f428c808eca0e039f50San Mehat            mMessage.obj = this;
218b104340496e3a531e26c8f428c808eca0e039f50San Mehat        }
219b104340496e3a531e26c8f428c808eca0e039f50San Mehat
220b104340496e3a531e26c8f428c808eca0e039f50San Mehat        public Message getMessage() {
221b104340496e3a531e26c8f428c808eca0e039f50San Mehat            return mMessage;
222b104340496e3a531e26c8f428c808eca0e039f50San Mehat        }
223b104340496e3a531e26c8f428c808eca0e039f50San Mehat    }
224b104340496e3a531e26c8f428c808eca0e039f50San Mehat
225b104340496e3a531e26c8f428c808eca0e039f50San Mehat    /**
226b104340496e3a531e26c8f428c808eca0e039f50San Mehat     * Message sent on a USB mass storage connection change.
227b104340496e3a531e26c8f428c808eca0e039f50San Mehat     */
228b104340496e3a531e26c8f428c808eca0e039f50San Mehat    private class UmsConnectionChangedStorageEvent extends StorageEvent {
229b104340496e3a531e26c8f428c808eca0e039f50San Mehat        public boolean available;
230b104340496e3a531e26c8f428c808eca0e039f50San Mehat
231b104340496e3a531e26c8f428c808eca0e039f50San Mehat        public UmsConnectionChangedStorageEvent(boolean a) {
232b104340496e3a531e26c8f428c808eca0e039f50San Mehat            super(EVENT_UMS_CONNECTION_CHANGED);
233b104340496e3a531e26c8f428c808eca0e039f50San Mehat            available = a;
234b104340496e3a531e26c8f428c808eca0e039f50San Mehat        }
235b104340496e3a531e26c8f428c808eca0e039f50San Mehat    }
236b104340496e3a531e26c8f428c808eca0e039f50San Mehat
237b104340496e3a531e26c8f428c808eca0e039f50San Mehat    /**
238b104340496e3a531e26c8f428c808eca0e039f50San Mehat     * Message sent on volume state change.
239b104340496e3a531e26c8f428c808eca0e039f50San Mehat     */
240b104340496e3a531e26c8f428c808eca0e039f50San Mehat    private class StorageStateChangedStorageEvent extends StorageEvent {
241b104340496e3a531e26c8f428c808eca0e039f50San Mehat        public String path;
242b104340496e3a531e26c8f428c808eca0e039f50San Mehat        public String oldState;
243b104340496e3a531e26c8f428c808eca0e039f50San Mehat        public String newState;
244b104340496e3a531e26c8f428c808eca0e039f50San Mehat
245b104340496e3a531e26c8f428c808eca0e039f50San Mehat        public StorageStateChangedStorageEvent(String p, String oldS, String newS) {
246b104340496e3a531e26c8f428c808eca0e039f50San Mehat            super(EVENT_STORAGE_STATE_CHANGED);
247b104340496e3a531e26c8f428c808eca0e039f50San Mehat            path = p;
248b104340496e3a531e26c8f428c808eca0e039f50San Mehat            oldState = oldS;
249b104340496e3a531e26c8f428c808eca0e039f50San Mehat            newState = newS;
250b104340496e3a531e26c8f428c808eca0e039f50San Mehat        }
251b104340496e3a531e26c8f428c808eca0e039f50San Mehat    }
252b104340496e3a531e26c8f428c808eca0e039f50San Mehat
253b104340496e3a531e26c8f428c808eca0e039f50San Mehat    /**
254b104340496e3a531e26c8f428c808eca0e039f50San Mehat     * Private class containing sender and receiver code for StorageEvents.
255b104340496e3a531e26c8f428c808eca0e039f50San Mehat     */
256b104340496e3a531e26c8f428c808eca0e039f50San Mehat    private class ListenerDelegate {
257b104340496e3a531e26c8f428c808eca0e039f50San Mehat        final StorageEventListener mStorageEventListener;
258b104340496e3a531e26c8f428c808eca0e039f50San Mehat        private final Handler mHandler;
259b104340496e3a531e26c8f428c808eca0e039f50San Mehat
260b104340496e3a531e26c8f428c808eca0e039f50San Mehat        ListenerDelegate(StorageEventListener listener) {
261b104340496e3a531e26c8f428c808eca0e039f50San Mehat            mStorageEventListener = listener;
262b104340496e3a531e26c8f428c808eca0e039f50San Mehat            mHandler = new Handler(mTgtLooper) {
263b104340496e3a531e26c8f428c808eca0e039f50San Mehat                @Override
264b104340496e3a531e26c8f428c808eca0e039f50San Mehat                public void handleMessage(Message msg) {
265b104340496e3a531e26c8f428c808eca0e039f50San Mehat                    StorageEvent e = (StorageEvent) msg.obj;
266b104340496e3a531e26c8f428c808eca0e039f50San Mehat
267b104340496e3a531e26c8f428c808eca0e039f50San Mehat                    if (msg.what == StorageEvent.EVENT_UMS_CONNECTION_CHANGED) {
268b104340496e3a531e26c8f428c808eca0e039f50San Mehat                        UmsConnectionChangedStorageEvent ev = (UmsConnectionChangedStorageEvent) e;
269b104340496e3a531e26c8f428c808eca0e039f50San Mehat                        mStorageEventListener.onUsbMassStorageConnectionChanged(ev.available);
270b104340496e3a531e26c8f428c808eca0e039f50San Mehat                    } else if (msg.what == StorageEvent.EVENT_STORAGE_STATE_CHANGED) {
271b104340496e3a531e26c8f428c808eca0e039f50San Mehat                        StorageStateChangedStorageEvent ev = (StorageStateChangedStorageEvent) e;
272b104340496e3a531e26c8f428c808eca0e039f50San Mehat                        mStorageEventListener.onStorageStateChanged(ev.path, ev.oldState, ev.newState);
273b104340496e3a531e26c8f428c808eca0e039f50San Mehat                    } else {
274b104340496e3a531e26c8f428c808eca0e039f50San Mehat                        Log.e(TAG, "Unsupported event " + msg.what);
275b104340496e3a531e26c8f428c808eca0e039f50San Mehat                    }
276b104340496e3a531e26c8f428c808eca0e039f50San Mehat                }
277b104340496e3a531e26c8f428c808eca0e039f50San Mehat            };
278b104340496e3a531e26c8f428c808eca0e039f50San Mehat        }
279b104340496e3a531e26c8f428c808eca0e039f50San Mehat
280b104340496e3a531e26c8f428c808eca0e039f50San Mehat        StorageEventListener getListener() {
281b104340496e3a531e26c8f428c808eca0e039f50San Mehat            return mStorageEventListener;
282b104340496e3a531e26c8f428c808eca0e039f50San Mehat        }
283b104340496e3a531e26c8f428c808eca0e039f50San Mehat
284b104340496e3a531e26c8f428c808eca0e039f50San Mehat        void sendShareAvailabilityChanged(boolean available) {
285b104340496e3a531e26c8f428c808eca0e039f50San Mehat            UmsConnectionChangedStorageEvent e = new UmsConnectionChangedStorageEvent(available);
286b104340496e3a531e26c8f428c808eca0e039f50San Mehat            mHandler.sendMessage(e.getMessage());
287b104340496e3a531e26c8f428c808eca0e039f50San Mehat        }
288b104340496e3a531e26c8f428c808eca0e039f50San Mehat
289b104340496e3a531e26c8f428c808eca0e039f50San Mehat        void sendStorageStateChanged(String path, String oldState, String newState) {
290b104340496e3a531e26c8f428c808eca0e039f50San Mehat            StorageStateChangedStorageEvent e = new StorageStateChangedStorageEvent(path, oldState, newState);
291b104340496e3a531e26c8f428c808eca0e039f50San Mehat            mHandler.sendMessage(e.getMessage());
292b104340496e3a531e26c8f428c808eca0e039f50San Mehat        }
293b104340496e3a531e26c8f428c808eca0e039f50San Mehat    }
294b104340496e3a531e26c8f428c808eca0e039f50San Mehat
295b104340496e3a531e26c8f428c808eca0e039f50San Mehat    /**
296b104340496e3a531e26c8f428c808eca0e039f50San Mehat     * Constructs a StorageManager object through which an application can
297b104340496e3a531e26c8f428c808eca0e039f50San Mehat     * can communicate with the systems mount service.
298b104340496e3a531e26c8f428c808eca0e039f50San Mehat     *
299b104340496e3a531e26c8f428c808eca0e039f50San Mehat     * @param tgtLooper The {@android.os.Looper} which events will be received on.
300b104340496e3a531e26c8f428c808eca0e039f50San Mehat     *
301b104340496e3a531e26c8f428c808eca0e039f50San Mehat     * <p>Applications can get instance of this class by calling
302b104340496e3a531e26c8f428c808eca0e039f50San Mehat     * {@link android.content.Context#getSystemService(java.lang.String)} with an argument
303b104340496e3a531e26c8f428c808eca0e039f50San Mehat     * of {@link android.content.Context#STORAGE_SERVICE}.
304b104340496e3a531e26c8f428c808eca0e039f50San Mehat     *
305b104340496e3a531e26c8f428c808eca0e039f50San Mehat     * @hide
306b104340496e3a531e26c8f428c808eca0e039f50San Mehat     */
307b104340496e3a531e26c8f428c808eca0e039f50San Mehat    public StorageManager(Looper tgtLooper) throws RemoteException {
308b104340496e3a531e26c8f428c808eca0e039f50San Mehat        mMountService = IMountService.Stub.asInterface(ServiceManager.getService("mount"));
309b104340496e3a531e26c8f428c808eca0e039f50San Mehat        if (mMountService == null) {
310b104340496e3a531e26c8f428c808eca0e039f50San Mehat            Log.e(TAG, "Unable to connect to mount service! - is it running yet?");
311b104340496e3a531e26c8f428c808eca0e039f50San Mehat            return;
312b104340496e3a531e26c8f428c808eca0e039f50San Mehat        }
313b104340496e3a531e26c8f428c808eca0e039f50San Mehat        mTgtLooper = tgtLooper;
314b104340496e3a531e26c8f428c808eca0e039f50San Mehat        mBinderListener = new MountServiceBinderListener();
315b104340496e3a531e26c8f428c808eca0e039f50San Mehat        mMountService.registerListener(mBinderListener);
316b104340496e3a531e26c8f428c808eca0e039f50San Mehat    }
317b104340496e3a531e26c8f428c808eca0e039f50San Mehat
318b104340496e3a531e26c8f428c808eca0e039f50San Mehat
319b104340496e3a531e26c8f428c808eca0e039f50San Mehat    /**
320b104340496e3a531e26c8f428c808eca0e039f50San Mehat     * Registers a {@link android.os.storage.StorageEventListener StorageEventListener}.
321b104340496e3a531e26c8f428c808eca0e039f50San Mehat     *
322b104340496e3a531e26c8f428c808eca0e039f50San Mehat     * @param listener A {@link android.os.storage.StorageEventListener StorageEventListener} object.
323b104340496e3a531e26c8f428c808eca0e039f50San Mehat     *
32402c8730c1bf19daf48bec8c6995df676a00a73b1Kenny Root     * @hide
325b104340496e3a531e26c8f428c808eca0e039f50San Mehat     */
326b104340496e3a531e26c8f428c808eca0e039f50San Mehat    public void registerListener(StorageEventListener listener) {
327b104340496e3a531e26c8f428c808eca0e039f50San Mehat        if (listener == null) {
328b104340496e3a531e26c8f428c808eca0e039f50San Mehat            return;
329b104340496e3a531e26c8f428c808eca0e039f50San Mehat        }
330b104340496e3a531e26c8f428c808eca0e039f50San Mehat
331b104340496e3a531e26c8f428c808eca0e039f50San Mehat        synchronized (mListeners) {
332b104340496e3a531e26c8f428c808eca0e039f50San Mehat            mListeners.add(new ListenerDelegate(listener));
333b104340496e3a531e26c8f428c808eca0e039f50San Mehat        }
334b104340496e3a531e26c8f428c808eca0e039f50San Mehat    }
335b104340496e3a531e26c8f428c808eca0e039f50San Mehat
336b104340496e3a531e26c8f428c808eca0e039f50San Mehat    /**
337b104340496e3a531e26c8f428c808eca0e039f50San Mehat     * Unregisters a {@link android.os.storage.StorageEventListener StorageEventListener}.
338b104340496e3a531e26c8f428c808eca0e039f50San Mehat     *
339b104340496e3a531e26c8f428c808eca0e039f50San Mehat     * @param listener A {@link android.os.storage.StorageEventListener StorageEventListener} object.
340b104340496e3a531e26c8f428c808eca0e039f50San Mehat     *
34102c8730c1bf19daf48bec8c6995df676a00a73b1Kenny Root     * @hide
342b104340496e3a531e26c8f428c808eca0e039f50San Mehat     */
343b104340496e3a531e26c8f428c808eca0e039f50San Mehat    public void unregisterListener(StorageEventListener listener) {
344b104340496e3a531e26c8f428c808eca0e039f50San Mehat        if (listener == null) {
345b104340496e3a531e26c8f428c808eca0e039f50San Mehat            return;
346b104340496e3a531e26c8f428c808eca0e039f50San Mehat        }
347b104340496e3a531e26c8f428c808eca0e039f50San Mehat
348b104340496e3a531e26c8f428c808eca0e039f50San Mehat        synchronized (mListeners) {
349b104340496e3a531e26c8f428c808eca0e039f50San Mehat            final int size = mListeners.size();
350b104340496e3a531e26c8f428c808eca0e039f50San Mehat            for (int i=0 ; i<size ; i++) {
351b104340496e3a531e26c8f428c808eca0e039f50San Mehat                ListenerDelegate l = mListeners.get(i);
352b104340496e3a531e26c8f428c808eca0e039f50San Mehat                if (l.getListener() == listener) {
353b104340496e3a531e26c8f428c808eca0e039f50San Mehat                    mListeners.remove(i);
354b104340496e3a531e26c8f428c808eca0e039f50San Mehat                    break;
355b104340496e3a531e26c8f428c808eca0e039f50San Mehat                }
356b104340496e3a531e26c8f428c808eca0e039f50San Mehat            }
357b104340496e3a531e26c8f428c808eca0e039f50San Mehat        }
358b104340496e3a531e26c8f428c808eca0e039f50San Mehat    }
359b104340496e3a531e26c8f428c808eca0e039f50San Mehat
360b104340496e3a531e26c8f428c808eca0e039f50San Mehat    /**
361b104340496e3a531e26c8f428c808eca0e039f50San Mehat     * Enables USB Mass Storage (UMS) on the device.
36202c8730c1bf19daf48bec8c6995df676a00a73b1Kenny Root     *
36302c8730c1bf19daf48bec8c6995df676a00a73b1Kenny Root     * @hide
364b104340496e3a531e26c8f428c808eca0e039f50San Mehat     */
3650eec21d97d9dc4eb4fdbad0e4c0fc53703452d02Suchi Amalapurapu    public void enableUsbMassStorage() {
366b104340496e3a531e26c8f428c808eca0e039f50San Mehat        try {
3670eec21d97d9dc4eb4fdbad0e4c0fc53703452d02Suchi Amalapurapu            mMountService.setUsbMassStorageEnabled(true);
368b104340496e3a531e26c8f428c808eca0e039f50San Mehat        } catch (Exception ex) {
369b104340496e3a531e26c8f428c808eca0e039f50San Mehat            Log.e(TAG, "Failed to enable UMS", ex);
370b104340496e3a531e26c8f428c808eca0e039f50San Mehat        }
371b104340496e3a531e26c8f428c808eca0e039f50San Mehat    }
372b104340496e3a531e26c8f428c808eca0e039f50San Mehat
373b104340496e3a531e26c8f428c808eca0e039f50San Mehat    /**
374b104340496e3a531e26c8f428c808eca0e039f50San Mehat     * Disables USB Mass Storage (UMS) on the device.
37502c8730c1bf19daf48bec8c6995df676a00a73b1Kenny Root     *
37602c8730c1bf19daf48bec8c6995df676a00a73b1Kenny Root     * @hide
377b104340496e3a531e26c8f428c808eca0e039f50San Mehat     */
3780eec21d97d9dc4eb4fdbad0e4c0fc53703452d02Suchi Amalapurapu    public void disableUsbMassStorage() {
379b104340496e3a531e26c8f428c808eca0e039f50San Mehat        try {
3800eec21d97d9dc4eb4fdbad0e4c0fc53703452d02Suchi Amalapurapu            mMountService.setUsbMassStorageEnabled(false);
381b104340496e3a531e26c8f428c808eca0e039f50San Mehat        } catch (Exception ex) {
382b104340496e3a531e26c8f428c808eca0e039f50San Mehat            Log.e(TAG, "Failed to disable UMS", ex);
383b104340496e3a531e26c8f428c808eca0e039f50San Mehat        }
384b104340496e3a531e26c8f428c808eca0e039f50San Mehat    }
385b104340496e3a531e26c8f428c808eca0e039f50San Mehat
386b104340496e3a531e26c8f428c808eca0e039f50San Mehat    /**
387b104340496e3a531e26c8f428c808eca0e039f50San Mehat     * Query if a USB Mass Storage (UMS) host is connected.
388b104340496e3a531e26c8f428c808eca0e039f50San Mehat     * @return true if UMS host is connected.
38902c8730c1bf19daf48bec8c6995df676a00a73b1Kenny Root     *
39002c8730c1bf19daf48bec8c6995df676a00a73b1Kenny Root     * @hide
391b104340496e3a531e26c8f428c808eca0e039f50San Mehat     */
392b104340496e3a531e26c8f428c808eca0e039f50San Mehat    public boolean isUsbMassStorageConnected() {
393b104340496e3a531e26c8f428c808eca0e039f50San Mehat        try {
394b104340496e3a531e26c8f428c808eca0e039f50San Mehat            return mMountService.isUsbMassStorageConnected();
395b104340496e3a531e26c8f428c808eca0e039f50San Mehat        } catch (Exception ex) {
396b104340496e3a531e26c8f428c808eca0e039f50San Mehat            Log.e(TAG, "Failed to get UMS connection state", ex);
397b104340496e3a531e26c8f428c808eca0e039f50San Mehat        }
398b104340496e3a531e26c8f428c808eca0e039f50San Mehat        return false;
399b104340496e3a531e26c8f428c808eca0e039f50San Mehat    }
400b104340496e3a531e26c8f428c808eca0e039f50San Mehat
401b104340496e3a531e26c8f428c808eca0e039f50San Mehat    /**
402b104340496e3a531e26c8f428c808eca0e039f50San Mehat     * Query if a USB Mass Storage (UMS) is enabled on the device.
403b104340496e3a531e26c8f428c808eca0e039f50San Mehat     * @return true if UMS host is enabled.
40402c8730c1bf19daf48bec8c6995df676a00a73b1Kenny Root     *
40502c8730c1bf19daf48bec8c6995df676a00a73b1Kenny Root     * @hide
406b104340496e3a531e26c8f428c808eca0e039f50San Mehat     */
407b104340496e3a531e26c8f428c808eca0e039f50San Mehat    public boolean isUsbMassStorageEnabled() {
408b104340496e3a531e26c8f428c808eca0e039f50San Mehat        try {
409b104340496e3a531e26c8f428c808eca0e039f50San Mehat            return mMountService.isUsbMassStorageEnabled();
410b104340496e3a531e26c8f428c808eca0e039f50San Mehat        } catch (RemoteException rex) {
411b104340496e3a531e26c8f428c808eca0e039f50San Mehat            Log.e(TAG, "Failed to get UMS enable state", rex);
412b104340496e3a531e26c8f428c808eca0e039f50San Mehat        }
413b104340496e3a531e26c8f428c808eca0e039f50San Mehat        return false;
414b104340496e3a531e26c8f428c808eca0e039f50San Mehat    }
41502c8730c1bf19daf48bec8c6995df676a00a73b1Kenny Root
41602c8730c1bf19daf48bec8c6995df676a00a73b1Kenny Root    /**
417a02b8b05dd1e8b8cf169e1f89542ef835b11fc13Kenny Root     * Mount an Opaque Binary Blob (OBB) file. If a <code>key</code> is
418a02b8b05dd1e8b8cf169e1f89542ef835b11fc13Kenny Root     * specified, it is supplied to the mounting process to be used in any
419a02b8b05dd1e8b8cf169e1f89542ef835b11fc13Kenny Root     * encryption used in the OBB.
420a02b8b05dd1e8b8cf169e1f89542ef835b11fc13Kenny Root     * <p>
42105105f7abe02b2dff91d6260b3628c8b97816babKenny Root     * The OBB will remain mounted for as long as the StorageManager reference
42205105f7abe02b2dff91d6260b3628c8b97816babKenny Root     * is held by the application. As soon as this reference is lost, the OBBs
42305105f7abe02b2dff91d6260b3628c8b97816babKenny Root     * in use will be unmounted. The {@link OnObbStateChangeListener} registered with
42405105f7abe02b2dff91d6260b3628c8b97816babKenny Root     * this call will receive all further OBB-related events until it goes out
42505105f7abe02b2dff91d6260b3628c8b97816babKenny Root     * of scope. If the caller is not interested in whether the call succeeds,
42605105f7abe02b2dff91d6260b3628c8b97816babKenny Root     * the <code>listener</code> may be specified as <code>null</code>.
42705105f7abe02b2dff91d6260b3628c8b97816babKenny Root     * <p>
428a02b8b05dd1e8b8cf169e1f89542ef835b11fc13Kenny Root     * <em>Note:</em> you can only mount OBB files for which the OBB tag on the
429a02b8b05dd1e8b8cf169e1f89542ef835b11fc13Kenny Root     * file matches a package ID that is owned by the calling program's UID.
43005105f7abe02b2dff91d6260b3628c8b97816babKenny Root     * That is, shared UID applications can attempt to mount any other
431a02b8b05dd1e8b8cf169e1f89542ef835b11fc13Kenny Root     * application's OBB that shares its UID.
432a02b8b05dd1e8b8cf169e1f89542ef835b11fc13Kenny Root     *
433a02b8b05dd1e8b8cf169e1f89542ef835b11fc13Kenny Root     * @param filename the path to the OBB file
43405105f7abe02b2dff91d6260b3628c8b97816babKenny Root     * @param key secret used to encrypt the OBB; may be <code>null</code> if no
43505105f7abe02b2dff91d6260b3628c8b97816babKenny Root     *            encryption was used on the OBB.
436a02b8b05dd1e8b8cf169e1f89542ef835b11fc13Kenny Root     * @return whether the mount call was successfully queued or not
43702c8730c1bf19daf48bec8c6995df676a00a73b1Kenny Root     */
43805105f7abe02b2dff91d6260b3628c8b97816babKenny Root    public boolean mountObb(String filename, String key, OnObbStateChangeListener listener) {
43902c8730c1bf19daf48bec8c6995df676a00a73b1Kenny Root        try {
44005105f7abe02b2dff91d6260b3628c8b97816babKenny Root            mObbActionListener.addListener(listener);
441a02b8b05dd1e8b8cf169e1f89542ef835b11fc13Kenny Root            mMountService.mountObb(filename, key, mObbActionListener);
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>
45505105f7abe02b2dff91d6260b3628c8b97816babKenny Root     * The {@link OnObbStateChangeListener} registered with this call will receive all
45605105f7abe02b2dff91d6260b3628c8b97816babKenny Root     * further OBB-related events until it goes out of scope. If the caller is
45705105f7abe02b2dff91d6260b3628c8b97816babKenny Root     * not interested in whether the call succeeded, the listener may be
45805105f7abe02b2dff91d6260b3628c8b97816babKenny Root     * specified as <code>null</code>.
459a02b8b05dd1e8b8cf169e1f89542ef835b11fc13Kenny Root     * <p>
460a02b8b05dd1e8b8cf169e1f89542ef835b11fc13Kenny Root     * <em>Note:</em> you can only mount OBB files for which the OBB tag on the
461a02b8b05dd1e8b8cf169e1f89542ef835b11fc13Kenny Root     * file matches a package ID that is owned by the calling program's UID.
462a02b8b05dd1e8b8cf169e1f89542ef835b11fc13Kenny Root     * That is, shared UID applications can obtain access to any other
463a02b8b05dd1e8b8cf169e1f89542ef835b11fc13Kenny Root     * application's OBB that shares its UID.
46402ca31fbae9f35dd30f79de6927fae11b549391aKenny Root     * <p>
465a02b8b05dd1e8b8cf169e1f89542ef835b11fc13Kenny Root     *
466a02b8b05dd1e8b8cf169e1f89542ef835b11fc13Kenny Root     * @param filename path to the OBB file
467a02b8b05dd1e8b8cf169e1f89542ef835b11fc13Kenny Root     * @param force whether to kill any programs using this in order to unmount
468a02b8b05dd1e8b8cf169e1f89542ef835b11fc13Kenny Root     *            it
469a02b8b05dd1e8b8cf169e1f89542ef835b11fc13Kenny Root     * @return whether the unmount call was successfully queued or not
47002c8730c1bf19daf48bec8c6995df676a00a73b1Kenny Root     */
47138cf8867a8d3e8d5159abd0bd0e6a3b0b8348b94Kenny Root    public boolean unmountObb(String filename, boolean force, OnObbStateChangeListener listener) {
47202c8730c1bf19daf48bec8c6995df676a00a73b1Kenny Root        try {
47305105f7abe02b2dff91d6260b3628c8b97816babKenny Root            mObbActionListener.addListener(listener);
474a02b8b05dd1e8b8cf169e1f89542ef835b11fc13Kenny Root            mMountService.unmountObb(filename, force, mObbActionListener);
475a02b8b05dd1e8b8cf169e1f89542ef835b11fc13Kenny Root            return true;
47602c8730c1bf19daf48bec8c6995df676a00a73b1Kenny Root        } catch (RemoteException e) {
47702c8730c1bf19daf48bec8c6995df676a00a73b1Kenny Root            Log.e(TAG, "Failed to mount OBB", e);
47802c8730c1bf19daf48bec8c6995df676a00a73b1Kenny Root        }
47902c8730c1bf19daf48bec8c6995df676a00a73b1Kenny Root
48002c8730c1bf19daf48bec8c6995df676a00a73b1Kenny Root        return false;
48102c8730c1bf19daf48bec8c6995df676a00a73b1Kenny Root    }
48202c8730c1bf19daf48bec8c6995df676a00a73b1Kenny Root
483a02b8b05dd1e8b8cf169e1f89542ef835b11fc13Kenny Root    /**
484a02b8b05dd1e8b8cf169e1f89542ef835b11fc13Kenny Root     * Check whether an Opaque Binary Blob (OBB) is mounted or not.
485a02b8b05dd1e8b8cf169e1f89542ef835b11fc13Kenny Root     *
486a02b8b05dd1e8b8cf169e1f89542ef835b11fc13Kenny Root     * @param filename path to OBB image
487a02b8b05dd1e8b8cf169e1f89542ef835b11fc13Kenny Root     * @return true if OBB is mounted; false if not mounted or on error
488a02b8b05dd1e8b8cf169e1f89542ef835b11fc13Kenny Root     */
489a02b8b05dd1e8b8cf169e1f89542ef835b11fc13Kenny Root    public boolean isObbMounted(String filename) throws IllegalArgumentException {
49002c8730c1bf19daf48bec8c6995df676a00a73b1Kenny Root        try {
49102c8730c1bf19daf48bec8c6995df676a00a73b1Kenny Root            return mMountService.isObbMounted(filename);
49202c8730c1bf19daf48bec8c6995df676a00a73b1Kenny Root        } catch (RemoteException e) {
49302c8730c1bf19daf48bec8c6995df676a00a73b1Kenny Root            Log.e(TAG, "Failed to check if OBB is mounted", e);
49402c8730c1bf19daf48bec8c6995df676a00a73b1Kenny Root        }
49502c8730c1bf19daf48bec8c6995df676a00a73b1Kenny Root
49602c8730c1bf19daf48bec8c6995df676a00a73b1Kenny Root        return false;
49702c8730c1bf19daf48bec8c6995df676a00a73b1Kenny Root    }
49802c8730c1bf19daf48bec8c6995df676a00a73b1Kenny Root
49902c8730c1bf19daf48bec8c6995df676a00a73b1Kenny Root    /**
500a02b8b05dd1e8b8cf169e1f89542ef835b11fc13Kenny Root     * Check the mounted path of an Opaque Binary Blob (OBB) file. This will
501a02b8b05dd1e8b8cf169e1f89542ef835b11fc13Kenny Root     * give you the path to where you can obtain access to the internals of the
502a02b8b05dd1e8b8cf169e1f89542ef835b11fc13Kenny Root     * OBB.
503a02b8b05dd1e8b8cf169e1f89542ef835b11fc13Kenny Root     *
504a02b8b05dd1e8b8cf169e1f89542ef835b11fc13Kenny Root     * @param filename path to OBB image
505a02b8b05dd1e8b8cf169e1f89542ef835b11fc13Kenny Root     * @return absolute path to mounted OBB image data or <code>null</code> if
506a02b8b05dd1e8b8cf169e1f89542ef835b11fc13Kenny Root     *         not mounted or exception encountered trying to read status
50702c8730c1bf19daf48bec8c6995df676a00a73b1Kenny Root     */
50802c8730c1bf19daf48bec8c6995df676a00a73b1Kenny Root    public String getMountedObbPath(String filename) {
50902c8730c1bf19daf48bec8c6995df676a00a73b1Kenny Root        try {
51002c8730c1bf19daf48bec8c6995df676a00a73b1Kenny Root            return mMountService.getMountedObbPath(filename);
51102c8730c1bf19daf48bec8c6995df676a00a73b1Kenny Root        } catch (RemoteException e) {
51202c8730c1bf19daf48bec8c6995df676a00a73b1Kenny Root            Log.e(TAG, "Failed to find mounted path for OBB", e);
513a02b8b05dd1e8b8cf169e1f89542ef835b11fc13Kenny Root        } catch (IllegalArgumentException e) {
514a02b8b05dd1e8b8cf169e1f89542ef835b11fc13Kenny Root            Log.d(TAG, "Couldn't read OBB file", e);
51502c8730c1bf19daf48bec8c6995df676a00a73b1Kenny Root        }
51602c8730c1bf19daf48bec8c6995df676a00a73b1Kenny Root
51702c8730c1bf19daf48bec8c6995df676a00a73b1Kenny Root        return null;
51802c8730c1bf19daf48bec8c6995df676a00a73b1Kenny Root    }
519b104340496e3a531e26c8f428c808eca0e039f50San Mehat}
520