Android 框架層爲IMountService 增長新接口

 在爲Android 增長多分區的支持時,可能會須要得到當前 USB 鏈接的掛載口,可能標準的Android 框架並未提供這樣的接口給開發者,這時就須要咱們本身爲它提供接口了。先來看一下上層(應用)如何獲得一個IMountService 的。html

複製代碼
  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;
    }
複製代碼

 關於Binder 能夠參考下這篇文章:Android深刻淺出之Binder機制 。java

Android 2.2新增接口 

Android 2.2爲IMountService 新增接口很是容易,在frameworks/base/core/java/android/os/storage 有一個IMountService.aidl 文件,能夠直接在這個文件裏面新增一個接口提供給上層,如:android

/*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 新增的接口ide

public String getUsbMountPointPath(){
        return usbMountPointPath;
    }

OK。經過上面的操做, StorageManage  就能夠很方便的獲得這個爲其新增的接口,上層即可以訪問了。this

編譯步驟:spa

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

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

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

 

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

  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後則能夠正常使用。 

相關文章
相關標籤/搜索