1. 程式人生 > >Android5.1 FrameWork新增自己的SystemService提供API給APP

Android5.1 FrameWork新增自己的SystemService提供API給APP

   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