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    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(listener->asBinder());
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(listener->asBinder());
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        const int32_t numUsers = reply.readInt32();
211        *users = (int32_t*)malloc(sizeof(int32_t)*numUsers);
212        for (int i = 0; i < numUsers; i++) {
213            **users++ = reply.readInt32();
214        }
215        return numUsers;
216    }
217
218    int32_t getVolumeState(const String16& mountPoint)
219    {
220        Parcel data, reply;
221        data.writeInterfaceToken(IMountService::getInterfaceDescriptor());
222        data.writeString16(mountPoint);
223        if (remote()->transact(TRANSACTION_getVolumeState, data, &reply) != NO_ERROR) {
224            ALOGD("getVolumeState could not contact remote\n");
225            return -1;
226        }
227        int32_t err = reply.readExceptionCode();
228        if (err < 0) {
229            ALOGD("getVolumeState caught exception %d\n", err);
230            return err;
231        }
232        return reply.readInt32();
233    }
234
235    int32_t createSecureContainer(const String16& id, const int32_t sizeMb, const String16& fstype,
236            const String16& key, const int32_t ownerUid)
237    {
238        Parcel data, reply;
239        data.writeInterfaceToken(IMountService::getInterfaceDescriptor());
240        data.writeString16(id);
241        data.writeInt32(sizeMb);
242        data.writeString16(fstype);
243        data.writeString16(key);
244        data.writeInt32(ownerUid);
245        if (remote()->transact(TRANSACTION_createSecureContainer, data, &reply) != NO_ERROR) {
246            ALOGD("createSecureContainer could not contact remote\n");
247            return -1;
248        }
249        int32_t err = reply.readExceptionCode();
250        if (err < 0) {
251            ALOGD("createSecureContainer caught exception %d\n", err);
252            return err;
253        }
254        return reply.readInt32();
255    }
256
257    int32_t finalizeSecureContainer(const String16& id)
258    {
259        Parcel data, reply;
260        data.writeInterfaceToken(IMountService::getInterfaceDescriptor());
261        data.writeString16(id);
262        if (remote()->transact(TRANSACTION_finalizeSecureContainer, data, &reply) != NO_ERROR) {
263            ALOGD("finalizeSecureContainer couldn't call remote\n");
264            return -1;
265        }
266        int32_t err = reply.readExceptionCode();
267        if (err < 0) {
268            ALOGD("finalizeSecureContainer caught exception %d\n", err);
269            return err;
270        }
271        return reply.readInt32();
272    }
273
274    int32_t destroySecureContainer(const String16& id)
275    {
276        Parcel data, reply;
277        data.writeInterfaceToken(IMountService::getInterfaceDescriptor());
278        data.writeString16(id);
279        if (remote()->transact(TRANSACTION_destroySecureContainer, data, &reply) != NO_ERROR) {
280            ALOGD("destroySecureContainer couldn't call remote");
281            return -1;
282        }
283        int32_t err = reply.readExceptionCode();
284        if (err < 0) {
285            ALOGD("destroySecureContainer caught exception %d\n", err);
286            return err;
287        }
288        return reply.readInt32();
289    }
290
291    int32_t mountSecureContainer(const String16& id, const String16& key, const int32_t ownerUid)
292    {
293        Parcel data, reply;
294        data.writeInterfaceToken(IMountService::getInterfaceDescriptor());
295        data.writeString16(id);
296        data.writeString16(key);
297        data.writeInt32(ownerUid);
298        // Assume read-only
299        data.writeInt32(1);
300        if (remote()->transact(TRANSACTION_mountSecureContainer, data, &reply) != NO_ERROR) {
301            ALOGD("mountSecureContainer couldn't call remote");
302            return -1;
303        }
304        int32_t err = reply.readExceptionCode(); // What to do...
305        if (err < 0) {
306            ALOGD("mountSecureContainer caught exception %d\n", err);
307            return err;
308        }
309        return reply.readInt32();
310    }
311
312    int32_t unmountSecureContainer(const String16& id, const bool force)
313    {
314        Parcel data, reply;
315        data.writeInterfaceToken(IMountService::getInterfaceDescriptor());
316        data.writeString16(id);
317        data.writeInt32(force ? 1 : 0);
318        if (remote()->transact(TRANSACTION_getSecureContainerPath, data, &reply) != NO_ERROR) {
319            ALOGD("unmountSecureContainer couldn't call remote");
320            return -1;
321        }
322        int32_t err = reply.readExceptionCode(); // What to do...
323        if (err < 0) {
324            ALOGD("unmountSecureContainer caught exception %d\n", err);
325            return err;
326        }
327        return reply.readInt32();
328    }
329
330    bool isSecureContainerMounted(const String16& id)
331    {
332        Parcel data, reply;
333        data.writeInterfaceToken(IMountService::getInterfaceDescriptor());
334        data.writeString16(id);
335        if (remote()->transact(TRANSACTION_isSecureContainerMounted, data, &reply) != NO_ERROR) {
336            ALOGD("isSecureContainerMounted couldn't call remote");
337            return false;
338        }
339        int32_t err = reply.readExceptionCode(); // What to do...
340        if (err < 0) {
341            ALOGD("isSecureContainerMounted caught exception %d\n", err);
342            return false;
343        }
344        return reply.readInt32() != 0;
345    }
346
347    int32_t renameSecureContainer(const String16& oldId, const String16& newId)
348    {
349        Parcel data, reply;
350        data.writeInterfaceToken(IMountService::getInterfaceDescriptor());
351        data.writeString16(oldId);
352        data.writeString16(newId);
353        if (remote()->transact(TRANSACTION_renameSecureContainer, data, &reply) != NO_ERROR) {
354            ALOGD("renameSecureContainer couldn't call remote");
355            return -1;
356        }
357        int32_t err = reply.readExceptionCode(); // What to do...
358        if (err < 0) {
359            ALOGD("renameSecureContainer caught exception %d\n", err);
360            return err;
361        }
362        return reply.readInt32();
363    }
364
365    bool getSecureContainerPath(const String16& id, String16& path)
366    {
367        Parcel data, reply;
368        data.writeInterfaceToken(IMountService::getInterfaceDescriptor());
369        data.writeString16(id);
370        if (remote()->transact(TRANSACTION_getSecureContainerPath, data, &reply) != NO_ERROR) {
371            ALOGD("getSecureContainerPath couldn't call remote");
372            return false;
373        }
374        int32_t err = reply.readExceptionCode(); // What to do...
375        if (err < 0) {
376            ALOGD("getSecureContainerPath caught exception %d\n", err);
377            return false;
378        }
379        path = reply.readString16();
380        return true;
381    }
382
383    int32_t getSecureContainerList(const String16& id, String16*& containers)
384    {
385        Parcel data, reply;
386        data.writeInterfaceToken(IMountService::getInterfaceDescriptor());
387        data.writeString16(id);
388        if (remote()->transact(TRANSACTION_getSecureContainerList, data, &reply) != NO_ERROR) {
389            ALOGD("getSecureContainerList couldn't call remote");
390            return -1;
391        }
392        int32_t err = reply.readExceptionCode();
393        if (err < 0) {
394            ALOGD("getSecureContainerList caught exception %d\n", err);
395            return err;
396        }
397        const int32_t numStrings = reply.readInt32();
398        containers = new String16[numStrings];
399        for (int i = 0; i < numStrings; i++) {
400            containers[i] = reply.readString16();
401        }
402        return numStrings;
403    }
404
405    void shutdown(const sp<IMountShutdownObserver>& observer)
406    {
407        Parcel data, reply;
408        data.writeInterfaceToken(IMountService::getInterfaceDescriptor());
409        data.writeStrongBinder(observer->asBinder());
410        if (remote()->transact(TRANSACTION_shutdown, data, &reply) != NO_ERROR) {
411            ALOGD("shutdown could not contact remote\n");
412            return;
413        }
414        int32_t err = reply.readExceptionCode();
415        if (err < 0) {
416            ALOGD("shutdown caught exception %d\n", err);
417            return;
418        }
419        reply.readExceptionCode();
420    }
421
422    void finishMediaUpdate()
423    {
424        Parcel data, reply;
425        data.writeInterfaceToken(IMountService::getInterfaceDescriptor());
426        if (remote()->transact(TRANSACTION_finishMediaUpdate, data, &reply) != NO_ERROR) {
427            ALOGD("finishMediaUpdate could not contact remote\n");
428            return;
429        }
430        int32_t err = reply.readExceptionCode();
431        if (err < 0) {
432            ALOGD("finishMediaUpdate caught exception %d\n", err);
433            return;
434        }
435        reply.readExceptionCode();
436    }
437
438    void mountObb(const String16& rawPath, const String16& canonicalPath, const String16& key,
439            const sp<IObbActionListener>& token, int32_t nonce)
440    {
441        Parcel data, reply;
442        data.writeInterfaceToken(IMountService::getInterfaceDescriptor());
443        data.writeString16(rawPath);
444        data.writeString16(canonicalPath);
445        data.writeString16(key);
446        data.writeStrongBinder(token->asBinder());
447        data.writeInt32(nonce);
448        if (remote()->transact(TRANSACTION_mountObb, data, &reply) != NO_ERROR) {
449            ALOGD("mountObb could not contact remote\n");
450            return;
451        }
452        int32_t err = reply.readExceptionCode();
453        if (err < 0) {
454            ALOGD("mountObb caught exception %d\n", err);
455            return;
456        }
457    }
458
459    void unmountObb(const String16& filename, const bool force,
460            const sp<IObbActionListener>& token, const int32_t nonce)
461    {
462        Parcel data, reply;
463        data.writeInterfaceToken(IMountService::getInterfaceDescriptor());
464        data.writeString16(filename);
465        data.writeInt32(force ? 1 : 0);
466        data.writeStrongBinder(token->asBinder());
467        data.writeInt32(nonce);
468        if (remote()->transact(TRANSACTION_unmountObb, data, &reply) != NO_ERROR) {
469            ALOGD("unmountObb could not contact remote\n");
470            return;
471        }
472        int32_t err = reply.readExceptionCode();
473        if (err < 0) {
474            ALOGD("unmountObb caught exception %d\n", err);
475            return;
476        }
477    }
478
479    bool isObbMounted(const String16& filename)
480    {
481        Parcel data, reply;
482        data.writeInterfaceToken(IMountService::getInterfaceDescriptor());
483        data.writeString16(filename);
484        if (remote()->transact(TRANSACTION_isObbMounted, data, &reply) != NO_ERROR) {
485            ALOGD("isObbMounted could not contact remote\n");
486            return false;
487        }
488        int32_t err = reply.readExceptionCode();
489        if (err < 0) {
490            ALOGD("isObbMounted caught exception %d\n", err);
491            return false;
492        }
493        return reply.readInt32() != 0;
494    }
495
496    bool getMountedObbPath(const String16& filename, String16& path)
497    {
498        Parcel data, reply;
499        data.writeInterfaceToken(IMountService::getInterfaceDescriptor());
500        data.writeString16(filename);
501        if (remote()->transact(TRANSACTION_getMountedObbPath, data, &reply) != NO_ERROR) {
502            ALOGD("getMountedObbPath could not contact remote\n");
503            return false;
504        }
505        int32_t err = reply.readExceptionCode();
506        if (err < 0) {
507            ALOGD("getMountedObbPath caught exception %d\n", err);
508            return false;
509        }
510        path = reply.readString16();
511        return true;
512    }
513
514    int32_t decryptStorage(const String16& password)
515    {
516        Parcel data, reply;
517        data.writeInterfaceToken(IMountService::getInterfaceDescriptor());
518        data.writeString16(password);
519        if (remote()->transact(TRANSACTION_decryptStorage, data, &reply) != NO_ERROR) {
520            ALOGD("decryptStorage could not contact remote\n");
521            return -1;
522        }
523        int32_t err = reply.readExceptionCode();
524        if (err < 0) {
525            ALOGD("decryptStorage caught exception %d\n", err);
526            return err;
527        }
528        return reply.readInt32();
529    }
530
531    int32_t encryptStorage(const String16& password)
532    {
533        Parcel data, reply;
534        data.writeInterfaceToken(IMountService::getInterfaceDescriptor());
535        data.writeString16(password);
536        if (remote()->transact(TRANSACTION_encryptStorage, data, &reply) != NO_ERROR) {
537            ALOGD("encryptStorage could not contact remote\n");
538            return -1;
539        }
540        int32_t err = reply.readExceptionCode();
541        if (err < 0) {
542            ALOGD("encryptStorage caught exception %d\n", err);
543            return err;
544        }
545        return reply.readInt32();
546    }
547};
548
549IMPLEMENT_META_INTERFACE(MountService, "IMountService");
550
551// ----------------------------------------------------------------------
552
553};
554