storage_manager.cpp revision 4fbbda4cecb078bd3867f416b02cc75f5455284f
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 <utils/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
33using namespace android;
34
35struct ObbActionListener : public BnObbActionListener {
36private:
37    sp<AStorageManager> mStorageManager;
38
39public:
40    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
48class ObbCallback {
49public:
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
61struct AStorageManager : public RefBase {
62protected:
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
82public:
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
166void 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
171AStorageManager* 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
180void AStorageManager_delete(AStorageManager* mgr) {
181    if (mgr) {
182        mgr->decStrong((void*)AStorageManager_new);
183    }
184}
185
186void 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
191void 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
196int AStorageManager_isObbMounted(AStorageManager* mgr, const char* filename) {
197    return mgr->isObbMounted(filename) != 0;
198}
199
200const char* AStorageManager_getMountedObbPath(AStorageManager* mgr, const char* filename) {
201    return mgr->getMountedObbPath(filename);
202}
203