Implementing Google Play Application Silent Install Feature On Android - Android Software/Hacking General [Developers Only]

Hi Experts / Expert Hackers,
I'm trying to implement the Google Play application silent install feature (similar to appbrain fast web installer) on android.
So far I was able achieve the following :
1. Find out a method to retrieve the Google Play Auth Token (thus granting permission for my application to talk with Google Play application on the Phone). I've listed the code I've used for this below :
Code:
Log.i(TAG,"Getting the Google Play Auth Token Using Account Manager : START");
AccountManager accountManager = AccountManager.get(getApplicationContext());
Account[] accArr = accountManager.getAccountsByType("com.google");
for (Account acc : accArr) {
Log.i(TAG, "For Account Name : " + acc.name + " - "+ "Account Type : " + acc.type);
accountManager.getAuthToken(acc, "googleplay", null, this,new AccountManagerCallback<Bundle>() {
public void run(
AccountManagerFuture<Bundle> paramAccountManagerFuture) {
try {
Bundle localBundle = (Bundle) paramAccountManagerFuture.getResult();
String authToken = localBundle.get("authtoken") + "";
Log.i(TAG, "Got AuthToken : " + authToken);
} catch (Exception ex) {
StackTraceElement[] starray = ex.getStackTrace();
StringBuffer bf = new StringBuffer();
bf.append("Error : " + ex.getMessage()).append("\n");
for (StackTraceElement ste : starray) {
bf.append(ste.toString()).append("\n");
}
Log.e(TAG, bf.toString());
}
}
}, null);
}
Log.i(TAG,"Getting the Google Play Auth Token Using Account Manager : END");
2. Find out how to Retrieve the Android-Id of the Phone (This Id as I believe should be used when sending the appInstall request to the GPlay Servers or the Gplay/vending application on the android phone)
Code:
Log.i(TAG, "Getting the Android ID Of the Phone : START");
Uri localUri = Uri.parse("content://com.google.android.gsf.gservices");
ContentResolver localContentResolver = getContentResolver();
String[] arrayOfString = new String[1];
arrayOfString[0] = "android_id";
Cursor localCursor = localContentResolver.query(localUri, null,null, arrayOfString, null);
Log.i(TAG, "Column Count : " + localCursor.getColumnCount());
if ((localCursor != null) && (localCursor.moveToFirst())) {
String androidId = Long.toHexString(Long.parseLong(localCursor.getString(1)));
Log.i(TAG, "Received Android ID : " + androidId);
Log.i(TAG,"Other Value in Column : " + localCursor.getString(0));
}
Log.i(TAG,"Getting the Android ID of the Phone : END");
3. Find out the Protocol Buffer Request to be sent to the Google Play servers or the Gplay/vending application on the phone to Initiate the silent application download & install process.
Code:
message InstallRequest {
optional string appId = 1;
}
message RequestContext {
required string authSubToken = 1;
required bool isSecure = 2;
required int32 version = 3;
required string androidId = 4;
optional string deviceAndSdkVersion = 5;
optional string userLanguage = 6;
optional string userCountry = 7;
optional string operatorAlpha = 8;
optional string simOperatorAlpha = 9;
optional string operatorNumeric = 10;
optional string simOperatorNumeric = 11;
}
message Request {
optional RequestContext context = 1;
repeated group RequestGroup = 2 {
optional InstallRequest installRequest = 10;
}
}
4.I even used the protobuf compiler and generated the java class for manipulating the above protocol buffer request and filled the above protocol buffer fields with some sample data. See the code below :
Code:
public void buildAndSendSilentInstallProtoBuffMessage(String gplayAuthToken, String deviceAndroidId){
try{
/*
* The Root Request Object Assumed to be Holding the Silent Install Request
*/
Request.Builder request = Request.newBuilder();
//Populating the ReequestContext Object
RequestContext.Builder context = RequestContext.newBuilder();
context.setAndroidId(deviceAndroidId);
context.setAuthSubToken(gplayAuthToken);
context.setIsSecure(true);
context.setVersion(1002);
context.setDeviceAndSdkVersion("dream:4");
context.setUserLanguage("en");
context.setUserCountry("us");
context.setOperatorAlpha("Android");
context.setOperatorNumeric("310260");
context.setSimOperatorNumeric("310260");
//Building the Install Request
InstallRequest.Builder installRequest = InstallRequest.newBuilder();
installRequest.setAppId("-2564446724934482383");
//Setting the Install Request to the Request Group
RequestGroup.Builder requestGroup = RequestGroup.newBuilder();
requestGroup.setInstallRequest(installRequest);
//Setting the Request Context to the Main Request Object
request.setContext(context);
//Setting the Request Group to the Request Object
request.addRequestGroup(requestGroup);
The Sample Data for GPlay Token and the Android Id are as follows :
1. Android_ID :
3a0f901831a0f402
2. Google Play AuthToken :
DQAAAMgAAACpOyPf6apRbb0i4qhTVaf0yYoikTAb4TYlHCRLrW4mu5f14j-H35KGmO9TQKUDYCfj3-b-QIH5chfXT3bS02Uxljg7vYt4I-kgXLEJwPcynjugDcJ9fYPOh1c2FnOnywFXXxXw6hcqs5sVnJEt5zW2ditoB5VeeXG9Zfodj9dXKobObi50-XnHoGfWi2b64Uf3EHGdQTsDCMzfZrE4mb22fr9LCW1oZG5tkzwS4KhPBHWMN2fO7w-1IZ4UK5LOI80vPBLjxBaavKAXHoVUHSNV
5. I also did some sniffing using my rooted galaxy nexus phone during Gplay application silent install and found only two HTTP GET Requests.
I tried reproducing the those two Http GET requests captured using Shark for root(using my rooted android galaxy nexus phone) and the 1st Request just downloads the Market File itself (which I was able to save to the SD card of the Phone. But then it has to be installed like any unknown sources application) while the second request returns nothing.
The two get requests captured are shown below :
Code:
1. GET REQUEST ONE :
21 0.827240 192.168.135.102 173.194.36.4 HTTP 535 GET /market/download/Download?packageName=com.gau.go.launcherex.theme.appwidget.gopowermaster.futureworld&versionCode=1&token=AOTCm0QRnH3rmypWtCGoAL_SU1BSt311wpyz-_LZTodkUSAlc-f5SrdMiz5WDRDUKMMm6S3plBI9Jbh1tukT1jyCYXLgP4QhVvZvn5JLtZQ&downloadId=-165214892049282883 HTTP/1.1
Which has the following http headers :
Cookie: MarketDA=17214805622679635526\r\n
Host: android.clients.google.com\r\n
Connection: Keep-Alive\r\n
User-Agent: AndroidDownloadManager/4.1.1 (Linux; U; Android 4.1.1; Galaxy Nexus Build/JRO03C)\r\n
2. GET REQUEST TWO :
44 6.595093 192.168.135.102 222.165.163.15 HTTP 608 GET /market/GetBinary/com.gau.go.launcherex.theme.appwidget.gopowermaster.futureworld/1?expire=1346838270&ipbits=0&ip=0.0.0.0&cp=SnpybWlzSFk6OTYzMzg0MTE2NzA1ODEwOTYxMjE&sparams=expire,ipbits,ip,q:,cp&signature=2C0778C4635F6F8AE1DA8479FB08DCB9BC04C2E9.60202D8D4D2FDDA70609A3862A25852F0BAA2766&key=am2 HTTP/1.1
Which has the following http headers :
Cookie: MarketDA=17214805622679635526\r\n
Host: o-o.preferred.slt-cmb2.v12.lscache4.c.android.clients.google.com\r\n
Connection: Keep-Alive\r\n
User-Agent: AndroidDownloadManager/4.1.1 (Linux; U; Android 4.1.1; Galaxy Nexus Build/JRO03C)\r\n
I've been looking into this for about two weeks now but I still couldn't find the following :
1. Whether the AppBrain fast Web Installer uses the protocol buffer to invoke the Gplay (vending application) on the phone or the Gplay servers ?. If so is the above Protocol Buffer Request format correct ??.
2. If the Above Protocol Buffer Request format is correct then to Where in the Phone or Gplay server should I send the Protocol buffer request to to invoke the Silent Application download and installing procedure ?.
I also have a C2DM (now GCM) server and client setup around this task as well. Could anyone point me in the correct direction or give me any clues for solving this ?. Any help is much appreciated .

Seriously No one ???. I thought this forum has some expert hackers . Where are those so called android hackers anyways ??. Please guys I need help on this and it's urgent .

Hello. How you login into google play with token from account manager? Thanks.

Related

[Resolved] [Q][DEV]Android Development Question about Shared Preferences.

Hi, I'm trying to do a simple login with Facebook in my app but I'm having trouble with Shared Preferences.
The idea is to start the app, it opens Activity A, checks if it's logged, and if it isn't, it sends you to activity B, you login and then go back to A.
My problem is that I can't get the SharedPreferences. I can save it, but I can't get it in the other activity.
So, it gets in a loop: A can't get the SP, so thinks it's not logged in, so send you to B, but B is logged on, and sends you to A...
That's my code in B:
Code:
public void onComplete(Bundle values) {
// TODO Auto-generated method stub
Editor edit = fbSP.edit();
edit.putString("access_token", fb.getAccessToken());
edit.putLong("access_expires", fb.getAccessExpires());
edit.commit();
aIMG();
ir();
}
And that's my code in A, where the problem is:
Code:
private SharedPreferences prefs;
public static String TOKEN = null;
public static final String FACEBOOK_DATA = "FacebookStuff";
long EXPIRES = 0;
...
private void SharedP() {
// TODO Auto-generated method stub
prefs = getSharedPreferences(FACEBOOK_DATA, MODE_PRIVATE);
TOKEN = prefs.getString("access_token", null);
EXPIRES = prefs.getLong("access_expires", 0);
if (TOKEN == null && EXPIRES == 0) { //If it's not logged in...
Intent login = new Intent("android.intent.action.FACELOGIN");
startActivity(login);
}
}
Edit: I got it. I was iniciating fbSP with getPreferences, not getSharedPreferences.

SMS AT commands doesnt work on my android device C++ | Bluetooth | winsock

Hi there!
I'm creating windows application in C++, which connect's PC with mobile via bluetooth and winsock. Allow's you to call and send messages from mobile via computer.
I'm using AT command's to tell mobile what i want to do. Pair with mobile device and force a call with At command
ATD+420******;
works perfect, but all commands for handling SMS like
AT+CMGL, AT+CMGF, AT+CMGS etc.
return's ERROR.
Here is code which connects PC with mobile via bluetooth and socket:
SOCKADDR_BTH RemoteEndPoint;
RemoteEndPoint.port = 0;
RemoteEndPoint.addressFamily = AF_BTH;
RemoteEndPoint.btAddr = m_foundDevices[m_deviceIndex].Address.ullLong;
RemoteEndPoint.serviceClassId = HandsfreeServiceClass_UUID;
int BTHAddrLength = sizeof(RemoteEndPoint);
// Create the socket.
if ((m_localSocket = socket(AF_BTH, SOCK_STREAM, BTHPROTO_RFCOMM)) == INVALID_SOCKET)
{
// handle error.
}
// Connect the socket.
if ((iResult = connect(m_localSocket, (SOCKADDR *)&RemoteEndPoint, sizeof(RemoteEndPoint))) == INVALID_SOCKET)
{
// handle error.
}
Notice line
Hide Copy Code
RemoteEndPoint.serviceClassId = HandsfreeServiceClass_UUID
I think the problem is here, becouse u cant send sms from Handsfree, but when i use another UUID, it doesnt even pair with mobile.
=== Here is just for info, how am i sending and receiving data from mobile ===
char recvbuf[DEFAULT_BUFLEN] = "";
const char *sendbuf = "AT+CMGL\r";
int len = (int)strlen(sendbuf);
if ((iResult = send(m_localSocket, sendbuf, len, MSG_OOB)) == SOCKET_ERROR)
{
// handle error. return ~0
}
if ((iResult = recv(m_localSocket, recvbuf, recvbuflen, 0)) == SOCKET_ERROR)
{
// handle error. return ~0
}
// Here recvbuf == "\r\nERROR\r\n"
Thank you for any advices! If you have any question's about problem, i'll kindly explain.
Regards,
Ferina.

How and where my device store fingerprint results and matches with my next attempt ?

MAIN QUESTION IS AT BOTTOM
Where my android devices stores scanned fingerprint data and in what format and how it matches with new scanned.
I also know this: :the scan of fingertip is analysed for certain control points and generates a token which is like a password hash.
It generates hash via this:
Code:
KeyStore mKeyStore;
String KEY_NAME = UUID.randomUUID().toString();
Cipher mCipher;
mKeyStore = KeyStore.getInstance("AndroidKeyStore");
keyGenerator = KeyGenerator.getInstance(KeyProperties.KEY_ALGORITHM_AES, "AndroidKeyStore");
keyGenerator.init(new
KeyGenParameterSpec.Builder(KEY_NAME,
KeyProperties.PURPOSE_ENCRYPT |
KeyProperties.PURPOSE_DECRYPT)
.setBlockModes(KeyProperties.BLOCK_MODE_CBC)
.setUserAuthenticationRequired(true)
.setEncryptionPaddings(
KeyProperties.ENCRYPTION_PADDING_PKCS7)
.build());
keyGenerator.generateKey();
mCipher = Cipher.getInstance(
KeyProperties.KEY_ALGORITHM_AES + "/"
+ KeyProperties.BLOCK_MODE_CBC + "/"
+ KeyProperties.ENCRYPTION_PADDING_PKCS7);
SecretKey key = (SecretKey) mKeyStore.getKey(KEY_NAME, null);
mCipher.init(Cipher.ENCRYPT_MODE, key);
Is editing/extracting or using this hash and storing somewhere else and try to match the newly generated hash with this while storing that security key of android(assuming same for all), is it possible OR ANY OTHERWAY ROUND?
ALSO
Code:
KeyStore ks = KeyStore.getInstance("AndroidKeyStore");
ks.load(null);
KeyStore.Entry entry = ks.getEntry(alias, null);
if (!(entry instanceof PrivateKeyEntry)) {
Log.w(TAG, "Not an instance of a PrivateKeyEntry");
return null;
}
Signature s = Signature.getInstance("SHA256withECDSA");
s.initSign(((PrivateKeyEntry) entry).getPrivateKey());
s.update(data);
byte[] signature = s.sign();
boolean valid = s.verify(signature);
I saw this, but can't say helpful or not

MMS to iPhone different behavior...

private static final String TEXT_PART_FILENAME = "notify.htm";
private static final String sSmilText =
"<smil>" +
"<head>" +
"<layout>" +
"<root-layout/>" +
"<region height=\"100%%\" id=\"Text\" left=\"0%%\" top=\"0%%\" width=\"100%%\"/>" +
"</layout>" +
"</head>" +
"<body>" +
"<par dur=\"8000ms\">" +
"<text src=\"%s\" region=\"Text\"/>" +
"</par>" +
"</body>" +
"</smil>";
PduBody body = new PduBody();
PduPart part = new PduPart();
// Set Charset if it's a text media.
part.setCharset(CharacterSets.UTF_8);
// Set Content-Type.
part.setContentType(ContentType.TEXT_HTML.getBytes());
// Set Content-Location
part.setContentLocation(TEXT_PART_FILENAME.getBytes());
int index = TEXT_PART_FILENAME.lastIndexOf(".");
String contentId = (index == -1) ? TEXT_PART_FILENAME
: TEXT_PART_FILENAME.substring(0, index);
part.setContentId(contentId.getBytes());
part.setData("https://www.google.com".getBytes());
body.addPart(part);
final String smil = String.format(sSmilText, TEXT_PART_FILENAME);
addSmilPart(body, smil);
// added some gif data as well...omitted for brevity.
private static void addSmilPart(PduBody pb, String smil) {
final PduPart smilPart = new PduPart();
smilPart.setContentId("smil".getBytes());
smilPart.setContentLocation("smil.xml".getBytes());
smilPart.setContentType(ContentType.APP_SMIL.getBytes());
smilPart.setData(smil.getBytes());
pb.addPart(0, smilPart);
}
Above is some code I found from some web site..and I tested it..then it is working fine...
When I sent MMS to an android phone, I see the clickable http link, "https://www.google.com".........
However, when I sent the same one to an iPhone user, then...they received "notify.htm" like an attachment..then they needed to tap the file..then they saw the clickable link to navigate...
Is there any way I could change somehow this code so that I could provide the same behavior like an Android user for an iPhone user as well?.. I don't want to send like an attached file..
Thanks,
P.s : BTW, I am not sure whether I am posting this under right category. If not, admin, could you please move this to the right category?

Software Development Developing an OBD2/Canbus data logger

So I wanted to implement something like TeslaMate for my UIS7862. The idea being to be able to visualize trips, and various vehicle stats from Grafana (and maybe a live location tracker).
My original plan was to use TorquePro to log vehicle stats + GPS location, and then to send those logs to a listening webserver for storage in Prometheus and display via Grafana. I found an Automate script to hook this into HomeAssistant here: here. However, I wanted a few additional items:
I don't have a SIM card in my radio and do not normally have it connected to my phone as a hotspot, so internet connection is intermittent and I didn't want to lose data
I wanted to be able to upload to different IP addresses depending on whether I'm connected to the home network (i.e. at home) or otspot (i.e I'm driving)
I wanted to be able to store stats from the media canbus (like fuel level) that don't seem to be available on OBD-II (at least I haven't found them for my GTI)
I wanted to learn Kotlin and write a 'real' Android app
I was successful in writing an app that would send all unsent Torque data to my home server once it connects via wifi (basically reproducing Rob's Automate script), but getting the canbus data out of the radio required more work.
I decompiled 190000000_com.syu.canbus.apk and set about learning how it worked, and trying to connect my own app.
What I found so far:
Unlike the MKC/D units which appear to communicate with the canbus module via a serial port, the FYT radios seem to use I2C
The com.syu.ms.apk is responsible for the hardware communication
the com.syu.canbus.apk connects to the com.syu.ms.toolkit Intent to access hardware data.
This Service provides a getRemoteModule() procedure which seems to provide 4 different interfaces:
0: the 'Main' interface
4: the Sound interface
7: the Canbus interface
14: the 'CanUp' interface (no idea what this is)
each interface (IRemoteModule) provides 4 commands: cmd, get, register, unregister
The 'register' command registers a callback to a specific ID. That callback will be called when the value at the ID changes.
For instance, on my GTI, ID '6' of the canbus module is the fuel-level. I can register a callback at ID=6, and that callback will be called whenever the value changes
I haven't spent time to look at the other modules, nor what the 'get' or 'cmd' functions do
With the above, I now have a rudimentay application that will fetch the Fuel level from the radio (via the Canbox). My plan is to incorporate this with the OBDII capture to create a composte data-set to upload to my prometheus database. Interestingly, the com.syu.ms.toolbox only responds back to me if I use the 'com.syu.ipc.[IModuleCallback|IRemoteModule|IRemoteToolkit' descriptor.
I will make everything above available on GitHub once I've cleaned it up a bit. It should be possible to extract any canbus data the radio has (along with other internal state depending on what the other modules expose). However, what I've learned is that every CanBox has a different interface and presents diferent data, so the effort to make a generic interface would be very high and beyond the scope of what I plan to do. There are about 2500 unique CanBoxes listed in FinalCanbus. I see about 600 unique classes implementing these modules, each of which implements a different set of registerable IDs.
I plan to add an interface to register any ID if you know what you are looking for to my app. I think @surfer63 could do the same to FytHwOneKey if they were so inclined, but without a table of which features are available it would only likely benefit programmers.
I'll update this post with a GitHub link once available, but I thought there might be some interest in the canbus analysis stuff.
Here is the GitHub repository for the Canbus access library: https://github.com/AxesOfEvil/FYTCanbusMonitor
The CanBox ID is specified by ID=1000.
The low 16 bits appear to specify the canbox type, and the upper 16bits seem to represent the car make/model. This mapping happens in syu.ms.module.canbus.HandlerCanbus with the name mapping in module.canbus.FinalCanbus
Here is an example of the IDs for (some) Reise RZS CanBox to give an idea of what type of data is available:
Code:
U_CUR_OIL_EXPEND 0
U_MISC_BEGIN 0
U_LOW_OIL_WARN 1
U_LOW_BATTERY_WARN 2
U_LIFE_BELT_WARN 3
U_CLEAN_FLUIT_WARN 4
U_HANDLE_BRAKE_WARN 5
U_RESIDUAL_OIL 6
U_BATTERY_VOLTAGE 7
U_DRIVE_MILE 8
U_PARK 9
U_RADAR_MUTE 10
U_CUR_SPEED 11
U_ENGINE_SPEED 12
U_OUT_TEMP 13
U_AIR_BEGIN 14
U_AIR_POWER 14
U_MISC_END 14
U_AIR_BIG_WIND_LIGHT 15
U_AIR_LITTLE_WIND_LIGHT 16
U_AIR_AC 17
U_AIR_MAX 18
U_AIR_CYCLE 19
U_AIR_DUAL 20
U_AIR_REAR 21
U_AIR_BLOW_UP 22
U_AIR_BLOW_BODY 23
U_AIR_SHOW 24
U_AIR_BLOW_FOOT 25
U_AIR_WIND_LEVEL 26
U_AIR_TEMP_LEFT 27
U_AIR_TEMP_RIGHT 28
U_AIR_AQS 29
U_AIR_SEAT_HEAT_LEFT 30
U_AIR_REAR_LOCK 31
U_AIR_AC_MAX 32
U_AIR_SEAT_HEAT_RIGHT 33
U_AIR_TEMP_OUT 34
U_AIR_AUTO 35
U_AIR_END 36
U_DOOR_BEGIN 37
U_DOOR_ENGINE 37
U_DOOR_FL 38
U_DOOR_FR 39
U_DOOR_RL 40
U_DOOR_RR 41
U_DOOR_BACK 42
U_DOOR_END 43
U_AIR_FRONT 44
U_AIR_BLOW_MODE 45
U_CNT_MAX 46
AxesofEvil said:
I plan to add an interface to register any ID if you know what you are looking for to my app. I think @surfer63 could do the same to FytHwOneKey if they were so inclined, but without a table of which features are available it would only likely benefit programmers.
Click to expand...
Click to collapse
Nice work you are doing here.
But I do not know what you mean with above statement.
For further reading: lbdroid did some reverse engineering in 2006.
You might take a look at some of his repos: https://github.com/lbdroid/MCUd
In that github/readme are 5 other repos. They are outdated, but might still give you some clues.
surfer63 said:
Nice work you are doing here.
But I do not know what you mean with above statement.
For further reading: lbdroid did some reverse engineering in 2006.
You might take a look at some of his repos: https://github.com/lbdroid/MCUd
In that github/readme are 5 other repos. They are outdated, but might still give you some clues.
Click to expand...
Click to collapse
Sorry, maybe that was inappropriate. I guess I was thinking about ways to give users access to the canbox data since Tasker doesn't seem able to hook into services this way. One use case would be direct access to steering wheel buttons from the canbox (my understanding is that in some cases FwHwOneKey can't handle canbus related buttons...maybe I'm wrong). Or, perhaps there isn't really any use at all for this info to trigger user applications.
I know there was a request to access Canbox data for widgets (for instance to be able to display the outside temperature on a custom screen). This method should be able to support something like that, but I have no idea if there is an existing app that could make use of it. Maybe I could write a proxy that would turn service updates into system broadcast events? Just spitballing here.
Wow, it’s really communicate with canbus from user apps?
May be there is way to read can data, like we can see in develop mode
Sdese2000 said:
Wow, it’s really communicate with canbus from user apps?
May be there is way to read can data, like we can see in develop mode
Click to expand...
Click to collapse
To be clear, I only have access to whatever the canbox has already decoded (and the radio has accepted), at least on my vehicle, thee is a lot more CAN traffic that is ignored. What CAN data do you see in develop mode? I am not aware of this.
AxesofEvil said:
Sorry, maybe that was inappropriate. I guess I was thinking about ways to give users access to the canbox data since Tasker doesn't seem able to hook into services this way. One use case would be direct access to steering wheel buttons from the canbox (my understanding is that in some cases FwHwOneKey can't handle canbus related buttons...maybe I'm wrong). Or, perhaps there isn't really any use at all for this info to trigger user applications.
Click to expand...
Click to collapse
Not inappropiate at all. I just didn't get what you meant.
And yes: The BT like commands are still a big misunderstanding (for me that is). I think that could very well be a combi of activity, canbus and "something else"
But as my unit doesn't have buttons anymore, and neither my previous one, I don't spend time on my own app anymore.
AxesofEvil said:
To be clear, I only have access to whatever the canbox has already decoded (and the radio has accepted), at least on my vehicle, thee is a lot more CAN traffic that is ignored. What CAN data do you see in develop mode? I am not aware of this.
Click to expand...
Click to collapse
In Head Unit settings there is trigger, if turn on it, can logs will appear on the screen.
If found some code in com/syu/util/DebugViev.jave that provide it
Spoiler
package com.syu.util;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.support.p000v4.internal.view.SupportMenu;
import android.view.View;
import android.view.WindowManager;
import java.util.Locale;
public class DebugView extends View {
private int CELL_HEIGHT = 35;
int[] COLOR = {SupportMenu.CATEGORY_MASK, -1, -16711936, -256, -16776961};
private final int MAX = 16;
private final int TEXT_SIZE = 23;
/* access modifiers changed from: private */
public int[] mColors = new int[16];
/* access modifiers changed from: private */
public int mCount;
private boolean mDbg = false;
/* access modifiers changed from: private */
public int mLastIndex;
private WindowManager.LayoutParams mLp = ToolkitApp.buildOverlayLayoutParams(-1, -1);
/* access modifiers changed from: private */
public int mMsgCnt;
/* access modifiers changed from: private */
public String[] mMsgs = new String[16];
private Paint mPaint = new Paint();
public DebugView(Context context) {
super(context);
init();
}
private void init() {
this.mPaint.setAntiAlias(true);
this.mPaint.setTextSize(23.0f);
this.mPaint.setColor(-1);
}
public void setDbg(boolean flag) {
this.mDbg = flag;
}
public boolean isDbg() {
return this.mDbg;
}
public WindowManager.LayoutParams getWindowLayoutParams() {
return this.mLp;
}
public void msg(String msg) {
if (this.mDbg && msg != null) {
HandlerUI.getInstance().post(new MessageHelper(msg));
}
}
public void msg2(String msg) {
if (this.mDbg && msg != null) {
HandlerUI.getInstance().post(new MessageHelper(msg));
}
}
public void msgHex(String str, byte[] data, int start, int length) {
if (this.mDbg && data != null) {
if (data.length - start < length) {
length = data.length - start;
}
String msg = String.valueOf(str) + " * ";
for (int i = 0; i < length; i++) {
String c = Integer.toHexString(data[start + i] & 255).toUpperCase(Locale.CHINA);
if (c.length() < 2) {
c = "0" + c;
}
msg = String.valueOf(msg) + c + " ";
}
HandlerUI.getInstance().post(new MessageHelper(msg));
}
}
public void msgHex(String str, int[] data, int start, int length) {
if (this.mDbg && data != null) {
if (data.length - start < length) {
length = data.length - start;
}
String msg = String.valueOf(str) + " * ";
for (int i = 0; i < length; i++) {
String c = Integer.toHexString(data[start + i] & 255).toUpperCase(Locale.CHINA);
if (c.length() < 2) {
c = "0" + c;
}
msg = String.valueOf(msg) + c + " ";
}
HandlerUI.getInstance().post(new MessageHelper(msg));
}
}
private class MessageHelper implements Runnable {
private String mMessage;
public MessageHelper(String msg) {
this.mMessage = msg;
}
public void run() {
DebugView debugView = DebugView.this;
debugView.mLastIndex = debugView.mLastIndex + 1;
DebugView debugView2 = DebugView.this;
debugView2.mCount = debugView2.mCount + 1;
if (DebugView.this.mLastIndex > 15) {
DebugView.this.mLastIndex = 0;
}
if (DebugView.this.mCount > 16) {
DebugView.this.mCount = 16;
}
DebugView debugView3 = DebugView.this;
debugView3.mMsgCnt = debugView3.mMsgCnt + 1;
DebugView.this.mMsgs[DebugView.this.mLastIndex] = String.format("%06d @ %s", new Object[]{Integer.valueOf(DebugView.this.mMsgCnt), this.mMessage});
DebugView.this.mColors[DebugView.this.mLastIndex] = DebugView.this.COLOR[DebugView.this.mLastIndex % DebugView.this.COLOR.length];
DebugView.this.invalidate();
}
}
/* access modifiers changed from: protected */
public void onDraw(Canvas canvas) {
if (this.mCount != 0) {
int count = this.mCount;
int firstIndex = (this.mLastIndex - count) + 1;
if (firstIndex < 0) {
firstIndex += 16;
}
if (firstIndex + count > 16) {
int rightCount = 16 - firstIndex;
int leftCount = count - rightCount;
for (int i = 0; i < rightCount; i++) {
int index = firstIndex + i;
this.mPaint.setColor(this.mColors[index]);
canvas.drawText(this.mMsgs[index], (float) 5, (float) ((i + 1) * this.CELL_HEIGHT), this.mPaint);
}
for (int i2 = 0; i2 < leftCount; i2++) {
this.mPaint.setColor(this.mColors[i2]);
canvas.drawText(this.mMsgs[i2], (float) 5, (float) ((rightCount + i2 + 1) * this.CELL_HEIGHT), this.mPaint);
}
return;
}
for (int i3 = 0; i3 < count; i3++) {
int index2 = firstIndex + i3;
this.mPaint.setColor(this.mColors[index2]);
canvas.drawText(this.mMsgs[index2], (float) 5, (float) ((i3 + 1) * this.CELL_HEIGHT), this.mPaint);
}
}
}
}
I have updated the OP with a link to the GitHub library (here). The library is not really meant to be used standalone, but instead to be incorporated into other projects. I haven't posted the code for the logger as there is still quite a bit more to do on that side.
The library repo does include an example application which will simply log every message received to the screen/logfile (in /Downloads). It is very inefficient since it just blindly asks for every possible ID regardless of whether it is actually available for a given CanBox or not, but is meant to give a quick idea of what data is available and a short example of how to use the library. The latest compiled APK can be found here: https://github.com/AxesOfEvil/FYTCanbusMonitor/releases
I found this interesting tidbit today:
It seems to be that arbitrary commands can be sent to the canbus through the radio via sys.ms by calling ToolkitDev.writeMcu(0xE3, PID, data-len, data0, data1, ...) (where data can be 1-8 bytes).
Edit: ToolkitDev.writeMcu(0xE3, ...) seems to write commands to the canbox module. As I don't have the source for teh module, I'm not sure how it handles these commands, but they don't g out verbatim on the canbus itself.
There is also ToolkitDev.writeCanbusDirect, but this may send commands via an OBDII dongle...Edit: this seems to just directly send raw commands to the CanBox. It is similar to the above but requires manually calculating the entire packet (including checksum)
I have not found a way to pass arbitrary data from an external app through an intent to allow other apps to send arbitrary canbus commands, but with a hacked syu.ms, it probably means I can eliminate the DynAudio AMP control box I had to make to get my audio working. And that with more hacking, it may be possible to send GPS directions and music info to the HUD.
AxesofEvil said:
The CanBox ID is specified by ID=1000.
The low 16 bits appear to specify the canbox type, and the upper 16bits seem to represent the car make/model. This mapping happens in syu.ms.module.canbus.HandlerCanbus with the name mapping in module.canbus.FinalCanbus
Here is an example of the IDs for (some) Reise RZS CanBox to give an idea of what type of data is available:
Code:
U_CUR_OIL_EXPEND 0
U_MISC_BEGIN 0
U_LOW_OIL_WARN 1
U_LOW_BATTERY_WARN 2
U_LIFE_BELT_WARN 3
U_CLEAN_FLUIT_WARN 4
U_HANDLE_BRAKE_WARN 5
U_RESIDUAL_OIL 6
U_BATTERY_VOLTAGE 7
U_DRIVE_MILE 8
U_PARK 9
U_RADAR_MUTE 10
U_CUR_SPEED 11
U_ENGINE_SPEED 12
U_OUT_TEMP 13
U_AIR_BEGIN 14
U_AIR_POWER 14
U_MISC_END 14
U_AIR_BIG_WIND_LIGHT 15
U_AIR_LITTLE_WIND_LIGHT 16
U_AIR_AC 17
U_AIR_MAX 18
U_AIR_CYCLE 19
U_AIR_DUAL 20
U_AIR_REAR 21
U_AIR_BLOW_UP 22
U_AIR_BLOW_BODY 23
U_AIR_SHOW 24
U_AIR_BLOW_FOOT 25
U_AIR_WIND_LEVEL 26
U_AIR_TEMP_LEFT 27
U_AIR_TEMP_RIGHT 28
U_AIR_AQS 29
U_AIR_SEAT_HEAT_LEFT 30
U_AIR_REAR_LOCK 31
U_AIR_AC_MAX 32
U_AIR_SEAT_HEAT_RIGHT 33
U_AIR_TEMP_OUT 34
U_AIR_AUTO 35
U_AIR_END 36
U_DOOR_BEGIN 37
U_DOOR_ENGINE 37
U_DOOR_FL 38
U_DOOR_FR 39
U_DOOR_RL 40
U_DOOR_RR 41
U_DOOR_BACK 42
U_DOOR_END 43
U_AIR_FRONT 44
U_AIR_BLOW_MODE 45
U_CNT_MAX 46
Click to expand...
Click to collapse
Where did these IDs come from? Did you find one for Illumination/Headlights?
The IDs came out of the source code for 190000000_com.syu.canbus.apk
The IDs are canbox and probably vehicle specific, so such info may be available, but you need to identify exactly what you are looking for.
Use JadX or BytecodeViewer or a similar application to analyze the apk file above, and look in app/src/main/java/module/canbus for the appropriate Canbox for your vehicle

Categories

Resources