Android 框架层为IMountService 增加新接口

it2022-05-09  24

     在为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;     }

 关于Binder 可以参考下这篇文章:Android深入浅出之Binder机制 。

Android 2.2新增接口 

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 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后则可以正常使用。 

 

转载于:https://www.cnblogs.com/TerryBlog/archive/2012/04/20/2458861.html

相关资源:android框架层为imountservice增加新接口.docx

最新回复(0)