1 /* 2 * Copyright (C) 2010 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #define LOG_TAG "NStorage" 18 19 #include <android/storage_manager.h> 20 #include <storage/IMountService.h> 21 22 #include <binder/Binder.h> 23 #include <binder/IServiceManager.h> 24 #include <cutils/atomic.h> 25 #include <utils/Log.h> 26 #include <utils/RefBase.h> 27 #include <utils/String8.h> 28 #include <utils/String16.h> 29 #include <utils/Vector.h> 30 #include <utils/threads.h> 31 32 33 using namespace android; 34 35 struct ObbActionListener : public BnObbActionListener { 36 private: 37 sp<AStorageManager> mStorageManager; 38 39 public: 40 explicit ObbActionListener(AStorageManager* mgr) : 41 mStorageManager(mgr) 42 {} 43 44 virtual void onObbResult(const android::String16& filename, const int32_t nonce, 45 const int32_t state); 46 }; 47 48 class ObbCallback { 49 public: 50 ObbCallback(int32_t _nonce, AStorageManager_obbCallbackFunc _cb, void* _data) 51 : nonce(_nonce) 52 , cb(_cb) 53 , data(_data) 54 {} 55 56 int32_t nonce; 57 AStorageManager_obbCallbackFunc cb; 58 void* data; 59 }; 60 61 struct AStorageManager : public RefBase { 62 protected: 63 Mutex mCallbackLock; 64 Vector<ObbCallback*> mCallbacks; 65 volatile int32_t mNextNonce; 66 sp<ObbActionListener> mObbActionListener; 67 sp<IMountService> mMountService; 68 69 int32_t getNextNonce() { 70 return android_atomic_inc(&mNextNonce); 71 } 72 73 ObbCallback* registerObbCallback(AStorageManager_obbCallbackFunc func, void* data) { 74 ObbCallback* cb = new ObbCallback(getNextNonce(), func, data); 75 { 76 AutoMutex _l(mCallbackLock); 77 mCallbacks.push(cb); 78 } 79 return cb; 80 } 81 82 public: 83 AStorageManager() 84 { 85 } 86 87 bool initialize() { 88 sp<IServiceManager> sm = defaultServiceManager(); 89 if (sm == NULL) { 90 ALOGE("Couldn't get default ServiceManager\n"); 91 return false; 92 } 93 94 mMountService = interface_cast<IMountService>(sm->getService(String16("mount"))); 95 if (mMountService == NULL) { 96 ALOGE("Couldn't get connection to MountService\n"); 97 return false; 98 } 99 100 mObbActionListener = new ObbActionListener(this); 101 102 return true; 103 } 104 105 void fireCallback(const char* filename, const int32_t nonce, const int32_t state) { 106 ObbCallback* target = NULL; 107 { 108 AutoMutex _l(mCallbackLock); 109 int N = mCallbacks.size(); 110 for (int i = 0; i < N; i++) { 111 ObbCallback* cb = mCallbacks.editItemAt(i); 112 if (cb->nonce == nonce) { 113 target = cb; 114 mCallbacks.removeAt(i); 115 break; 116 } 117 } 118 } 119 120 if (target != NULL) { 121 target->cb(filename, state, target->data); 122 delete target; 123 } else { 124 ALOGI("Didn't find the callback handler for: %s\n", filename); 125 } 126 } 127 128 void mountObb(const char* rawPath, const char* key, AStorageManager_obbCallbackFunc func, 129 void* data) { 130 // Resolve path before sending to MountService 131 char canonicalPath[PATH_MAX]; 132 if (realpath(rawPath, canonicalPath) == NULL) { 133 ALOGE("mountObb failed to resolve path %s: %s", rawPath, strerror(errno)); 134 return; 135 } 136 137 ObbCallback* cb = registerObbCallback(func, data); 138 String16 rawPath16(rawPath); 139 String16 canonicalPath16(canonicalPath); 140 String16 key16(key); 141 mMountService->mountObb(rawPath16, canonicalPath16, key16, mObbActionListener, cb->nonce); 142 } 143 144 void unmountObb(const char* filename, const bool force, AStorageManager_obbCallbackFunc func, void* data) { 145 ObbCallback* cb = registerObbCallback(func, data); 146 String16 filename16(filename); 147 mMountService->unmountObb(filename16, force, mObbActionListener, cb->nonce); 148 } 149 150 int isObbMounted(const char* filename) { 151 String16 filename16(filename); 152 return mMountService->isObbMounted(filename16); 153 } 154 155 const char* getMountedObbPath(const char* filename) { 156 String16 filename16(filename); 157 String16 path16; 158 if (mMountService->getMountedObbPath(filename16, path16)) { 159 return String8(path16).string(); 160 } else { 161 return NULL; 162 } 163 } 164 }; 165 166 void ObbActionListener::onObbResult(const android::String16& filename, const int32_t nonce, const int32_t state) { 167 mStorageManager->fireCallback(String8(filename).string(), nonce, state); 168 } 169 170 171 AStorageManager* AStorageManager_new() { 172 sp<AStorageManager> mgr = new AStorageManager(); 173 if (mgr == NULL || !mgr->initialize()) { 174 return NULL; 175 } 176 mgr->incStrong((void*)AStorageManager_new); 177 return static_cast<AStorageManager*>(mgr.get()); 178 } 179 180 void AStorageManager_delete(AStorageManager* mgr) { 181 if (mgr) { 182 mgr->decStrong((void*)AStorageManager_new); 183 } 184 } 185 186 void AStorageManager_mountObb(AStorageManager* mgr, const char* filename, const char* key, 187 AStorageManager_obbCallbackFunc cb, void* data) { 188 mgr->mountObb(filename, key, cb, data); 189 } 190 191 void AStorageManager_unmountObb(AStorageManager* mgr, const char* filename, const int force, 192 AStorageManager_obbCallbackFunc cb, void* data) { 193 mgr->unmountObb(filename, force != 0, cb, data); 194 } 195 196 int AStorageManager_isObbMounted(AStorageManager* mgr, const char* filename) { 197 return mgr->isObbMounted(filename) != 0; 198 } 199 200 const char* AStorageManager_getMountedObbPath(AStorageManager* mgr, const char* filename) { 201 return mgr->getMountedObbPath(filename); 202 } 203