[Android Head-Units] KID52:
I just used APK2Java and the results are promising.

Looking through "TWService.java" as you mentioned previously (I did look through the smali code and picked this up actually, but in Java it is much clearer), I found the following function.

private void e(int paramInt)
{
long l1 = SystemClock.uptimeMillis();
KeyEvent localKeyEvent1 = new KeyEvent(l1, l1, 0, paramInt, 0, 0, -1, 0, 72, 257);
InputManager.getInstance().injectInputEvent(localKeyEvent1, 0);
KeyEvent localKeyEvent2 = new KeyEvent(l1, l1, 1, paramInt, 0, 0, -1, 0, 72, 257);
InputManager.getInstance().injectInputEvent(localKeyEvent2, 0);
}

Which I believe corresponds to

KeyEvent(long downTime, long eventTime, int action, int code, int repeat, int metaState, int deviceId, int scancode, int flags, int source)

http://developer.android.com/reference/android/view/KeyEvent.html

Now I may be wrong, but that looks exactly like what we are looking for. However, what concerns me is that gives a code paramInt with no conditions, so surely that should mean whatever button is pressed, the KeyTest app should be picking it up, or am I missing something here?

Full code.

package com.tw.service;

import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.hardware.input.InputManager;
import android.location.LocationListener;
import android.location.LocationManager;
import android.media.AudioManager;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
import android.os.Looper;
import android.os.PowerManager;
import android.os.PowerManager.WakeLock;
import android.os.SystemClock;
import android.view.KeyEvent;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;
import java.io.File;
import java.io.IOException;

public class TWService extends Service
{
private static final int[] A;
private static final String[] B;
private static final int[] y;
private c C;
private b D;
private m E;
private f F;
private int G = 0;
private volatile Looper H;
private volatile a I;
private BroadcastReceiver J = new s(this);
private BroadcastReceiver K = new t(this);
private int L = 0;
private int M = 0;
private float N = 0.0F;
private LocationListener O;
final Object P = new Object();
ServiceConnection Q = null;
final Runnable R = new p(this);
private w j = null;
private int k = -1;
private int l = 0;
private int m = -1;
private AudioManager mAudioManager = null;
private Handler mHandler = new k(this);
private int mMode = 0;
private Toast mToast;
private int n = 0;
private int o = 0;
private int p = 0;
private int q = 0;
private int r = 2;
private int s = 0;
private int t = 14;
private int u = 11;
private int v = 14;
private ComponentName x = null;
private int z = 0;

static
{
int[] arrayOfInt1 = new int[7];
arrayOfInt1[0] = 2130968578;
arrayOfInt1[1] = 2130968579;
arrayOfInt1[2] = 2130968580;
arrayOfInt1[3] = 2130968581;
arrayOfInt1[4] = 2130968582;
arrayOfInt1[5] = 2130968583;
arrayOfInt1[6] = 2130968584;
y = arrayOfInt1;
int[] arrayOfInt2 = new int[3];
arrayOfInt2[0] = 2130968586;
arrayOfInt2[1] = 2130968587;
arrayOfInt2[2] = 2130968588;
A = arrayOfInt2;
String[] arrayOfString = new String[3];
arrayOfString[0] = "bl_0";
arrayOfString[1] = "bl_x";
arrayOfString[2] = "bl_f";
B = arrayOfString;
}

private void a()
{
if (w.aO == 32)
{
a("com.tw.usbipod_b542.apk");
if (w.aO != 48)
break label38;
a("com.tw.fuel_e595.apk");
}
while (true)
{
return;
c("com.tw.usbipod_b542.apk");
break;
label38: c("com.tw.fuel_e595.apk");
}
}

private void a(String paramString)
{
if ((!new File("/system/app/" + paramString).canRead()) && (new File("/system/etc/apk/" + paramString).canRead()))
b(paramString);
}

private void a(boolean paramBoolean)
{
if (paramBoolean)
a("com.tw.color_8f2a.apk");
while (true)
{
return;
c("com.tw.color_8f2a.apk");
}
}

private void b()
{
if ((!new File("/system/bin/gocsdk").canRead()) && (new File("/system/etc/goc/gocsdk").canRead()));
try
{
Runtime.getRuntime().exec("run-as john@tw-desktop.(none) busybox mount -o remount,rw /system").waitFor();
Runtime.getRuntime().exec("run-as john@tw-desktop.(none) ln /system/etc/goc/gocsdk /system/bin/gocsdk").waitFor();
Runtime.getRuntime().exec("run-as john@tw-desktop.(none) chown root.root /system/bin/gocsdk").waitFor();
Runtime.getRuntime().exec("run-as john@tw-desktop.(none) chmod 755 /system/bin/gocsdk").waitFor();
Runtime.getRuntime().exec("run-as john@tw-desktop.(none) ln /system/etc/goc/GocSdk.apk /system/app/GocSdk.apk").waitFor();
Runtime.getRuntime().exec("run-as john@tw-desktop.(none) chown root.root /system/app/GocSdk.apk").waitFor();
Runtime.getRuntime().exec("run-as john@tw-desktop.(none) chmod 644 /system/app/GocSdk.apk").waitFor();
Runtime.getRuntime().exec("run-as john@tw-desktop.(none) busybox mount -o remount,ro /system").waitFor();
label133: return;
}
catch (IOException localIOException)
{
break label133;
}
catch (InterruptedException localInterruptedException)
{
break label133;
}
}

private void b(String paramString)
{
try
{
Runtime.getRuntime().exec("run-as john@tw-desktop.(none) busybox mount -o remount,rw /system").waitFor();
Runtime.getRuntime().exec("run-as john@tw-desktop.(none) ln /system/etc/apk/" + paramString + " /system/app/" + paramString).waitFor();
Runtime.getRuntime().exec("run-as john@tw-desktop.(none) chown root.root /system/app/" + paramString).waitFor();
Runtime.getRuntime().exec("run-as john@tw-desktop.(none) chmod 644 /system/app/" + paramString).waitFor();
Runtime.getRuntime().exec("run-as john@tw-desktop.(none) busybox mount -o remount,ro /system").waitFor();
label125: return;
}
catch (IOException localIOException)
{
break label125;
}
catch (InterruptedException localInterruptedException)
{
break label125;
}
}

private void b(boolean paramBoolean)
{
if (paramBoolean)
b();
while (true)
{
return;
c();
}
}

private void c()
{
if (new File("/system/bin/gocsdk").canRead());
try
{
Runtime.getRuntime().exec("run-as john@tw-desktop.(none) busybox mount -o remount,rw /system").waitFor();
Runtime.getRuntime().exec("run-as john@tw-desktop.(none) rm /system/bin/gocsdk").waitFor();
Runtime.getRuntime().exec("run-as john@tw-desktop.(none) rm /system/app/GocSdk.apk").waitFor();
Runtime.getRuntime().exec("run-as john@tw-desktop.(none) busybox mount -o remount,ro /system").waitFor();
label66: return;
}
catch (IOException localIOException)
{
break label66;
}
catch (InterruptedException localInterruptedException)
{
break label66;
}
}

private void c(String paramString)
{
if (new File("/system/app/" + paramString).canRead())
d(paramString);
}

private void d()
{
synchronized (this.P)
{
if (this.Q == null)
{
ComponentName localComponentName = new ComponentName("com.android.systemui", "com.android.systemui.screenshot.TakeScreenshotService");
Intent localIntent = new Intent();
localIntent.setComponent(localComponentName);
r localr = new r(this);
if (bindService(localIntent, localr, 1))
{
this.Q = localr;
this.mHandler.postDelayed(this.R, 5000L);
}
}
}
}

private void d(String paramString)
{
try
{
Runtime.getRuntime().exec("run-as john@tw-desktop.(none) busybox mount -o remount,rw /system").waitFor();
Runtime.getRuntime().exec("run-as john@tw-desktop.(none) rm /system/app/" + paramString).waitFor();
Runtime.getRuntime().exec("run-as john@tw-desktop.(none) busybox mount -o remount,ro /system").waitFor();
label55: return;
}
catch (IOException localIOException)
{
break label55;
}
catch (InterruptedException localInterruptedException)
{
break label55;
}
}

private void e(int paramInt)
{
long l1 = SystemClock.uptimeMillis();
KeyEvent localKeyEvent1 = new KeyEvent(l1, l1, 0, paramInt, 0, 0, -1, 0, 72, 257);
InputManager.getInstance().injectInputEvent(localKeyEvent1, 0);
KeyEvent localKeyEvent2 = new KeyEvent(l1, l1, 1, paramInt, 0, 0, -1, 0, 72, 257);
InputManager.getInstance().injectInputEvent(localKeyEvent2, 0);
}

private void f(int paramInt)
{
PowerManager.WakeLock localWakeLock = ((PowerManager)getSystemService("power")).newWakeLock(6, B[paramInt]);
localWakeLock.acquire();
localWakeLock.release();
}

private void g(int paramInt)
{
switch (paramInt)
{
default:
case 2:
case 3:
case 9:
}
while (true)
{
this.j.write(65296, 0);
if (this.s != 0)
this.j.write(40456, 2);
try
{
Intent localIntent = new Intent(this, SRActivity.class);
localIntent.setFlags(268435456);
startActivity(localIntent);
label95: return;
if (this.s == 0)
this.j.write(65282, 129);
this.j.write(65282, 61);
continue;
this.j.write(40451, 2);
this.j.write(40451, 6);
continue;
this.j.write(40457, 2);
this.j.write(40457, 6);
}
catch (Exception localException)
{
break label95;
}
}
}

private void resume(int paramInt)
{
if (this.s != 0);
while (true)
{
return;
this.j.write(65296, 1);
if (this.l != 0)
continue;
switch (paramInt)
{
case 11:
case 12:
default:
break;
case 1:
this.j.write(33281, 1, 33);
break;
case 2:
this.j.write(33281, 1, 36);
break;
case 3:
if (this.G <= 0)
continue;
this.j.write(33281, 1, 41);
break;
case 4:
case 10:
this.j.write(33281, 1, 35);
break;
case 5:
this.j.write(33281, 1, 39);
break;
case 6:
case 7:
this.j.write(33281, 1, 40);
break;
case 8:
this.j.write(769, 192, 8);
break;
case 9:
if (this.G <= 0)
continue;
this.j.write(33281, 1, 42);
break;
case 13:
this.j.write(769, 192, 13);
}
}
}

public IBinder onBind(Intent paramIntent)
{
return null;
}

public void onCreate()
{
super.onCreate();
this.mToast = Toast.makeText(this, "", 0);
((TextView)this.mToast.getView().findViewById(16908299)).setTextSize(30.0F);
this.C = new c(this);
this.D = new b(this);
this.E = new m(this);
this.F = new f(this);
this.mAudioManager = ((AudioManager)getSystemService("audio"));
this.mAudioManager.setStreamVolume(3, this.t, 0);
this.mAudioManager.setStreamVolume(5, this.v, 0);
HandlerThread localHandlerThread = new HandlerThread("MediaScan", 11);
localHandlerThread.start();
this.H = localHandlerThread.getLooper();
this.I = new a(this, this.H);
this.j = w.h();
if (this.j != null)
{
IntentFilter localIntentFilter1 = new IntentFilter();
localIntentFilter1.addAction("android.intent.action.MEDIA_MOUNTED");
localIntentFilter1.addAction("android.intent.action.MEDIA_UNMOUNTED");
localIntentFilter1.addDataScheme("file");
registerReceiver(this.J, localIntentFilter1);
IntentFilter localIntentFilter2 = new IntentFilter();
localIntentFilter2.addAction("android.intent.action.TIME_SET");
localIntentFilter2.addAction("android.intent.action.TIMEZONE_CHANGED");
registerReceiver(this.K, localIntentFilter2);
this.j.addHandler("TWService", this.mHandler);
this.j.write(266, 255, 0);
this.j.write(40464, 1);
this.j.write(260, 255);
this.j.write(262, 255);
this.j.write(514, 3);
this.j.write(769, 255);
}
}

public void onDestroy()
{
this.mHandler.removeCallbacksAndMessages(null);
if (this.O != null)
{
((LocationManager)getSystemService("location")).removeUpdates(this.O);
this.O = null;
}
unregisterReceiver(this.K);
unregisterReceiver(this.J);
this.H.quit();
if (this.j != null)
{
this.j.removeHandler("TWService");
this.j.close();
this.j = null;
}
super.onDestroy();
}
}