1、背景
項目中遇到一個需求,要對Mdmservice進行管控。簡化下來大概就是需要監聽一個系統屬性值,當這個屬性值變爲false的時候,禁止調用揚聲器、聽筒。跟蹤代碼發現這個需求裏面的場景,只需要處理MediaRecorder就能達到目標。
2、實現
根據需求,調用揚聲器、聽筒之前讀取一下系統屬性值判斷一下即可,有個場景是正在調用揚聲器、聽筒的過程中屬性值發生變化,着重要處理的就是這個場景。
2.1 定義AIDL接口
接口名稱定爲INotifyPolicyChange.aidl,直接給出代碼:
/*
* server use this interface of client
*/
interface INotifyPolicyChange {
void notifyPolicyChange();
}
2.2 在IMdmService.aidl中定義註冊、去註冊接口
interface IMdmService {
//Interactive interface
void registerCallBack(IBinder token, INotifyPolicyChange callback);
void unregisterCallBack(INotifyPolicyChange callback);
……
}
2.3 在MdmService中實現註冊、去註冊
給出代碼片段:
private RemoteCallbackList<INotifyPolicyChange> mCallBacks = new RemoteCallbackList<>();
final class ClientDeathCallback implements DeathRecipient {
public final IBinder mToken;
public final INotifyPolicyChange mCallback;
public ClientDeathCallback(IBinder token, INotifyPolicyChange mCallback) {
this.mToken = token;
this.mCallback = mCallback;
}
@Override
public void binderDied() {
Log.d(TAG,"client died! mToken=" + mToken + ";callback=" + mCallback);
try {
unregisterCallBack(mCallback);
} catch (RemoteException e) {
e.printStackTrace();
}
}
}
public void registerCallBack(IBinder token, INotifyPolicyChange callback) throws RemoteException {
ClientDeathCallback clientDeathCallback = new ClientDeathCallback(token, callback);
//register callback
mCallBacks.register(callback);
//register recipient
token.linkToDeath(clientDeathCallback, 0);
}
public void unregisterCallBack(INotifyPolicyChange callback) throws RemoteException {
mCallBacks.unregister(callback);
}
/**
* notify client that policy change
*/
private void notifyChange() {
final int len = mCallBacks.beginBroadcast();
for(int i = 0; i < len; i++) {
try {
mCallBacks.getBroadcastItem(i).notifyPolicyChange();
} catch (RemoteException e) {
e.printStackTrace();
}
}
mCallBacks.finishBroadcast();
}
public boolean setMicrophonePolicy(int policy) throws RemoteException {
if(isActive) {
boolean success = MdmDevicePolicyManager.getInstance(mContext)
.getPeripheralPolicy().setMicrophonePolicy(policy);
//notify client policy changed
if(success) {
notifyChange();
}
return success;
}
return false;
}
2.4 在MediaRecorder中實現業務邏輯
給出代碼片段:
private IBinder mBinder;
private IMdmService mMdmService;
public MediaRecorder() {
//get mdmservice mBinder and register a callback
mBinder = ServiceManager.getService("mdm3");
mMdmService = mBinder == null ? null : IMdmService.Stub.asInterface(mBinder);
if(mMdmService != null) {
try {
mMdmService.registerCallBack(new Binder(), mNotifyCallBack);
} catch (RemoteException e) {
e.printStackTrace();
}
} else {
Log.e(TAG, "MediaRecorder cannot get mdmservice mBinder!");
}
}
private INotifyPolicyChange mNotifyCallBack = new INotifyPolicyChange.Stub() {
@Override
public void notifyPolicyChange() throws RemoteException {
//add logic here
}
};
mBinder = ServiceManager.getService("mdm3");
這句代碼能獲取到MdmService實例是因爲在SystemService已經以“mdm3”對MdmService註冊過了。
2.5 在mk及其他文件裏註冊新增AIDL文件
新增了AIDL之後,需手動註冊,否則編譯時找不到相應文件。
core/java/android/service/mdm3/INotifyPolicyChange.aidl
編譯過後,“api/current.txt”、“api/system-current.txt”、“api/test-current”也新增了相應接口。
這樣,就完成了在framework中新增一個AIDL接口。