Androidアプリでカーネル駆動を起動する方法
この文は商業用途としてはいけません.勉強のためだけに使うものです.転載は出所を明記してください.http://blog.csdn.net/callon_h/articale/detail/51909169
一、Android駆動フレームを理解する:
1.方法1——Jniは下のドライバを呼び出します.
Androidフレームにc/c+++を書き込み、直接に下のlinuxドライバを呼び出し、上にjniインターフェースをアプリケーションに提供します.
長所:簡単で行いやすい;
欠点:主にドライバにあります.linuxではGPLプロトコルに従う必要があるので、オープンソースが必要です.多くのメーカーのコードはオープンソースを望まないです.
2.方法2——ハードウェアの抽象層を増やす
ドライバを二つに分けて、一部のオープンソースはカーネルにあり、一部のオープンソースはアンディフレームにあります.
二、例えばled android駆動:
ここから全体の応用フレーム層の最終層駆動の流れを見るであろう.まず、どの方法であれ、上の階層がledリソースにアクセスするために、linux駆動を実現する必要があります.
1.linuxドライバ:
linuxのキャラクターデバイスドライバの作成:
まず、なぜjniを使うかを説明します.
1.コードの保護に基づいて、Javaは相対的に逆コンパイルされやすいですが、c/c++ライブラリの逆コンパイルは難しいです.
2.既存のオープンソースライブラリを便利に使用することができます.
3.実行効率を向上させる.
4.javaはいくつかのファイルの操作の方面で、関連しているAPIが探し出せません.このようなところのioctl.
次に、なぜndkを使いますか?
ndkは一連のツールを提供しています.開発者が素早くc/c++のダイナミックライブラリを開発するのを助けることができます.そして自動的に.soダイナミックライブラリとjavaをappkに包装します.
第一の方法の設計構想は以下の通りである.
最初のステップでjavahコマンドを使って自動的にヘッドファイルを生成するには、まずappプログラムを作成する必要がありますが、この時のアプリは完璧ではなく、あなたが欲しいnativeインターフェースを提出するだけでいいです.
javah-d jni-classipathあなたのsdkディレクトリ/plotforms/あなたのプラットフォーム名/android.jar:あなたのアプリケーション/ap/build/intermediates/classis/debug/あなたのバッグ名.主類名
例えば:
は、頭ファイルのcom_が含まれています.led_ドラック.example_calon_ドラック.led_MainActivity.h、ヘッダファイルが重要です.
まず、Project形式で私達のapを見にきて、そしてapp->src->mainの下で1つのディレクトリ“jniLibs”を創建します.
そして、私たち.soがいるarmeabiディレクトリをjniLibsディレクトリにコピーします.
最後に私達のアプリコードの最後に追加します.
3第二の方法を実現する:
1.HALプログラミング:
まずは 安卓源コードルートディレクトリ/ハードware/libhard ware/modules/下に自分のhalコードの保存経路を作成します.例えば、led.
最終的に作成されたファイルは、安卓源コードルートディレクトリ/hardware/libhardware/modules/led_hal.cとAndroid.mkと、Androidコードのルートディレクトリ/hadware/libhardware/include/hardware/led.h.
私たちはsystem.imgをやり直します.ここでスクリプトを通して完成します.
2.ハードウェアサービスの作成:
まず、Service Managerはアクセス衝突を解決するために存在します.Service Managerがある上に、私達の下の階は先にハードウェアサービスを作成して、Service Managerに登録しなければなりません.私達のアプリはService Managerを通じてサービスを取得し、下の階を操作することができます.
多くのディレクトリ操作に関連していますので、詳細な操作後は以下の通りです.
1.ILedService.aidlを作成する
フレームワーク/base/core/java/android/os/IVibrate Service.aidlに倣う
増加
mmm frame eworks/base/コンパイル自動生成out/target/common/obj/JAVA_LIBREIES/frame ework_intermediates/src/core/java/android/os/ILedService.java
4.LedService.javaを作成し、インターフェース機能を実現する.
フレームワーク/base/services/core/java/com/android/server/Vibrator Servicer.javaを模倣します.
frame eworks/base/services/java/com/android/server/SystemServer.javaを修正します.
vibratorの修正箇所を参考にしてください.
なぜそれが必要ですか?私たちのhalコードはjniのインターフェースを提供していませんから(ここではnative方法を提供するための新しい方法が提供されています.以前は自動的にヘッダファイルを生成してから実現します).
frame eworks/base/services/core/jni/com_android_server_Vibrate Service.cpp
フレームワーク/base/services/core/jni/onload.cppに追加します.
frame eworks/base/services/core/jni/Android.mkに自分の書いたcomを入れます.android_server_LedService.cpp
ファイル名にスペースがあります.
.このようなミスが発生したら、忍耐強くしなければならない.
最後に引き続き使用します.
3.アプリケーション設計:
http://blog.csdn.net/wukunting/article/details/5788196
まずout/target/comon/obj/JAVA_をコピーします.LIBREIES/frame ework_intermediat/classis.jarは工事の下に着きます.
その後、Android StudioでFile->Project Structureをクリックし、その中の'+'-'をクリックしてImport.JAR/.AAR Package-'を選択し、class.jar->Finishを選択します.
引き続きProject Structureの下でap->Dependencies->選択'+'->Module Dependency->選択'clases'を選択すればいいです.
この時点でソース全体が良くなりましたが、ダウンロード速度が遅くなります.frame ewarksに基づいて設計されたアプリのダウンロードと運行速度を改善する方案:
1.build.gradleを修正する(Module:app)
アプリで追加
android:name=「android.support.multiide x.Multi DexAppliation」
最後にダウンロードして実行してください.
一、Android駆動フレームを理解する:
1.方法1——Jniは下のドライバを呼び出します.
Androidフレームにc/c+++を書き込み、直接に下のlinuxドライバを呼び出し、上にjniインターフェースをアプリケーションに提供します.
長所:簡単で行いやすい;
欠点:主にドライバにあります.linuxではGPLプロトコルに従う必要があるので、オープンソースが必要です.多くのメーカーのコードはオープンソースを望まないです.
2.方法2——ハードウェアの抽象層を増やす
ドライバを二つに分けて、一部のオープンソースはカーネルにあり、一部のオープンソースはアンディフレームにあります.
二、例えばled android駆動:
ここから全体の応用フレーム層の最終層駆動の流れを見るであろう.まず、どの方法であれ、上の階層がledリソースにアクセスするために、linux駆動を実現する必要があります.
1.linuxドライバ:
linuxのキャラクターデバイスドライバの作成:
#include
#include
#include
#include
#include
#include
#include
#include
static struct cdev dev;
static dev_t dev_num;
#define GPM4CON 0x110002E0
#define GPM4DAT 0X110002E4
#define LED_ON _IOW('G',0,int)
#define LED_OFF _IOW('G',1,int)
static unsigned int *led_con = NULL;
static unsigned int *led_dat = NULL;
static struct class *led_class = NULL;
static long led_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
switch(cmd)
{
case LED_ON:
{
writel(readl(led_dat)& ~(0x1<
2第一の方法を実現する:まず、なぜjniを使うかを説明します.
1.コードの保護に基づいて、Javaは相対的に逆コンパイルされやすいですが、c/c++ライブラリの逆コンパイルは難しいです.
2.既存のオープンソースライブラリを便利に使用することができます.
3.実行効率を向上させる.
4.javaはいくつかのファイルの操作の方面で、関連しているAPIが探し出せません.このようなところのioctl.
次に、なぜndkを使いますか?
ndkは一連のツールを提供しています.開発者が素早くc/c++のダイナミックライブラリを開発するのを助けることができます.そして自動的に.soダイナミックライブラリとjavaをappkに包装します.
第一の方法の設計構想は以下の通りである.
最初のステップでjavahコマンドを使って自動的にヘッドファイルを生成するには、まずappプログラムを作成する必要がありますが、この時のアプリは完璧ではなく、あなたが欲しいnativeインターフェースを提出するだけでいいです.
package com.led.ndk.example.callon.ndk_led;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.CheckBox;
public class MainActivity extends Activity {
private CheckBox[] Led = new CheckBox[4];
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Led[0] = (CheckBox)findViewById(R.id.checkbox_led1);
Led[1] = (CheckBox)findViewById(R.id.checkbox_led2);
Led[2] = (CheckBox)findViewById(R.id.checkbox_led3);
Led[3] = (CheckBox)findViewById(R.id.checkbox_led4);
}
private void SendCmd(View view)
{
for(int i =1; i<5; i++)
{
if(Led[i].isChecked())
{
cmdLeds(1, i);
}
else
{
cmdLeds(0, i);
}
}
}
public native void cmdLeds(int cmd, int arg);
}
上記の簡単なアプリに基づいて、コマンドを使用します.javah-d jni-classipathあなたのsdkディレクトリ/plotforms/あなたのプラットフォーム名/android.jar:あなたのアプリケーション/ap/build/intermediates/classis/debug/あなたのバッグ名.主類名
例えば:
javah -d jni -classpath /opt/AndroidSDK/platforms/android-23/android.jar:/home/callon/Downloads/callon_ndk_led/ndk_led/app/build/intermediates/classes/debug/ com.led.ndk.example.callon.ndk_led.MainActivity
jniフォルダが自動的に生成されます.は、頭ファイルのcom_が含まれています.led_ドラック.example_calon_ドラック.led_MainActivity.h、ヘッダファイルが重要です.
JNIEXPORT void JNICALL Java_com_led_ndk_example_callon_ndk_1led_MainActivity_cmdLeds
(JNIEnv *, jobject, jint, jint);
これはソースファイルを作成するために必要な方法名です.直接ソースファイルを作成します.#include "com_led_ndk_example_callon_ndk_led_MainActivity.h"
#include
#include
#include
#include
#include
#include
#include
#define LED_ON _IOW('G',0,int)
#define LED_OFF _IOW('G',1,int)
JNIEXPORT void JNICALL Java_com_led_ndk_example_callon_ndk_1led_MainActivity_cmdLeds
(JNIEnv * env, jobject thiz, jint cmd, jint arg)
{
int fd;
int temp_cmd;
fd = open("/dev/callon_led",O_WRONLY);
if(cmd == 1)
temp_cmd = LED_ON;
else
temp_cmd = LED_OFF;
ioctl(fd, temp_cmd, arg);
close(fd);
}
カーネル駆動ファイルのいくつかの操作で、Android.mkであるmakefileを作成します.LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := callon_ndk_led
LOCAL_SRC_FILES := ndk_led.c
include $(BUILD_SHARED_LIBRARY)
この時、あなたのjniフォルダにはこの3つのファイルがあるはずです.jniフォルダ以外に退避して、コマンドndk-buildを使えばいいです.callon@untu:~/Downloads/callon_ndk_led/jni$ ls
Android.mk com_led_ndk_example_callon_ndk_led_MainActivity.h ndk_led.c
callon@ubuntu:~/Downloads/callon_ndk_led/jni$ cd ..
callon@ubuntu:~/Downloads/callon_ndk_led$ ndk-build
[armeabi] Compile thumb : callon_ndk_led <= ndk_led.c
[armeabi] SharedLibrary : libcallon_ndk_led.so
[armeabi] Install : libcallon_ndk_led.so => libs/armeabi/libcallon_ndk_led.so
callon@ubuntu:~/Downloads/callon_ndk_led$
最終ステップ、完全アプリ:まず、Project形式で私達のapを見にきて、そしてapp->src->mainの下で1つのディレクトリ“jniLibs”を創建します.
そして、私たち.soがいるarmeabiディレクトリをjniLibsディレクトリにコピーします.
最後に私達のアプリコードの最後に追加します.
static
{
system.loadLibrary("callon_ndk_led");
}
そしてRebuild Projectでいいです.3第二の方法を実現する:
1.HALプログラミング:
まずは 安卓源コードルートディレクトリ/ハードware/libhard ware/modules/下に自分のhalコードの保存経路を作成します.例えば、led.
最終的に作成されたファイルは、安卓源コードルートディレクトリ/hardware/libhardware/modules/led_hal.cとAndroid.mkと、Androidコードのルートディレクトリ/hadware/libhardware/include/hardware/led.h.
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define LOG_TAG "callon_led"
static int fd;
static int led_close(struct hw_device_t *device)
{
struct led_device_t* led = (struct led_device_t*)device;
free(led);
close(fd);
return 0;
}
int led_on(struct led_device_t* dev,int arg)
{
ioctl(fd,LED_ON,arg);
return 0;
}
int led_off(struct led_device_t* dev,int arg)
{
ioctl(fd,LED_OFF,arg);
return 0;
}
static struct led_device_t led_dev = {
.led_device = {
.tag = HARDWARE_DEVICE_TAG,
.close = led_close,
},
.set_on = led_on,
.set_off = led_off,
};
static int open_led(const struct hw_module_t* module, char const* name,
struct hw_device_t** device)
{
*device = &led_dev;
fd = open("/dev/callon_led",O_RDWR);
if(fd < 0)
{
ALOGD(LOG_TAG, "open device fail!");
return -1;
}
return 0;
}
static struct hw_module_methods_t led_methods = {
.open = open_led,
};
struct hw_module_t HAL_MODULE_INFO_SYM = {
.tag = HARDWARE_MODULE_TAG,
.id = "led",
.methods = &led_methods,
};
led.h#ifndef _HARDWARE_LED_H
#define _HARDWARE_LED_H
#include
#define LED_ON _IOW('G',0,int)
#define LED_OFF _IOW('G',1,int)
struct led_device_t {
struct hw_device_t led_device;
int (*set_on)(struct led_device_t* dev,int arg);//means led_number
int (*set_off)(struct led_device_t* dev,int arg);
};
#endif // _HARDWARE_LED_H
Android.mkLOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := led.default
# HAL module implementation stored in
# hw/.default.so
LOCAL_MODULE_RELATIVE_PATH := hw
LOCAL_C_INCLUDES := hardware/libhardware
LOCAL_SRC_FILES := led_hal.c
LOCAL_SHARED_LIBRARIES := liblog
LOCAL_MODULE_TAGS := eng
include $(BUILD_SHARED_LIBRARY)
コンパイルは 安卓源コードのルートディレクトリの下で使用します.$ . setenv
$ lunch
$ mmm hardware/libhardware/modules/led/
目に入るtarget SharedLib: led.default (out/target/product/tiny4412/obj/SHARED_LIBRARIES/led.default_intermediates/LINKED/led.default.so)
target Symbolic: led.default (out/target/product/tiny4412/symbols/system/lib/hw/led.default.so)
Export includes file: hardware/libhardware/modules/led/Android.mk -- out/target/product/tiny4412/obj/SHARED_LIBRARIES/led.default_intermediates/export_includes
target Strip: led.default (out/target/product/tiny4412/obj/lib/led.default.so)
Install: out/target/product/tiny4412/system/lib/hw/led.default.so
make: Leaving directory `/opt/Tiny4412/Android/android-5.0.2'
#### make completed successfully (1 seconds) ####
はい、最後に発生したのはout/target/product/iny 4412/system/lib/hw/led.default.soです.私たちはsystem.imgをやり直します.ここでスクリプトを通して完成します.
2.ハードウェアサービスの作成:
まず、Service Managerはアクセス衝突を解決するために存在します.Service Managerがある上に、私達の下の階は先にハードウェアサービスを作成して、Service Managerに登録しなければなりません.私達のアプリはService Managerを通じてサービスを取得し、下の階を操作することができます.
多くのディレクトリ操作に関連していますので、詳細な操作後は以下の通りです.
1.ILedService.aidlを作成する
フレームワーク/base/core/java/android/os/IVibrate Service.aidlに倣う
package android.os;
/** {@hide} */
インターフェース ILedService
{
int LedOpen();
int LedOn(int arg);
int LedOff(int arg);
}
2.フレームワーク/base/Android.mkを修正する増加
core/java/android/os/ILedService.aidl \
3.自動的にILedService.javaを生成するmmm frame eworks/base/コンパイル自動生成out/target/common/obj/JAVA_LIBREIES/frame ework_intermediates/src/core/java/android/os/ILedService.java
4.LedService.javaを作成し、インターフェース機能を実現する.
フレームワーク/base/services/core/java/com/android/server/Vibrator Servicer.javaを模倣します.
package com.android.server;
import android.util.Slog;
import android.os.ILedService;
public class LedService extends ILedService.Stub{
private static final String TAG = "LedService";
public LedService()
{
Slog.d(TAG,"LedService");
}
public int LedOpen() throws android.os.RemoteException
{
return native_LedOpen();
}
public int LedOn(int arg) throws android.os.RemoteException
{
return native_LedOn(arg);
}
public int LedOff(int arg) throws android.os.RemoteException
{
return native_LedOff(arg);
}
public static native int native_LedOpen();
public static native int native_LedOn(int arg);
public static native int native_LedOff(int arg);
}
5.サービスをService Managerに登録するframe eworks/base/services/java/com/android/server/SystemServer.javaを修正します.
vibratorの修正箇所を参考にしてください.
LedService led = null;
Slog.i(TAG, "Led Service");
led = new LedService();
ServiceManager.addService("led", led);
6.com_を実現するandroid_server_LedService.cppなぜそれが必要ですか?私たちのhalコードはjniのインターフェースを提供していませんから(ここではnative方法を提供するための新しい方法が提供されています.以前は自動的にヘッダファイルを生成してから実現します).
frame eworks/base/services/core/jni/com_android_server_Vibrate Service.cpp
/*
* Copyright (C) 2009 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, ソフトウェア
* 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.
*/
#define LOG_TAG "LedService"
#include "jni.h"
#include "JNIHelp.h"
#include "android_runtime/AndroidRuntime.h"
#include
#include
#include
#include
struct led_device_t *led_dev;
namespace android
{
static jint LedOpen(JNIEnv *env, jobject clazz)
{
hw_module_t *module;
hw_device_t *device;
hw_get_module("led",(hw_module_t const **)&module);
module->methods->open(module, NULL, &device);
led_dev = (struct led_device_t*)device;
return 0;
}
static jint LedOn(JNIEnv *env, jobject clazz, int arg)
{
led_dev->set_on(led_dev,arg);
return 0;
}
static jint LedOff(JNIEnv *env, jobject clazz, int arg)
{
led_dev->set_off(led_dev,arg);
return 0;
}
static JNINativeMethod method_table[] = {
{ "native_LedOpen", "()I", (void*)LedOpen },
{ "native_LedOn", "(I)I", (void*)LedOn },
{ "native_LedOff", "(I)I", (void*)LedOff}
};
int register_android_server_LedService(JNIEnv *env)
{
return jniRegisterNativeMethods(env, "com/android/server/LedService",
method_table, NELEM(method_table));
}
};
7.nativeインターフェースを登録するフレームワーク/base/services/core/jni/onload.cppに追加します.
int register_android_server_LedService(JNIEnv* env);
register_android_server_LedService(env);
8.Android.mkを修正するframe eworks/base/services/core/jni/Android.mkに自分の書いたcomを入れます.android_server_LedService.cpp
$(LOCAL_REL_DIR)/com_android_server_LedService.cpp \
9.mmm frame eworks/base/services/コンパイルCopying: out/target/common/obj/JAVA_LIBRARIES/services_intermediates/classes.dex
target Jar: services (out/target/common/obj/JAVA_LIBRARIES/services_intermediates/javalib.jar)
Install: out/target/product/tiny4412/system/framework/services.jar
make: Leaving directory `/opt/Tiny4412/Android/android-5.0.2'
#### make completed successfully (50 seconds) ####
中には間違いがありました.とても言葉がありません.make: Entering directory `/opt/Tiny4412/Android/android-5.0.2'
make: *** No rule to make target `frameworks/base/services/core/.java', needed by `out/target/common/obj/JAVA_LIBRARIES/services.core_intermediates/classes-full-debug.jar'. Stop.
make: Leaving directory `/opt/Tiny4412/Android/android-5.0.2'
#### make failed to build some targets (1 seconds) ####
直接に下のコンパイルをしないで、直接に間違いを報告して、とても探しにくい誤り、最後にLedService.javaのため発見します.ファイル名にスペースがあります.
.このようなミスが発生したら、忍耐強くしなければならない.
最後に引き続き使用します.
3.アプリケーション設計:
package com.led.hal.example.callon.callonhalled;
import android.os.RemoteException;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.CheckBox;
import android.os.ILedService;
import android.os.ServiceManager;
public class MainActivity extends AppCompatActivity {
private CheckBox[] Led = new CheckBox[4];
private ILedService iLedService = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Led[0] = (CheckBox)findViewById(R.id.checkbox_led1);
Led[1] = (CheckBox)findViewById(R.id.checkbox_led2);
Led[2] = (CheckBox)findViewById(R.id.checkbox_led3);
Led[3] = (CheckBox)findViewById(R.id.checkbox_led4);
iLedService = ILedService.Stub.asInterface(ServiceManager.getService("led"));
try {
iLedService.LedOpen();
}catch(RemoteException e){
e.printStackTrace();
}
}
private void SendCmd(View view)
{
for(int i =1; i<5; i++)
{
if(Led[i].isChecked()) {
try {
iLedService.LedOn(i);
}catch (RemoteException e){
e.printStackTrace();
}
}
else {
try {
iLedService.LedOff(i);
}catch (RemoteException e){
e.printStackTrace();
}
}
}
}
}
プログラムは簡単ですが、Androidの中に隠れている種類の使用に関しては、私達のILedServiceとServiceManagerは実はすべて隠し種類です.あなたがコンパイルできないなら、相応のjarパッケージを追加すればいいです.参考にしてください.http://blog.csdn.net/wukunting/article/details/5788196
まずout/target/comon/obj/JAVA_をコピーします.LIBREIES/frame ework_intermediat/classis.jarは工事の下に着きます.
その後、Android StudioでFile->Project Structureをクリックし、その中の'+'-'をクリックしてImport.JAR/.AAR Package-'を選択し、class.jar->Finishを選択します.
引き続きProject Structureの下でap->Dependencies->選択'+'->Module Dependency->選択'clases'を選択すればいいです.
この時点でソース全体が良くなりましたが、ダウンロード速度が遅くなります.frame ewarksに基づいて設計されたアプリのダウンロードと運行速度を改善する方案:
1.build.gradleを修正する(Module:app)
apply plugin: 'com.android.application'
android {
compileSdkVersion 23
buildToolsVersion "23.0.2"
defaultConfig {
applicationId "com.led.hal.example.callon.callonhalled"
minSdkVersion 21
targetSdkVersion 23
versionCode 1
versionName "1.0"
multiDexEnabled true
}
dexOptions {
javaMaxHeapSize "4g"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
testCompile 'junit:junit:4.12'
compile 'com.android.support:appcompat-v7:23.2.0'
compile project(':classes')
compile 'com.android.support:multidex:1.0.0'
}
2.Android Manifest.xmlを修正するアプリで追加
android:name=「android.support.multiide x.Multi DexAppliation」
最後にダウンロードして実行してください.