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 
33 using namespace android;
34 
35 struct ObbActionListener : public BnObbActionListener {
36 private:
37     sp<AStorageManager> mStorageManager;
38 
39 public:
ObbActionListenerObbActionListener40     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:
ObbCallback(int32_t _nonce,AStorageManager_obbCallbackFunc _cb,void * _data)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 
getNextNonceAStorageManager69     int32_t getNextNonce() {
70         return android_atomic_inc(&mNextNonce);
71     }
72 
registerObbCallbackAStorageManager73     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:
AStorageManagerAStorageManager83     AStorageManager()
84     {
85     }
86 
initializeAStorageManager87     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 
fireCallbackAStorageManager105     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 
mountObbAStorageManager128     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 
unmountObbAStorageManager144     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 
isObbMountedAStorageManager150     int isObbMounted(const char* filename) {
151         String16 filename16(filename);
152         return mMountService->isObbMounted(filename16);
153     }
154 
getMountedObbPathAStorageManager155     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 
onObbResult(const android::String16 & filename,const int32_t nonce,const int32_t state)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 
AStorageManager_new()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 
AStorageManager_delete(AStorageManager * mgr)180 void AStorageManager_delete(AStorageManager* mgr) {
181     if (mgr) {
182         mgr->decStrong((void*)AStorageManager_new);
183     }
184 }
185 
AStorageManager_mountObb(AStorageManager * mgr,const char * filename,const char * key,AStorageManager_obbCallbackFunc cb,void * data)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 
AStorageManager_unmountObb(AStorageManager * mgr,const char * filename,const int force,AStorageManager_obbCallbackFunc cb,void * data)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 
AStorageManager_isObbMounted(AStorageManager * mgr,const char * filename)196 int AStorageManager_isObbMounted(AStorageManager* mgr, const char* filename) {
197     return mgr->isObbMounted(filename) != 0;
198 }
199 
AStorageManager_getMountedObbPath(AStorageManager * mgr,const char * filename)200 const char* AStorageManager_getMountedObbPath(AStorageManager* mgr, const char* filename) {
201     return mgr->getMountedObbPath(filename);
202 }
203