当前位置:   article > 正文

Android Framework添加自定义服务和接口_framework加接口

framework加接口

1、概述

本博文配套的硬件是瑞芯微RK3288芯片,跑的是Android5.1的SDK。作为设备开发商,经常有release接口给第三方调用的需求,本文基于实际案例撰写,不同版本的Android Framework架构可能略有不同,但是大同小异,均可作为参考。

2、扩展Framework接口

第三方APP如果要操作硬件,比如通过ioctl操作某个GPIO,大体上来说,应该有以下两种方法:

1、我们封装操作硬件的API,形成一个so库给到第三方,并写好JNI接口打通到Java层,第三方直接调用Java层接口就好。这种方法理论上可行,但是实际操作中一般会有API调用权限问题。操作硬件接口,一般都需要调用者进程需要system权限甚至是root权限,通过release JNI接口的方式给第三方调用,所有的代码都是跑在第三方APP的进程,一般而言,我们是不会随便给第三方APP系统权限,这样既会有安全问题,也会引入第三方APP升级麻烦等问题,不推荐使用。

2、扩展Framework接口:第三方APP调用标准接口,然后通过aidl的方式,跨进程调用到system_server进程中对应的远程接口,由于system_server是系统进程,所以不存在权限问题。本文就是使用该种方式。

2.1、定义Java接口

frameworks/base/core/java目录下,根据包名创建一个子目录,比如我创建的是com/wrtsz/api/,在该目录下,新建一个java文件,比如WrtdevManager.java ,对应的代码如下:

package com.wrtsz.api;
 
import android.os.Handler;
import android.os.RemoteException;
import android.util.Log;
 
public class WrtdevManager {
	
	private final IWrtdevManager mService;
 
    private Handler mHandler;
    private static final String TAG = "WrtdevManager";
	
    public WrtdevManager(IWrtdevManager service, Handler handler) 
	{
        mHandler = handler;
        mService = service;
    }   
 
	public int getMicroWaveState()
	{
		try{
	        return mService.getMicroWaveState();
	    }catch (RemoteException e){
	        Log.e(TAG, "getMicroWaveState failed");
	        return -1;
	    }
	}
	
	public byte[] getIcCardNo()
	{
		try{
	        return mService.getIcCardNo();
	    }catch (RemoteException e){
	        Log.e(TAG, "getIcCardNo failed");
	        return null;
	    }
	}
 
	public int openLed(int opIndex)
	{
		try{
	        return mService.openLed(opIndex);
	    }catch (RemoteException e){
	        Log.e(TAG, "openWhiteLed failed");
	        return -1;
	    }
	}
 
	public int openDoor()
	{
		try{
	        return mService.openDoor();
	    }catch (RemoteException e){
	        Log.e(TAG, "openDoor failed");
	        return -1;
	    }
	}
 
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60

以上代码,注意两点:

1、每个接口中,都必须catch RemoteException异常,这个不加上应该编译不过,主要是防止对应的远程接口没有定义,导致APP调用出错;

2、构造函数有两个参数,一个是Handler,一个是IWrtdevManager (继承于android.os.IInterface)

2.2、定义aidl接口

WrtdevManager.java文件中有用到IWrtdevManager,这是通过编译aidl文件生成,定义的.aidl文件如下:

package com.wrtsz.api;
 
interface IWrtdevManager
{
    int getMicroWaveState();
	byte[] getIcCardNo();
	int openLed(int opIndex);
	int openDoor();	
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

需要注意的是:.aidl中的接口必须跟.java中的接口保持一致,否则会编译不过。另外就是aidl语言的语法跟Java语言略有不同,且传递的参数必须是Java基本类型或者是其他实现Parcelable 接口的类,这里不再详述,可以参考官方文档:https://developer.android.com/guide/components/aidl?hl=zh-cn

2.3、编译接口

上面虽然定义了两个文件,但是默认情况下,编译Android的时候是不会编译到这两个文件的,如果要用编译到对应的文件,需要修改frameworks/base/Android.mk文件,在对应的LOCAL_SRC_FILES宏中添加对应的文件即可,相应的patch文件如下:

 	packages/services/Proxy/com/android/net/IProxyCallback.aidl \
 	packages/services/Proxy/com/android/net/IProxyPortListener.aidl \
 	core/java/android/os/IDisplayDeviceManagementService.aidl \
+ 	core/java/com/wrtsz/api/IWrtdevManager.aidl \
+ 	core/java/com/wrtsz/api/WrtdevManager.java
 	
 
 # FRAMEWORKS_BASE_JAVA_SRC_DIRS comes from build/core/pathmap.mk
 LOCAL_AIDL_INCLUDES += $(FRAMEWORKS_BASE_JAVA_SRC_DIRS)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

清空之后在Android根目录编译,发现会报错:

see build/core/apicheck_msg_current.txt
******************************
You have tried to change the API from what has been previously approved.
To make these errors go away, you have two choices:
   1) You can add "@hide" javadoc comments to the methods, etc. listed in the
      errors above.
   2) You can update current.txt by executing the following command:
         make update-api
      To submit the revised current.txt to the main Android repository,
      you will need approval.
******************************
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

熟悉Android SDK开发的就比较清楚原因,因为我们添加了系统接口,需要先make update-api,执行完该命令后,发现frameworks/base/api/current.txt文件有更新,可以看到,文件中增加了一个WRTSZ_SERVICE 的常量和一个com.wrtsz.api的package,该package中就有对应的接口声明。

     field public static final java.lang.String WIFI_P2P_SERVICE = "wifip2p";
     field public static final java.lang.String WIFI_SERVICE = "wifi";
     field public static final java.lang.String WINDOW_SERVICE = "window";
     field public static final java.lang.String WRTSZ_SERVICE = "wrtsz";
   }
 
   public class ContextWrapper extends android.content.Context {
@@ -39532,6 +39533,24 @@ package com.android.internal.util {
 
 }
 
 package com.wrtsz.api {
 
   public abstract interface IWrtdevManager implements android.os.IInterface {
     method public abstract byte[] getIcCardNo() throws android.os.RemoteException;
     method public abstract int getMicroWaveState() throws android.os.RemoteException;
     method public abstract int openDoor() throws android.os.RemoteException;
     method public abstract int openLed(int) throws android.os.RemoteException;
   }
 
   public static abstract class IWrtdevManager.Stub extends android.os.Binder implements com.wrtsz.api.IWrtdevManager {
     ctor public IWrtdevManager.Stub();
     method public android.os.IBinder asBinder();
     method public static com.wrtsz.api.IWrtdevManager asInterface(android.os.IBinder);
     method public boolean onTransact(int, android.os.Parcel, android.os.Parcel, int) throws android.os.RemoteException;
   }
 
 }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28

接着就可以敲make -j16命令直接编译了,编译完成之后,在./out/target/common/obj/JAVA_LIBRARIES/framework_intermediates/src/core/java/com/wrtsz/api目录下会生成一个IWrtdevManager.java文件,对应的内容如下:

/*
 * This file is auto-generated.  DO NOT MODIFY.
 * Original file: frameworks/base/core/java/com/wrtsz/api/IWrtdevManager.aidl
 */
package com.wrtsz.api;
public interface IWrtdevManager extends android.os.IInterface
{
/** Local-side IPC implementation stub class. */
public static abstract class Stub extends android.os.Binder implements com.wrtsz.api.IWrtdevManager
{
private static final java.lang.String DESCRIPTOR = "com.wrtsz.api.IWrtdevManager";
/** Construct the stub at attach it to the interface. */
public Stub()
{
this.attachInterface(this, DESCRIPTOR);
}
/**
 * Cast an IBinder object into an com.wrtsz.api.IWrtdevManager interface,
 * generating a proxy if needed.
 */
public static com.wrtsz.api.IWrtdevManager asInterface(android.os.IBinder obj)
{
if ((obj==null)) {
return null;
}
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
if (((iin!=null)&&(iin instanceof com.wrtsz.api.IWrtdevManager))) {
return ((com.wrtsz.api.IWrtdevManager)iin);
}
return new com.wrtsz.api.IWrtdevManager.Stub.Proxy(obj);
}
@Override public android.os.IBinder asBinder()
{
return this;
}
@Override public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException
{
switch (code)
{
case INTERFACE_TRANSACTION:
{
reply.writeString(DESCRIPTOR);
return true;
}
case TRANSACTION_getMicroWaveState:
{
data.enforceInterface(DESCRIPTOR);
int _result = this.getMicroWaveState();
reply.writeNoException();
reply.writeInt(_result);
return true;
}
case TRANSACTION_getIcCardNo:
{
data.enforceInterface(DESCRIPTOR);
byte[] _result = this.getIcCardNo();
reply.writeNoException();
reply.writeByteArray(_result);
return true;
}
case TRANSACTION_openLed:
{
data.enforceInterface(DESCRIPTOR);
int _arg0;
_arg0 = data.readInt();
int _result = this.openLed(_arg0);
reply.writeNoException();
reply.writeInt(_result);
return true;
}
case TRANSACTION_openDoor:
{
data.enforceInterface(DESCRIPTOR);
int _result = this.openDoor();
reply.writeNoException();
reply.writeInt(_result);
return true;
}
case TRANSACTION_getFireAlarmStatus:
{
data.enforceInterface(DESCRIPTOR);
int _result = this.getFireAlarmStatus();
reply.writeNoException();
reply.writeInt(_result);
return true;
}
case TRANSACTION_getMagnetometerStatus:
{
data.enforceInterface(DESCRIPTOR);
int _result = this.getMagnetometerStatus();
reply.writeNoException();
reply.writeInt(_result);
return true;
}
case TRANSACTION_getTamperStatus:
{
data.enforceInterface(DESCRIPTOR);
int _result = this.getTamperStatus();
reply.writeNoException();
reply.writeInt(_result);
return true;
}
}
return super.onTransact(code, data, reply, flags);
}
private static class Proxy implements com.wrtsz.api.IWrtdevManager
{
private android.os.IBinder mRemote;
Proxy(android.os.IBinder remote)
{
mRemote = remote;
}
@Override public android.os.IBinder asBinder()
{
return mRemote;
}
public java.lang.String getInterfaceDescriptor()
{
return DESCRIPTOR;
}
@Override public int getMicroWaveState() throws android.os.RemoteException
{
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
int _result;
try {
_data.writeInterfaceToken(DESCRIPTOR);
mRemote.transact(Stub.TRANSACTION_getMicroWaveState, _data, _reply, 0);
_reply.readException();
_result = _reply.readInt();
}
finally {
_reply.recycle();
_data.recycle();
}
return _result;
}
@Override public byte[] getIcCardNo() throws android.os.RemoteException
{
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
byte[] _result;
try {
_data.writeInterfaceToken(DESCRIPTOR);
mRemote.transact(Stub.TRANSACTION_getIcCardNo, _data, _reply, 0);
_reply.readException();
_result = _reply.createByteArray();
}
finally {
_reply.recycle();
_data.recycle();
}
return _result;
}
@Override public int openLed(int opIndex) throws android.os.RemoteException
{
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
int _result;
try {
_data.writeInterfaceToken(DESCRIPTOR);
_data.writeInt(opIndex);
mRemote.transact(Stub.TRANSACTION_openLed, _data, _reply, 0);
_reply.readException();
_result = _reply.readInt();
}
finally {
_reply.recycle();
_data.recycle();
}
return _result;
}
@Override public int openDoor() throws android.os.RemoteException
{
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
int _result;
try {
_data.writeInterfaceToken(DESCRIPTOR);
mRemote.transact(Stub.TRANSACTION_openDoor, _data, _reply, 0);
_reply.readException();
_result = _reply.readInt();
}
finally {
_reply.recycle();
_data.recycle();
}
return _result;
}
@Override public int getFireAlarmStatus() throws android.os.RemoteException
{
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
int _result;
try {
_data.writeInterfaceToken(DESCRIPTOR);
mRemote.transact(Stub.TRANSACTION_getFireAlarmStatus, _data, _reply, 0);
_reply.readException();
_result = _reply.readInt();
}
finally {
_reply.recycle();
_data.recycle();
}
return _result;
}
@Override public int getMagnetometerStatus() throws android.os.RemoteException
{
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
int _result;
try {
_data.writeInterfaceToken(DESCRIPTOR);
mRemote.transact(Stub.TRANSACTION_getMagnetometerStatus, _data, _reply, 0);
_reply.readException();
_result = _reply.readInt();
}
finally {
_reply.recycle();
_data.recycle();
}
return _result;
}
@Override public int getTamperStatus() throws android.os.RemoteException
{
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
int _result;
try {
_data.writeInterfaceToken(DESCRIPTOR);
mRemote.transact(Stub.TRANSACTION_getTamperStatus, _data, _reply, 0);
_reply.readException();
_result = _reply.readInt();
}
finally {
_reply.recycle();
_data.recycle();
}
return _result;
}
}
static final int TRANSACTION_getMicroWaveState = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
static final int TRANSACTION_getIcCardNo = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
static final int TRANSACTION_openLed = (android.os.IBinder.FIRST_CALL_TRANSACTION + 2);
static final int TRANSACTION_openDoor = (android.os.IBinder.FIRST_CALL_TRANSACTION + 3);
static final int TRANSACTION_getFireAlarmStatus = (android.os.IBinder.FIRST_CALL_TRANSACTION + 4);
static final int TRANSACTION_getMagnetometerStatus = (android.os.IBinder.FIRST_CALL_TRANSACTION + 5);
static final int TRANSACTION_getTamperStatus = (android.os.IBinder.FIRST_CALL_TRANSACTION + 6);
}
public int getMicroWaveState() throws android.os.RemoteException;
public byte[] getIcCardNo() throws android.os.RemoteException;
public int openLed(int opIndex) throws android.os.RemoteException;
public int openDoor() throws android.os.RemoteException;
public int getFireAlarmStatus() throws android.os.RemoteException;
public int getMagnetometerStatus() throws android.os.RemoteException;
public int getTamperStatus() throws android.os.RemoteException;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202
  • 203
  • 204
  • 205
  • 206
  • 207
  • 208
  • 209
  • 210
  • 211
  • 212
  • 213
  • 214
  • 215
  • 216
  • 217
  • 218
  • 219
  • 220
  • 221
  • 222
  • 223
  • 224
  • 225
  • 226
  • 227
  • 228
  • 229
  • 230
  • 231
  • 232
  • 233
  • 234
  • 235
  • 236
  • 237
  • 238
  • 239
  • 240
  • 241
  • 242
  • 243
  • 244
  • 245
  • 246
  • 247
  • 248
  • 249
  • 250
  • 251
  • 252
  • 253
  • 254
  • 255
  • 256
  • 257

文件的头两行注释就写清楚了:
1、这个文件是自动生成的,不要自行修改;
2、其对应的原始文件为frameworks/base/core/java/com/wrtsz/api/IWrtdevManager.aidl

  • This file is auto-generated. DO NOT MODIFY.
  • Original file: frameworks/base/core/java/com/wrtsz/api/IWrtdevManager.aidl
2.4、输出jar包

以上完成之后,我们最终要输出给第三方一个jar包,该文件最终生成在out/target/common/obj/JAVA_LIBRARIES/framework_intermediates目录下,我们可以ls -l看一下,目录下的classes.jar文件就是我们要找的文件。

在这里插入图片描述
当然,细心的童鞋可能会发现classes.jar、class-full-debug.jar、classes-jarjar.jar其实是三个同样的文件,校验md5值就可以证明。

在这里插入图片描述
然后把对应的 classes.jar文件release给第三方,替换原生的android.jar,就可以愉快地调用我们的WrtdevManager接口了。

3、添加自定义service

以上部分完成后,第三方APP调用接口的时候,会发现编译不会报错,但是运行时会报RemoteException的异常,因为我们还没有定义对应的service。

3.1、service定义

可以在frameworks/opt目录下创建一个vendor/wrtsz/java/com/wrtsz/server目录,在该目录下首先新建一个WrtdevService类,该类继承自SystemService类,对应的代码如下:

package com.wrtsz.server;
 
import android.content.Context;
import android.util.Log;
import com.android.server.SystemService;
 
public final class WrtdevService extends SystemService {
 
    private static final String TAG = "csh_debug_wrtsz";
    final WrtdevServiceImpl mImpl;
 
    public WrtdevService(Context context) {
        super(context);
        mImpl = new WrtdevServiceImpl(context);
    }
 
    @Override
    public void onStart() {
        Log.i(TAG, "Registering service " + Context.WRTSZ_SERVICE);
        publishBinderService(Context.WRTSZ_SERVICE, mImpl);
    }
 
    @Override
    public void onBootPhase(int phase) {
        if (phase == SystemService.PHASE_SYSTEM_SERVICES_READY) {
            mImpl.start();
        }
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29

可以看到,在WrtdevService中,我们调用了WrtdevServiceImpl 类,这个类才是真正干活儿的,说白了WrtdevService类不过是个马甲,方便SystemServer统一管理。Android5.1是这种架构,之前Android4.4中可以不需要定义WrtdevService,直接定义WrtdevServiceImpl类,其代码如下:

package com.wrtsz.server;
 
import android.util.Log;
import android.content.Context;
import com.wrtsz.api.IWrtdevManager;
 
public class WrtdevServiceImpl extends IWrtdevManager.Stub {
    private static final String TAG = "WrtdevServiceImpl";
    public Context mContext;
    private final WrtdevNative mNative;
 
    public WrtdevServiceImpl(Context context) {
         Log.i(TAG, "Creating WrtdevServiceImpl");
         mContext=context;
		 mNative=new WrtdevNative();
    }
 
    public void start() 
    {
        Log.i(TAG, "Starting Wrtdev  service");       
    }
 
	public int getMicroWaveState()
	{
		return mNative.getMicroWaveState();
	}
 
	public byte[] getIcCardNo()
	{
		
		return mNative.getIcCardNo();
	}
 
	public int openLed(int opIndex)
	{		
		return mNative.openLed(opIndex);
	}
 
	public int openDoor()
	{
		return mNative.openDoor();
 
	}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44

WrtdevServiceImpl类中实现了所有WrtdevManager中定义的接口,它通过一个native类,最终调用C层接口,由于跟业务有关,这里不再赘述。

然后就是在同目录下新建一个Android.mk,对应的内容如下:

package com.wrtsz.server;
 
import android.util.Log;
import android.content.Context;
import com.wrtsz.api.IWrtdevManager;
 
public class WrtdevServiceImpl extends IWrtdevManager.Stub {
    private static final String TAG = "WrtdevServiceImpl";
    public Context mContext;
    private final WrtdevNative mNative;
 
    public WrtdevServiceImpl(Context context) {
         Log.i(TAG, "Creating WrtdevServiceImpl");
         mContext=context;
		 mNative=new WrtdevNative();
    }
 
    public void start() 
    {
        Log.i(TAG, "Starting Wrtdev  service");       
    }
 
	public int getMicroWaveState()
	{
		return mNative.getMicroWaveState();
	}
 
	public byte[] getIcCardNo()
	{
		
		return mNative.getIcCardNo();
	}
 
	public int openLed(int opIndex)
	{		
		return mNative.openLed(opIndex);
	}
 
	public int openDoor()
	{
		return mNative.openDoor();
 
	}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44

WrtdevServiceImpl类中实现了所有WrtdevManager中定义的接口,它通过一个native类,最终调用C层接口,由于跟业务有关,这里不再赘述。

然后就是在同目录下新建一个Android.mk,对应的内容如下:

LOCAL_CFLAGS += -Wno-unused-parameter -Wno-int-to-pointer-cast
LOCAL_CFLAGS += -Wno-maybe-uninitialized -Wno-parentheses
LOCAL_CPPFLAGS += -Wno-conversion-null
 
include $(CLEAR_VARS)
 
LOCAL_AIDL_INCLUDES := $(LOCAL_PATH)/java
LOCAL_SRC_FILES := $(call all-java-files-under, java) \
	$(call all-Iaidl-files-under, java) \
	$(call all-logtags-files-under, java)
 
LOCAL_JAVA_LIBRARIES := services
LOCAL_MODULE := wrtsz-service
 
include $(BUILD_JAVA_LIBRARY)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

编译之后会在./out/target/product/rk3288/system/framework/目录下生成一个wrtsz-service.jar文件。

3.2、注册与启动service

系统service的注册统一在frameworks/base/core/java/android/app/ContextImpl.java 中,调用registerService方法。

import java.util.ArrayList;
 import java.util.HashMap;
 
 import com.wrtsz.api.WrtdevManager;
 import com.wrtsz.api.IWrtdevManager;
 
 class ReceiverRestrictedContext extends ContextWrapper {
     ReceiverRestrictedContext(Context base) {
         super(base);
@@ -648,6 +651,16 @@ class ContextImpl extends Context {
                  }});
 
 
         registerService(WRTSZ_SERVICE, new ServiceFetcher() {
                  public Object createService(ContextImpl ctx) {
                     IBinder b = ServiceManager.getService(WRTSZ_SERVICE);
                     IWrtdevManager service = IWrtdevManager.Stub.asInterface(b);
                     return new WrtdevManager(service, ctx.mMainThread.getHandler());
                  }});
 
 
         registerService(WINDOW_SERVICE, new ServiceFetcher() {
                 Display mDefaultDisplay;
                 public Object getService(ContextImpl ctx) {
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

这里的WRTSZ_SERVICE常量定义在 frameworks/base/core/java/android/content/Context.java 中,方便上层APP通过addService方法调用时,直接传这个常量。

注册完服务之后,需要启动服务,需要在 frameworks/base/services/java/com/android/server/SystemServer.java中添加,调用startService启动,直接传对应的类全名即可。

try {
    Slog.i("csh_debug_wrtsz", "WrtszService");
    mSystemServiceManager.startService("com.wrtsz.server.WrtdevService");
}catch (Throwable e) {
    reportWtf("start WrtszService error ", e);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

以上添加完之后,如果要正常编译运行,还需要在device/rockchip/common/device.mk中添加几行代码:

 PRODUCT_PACKAGES += \
     wrtsz-service
 
 PRODUCT_SYSTEM_SERVER_JARS += \
     wrtsz-service
  • 1
  • 2
  • 3
  • 4
  • 5

注意一定要在PRODUCT_SYSTEM_SERVER_JARS宏中添加自定义的service,否则系统跑起来之后,自定义的service代码其实没有执行

4、总结

以上就是自定义Android服务和接口的全部内容,不同的芯片商和不同的Android版本,可能略有不同,但是整体架构差不多。

文章转载:
Android Framework添加自定义服务和接口

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/盐析白兔/article/detail/272949
推荐阅读
相关标签
  

闽ICP备14008679号