| /* | |
| * Copyright (C) 2010 The Android Open Source Project | |
| * | |
| * Licensed under the Apache License, Version 2.0 (the "License"); | |
| * you may not use this file except in compliance with the License. | |
| * You may obtain a copy of the License at | |
| * | |
| * http://www.apache.org/licenses/LICENSE-2.0 | |
| * | |
| * Unless required by applicable law or agreed to in writing, software | |
| * distributed under the License is distributed on an "AS IS" BASIS, | |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| * See the License for the specific language governing permissions and | |
| * limitations under the License. | |
| */ | |
| #define LOG_TAG "IMountService" | |
| #include <storage/IMountService.h> | |
| #include <binder/Parcel.h> | |
| namespace android { | |
| enum { | |
| TRANSACTION_registerListener = IBinder::FIRST_CALL_TRANSACTION, | |
| TRANSACTION_unregisterListener, | |
| TRANSACTION_isUsbMassStorageConnected, | |
| TRANSACTION_setUsbMassStorageEnabled, | |
| TRANSACTION_isUsbMassStorageEnabled, | |
| TRANSACTION_mountVolume, | |
| TRANSACTION_unmountVolume, | |
| TRANSACTION_formatVolume, | |
| TRANSACTION_getStorageUsers, | |
| TRANSACTION_getVolumeState, | |
| TRANSACTION_createSecureContainer, | |
| TRANSACTION_finalizeSecureContainer, | |
| TRANSACTION_destroySecureContainer, | |
| TRANSACTION_mountSecureContainer, | |
| TRANSACTION_unmountSecureContainer, | |
| TRANSACTION_isSecureContainerMounted, | |
| TRANSACTION_renameSecureContainer, | |
| TRANSACTION_getSecureContainerPath, | |
| TRANSACTION_getSecureContainerList, | |
| TRANSACTION_shutdown, | |
| TRANSACTION_finishMediaUpdate, | |
| TRANSACTION_mountObb, | |
| TRANSACTION_unmountObb, | |
| TRANSACTION_isObbMounted, | |
| TRANSACTION_getMountedObbPath, | |
| TRANSACTION_isExternalStorageEmulated, | |
| }; | |
| class BpMountService: public BpInterface<IMountService> | |
| { | |
| public: | |
| explicit BpMountService(const sp<IBinder>& impl) | |
| : BpInterface<IMountService>(impl) | |
| { | |
| } | |
| virtual void registerListener(const sp<IMountServiceListener>& listener) | |
| { | |
| Parcel data, reply; | |
| data.writeInterfaceToken(IMountService::getInterfaceDescriptor()); | |
| data.writeStrongBinder(IInterface::asBinder(listener)); | |
| if (remote()->transact(TRANSACTION_registerListener, data, &reply) != NO_ERROR) { | |
| ALOGD("registerListener could not contact remote\n"); | |
| return; | |
| } | |
| int32_t err = reply.readExceptionCode(); | |
| if (err < 0) { | |
| ALOGD("registerListener caught exception %d\n", err); | |
| return; | |
| } | |
| } | |
| virtual void unregisterListener(const sp<IMountServiceListener>& listener) | |
| { | |
| Parcel data, reply; | |
| data.writeInterfaceToken(IMountService::getInterfaceDescriptor()); | |
| data.writeStrongBinder(IInterface::asBinder(listener)); | |
| if (remote()->transact(TRANSACTION_unregisterListener, data, &reply) != NO_ERROR) { | |
| ALOGD("unregisterListener could not contact remote\n"); | |
| return; | |
| } | |
| int32_t err = reply.readExceptionCode(); | |
| if (err < 0) { | |
| ALOGD("unregisterListener caught exception %d\n", err); | |
| return; | |
| } | |
| } | |
| virtual bool isUsbMassStorageConnected() | |
| { | |
| Parcel data, reply; | |
| data.writeInterfaceToken(IMountService::getInterfaceDescriptor()); | |
| if (remote()->transact(TRANSACTION_isUsbMassStorageConnected, data, &reply) != NO_ERROR) { | |
| ALOGD("isUsbMassStorageConnected could not contact remote\n"); | |
| return false; | |
| } | |
| int32_t err = reply.readExceptionCode(); | |
| if (err < 0) { | |
| ALOGD("isUsbMassStorageConnected caught exception %d\n", err); | |
| return false; | |
| } | |
| return reply.readInt32() != 0; | |
| } | |
| virtual void setUsbMassStorageEnabled(const bool enable) | |
| { | |
| Parcel data, reply; | |
| data.writeInterfaceToken(IMountService::getInterfaceDescriptor()); | |
| data.writeInt32(enable != 0); | |
| if (remote()->transact(TRANSACTION_setUsbMassStorageEnabled, data, &reply) != NO_ERROR) { | |
| ALOGD("setUsbMassStorageEnabled could not contact remote\n"); | |
| return; | |
| } | |
| int32_t err = reply.readExceptionCode(); | |
| if (err < 0) { | |
| ALOGD("setUsbMassStorageEnabled caught exception %d\n", err); | |
| return; | |
| } | |
| } | |
| virtual bool isUsbMassStorageEnabled() | |
| { | |
| Parcel data, reply; | |
| data.writeInterfaceToken(IMountService::getInterfaceDescriptor()); | |
| if (remote()->transact(TRANSACTION_isUsbMassStorageEnabled, data, &reply) != NO_ERROR) { | |
| ALOGD("isUsbMassStorageEnabled could not contact remote\n"); | |
| return false; | |
| } | |
| int32_t err = reply.readExceptionCode(); | |
| if (err < 0) { | |
| ALOGD("isUsbMassStorageEnabled caught exception %d\n", err); | |
| return false; | |
| } | |
| return reply.readInt32() != 0; | |
| } | |
| int32_t mountVolume(const String16& mountPoint) | |
| { | |
| Parcel data, reply; | |
| data.writeInterfaceToken(IMountService::getInterfaceDescriptor()); | |
| data.writeString16(mountPoint); | |
| if (remote()->transact(TRANSACTION_mountVolume, data, &reply) != NO_ERROR) { | |
| ALOGD("mountVolume could not contact remote\n"); | |
| return -1; | |
| } | |
| int32_t err = reply.readExceptionCode(); | |
| if (err < 0) { | |
| ALOGD("mountVolume caught exception %d\n", err); | |
| return err; | |
| } | |
| return reply.readInt32(); | |
| } | |
| int32_t unmountVolume(const String16& mountPoint, const bool force, const bool removeEncryption) | |
| { | |
| Parcel data, reply; | |
| data.writeInterfaceToken(IMountService::getInterfaceDescriptor()); | |
| data.writeString16(mountPoint); | |
| data.writeInt32(force ? 1 : 0); | |
| data.writeInt32(removeEncryption ? 1 : 0); | |
| if (remote()->transact(TRANSACTION_unmountVolume, data, &reply) != NO_ERROR) { | |
| ALOGD("unmountVolume could not contact remote\n"); | |
| return -1; | |
| } | |
| int32_t err = reply.readExceptionCode(); | |
| if (err < 0) { | |
| ALOGD("unmountVolume caught exception %d\n", err); | |
| return err; | |
| } | |
| return reply.readInt32(); | |
| } | |
| int32_t formatVolume(const String16& mountPoint) | |
| { | |
| Parcel data, reply; | |
| data.writeInterfaceToken(IMountService::getInterfaceDescriptor()); | |
| data.writeString16(mountPoint); | |
| if (remote()->transact(TRANSACTION_formatVolume, data, &reply) != NO_ERROR) { | |
| ALOGD("formatVolume could not contact remote\n"); | |
| return -1; | |
| } | |
| int32_t err = reply.readExceptionCode(); | |
| if (err < 0) { | |
| ALOGD("formatVolume caught exception %d\n", err); | |
| return err; | |
| } | |
| return reply.readInt32(); | |
| } | |
| int32_t getStorageUsers(const String16& mountPoint, int32_t** users) | |
| { | |
| Parcel data, reply; | |
| data.writeInterfaceToken(IMountService::getInterfaceDescriptor()); | |
| data.writeString16(mountPoint); | |
| if (remote()->transact(TRANSACTION_getStorageUsers, data, &reply) != NO_ERROR) { | |
| ALOGD("getStorageUsers could not contact remote\n"); | |
| return -1; | |
| } | |
| int32_t err = reply.readExceptionCode(); | |
| if (err < 0) { | |
| ALOGD("getStorageUsers caught exception %d\n", err); | |
| return err; | |
| } | |
| int32_t numUsersI = reply.readInt32(); | |
| uint32_t numUsers; | |
| if (numUsersI < 0) { | |
| ALOGW("Number of users is negative: %d\n", numUsersI); | |
| numUsers = 0; | |
| } else { | |
| numUsers = static_cast<uint32_t>(numUsersI); | |
| } | |
| *users = (int32_t*)malloc(sizeof(int32_t)*numUsers); | |
| for (size_t i = 0; i < numUsers; i++) { | |
| **users++ = reply.readInt32(); | |
| } | |
| return static_cast<int32_t>(numUsers); | |
| } | |
| int32_t getVolumeState(const String16& mountPoint) | |
| { | |
| Parcel data, reply; | |
| data.writeInterfaceToken(IMountService::getInterfaceDescriptor()); | |
| data.writeString16(mountPoint); | |
| if (remote()->transact(TRANSACTION_getVolumeState, data, &reply) != NO_ERROR) { | |
| ALOGD("getVolumeState could not contact remote\n"); | |
| return -1; | |
| } | |
| int32_t err = reply.readExceptionCode(); | |
| if (err < 0) { | |
| ALOGD("getVolumeState caught exception %d\n", err); | |
| return err; | |
| } | |
| return reply.readInt32(); | |
| } | |
| int32_t createSecureContainer(const String16& id, const int32_t sizeMb, const String16& fstype, | |
| const String16& key, const int32_t ownerUid) | |
| { | |
| Parcel data, reply; | |
| data.writeInterfaceToken(IMountService::getInterfaceDescriptor()); | |
| data.writeString16(id); | |
| data.writeInt32(sizeMb); | |
| data.writeString16(fstype); | |
| data.writeString16(key); | |
| data.writeInt32(ownerUid); | |
| if (remote()->transact(TRANSACTION_createSecureContainer, data, &reply) != NO_ERROR) { | |
| ALOGD("createSecureContainer could not contact remote\n"); | |
| return -1; | |
| } | |
| int32_t err = reply.readExceptionCode(); | |
| if (err < 0) { | |
| ALOGD("createSecureContainer caught exception %d\n", err); | |
| return err; | |
| } | |
| return reply.readInt32(); | |
| } | |
| int32_t finalizeSecureContainer(const String16& id) | |
| { | |
| Parcel data, reply; | |
| data.writeInterfaceToken(IMountService::getInterfaceDescriptor()); | |
| data.writeString16(id); | |
| if (remote()->transact(TRANSACTION_finalizeSecureContainer, data, &reply) != NO_ERROR) { | |
| ALOGD("finalizeSecureContainer couldn't call remote\n"); | |
| return -1; | |
| } | |
| int32_t err = reply.readExceptionCode(); | |
| if (err < 0) { | |
| ALOGD("finalizeSecureContainer caught exception %d\n", err); | |
| return err; | |
| } | |
| return reply.readInt32(); | |
| } | |
| int32_t destroySecureContainer(const String16& id) | |
| { | |
| Parcel data, reply; | |
| data.writeInterfaceToken(IMountService::getInterfaceDescriptor()); | |
| data.writeString16(id); | |
| if (remote()->transact(TRANSACTION_destroySecureContainer, data, &reply) != NO_ERROR) { | |
| ALOGD("destroySecureContainer couldn't call remote"); | |
| return -1; | |
| } | |
| int32_t err = reply.readExceptionCode(); | |
| if (err < 0) { | |
| ALOGD("destroySecureContainer caught exception %d\n", err); | |
| return err; | |
| } | |
| return reply.readInt32(); | |
| } | |
| int32_t mountSecureContainer(const String16& id, const String16& key, const int32_t ownerUid) | |
| { | |
| Parcel data, reply; | |
| data.writeInterfaceToken(IMountService::getInterfaceDescriptor()); | |
| data.writeString16(id); | |
| data.writeString16(key); | |
| data.writeInt32(ownerUid); | |
| // Assume read-only | |
| data.writeInt32(1); | |
| if (remote()->transact(TRANSACTION_mountSecureContainer, data, &reply) != NO_ERROR) { | |
| ALOGD("mountSecureContainer couldn't call remote"); | |
| return -1; | |
| } | |
| int32_t err = reply.readExceptionCode(); // What to do... | |
| if (err < 0) { | |
| ALOGD("mountSecureContainer caught exception %d\n", err); | |
| return err; | |
| } | |
| return reply.readInt32(); | |
| } | |
| int32_t unmountSecureContainer(const String16& id, const bool force) | |
| { | |
| Parcel data, reply; | |
| data.writeInterfaceToken(IMountService::getInterfaceDescriptor()); | |
| data.writeString16(id); | |
| data.writeInt32(force ? 1 : 0); | |
| if (remote()->transact(TRANSACTION_getSecureContainerPath, data, &reply) != NO_ERROR) { | |
| ALOGD("unmountSecureContainer couldn't call remote"); | |
| return -1; | |
| } | |
| int32_t err = reply.readExceptionCode(); // What to do... | |
| if (err < 0) { | |
| ALOGD("unmountSecureContainer caught exception %d\n", err); | |
| return err; | |
| } | |
| return reply.readInt32(); | |
| } | |
| bool isSecureContainerMounted(const String16& id) | |
| { | |
| Parcel data, reply; | |
| data.writeInterfaceToken(IMountService::getInterfaceDescriptor()); | |
| data.writeString16(id); | |
| if (remote()->transact(TRANSACTION_isSecureContainerMounted, data, &reply) != NO_ERROR) { | |
| ALOGD("isSecureContainerMounted couldn't call remote"); | |
| return false; | |
| } | |
| int32_t err = reply.readExceptionCode(); // What to do... | |
| if (err < 0) { | |
| ALOGD("isSecureContainerMounted caught exception %d\n", err); | |
| return false; | |
| } | |
| return reply.readInt32() != 0; | |
| } | |
| int32_t renameSecureContainer(const String16& oldId, const String16& newId) | |
| { | |
| Parcel data, reply; | |
| data.writeInterfaceToken(IMountService::getInterfaceDescriptor()); | |
| data.writeString16(oldId); | |
| data.writeString16(newId); | |
| if (remote()->transact(TRANSACTION_renameSecureContainer, data, &reply) != NO_ERROR) { | |
| ALOGD("renameSecureContainer couldn't call remote"); | |
| return -1; | |
| } | |
| int32_t err = reply.readExceptionCode(); // What to do... | |
| if (err < 0) { | |
| ALOGD("renameSecureContainer caught exception %d\n", err); | |
| return err; | |
| } | |
| return reply.readInt32(); | |
| } | |
| bool getSecureContainerPath(const String16& id, String16& path) | |
| { | |
| Parcel data, reply; | |
| data.writeInterfaceToken(IMountService::getInterfaceDescriptor()); | |
| data.writeString16(id); | |
| if (remote()->transact(TRANSACTION_getSecureContainerPath, data, &reply) != NO_ERROR) { | |
| ALOGD("getSecureContainerPath couldn't call remote"); | |
| return false; | |
| } | |
| int32_t err = reply.readExceptionCode(); // What to do... | |
| if (err < 0) { | |
| ALOGD("getSecureContainerPath caught exception %d\n", err); | |
| return false; | |
| } | |
| path = reply.readString16(); | |
| return true; | |
| } | |
| int32_t getSecureContainerList(const String16& id, String16*& containers) | |
| { | |
| Parcel data, reply; | |
| data.writeInterfaceToken(IMountService::getInterfaceDescriptor()); | |
| data.writeString16(id); | |
| if (remote()->transact(TRANSACTION_getSecureContainerList, data, &reply) != NO_ERROR) { | |
| ALOGD("getSecureContainerList couldn't call remote"); | |
| return -1; | |
| } | |
| int32_t err = reply.readExceptionCode(); | |
| if (err < 0) { | |
| ALOGD("getSecureContainerList caught exception %d\n", err); | |
| return err; | |
| } | |
| const int32_t numStrings = reply.readInt32(); | |
| containers = new String16[numStrings]; | |
| for (int i = 0; i < numStrings; i++) { | |
| containers[i] = reply.readString16(); | |
| } | |
| return numStrings; | |
| } | |
| void shutdown(const sp<IMountShutdownObserver>& observer) | |
| { | |
| Parcel data, reply; | |
| data.writeInterfaceToken(IMountService::getInterfaceDescriptor()); | |
| data.writeStrongBinder(IInterface::asBinder(observer)); | |
| if (remote()->transact(TRANSACTION_shutdown, data, &reply) != NO_ERROR) { | |
| ALOGD("shutdown could not contact remote\n"); | |
| return; | |
| } | |
| int32_t err = reply.readExceptionCode(); | |
| if (err < 0) { | |
| ALOGD("shutdown caught exception %d\n", err); | |
| return; | |
| } | |
| reply.readExceptionCode(); | |
| } | |
| void finishMediaUpdate() | |
| { | |
| Parcel data, reply; | |
| data.writeInterfaceToken(IMountService::getInterfaceDescriptor()); | |
| if (remote()->transact(TRANSACTION_finishMediaUpdate, data, &reply) != NO_ERROR) { | |
| ALOGD("finishMediaUpdate could not contact remote\n"); | |
| return; | |
| } | |
| int32_t err = reply.readExceptionCode(); | |
| if (err < 0) { | |
| ALOGD("finishMediaUpdate caught exception %d\n", err); | |
| return; | |
| } | |
| reply.readExceptionCode(); | |
| } | |
| void mountObb(const String16& rawPath, const String16& canonicalPath, | |
| const sp<IObbActionListener>& token, int32_t nonce, const sp<ObbInfo>& obbInfo) | |
| { | |
| Parcel data, reply; | |
| data.writeInterfaceToken(IMountService::getInterfaceDescriptor()); | |
| data.writeString16(rawPath); | |
| data.writeString16(canonicalPath); | |
| data.writeStrongBinder(IInterface::asBinder(token)); | |
| data.writeInt32(nonce); | |
| obbInfo->writeToParcel(&data); | |
| if (remote()->transact(TRANSACTION_mountObb, data, &reply) != NO_ERROR) { | |
| ALOGD("mountObb could not contact remote\n"); | |
| return; | |
| } | |
| int32_t err = reply.readExceptionCode(); | |
| if (err < 0) { | |
| ALOGD("mountObb caught exception %d\n", err); | |
| return; | |
| } | |
| } | |
| void unmountObb(const String16& filename, const bool force, | |
| const sp<IObbActionListener>& token, const int32_t nonce) | |
| { | |
| Parcel data, reply; | |
| data.writeInterfaceToken(IMountService::getInterfaceDescriptor()); | |
| data.writeString16(filename); | |
| data.writeInt32(force ? 1 : 0); | |
| data.writeStrongBinder(IInterface::asBinder(token)); | |
| data.writeInt32(nonce); | |
| if (remote()->transact(TRANSACTION_unmountObb, data, &reply) != NO_ERROR) { | |
| ALOGD("unmountObb could not contact remote\n"); | |
| return; | |
| } | |
| int32_t err = reply.readExceptionCode(); | |
| if (err < 0) { | |
| ALOGD("unmountObb caught exception %d\n", err); | |
| return; | |
| } | |
| } | |
| bool isObbMounted(const String16& filename) | |
| { | |
| Parcel data, reply; | |
| data.writeInterfaceToken(IMountService::getInterfaceDescriptor()); | |
| data.writeString16(filename); | |
| if (remote()->transact(TRANSACTION_isObbMounted, data, &reply) != NO_ERROR) { | |
| ALOGD("isObbMounted could not contact remote\n"); | |
| return false; | |
| } | |
| int32_t err = reply.readExceptionCode(); | |
| if (err < 0) { | |
| ALOGD("isObbMounted caught exception %d\n", err); | |
| return false; | |
| } | |
| return reply.readInt32() != 0; | |
| } | |
| bool getMountedObbPath(const String16& filename, String16& path) | |
| { | |
| Parcel data, reply; | |
| data.writeInterfaceToken(IMountService::getInterfaceDescriptor()); | |
| data.writeString16(filename); | |
| if (remote()->transact(TRANSACTION_getMountedObbPath, data, &reply) != NO_ERROR) { | |
| ALOGD("getMountedObbPath could not contact remote\n"); | |
| return false; | |
| } | |
| int32_t err = reply.readExceptionCode(); | |
| if (err < 0) { | |
| ALOGD("getMountedObbPath caught exception %d\n", err); | |
| return false; | |
| } | |
| path = reply.readString16(); | |
| return true; | |
| } | |
| }; | |
| IMPLEMENT_META_INTERFACE(MountService, "android.os.storage.IStorageManager") | |
| // ---------------------------------------------------------------------- | |
| } |