Home | History | Annotate | Download | only in android
      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