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 #include <storage/ObbInfo.h>
22 
23 #include <androidfw/ObbFile.h>
24 #include <binder/Binder.h>
25 #include <binder/IServiceManager.h>
26 #include <cutils/atomic.h>
27 #include <utils/Log.h>
28 #include <utils/RefBase.h>
29 #include <utils/String8.h>
30 #include <utils/String16.h>
31 #include <utils/Vector.h>
32 #include <utils/threads.h>
33 
34 using namespace android;
35 
36 struct ObbActionListener : public BnObbActionListener {
37 private:
38     sp<AStorageManager> mStorageManager;
39 
40 public:
ObbActionListenerObbActionListener41     explicit ObbActionListener(AStorageManager* mgr) :
42             mStorageManager(mgr)
43     {}
44 
45     virtual void onObbResult(const android::String16& filename, const int32_t nonce,
46             const int32_t state);
47 };
48 
49 class ObbCallback {
50 public:
ObbCallback(int32_t _nonce,AStorageManager_obbCallbackFunc _cb,void * _data)51     ObbCallback(int32_t _nonce, AStorageManager_obbCallbackFunc _cb, void* _data)
52             : nonce(_nonce)
53             , cb(_cb)
54             , data(_data)
55     {}
56 
57     int32_t nonce;
58     AStorageManager_obbCallbackFunc cb;
59     void* data;
60 };
61 
62 struct AStorageManager : public RefBase {
63 protected:
64     Mutex mCallbackLock;
65     Vector<ObbCallback*> mCallbacks;
66     volatile int32_t mNextNonce;
67     sp<ObbActionListener> mObbActionListener;
68     sp<IMountService> mMountService;
69 
getNextNonceAStorageManager70     int32_t getNextNonce() {
71         return android_atomic_inc(&mNextNonce);
72     }
73 
registerObbCallbackAStorageManager74     ObbCallback* registerObbCallback(AStorageManager_obbCallbackFunc func, void* data) {
75         ObbCallback* cb = new ObbCallback(getNextNonce(), func, data);
76         {
77             AutoMutex _l(mCallbackLock);
78             mCallbacks.push(cb);
79         }
80         return cb;
81     }
82 
getObbInfoAStorageManager83     ObbInfo* getObbInfo(char* canonicalPath) {
84         sp<ObbFile> obbFile = new ObbFile();
85         if (!obbFile->readFrom(canonicalPath)) {
86             return nullptr;
87         }
88 
89         String16 fileName(obbFile->getFileName());
90         String16 packageName(obbFile->getPackageName());
91         size_t length;
92         const unsigned char* salt = obbFile->getSalt(&length);
93         return new ObbInfo(fileName, packageName,
94                 obbFile->getVersion(), obbFile->getFlags(), length, salt);
95     }
96 
97 public:
AStorageManagerAStorageManager98     AStorageManager()
99     {
100     }
101 
initializeAStorageManager102     bool initialize() {
103         sp<IServiceManager> sm = defaultServiceManager();
104         if (sm == NULL) {
105             ALOGE("Couldn't get default ServiceManager\n");
106             return false;
107         }
108 
109         mMountService = interface_cast<IMountService>(sm->getService(String16("mount")));
110         if (mMountService == NULL) {
111             ALOGE("Couldn't get connection to MountService\n");
112             return false;
113         }
114 
115         mObbActionListener = new ObbActionListener(this);
116 
117         return true;
118     }
119 
fireCallbackAStorageManager120     void fireCallback(const char* filename, const int32_t nonce, const int32_t state) {
121         ObbCallback* target = NULL;
122         {
123             AutoMutex _l(mCallbackLock);
124             int N = mCallbacks.size();
125             for (int i = 0; i < N; i++) {
126                 ObbCallback* cb = mCallbacks.editItemAt(i);
127                 if (cb->nonce == nonce) {
128                     target = cb;
129                     mCallbacks.removeAt(i);
130                     break;
131                 }
132             }
133         }
134 
135         if (target != NULL) {
136             target->cb(filename, state, target->data);
137             delete target;
138         } else {
139             ALOGI("Didn't find the callback handler for: %s\n", filename);
140         }
141     }
142 
mountObbAStorageManager143     void mountObb(const char* rawPath, const char* key, AStorageManager_obbCallbackFunc func,
144             void* data) {
145         // Resolve path before sending to MountService
146         char canonicalPath[PATH_MAX];
147         if (realpath(rawPath, canonicalPath) == NULL) {
148             ALOGE("mountObb failed to resolve path %s: %s", rawPath, strerror(errno));
149             return;
150         }
151 
152         sp<ObbInfo> obbInfo = getObbInfo(canonicalPath);
153         if (obbInfo == nullptr) {
154             ALOGE("Couldn't get obb info for %s: %s", canonicalPath, strerror(errno));
155             return;
156         }
157 
158         ObbCallback* cb = registerObbCallback(func, data);
159         String16 rawPath16(rawPath);
160         String16 canonicalPath16(canonicalPath);
161         String16 key16(key);
162         mMountService->mountObb(rawPath16, canonicalPath16, key16, mObbActionListener,
163                 cb->nonce, obbInfo);
164     }
165 
unmountObbAStorageManager166     void unmountObb(const char* filename, const bool force, AStorageManager_obbCallbackFunc func, void* data) {
167         ObbCallback* cb = registerObbCallback(func, data);
168         String16 filename16(filename);
169         mMountService->unmountObb(filename16, force, mObbActionListener, cb->nonce);
170     }
171 
isObbMountedAStorageManager172     int isObbMounted(const char* filename) {
173         String16 filename16(filename);
174         return mMountService->isObbMounted(filename16);
175     }
176 
getMountedObbPathAStorageManager177     const char* getMountedObbPath(const char* filename) {
178         String16 filename16(filename);
179         String16 path16;
180         if (mMountService->getMountedObbPath(filename16, path16)) {
181             return String8(path16).string();
182         } else {
183             return NULL;
184         }
185     }
186 };
187 
onObbResult(const android::String16 & filename,const int32_t nonce,const int32_t state)188 void ObbActionListener::onObbResult(const android::String16& filename, const int32_t nonce, const int32_t state) {
189     mStorageManager->fireCallback(String8(filename).string(), nonce, state);
190 }
191 
192 
AStorageManager_new()193 AStorageManager* AStorageManager_new() {
194     sp<AStorageManager> mgr = new AStorageManager();
195     if (mgr == NULL || !mgr->initialize()) {
196         return NULL;
197     }
198     mgr->incStrong((void*)AStorageManager_new);
199     return static_cast<AStorageManager*>(mgr.get());
200 }
201 
AStorageManager_delete(AStorageManager * mgr)202 void AStorageManager_delete(AStorageManager* mgr) {
203     if (mgr) {
204         mgr->decStrong((void*)AStorageManager_new);
205     }
206 }
207 
AStorageManager_mountObb(AStorageManager * mgr,const char * filename,const char * key,AStorageManager_obbCallbackFunc cb,void * data)208 void AStorageManager_mountObb(AStorageManager* mgr, const char* filename, const char* key,
209         AStorageManager_obbCallbackFunc cb, void* data) {
210     mgr->mountObb(filename, key, cb, data);
211 }
212 
AStorageManager_unmountObb(AStorageManager * mgr,const char * filename,const int force,AStorageManager_obbCallbackFunc cb,void * data)213 void AStorageManager_unmountObb(AStorageManager* mgr, const char* filename, const int force,
214         AStorageManager_obbCallbackFunc cb, void* data) {
215     mgr->unmountObb(filename, force != 0, cb, data);
216 }
217 
AStorageManager_isObbMounted(AStorageManager * mgr,const char * filename)218 int AStorageManager_isObbMounted(AStorageManager* mgr, const char* filename) {
219     return mgr->isObbMounted(filename) != 0;
220 }
221 
AStorageManager_getMountedObbPath(AStorageManager * mgr,const char * filename)222 const char* AStorageManager_getMountedObbPath(AStorageManager* mgr, const char* filename) {
223     return mgr->getMountedObbPath(filename);
224 }
225