一、概述
本文将讲述如何在Framework层增加系统服务,提供给其他进程访问。在讲述之前,读者应该了解所有的系统服务运行在SystemServer进程中,并将对应的IBinder对象注册在ServiceManger进程中。
二、编码思路
1、在framework/base/core/android/os/下定义AppLockServiceTest.aidl接口
2、在framework/base/service定义AppLockServiceTest.java
3、修改framework/base/Android.mk文件
4、在SystemService中启动服务,并注册在ServiceManager中。
1、AppLockServiceTest.aidl类
// IAppLockService.aidl
package android.os;
import android.os.IAppLockCallback;
// Declare any non-default types here with import statements
interface IAppLockServiceTest {
/**
* Demonstrates some basic types that you can use as parameters
* and return values in AIDL.
*/
//给应用上锁或解锁
void setLocked(String pkg,boolean isLocked);
//判断应用是否上锁
boolean isLocked(String pkg);
}
2、创建AppLockServiceTest服务
package com.android.server;
import android.app.Activity;
import android.app.ActivityManager;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.os.IAppLockServiceTest;
import android.os.IBinder;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.util.Log;
import android.util.Slog;
import android.widget.Toast;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class AppLockServiceTest extends SystemService {
private Map map = new HashMap();
private Object object = new Object();
private Context mContext;
public AppLockServiceTest(Context context) {
super(context);
mContext = context;
}
private final IBinder mService = new IAppLockServiceTest.Stub() {
@Override
public boolean isLocked(String pkg) throws RemoteException {
synchronized (object) {
return isAppLocked(pkg);
}
}
@Override
public void setLocked(String pkg, boolean isLocked) throws RemoteException {
synchronized (object) {
setAppLocked(pkg, isLocked);
}
}
};
@Override
public void onStart() {
ServiceManager.addService(Context.APP_LOCK_SERVICE_TEST, mService);
}
/**
* 设置锁状态
*
* @param pkg
* @param isLocked
*/
private void setAppLocked(String pkg, boolean isLocked) {
//判断包名是否为空
checkNull(pkg);
Log.d("应用锁服务:", "修改的应用包名 : " + pkg + "是否被锁 " + isLocked);
if (map.get(pkg) != null) {
map.remove(pkg);
map.put(pkg, isLocked);
}
}
private boolean isAppLocked(String pkg) {
checkNull(pkg);
Log.d("应用锁服务:", "修改的应用包名 : " + pkg);
if (map.get(pkg)) {
return true;
} else {
return false;
}
}
private void checkNull(String pkg) {
if (pkg == null || "".equals(pkg)) {
throw new IllegalArgumentException("Illegal package name");
}
}
}
在此类中,我们需要实现aidl的服务端,并创建对应的Binder对象注册在ServiceManager中,其中ServiceManager.java也是一个binder类,这个类中处理了Service的Binder对象的缓存,并与ServiceManager进程通信。注意在Context中定义一个代表我们服务的字符串标志。
//start, add by zl topwise for app_lock
public static final String APP_LOCK_SERVICE_TEST = "app_lock_service_test";
//end, add by zl topwise for app_lock
3、修改Android.mk文件
core/java/android/os/IPowerManager.aidl \
core/java/android/os/IAppLockService.aidl \
core/java/android/os/IAppLockServiceTest.aidl \
core/java/android/os/IAppLockCallback.aidl \
core/java/android/os/IStudentModeManageService.aidl\
把定义好的aidl文件加入到里面
4、在SystemService进程中启动该服务
//start, add by zl topwise for app Protect
if (android.os.TopwiseConfig.SUPPORT_PRIVATE_PROTECT) {
try {
mSystemServiceManager.startService(AppLockService.class);
mSystemServiceManager.startService(AppLockServiceTest.class);
} catch (Throwable e) {
reportWtf("starting PrivateProtect Service", e);
}
}
//end, start, add by zl topwise for app Protect
到此我们服务端已经定义完了,可用模块编译下framework/base 和 framework/base/service/这俩个模块。
5、客户端获取服务
客户端获取服务只需要通过ServiceManger.getSerivce()方法获取到对应服务的IBinder对象转化成接口类型的对象就可以访问到服务端的所有方法了。
例:IAppLockServiceTest.Stub.asInterface(ServiceManager.getService(Context.APP_LOCK_SERVICE_TEST));
其中通过context.getSystemService("")的方法获取对应的ServiceManager对象也是在SystemServiceRegistry类中缓存了对应Binder对象的代理。