android原始版本里是没有屏幕校准功能的,tp坐标到lcd坐标是完全按照线性关系来转换的。例如,tp坐标是(Xt ,Yt )分辨率是(Wt x Ht ),lcd坐标是(X,Y),分辨率是(W x H),则 X=(Xt *W)/Wt, Y=(Yt *H)/Ht 。但是一般触摸屏不是完全线性的,自然转换关系也就不一样了,好在有tslib,能帮我们解决这个问题。但是android里没有tslib,我们也不需要完全将tslib移植过来,只需要其中根据采样点生成转换矩阵的部分,这部分是由ts_calibrate.c文件中的perform_calibration()函数来实现的。所以只需要将该函数移植过来就可以。这里将该函数及用到的数据结构代码贴出来如下:
有了上面的基础,接下来就是将上面的代码移植到android中并在setting里面添加屏幕校准入口,要完成这些,需要修改的文件有:
1. frameworks/base/services/java/com/android/server/InputDevice.java
2. packages/apps/Settings/AndroidManifest.xml
3. packages/apps/Settings/res/xml/settings.xml
另外在Setting源码目录里再添加一个Calibration.java文件。
frameworks/base/services/java/com/android/server/InputDevice.java修改的地方如下(红色 表示添加,蓝色 表示删除):
public class InputDevice {
static final boolean DEBUG_POINTERS = false;
static final boolean DEBUG_HACKS = false;
/** Amount that trackball needs to move in order to generate a key event. */
static final int TRACKBALL_MOVEMENT_THRESHOLD = 6;
/** Maximum number of pointers we will track and report. */
static final int MAX_POINTERS = 10;
static final String CALIBRATION_FILE="/data/pointercal";
final int id;
final int classes;
final String name;
final AbsoluteInfo absX;
final AbsoluteInfo absY;
final AbsoluteInfo absPressure;
final AbsoluteInfo absSize;
....................
final AbsoluteInfo absX = device.absX;
final AbsoluteInfo absY = device.absY;
final AbsoluteInfo absPressure = device.absPressure;
final AbsoluteInfo absSize = device.absSize;
float tmpX = 0;
float tmpY = 0;
String prop = SystemProperties.get("sys.config.calibrate", "noset");
if ( !prop.equalsIgnoreCase("loaded") )
{
if ( prop.equalsIgnoreCase("start") )
{
TransformInfo.xs = 0;
TransformInfo.ys = 0;
}
else if ( prop.equalsIgnoreCase("done") )
{
readCalibrate();
}
if ( TransformInfo.xs == 0 && absX != null )
{
TransformInfo.x1 = w;
TransformInfo.y1 = 0;
TransformInfo.z1 = 0-absX.minValue*w;
TransformInfo.xs = absX.range;
}
if ( TransformInfo.ys == 0 && absY != null )
{
TransformInfo.x2 = 0;
TransformInfo.y2 = h;
TransformInfo.z2 = 0-absY.minValue*h;
TransformInfo.ys = absY.range;
}
SystemProperties.set("sys.config.calibrate", "loaded");
}
for (int i=0; i<numPointers; i++) {
final int j = i * MotionEvent.NUM_SAMPLE_DATA;
tmpX = reportData[j + MotionEvent.SAMPLE_X];
tmpY = reportData[j + MotionEvent.SAMPLE_Y];
if (absX != null ) {
reportData[j + MotionEvent.SAMPLE_X] =
((reportData[j + MotionEvent.SAMPLE_X]-absX.minValue)
/ absX.range) * w;
reportData[j + MotionEvent.SAMPLE_X] = (TransformInfo.x1 * tmpX + TransformInfo.y1 * tmpY + TransformInfo.z1) / TransformInfo.xs;
}
if (absY != null ) {
reportData[j + MotionEvent.SAMPLE_Y] =
((reportData[j + MotionEvent.SAMPLE_Y]-absY.minValue)
/ absY.range) * h;
reportData[j + MotionEvent.SAMPLE_Y] = (TransformInfo.x2 * tmpX + TransformInfo.y2 * tmpY + TransformInfo.z2) / TransformInfo.ys;
}
if (absPressure != null) {
reportData[j + MotionEvent.SAMPLE_PRESSURE] =
((reportData[j + MotionEvent.SAMPLE_PRESSURE]-absPressure.minValue)
/ (float)absPressure.range);
}
if (absSize != null) {
reportData[j + MotionEvent.SAMPLE_SIZE] =
((reportData[j + MotionEvent.SAMPLE_SIZE]-absSize.minValue)
/ (float)absSize.range);
}
..................................
static class AbsoluteInfo {
int minValue;
int maxValue;
int range;
int flat;
int fuzz;
};
static class TransformInfo {
static int x1;
static int y1;
static int z1;
static int x2;
static int y2;
static int z2;
static int xs;
static int ys;
};
InputDevice(int _id, int _classes, String _name,
AbsoluteInfo _absX, AbsoluteInfo _absY,
AbsoluteInfo _absPressure, AbsoluteInfo _absSize) {
id = _id;
classes = _classes;
name = _name;
absX = _absX;
absY = _absY;
absPressure = _absPressure;
absSize = _absSize;
TransformInfo.xs = 0;
TransformInfo.ys = 0;
readCalibrate();
}
static void readCalibrate(){
try {
FileInputStream is = new FileInputStream(CALIBRATION_FILE);
byte[] mBuffer = new byte[64];
int len = is.read(mBuffer);
is.close();
if (len > 0) {
int i;
for (i = 0; i < len; i++) {
if (mBuffer[i] == '/n' || mBuffer[i] == 0) {
break;
}
}
len = i;
}
StringTokenizer st = new StringTokenizer(new String(mBuffer, 0, len));
TransformInfo.x1 = Integer.parseInt(st.nextToken());
TransformInfo.y1 = Integer.parseInt(st.nextToken());
TransformInfo.z1 = Integer.parseInt(st.nextToken());
TransformInfo.x2 = Integer.parseInt(st.nextToken());
TransformInfo.y2 = Integer.parseInt(st.nextToken());
TransformInfo.z2 = Integer.parseInt(st.nextToken());
TransformInfo.xs = Integer.parseInt(st.nextToken());
TransformInfo.ys = TransformInfo.xs;
SystemProperties.set("sys.config.calibrate", "loaded");
} catch (java.io.FileNotFoundException e) {
Log.i("InputDevice", "calibration file not found exception");
} catch (java.io.IOException e) {
Log.i("InputDevice", "io exception");
} catch (java.lang.NumberFormatException e) {
Log.i("InputDevice", "number format exception");
}
}
};
packages/apps/Settings/AndroidManifest.xml文件修改地方如下:
<activity android:name=".fuelgauge.PowerUsageDetail"
android:label="@string/details_title">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<activity android:name="Calibration"
android:label="@string/screen_calibration_settings">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<receiver android:name=".widget.SettingsAppWidgetProvider" android:label="@string/gadget_title">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
packages/apps/Settings/res/xml/settings.xml文件修改地方如下:
<com.android.settings.IconPreferenceScreen
settings:icon="@drawable/ic_settings_date_time"
android:title="@string/date_and_time_settings_title">
<intent
android:action="android.intent.action.MAIN"
android:targetPackage="com.android.settings"
android:targetClass="com.android.settings.DateTimeSettings" />
</com.android.settings.IconPreferenceScreen>
<!-- touchscreen Calibration -->
<com.android.settings.IconPreferenceScreen
settings:icon="@drawable/ic_settings_privacy"
android:title="@string/screen_calibration_settings">
<intent
android:action="android.intent.action.MAIN"
android:targetPackage="com.android.settings"
android:targetClass="com.android.settings.Calibration"/>
</com.android.settings.IconPreferenceScreen>
<!-- About Device -->
<com.android.settings.IconPreferenceScreen
settings:icon="@drawable/ic_settings_about"
android:title="@string/about_settings">
<intent
android:action="android.intent.action.MAIN"
android:targetPackage="com.android.settings"
android:targetClass="com.android.settings.DeviceInfoSettings" />
</com.android.settings.IconPreferenceScreen>
Calibration.java文件代码如下