Android5.1 FrameWork新增自己的SystemService提供API給APP
阿新 • • 發佈:2019-01-07
FrameWork從縱向來看主要就是新增Service並且利用JNI呼叫HAL層C/C++的程式碼來實現提供API給APP操作硬體的目的
本文就是描述在Android5.1如何實現新增自己的System Service來實現跟HAL進行Socket通訊
一:首先先描述如何註冊自己的SystemService並且實現自己的AIDL,我們這部分要實現的目標是在APP通過呼叫 (InfraredManager)context.getSystemService(Context.XXX) 提供API,實現InfraredManager步驟如下
1:將Binder的"客戶端"部分實現在\frameworks\base\core\java\com\android\infrared\InfraredManager.java 同時建立 \frameworks\base\core\java\com\yuekong\infrared\InfraredReceptionManager.aidl
AIDL就是Binder呼叫的介面
package com.android.infrared; import com.android.infrared.IOnInfraredReceivedListener; import java.lang.String; /** * Binder interface that clients running in application context * can use to interface with remote service */ interface InfraredReceptionManager { void sendStartLearnMsg(); void sendLearnMsg(); void sendStopLearnMsg(); void sendInfo(in String info); void addInfraredReceivedListener(in IOnInfraredReceivedListener listener); void removeInfraredReceivedListener(in IOnInfraredReceivedListener listener); }
2:binder介面建立好後,實現"服務端"的service 在\frameworks\base\services\core\java\com\yuekong\infrared\InfraredManagerService
package com.android.infrared; import android.content.Context; import android.widget.Toast; import android.os.IBinder; import com.android.server.SystemService; import com.android.infrared.IOnInfraredReceivedListener; import android.os.RemoteCallbackList; import android.os.Binder; import com.android.infrared.InfraredSocketClient.OnReceivedInfraredListener; import android.os.RemoteException; public class InfraredManagerService extends SystemService implements OnReceivedInfraredListener { private static final String TAG = "InfraredManagerService"; private final Context mContext; private InfraredSocketClient mClient = null; private RemoteCallbackList<IOnInfraredReceivedListener> mListenersList = new RemoteCallbackList<IOnInfraredReceivedListener>(); public InfraredManagerService(Context context){ super(context); mContext = context; publishBinderService(context.INFRARED_SERVICE, mService); } /** * Implementation of AIDL service interface */ private final IBinder mService = new InfraredReceptionManager.Stub() { @Override public void sendStartLearnMsg() { getSocketInstance().sendSocket(CommandConstant.Command_Learn_Start); } @Override public void sendLearnMsg() { getSocketInstance().sendSocket(CommandConstant.Command_Learn_Key); } @Override public void sendStopLearnMsg() { getSocketInstance().sendSocket(CommandConstant.Command_Learn_Stop); } @Override public void sendInfo(String info) { getSocketInstance().sendSocket(info); Xlog.w(TAG, "stop learn mode"); } @Override public void addInfraredReceivedListener(IOnInfraredReceivedListener listener){ if(listener == null){ return; } synchronized(mListenersList){ mListenersList.register(listener, Binder.getCallingUserHandle()); } } @Override public void removeInfraredReceivedListener(IOnInfraredReceivedListener listener){ if(listener == null){ return; } synchronized(mListenersList){ mListenersList.unregister(listener); } } }; /** * Called when service is started by the main system service */ @Override public void onStart() { Xlog.d(TAG, "Service start"); getSocketInstance().startConnection(); getSocketInstance().setInfraredReceivedListener(InfraredManagerService.this); } @Override public void onReceivedInfraredInfo(int mode,boolean success, int[] info){ final int size = mListenersList.beginBroadcast(); for (int i = 0; i < size; i++) { IOnInfraredReceivedListener listener = mListenersList.getBroadcastItem(i); try { Xlog.d(TAG, "binder listener call back" + listener.toString()); listener.onInfraredReceived(mode,success, info); } catch (RemoteException re) { Xlog.d(TAG, "Callback failed "); } } mListenersList.finishBroadcast(); } private InfraredSocketClient getSocketInstance(){ if(mClient == null){ mClient = new InfraredSocketClient(); } return mClient; } }
3:我們在呼叫SystemService的時候都會用context.getSystemService實現呼叫,然後我們實現自己的Manager給App呼叫
package com.android.infrared;
import com.android.infrared.InfraredReceptionManager;
import android.content.Context;
import android.os.RemoteException;
import java.util.ArrayList;
import java.util.List;
public class InfraredManager{
private static final String TAG = "InfraredManager";
private final Context mContext;
private final InfraredReceptionManager mService;
private List<InfraredReceiverListener> mCallBackList = new ArrayList<InfraredReceiverListener>();
private IOnInfraredReceivedListener.Stub mInfraredReceivedListener;
public InfraredManager(Context context,InfraredReceptionManager service ){
this.mContext = context;
this.mService = service;
}
public void sendStartLearnMsg() {
try{
if(mService != null){
mService.sendStartLearnMsg();
}
} catch (RemoteException ex){
}
}
public void sendLearnMsg(){
try{
if(mService != null){
mService.sendLearnMsg();
}
} catch (RemoteException ex){
}
}
public void sendStopLearnMsg() {
try{
if(mService != null){
mService.sendStopLearnMsg();
}
} catch (RemoteException ex){
}
}
public void sendInfo(String info){
try{
mService.sendInfo(info);
} catch (RemoteException ex){
}
}
public void registerListerner(InfraredReceiverListener listener){
synchronized(this){
if(mCallBackList != null && listener != null && !callBackContain(mCallBackList,listener)){
mCallBackList.add(listener);
boolean addedFirstCallback = (mCallBackList.size() == 1);
if(addedFirstCallback){
try {
mService.addInfraredReceivedListener(getInstance());
} catch (RemoteException re) {
}
}
}
}
}
private boolean callBackContain( List<InfraredReceiverListener> callBackList,InfraredReceiverListener listener){
if( callBackList.size() == 0 ){
return false;
}
for(int i = 0 ; i < callBackList.size(); i++ ){
Xlog.d(TAG, "register listener has this : " +listener.toString());
if(callBackList.get(i) == listener ){
return true;
}
}
return false;
}
public void unregisterListener(InfraredReceiverListener listener) {
if(listener == null){
return;
}
synchronized (this) {
final int size = mCallBackList.size();
for (int i = 0; i < size; ++i) {
if (mCallBackList.get(i) == listener) {
Xlog.d(TAG, "unregister listener :" +listener.toString());
mCallBackList.remove(i);
Xlog.d(TAG, "after unregieter size :" + mCallBackList.size());
return;
}
}
if(mCallBackList.size() == 0 && mInfraredReceivedListener != null){
try{
mService.removeInfraredReceivedListener(mInfraredReceivedListener);
}catch(RemoteException re){
}
Xlog.d(TAG, "unregister binder listener :" +mInfraredReceivedListener.toString());
mInfraredReceivedListener = null;
}
}
}
public static abstract class InfraredReceiverListener{
abstract public void onInfraredReceived(int mode,boolean isSuccess,int[] info);
}
private IOnInfraredReceivedListener.Stub getInstance(){
if(mInfraredReceivedListener == null){
mInfraredReceivedListener = new IOnInfraredReceivedListener.Stub() {
@Override
public void onInfraredReceived(int mode,boolean isSuccess,int[] info){
synchronized (InfraredManager.this) {
for (UCONInfraredReceiverListener listener : mCallBackList) {
Xlog.d(TAG, "start call back listener " + listener.toString());
listener.onInfraredReceived(mode,isSuccess,info);
}
}
}
};
}
Xlog.d(TAG, "create binder listener name is " + mInfraredReceivedListener.toString());
return mInfraredReceivedListener;
}
}
//add by zhongqi.shao on 2016-08-05 start
registerService(INFRARED_SERVICE, new ServiceFetcher() {
public Object createService(ContextImpl ctx) {
IBinder b = ServiceManager.getService(INFRARED_SERVICE);
InfraredReceptionManager uconInfraredService =
InfraredReceptionManager.Stub.asInterface(b);
if (InfraredService != null) {
return new InfraredManager(ctx,InfraredService);
} else {
// not supported
return null;
}
}
});
//add by zhongqi.shao on 2016-08-05 end
</pre><pre code_snippet_id="1978267" snippet_file_name="blog_20161110_6_4875789" name="code" class="java">這一步就可以實現在framework新增自己的SystemService