diff options
author | Danny Baumann <dannybaumann@web.de> | 2016-11-23 10:12:35 +0100 |
---|---|---|
committer | Dan Pasanen <invisiblek@cyanogenmod.org> | 2016-11-25 22:00:39 -0600 |
commit | 512122a016488f71ca3f2868c5950229f8634648 (patch) | |
tree | b7e88d82988db613f2b77d194fdd23896d7c79fb | |
parent | 7a9c884f482fed0a105a61e61c4881dfd5657985 (diff) | |
download | frameworks_base-512122a016488f71ca3f2868c5950229f8634648.zip frameworks_base-512122a016488f71ca3f2868c5950229f8634648.tar.gz frameworks_base-512122a016488f71ca3f2868c5950229f8634648.tar.bz2 |
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
-rw-r--r-- | core/java/android/os/Build.java | 41 | ||||
-rw-r--r-- | core/java/com/android/internal/os/RuntimeInit.java | 2 |
2 files changed, 43 insertions, 0 deletions
diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java index 862f4c4..883977f 100644 --- a/core/java/android/os/Build.java +++ b/core/java/android/os/Build.java @@ -23,7 +23,11 @@ import com.android.internal.telephony.TelephonyProperties; import dalvik.system.VMRuntime; +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; import java.util.Objects; +import java.util.regex.Matcher; +import java.util.regex.Pattern; /** * Information about the current build, extracted from system properties. @@ -664,6 +668,7 @@ public class Build { /** The type of build, like "user" or "eng". */ public static final String TYPE = getString("ro.build.type"); + private static String TYPE_FOR_APPS = parseBuildTypeFromFingerprint(); /** Comma-separated tags describing the build, like "unsigned,debug". */ public static final String TAGS = getString("ro.build.tags"); @@ -690,6 +695,42 @@ public class Build { return finger; } + // Some apps like to compare the build type embedded in fingerprint + // to the actual build type. As the fingerprint in our case is almost + // always hardcoded to the stock ROM fingerprint, provide that instead + // of the actual one if possible. + private static String parseBuildTypeFromFingerprint() { + final String fingerprint = SystemProperties.get("ro.build.fingerprint"); + if (TextUtils.isEmpty(fingerprint)) { + return null; + } + Pattern fingerprintPattern = + Pattern.compile("(.*)\\/(.*)\\/(.*):(.*)\\/(.*)\\/(.*):(.*)\\/(.*)"); + Matcher matcher = fingerprintPattern.matcher(fingerprint); + return matcher.matches() ? matcher.group(7) : null; + } + + /** @hide */ + public static void adjustBuildTypeIfNeeded() { + if (Process.isApplicationUid(Process.myUid()) && !TextUtils.isEmpty(TYPE_FOR_APPS)) { + try { + // This is sick. TYPE is final (which can't be changed because it's an API + // guarantee), but we have to reassign it. Resort to reflection to unset the + // final modifier, change the value and restore the final modifier afterwards. + Field typeField = Build.class.getField("TYPE"); + Field accessFlagsField = Field.class.getDeclaredField("accessFlags"); + accessFlagsField.setAccessible(true); + int currentFlags = accessFlagsField.getInt(typeField); + accessFlagsField.setInt(typeField, currentFlags & ~Modifier.FINAL); + typeField.set(null, TYPE_FOR_APPS); + accessFlagsField.setInt(typeField, currentFlags); + accessFlagsField.setAccessible(false); + } catch (Exception e) { + // shouldn't happen, but we don't want to crash the app even if it does happen + } + } + } + /** * Ensure that raw fingerprint system property is defined. If it was derived * dynamically by {@link #deriveFingerprint()} this is where we push the diff --git a/core/java/com/android/internal/os/RuntimeInit.java b/core/java/com/android/internal/os/RuntimeInit.java index 3377189..45dac2f 100644 --- a/core/java/com/android/internal/os/RuntimeInit.java +++ b/core/java/com/android/internal/os/RuntimeInit.java @@ -114,6 +114,8 @@ public class RuntimeInit { /* set default handler; this applies to all threads in the VM */ Thread.setDefaultUncaughtExceptionHandler(new UncaughtHandler()); + Build.adjustBuildTypeIfNeeded(); + /* * Install a TimezoneGetter subclass for ZoneInfo.db */ |