天天看點

Android 架構層為IMountService 增加新接口

 在為Android 增加多分區的支援時,可能會需要獲得目前 USB 連接配接的挂載口,可能标準的Android 架構并未提供這樣的接口給開發者,這時就需要我們自己為它提供接口了。先來看一下上層(應用)如何得到一個IMountService 的。

 private synchronized IMountService getMountService() {

       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;

    }

Android 2.2為IMountService 新增接口非常容易,在frameworks/base/core/java/android/os/storage 有一個IMountService.aidl 檔案,可以直接在這個檔案裡面新增一個接口提供給上層,如:

/*add by terry*/

    String getUsbMountPointPath();

該檔案負責生成IMountService.java檔案,接着進入frameworks/base/services/java/com/android/server ,打開MountService.java 該檔案繼承于IMountService.aidl生成的類

class MountService extends IMountService.Stub

在這個類裡面實作我們為IMountService.aidl 新增的接口

public String getUsbMountPointPath(){

       return usbMountPointPath;

OK。通過上面的操作, StorageManage  就可以很友善的得到這個為其新增的接口,上層便可以通路了。

編譯步驟:

1):編譯framework/base (生成IMountService.java)

 2):編譯framework/base/service (編譯MountService)

3):編譯framework/base  (編譯StorageManage以提供給上層調用)

相比于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 ,新增這個方法:

 virtual int32_t getUsbMountPointPath() = 0 ;

完成後進入frameworks/base/libs/storage  打開IMountService.cpp ,在枚舉裡面新增方法枚舉:

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,

    TRANSACTION_decryptStorage,

    TRANSACTION_encryptStorage,

    TRANSACTION_getUsbMountPointPath,

};

 接着新增要實作的方法

  int32_t 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 檔案。

實作該接口,增加以下方法:

 public String getUsbMountPointPath() throws RemoteException {

                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 判斷:

case TRANSACTION_getUsbMountPointPath:{

                   data.enforceInterface(DESCRIPTOR);

                    String state = getUsbMountPointPath();

                    reply.writeNoException();

                    reply.writeString(state);

                   return true;

               }

最後,再增加一個該接口的方法

public String getUsbMountPointPath() throws RemoteException;

到此為止,為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後則可以正常使用。 

 本文轉自 terry_龍 51CTO部落格,原文連結:http://blog.51cto.com/terryblog/839287,如需轉載請自行聯系原作者