androidでタッチパネルのキャリブレーションを実現

7530 ワード

http://loovle.iteye.com/blog/663457
一、タッチキャリブレーションアルゴリズム   タッチパネルキャリブレーション共通の方法.  (XL、YLはスクリーン座標、XT、YTはタッチパネル座標、)XL=XT*A+YT*B+C YL=XT*D+YT*E+F   具体的な計算は整数演算を希望するため、実際に保存されているABCDEFは整数であり、一つのパラメータDiv XL=(XT*A+YT*B+C)/Div YL=(YT*D+YT*E+F)/Div    TSLIBは以上の7つのパラメータABCDEF Divをpointercalファイルに保存します.キャリブレーションしないデータ:A=1、B=0、C=0、D=0、E=1、F=0、Div=1
A
B
C
D
E
F
Div
-411
37818
-3636780
-51325
39
4706584
65536
二、Android事件処理メカニズム    Androidイベントの着信はEventHubから始まり、EventHubはイベントの抽象構造であり、システム設備の運行状況を維持しています.デバイスタイプはKeyboard、TouchScreen、TraceBallを含みます.これはシステムが起動する時にopen_を通過します.device方法は、システムが提供する入力デバイスをこの抽象的な構造に追加し、すべての入力デバイスのファイル記述子を維持します.入力デバイスがキーボードであれば、キーのマッピング関係を変更します.また、getEventメソッドは、EventHubのデバイスファイル記述子に対して、poll操作などの侍駆動層イベントが発生し、発生したイベントがキーボードイベントであれば、Map関数を呼び出して、マッピングファイルに従って対応するキー値に変換し、スキャンコードとキーをKeyInputQue.frame orks/base/services/jniandroid_server_KeyInputQue.cpp    イベントの種類およびイベント値に基づいて判断処理を行い、このイベントに対応するデバイスの状態が変化し、対応するデバイスの記述構造を変更したかどうかを判断する.Windowmanagerはスレッドを作成し、このスレッドでイベントキューから発生したイベント(QueueuedEvent ev=mQueueue.getEvent()を読み取り、イベントタイプによって三つの種類に分けて処理します.イベントをBinderを通じてフォーカスのあるウィンドウアプリケーションに送信し、mQue.recycleEvent(ev)を呼び出して引き続きキーボードイベントの発生を待つ.タッチスクリーンイベントの場合は、イベントの種類(UP、DOWN、MOVE、OUTUSIDEなど)によって判断して処理します.例えば、Cancelやイベントを権限のある指定されたウィンドウに送信します.    移植方式のAndroid自体はタッチスクリーンキャリブレーションを持たない.Androidが取得したデータは、レポートを駆動する元のデータです.案1:TSLIBを移植し、TSLIBを介してpointercal較正パラメータファイルを生成する.案2:Androidフレーム層からOnTouchイベントを取得し、pointercal較正パラメータファイル方式を生成する.一:データの較正は駆動中に完了する.pointercalのパラメータデータを何らかの方法でドライバに伝えて校正します.案二:元の点を報告するために駆動し、元の点はフレーム層でブロックされた後、検証処理を行う.    TSLIB移植プロセスのソースコードを修正し、androidのファイル構造に適応します.Android.mkコンパイルオプションを設定し、生成ライブラリはアプリケーションです.etc/ts.co nf module_raw input src/tsuconfig.c.菗define TS_CONF"/system/etc/ts.com"src/tsuロード.module.cchar*plugin_directory="/system/lib/ts/plugins/"tests/fbutils.cchar*defaultfbdevice="/dev/graphics/fb 0"COPY ts.co nfから/system/etc/ts.com nf init.rc.mkdir/data/etc/pointercalまでtsuを通じてcalibrateはpointercalデータファイルを生成します.フレーム内でパラメータファイルを取得してAPKアプリケーションを作成し、tsuに倣う.calibrateの採点と各パラメータを計算し、pointercalフレームを生成し、InputDevive.javaでタッチスクリーンの元データをブロックしてpointercalパラメータをチェックしてから配布し、駆動内でタッチスクリーンキャリブレーションをinit.rcにeventを追加し、タッチスクリーンローディング後にpointercalパラメータを駆動に転送します.    結果-効果の詳細:    拡張init-proper_serivceシステムがサポートしている属性権限は、カスタマイズした特殊なシステム属性に対して権限を開放します.    カスタムシステム属性を使用して、init.rcにおけるon propertyイベントでpointercalの読み書き権限を処理します.    カスタムシステムのプロパティを使用して、タッチスクリーンを使ってプログラム.appkとInputDevice.javaの入力イベントの同期を較正します.(タッチスクリーンキャリブレーション中にinput Deviceは入力イベントでアルゴリズムを使用できません.キャリブレーションプログラムが完了したらinput Deviceでキャリブレーションアルゴリズムを再起動します.)    シミュレータの中では今までdevice.absX/Yに入れません.=nullのコードは、以下のinputDeviceで呼び出される手順を知る必要があります.タッチパネルの時間流れ:駆動層:   
Androidベースドライブ
EventHub.cpp

static const char *device_path = "/dev/input";

openPlatformInput(void)
  scan_dir(device_path);
    open_device(devname);
      fd = open(deviceName, O_RDWR);

/*
*     ,getEvent, 
* inotify   device_path  ,   poll     inotify             。          ,         。
*/
bool EventHub::getEvent(int32_t* outDeviceId, int32_t* outType,
        int32_t* outScancode, int32_t* outKeycode, uint32_t *outFlags,
        int32_t* outValue, nsecs_t* outWhen)

JNI   : com_android_server_KeyInputQueue.cpp.     

static JNINativeMethod gInputMethods[] = {
    /* name, signature, funcPtr */
    { "readEvent", "(Landroid/view/RawInputEvent;)Z",
            (void*) android_server_KeyInputQueue_readEvent },
    { "getDeviceClasses", "(I)I",
        (void*) android_server_KeyInputQueue_getDeviceClasses },
    { "getDeviceName", "(I)Ljava/lang/String;",
        (void*) android_server_KeyInputQueue_getDeviceName },
    { "getAbsoluteInfo", "(IILcom/android/server/InputDevice$AbsoluteInfo;)Z",
        (void*) android_server_KeyInputQueue_getAbsoluteInfo },
    { "getSwitchState", "(I)I",
        (void*) android_server_KeyInputQueue_getSwitchState },
    { "getSwitchState", "(II)I",
        (void*) android_server_KeyInputQueue_getSwitchStateDevice },
    { "getScancodeState", "(I)I",
        (void*) android_server_KeyInputQueue_getScancodeState },
    { "getScancodeState", "(II)I",
        (void*) android_server_KeyInputQueue_getScancodeStateDevice },
    { "getKeycodeState", "(I)I",
        (void*) android_server_KeyInputQueue_getKeycodeState },
    { "getKeycodeState", "(II)I",
        (void*) android_server_KeyInputQueue_getKeycodeStateDevice },
    { "hasKeys", "([I[Z)Z",
        (void*) android_server_KeyInputQueue_hasKeys },
};
java service部分:KeyInput Que.java.入力デバイス情報またはディレクトリの状態を巡回して調べて処理します.
Thread mThread = new Thread("InputDeviceReader") {
        public void run() {
            android.os.Process.setThreadPriority(
                    android.os.Process.THREAD_PRIORITY_URGENT_DISPLAY);
            
            try {
                RawInputEvent ev = new RawInputEvent();
                while (true) {
                    InputDevice di;

                    // block, doesn't release the monitor

                    readEvent(ev);

                    boolean send = false;
                    boolean configChanged = false;

......
                    

//       

if (ev.type == RawInputEvent.EV_DEVICE_ADDED) {
                        synchronized (mFirst) {
                            di = newInputDevice(ev.deviceId);
                            mDevices.put(ev.deviceId, di);
                            configChanged = true;
                        }
                    }

//      
InputDevice.AbsoluteInfo absX;
        InputDevice.AbsoluteInfo absY;
        InputDevice.AbsoluteInfo absPressure;
        InputDevice.AbsoluteInfo absSize;
        if ((classes&RawInputEvent.CLASS_TOUCHSCREEN) != 0) {
            absX = loadAbsoluteInfo(deviceId, RawInputEvent.ABS_X, "X");
            absY = loadAbsoluteInfo(deviceId, RawInputEvent.ABS_Y, "Y");
            absPressure = loadAbsoluteInfo(deviceId, RawInputEvent.ABS_PRESSURE, "Pressure");
            absSize = loadAbsoluteInfo(deviceId, RawInputEvent.ABS_TOOL_WIDTH, "Size");
        } else {
            absX = null;
            absY = null;
            absPressure = null;
            absSize = null;
        }
        
        return new InputDevice(deviceId, classes, name, absX, absY, absPressure, absSize);
  
タッチスクリーンに対するデータの修正は、InputDevice.javaでabsX、absY、abs Pressureに基づいています.nullの状態では、ドライバから絶対元のデータが送られてきたら、InputDevice.javaに転送して私達のキャリブレーションを経てからwindow Manager->activityにdispatchを出ます.これによりキャリブレーション効果が得られた.四、注意すべき補助はEventHubにおいて、タッチスクリーンのEVIOCGABS(axis)をIOCTLを使ってサンプリングし、コンテンツのstructを取り出すというものがあると説明しています.
input_absinfo info;
struct input_absinfo {
    __s32 value;
    __s32 minimum;
    __s32 maximum;
    __s32 fuzz;
    __s32 flat;
    __s32 resolution;
};

#define EVIOCGABS(abs)        _IOR('E', 0x40 + abs, struct input_absinfo)        /* get abs value/limits */
   
取り出したのはタッチパネルの最大値、最小値などで、これらの値はcom_にあります.android_server_KeyInputQue.cppではこれらの値をInputDevice.cppに伝えて使用します.つまり、報告された位置をアルゴリズムで絶対座標値に計算します.
scaledX = ((scaledX-device.absX.minValue)
                                / device.absX.range) * w;
もちろんXが発生したら、Y軸の反対や座標の逆などの問題はこの文を書き換えることで実際に操作できます.
転載先:https://www.cnblogs.com/yuzaipiaofei/archive/2011/09/28/4124319.html