StorageManager.java revision bff405f91001237ec94ec64f86fa2370c4509559
1923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project/*
2913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka * Copyright (C) 2008 The Android Open Source Project
3e49bd1c43acad08f103b38430a8bbcba23f325b3Tadashi G. Takaoka *
48aa9963a895f9dd5bb1bc92ab2e4f461e058f87aTadashi G. Takaoka * Licensed under the Apache License, Version 2.0 (the "License");
58aa9963a895f9dd5bb1bc92ab2e4f461e058f87aTadashi G. Takaoka * you may not use this file except in compliance with the License.
68aa9963a895f9dd5bb1bc92ab2e4f461e058f87aTadashi G. Takaoka * You may obtain a copy of the License at
7e49bd1c43acad08f103b38430a8bbcba23f325b3Tadashi G. Takaoka *
88aa9963a895f9dd5bb1bc92ab2e4f461e058f87aTadashi G. Takaoka *      http://www.apache.org/licenses/LICENSE-2.0
9e49bd1c43acad08f103b38430a8bbcba23f325b3Tadashi G. Takaoka *
10923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
118aa9963a895f9dd5bb1bc92ab2e4f461e058f87aTadashi G. Takaoka * distributed under the License is distributed on an "AS IS" BASIS,
128aa9963a895f9dd5bb1bc92ab2e4f461e058f87aTadashi G. Takaoka * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
138aa9963a895f9dd5bb1bc92ab2e4f461e058f87aTadashi G. Takaoka * See the License for the specific language governing permissions and
148aa9963a895f9dd5bb1bc92ab2e4f461e058f87aTadashi G. Takaoka * limitations under the License.
15923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project */
16923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project
178c3d5b6961a9b9d40c4bf21ad495f852971c24f4Tadashi G. Takaokapackage android.os.storage;
18923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project
19923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.os.Handler;
2066a787b953d703201c6b827abbee74e8cd9bb063Amith Yamasaniimport android.os.Looper;
2108a6f2aea71d998206c47c16dcda4eaa90f8c9eaTadashi G. Takaokaimport android.os.Message;
220967ef40368c4bc7a0576ecc3dc222a8fe9b94c3Tadashi G. Takaokaimport android.os.RemoteException;
230967ef40368c4bc7a0576ecc3dc222a8fe9b94c3Tadashi G. Takaokaimport android.os.ServiceManager;
246f7218627eda110a8454053f8ecb7b80edfdc8cesatokimport android.util.Log;
250967ef40368c4bc7a0576ecc3dc222a8fe9b94c3Tadashi G. Takaoka
260967ef40368c4bc7a0576ecc3dc222a8fe9b94c3Tadashi G. Takaokaimport java.lang.ref.WeakReference;
270967ef40368c4bc7a0576ecc3dc222a8fe9b94c3Tadashi G. Takaokaimport java.util.ArrayList;
28923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport java.util.Iterator;
290967ef40368c4bc7a0576ecc3dc222a8fe9b94c3Tadashi G. Takaokaimport java.util.LinkedList;
30e583371b13ebd9aa336d0883e8c174ae4918c758Tadashi G. Takaokaimport java.util.List;
31522d5c16d20657e7d26009fe9c067404e16a6c2aTadashi G. Takaoka
32522d5c16d20657e7d26009fe9c067404e16a6c2aTadashi G. Takaoka/**
33e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka * StorageManager is the interface to the systems storage service. The storage
34b47319867ef3834a222865b8cb6abe62962e70f7Tadashi G. Takaoka * manager handles storage-related items such as Opaque Binary Blobs (OBBs).
35e49bd1c43acad08f103b38430a8bbcba23f325b3Tadashi G. Takaoka * <p>
36522d5c16d20657e7d26009fe9c067404e16a6c2aTadashi G. Takaoka * OBBs contain a filesystem that maybe be encrypted on disk and mounted
3774b6897a12ec603ef835aaa77a01f0c32f49aa1cTadashi G. Takaoka * on-demand from an application. OBBs are a good way of providing large amounts
38522d5c16d20657e7d26009fe9c067404e16a6c2aTadashi G. Takaoka * of binary assets without packaging them into APKs as they may be multiple
39923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * gigabytes in size. However, due to their size, they're most likely stored in
403fc4ddec68b4f56f53ed6da80b5e44f38c085740Tadashi G. Takaoka * a shared storage pool accessible from all programs. The system does not
41923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * guarantee the security of the OBB file itself: if any program modifies the
42923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * OBB, there is no guarantee that a read from that OBB will produce the
4329e7b7ed6ef88c3e10cc6469801fef87241c9cb5Tadashi G. Takaoka * expected output.
44923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * <p>
45e49bd1c43acad08f103b38430a8bbcba23f325b3Tadashi G. Takaoka * Get an instance of this class by calling
46ae5c736e37973e26b201d45ff6c139862a6e05cfTadashi G. Takaoka * {@link android.content.Context#getSystemService(java.lang.String)} with an
47e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka * argument of {@link android.content.Context#STORAGE_SERVICE}.
48e49bd1c43acad08f103b38430a8bbcba23f325b3Tadashi G. Takaoka */
49c412309b7a32308b1b0a175dafc13f90254353c5Tadashi G. Takaoka
50923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectpublic class StorageManager
51923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project{
527339a62a1368b632c0cedaf1d876a0e8590a47edTadashi G. Takaoka    private static final String TAG = "StorageManager";
537339a62a1368b632c0cedaf1d876a0e8590a47edTadashi G. Takaoka
54d9449ccf3ce9e5eabb022aed6a45bba680bce115Tadashi G. Takaoka    /*
5529e7b7ed6ef88c3e10cc6469801fef87241c9cb5Tadashi G. Takaoka     * Our internal MountService binder reference
56c8461d1ae26d43a09c0f835d833f3d49fbe8d2f3Tadashi G. Takaoka     */
57f72b8f5662afb42b08eb88e92731d52f99df13e3Jean Chalard    private IMountService mMountService;
585f282ea9e4a4590fcbab6e27d5fca7dacbb40a6aTadashi G. Takaoka
595faf41951929301af80026bc3191812ef874fd5aTadashi G. Takaoka    /*
608c3d5b6961a9b9d40c4bf21ad495f852971c24f4Tadashi G. Takaoka     * The looper target for callbacks
618c3d5b6961a9b9d40c4bf21ad495f852971c24f4Tadashi G. Takaoka     */
6292821614fd80112527e133f069e31ee48250314fTadashi G. Takaoka    Looper mTgtLooper;
638c3d5b6961a9b9d40c4bf21ad495f852971c24f4Tadashi G. Takaoka
649310f42a36eabe99ed7dcd3b835d6cdaa3c6fdcaJean Chalard    /*
65042557b45bf2554608cd22874633011157cd1752Jean Chalard     * Target listener for binder callbacks
66a9ca7867b5a7c0be115966211a05f5d460c8638cKurt Partridge     */
676f7905ae757c30ac0f8080f025b88afc61a6f6b1Tadashi G. Takaoka    private MountServiceBinderListener mBinderListener;
686b966160ac8570271547bf63217efa5e228d4accKurt Partridge
69ddb61ea461b920d87be4ad78c8a36eec1013b965Tadashi G. Takaoka    /*
70179ada958b0bb46c6b9c8eb8b220d84dd3db855aTadashi G. Takaoka     * List of our listeners
71179ada958b0bb46c6b9c8eb8b220d84dd3db855aTadashi G. Takaoka     */
72a28a05e971cc242b338331a3b78276fa95188d19Tadashi G. Takaoka    private ArrayList<ListenerDelegate> mListeners = new ArrayList<ListenerDelegate>();
73c412309b7a32308b1b0a175dafc13f90254353c5Tadashi G. Takaoka
74c97810693dfe83bf37c09f73c8d4b40f2ba8dddbTadashi G. Takaoka    private class MountServiceBinderListener extends IMountServiceListener.Stub {
7518d688c94bb8e1e26de2d12445cb3096c6126f75Jean Chalard        public void onUsbMassStorageConnectionChanged(boolean available) {
769310f42a36eabe99ed7dcd3b835d6cdaa3c6fdcaJean Chalard            final int size = mListeners.size();
77c97810693dfe83bf37c09f73c8d4b40f2ba8dddbTadashi G. Takaoka            for (int i = 0; i < size; i++) {
78c97810693dfe83bf37c09f73c8d4b40f2ba8dddbTadashi G. Takaoka                mListeners.get(i).sendShareAvailabilityChanged(available);
7986e815a142c8aa13213151e381a8a24ef23073d3Tadashi G. Takaoka            }
8029e7b7ed6ef88c3e10cc6469801fef87241c9cb5Tadashi G. Takaoka        }
81923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project
828c3d5b6961a9b9d40c4bf21ad495f852971c24f4Tadashi G. Takaoka        public void onStorageStateChanged(String path, String oldState, String newState) {
836f7218627eda110a8454053f8ecb7b80edfdc8cesatok            final int size = mListeners.size();
84913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka            for (int i = 0; i < size; i++) {
85d9449ccf3ce9e5eabb022aed6a45bba680bce115Tadashi G. Takaoka                mListeners.get(i).sendStorageStateChanged(path, oldState, newState);
8674b6897a12ec603ef835aaa77a01f0c32f49aa1cTadashi G. Takaoka            }
8729e7b7ed6ef88c3e10cc6469801fef87241c9cb5Tadashi G. Takaoka        }
8829e7b7ed6ef88c3e10cc6469801fef87241c9cb5Tadashi G. Takaoka    }
8929e7b7ed6ef88c3e10cc6469801fef87241c9cb5Tadashi G. Takaoka
9029e7b7ed6ef88c3e10cc6469801fef87241c9cb5Tadashi G. Takaoka    /**
915f282ea9e4a4590fcbab6e27d5fca7dacbb40a6aTadashi G. Takaoka     * Binder listener for OBB action results.
925f282ea9e4a4590fcbab6e27d5fca7dacbb40a6aTadashi G. Takaoka     */
935f282ea9e4a4590fcbab6e27d5fca7dacbb40a6aTadashi G. Takaoka    private final ObbActionListener mObbActionListener = new ObbActionListener();
9474b6897a12ec603ef835aaa77a01f0c32f49aa1cTadashi G. Takaoka
953e5a3c18bebbfb56012383411b24ee81ffde09cbTadashi G. Takaoka    private class ObbActionListener extends IObbActionListener.Stub {
966f7905ae757c30ac0f8080f025b88afc61a6f6b1Tadashi G. Takaoka        private List<WeakReference<ObbListenerDelegate>> mListeners = new LinkedList<WeakReference<ObbListenerDelegate>>();
976a6075caba3865383eeeb52cccc63a28e4ae5900Amith Yamasani
984702671ea4feb0c79a879e2e3013afdd6ed800b1Tadashi G. Takaoka        @Override
99ae5c736e37973e26b201d45ff6c139862a6e05cfTadashi G. Takaoka        public void onObbResult(String filename, String status) throws RemoteException {
100b47319867ef3834a222865b8cb6abe62962e70f7Tadashi G. Takaoka            synchronized (mListeners) {
101a28a05e971cc242b338331a3b78276fa95188d19Tadashi G. Takaoka                final Iterator<WeakReference<ObbListenerDelegate>> iter = mListeners.iterator();
102d3e50a2acf04638f09786c487326f2c09e738f32Tadashi G. Takaoka                while (iter.hasNext()) {
103ef2bfad5903fb55adca61dbea51984fbc7e4375fTadashi G. Takaoka                    final WeakReference<ObbListenerDelegate> ref = iter.next();
1049676038b6e9fb66760588d7f9c9c642cc493dd71Tadashi G. Takaoka
105293db0873fd89b5c2bd077ffa5091321b3ab8149Ken Wakasa                    final ObbListenerDelegate delegate = (ref == null) ? null : ref.get();
106d3e50a2acf04638f09786c487326f2c09e738f32Tadashi G. Takaoka                    if (delegate == null) {
10774b6897a12ec603ef835aaa77a01f0c32f49aa1cTadashi G. Takaoka                        iter.remove();
10874b6897a12ec603ef835aaa77a01f0c32f49aa1cTadashi G. Takaoka                        continue;
109913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka                    }
110d3e50a2acf04638f09786c487326f2c09e738f32Tadashi G. Takaoka
111c8b0e5797e20d3fa25d319a9709aabc9149f8ff9Tadashi G. Takaoka                    delegate.sendObbStateChanged(filename, status);
112c8b0e5797e20d3fa25d319a9709aabc9149f8ff9Tadashi G. Takaoka                }
1139676038b6e9fb66760588d7f9c9c642cc493dd71Tadashi G. Takaoka            }
1144269a7cebdfe5c76372d0f0dd187432f0594ffe5Tadashi G. Takaoka        }
11516713e5630b93fb5625df26745eb73271f189457Tadashi G. Takaoka
116660776e09b9a3b321074a94721d901a035ca1b9fKen Wakasa        public void addListener(OnObbStateChangeListener listener) {
117660776e09b9a3b321074a94721d901a035ca1b9fKen Wakasa            if (listener == null) {
118660776e09b9a3b321074a94721d901a035ca1b9fKen Wakasa                return;
119d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka            }
120a44685ab326809185a0e4c44afabe8fd93441b4cTadashi G. Takaoka
121d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka            synchronized (mListeners) {
122d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka                final Iterator<WeakReference<ObbListenerDelegate>> iter = mListeners.iterator();
123913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka                while (iter.hasNext()) {
124697bf585f8dac6ffc4d008c02b63407cfdd83104Tadashi G. Takaoka                    final WeakReference<ObbListenerDelegate> ref = iter.next();
125913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka
126913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka                    final ObbListenerDelegate delegate = (ref == null) ? null : ref.get();
127913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka                    if (delegate == null) {
1289bdce3a59e9bf00095bc92fae88b830b0a8455beFabrice Di Meglio                        iter.remove();
1292eb8781dc2e42d55474fb6e5c461c56c066b8363Tadashi G. Takaoka                        continue;
130d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka                    }
131d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka
132d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka                    /*
133d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka                     * If we're already in the listeners, we don't need to be in
134d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka                     * there again.
13577a87e3cb5886b1319230906c77c0bc98b905248Tadashi G. Takaoka                     */
136d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka                    if (listener.equals(delegate.getListener())) {
137d47a955610987c8abdab4d275c044aefc8a7f1dbTadashi G. Takaoka                        return;
13874b6897a12ec603ef835aaa77a01f0c32f49aa1cTadashi G. Takaoka                    }
1395f282ea9e4a4590fcbab6e27d5fca7dacbb40a6aTadashi G. Takaoka                }
14074b6897a12ec603ef835aaa77a01f0c32f49aa1cTadashi G. Takaoka
141ae5c736e37973e26b201d45ff6c139862a6e05cfTadashi G. Takaoka                final ObbListenerDelegate delegate = new ObbListenerDelegate(listener);
142ae5c736e37973e26b201d45ff6c139862a6e05cfTadashi G. Takaoka                mListeners.add(new WeakReference<ObbListenerDelegate>(delegate));
1439f763d14451685965039990891eb0bc8e8db0735Tadashi G. Takaoka            }
1442eb8781dc2e42d55474fb6e5c461c56c066b8363Tadashi G. Takaoka        }
145c04bbc1ae9be81d25a356407c27a8e7fa22028bfTadashi G. Takaoka    }
146c04bbc1ae9be81d25a356407c27a8e7fa22028bfTadashi G. Takaoka
1473e5a3c18bebbfb56012383411b24ee81ffde09cbTadashi G. Takaoka    /**
1483e5a3c18bebbfb56012383411b24ee81ffde09cbTadashi G. Takaoka     * Private class containing sender and receiver code for StorageEvents.
1493e5a3c18bebbfb56012383411b24ee81ffde09cbTadashi G. Takaoka     */
150d3e50a2acf04638f09786c487326f2c09e738f32Tadashi G. Takaoka    private class ObbListenerDelegate {
151d3e50a2acf04638f09786c487326f2c09e738f32Tadashi G. Takaoka        private final WeakReference<OnObbStateChangeListener> mObbEventListenerRef;
152d3e50a2acf04638f09786c487326f2c09e738f32Tadashi G. Takaoka        private final Handler mHandler;
153d3e50a2acf04638f09786c487326f2c09e738f32Tadashi G. Takaoka
154d3e50a2acf04638f09786c487326f2c09e738f32Tadashi G. Takaoka        ObbListenerDelegate(OnObbStateChangeListener listener) {
155d3e50a2acf04638f09786c487326f2c09e738f32Tadashi G. Takaoka            mObbEventListenerRef = new WeakReference<OnObbStateChangeListener>(listener);
156d3e50a2acf04638f09786c487326f2c09e738f32Tadashi G. Takaoka            mHandler = new Handler(mTgtLooper) {
157d3e50a2acf04638f09786c487326f2c09e738f32Tadashi G. Takaoka                @Override
158d3e50a2acf04638f09786c487326f2c09e738f32Tadashi G. Takaoka                public void handleMessage(Message msg) {
159d3e50a2acf04638f09786c487326f2c09e738f32Tadashi G. Takaoka                    final OnObbStateChangeListener listener = getListener();
160d3e50a2acf04638f09786c487326f2c09e738f32Tadashi G. Takaoka                    if (listener == null) {
161d3e50a2acf04638f09786c487326f2c09e738f32Tadashi G. Takaoka                        return;
162d3e50a2acf04638f09786c487326f2c09e738f32Tadashi G. Takaoka                    }
163d3e50a2acf04638f09786c487326f2c09e738f32Tadashi G. Takaoka
1644702671ea4feb0c79a879e2e3013afdd6ed800b1Tadashi G. Takaoka                    StorageEvent e = (StorageEvent) msg.obj;
1654702671ea4feb0c79a879e2e3013afdd6ed800b1Tadashi G. Takaoka
1664702671ea4feb0c79a879e2e3013afdd6ed800b1Tadashi G. Takaoka                    if (msg.what == StorageEvent.EVENT_OBB_STATE_CHANGED) {
1674702671ea4feb0c79a879e2e3013afdd6ed800b1Tadashi G. Takaoka                        ObbStateChangedStorageEvent ev = (ObbStateChangedStorageEvent) e;
16892821614fd80112527e133f069e31ee48250314fTadashi G. Takaoka                        listener.onObbStateChange(ev.path, ev.state);
169ef2bfad5903fb55adca61dbea51984fbc7e4375fTadashi G. Takaoka                    } else {
17092821614fd80112527e133f069e31ee48250314fTadashi G. Takaoka                        Log.e(TAG, "Unsupported event " + msg.what);
171ef2bfad5903fb55adca61dbea51984fbc7e4375fTadashi G. Takaoka                    }
17292821614fd80112527e133f069e31ee48250314fTadashi G. Takaoka                }
173ef2bfad5903fb55adca61dbea51984fbc7e4375fTadashi G. Takaoka            };
17492821614fd80112527e133f069e31ee48250314fTadashi G. Takaoka        }
175ef2bfad5903fb55adca61dbea51984fbc7e4375fTadashi G. Takaoka
17692821614fd80112527e133f069e31ee48250314fTadashi G. Takaoka        OnObbStateChangeListener getListener() {
177ef2bfad5903fb55adca61dbea51984fbc7e4375fTadashi G. Takaoka            if (mObbEventListenerRef == null) {
1784702671ea4feb0c79a879e2e3013afdd6ed800b1Tadashi G. Takaoka                return null;
1794702671ea4feb0c79a879e2e3013afdd6ed800b1Tadashi G. Takaoka            }
1804702671ea4feb0c79a879e2e3013afdd6ed800b1Tadashi G. Takaoka            return mObbEventListenerRef.get();
1814702671ea4feb0c79a879e2e3013afdd6ed800b1Tadashi G. Takaoka        }
1824702671ea4feb0c79a879e2e3013afdd6ed800b1Tadashi G. Takaoka
1834702671ea4feb0c79a879e2e3013afdd6ed800b1Tadashi G. Takaoka        void sendObbStateChanged(String path, String state) {
1844702671ea4feb0c79a879e2e3013afdd6ed800b1Tadashi G. Takaoka            ObbStateChangedStorageEvent e = new ObbStateChangedStorageEvent(path, state);
1854702671ea4feb0c79a879e2e3013afdd6ed800b1Tadashi G. Takaoka            mHandler.sendMessage(e.getMessage());
186913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka        }
1874702671ea4feb0c79a879e2e3013afdd6ed800b1Tadashi G. Takaoka    }
188913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka
18992821614fd80112527e133f069e31ee48250314fTadashi G. Takaoka    /**
1904702671ea4feb0c79a879e2e3013afdd6ed800b1Tadashi G. Takaoka     * Message sent during an OBB status change event.
191697bf585f8dac6ffc4d008c02b63407cfdd83104Tadashi G. Takaoka     */
1929676038b6e9fb66760588d7f9c9c642cc493dd71Tadashi G. Takaoka    private class ObbStateChangedStorageEvent extends StorageEvent {
1934702671ea4feb0c79a879e2e3013afdd6ed800b1Tadashi G. Takaoka        public final String path;
1949676038b6e9fb66760588d7f9c9c642cc493dd71Tadashi G. Takaoka        public final String state;
19592821614fd80112527e133f069e31ee48250314fTadashi G. Takaoka
196ef2bfad5903fb55adca61dbea51984fbc7e4375fTadashi G. Takaoka        public ObbStateChangedStorageEvent(String path, String state) {
197d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka            super(EVENT_OBB_STATE_CHANGED);
198d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka            this.path = path;
1990967ef40368c4bc7a0576ecc3dc222a8fe9b94c3Tadashi G. Takaoka            this.state = state;
2000967ef40368c4bc7a0576ecc3dc222a8fe9b94c3Tadashi G. Takaoka        }
201913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka    }
2024269a7cebdfe5c76372d0f0dd187432f0594ffe5Tadashi G. Takaoka
2034269a7cebdfe5c76372d0f0dd187432f0594ffe5Tadashi G. Takaoka    /**
204c8b0e5797e20d3fa25d319a9709aabc9149f8ff9Tadashi G. Takaoka     * Private base class for messages sent between the callback thread
205c8b0e5797e20d3fa25d319a9709aabc9149f8ff9Tadashi G. Takaoka     * and the target looper handler.
20660a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka     */
207c04bbc1ae9be81d25a356407c27a8e7fa22028bfTadashi G. Takaoka    private class StorageEvent {
208913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka        static final int EVENT_UMS_CONNECTION_CHANGED = 1;
2092eb8781dc2e42d55474fb6e5c461c56c066b8363Tadashi G. Takaoka        static final int EVENT_STORAGE_STATE_CHANGED = 2;
2102eb8781dc2e42d55474fb6e5c461c56c066b8363Tadashi G. Takaoka        static final int EVENT_OBB_STATE_CHANGED = 3;
21174b6897a12ec603ef835aaa77a01f0c32f49aa1cTadashi G. Takaoka
21274b6897a12ec603ef835aaa77a01f0c32f49aa1cTadashi G. Takaoka        private Message mMessage;
213c8b0e5797e20d3fa25d319a9709aabc9149f8ff9Tadashi G. Takaoka
214c8b0e5797e20d3fa25d319a9709aabc9149f8ff9Tadashi G. Takaoka        public StorageEvent(int what) {
215c8b0e5797e20d3fa25d319a9709aabc9149f8ff9Tadashi G. Takaoka            mMessage = Message.obtain();
216c8b0e5797e20d3fa25d319a9709aabc9149f8ff9Tadashi G. Takaoka            mMessage.what = what;
217c8b0e5797e20d3fa25d319a9709aabc9149f8ff9Tadashi G. Takaoka            mMessage.obj = this;
218c8b0e5797e20d3fa25d319a9709aabc9149f8ff9Tadashi G. Takaoka        }
219c8b0e5797e20d3fa25d319a9709aabc9149f8ff9Tadashi G. Takaoka
220c8b0e5797e20d3fa25d319a9709aabc9149f8ff9Tadashi G. Takaoka        public Message getMessage() {
2213e5a3c18bebbfb56012383411b24ee81ffde09cbTadashi G. Takaoka            return mMessage;
222c8b0e5797e20d3fa25d319a9709aabc9149f8ff9Tadashi G. Takaoka        }
223c8b0e5797e20d3fa25d319a9709aabc9149f8ff9Tadashi G. Takaoka    }
224c8b0e5797e20d3fa25d319a9709aabc9149f8ff9Tadashi G. Takaoka
225c8b0e5797e20d3fa25d319a9709aabc9149f8ff9Tadashi G. Takaoka    /**
226c8b0e5797e20d3fa25d319a9709aabc9149f8ff9Tadashi G. Takaoka     * Message sent on a USB mass storage connection change.
227c8b0e5797e20d3fa25d319a9709aabc9149f8ff9Tadashi G. Takaoka     */
228c8b0e5797e20d3fa25d319a9709aabc9149f8ff9Tadashi G. Takaoka    private class UmsConnectionChangedStorageEvent extends StorageEvent {
229c8b0e5797e20d3fa25d319a9709aabc9149f8ff9Tadashi G. Takaoka        public boolean available;
230c8b0e5797e20d3fa25d319a9709aabc9149f8ff9Tadashi G. Takaoka
231c8b0e5797e20d3fa25d319a9709aabc9149f8ff9Tadashi G. Takaoka        public UmsConnectionChangedStorageEvent(boolean a) {
232c8b0e5797e20d3fa25d319a9709aabc9149f8ff9Tadashi G. Takaoka            super(EVENT_UMS_CONNECTION_CHANGED);
2333e5a3c18bebbfb56012383411b24ee81ffde09cbTadashi G. Takaoka            available = a;
2343e5a3c18bebbfb56012383411b24ee81ffde09cbTadashi G. Takaoka        }
2350967ef40368c4bc7a0576ecc3dc222a8fe9b94c3Tadashi G. Takaoka    }
2360967ef40368c4bc7a0576ecc3dc222a8fe9b94c3Tadashi G. Takaoka
2370967ef40368c4bc7a0576ecc3dc222a8fe9b94c3Tadashi G. Takaoka    /**
2380967ef40368c4bc7a0576ecc3dc222a8fe9b94c3Tadashi G. Takaoka     * Message sent on volume state change.
2390967ef40368c4bc7a0576ecc3dc222a8fe9b94c3Tadashi G. Takaoka     */
2400967ef40368c4bc7a0576ecc3dc222a8fe9b94c3Tadashi G. Takaoka    private class StorageStateChangedStorageEvent extends StorageEvent {
241c9f562a9a4c2b634eb43d1ddaef69068c0d93f6fKen Wakasa        public String path;
2420967ef40368c4bc7a0576ecc3dc222a8fe9b94c3Tadashi G. Takaoka        public String oldState;
2430967ef40368c4bc7a0576ecc3dc222a8fe9b94c3Tadashi G. Takaoka        public String newState;
2440967ef40368c4bc7a0576ecc3dc222a8fe9b94c3Tadashi G. Takaoka
2450967ef40368c4bc7a0576ecc3dc222a8fe9b94c3Tadashi G. Takaoka        public StorageStateChangedStorageEvent(String p, String oldS, String newS) {
2460967ef40368c4bc7a0576ecc3dc222a8fe9b94c3Tadashi G. Takaoka            super(EVENT_STORAGE_STATE_CHANGED);
2470967ef40368c4bc7a0576ecc3dc222a8fe9b94c3Tadashi G. Takaoka            path = p;
2480967ef40368c4bc7a0576ecc3dc222a8fe9b94c3Tadashi G. Takaoka            oldState = oldS;
2490967ef40368c4bc7a0576ecc3dc222a8fe9b94c3Tadashi G. Takaoka            newState = newS;
2500967ef40368c4bc7a0576ecc3dc222a8fe9b94c3Tadashi G. Takaoka        }
2513e5a3c18bebbfb56012383411b24ee81ffde09cbTadashi G. Takaoka    }
2523e5a3c18bebbfb56012383411b24ee81ffde09cbTadashi G. Takaoka
253bc464e2952e102219f0b977fc1e9140ad5bd03e4Tadashi G. Takaoka    /**
254e79b1a83126b41e09a8ec0a8dbb751ae0e02c7f6Tadashi G. Takaoka     * Private class containing sender and receiver code for StorageEvents.
255e79b1a83126b41e09a8ec0a8dbb751ae0e02c7f6Tadashi G. Takaoka     */
256d47a955610987c8abdab4d275c044aefc8a7f1dbTadashi G. Takaoka    private class ListenerDelegate {
257d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka        final StorageEventListener mStorageEventListener;
258d47a955610987c8abdab4d275c044aefc8a7f1dbTadashi G. Takaoka        private final Handler mHandler;
259d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka
260d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka        ListenerDelegate(StorageEventListener listener) {
261d47a955610987c8abdab4d275c044aefc8a7f1dbTadashi G. Takaoka            mStorageEventListener = listener;
262d47a955610987c8abdab4d275c044aefc8a7f1dbTadashi G. Takaoka            mHandler = new Handler(mTgtLooper) {
263d47a955610987c8abdab4d275c044aefc8a7f1dbTadashi G. Takaoka                @Override
264d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka                public void handleMessage(Message msg) {
265d47a955610987c8abdab4d275c044aefc8a7f1dbTadashi G. Takaoka                    StorageEvent e = (StorageEvent) msg.obj;
266d47a955610987c8abdab4d275c044aefc8a7f1dbTadashi G. Takaoka
267d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka                    if (msg.what == StorageEvent.EVENT_UMS_CONNECTION_CHANGED) {
268d47a955610987c8abdab4d275c044aefc8a7f1dbTadashi G. Takaoka                        UmsConnectionChangedStorageEvent ev = (UmsConnectionChangedStorageEvent) e;
269d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka                        mStorageEventListener.onUsbMassStorageConnectionChanged(ev.available);
270d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka                    } else if (msg.what == StorageEvent.EVENT_STORAGE_STATE_CHANGED) {
271d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka                        StorageStateChangedStorageEvent ev = (StorageStateChangedStorageEvent) e;
2723e5a3c18bebbfb56012383411b24ee81ffde09cbTadashi G. Takaoka                        mStorageEventListener.onStorageStateChanged(ev.path, ev.oldState, ev.newState);
27360a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka                    } else {
27460a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka                        Log.e(TAG, "Unsupported event " + msg.what);
275e79b1a83126b41e09a8ec0a8dbb751ae0e02c7f6Tadashi G. Takaoka                    }
276913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka                }
27760a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka            };
27860a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka        }
279913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka
28060a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka        StorageEventListener getListener() {
281d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka            return mStorageEventListener;
282d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka        }
283d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka
284d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka        void sendShareAvailabilityChanged(boolean available) {
2853e5a3c18bebbfb56012383411b24ee81ffde09cbTadashi G. Takaoka            UmsConnectionChangedStorageEvent e = new UmsConnectionChangedStorageEvent(available);
2863e5a3c18bebbfb56012383411b24ee81ffde09cbTadashi G. Takaoka            mHandler.sendMessage(e.getMessage());
287d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka        }
288913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka
289d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka        void sendStorageStateChanged(String path, String oldState, String newState) {
290d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka            StorageStateChangedStorageEvent e = new StorageStateChangedStorageEvent(path, oldState, newState);
291e79b1a83126b41e09a8ec0a8dbb751ae0e02c7f6Tadashi G. Takaoka            mHandler.sendMessage(e.getMessage());
292d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka        }
293e79b1a83126b41e09a8ec0a8dbb751ae0e02c7f6Tadashi G. Takaoka    }
294a44685ab326809185a0e4c44afabe8fd93441b4cTadashi G. Takaoka
295913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka    /**
296913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka     * Constructs a StorageManager object through which an application can
297d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka     * can communicate with the systems mount service.
298d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka     *
299d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka     * @param tgtLooper The {@android.os.Looper} which events will be received on.
300c0c20b386fb06b688f56dd7f807e2bcbb70b3a59Jean Chalard     *
301ebbb7e9665b2f9bce46ddc2daa82b9ef73f6c712Jean Chalard     * <p>Applications can get instance of this class by calling
302ebbb7e9665b2f9bce46ddc2daa82b9ef73f6c712Jean Chalard     * {@link android.content.Context#getSystemService(java.lang.String)} with an argument
303f72b8f5662afb42b08eb88e92731d52f99df13e3Jean Chalard     * of {@link android.content.Context#STORAGE_SERVICE}.
304f72b8f5662afb42b08eb88e92731d52f99df13e3Jean Chalard     *
305bc464e2952e102219f0b977fc1e9140ad5bd03e4Tadashi G. Takaoka     * @hide
3062aa1dd45c44295e2f7e8ece1b520032d86b9f908satok     */
3072aa1dd45c44295e2f7e8ece1b520032d86b9f908satok    public StorageManager(Looper tgtLooper) throws RemoteException {
3082aa1dd45c44295e2f7e8ece1b520032d86b9f908satok        mMountService = IMountService.Stub.asInterface(ServiceManager.getService("mount"));
30960a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka        if (mMountService == null) {
3104f6cf258fe208329247ade7a6701ac9709820717Jean Chalard            Log.e(TAG, "Unable to connect to mount service! - is it running yet?");
311697bf585f8dac6ffc4d008c02b63407cfdd83104Tadashi G. Takaoka            return;
312d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka        }
313d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka        mTgtLooper = tgtLooper;
314d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka        mBinderListener = new MountServiceBinderListener();
315d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka        mMountService.registerListener(mBinderListener);
316d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka    }
317d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka
318d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka
319d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka    /**
320d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka     * Registers a {@link android.os.storage.StorageEventListener StorageEventListener}.
321d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka     *
3222c47080e7b4b9b2a6c2dbf1444e041c1b7943316Tadashi G. Takaoka     * @param listener A {@link android.os.storage.StorageEventListener StorageEventListener} object.
3232c47080e7b4b9b2a6c2dbf1444e041c1b7943316Tadashi G. Takaoka     *
3242c47080e7b4b9b2a6c2dbf1444e041c1b7943316Tadashi G. Takaoka     */
3252c47080e7b4b9b2a6c2dbf1444e041c1b7943316Tadashi G. Takaoka    public void registerListener(StorageEventListener listener) {
3262c47080e7b4b9b2a6c2dbf1444e041c1b7943316Tadashi G. Takaoka        if (listener == null) {
3272c47080e7b4b9b2a6c2dbf1444e041c1b7943316Tadashi G. Takaoka            return;
3282c47080e7b4b9b2a6c2dbf1444e041c1b7943316Tadashi G. Takaoka        }
3293e5a3c18bebbfb56012383411b24ee81ffde09cbTadashi G. Takaoka
3303e5a3c18bebbfb56012383411b24ee81ffde09cbTadashi G. Takaoka        synchronized (mListeners) {
331e79b1a83126b41e09a8ec0a8dbb751ae0e02c7f6Tadashi G. Takaoka            mListeners.add(new ListenerDelegate(listener));
332e79b1a83126b41e09a8ec0a8dbb751ae0e02c7f6Tadashi G. Takaoka        }
3333a566c48b0eb3625788e1cce3fb2f58d8f4b380dTadashi G. Takaoka    }
33460a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka
33560a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka    /**
336913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka     * Unregisters a {@link android.os.storage.StorageEventListener StorageEventListener}.
337e79b1a83126b41e09a8ec0a8dbb751ae0e02c7f6Tadashi G. Takaoka     *
338e79b1a83126b41e09a8ec0a8dbb751ae0e02c7f6Tadashi G. Takaoka     * @param listener A {@link android.os.storage.StorageEventListener StorageEventListener} object.
33960a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka     *
34060a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka     */
341e79b1a83126b41e09a8ec0a8dbb751ae0e02c7f6Tadashi G. Takaoka    public void unregisterListener(StorageEventListener listener) {
34260a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka        if (listener == null) {
34360a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka            return;
34460a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka        }
345913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka
3462c47080e7b4b9b2a6c2dbf1444e041c1b7943316Tadashi G. Takaoka        synchronized (mListeners) {
347013ba3e3e785980b74db83ac5ab1e11b438485daTadashi G. Takaoka            final int size = mListeners.size();
34860a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka            for (int i=0 ; i<size ; i++) {
34960a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka                ListenerDelegate l = mListeners.get(i);
35016713e5630b93fb5625df26745eb73271f189457Tadashi G. Takaoka                if (l.getListener() == listener) {
35160a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka                    mListeners.remove(i);
352913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka                    break;
353ae5c736e37973e26b201d45ff6c139862a6e05cfTadashi G. Takaoka                }
354ae5c736e37973e26b201d45ff6c139862a6e05cfTadashi G. Takaoka            }
355913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka        }
356580e1d7ac0cb90a464a3b3aed88047f85a4ab41fTadashi G. Takaoka    }
357913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka
358ae5c736e37973e26b201d45ff6c139862a6e05cfTadashi G. Takaoka    /**
359580e1d7ac0cb90a464a3b3aed88047f85a4ab41fTadashi G. Takaoka     * Enables USB Mass Storage (UMS) on the device.
360ae5c736e37973e26b201d45ff6c139862a6e05cfTadashi G. Takaoka     */
361ae5c736e37973e26b201d45ff6c139862a6e05cfTadashi G. Takaoka    public void enableUsbMassStorage() {
362913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka        try {
36360a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka            mMountService.setUsbMassStorageEnabled(true);
364e79b1a83126b41e09a8ec0a8dbb751ae0e02c7f6Tadashi G. Takaoka        } catch (Exception ex) {
365913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka            Log.e(TAG, "Failed to enable UMS", ex);
36660a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka        }
36760a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka    }
36860a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka
36960a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka    /**
37060a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka     * Disables USB Mass Storage (UMS) on the device.
371b8dc67466339dc14653ad634c86851025373326bTadashi G. Takaoka     */
372913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka    public void disableUsbMassStorage() {
373013ba3e3e785980b74db83ac5ab1e11b438485daTadashi G. Takaoka        try {
37416713e5630b93fb5625df26745eb73271f189457Tadashi G. Takaoka            mMountService.setUsbMassStorageEnabled(false);
375042557b45bf2554608cd22874633011157cd1752Jean Chalard        } catch (Exception ex) {
376bc464e2952e102219f0b977fc1e9140ad5bd03e4Tadashi G. Takaoka            Log.e(TAG, "Failed to disable UMS", ex);
37716713e5630b93fb5625df26745eb73271f189457Tadashi G. Takaoka        }
37860a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka    }
37916713e5630b93fb5625df26745eb73271f189457Tadashi G. Takaoka
380013ba3e3e785980b74db83ac5ab1e11b438485daTadashi G. Takaoka    /**
381b8dc67466339dc14653ad634c86851025373326bTadashi G. Takaoka     * Query if a USB Mass Storage (UMS) host is connected.
382b8dc67466339dc14653ad634c86851025373326bTadashi G. Takaoka     * @return true if UMS host is connected.
38360a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka     */
38416713e5630b93fb5625df26745eb73271f189457Tadashi G. Takaoka    public boolean isUsbMassStorageConnected() {
385c8461d1ae26d43a09c0f835d833f3d49fbe8d2f3Tadashi G. Takaoka        try {
386013ba3e3e785980b74db83ac5ab1e11b438485daTadashi G. Takaoka            return mMountService.isUsbMassStorageConnected();
38716713e5630b93fb5625df26745eb73271f189457Tadashi G. Takaoka        } catch (Exception ex) {
38860a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka            Log.e(TAG, "Failed to get UMS connection state", ex);
38916713e5630b93fb5625df26745eb73271f189457Tadashi G. Takaoka        }
39016713e5630b93fb5625df26745eb73271f189457Tadashi G. Takaoka        return false;
39116713e5630b93fb5625df26745eb73271f189457Tadashi G. Takaoka    }
3923e5a3c18bebbfb56012383411b24ee81ffde09cbTadashi G. Takaoka
393913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka    /**
394913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka     * Query if a USB Mass Storage (UMS) is enabled on the device.
39560a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka     * @return true if UMS host is enabled.
396913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka     */
39760a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka    public boolean isUsbMassStorageEnabled() {
39874b6897a12ec603ef835aaa77a01f0c32f49aa1cTadashi G. Takaoka        try {
3993e5a3c18bebbfb56012383411b24ee81ffde09cbTadashi G. Takaoka            return mMountService.isUsbMassStorageEnabled();
400913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka        } catch (RemoteException rex) {
401913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka            Log.e(TAG, "Failed to get UMS enable state", rex);
40260a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka        }
40360a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka        return false;
404913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka    }
40574b6897a12ec603ef835aaa77a01f0c32f49aa1cTadashi G. Takaoka
40674b6897a12ec603ef835aaa77a01f0c32f49aa1cTadashi G. Takaoka    /**
40774b6897a12ec603ef835aaa77a01f0c32f49aa1cTadashi G. Takaoka     * Mount an Opaque Binary Blob (OBB) file. If a <code>key</code> is
4083e5a3c18bebbfb56012383411b24ee81ffde09cbTadashi G. Takaoka     * specified, it is supplied to the mounting process to be used in any
40974b6897a12ec603ef835aaa77a01f0c32f49aa1cTadashi G. Takaoka     * encryption used in the OBB.
410e79b1a83126b41e09a8ec0a8dbb751ae0e02c7f6Tadashi G. Takaoka     * <p>
41160a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka     * The OBB will remain mounted for as long as the StorageManager reference
412e79b1a83126b41e09a8ec0a8dbb751ae0e02c7f6Tadashi G. Takaoka     * is held by the application. As soon as this reference is lost, the OBBs
41374b6897a12ec603ef835aaa77a01f0c32f49aa1cTadashi G. Takaoka     * in use will be unmounted. The {@link OnObbStateChangeListener} registered with
41474b6897a12ec603ef835aaa77a01f0c32f49aa1cTadashi G. Takaoka     * this call will receive all further OBB-related events until it goes out
41560a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka     * of scope. If the caller is not interested in whether the call succeeds,
41660a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka     * the <code>listener</code> may be specified as <code>null</code>.
41760a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka     * <p>
41860a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka     * <em>Note:</em> you can only mount OBB files for which the OBB tag on the
41974b6897a12ec603ef835aaa77a01f0c32f49aa1cTadashi G. Takaoka     * file matches a package ID that is owned by the calling program's UID.
42074b6897a12ec603ef835aaa77a01f0c32f49aa1cTadashi G. Takaoka     * That is, shared UID applications can attempt to mount any other
4213e5a3c18bebbfb56012383411b24ee81ffde09cbTadashi G. Takaoka     * application's OBB that shares its UID.
4223e5a3c18bebbfb56012383411b24ee81ffde09cbTadashi G. Takaoka     *
423e79b1a83126b41e09a8ec0a8dbb751ae0e02c7f6Tadashi G. Takaoka     * @param filename the path to the OBB file
42460a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka     * @param key secret used to encrypt the OBB; may be <code>null</code> if no
42560a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka     *            encryption was used on the OBB.
426913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka     * @return whether the mount call was successfully queued or not
4272c47080e7b4b9b2a6c2dbf1444e041c1b7943316Tadashi G. Takaoka     * @throws IllegalArgumentException when the OBB is already mounted
42860a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka     */
42960a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka    public boolean mountObb(String filename, String key, OnObbStateChangeListener listener) {
43060a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka        try {
43160a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka            mObbActionListener.addListener(listener);
432a44685ab326809185a0e4c44afabe8fd93441b4cTadashi G. Takaoka            mMountService.mountObb(filename, key, mObbActionListener);
433bc464e2952e102219f0b977fc1e9140ad5bd03e4Tadashi G. Takaoka            return true;
43460a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka        } catch (RemoteException e) {
43560a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka            Log.e(TAG, "Failed to mount OBB", e);
436ae5c736e37973e26b201d45ff6c139862a6e05cfTadashi G. Takaoka        }
43760a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka
438913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka        return false;
43960a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka    }
440ae5c736e37973e26b201d45ff6c139862a6e05cfTadashi G. Takaoka
44174b6897a12ec603ef835aaa77a01f0c32f49aa1cTadashi G. Takaoka    /**
442c04bbc1ae9be81d25a356407c27a8e7fa22028bfTadashi G. Takaoka     * Unmount an Opaque Binary Blob (OBB) file asynchronously. If the
443bc464e2952e102219f0b977fc1e9140ad5bd03e4Tadashi G. Takaoka     * <code>force</code> flag is true, it will kill any application needed to
4443e5a3c18bebbfb56012383411b24ee81ffde09cbTadashi G. Takaoka     * unmount the given OBB (even the calling application).
445c04bbc1ae9be81d25a356407c27a8e7fa22028bfTadashi G. Takaoka     * <p>
446c04bbc1ae9be81d25a356407c27a8e7fa22028bfTadashi G. Takaoka     * The {@link OnObbStateChangeListener} registered with this call will receive all
447c04bbc1ae9be81d25a356407c27a8e7fa22028bfTadashi G. Takaoka     * further OBB-related events until it goes out of scope. If the caller is
448c04bbc1ae9be81d25a356407c27a8e7fa22028bfTadashi G. Takaoka     * not interested in whether the call succeeded, the listener may be
449913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka     * specified as <code>null</code>.
450c04bbc1ae9be81d25a356407c27a8e7fa22028bfTadashi G. Takaoka     * <p>
451c04bbc1ae9be81d25a356407c27a8e7fa22028bfTadashi G. Takaoka     * <em>Note:</em> you can only mount OBB files for which the OBB tag on the
452c04bbc1ae9be81d25a356407c27a8e7fa22028bfTadashi G. Takaoka     * file matches a package ID that is owned by the calling program's UID.
453c04bbc1ae9be81d25a356407c27a8e7fa22028bfTadashi G. Takaoka     * That is, shared UID applications can obtain access to any other
454c04bbc1ae9be81d25a356407c27a8e7fa22028bfTadashi G. Takaoka     * application's OBB that shares its UID.
455c04bbc1ae9be81d25a356407c27a8e7fa22028bfTadashi G. Takaoka     * <p>
456913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka     *
457c04bbc1ae9be81d25a356407c27a8e7fa22028bfTadashi G. Takaoka     * @param filename path to the OBB file
458c04bbc1ae9be81d25a356407c27a8e7fa22028bfTadashi G. Takaoka     * @param force whether to kill any programs using this in order to unmount
459c04bbc1ae9be81d25a356407c27a8e7fa22028bfTadashi G. Takaoka     *            it
4602eb8781dc2e42d55474fb6e5c461c56c066b8363Tadashi G. Takaoka     * @return whether the unmount call was successfully queued or not
4612eb8781dc2e42d55474fb6e5c461c56c066b8363Tadashi G. Takaoka     * @throws IllegalArgumentException when OBB is not already mounted
4622eb8781dc2e42d55474fb6e5c461c56c066b8363Tadashi G. Takaoka     */
4632eb8781dc2e42d55474fb6e5c461c56c066b8363Tadashi G. Takaoka    public boolean unmountObb(String filename, boolean force, OnObbStateChangeListener listener)
4642eb8781dc2e42d55474fb6e5c461c56c066b8363Tadashi G. Takaoka            throws IllegalArgumentException {
465c04bbc1ae9be81d25a356407c27a8e7fa22028bfTadashi G. Takaoka        try {
4662eb8781dc2e42d55474fb6e5c461c56c066b8363Tadashi G. Takaoka            mObbActionListener.addListener(listener);
467c04bbc1ae9be81d25a356407c27a8e7fa22028bfTadashi G. Takaoka            mMountService.unmountObb(filename, force, mObbActionListener);
4682eb8781dc2e42d55474fb6e5c461c56c066b8363Tadashi G. Takaoka            return true;
469644d33d60ea5a87501274488013d65f55238895eKen Wakasa        } catch (RemoteException e) {
470644d33d60ea5a87501274488013d65f55238895eKen Wakasa            Log.e(TAG, "Failed to mount OBB", e);
471c04bbc1ae9be81d25a356407c27a8e7fa22028bfTadashi G. Takaoka        }
472c04bbc1ae9be81d25a356407c27a8e7fa22028bfTadashi G. Takaoka
473b8dc67466339dc14653ad634c86851025373326bTadashi G. Takaoka        return false;
474913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka    }
4759f763d14451685965039990891eb0bc8e8db0735Tadashi G. Takaoka
4769f763d14451685965039990891eb0bc8e8db0735Tadashi G. Takaoka    /**
4779f763d14451685965039990891eb0bc8e8db0735Tadashi G. Takaoka     * Check whether an Opaque Binary Blob (OBB) is mounted or not.
4789f763d14451685965039990891eb0bc8e8db0735Tadashi G. Takaoka     *
4799f763d14451685965039990891eb0bc8e8db0735Tadashi G. Takaoka     * @param filename path to OBB image
4809f763d14451685965039990891eb0bc8e8db0735Tadashi G. Takaoka     * @return true if OBB is mounted; false if not mounted or on error
4819f763d14451685965039990891eb0bc8e8db0735Tadashi G. Takaoka     */
4829f763d14451685965039990891eb0bc8e8db0735Tadashi G. Takaoka    public boolean isObbMounted(String filename) throws IllegalArgumentException {
4839f763d14451685965039990891eb0bc8e8db0735Tadashi G. Takaoka        try {
4849f763d14451685965039990891eb0bc8e8db0735Tadashi G. Takaoka            return mMountService.isObbMounted(filename);
4853e5a3c18bebbfb56012383411b24ee81ffde09cbTadashi G. Takaoka        } catch (RemoteException e) {
4869f763d14451685965039990891eb0bc8e8db0735Tadashi G. Takaoka            Log.e(TAG, "Failed to check if OBB is mounted", e);
487c04bbc1ae9be81d25a356407c27a8e7fa22028bfTadashi G. Takaoka        }
4882d74806262431ce25b159e1ec5c6ac4a26007c3eTadashi G. Takaoka
4893e5a3c18bebbfb56012383411b24ee81ffde09cbTadashi G. Takaoka        return false;
4902d74806262431ce25b159e1ec5c6ac4a26007c3eTadashi G. Takaoka    }
4912d74806262431ce25b159e1ec5c6ac4a26007c3eTadashi G. Takaoka
4922d74806262431ce25b159e1ec5c6ac4a26007c3eTadashi G. Takaoka    /**
4932d74806262431ce25b159e1ec5c6ac4a26007c3eTadashi G. Takaoka     * Check the mounted path of an Opaque Binary Blob (OBB) file. This will
4942d74806262431ce25b159e1ec5c6ac4a26007c3eTadashi G. Takaoka     * give you the path to where you can obtain access to the internals of the
4952d74806262431ce25b159e1ec5c6ac4a26007c3eTadashi G. Takaoka     * OBB.
4962d74806262431ce25b159e1ec5c6ac4a26007c3eTadashi G. Takaoka     *
4972d74806262431ce25b159e1ec5c6ac4a26007c3eTadashi G. Takaoka     * @param filename path to OBB image
4982d74806262431ce25b159e1ec5c6ac4a26007c3eTadashi G. Takaoka     * @return absolute path to mounted OBB image data or <code>null</code> if
4993e5a3c18bebbfb56012383411b24ee81ffde09cbTadashi G. Takaoka     *         not mounted or exception encountered trying to read status
5003e5a3c18bebbfb56012383411b24ee81ffde09cbTadashi G. Takaoka     */
5012d74806262431ce25b159e1ec5c6ac4a26007c3eTadashi G. Takaoka    public String getMountedObbPath(String filename) {
5022d74806262431ce25b159e1ec5c6ac4a26007c3eTadashi G. Takaoka        try {
5032d74806262431ce25b159e1ec5c6ac4a26007c3eTadashi G. Takaoka            return mMountService.getMountedObbPath(filename);
5042d74806262431ce25b159e1ec5c6ac4a26007c3eTadashi G. Takaoka        } catch (RemoteException e) {
5052d74806262431ce25b159e1ec5c6ac4a26007c3eTadashi G. Takaoka            Log.e(TAG, "Failed to find mounted path for OBB", e);
5062d74806262431ce25b159e1ec5c6ac4a26007c3eTadashi G. Takaoka        } catch (IllegalArgumentException e) {
5072d74806262431ce25b159e1ec5c6ac4a26007c3eTadashi G. Takaoka            Log.d(TAG, "Couldn't read OBB file", e);
5082d74806262431ce25b159e1ec5c6ac4a26007c3eTadashi G. Takaoka        }
5093e5a3c18bebbfb56012383411b24ee81ffde09cbTadashi G. Takaoka
5103e5a3c18bebbfb56012383411b24ee81ffde09cbTadashi G. Takaoka        return null;
5112d74806262431ce25b159e1ec5c6ac4a26007c3eTadashi G. Takaoka    }
5122d74806262431ce25b159e1ec5c6ac4a26007c3eTadashi G. Takaoka}
5132d74806262431ce25b159e1ec5c6ac4a26007c3eTadashi G. Takaoka