Android从硬件到APP:增加硬件服务
Android平台应用越来越广泛,在一些应用领域我们经常需要增加一些硬件控制等特殊功能,而标准Android框架仅支持手机、平板等常见外围器件,比如:相机、震动、电话、蓝牙、音频等。下面就以某个项目需要实现APP操作GPIO来讲述开发的整个过程。
驱动
- 在kernel/drivers/misc/目录下新建topband_gpio目录,并增加下面几个文件:
topband_gpio.c
#include <linux/module.h>
#include <linux/init.h>
#include <linux/device.h>
#include <linux/errno.h>
#include <linux/err.h>
#include <linux/kernel.h>
#include <linux/ctype.h>
#include <linux/delay.h>
#include <linux/idr.h>
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/interrupt.h>
#include <linux/signal.h>
#include <linux/pm.h>
#include <linux/notifier.h>
#include <linux/fb.h>
#include <linux/input.h>
#include <linux/ioport.h>
#include <linux/io.h>
#include <linux/clk.h>
#include <linux/pinctrl/consumer.h>
#include <linux/platform_device.h>
#include <linux/kthread.h>
#include <linux/time.h>
#include <linux/timer.h>
#include <linux/regulator/consumer.h>
#include <linux/gpio.h>
#include <linux/of.h>
#include <linux/of_irq.h>
#include <linux/of_gpio.h>
#include <linux/of_platform.h>
#include <linux/miscdevice.h>
#include <linux/uaccess.h>
#define TOPBAND_GPIO_NAME "topband,gpio"
// ioctl cmd
#define TOPBAND_GPIO_IOC_MAGIC 'f'
#define TOPBAND_GPIO_IOC_SET_VALUE _IOW(TOPBAND_GPIO_IOC_MAGIC, 1, int)
#define TOPBAND_GPIO_IOC_MAXNR 1
struct topband_gpio_data {
struct platform_device *platform_dev;
struct miscdevice topband_gpio_device;
int gpio1;
int gpio2;
int gpio3;
int gpio4;
};
static void topband_gpio_free_io_port(struct topband_gpio_data *topband_gpio)
{
if(gpio_is_valid(topband_gpio->gpio1)) {
gpio_free(topband_gpio->gpio1);
}
if(gpio_is_valid(topband_gpio->gpio2)) {
gpio_free(topband_gpio->gpio2);
}
if(gpio_is_valid(topband_gpio->gpio3)) {
gpio_free(topband_gpio->gpio3);
}
if(gpio_is_valid(topband_gpio->gpio4)) {
gpio_free(topband_gpio->gpio4);
}
return;
}
static int topband_gpio_parse_dt(struct device *dev,
struct topband_gpio_data *topband_gpio)
{
struct device_node *np = dev->of_node;
topband_gpio->gpio1 = of_get_named_gpio(np, "gpio-1", 0);
if(!gpio_is_valid(topband_gpio->gpio1)) {
dev_err(dev, "No valid gpio1");
}
topband_gpio->gpio2 = of_get_named_gpio(np, "gpio-2", 0);
if(!gpio_is_valid(topband_gpio->gpio2)) {
dev_err(dev, "No valid gpio2");
}
topband_gpio->gpio3 = of_get_named_gpio(np, "gpio-3", 0);
if(!gpio_is_valid(topband_gpio->gpio3)) {
dev_err(dev, "No valid gpio3");
}
topband_gpio->gpio4 = of_get_named_gpio(np, "gpio-4", 0);
if(!gpio_is_valid(topband_gpio->gpio4)) {
dev_err(dev, "No valid gpio4");
}
return 0;
}
static int topband_gpio_request_io_port(struct topband_gpio_data *topband_gpio)
{
int ret = 0;
if(gpio_is_valid(topband_gpio->gpio1)) {
ret = gpio_request(topband_gpio->gpio1, "topband_gpio_1");
if(ret < 0) {
dev_err(&topband_gpio->platform_dev->dev,
"Failed to request GPIO1:%d, ERRNO:%d\n",
(s32)topband_gpio->gpio1, ret);
return -ENODEV;
}
gpio_direction_output(topband_gpio->gpio1, 0);
dev_info(&topband_gpio->platform_dev->dev, "Success request gpio1\n");
}
if(gpio_is_valid(topband_gpio->gpio2)) {
ret = gpio_request(topband_gpio->gpio2, "topband_gpio_2");
if(ret < 0) {
dev_err(&topband_gpio->platform_dev->dev,
"Failed to request GPIO2:%d, ERRNO:%d\n",
(s32)topband_gpio->gpio2, ret);
return -ENODEV;
}
gpio_direction_output(topband_gpio->gpio2, 0);
dev_info(&topband_gpio->platform_dev->dev, "Success request gpio2\n");
}
if(gpio_is_valid(topband_gpio->gpio3)) {
ret = gpio_request(topband_gpio->gpio3, "topband_gpio_3");
if(ret < 0) {
dev_err(&topband_gpio->platform_dev->dev,
"Failed to request GPIO3:%d, ERRNO:%d\n",
(s32)topband_gpio->gpio3, ret);
return -ENODEV;
}
gpio_direction_output(topband_gpio->gpio3, 0);
dev_info(&topband_gpio->platform_dev->dev, "Success request gpio3\n");
}
if(gpio_is_valid(topband_gpio->gpio4)) {
ret = gpio_request(topband_gpio->gpio4, "topband_gpio_4");
if(ret < 0) {
dev_err(&topband_gpio->platform_dev->dev,
"Failed to request GPIO4:%d, ERRNO:%d\n",
(s32)topband_gpio->gpio4, ret);
return -ENODEV;
}
gpio_direction_output(topband_gpio->gpio4, 0);
dev_info(&topband_gpio->platform_dev->dev, "Success request gpio4\n");
}
return ret;
}
static int topband_gpio_set_value(int gpio, int value) {
if(gpio_is_valid(gpio)) {
gpio_set_value(gpio, value);
return 0;
}
return -1;
}
static int topband_gpio_ctrl(struct topband_gpio_data *topband_gpio, int data) {
int ret = 0;
int gpio, value;
gpio = (data >> 4) & 0x0f;
value = data & 0x0f;
dev_info(&topband_gpio->platform_dev->dev,
"%s, gpio=%d, value=%d\n", __func__, gpio, value);
switch (gpio) {
case 1:
ret = topband_gpio_set_value(topband_gpio->gpio1, value);
break;
case 2:
ret = topband_gpio_set_value(topband_gpio->gpio2, value);
break;
case 3:
ret = topband_gpio_set_value(topband_gpio->gpio3, value);
break;
case 4:
ret = topband_gpio_set_value(topband_gpio->gpio4, value);
break;
default:
ret = -1;
break;
}
return ret;
}
static int topband_gpio_dev_open(struct inode *inode, struct file *filp)
{
int ret = 0;
struct topband_gpio_data *topband_gpio = container_of(filp->private_data,
struct topband_gpio_data,
topband_gpio_device);
filp->private_data = topband_gpio;
dev_info(&topband_gpio->platform_dev->dev,
"device node major=%d, minor=%d\n", imajor(inode), iminor(inode));
return ret;
}
static long topband_gpio_dev_ioctl(struct file *pfile,
unsigned int cmd, unsigned long arg)
{
int ret = 0;
int data = 0;
struct topband_gpio_data *topband_gpio = pfile->private_data;
if (_IOC_TYPE(cmd) != TOPBAND_GPIO_IOC_MAGIC)
return -EINVAL;
if (_IOC_NR(cmd) > TOPBAND_GPIO_IOC_MAXNR)
return -EINVAL;
if (_IOC_DIR(cmd) & _IOC_READ)
ret = !access_ok(VERIFY_WRITE, (void *)arg, _IOC_SIZE(cmd));
else if (_IOC_DIR(cmd) & _IOC_WRITE)
ret = !access_ok(VERIFY_READ, (void *)arg, _IOC_SIZE(cmd));
if (ret)
return -EFAULT;
dev_info(&topband_gpio->platform_dev->dev,
"%s, (%x, %lx):\n", __func__, cmd,
arg);
switch (cmd) {
case TOPBAND_GPIO_IOC_SET_VALUE:
if (copy_from_user(&data, (int *)arg, sizeof(int))) {
dev_err(&topband_gpio->platform_dev->dev,
"%s, copy from user failed\n", __func__);
return -EFAULT;
}
ret = topband_gpio_ctrl(topband_gpio, data);
break;
default:
return -EINVAL;
}
return ret;
}
static const struct file_operations topband_gpio_dev_fops = {
.owner = THIS_MODULE,
.open = topband_gpio_dev_open,
.unlocked_ioctl = topband_gpio_dev_ioctl
};
static int topband_gpio_probe(struct platform_device *pdev)
{
int ret = 0;
struct topband_gpio_data *topband_gpio;
topband_gpio = devm_kzalloc(&pdev->dev, sizeof(*topband_gpio), GFP_KERNEL);
if(topband_gpio == NULL) {
dev_err(&pdev->dev, "Failed alloc ts memory");
return -ENOMEM;
}
if(pdev->dev.of_node) {
ret = topband_gpio_parse_dt(&pdev->dev, topband_gpio);
if(ret) {
dev_err(&pdev->dev, "Failed parse dts\n");
goto exit_free_data;
}
}
topband_gpio->platform_dev = pdev;
ret = topband_gpio_request_io_port(topband_gpio);
if(ret < 0) {
dev_err(&pdev->dev, "Failed request IO port\n");
goto exit_free_data;
}
platform_set_drvdata(pdev, topband_gpio);
topband_gpio->topband_gpio_device.minor = MISC_DYNAMIC_MINOR;
topband_gpio->topband_gpio_device.name = "topband_gpio";
topband_gpio->topband_gpio_device.fops = &topband_gpio_dev_fops;
ret = misc_register(&topband_gpio->topband_gpio_device);
if (ret) {
dev_err(&pdev->dev, "Failed misc_register\n");
goto exit_free_io_port;
}
dev_info(&pdev->dev, "%s, over\n", __func__);
return 0;
exit_free_io_port:
topband_gpio_free_io_port(topband_gpio);
exit_free_data:
devm_kfree(&pdev->dev, topband_gpio);
return ret;
}
static int topband_gpio_remove(struct platform_device *pdev)
{
struct topband_gpio_data *topband_gpio = platform_get_drvdata(pdev);
topband_gpio_free_io_port(topband_gpio);
kfree(topband_gpio);
return 0;
}
static const struct of_device_id topband_gpio_of_match[] = {
{ .compatible = "topband,gpio"},
{},
};
MODULE_DEVICE_TABLE(of, topband_gpio_of_match);
static struct platform_driver topband_gpio_driver = {
.probe = topband_gpio_probe,
.remove = topband_gpio_remove,
.driver = {
.name = TOPBAND_GPIO_NAME,
.owner = THIS_MODULE,
.of_match_table = topband_gpio_of_match,
},
};
module_platform_driver(topband_gpio_driver);
MODULE_AUTHOR("shenhb@topband.com");
MODULE_DESCRIPTION("Topband GPIO for application control");
MODULE_VERSION("1.0");
MODULE_LICENSE("GPL");
Kconfig
#
# TOPBAND GPIO driver configuration
#
config TOPBAND_GPIO_DRIVER
tristate "Topband GPIO driver"
default n
help
Topband GPIO driver for application control
Makefile
obj-$(CONFIG_TOPBAND_GPIO_DRIVER) += topband_gpio.o
- 修改上级目录的Kconfig与Makefile
diff --git a/kernel/drivers/misc/Kconfig b/kernel/drivers/misc/Kconfig
index b72da72..f22ca49 100755
--- a/kernel/drivers/misc/Kconfig
+++ b/kernel/drivers/misc/Kconfig
@@ -577,4 +577,5 @@ source "drivers/misc/genwqe/Kconfig"
source "drivers/misc/echo/Kconfig"
source "drivers/misc/cxl/Kconfig"
source "drivers/misc/n76e003/Kconfig"
+source "drivers/misc/topband_gpio/Kconfig"
diff --git a/kernel/drivers/misc/Makefile b/kernel/drivers/misc/Makefile
index e8d597b..2e97a69 100755
--- a/kernel/drivers/misc/Makefile
+++ b/kernel/drivers/misc/Makefile
@@ -62,3 +62,4 @@ obj-$(CONFIG_UID_SYS_STATS) += uid_sys_stats.o
obj-$(CONFIG_MEMORY_STATE_TIME) += memory_state_time.o
obj-$(CONFIG_USB_CAM_GPIO) += usb_cam_gpio.o
obj-$(CONFIG_N76E003_DRIVER) += n76e003/
+obj-$(CONFIG_TOPBAND_GPIO_DRIVER) += topband_gpio/
- 修改内核defconfig,将驱动编译至内核
diff --git a/kernel/arch/arm/configs/topband_pos_defconfig b/kernel/arch/arm/configs/topband_pos_defconfig
index 36c7947..cabe18c 100755
--- a/kernel/arch/arm/configs/topband_pos_defconfig
+++ b/kernel/arch/arm/configs/topband_pos_defconfig
@@ -715,4 +715,5 @@ CONFIG_CRYPTO_SHA256_ARM=y
CONFIG_CRYPTO_SHA512_ARM=y
CONFIG_CRYPTO_AES_ARM_BS=y
+CONFIG_TOPBAND_GPIO_DRIVER=y
- 配置dts文件
diff --git a/kernel/arch/arm/boot/dts/topband-pos-lvds-1280x800.dts b/kernel/arch/arm/boot/dts/topband-pos-lvds-12
index 45b0e45..0d99a97 100755
--- a/kernel/arch/arm/boot/dts/topband-pos-lvds-1280x800.dts
+++ b/kernel/arch/arm/boot/dts/topband-pos-lvds-1280x800.dts
@@ -96,6 +96,15 @@
mwsensor,delay_time = <3>;
mwsensor,is_poll = <1>;
};
+
+ topband_gpio: topband_gpio {
+ status = "okay";
+ compatible = "topband,gpio";
+ gpio-1 = <&gpio7 8 GPIO_ACTIVE_HIGH>;
+ gpio-2 = <&gpio8 1 GPIO_ACTIVE_HIGH>;
+ gpio-3 = <&gpio8 2 GPIO_ACTIVE_HIGH>;
+ gpio-4 = <&gpio8 3 GPIO_ACTIVE_HIGH>;
+ };
};
&cpu0 {
- 修改设备文件权限为:0666,否则Hal层无权限访问
diff --git a/system/core/rootdir/ueventd.rc b/system/core/rootdir/ueventd.rc
old mode 100644
new mode 100755
index eadf219..f0a3609
--- a/system/core/rootdir/ueventd.rc
+++ b/system/core/rootdir/ueventd.rc
@@ -65,6 +65,9 @@ subsystem sound
# kms driver for drm based gpu
/dev/dri/* 0666 root graphics
+# topband gpio driver
+/dev/topband_gpio 0666 system system
+
# these should not be world writable
/dev/diag 0660 radio radio
/dev/diag_arm9 0660 radio radio
shenhb@dqrd01:~/code/rk3288$
Hal&Framework
修改文件:
modified: frameworks/base/Android.mk
modified: frameworks/base/core/java/android/app/SystemServiceRegistry.java
modified: frameworks/base/core/java/android/content/Context.java
new file: frameworks/base/core/java/android/os/IGpioService.aidl
new file: frameworks/base/core/java/android/os/SystemGpio.java
new file: frameworks/base/services/core/java/com/android/server/GpioService.java
modified: frameworks/base/services/core/jni/Android.mk
new file: frameworks/base/services/core/jni/com_android_server_GpioService.cpp
modified: frameworks/base/services/core/jni/onload.cpp
modified: frameworks/base/services/java/com/android/server/SystemServer.java
new file: hardware/libhardware/include/hardware/gpio_hal.h
modified: hardware/libhardware/modules/Android.mk
new file: hardware/libhardware/modules/gpio/Android.mk
new file: hardware/libhardware/modules/gpio/gpio_hal.c
modified: system/core/rootdir/ueventd.rc
HAL层
1.在hardware/libhardware/modules/下新建目录gpio目录,在gpio目录下创建Android.mk和gpio_hal.c
Android.mk
# Copyright (C) 2012 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, oftware
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or mplied.
# See the License for the specific language governing permissions nd
# limitations under the License.
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := gpio.default
LOCAL_MODULE_RELATIVE_PATH := hw
LOCAL_PROPRIETARY_MODULE := true
LOCAL_SRC_FILES := gpio_hal.c
LOCAL_HEADER_LIBRARIES := libhardware_headers
LOCAL_SHARED_LIBRARIES := liblog libcutils libutils
LOCAL_MODULE_TAGS := optional
include $(BUILD_SHARED_LIBRARY)
gpio_hal.c
#include <hardware/hardware.h>
#include <cutils/log.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <hardware/gpio_hal.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <utils/Log.h>
#define DEVICE "/dev/topband_gpio"
#define GPIO_IOC_MAGIC 'f'
#define GPIO_IOC_SET_VALUE _IOW(GPIO_IOC_MAGIC, 1, int)
static int fd;
static int gpio_close(struct hw_device_t* device)
{
close(fd);
return 0;
}
static int gpio_open(struct gpio_device_t* dev)
{
fd = open(DEVICE, O_RDWR);
ALOGI("gpio_open : %d", fd);
if(fd >= 0) {
return 0;
} else {
return -1;
}
}
static int gpio_ctrl(struct gpio_device_t* dev, int gpio, int value)
{
int ret = 0;
int data = 0;
if(fd < 0) {
ret = gpio_open(dev);
if (ret < 0) {
return -1;
}
}
data = ((gpio & 0x0f) << 4) | (value & 0x0f);
ret = ioctl(fd, GPIO_IOC_SET_VALUE, &data);
ALOGI("gpio_ctrl: gpio=%d, value=%d, data=%d, ret=%d", gpio, alue, data, ret);
return ret;
}
static struct gpio_device_t gpio_dev = {
.common = {
.tag = HARDWARE_DEVICE_TAG,
.close = gpio_close,
},
.gpio_open = gpio_open,
.gpio_ctrl = gpio_ctrl,
};
static int gpio_device_open(const struct hw_module_t* module, const har* id,
struct hw_device_t** device)
{
*device = &gpio_dev;
return 0;
}
static struct hw_module_methods_t gpio_module_methods = {
.open = gpio_device_open,
};
struct hw_module_t HAL_MODULE_INFO_SYM = {
.tag = HARDWARE_MODULE_TAG,
.id = "gpio",
.methods = &gpio_module_methods,
};
2.增加文件:hardware/libhardware/include/hardware/gpio_hal.h
#ifndef ANDROID_GPIO_INTERFACE_H
#define ANDROID_GPIO_INTERFACE_H
#include <stdint.h>
#include <sys/cdefs.h>
#include <sys/types.h>
#include <hardware/hardware.h>
__BEGIN_DECLS
struct gpio_device_t {
struct hw_device_t common;
int (*gpio_open)(struct gpio_device_t* dev);
int (*gpio_ctrl)(struct gpio_device_t* dev, int gpio, int alue);
};
__END_DECLS^M
#endif // ANDROID_GPIO_INTERFACE_H
3.修改父级Android.mk,将gpio模块加入编译
diff --git a/hardware/libhardware/modules/Android.mk b/hardware/libhardware/modules/Android.mk
old mode 100644
new mode 100755
index 462081d..9e33f41
--- a/hardware/libhardware/modules/Android.mk
+++ b/hardware/libhardware/modules/Android.mk
@@ -10,5 +10,6 @@ hardware_modules := \
usbaudio \
usbcamera \
vehicle \
- vr
+ vr \
+ gpio
include $(call all-named-subdir-makefiles,$(hardware_modules))
JNI层
1.增加文件:frameworks/base/services/core/jni/com_android_server_GpioService.cpp
#include "jni.h"
#include "JNIHelp.h"
#include "android_runtime/AndroidRuntime.h"
#include <utils/misc.h>
#include <utils/Log.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <hardware/gpio_hal.h>
namespace android
{
static struct gpio_device_t* gpioDevice;
jint gpioOpen(JNIEnv *env, jobject cls)
{
jint err;
hw_module_t* module;
hw_device_t* device;
ALOGI("native gpioOpen ...");
// hw_get_module finds the library by "gpio" (this is the id of al)
err = hw_get_module("gpio", (hw_module_t const**)&module);
if(err == 0) {
// Get device : module->methods->open
err = module->methods->open(module, NULL, &device);
if(err == 0) {
// Call gpio_open
gpioDevice = (gpio_device_t *)device;
return gpioDevice->gpio_open(gpioDevice);
} else {
return -1;
}
}
return -1;
}
void gpioClose(JNIEnv *env, jobject cls)
{
ALOGI("native gpioClose ...");
}
jint gpioCtrl(JNIEnv *env, jobject cls, jint gpio, jint value)
{
ALOGI("native gpioCtrl gpio=%d, value=%d", gpio, value);
return gpioDevice->gpio_ctrl(gpioDevice, gpio, value);
}
// Register native methods
static const JNINativeMethod methods[] = {
{"native_gpioOpen", "()I", (void *)gpioOpen},
{"native_gpioClose", "()V", (void *)gpioClose},
{"native_gpioCtrl", "(II)I", (void *)gpioCtrl},
};
int register_android_server_GpioService(JNIEnv *env)
{
// The Java method corresponding to the local method GpioService
return jniRegisterNativeMethods(env, com/android/server/GpioService",
methods, NELEM(methods));
}
}
2.修改:frameworks/base/services/core/jni/onload.cpp
diff --git a/frameworks/base/services/core/jni/onload.cpp b/frameworks/base/services/core/jni/onload.cpp
old mode 100644
new mode 100755
index 4d70384..08ddb64
--- a/frameworks/base/services/core/jni/onload.cpp
+++ b/frameworks/base/services/core/jni/onload.cpp
@@ -39,6 +39,7 @@ int register_android_server_UsbMidiDevice(JNIEnv* env);
int register_android_server_UsbHostManager(JNIEnv* env);
int register_android_server_vr_VrManagerService(JNIEnv* env);
int register_android_server_VibratorService(JNIEnv* env);
+int register_android_server_GpioService(JNIEnv* env);
int register_android_server_location_ContextHubService(JNIEnv* env);
int register_android_server_location_GnssLocationProvider(JNIEnv* env);
int register_android_server_connectivity_Vpn(JNIEnv* env);
@@ -82,6 +83,7 @@ extern "C" jint JNI_OnLoad(JavaVM* vm, void* /* reserved */)
register_android_server_UsbHostManager(env);
register_android_server_vr_VrManagerService(env);
register_android_server_VibratorService(env);
+ register_android_server_GpioService(env);
register_android_server_SystemServer(env);
register_android_server_location_ContextHubService(env);
register_android_server_location_GnssLocationProvider(env);
3.修改:frameworks/base/services/core/jni/Android.mk
diff --git a/frameworks/base/services/core/jni/Android.mk b/frameworks/base/services/core/jni/Android.mk
old mode 100644
new mode 100755
index b44362a..0d57546
--- a/frameworks/base/services/core/jni/Android.mk
+++ b/frameworks/base/services/core/jni/Android.mk
@@ -38,6 +38,7 @@ LOCAL_SRC_FILES += \
$(LOCAL_REL_DIR)/com_android_server_UsbMidiDevice.cpp \
$(LOCAL_REL_DIR)/com_android_server_UsbHostManager.cpp \
$(LOCAL_REL_DIR)/com_android_server_VibratorService.cpp \
+ $(LOCAL_REL_DIR)/com_android_server_GpioService.cpp \
$(LOCAL_REL_DIR)/com_android_server_PersistentDataBlockService.cpp \
$(LOCAL_REL_DIR)/com_android_server_GraphicsStatsService.cpp \
$(LOCAL_REL_DIR)/onload.cpp
Framework层(将GpioService注册到Framework)
1.增加文件:frameworks/base/core/java/android/os/IGpioService.aidl
package android.os;
/** {@hide} */
interface IGpioService
{
int gpioCtrl(int gpio, int value);
}
2.增加文件:frameworks/base/services/core/java/com/android/server/GpioService.java
package com.android.server;
import android.os.IGpioService;
public class GpioService extends IGpioService.Stub
{
private static final String TAG = "GpioService";
/* call native c function to access hardware */
public int gpioCtrl(int gpio, int value) throws ndroid.os.RemoteException
{
return native_gpioCtrl(gpio, value);
}
public GpioService()
{
native_gpioOpen();
}
public static native int native_gpioOpen();
public static native void native_gpioClose();
public static native int native_gpioCtrl(int gpio, int value);
}
3.修改:frameworks/base/Android.mk
diff --git a/frameworks/base/Android.mk b/frameworks/base/Android.mk
index 3018c4e..d301cfd 100755
--- a/frameworks/base/Android.mk
+++ b/frameworks/base/Android.mk
@@ -276,6 +276,7 @@ LOCAL_SRC_FILES += \
core/java/android/os/IUpdateLock.aidl \
core/java/android/os/IUserManager.aidl \
core/java/android/os/IVibratorService.aidl \
+ core/java/android/os/IGpioService.aidl \
core/java/android/os/storage/IStorageManager.aidl \
core/java/android/os/storage/IStorageEventListener.aidl \
core/java/android/os/storage/IStorageShutdownObserver.aidl \
- 修改:frameworks/base/services/java/com/android/server/SystemServer.java
diff --git a/frameworks/base/services/java/com/android/server/SystemServer.java b/frameworks/base/services/java/co
index fdf580e..8800516 100755
--- a/frameworks/base/services/java/com/android/server/SystemServer.java
+++ b/frameworks/base/services/java/com/android/server/SystemServer.java
@@ -795,6 +795,11 @@ public final class SystemServer {
vibrator = new VibratorService(context);
ServiceManager.addService("vibrator", vibrator);
traceEnd();
+
+ traceBeginAndSlog("StartGpioService");
+ GpioService gpio = new GpioService();
+ ServiceManager.addService("gpio", gpio);
+ traceEnd();
if (!disableConsumerIr) {
traceBeginAndSlog("StartConsumerIrService");
Framework(Application)
1.增加文件:frameworks/base/core/java/android/os/SystemGpio.java
package android.os;
import android.content.Context;
import android.media.AudioAttributes;
import android.util.Log;
/**
Gpio implementation that controls the main system gpio.
@hide
*/
public class SystemGpio
{
private static final String TAG = "gpio";
private final IGpioService mService;
public SystemGpio()
{
mService = IGpioService.Stub.asInterface(
ServiceManager.getService("gpio"));
}
public SystemGpio(Context context)
{
mService = IGpioService.Stub.asInterface(
ServiceManager.getService("gpio"));
}
public void gpioCtrl(int gpio,int value)
{
try {
mService.gpioCtrl(gpio, value);
} catch(Exception e) {}
}
}
2.修改:frameworks/base/core/java/android/content/Context.java
diff --git a/frameworks/base/core/java/android/content/Context.java b/frameworks/base/core/java/android/content/Co
index a31cb43..c18b848 100755
--- a/frameworks/base/core/java/android/content/Context.java
+++ b/frameworks/base/core/java/android/content/Context.java
@@ -3352,6 +3352,8 @@ public abstract class Context {
* @see android.os.Vibrator
*/
public static final String VIBRATOR_SERVICE = "vibrator";
+
+ public static final String GPIO_SERVICE = "gpio";
/**
* Use with {@link #getSystemService} to retrieve a {@link
3.修改:frameworks/base/core/java/android/app/SystemServiceRegistry.java
diff --git a/frameworks/base/core/java/android/app/SystemServiceRegistry.java b/frameworks/base/core/java/android/
index e695936..ce1fe51 100755
--- a/frameworks/base/core/java/android/app/SystemServiceRegistry.java
+++ b/frameworks/base/core/java/android/app/SystemServiceRegistry.java
@@ -119,6 +119,7 @@ import android.os.SystemVibrator;
import android.os.UserHandle;
import android.os.UserManager;
import android.os.Vibrator;
+import android.os.SystemGpio;
import android.os.health.SystemHealthManager;
import android.os.storage.StorageManager;
import android.print.IPrintManager;
@@ -535,6 +536,14 @@ final class SystemServiceRegistry {
public Vibrator createService(ContextImpl ctx) {
return new SystemVibrator(ctx);
}});
+
+
+ registerService(Context.GPIO_SERVICE, SystemGpio.class,
+ new CachedServiceFetcher<SystemGpio>() {
+ @Override
+ public SystemGpio createService(ContextImpl ctx) {
+ return new SystemGpio(ctx);
+ }});
registerService(Context.WALLPAPER_SERVICE, WallpaperManager.class,
new CachedServiceFetcher<WallpaperManager>() {
编译更新API
make update-api
APP
- 引入Android定制后的Framework jar包(out/target/common/obj/JAVA_LIBRARIES/framework_intermediates/classes.jar)
- 将classes.jar拷贝到app/libs/目录下
- 修改项目根目录build.gradle,在allprojects段内增加下面代码:
allprojects { repositories { google() jcenter() } gradle.projectsEvaluated { tasks.withType(JavaCompile) { options.compilerArgs.add('-Xbootclasspath/p:app\\libs\\classes.jar') } } }
- 修改app/build.gradle,如下:
android{ defaultConfig { multiDexEnabled true } } dependencies { compileOnly files('libs/classes.jar') } preBuild { doLast { def imlFile = file(project.name + ".iml") println('Change ' + project.name + '.iml order') try { def parsedXml = (new XmlParser()).parse(imlFile) def jdkNode = parsedXml.component[1].orderEntry.find { it.'@type' == 'jdk' } parsedXml.component[1].remove(jdkNode) def sdkString = "Android API " + android.compileSdkVersion.substring("android-".length()) + " Platform" new groovy.util.Node(parsedXml.component[1], 'orderEntry', ['type': 'jdk', 'jdkName': sdkString, 'jdkType': 'Android SDK']) groovy.xml.XmlUtil.serialize(parsedXml, new FileOutputStream(imlFile)) } catch (FileNotFoundException e) { // nop, iml not found } } }
- 系统GPIO Service类为SystemGpio,调用方式如下:
package com.ayst.item;
import android.annotation.SuppressLint;
import android.content.Context;
import android.os.SystemGpio;
public class GpioTest {
private SystemGpio mGpioService;
@SuppressLint("WrongConstant")
public GpioTest(Context context) {
mGpioService = (SystemGpio) context.getSystemService("gpio");
}
/**
* GPIO control
* @param gpio 1,2,3,4
* @param value 0: Low 1: High
*/
public void gpioCtrl(int gpio, int value) {
if (null != mGpioService) {
mGpioService.gpioCtrl(gpio, value);
}
}
}
网友评论