在為Android 增加多分區的支持時,可能會需要獲得當前 USB 連接的掛載口,可能標准的Android 框架並未提供這樣的接口給開發者,這時就需要我們自己為它提供接口了。先來看一下上層(應用)如何得到一個IMountService 的。
if (mMountService == null) {
IBinder service = ServiceManager.getService("mount");
if (service != null) {
mMountService = IMountService.Stub.asInterface(service);
} else {
Log.e(TAG, "Can't get mount service");
}
}
return mMountService;
}
關於Binder 可以參考下這篇文章:Android深入淺出之Binder機制 。
Android 2.2新增接口
Android 2.2為IMountService 新增接口非常容易,在frameworks/base/core/java/android/os/storage 有一個IMountService.aidl 文件,可以直接在這個文件里面新增一個接口提供給上層,如:
String getUsbMountPointPath() ;
該文件負責生成IMountService.java文件,接着進入frameworks/base/services/java/com/android/server ,打開MountService.java 該文件繼承於IMountService.aidl生成的類
在這個類里面實現我們為IMountService.aidl 新增的接口
return usbMountPointPath;
}
OK。通過上面的操作, StorageManage 就可以很方便的得到這個為其新增的接口,上層便可以訪問了。
編譯步驟:
1):編譯framework/base (生成IMountService.java)
2):編譯framework/base/service (編譯MountService)
3):編譯framework/base (編譯StorageManage以提供給上層調用)
Android 4.0 以上新增接口
相比於Android 2.2,在Android 4.0框架層 為IMountService 新增一個接口就顯得比較復雜了。
按照Android 2.2 新增接口的方法,我們會先進入frameworks/base/core/java/android/os/storage 查找IMountService.aidl文件,進入目錄,ls 一下,會發現並沒有該文件,取而代之的是IMountService.java。這是怎么回事?打開該文件:映入眼簾首先會看到該警告:
* WARNING! Update IMountService.h and IMountService.cpp if you change this
* file. In particular, the ordering of the methods below must match the
* _TRANSACTION enum in IMountService.cpp
*
* @hide - Applications should use android.os.storage.StorageManager to access
* storage functions.
*/
該警告提示我們,如果要修改這個文件,必須先修改IMountService.h 頭文件和 IMountService.cpp 文件 ,並且還需要注意枚舉里面的順序。按照警告可以一步步修改了。
進入frameworks/base/include/storage 打開IMountService.h ,新增這個方法:
完成后進入frameworks/base/libs/storage 打開IMountService.cpp ,在枚舉里面新增方法枚舉:
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,
TRANSACTION_decryptStorage,
TRANSACTION_encryptStorage,
TRANSACTION_getUsbMountPointPath,
};
接着新增要實現的方法
{
Parcel data, reply;
data.writeInterfaceToken(IMountService::getInterfaceDescriptor());
if (remote()->transact( TRANSACTION_getUsbMountPointPath, data, &reply) != NO_ERROR) {
LOGD( " getVolumeState could not contact remote\n ");
return - 1;
}
int32_t err = reply.readExceptionCode();
if (err < 0) {
LOGD( " getVolumeState caught exception %d\n ", err);
return err;
}
return reply.readInt32();
}
OK,這個方法到了這里,CPP部分就算完成了。接下來可以為IMountService.java加接口了。
再次進入frameworks/base/core/java/android/os/storage ,打開IMountService.java 文件。
實現該接口,增加以下方法:
Parcel _data = Parcel.obtain();
Parcel _reply = Parcel.obtain();
String _result;
try {
_data.writeInterfaceToken(DESCRIPTOR);
mRemote.transact( Stub.TRANSACTION_getUsbMountPointPath, _data, _reply, 0);
_reply.readException();
_result = _reply.readString();
} finally {
_reply.recycle();
_data.recycle();
}
return _result;
}
增加這個常量:static final int TRANSACTION_getUsbMountPointPath = IBinder.FIRST_CALL_TRANSACTION + 28;
在onTransact方法里面增加一個case 判斷:
data.enforceInterface(DESCRIPTOR);
String state = getUsbMountPointPath();
reply.writeNoException();
reply.writeString(state);
return true;
}
最后,再增加一個該接口的方法
到此為止,為IMountService 增加接口所要做的必要步驟就算完成了。
編譯步驟:
1):編譯framework/base/libs/storage ,產生libstorage.a靜態文件。
2):編譯framework/base/native/android 產生libandroid.so動態庫文件,該文件最終會被IMountService.java 使用。必須通過push 到 system/lib 目錄下 。
3) :編譯framework/base/service 讓getUsbMountPointPath 接口生效。
4):編譯framework/base 這樣我們就可以在使用StorageManage 來讀取IMountService 的新接口了。
注:StorageManage 部分就不寫了,可以借鑒其他的方法,添加一個可供上層訪問的方法,這部分比較簡單。StorageManage在2.2是隱藏的不被開發者使用的,在4.0后則可以正常使用。