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接口。