-一、Aidl接口文件
代碼路徑:frameworks/base/core/java/android/os/IHookStatus.aidl
package android.os;
interface IHookStatus {
boolean IsOffhookByHost();
boolean IsOnhookByHost();
boolean IsOffhookByFxs();
boolean IsOnhookByFxs();
void setstatus(int which, boolean value);
}
在frameworks/base/Android.mk里加入IHookStatus.aidl
LOCAL_SRC_FILES += \
core/java/android/os/IHookStatus.aidl \
使用過aidl的都知道,編譯後aidl文件會生成一個同名的java文件,這是aidl技術的核心代碼,是binder技術java層的實現。
二、Aidl生成的java文件
代碼路徑:out\target\common\obj\JAVA_LIBRARIES\framework_intermediates\core\java\android\os\IHookStatus.java
/*
* This file is auto-generated. DO NOT MODIFY.
* Original file: frameworks/base/core/java/android/os/IHookStatus.aidl
*/
package android.os;
public interface IHookStatus extends android.os.IInterface
{
/** Local-side IPC implementation stub class. */
public static abstract class Stub extends android.os.Binder implements android.os.IHookStatus
{
private static final java.lang.String DESCRIPTOR = "android.os.IHookStatus";
/** Construct the stub at attach it to the interface. */
public Stub()
{
this.attachInterface(this, DESCRIPTOR);
}
/**
* Cast an IBinder object into an android.os.IHookStatus interface,
* generating a proxy if needed.
*/
public static android.os.IHookStatus asInterface(android.os.IBinder obj)
{
if ((obj==null)) {
return null;
}
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
if (((iin!=null)&&(iin instanceof android.os.IHookStatus))) {
return ((android.os.IHookStatus)iin);
}
return new android.os.IHookStatus.Stub.Proxy(obj);
}
@Override public android.os.IBinder asBinder()
{
return this;
}
@Override public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException
{
switch (code)
{
case INTERFACE_TRANSACTION:
{
reply.writeString(DESCRIPTOR);
return true;
}
case TRANSACTION_IsOffhookByHost:
{
data.enforceInterface(DESCRIPTOR);
boolean _result = this.IsOffhookByHost();
reply.writeNoException();
reply.writeInt(((_result)?(1):(0)));
return true;
}
case TRANSACTION_IsOnhookByHost:
{
data.enforceInterface(DESCRIPTOR);
boolean _result = this.IsOnhookByHost();
reply.writeNoException();
reply.writeInt(((_result)?(1):(0)));
return true;
}
case TRANSACTION_IsOffhookByFxs:
{
data.enforceInterface(DESCRIPTOR);
boolean _result = this.IsOffhookByFxs();
reply.writeNoException();
reply.writeInt(((_result)?(1):(0)));
return true;
}
case TRANSACTION_IsOnhookByFxs:
{
data.enforceInterface(DESCRIPTOR);
boolean _result = this.IsOnhookByFxs();
reply.writeNoException();
reply.writeInt(((_result)?(1):(0)));
return true;
}
case TRANSACTION_setstatus:
{
data.enforceInterface(DESCRIPTOR);
int _arg0;
_arg0 = data.readInt();
boolean _arg1;
_arg1 = (0!=data.readInt());
this.setstatus(_arg0, _arg1);
reply.writeNoException();
return true;
}
}
return super.onTransact(code, data, reply, flags);
}
private static class Proxy implements android.os.IHookStatus
{
private android.os.IBinder mRemote;
Proxy(android.os.IBinder remote)
{
mRemote = remote;
}
@Override public android.os.IBinder asBinder()
{
return mRemote;
}
public java.lang.String getInterfaceDescriptor()
{
return DESCRIPTOR;
}
@Override public boolean IsOffhookByHost() throws android.os.RemoteException
{
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
boolean _result;
try {
_data.writeInterfaceToken(DESCRIPTOR);
mRemote.transact(Stub.TRANSACTION_IsOffhookByHost, _data, _reply, 0);
_reply.readException();
_result = (0!=_reply.readInt());
}
finally {
_reply.recycle();
_data.recycle();
}
return _result;
}
@Override public boolean IsOnhookByHost() throws android.os.RemoteException
{
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
boolean _result;
try {
_data.writeInterfaceToken(DESCRIPTOR);
mRemote.transact(Stub.TRANSACTION_IsOnhookByHost, _data, _reply, 0);
_reply.readException();
_result = (0!=_reply.readInt());
}
finally {
_reply.recycle();
_data.recycle();
}
return _result;
}
@Override public boolean IsOffhookByFxs() throws android.os.RemoteException
{
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
boolean _result;
try {
_data.writeInterfaceToken(DESCRIPTOR);
mRemote.transact(Stub.TRANSACTION_IsOffhookByFxs, _data, _reply, 0);
_reply.readException();
_result = (0!=_reply.readInt());
}
finally {
_reply.recycle();
_data.recycle();
}
return _result;
}
@Override public boolean IsOnhookByFxs() throws android.os.RemoteException
{
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
boolean _result;
try {
_data.writeInterfaceToken(DESCRIPTOR);
mRemote.transact(Stub.TRANSACTION_IsOnhookByFxs, _data, _reply, 0);
_reply.readException();
_result = (0!=_reply.readInt());
}
finally {
_reply.recycle();
_data.recycle();
}
return _result;
}
@Override public void setstatus(int which, boolean value) throws android.os.RemoteException
{
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
try {
_data.writeInterfaceToken(DESCRIPTOR);
_data.writeInt(which);
_data.writeInt(((value)?(1):(0)));
mRemote.transact(Stub.TRANSACTION_setstatus, _data, _reply, 0);
_reply.readException();
}
finally {
_reply.recycle();
_data.recycle();
}
}
}
static final int TRANSACTION_IsOffhookByHost = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
static final int TRANSACTION_IsOnhookByHost = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
static final int TRANSACTION_IsOffhookByFxs = (android.os.IBinder.FIRST_CALL_TRANSACTION + 2);
static final int TRANSACTION_IsOnhookByFxs = (android.os.IBinder.FIRST_CALL_TRANSACTION + 3);
static final int TRANSACTION_setstatus = (android.os.IBinder.FIRST_CALL_TRANSACTION + 4);
}
public boolean IsOffhookByHost() throws android.os.RemoteException;
public boolean IsOnhookByHost() throws android.os.RemoteException;
public boolean IsOffhookByFxs() throws android.os.RemoteException;
public boolean IsOnhookByFxs() throws android.os.RemoteException;
public void setstatus(int which, boolean value) throws android.os.RemoteException;
}
三、HookStatusService服務的定義
代碼路徑:\frameworks\base\services\core\java\com\android\server\os\HookStatusService.java
package com.android.server.os;
import android.os.IHookStatus;
public class HookStatusService extends IHookStatus.Stub {
private static final String TAG = "HookStatusService";
@Override
public boolean IsOffhookByHost() {
return true;
}
@Override
public boolean IsOnhookByHost() {
return true;
}
@Override
public boolean IsOffhookByFxs() {
return true;
}
@Override
public boolean IsOnhookByFxs() {
return true;
}
@Override
public void setstatus(int which, boolean value) {
}
}
HookStatusService實現之前定義的方法,我們需要看到的是HookStatusService繼IHookStatus.Stub。
四、定義HookStatusService的封裝接口HookStatusManager
代碼路徑:frameworks/base/core/java/android/app/HookStatusManager.java
package android.app;
import android.content.Context;
import android.util.Log;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.RemoteException;
import android.os.IHookStatus;
public class HookStatusManager {
private static final String TAG = "HookStatusManager";
private IHookStatus mService;
public static final int OFFHOOK_HOST = 0;
public static final int ONHOOK_HOST = 1;
public static final int OFFHOOK_FXS = 2;
public static final int ONHOOK_FXS = 3;
public HookStatusManager(Context ctx, IHookStatus service){
mService = service;
}
public boolean IsOffhookByHost() {
try {
return mService.IsOffhookByHost();
}catch(Exception e){
Log.e(TAG, "exception=" + e);
e.printStackTrace();
}
return false;
}
public boolean IsOnhookByHost() {
try {
return mService.IsOnhookByHost();
}catch(Exception e){
Log.e(TAG, "exception=" + e);
e.printStackTrace();
}
return false;
}
public boolean IsOffhookByFxs() {
try {
return mService.IsOffhookByFxs();
} catch(Exception e){
Log.e(TAG, "exception=" + e);
e.printStackTrace();
}
return false;
}
public boolean IsOnhookByFxs() {
try {
return mService.IsOnhookByFxs();
} catch(Exception e){
Log.e(TAG, "exception=" + e);
e.printStackTrace();
}
return false;
}
public void setstatus(int which, boolean value) {
try {
mService.setstatus(which, value);
}catch(Exception e){
Log.e(TAG, "exception=" + e);
e.printStackTrace();
}
}
}
封裝了之前在服務端實現的方法,注意到方法的調用者是IHookStatus,實際上在後續註冊服務的時候,我們可以看到並把它理解爲服務的本地代理prox。
五、自定義服務添加到SystemService
1、代碼路徑:/frameworks/base/services/java/com/android/server/SystemServer.java
導入頭文件
import com.android.server.os.HookStatusService;
在startOtherServices()方法中註冊
private void startOtherServices() {
traceBeginAndSlog("Start hookstatus service");
ServiceManager.addService(Context.HOOKSTATUS_SERVICE, new HookStatusService());
traceEnd();
}
systemserver是啓動各個系統服務的地方,系統服務會add到servicemanager,由其管理。
2、代碼路徑:frameworks/base/core/java/android/app/SystemServiceRegistry.java 在靜態代碼塊中增加如下代碼
import android.os.IHookStatus;
static {
registerService(Context.HOOKSTATUS_SERVICE, HookStatusManager.class,
new CachedServiceFetcher<HookStatusManager>() {
@Override
public HookStatusManager createService(ContextImpl ctx) throws ServiceNotFoundException {
IBinder b = ServiceManager.getServiceOrThrow(Context.HOOKSTATUS_SERVICE);
return new HookStatusManager(ctx, IHookStatus.Stub.asInterface(b));
}
});
}
定義了getsystemservice獲得manager的位置
六、服務名字的定義
代碼路徑:frameworks/base/core/java/android/content/Context.java
public static final String HOOKSTATUS_SERVICE = "hookstatus";
七、自定義服務sepolicy權限策略配置
1、代碼路徑:system/sepolicy/prebuilts/api/26.0/private/service_contexts 以及 system/sepolicy/private/service_contexts兩個配置文件分別添加
hookstatus u:object_r:hookstatus_service:s0
2、system/sepolicy/prebuilts/api/26.0/public/service.te 以及 system/sepolicy/public/service.te兩個配置文件分別添加
type hookstatus_service, system_api_service, system_server_service, service_manager_type;
需要添加的代碼到這裏就結束了,編譯前需要先 make update-api,然後正常編譯即可.
八、代碼驗證
import android.app.HookStatusManager;
private HookStatusManager mHookStatusManager ;
mHookStatusManager = (HookStatusManager)this.getSystemService("hookstatus");
Log.e(TAG, "mHookStatusManager !"+mHookStatusManager .IsOffhookByFxs());
打印結果
04-29 09:03:16.711 19377 19377 E MyService: mHookStatusManager !true