android源码中添加GPIO服务供上层调用
指定make时需要编译进system中的服务
以rk源码为例,在deveice/rockchip/common/device.mk中添加服务
PRODUCT_PACKAGES += \
libmoyu-jni \ #服务中用到的jni
moyu-service
PRODUCT_SYSTEM_SERVER_JARS += \
moyu-service \ #将服务编译进jar包
添加源码编译
framework/base/Android.mk
LOCAL_SRC_FILES += \
.
.
.
core/java/com/moyu/api/IMoyuManager.aidl \
core/java/com/moyu/api/MoyuManager.java
添加api更新类与字段(此步骤可以通过make update-api命令更新)
framework/base/api/current.txt与framework/base/api/system-current.txt
在Context类中添加字段
field public static final java.lang.String MOYU_SERVICE = "moyu";
添加一个新类
package com.moyu.api {
public abstract interface IMoyuManager implements android.os.IInterface {
method public abstract int GetGpioValue(int) throws android.os.RemoteException;
method public abstract int InitGpio(int, int) throws android.os.RemoteException;
method public abstract int SetGpioValue(int, int) throws android.os.RemoteException;
method public abstract int UninitGpio(int) throws android.os.RemoteException;
}
public static abstract class IMoyuManager.Stub extends android.os.Binder implements com.moyu.api.IMoyuManager {
ctor public IMoyuManager.Stub();
method public android.os.IBinder asBinder();
method public static com.moyu.api.IMoyuManager asInterface(android.os.IBinder);
method public boolean onTransact(int, android.os.Parcel, android.os.Parcel, int) throws android.os.RemoteException;
}
}
注册服务
framework/base/core/java/android/app/ContextImp.java
import com.moyu.api.MoyuManager;
import com.moyu.api.IMoyuManager;
...
registerService(MOYU_SERVICE, new ServiceFetcher() {
public Object createService(ContextImpl ctx) {
IBinder b = ServiceManager.getService(MOYU_SERVICE);
IMoyuManager service = IMoyuManager.Stub.asInterface(b);
return new MoyuManager(service, ctx.mMainThread.getHandler());
}});
Context中添加字段
frameworks/base/core/java/android/content/Context.java
public static final String MOYU_SERVICE = "moyu";
添加源码文件
frameworks/base/core/java/com下新建目录moyu/api
package com.moyu.api;
import android.os.Handler;
import android.os.RemoteException;
import android.util.Log;
public class MoyuManager {
private final IMoyuManager mService;
private Handler mHandler;
private static final String TAG = "MoyuManager";
public MoyuManager(IMoyuManager service, Handler handler)
{
mHandler = handler;
mService = service;
}
public int InitGpio(int gpio, int dir)
{
try{
return mService.InitGpio(gpio,dir);
}catch (RemoteException e){
Log.e(TAG, "InitGpio failed");
return -1;
}
}
public int UninitGpio(int fd)
{
try{
return mService.UninitGpio(fd);
}catch (RemoteException e){
Log.e(TAG, "UninitGpio failed");
return -1;
}
}
public int SetGpioValue(int fd, int value)
{
try{
return mService.SetGpioValue(fd, value);
}catch (RemoteException e){
Log.e(TAG, "SetGpioValue failed");
return -1;
}
}
public int GetGpioValue(int fd)
{
try{
return mService.GetGpioValue(fd);
}catch (RemoteException e){
Log.e(TAG, "GetGpioValue failed");
return -1;
}
}
}
package com.moyu.api;
interface IMoyuManager
{
int InitGpio(int gpio, int dir);
int UninitGpio(int fd);
int SetGpioValue(int fd, int value);
int GetGpioValue(int fd);
}
启动服务
/frameworks/base/services/java/com/android/server/SystemServer.java
startOtherServices()中添加启动代码
try {
Slog.i(TAG, "MoyuService");
mSystemServiceManager.startService("com.moyu.server.MoyuService");
}catch (Throwable e) {
reportWtf("start MoyuService error ", e);
}
编写Service源代码
/framework/opt/下新建vendor/moyu目录,在vendor/moyu下新建Android.mk、jni、java目录以及文件
Android.mk
# Copyright (C) 2014 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
LOCAL_PATH := $(call my-dir)
# Build the java code
# ============================================================
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 := moyu-service
include $(BUILD_JAVA_LIBRARY)
#========================================================
include $(CLEAR_VARS)
LOCAL_CFLAGS += -Wno-unused-parameter -Wno-int-to-pointer-cast
LOCAL_CFLAGS += -Wno-maybe-uninitialized -Wno-parentheses
LOCAL_CPPFLAGS += -Wno-conversion-null
LOCAL_SRC_FILES := \
jni/com_moyu_server_MoyuNative.cpp
LOCAL_SHARED_LIBRARIES := \
libandroid_runtime\
libz \
libcutils \
libutils \
libbinder \
libnetutils \
LOCAL_MODULE := libmoyu-jni
include $(BUILD_SHARED_LIBRARY)
com_moyu_server_MoyuNative.cpp
#define LOG_TAG "com_moyu_server_MoyuNative"
#include "jni.h"
#include <utils/misc.h>
#include <android_runtime/AndroidRuntime.h>
#include <utils/Log.h>
#include <cutils/properties.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <poll.h>
#define LOGD ALOGD
#define LOGE ALOGE
#define LOGV ALOGV
#define GPIOSET_PATH "/dev/ugpio"
//gpio ctr
#define IOCTRL_GPIO_INIT 0x4c434b06
#define IOCTRL_SET_GPIO_VALUE 0x4c434b07
#define IOCTRL_GET_GPIO_VALUE 0x4c434b08
typedef struct
{
unsigned short gpio_num;
unsigned char gpio_cfg;//0 input 1 output (0~7)
unsigned char gpio_pull;//PULL_DISABLE,PULL_UP,PULL_DOWN
unsigned char gpio_driver;//0~3
}GPIO_CFG;
namespace android {
//gpio
static jint InitGpio(JNIEnv* env, jobject clazz, jint gpio, jint dir)
{
int result;
GPIO_CFG gpio_cfg;
int gpio_fd = open(GPIOSET_PATH, O_RDWR);
if (gpio_fd < 0)
{
LOGE("open /dev/ugpio failed");
return -1;
}
memset(&gpio_cfg,0,sizeof(GPIO_CFG));
gpio_cfg.gpio_num= gpio;
gpio_cfg.gpio_cfg = dir;
if(ioctl(gpio_fd , IOCTRL_GPIO_INIT, &gpio_cfg))
{
LOGE("IOCTRL_GPIO_INIT fail");
return -1;
}
return gpio_fd;
}
static int UninitGpio(JNIEnv* env, jobject clazz,jint fd)
{
close(fd);
return 0;
}
static jint SetGpioValue(JNIEnv* env, jobject clazz,jint fd ,jint value)
{
char data=value;
if(ioctl(fd, IOCTRL_SET_GPIO_VALUE, &data))
{
LOGE("IOCTRL_SET_GPIO_VALUE fail");
return -1;
}
else
return 0;
}
static jint GetGpioValue(JNIEnv* env, jobject clazz,jint fd)
{
unsigned char data;
if(ioctl(fd,IOCTRL_GET_GPIO_VALUE,&data))
{
LOGE("IOCTRL_SET_GPIO_VALUE fail");
return -1;
}
return data;
}
//gpio end
/*
* JNI registration.
*/
static JNINativeMethod gMoyuMethods[] = {
{"InitGpio", "(II)I", (void *)InitGpio },
{"UninitGpio", "(I)I", (void *)UninitGpio },
{"SetGpioValue", "(II)I", (void *)SetGpioValue },
{"GetGpioValue", "(I)I", (void *)GetGpioValue },
};
#if 0
int register_com_moyu_server_MoyuNative(JNIEnv* env)
{
return AndroidRuntime::registerNativeMethods(env, "com/moyu/server/MoyuNative", gMoyuMethods, NELEM(gMoyuMethods) );
}
#endif
/* User to register native functions */
extern "C"
jint Java_com_moyu_server_MoyuNative_registerNatives(JNIEnv* env, jclass clazz) {
return AndroidRuntime::registerNativeMethods(env, "com/moyu/server/MoyuNative", gMoyuMethods, NELEM(gMoyuMethods) );
}
}
com.moyu.server.MoyuNative.java
package com.moyu.server;
class MoyuNative {
static {
System.loadLibrary("moyu-jni");
registerNatives();
}
MoyuNative() {
}
public native static int registerNatives();
public native static int InitGpio(int gpio, int dir);
public native static int UninitGpio(int fd);
public native static int SetGpioValue(int fd, int value);
public native static int GetGpioValue(int fd);
}
com.moyu.server.MoyuService.java
package com.moyu.server;
import android.content.Context;
import android.util.Log;
import com.android.server.SystemService;
public final class MoyuService extends SystemService {
private static final String TAG = "MoyuService";
final MoyuServiceImpl mImpl;
public MoyuService(Context context) {
super(context);
mImpl = new MoyuServiceImpl(context);
}
@Override
public void onStart() {
Log.i(TAG, "Registering service " + Context.MOYU_SERVICE);
publishBinderService(Context.MOYU_SERVICE, mImpl);
}
@Override
public void onBootPhase(int phase) {
if (phase == SystemService.PHASE_SYSTEM_SERVICES_READY) {
mImpl.start();
}
}
}
com.moyu.server.MoyuServiceImpl.java
package com.moyu.server;
import android.util.Log;
import android.content.Context;
import com.moyu.api.IMoyuManager;
public class MoyuServiceImpl extends IMoyuManager.Stub {
private static final String TAG = "MoyuServiceImpl";
public Context mContext;
private final MoyuNative mNative;
public MoyuServiceImpl(Context context) {
Log.i(TAG, "Creating MoyuImpl");
mContext=context;
mNative=new MoyuNative();
}
public void start()
{
Log.i(TAG, "Starting Moyu service");
}
public int InitGpio(int gpio, int dir)
{
return mNative.InitGpio(gpio,dir);
}
public int UninitGpio(int fd)
{
return mNative.UninitGpio(fd);
}
public int SetGpioValue(int fd, int value)
{
return mNative.SetGpioValue(fd,value);
}
public int GetGpioValue(int fd)
{
return mNative.GetGpioValue(fd);
}
}
至此从新编译烧录,可将framework.jar提取到项目中使用