Skip to content

Commit 512122a

Browse files
maniac103invisiblek
authored andcommitted
Make Build.TYPE and Build.FINGERPRINT consistent for apps.
Some apps (namely Android Wear) like to do comparisons between TYPE and FINGERPRINT and throw errors on inconsistencies. As our fingerprints are almost always taken from stock ROMs, they don't really match our builds, causing said comparisons to fail. Avoid those failures by taking build type out of fingerprint for apps. Change-Id: I8e8db64de7ea224572ecb3695c85abea91e0e29f
1 parent 7a9c884 commit 512122a

File tree

2 files changed

+43
-0
lines changed

2 files changed

+43
-0
lines changed

core/java/android/os/Build.java

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,11 @@
2323

2424
import dalvik.system.VMRuntime;
2525

26+
import java.lang.reflect.Field;
27+
import java.lang.reflect.Modifier;
2628
import java.util.Objects;
29+
import java.util.regex.Matcher;
30+
import java.util.regex.Pattern;
2731

2832
/**
2933
* Information about the current build, extracted from system properties.
@@ -664,6 +668,7 @@ public static class VERSION_CODES {
664668

665669
/** The type of build, like "user" or "eng". */
666670
public static final String TYPE = getString("ro.build.type");
671+
private static String TYPE_FOR_APPS = parseBuildTypeFromFingerprint();
667672

668673
/** Comma-separated tags describing the build, like "unsigned,debug". */
669674
public static final String TAGS = getString("ro.build.tags");
@@ -690,6 +695,42 @@ private static String deriveFingerprint() {
690695
return finger;
691696
}
692697

698+
// Some apps like to compare the build type embedded in fingerprint
699+
// to the actual build type. As the fingerprint in our case is almost
700+
// always hardcoded to the stock ROM fingerprint, provide that instead
701+
// of the actual one if possible.
702+
private static String parseBuildTypeFromFingerprint() {
703+
final String fingerprint = SystemProperties.get("ro.build.fingerprint");
704+
if (TextUtils.isEmpty(fingerprint)) {
705+
return null;
706+
}
707+
Pattern fingerprintPattern =
708+
Pattern.compile("(.*)\\/(.*)\\/(.*):(.*)\\/(.*)\\/(.*):(.*)\\/(.*)");
709+
Matcher matcher = fingerprintPattern.matcher(fingerprint);
710+
return matcher.matches() ? matcher.group(7) : null;
711+
}
712+
713+
/** @hide */
714+
public static void adjustBuildTypeIfNeeded() {
715+
if (Process.isApplicationUid(Process.myUid()) && !TextUtils.isEmpty(TYPE_FOR_APPS)) {
716+
try {
717+
// This is sick. TYPE is final (which can't be changed because it's an API
718+
// guarantee), but we have to reassign it. Resort to reflection to unset the
719+
// final modifier, change the value and restore the final modifier afterwards.
720+
Field typeField = Build.class.getField("TYPE");
721+
Field accessFlagsField = Field.class.getDeclaredField("accessFlags");
722+
accessFlagsField.setAccessible(true);
723+
int currentFlags = accessFlagsField.getInt(typeField);
724+
accessFlagsField.setInt(typeField, currentFlags & ~Modifier.FINAL);
725+
typeField.set(null, TYPE_FOR_APPS);
726+
accessFlagsField.setInt(typeField, currentFlags);
727+
accessFlagsField.setAccessible(false);
728+
} catch (Exception e) {
729+
// shouldn't happen, but we don't want to crash the app even if it does happen
730+
}
731+
}
732+
}
733+
693734
/**
694735
* Ensure that raw fingerprint system property is defined. If it was derived
695736
* dynamically by {@link #deriveFingerprint()} this is where we push the

core/java/com/android/internal/os/RuntimeInit.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,8 @@ private static final void commonInit() {
114114
/* set default handler; this applies to all threads in the VM */
115115
Thread.setDefaultUncaughtExceptionHandler(new UncaughtHandler());
116116

117+
Build.adjustBuildTypeIfNeeded();
118+
117119
/*
118120
* Install a TimezoneGetter subclass for ZoneInfo.db
119121
*/

0 commit comments

Comments
 (0)