1、定义硬件访问服务接口
添加 frameworks\base\core\java\android\hardware\freg\IFregService.aidl
package android.hardware.freg;
interface IFregService {
void setVal (int val);
int getVal ();
}
修改 frameworks\base\Android.mk
core/java/android/hardware/freg/IFregService.aidl \
mmm frameworks/base/
2、实现硬件访问服务
添加 frameworks\base\services\core\java\com\android\server\freg\FregService.java
package com.android.server.freg;
import android.hardware.freg.IFregService;
import android.util.Slog;
/**
* Created by liudongming on 1/14/17.
*/
public class FregService extends IFregService.Stub {
private static final String TAG = "FregService";
private long mPtr = 0;
public FregService () {
Slog.d(TAG, "FregService()");
mPtr = init_native ();
if(mPtr == 0){
Slog.e(TAG, "Failed to initialize freg service.");
}
}
public void setVal (int val){
if (mPtr == 0){
Slog.e(TAG, "setVal Freg service is not initialized.");
return;
}
setVal_native(mPtr, val);
}
public int getVal(){
if (mPtr == 0){
Slog.e(TAG, "getVal Freg service is not initialized.");
return 0;
}
return getVal_native(mPtr);
}
private static native long init_native();
private static native void setVal_native(long ptr, int val);
private static native int getVal_native(long ptr);
};
3、实现硬件访问服务的JNI方法
添加 frameworks\base\services\core\jni\com_android_server_freg_FregService.cpp
//
// Created by liudongming on 1/14/17.
//
#undef LOG_TAG
#define LOG_TAG "FregServiceJNI"
#define TAG "[Freg] "
#include "jni.h"
#include "JNIHelp.h"
#include <android_runtime/AndroidRuntime.h>
#include <android_runtime/Log.h>
#include <utils/Log.h>
#include <utils/misc.h>
#include <hardware/hardware.h>
#include <hardware/freg.h>
#include <stdio.h>
#define LOGD ALOGD
#define LOGI ALOGI
#define LOGW ALOGW
#define LOGE ALOGE
namespace android
{
//设置虚拟硬件设备freg的寄存器的值,64位机器上指针占8字节,使用long来转换
//static void freg_setVal (JNIEnv* env, jobject clazz, jint ptr, jint value){
static void freg_setVal (JNIEnv* env, jobject clazz, jlong ptr, jint value){
//将参数ptr转换为freg_device_t结构体变量
freg_device_t* device = (freg_device_t*)ptr;
if(!device){
LOGE(TAG"Device freg is not open.");
return;
}
int val = value;
LOGI(TAG"Set value %d to device freg.", val);
device->set_val(device, val);
}
//读取虚拟硬件设备freg的寄存器的值,64位机器上指针占8字节,使用long来转换
//static jint freg_getVal (JNIEnv* env, jobject clazz, jint ptr) {
static jint freg_getVal (JNIEnv* env, jobject clazz, jlong ptr) {
//将参数ptr转换为freg_device_t结构体变量
freg_device_t* device = (freg_device_t*)ptr;
if(!device){
LOGE(TAG"Device freg is not open.");
return 0;
}
int val = 0;
device->get_val (device, &val);
LOGI(TAG"Get value %d from device freg.", val);
return val;
}
//打开虚拟硬件设备freg
static inline int freg_device_open(const hw_module_t* module, struct freg_device_t** device) {
LOGD(TAG"freg_device_open");
return module->methods->open(module, FREG_HARDWARE_DEVICE_ID, (struct hw_device_t**)device);
}
//初始化虚拟硬件设备freg
static jlong freg_init (JNIEnv* env, jclass clazz) {
freg_module_t* module;
freg_device_t* device;
LOGI(TAG"Initializing HAL stub freg......");
//加载硬件抽象层模块freg
if(hw_get_module(FREG_HARDWARE_MODULE_ID, (const struct hw_module_t**)&module) == 0){
LOGI(TAG"Device freg found.");
//打开虚拟硬件设备freg
if(freg_device_open(&(module->common), &device) == 0){
LOGI(TAG"Device freg is open");
//将freg_device_t接口转换为整形值返回
//return (jlong)device;
return reinterpret_cast<jlong>(device);
}
LOGE(TAG"Faied to open device freg.");
return 0;
}
LOGE(TAG"Faied to get HAL stub freg.");
return 0;
}
//Java本地接口方法表
static const JNINativeMethod method_table[] = {
{"init_native", "()J", (void*)freg_init},
{"setVal_native", "(JI)V", (void*)freg_setVal},
{"getVal_native", "(J)I", (void*)freg_getVal},
};
//注册Java本地接口方法
int register_android_server_FregService(JNIEnv* env){
return jniRegisterNativeMethods(env, "com/android/server/freg/FregService",
method_table, NELEM(method_table));
}
}
修改 frameworks\base\services\core\jni\Onload.cpp
添加
int register_android_server_FregService(JNIEnv* env);// add by liudongming
和
register_android_server_FregService(env); //add by liudongming
namespace android {
int register_android_server_AlarmManagerService(JNIEnv* env);
int register_android_server_AssetAtlasService(JNIEnv* env);
int register_android_server_BatteryStatsService(JNIEnv* env);
int register_android_server_ConsumerIrService(JNIEnv *env);
int register_android_server_InputApplicationHandle(JNIEnv* env);
int register_android_server_InputWindowHandle(JNIEnv* env);
int register_android_server_InputManager(JNIEnv* env);
int register_android_server_FregService(JNIEnv* env);// add by liudongming
int register_android_server_LightsService(JNIEnv* env);
int register_android_server_PowerManagerService(JNIEnv* env);
int register_android_server_SerialService(JNIEnv* env);
int register_android_server_SystemServer(JNIEnv* env);
int register_android_server_UsbDeviceManager(JNIEnv* env);
......
extern "C" jint JNI_OnLoad(JavaVM* vm, void* /* reserved */)
{
JNIEnv* env = NULL;
jint result = -1;
if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) {
ALOGE("GetEnv failed!");
return result;
}
ALOG_ASSERT(env, "Could not retrieve the env!");
register_android_server_PowerManagerService(env);
register_android_server_SerialService(env);
register_android_server_InputApplicationHandle(env);
register_android_server_InputWindowHandle(env);
register_android_server_InputManager(env);
register_android_server_FregService(env); //add by liudongming
register_android_server_LightsService(env);
register_android_server_AlarmManagerService(env);
register_android_server_UsbDeviceManager(env);
register_android_server_UsbMidiDevice(env);
register_android_server_UsbHostManager(env);
......
修改 frameworks\base\services\core\jni\Android.mk 添加
$(LOCAL_REL_DIR)/com_android_server_freg_FregService.cpp \
LOCAL_SRC_FILES += \
......
$(LOCAL_REL_DIR)/com_android_server_freg_FregService.cpp \
$(LOCAL_REL_DIR)/onload.cpp
编译一下 mmm /frameworks/base/
4、启动硬件访问服务
修改 frameworks\base\services\java\com\android\server\SystemServer.java
import com.android.server.freg.FregService; //add by liudongming
private void startOtherServices() {
......
StatusBarManagerService statusBar = null;
INotificationManager notification = null;
InputMethodManagerService imm = null;
FregService afregService = null; //add by liudongming
WallpaperManagerService wallpaper = null;
LocationManagerService location = null;
CountryDetectorService countryDetector = null;
......
// Bring up services needed for UI.
if (mFactoryTestMode != FactoryTest.FACTORY_TEST_LOW_LEVEL) {
traceBeginAndSlog("StartInputMethodManagerService");
try {
imm = new InputMethodManagerService(context, wm);
ServiceManager.addService(Context.INPUT_METHOD_SERVICE, imm);
} catch (Throwable e) {
reportWtf("starting Input Manager Service", e);
}
Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
//add by liudongming begin
traceBeginAndSlog("StartFregService");
try {
afregService = new FregService();
ServiceManager.addService("freg", afregService);
} catch (Throwable e) {
reportWtf("starting Freg Service", e);
}
Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
//add by liudongming end
traceBeginAndSlog("StartAccessibilityManagerService");
try {
ServiceManager.addService(Context.ACCESSIBILITY_SERVICE,
new AccessibilityManagerService(context));
} catch (Throwable e) {
reportWtf("starting Accessibility Manager", e);
}
Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
}
注:要更新一下api
make update-api
生成新的两个txt文件记得提交服务器
/frameworks/base/api/current.txt
/frameworks/base/api/system-current.txt
mmm /frameworks/base/
make snod
5、开发Android应用程序来使用硬件访问服务
~/packages/experimental/FregServiceTest
----AndroidManifest.xml
----Android.mk
----src
----com/mycompany/fregtest
-----MainActivity.java
----res
----layout
-----activity_main.xml
---- values
---- strings.xml
---- minimap
----ic_launcher.png
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.mycompany.fregtest">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
Android.mk
# Copyright (C) 2010 Google Inc.
#
# 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)
include $(CLEAR_VARS)
LOCAL_MODULE_TAGS := optional
LOCAL_SRC_FILES := $(call all-java-files-under, src)
LOCAL_PACKAGE_NAME := FregTest
include $(BUILD_PACKAGE)
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.mycompany.fregtest.MainActivity">
<EditText
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:inputType="textPersonName"
android:text="@string/namd"
android:ems="10"
android:layout_alignParentTop="true"
android:layout_alignParentStart="true"
android:id="@+id/editText" />
<Button
android:text="@string/read"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/editText"
android:layout_alignParentStart="true"
android:id="@+id/btnRead" />
<Button
android:text="@string/write"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/btnWrite"
android:layout_below="@+id/editText"
android:layout_toEndOf="@+id/btnRead" />
<Button
android:text="@string/clear"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/btnClear"
android:layout_below="@+id/editText"
android:layout_toEndOf="@+id/btnWrite" />
</RelativeLayout>
MainActivity.java
package com.mycompany.fregtest;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.hardware.freg.IFregService;
import android.util.Log;
import android.app.Activity;
import android.os.ServiceManager;
import android.os.RemoteException;
import android.widget.Toast;
public class MainActivity extends Activity implements View.OnClickListener {
private EditText etFregVal;
private Button btnRead;
private Button btnWrite;
private Button btnClear;
private IFregService fregService;
private final String TAG = "FregTest";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
etFregVal = (EditText) findViewById(R.id.editText);
btnRead = (Button) findViewById(R.id.btnRead);
btnWrite = (Button) findViewById(R.id.btnWrite);
btnClear = (Button) findViewById(R.id.btnClear);
btnRead.setOnClickListener(this);
btnWrite.setOnClickListener(this);
btnClear.setOnClickListener(this);
fregService = IFregService.Stub.asInterface(ServiceManager.getService("freg"));
if (fregService == null) {
Toast.makeText(this, "fregService is null", Toast.LENGTH_SHORT).show();
}
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btnRead:
try{
int val = fregService.getVal();
Log.d(TAG, "fregService.getVal " + val);
String text = String.valueOf(val);
etFregVal.setText(text);
} catch (RemoteException e) {
Log.e(TAG, "Remote Exception while reading value from freg service." + e);
Toast.makeText(this, "Remote Exception while reading value from freg service.",
Toast.LENGTH_SHORT).show();
}
break;
case R.id.btnWrite:
try{
String text = etFregVal.getText().toString();
int val = Integer.parseInt(text);
Log.d(TAG, "fregService.setVal " + val);
fregService.setVal(val);
} catch (RemoteException e){
Log.e(TAG, "Remote Exception while writing value to freg service." + e);
Toast.makeText(this, "Remote Exception while writing value to freg service.",
Toast.LENGTH_SHORT).show();
}
break;
case R.id.btnClear:
etFregVal.setText("");
break;
default:
break;
}
}
}
strings.xml
<resources>
<string name="app_name">FregTest</string>
<string name="namd"></string>
<string name="read">读取</string>
<string name="write">写入</string>
<string name="clear">清除</string>
</resources>