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 "IMountService"
18
19#include <storage/IMountService.h>
20#include <binder/Parcel.h>
21
22namespace android {
23
24enum {
25    TRANSACTION_registerListener = IBinder::FIRST_CALL_TRANSACTION,
26    TRANSACTION_unregisterListener,
27    TRANSACTION_isUsbMassStorageConnected,
28    TRANSACTION_setUsbMassStorageEnabled,
29    TRANSACTION_isUsbMassStorageEnabled,
30    TRANSACTION_mountVolume,
31    TRANSACTION_unmountVolume,
32    TRANSACTION_formatVolume,
33    TRANSACTION_getStorageUsers,
34    TRANSACTION_getVolumeState,
35    TRANSACTION_createSecureContainer,
36    TRANSACTION_finalizeSecureContainer,
37    TRANSACTION_destroySecureContainer,
38    TRANSACTION_mountSecureContainer,
39    TRANSACTION_unmountSecureContainer,
40    TRANSACTION_isSecureContainerMounted,
41    TRANSACTION_renameSecureContainer,
42    TRANSACTION_getSecureContainerPath,
43    TRANSACTION_getSecureContainerList,
44    TRANSACTION_shutdown,
45    TRANSACTION_finishMediaUpdate,
46    TRANSACTION_mountObb,
47    TRANSACTION_unmountObb,
48    TRANSACTION_isObbMounted,
49    TRANSACTION_getMountedObbPath,
50    TRANSACTION_isExternalStorageEmulated,
51    TRANSACTION_decryptStorage,
52    TRANSACTION_encryptStorage,
53};
54
55class BpMountService: public BpInterface<IMountService>
56{
57public:
58    explicit BpMountService(const sp<IBinder>& impl)
59        : BpInterface<IMountService>(impl)
60    {
61    }
62
63    virtual void registerListener(const sp<IMountServiceListener>& listener)
64    {
65        Parcel data, reply;
66        data.writeInterfaceToken(IMountService::getInterfaceDescriptor());
67        data.writeStrongBinder(IInterface::asBinder(listener));
68        if (remote()->transact(TRANSACTION_registerListener, data, &reply) != NO_ERROR) {
69            ALOGD("registerListener could not contact remote\n");
70            return;
71        }
72        int32_t err = reply.readExceptionCode();
73        if (err < 0) {
74            ALOGD("registerListener caught exception %d\n", err);
75            return;
76        }
77    }
78
79    virtual void unregisterListener(const sp<IMountServiceListener>& listener)
80    {
81        Parcel data, reply;
82        data.writeInterfaceToken(IMountService::getInterfaceDescriptor());
83        data.writeStrongBinder(IInterface::asBinder(listener));
84        if (remote()->transact(TRANSACTION_unregisterListener, data, &reply) != NO_ERROR) {
85            ALOGD("unregisterListener could not contact remote\n");
86            return;
87        }
88        int32_t err = reply.readExceptionCode();
89        if (err < 0) {
90            ALOGD("unregisterListener caught exception %d\n", err);
91            return;
92        }
93    }
94
95    virtual bool isUsbMassStorageConnected()
96    {
97        Parcel data, reply;
98        data.writeInterfaceToken(IMountService::getInterfaceDescriptor());
99        if (remote()->transact(TRANSACTION_isUsbMassStorageConnected, data, &reply) != NO_ERROR) {
100            ALOGD("isUsbMassStorageConnected could not contact remote\n");
101            return false;
102        }
103        int32_t err = reply.readExceptionCode();
104        if (err < 0) {
105            ALOGD("isUsbMassStorageConnected caught exception %d\n", err);
106            return false;
107        }
108        return reply.readInt32() != 0;
109    }
110
111    virtual void setUsbMassStorageEnabled(const bool enable)
112    {
113        Parcel data, reply;
114        data.writeInterfaceToken(IMountService::getInterfaceDescriptor());
115        data.writeInt32(enable != 0);
116        if (remote()->transact(TRANSACTION_setUsbMassStorageEnabled, data, &reply) != NO_ERROR) {
117            ALOGD("setUsbMassStorageEnabled could not contact remote\n");
118            return;
119        }
120        int32_t err = reply.readExceptionCode();
121        if (err < 0) {
122            ALOGD("setUsbMassStorageEnabled caught exception %d\n", err);
123            return;
124        }
125    }
126
127    virtual bool isUsbMassStorageEnabled()
128    {
129        Parcel data, reply;
130        data.writeInterfaceToken(IMountService::getInterfaceDescriptor());
131        if (remote()->transact(TRANSACTION_isUsbMassStorageEnabled, data, &reply) != NO_ERROR) {
132            ALOGD("isUsbMassStorageEnabled could not contact remote\n");
133            return false;
134        }
135        int32_t err = reply.readExceptionCode();
136        if (err < 0) {
137            ALOGD("isUsbMassStorageEnabled caught exception %d\n", err);
138            return false;
139        }
140        return reply.readInt32() != 0;
141    }
142
143    int32_t mountVolume(const String16& mountPoint)
144    {
145        Parcel data, reply;
146        data.writeInterfaceToken(IMountService::getInterfaceDescriptor());
147        data.writeString16(mountPoint);
148        if (remote()->transact(TRANSACTION_mountVolume, data, &reply) != NO_ERROR) {
149            ALOGD("mountVolume could not contact remote\n");
150            return -1;
151        }
152        int32_t err = reply.readExceptionCode();
153        if (err < 0) {
154            ALOGD("mountVolume caught exception %d\n", err);
155            return err;
156        }
157        return reply.readInt32();
158    }
159
160    int32_t unmountVolume(const String16& mountPoint, const bool force, const bool removeEncryption)
161    {
162        Parcel data, reply;
163        data.writeInterfaceToken(IMountService::getInterfaceDescriptor());
164        data.writeString16(mountPoint);
165        data.writeInt32(force ? 1 : 0);
166        data.writeInt32(removeEncryption ? 1 : 0);
167        if (remote()->transact(TRANSACTION_unmountVolume, data, &reply) != NO_ERROR) {
168            ALOGD("unmountVolume could not contact remote\n");
169            return -1;
170        }
171        int32_t err = reply.readExceptionCode();
172        if (err < 0) {
173            ALOGD("unmountVolume caught exception %d\n", err);
174            return err;
175        }
176        return reply.readInt32();
177    }
178
179    int32_t formatVolume(const String16& mountPoint)
180    {
181        Parcel data, reply;
182        data.writeInterfaceToken(IMountService::getInterfaceDescriptor());
183        data.writeString16(mountPoint);
184        if (remote()->transact(TRANSACTION_formatVolume, data, &reply) != NO_ERROR) {
185            ALOGD("formatVolume could not contact remote\n");
186            return -1;
187        }
188        int32_t err = reply.readExceptionCode();
189        if (err < 0) {
190            ALOGD("formatVolume caught exception %d\n", err);
191            return err;
192        }
193        return reply.readInt32();
194    }
195
196    int32_t getStorageUsers(const String16& mountPoint, int32_t** users)
197    {
198        Parcel data, reply;
199        data.writeInterfaceToken(IMountService::getInterfaceDescriptor());
200        data.writeString16(mountPoint);
201        if (remote()->transact(TRANSACTION_getStorageUsers, data, &reply) != NO_ERROR) {
202            ALOGD("getStorageUsers could not contact remote\n");
203            return -1;
204        }
205        int32_t err = reply.readExceptionCode();
206        if (err < 0) {
207            ALOGD("getStorageUsers caught exception %d\n", err);
208            return err;
209        }
210        int32_t numUsersI = reply.readInt32();
211        uint32_t numUsers;
212        if (numUsersI < 0) {
213            ALOGW("Number of users is negative: %d\n", numUsersI);
214            numUsers = 0;
215        } else {
216            numUsers = static_cast<uint32_t>(numUsersI);
217        }
218        *users = (int32_t*)malloc(sizeof(int32_t)*numUsers);
219        for (size_t i = 0; i < numUsers; i++) {
220            **users++ = reply.readInt32();
221        }
222        return static_cast<int32_t>(numUsers);
223    }
224
225    int32_t getVolumeState(const String16& mountPoint)
226    {
227        Parcel data, reply;
228        data.writeInterfaceToken(IMountService::getInterfaceDescriptor());
229        data.writeString16(mountPoint);
230        if (remote()->transact(TRANSACTION_getVolumeState, data, &reply) != NO_ERROR) {
231            ALOGD("getVolumeState could not contact remote\n");
232            return -1;
233        }
234        int32_t err = reply.readExceptionCode();
235        if (err < 0) {
236            ALOGD("getVolumeState caught exception %d\n", err);
237            return err;
238        }
239        return reply.readInt32();
240    }
241
242    int32_t createSecureContainer(const String16& id, const int32_t sizeMb, const String16& fstype,
243            const String16& key, const int32_t ownerUid)
244    {
245        Parcel data, reply;
246        data.writeInterfaceToken(IMountService::getInterfaceDescriptor());
247        data.writeString16(id);
248        data.writeInt32(sizeMb);
249        data.writeString16(fstype);
250        data.writeString16(key);
251        data.writeInt32(ownerUid);
252        if (remote()->transact(TRANSACTION_createSecureContainer, data, &reply) != NO_ERROR) {
253            ALOGD("createSecureContainer could not contact remote\n");
254            return -1;
255        }
256        int32_t err = reply.readExceptionCode();
257        if (err < 0) {
258            ALOGD("createSecureContainer caught exception %d\n", err);
259            return err;
260        }
261        return reply.readInt32();
262    }
263
264    int32_t finalizeSecureContainer(const String16& id)
265    {
266        Parcel data, reply;
267        data.writeInterfaceToken(IMountService::getInterfaceDescriptor());
268        data.writeString16(id);
269        if (remote()->transact(TRANSACTION_finalizeSecureContainer, data, &reply) != NO_ERROR) {
270            ALOGD("finalizeSecureContainer couldn't call remote\n");
271            return -1;
272        }
273        int32_t err = reply.readExceptionCode();
274        if (err < 0) {
275            ALOGD("finalizeSecureContainer caught exception %d\n", err);
276            return err;
277        }
278        return reply.readInt32();
279    }
280
281    int32_t destroySecureContainer(const String16& id)
282    {
283        Parcel data, reply;
284        data.writeInterfaceToken(IMountService::getInterfaceDescriptor());
285        data.writeString16(id);
286        if (remote()->transact(TRANSACTION_destroySecureContainer, data, &reply) != NO_ERROR) {
287            ALOGD("destroySecureContainer couldn't call remote");
288            return -1;
289        }
290        int32_t err = reply.readExceptionCode();
291        if (err < 0) {
292            ALOGD("destroySecureContainer caught exception %d\n", err);
293            return err;
294        }
295        return reply.readInt32();
296    }
297
298    int32_t mountSecureContainer(const String16& id, const String16& key, const int32_t ownerUid)
299    {
300        Parcel data, reply;
301        data.writeInterfaceToken(IMountService::getInterfaceDescriptor());
302        data.writeString16(id);
303        data.writeString16(key);
304        data.writeInt32(ownerUid);
305        // Assume read-only
306        data.writeInt32(1);
307        if (remote()->transact(TRANSACTION_mountSecureContainer, data, &reply) != NO_ERROR) {
308            ALOGD("mountSecureContainer couldn't call remote");
309            return -1;
310        }
311        int32_t err = reply.readExceptionCode(); // What to do...
312        if (err < 0) {
313            ALOGD("mountSecureContainer caught exception %d\n", err);
314            return err;
315        }
316        return reply.readInt32();
317    }
318
319    int32_t unmountSecureContainer(const String16& id, const bool force)
320    {
321        Parcel data, reply;
322        data.writeInterfaceToken(IMountService::getInterfaceDescriptor());
323        data.writeString16(id);
324        data.writeInt32(force ? 1 : 0);
325        if (remote()->transact(TRANSACTION_getSecureContainerPath, data, &reply) != NO_ERROR) {
326            ALOGD("unmountSecureContainer couldn't call remote");
327            return -1;
328        }
329        int32_t err = reply.readExceptionCode(); // What to do...
330        if (err < 0) {
331            ALOGD("unmountSecureContainer caught exception %d\n", err);
332            return err;
333        }
334        return reply.readInt32();
335    }
336
337    bool isSecureContainerMounted(const String16& id)
338    {
339        Parcel data, reply;
340        data.writeInterfaceToken(IMountService::getInterfaceDescriptor());
341        data.writeString16(id);
342        if (remote()->transact(TRANSACTION_isSecureContainerMounted, data, &reply) != NO_ERROR) {
343            ALOGD("isSecureContainerMounted couldn't call remote");
344            return false;
345        }
346        int32_t err = reply.readExceptionCode(); // What to do...
347        if (err < 0) {
348            ALOGD("isSecureContainerMounted caught exception %d\n", err);
349            return false;
350        }
351        return reply.readInt32() != 0;
352    }
353
354    int32_t renameSecureContainer(const String16& oldId, const String16& newId)
355    {
356        Parcel data, reply;
357        data.writeInterfaceToken(IMountService::getInterfaceDescriptor());
358        data.writeString16(oldId);
359        data.writeString16(newId);
360        if (remote()->transact(TRANSACTION_renameSecureContainer, data, &reply) != NO_ERROR) {
361            ALOGD("renameSecureContainer couldn't call remote");
362            return -1;
363        }
364        int32_t err = reply.readExceptionCode(); // What to do...
365        if (err < 0) {
366            ALOGD("renameSecureContainer caught exception %d\n", err);
367            return err;
368        }
369        return reply.readInt32();
370    }
371
372    bool getSecureContainerPath(const String16& id, String16& path)
373    {
374        Parcel data, reply;
375        data.writeInterfaceToken(IMountService::getInterfaceDescriptor());
376        data.writeString16(id);
377        if (remote()->transact(TRANSACTION_getSecureContainerPath, data, &reply) != NO_ERROR) {
378            ALOGD("getSecureContainerPath couldn't call remote");
379            return false;
380        }
381        int32_t err = reply.readExceptionCode(); // What to do...
382        if (err < 0) {
383            ALOGD("getSecureContainerPath caught exception %d\n", err);
384            return false;
385        }
386        path = reply.readString16();
387        return true;
388    }
389
390    int32_t getSecureContainerList(const String16& id, String16*& containers)
391    {
392        Parcel data, reply;
393        data.writeInterfaceToken(IMountService::getInterfaceDescriptor());
394        data.writeString16(id);
395        if (remote()->transact(TRANSACTION_getSecureContainerList, data, &reply) != NO_ERROR) {
396            ALOGD("getSecureContainerList couldn't call remote");
397            return -1;
398        }
399        int32_t err = reply.readExceptionCode();
400        if (err < 0) {
401            ALOGD("getSecureContainerList caught exception %d\n", err);
402            return err;
403        }
404        const int32_t numStrings = reply.readInt32();
405        containers = new String16[numStrings];
406        for (int i = 0; i < numStrings; i++) {
407            containers[i] = reply.readString16();
408        }
409        return numStrings;
410    }
411
412    void shutdown(const sp<IMountShutdownObserver>& observer)
413    {
414        Parcel data, reply;
415        data.writeInterfaceToken(IMountService::getInterfaceDescriptor());
416        data.writeStrongBinder(IInterface::asBinder(observer));
417        if (remote()->transact(TRANSACTION_shutdown, data, &reply) != NO_ERROR) {
418            ALOGD("shutdown could not contact remote\n");
419            return;
420        }
421        int32_t err = reply.readExceptionCode();
422        if (err < 0) {
423            ALOGD("shutdown caught exception %d\n", err);
424            return;
425        }
426        reply.readExceptionCode();
427    }
428
429    void finishMediaUpdate()
430    {
431        Parcel data, reply;
432        data.writeInterfaceToken(IMountService::getInterfaceDescriptor());
433        if (remote()->transact(TRANSACTION_finishMediaUpdate, data, &reply) != NO_ERROR) {
434            ALOGD("finishMediaUpdate could not contact remote\n");
435            return;
436        }
437        int32_t err = reply.readExceptionCode();
438        if (err < 0) {
439            ALOGD("finishMediaUpdate caught exception %d\n", err);
440            return;
441        }
442        reply.readExceptionCode();
443    }
444
445    void mountObb(const String16& rawPath, const String16& canonicalPath, const String16& key,
446            const sp<IObbActionListener>& token, int32_t nonce)
447    {
448        Parcel data, reply;
449        data.writeInterfaceToken(IMountService::getInterfaceDescriptor());
450        data.writeString16(rawPath);
451        data.writeString16(canonicalPath);
452        data.writeString16(key);
453        data.writeStrongBinder(IInterface::asBinder(token));
454        data.writeInt32(nonce);
455        if (remote()->transact(TRANSACTION_mountObb, data, &reply) != NO_ERROR) {
456            ALOGD("mountObb could not contact remote\n");
457            return;
458        }
459        int32_t err = reply.readExceptionCode();
460        if (err < 0) {
461            ALOGD("mountObb caught exception %d\n", err);
462            return;
463        }
464    }
465
466    void unmountObb(const String16& filename, const bool force,
467            const sp<IObbActionListener>& token, const int32_t nonce)
468    {
469        Parcel data, reply;
470        data.writeInterfaceToken(IMountService::getInterfaceDescriptor());
471        data.writeString16(filename);
472        data.writeInt32(force ? 1 : 0);
473        data.writeStrongBinder(IInterface::asBinder(token));
474        data.writeInt32(nonce);
475        if (remote()->transact(TRANSACTION_unmountObb, data, &reply) != NO_ERROR) {
476            ALOGD("unmountObb could not contact remote\n");
477            return;
478        }
479        int32_t err = reply.readExceptionCode();
480        if (err < 0) {
481            ALOGD("unmountObb caught exception %d\n", err);
482            return;
483        }
484    }
485
486    bool isObbMounted(const String16& filename)
487    {
488        Parcel data, reply;
489        data.writeInterfaceToken(IMountService::getInterfaceDescriptor());
490        data.writeString16(filename);
491        if (remote()->transact(TRANSACTION_isObbMounted, data, &reply) != NO_ERROR) {
492            ALOGD("isObbMounted could not contact remote\n");
493            return false;
494        }
495        int32_t err = reply.readExceptionCode();
496        if (err < 0) {
497            ALOGD("isObbMounted caught exception %d\n", err);
498            return false;
499        }
500        return reply.readInt32() != 0;
501    }
502
503    bool getMountedObbPath(const String16& filename, String16& path)
504    {
505        Parcel data, reply;
506        data.writeInterfaceToken(IMountService::getInterfaceDescriptor());
507        data.writeString16(filename);
508        if (remote()->transact(TRANSACTION_getMountedObbPath, data, &reply) != NO_ERROR) {
509            ALOGD("getMountedObbPath could not contact remote\n");
510            return false;
511        }
512        int32_t err = reply.readExceptionCode();
513        if (err < 0) {
514            ALOGD("getMountedObbPath caught exception %d\n", err);
515            return false;
516        }
517        path = reply.readString16();
518        return true;
519    }
520
521    int32_t decryptStorage(const String16& password)
522    {
523        Parcel data, reply;
524        data.writeInterfaceToken(IMountService::getInterfaceDescriptor());
525        data.writeString16(password);
526        if (remote()->transact(TRANSACTION_decryptStorage, data, &reply) != NO_ERROR) {
527            ALOGD("decryptStorage could not contact remote\n");
528            return -1;
529        }
530        int32_t err = reply.readExceptionCode();
531        if (err < 0) {
532            ALOGD("decryptStorage caught exception %d\n", err);
533            return err;
534        }
535        return reply.readInt32();
536    }
537
538    int32_t encryptStorage(const String16& password)
539    {
540        Parcel data, reply;
541        data.writeInterfaceToken(IMountService::getInterfaceDescriptor());
542        data.writeString16(password);
543        if (remote()->transact(TRANSACTION_encryptStorage, data, &reply) != NO_ERROR) {
544            ALOGD("encryptStorage could not contact remote\n");
545            return -1;
546        }
547        int32_t err = reply.readExceptionCode();
548        if (err < 0) {
549            ALOGD("encryptStorage caught exception %d\n", err);
550            return err;
551        }
552        return reply.readInt32();
553    }
554};
555
556IMPLEMENT_META_INTERFACE(MountService, "android.os.storage.IStorageManager")
557
558// ----------------------------------------------------------------------
559
560}
561