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