Android TV 添加系统服务,通过Binder机制从APK对其进行跨进程远程调用

关于Binder机制及其原理可以阅读《深入理解Android内核设计思想》第6章,不再详述。

此处,仅介绍一个系统service的具体实现示例

实现过程:

1.apk调用的是jar包里的函数

2.服务器上编译生成jar包供apk使用

首先是source命令加载并选择sh脚本,执行mm命令之后会打包生成三个jar包

com.***.tvapi.factory.jar
com.***.factory.jar
com.***.facservice.jar

 

http://blog.csdn.net/yajun0601/article/details/7309010

3.框架层的结构分析:

1.APK调用FactoryMenuAdapter的函数:

public class ThirdParty {
	private final static String TAG = "ThirdParty";
	public static FactoryMenuAdapter mFactoryAdapter;
	public ThirdParty(Context mContext_) {
		ThirdParty.mContext = mContext_;
		mFactoryAdapter = FactoryMenuAdapter.getInstance(mContext_);
	}
	public static void setRGainValue(int value) {
		mFactoryAdapter.setRedGainValue(value);
		Log.v(TAG, "setRGainValue : " + value);
	}
}

 

2.FactoryMenuAdapter中调用FacService的函数:

public class FactoryMenuAdapter {
	private static final String TAG = "FactoryAdapter";
	private Context mContext;
	private IFacService mService;
	private static FactoryMenuAdapter sInstance = null;
	private FactoryMenuAdapter(Context context) {
		mService = IFacService.Stub.asInterface(ServiceManager
				.getService("my_factory"));
		mContext = context;
	}

	public static FactoryMenuAdapter getInstance(Context context) {
		if (sInstance == null) {
			synchronized (FactoryMenuAdapter.class) {
				if (sInstance == null) {
					sInstance = new FactoryMenuAdapter(context);
				}
			}
		}
		return sInstance;
	}
	/**
	 * set red gain value of system
	 * @param redGainValue red gain value of system
	 * @return void
	 */
	public void setRedGainValue(int redGainValue) {
		try {
			mService.setRedGainValue(redGainValue);
		} catch (RemoteException e) {
			e.printStackTrace();
		}
	}
}


 

(这里对IFacService的使用要进行说明)

3.FacService中调用FactoryMenuManager的函数:

public class FacService extends IFacService.Stub {
    private static final String TAG = "FacService";
	private FactoryMenuManager mFactoryMenuManager;
    static final boolean DEBUG = true;
    public FacService(Context context) {
        mFactoryMenuManager = FactoryMenu.getFactoryMenuManager();
    }
	@Override
	public void setRedGainValue(int redGainValue) throws RemoteException {
		// TODO Auto-generated method stub
		if (mFactoryMenuManager != null) {
			mFactoryMenuManager.setRedGainValue(redGainValue);
		}
	}
}


 

(这里用工厂模式,从FactoryMenu获取实例也要进行说明)

4.FactoryMenu中提供getFactoryMenuManager()函数供获取FactoryMenuManager实例

 

public final class FactoryMenu {
    private static final String POLICY_IMPL_CLASS_NAME =
        "com.my.tvapi.factory.impl.Policy";

    private static final IPolicy sPolicy;

    static {
        // Pull in the actual implementation of the policy at run-time
        try {
            Class policyClass = Class.forName(POLICY_IMPL_CLASS_NAME);
            sPolicy = (IPolicy)policyClass.newInstance();
        } catch (ClassNotFoundException ex) {
            throw new RuntimeException(
                    POLICY_IMPL_CLASS_NAME + " could not be loaded", ex);
        } catch (InstantiationException ex) {
            throw new RuntimeException(
                    POLICY_IMPL_CLASS_NAME + " could not be instantiated", ex);
        } catch (IllegalAccessException ex) {
            throw new RuntimeException(
                    POLICY_IMPL_CLASS_NAME + " could not be instantiated", ex);
        }
    }

    // Cannot instantiate this class
    private FactoryMenu() {}

    public static FactoryMenuManager getFactoryMenuManager() {
        return sPolicy.getFactoryMenuManager();
    }
}

 

5.IPolicy是一个接口

public interface IPolicy {
    FactoryMenuManager getFactoryMenuManager();
}

 

6.FactoryMenuManager也是一个接口

public interface FactoryMenuManager  {
		/**
		 * set red gain value of system
		 * @param redGainValue red gain value of system 	 
		 * @return void
		 */
		public void setRedGainValue(int redGainValue);
}

 

7.FactoryMenuManagerImpl是一个继承并实现了FactoryMenuManager接口的类

 

public class FactoryMenuManagerImpl implements FactoryMenuManager {

private static TvFactoryManager factormanager;

...

public void setRedGainValue(int redGainValue){

factormanager.setAdcRedGain(redGainValue);

}

...

}

8.TvFactoryManager的实现是执行ITvFactory的函数调用

public class TvFactoryManager {

 private static ITvFactory mService = null;

...

 private static ITvFactory getService() {

        if (mService != null) {

            return mService;

        }

        mService = TvManager.getInstance().getTvFactory();

        return mService;

}

...

 public boolean setAdcRedGain(int redGain) {

       ITvFactory service = getService();

        try {

            service.setAdcRedGain(redGain);

        } catch (RemoteException e) {

            e.printStackTrace();

        }

        return false;

}

...

}


 

9.TvManager通过ServiceManager获取不同的工厂,比如这里是TvFactory,还可以是TvPicture等等。

public class TvManager {

static TvManager mInstance = null;

   ITvService mService = null;

public static TvManager getInstance() {

        

        if (mInstance == null) {

            synchronized (TvManager.class) {

                if (mInstance == null) {

                    IBinder b = ServiceManager.getService(Context.TV_SERVICE);

                    mInstance = new TvManager(ITvService.Stub.asInterface(b));

                }

            }

        }

        return mInstance;

}

...

    public ITvFactory getTvFactory() {

        try {

            return mService.getTvFactory();

        } catch (RemoteException e) {

            e.printStackTrace();

            return null;

        }

}

...

}


 

10.ServiceManager是在内核之中,通过一个HashMap来查找绑定的服务是否存在,如果不存在就通过静态成员函数getIServiceManager来获取ServiceManager的java远程接口。(可以getService和addService,我们添加系统服务就在这添加)

public final class ServiceManager {

private static IServiceManager sServiceManager;

private static HashMap sCache = new HashMap();

....

 public static IBinder getService(String name) {

        try {

            IBinder service = sCache.get(name);

            if (service != null) {

                return service;

            } else {

                return getIServiceManager().getService(name);

            }

        } catch (RemoteException e) {

            Log.e(TAG, "error in getService", e);

        }

        return null;

}

...

}


 

11.综上

 在8当中调用到了service.setAdcRedGain(redGain);

等价于:

ServiceManager.getService(Context.TV_SERVICE).getTvFactory().setAdcRedGain(redGain);


 

12.现在看ITvFactory接口,因为ServiceManager.getService(Context.TV_SERVICE).getTvFactory()

就是ITvFactory.getTvFactory();

ITvService中通过getTvFactory()返回一个ITvFactory接口

public interface ITvService extends android.os.IInterface

{

...

@Override

public com.mstar.android.tv.ITvFactory getTvFactory()

throws android.os.RemoteException {

android.os.Parcel _data = android.os.Parcel.obtain();

android.os.Parcel _reply = android.os.Parcel.obtain();

com.mstar.android.tv.ITvFactory _result;

try {

_data.writeInterfaceToken(DESCRIPTOR);

mRemote.transact(Stub.TRANSACTION_getTvFactory, _data,

_reply, 0);

_reply.readException();

_result = com.mstar.android.tv.ITvFactory.Stub

.asInterface(_reply.readStrongBinder());

} finally {

_reply.recycle();

_data.recycle();

}

return _result;

}

...

 

}


 

13.ITvFactory这个接口中有setAdcRedGain()的实现

public interface ITvFactory extends android.os.IInterface {

...

 

@Override

public boolean setAdcRedGain(int redGain)

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);

_data.writeInt(redGain);

mRemote.transact(Stub.TRANSACTION_setAdcRedGain, _data,

_reply, 0);

_reply.readException();

_result = (0 != _reply.readInt());

} finally {

_reply.recycle();

_data.recycle();

}

return _result;

}

...

}


14.到此程序的调用流程就结束了,那么工厂服务又是在什么时候添加的呢?又是什么时候开启的呢?又是怎么查找的呢?

第二部分

系统服务的添加地点、开启时机、和获取

 

15.自定义系统服务的添加地点

前面提到ServiceManager的时候,说过可以通过addService函数来添加系统服务。

在SystemService中开启了一个ServerThread线程,在ServiceThread线程中添加的服务

public class SystemServer {

private static final String TAG = "SystemServer";

 

public static final int FACTORY_TEST_OFF = 0;

public static final int FACTORY_TEST_LOW_LEVEL = 1;

public static final int FACTORY_TEST_HIGH_LEVEL = 2;

 

static Timer timer;

static final long SNAPSHOT_INTERVAL = 60 * 60 * 1000; // 1hr

 

// The earliest supported time. We pick one day into 1970, to

// give any timezone code room without going into negative time.

private static final long EARLIEST_SUPPORTED_TIME = 86400 * 1000;

 

 

native public static void init1(String[] args);

 

public static void main(String[] args) {

if (System.currentTimeMillis() < EARLIEST_SUPPORTED_TIME) {

// If a device's clock is before 1970 (before 0), a lot of

// APIs crash dealing with negative numbers, notably

// java.io.File#setLastModified, so instead we fake it and

// hope that time from cell towers or NTP fixes it

// shortly.

Slog.w(TAG, "System clock is before 1970; setting to 1970.");

SystemClock.setCurrentTimeMillis(EARLIEST_SUPPORTED_TIME);

}

 

if (SamplingProfilerIntegration.isEnabled()) {

SamplingProfilerIntegration.start();

timer = new Timer();

timer.schedule(new TimerTask() {

@Override

public void run() {

SamplingProfilerIntegration.writeSnapshot("system_server",

null);

}

}, SNAPSHOT_INTERVAL, SNAPSHOT_INTERVAL);

}

 

// Mmmmmm... more memory!

dalvik.system.VMRuntime.getRuntime().clearGrowthLimit();

 

// The system server has to run all of the time, so it needs to be

// as efficient as possible with its memory usage.

VMRuntime.getRuntime().setTargetHeapUtilization(0.8f);

 

Environment.setUserRequired(true);

 

System.loadLibrary("android_servers");

init1(args);

}

 

public static final void init2() {

Slog.i(TAG, "Entered the Android system server!");

Thread thr = new ServerThread();

thr.setName("android.server.ServerThread");

thr.start();

}

}

 

线程如下:

class ServerThread extends Thread {

...

Public void run(){

...

        if (factoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {

            // MStar Android Patch Begin

            if (!"1".equals(SystemProperties.get("mstar.disable.tvservice"))) {

                try {

                    Slog.i(TAG, "TV Service");

                    tv = new TvService(context);

                    ServiceManager.addService(Context.TV_SERVICE, tv);

                } catch (Throwable e) {

                    reportWtf("starting TV Service", e);

                }

 try {

                Slog.i(TAG, "xxTvService");

                xxTvService = new xxTvService(context);

                ServiceManager.addService("xx_tv", xxTvService);

            } catch (Throwable e) {

                Log.e(TAG, "failuer to start xxTvService");

            }

            }


...

}

...

}


 

16.系统服务的开启时机

AndroidRuntime.cpp中有这么一段话

   if (argv[1].equals("start-system-server")) {

                startSystemServer();

            } else if (!argv[1].equals("")) {

                throw new RuntimeException(argv[0] + USAGE_STRING);

            }


startSystemServer()在Zygote上fork了一个进程com.android.server.SystemServer.()

17,系统服务的获取

ServiceManager.getService(Context.TV_SERVICE).getTvFactory();

 

总结:

如何在Android系统中添加一个系统服务,并通过Binder机制实现APK对其进行的跨进程远程调用

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Android Binder 机制Android 系统中的一种进程间通信(IPC)机制,用于在不同的进程之间传递数据和调用方法。它是 Android 系统中最重要的 IPC 机制之一,也是 Android 应用程序与系统服务进行通信的基础。 Binder 机制的工作原理是基于一个抽象的客户端-服务器模型。在 Binder 机制中,有三种角色:客户端、服务器和服务管理器。客户端和服务器在不同的进程中运行,而服务管理器运行在系统服务进程中。 当客户端需要与服务器通信时,它首先通过服务管理器获取服务器的引用。服务管理器通过一个名为 Binder 驱动的内核模块来实现进程间通信。客户端可以通过进程访问服务器对象来调用服务器上的方法,并将参数传递给服务器。服务器可以将结果返回给客户端。 Binder 机制的一个重要特性是它支持进程的对象引用。这意味着客户端可以获取服务器上的对象引用,并将其传递给其他进程中的客户端。通过这种方式,多个客户端可以共享服务器上的相同对象,并相互协作。 在 Android 应用程序中,开发者可以通过 AIDL(Android 接口定义语言)来定义客户端和服务器之间的接口。AIDL 可以生成一个 Java 接口和一个 C++ 接口,用于在客户端和服务器之间进行通信。 总之,Android Binder 机制Android 系统中用于进程间通信的核心技术之一。它提供了一种高效、灵活和安全的方式来在不同的进程之间传递数据和调用方法。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值