Android开发Android开发经验谈Android技术知识

Android从硬件到APP:增加硬件服务

2018-12-11  本文已影响33人  爱因私谈

Android从硬件到APP:增加硬件服务

Android平台应用越来越广泛,在一些应用领域我们经常需要增加一些硬件控制等特殊功能,而标准Android框架仅支持手机、平板等常见外围器件,比如:相机、震动、电话、蓝牙、音频等。下面就以某个项目需要实现APP操作GPIO来讲述开发的整个过程。

驱动

  1. 在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
  1. 修改上级目录的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/
  1. 修改内核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
  1. 配置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 {
  1. 修改设备文件权限为: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 \
  1. 修改: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

  1. 引入Android定制后的Framework jar包(out/target/common/obj/JAVA_LIBRARIES/framework_intermediates/classes.jar)
    1. 将classes.jar拷贝到app/libs/目录下
    2. 修改项目根目录build.gradle,在allprojects段内增加下面代码:
    allprojects {
        repositories {
            google()
            jcenter()
        }
    
        gradle.projectsEvaluated {
            tasks.withType(JavaCompile) {
                options.compilerArgs.add('-Xbootclasspath/p:app\\libs\\classes.jar')
            }
        }
    }
    
    1. 修改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
            }
        }
    }
    
  2. 系统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);
        }
    }
}
上一篇下一篇

猜你喜欢

热点阅读