mirror of
https://github.com/YTVanced/VancedMicroG
synced 2024-11-13 06:25:06 +00:00
Add profile manager
This commit is contained in:
parent
6d45bfb7ed
commit
a7b2b7e3f8
18 changed files with 488 additions and 140 deletions
|
@ -1,62 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2013-2017 microG Project Team
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.microg.gms.common;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
|
||||
import java.util.Locale;
|
||||
import java.util.Random;
|
||||
|
||||
// TODO: Make flexible
|
||||
public class Build {
|
||||
public String board = android.os.Build.BOARD;
|
||||
public String bootloader = android.os.Build.BOOTLOADER;
|
||||
public String brand = android.os.Build.BRAND;
|
||||
public String cpu_abi = android.os.Build.CPU_ABI;
|
||||
public String cpu_abi2 = android.os.Build.CPU_ABI2;
|
||||
@TargetApi(21)
|
||||
public String[] supported_abis = android.os.Build.VERSION.SDK_INT >= 21 ? android.os.Build.SUPPORTED_ABIS : new String[0];
|
||||
public String device = android.os.Build.DEVICE;
|
||||
public String display = android.os.Build.DISPLAY;
|
||||
public String fingerprint = android.os.Build.FINGERPRINT;
|
||||
public String hardware = android.os.Build.HARDWARE;
|
||||
public String host = android.os.Build.HOST;
|
||||
public String id = android.os.Build.ID;
|
||||
public String manufacturer = android.os.Build.MANUFACTURER;
|
||||
public String model = android.os.Build.MODEL;
|
||||
public String product = android.os.Build.PRODUCT;
|
||||
public String radio = android.os.Build.RADIO;
|
||||
public String serial = generateSerialNumber(); // TODO: static
|
||||
public String tags = android.os.Build.TAGS;
|
||||
public long time = android.os.Build.TIME;
|
||||
public String type = android.os.Build.TYPE;
|
||||
public String user = android.os.Build.USER;
|
||||
public String version_codename = android.os.Build.VERSION.CODENAME;
|
||||
public String version_incremental = android.os.Build.VERSION.INCREMENTAL;
|
||||
public String version_release = android.os.Build.VERSION.RELEASE;
|
||||
public String version_sdk = android.os.Build.VERSION.SDK;
|
||||
public int version_sdk_int = android.os.Build.VERSION.SDK_INT;
|
||||
|
||||
private String generateSerialNumber() {
|
||||
String serial = "008741";
|
||||
Random rand = new Random();
|
||||
for (int i = 0; i < 10; i++)
|
||||
serial += Integer.toString(rand.nextInt(16), 16);
|
||||
serial = serial.toUpperCase(Locale.US);
|
||||
return serial;
|
||||
}
|
||||
}
|
|
@ -33,10 +33,6 @@ public class Utils {
|
|||
return Locale.getDefault(); // TODO
|
||||
}
|
||||
|
||||
public static Build getBuild(Context context) {
|
||||
return new Build();
|
||||
}
|
||||
|
||||
public static DeviceIdentifier getDeviceIdentifier(Context context) {
|
||||
return new DeviceIdentifier();
|
||||
}
|
||||
|
|
|
@ -0,0 +1,94 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2021, microG Project Team
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package org.microg.gms.profile
|
||||
|
||||
import android.annotation.TargetApi
|
||||
import android.content.Context
|
||||
import android.os.Build
|
||||
import kotlin.random.Random
|
||||
|
||||
object Build {
|
||||
@JvmField
|
||||
var BOARD: String? = null
|
||||
|
||||
@JvmField
|
||||
var BOOTLOADER: String? = null
|
||||
|
||||
@JvmField
|
||||
var BRAND: String? = null
|
||||
|
||||
@JvmField
|
||||
var CPU_ABI: String? = null
|
||||
|
||||
@JvmField
|
||||
var CPU_ABI2: String? = null
|
||||
|
||||
@JvmField
|
||||
@TargetApi(21)
|
||||
var SUPPORTED_ABIS: Array<String> = emptyArray()
|
||||
|
||||
@JvmField
|
||||
var DEVICE: String? = null
|
||||
|
||||
@JvmField
|
||||
var DISPLAY: String? = null
|
||||
|
||||
@JvmField
|
||||
var FINGERPRINT: String? = null
|
||||
|
||||
@JvmField
|
||||
var HARDWARE: String? = null
|
||||
|
||||
@JvmField
|
||||
var HOST: String? = null
|
||||
|
||||
@JvmField
|
||||
var ID: String? = null
|
||||
|
||||
@JvmField
|
||||
var MANUFACTURER: String? = null
|
||||
|
||||
@JvmField
|
||||
var MODEL: String? = null
|
||||
|
||||
@JvmField
|
||||
var PRODUCT: String? = null
|
||||
|
||||
@JvmField
|
||||
var RADIO: String? = null
|
||||
|
||||
@JvmField
|
||||
var SERIAL: String? = null
|
||||
|
||||
@JvmField
|
||||
var TAGS: String? = null
|
||||
|
||||
@JvmField
|
||||
var TIME: Long = 0L
|
||||
|
||||
@JvmField
|
||||
var TYPE: String? = null
|
||||
|
||||
@JvmField
|
||||
var USER: String? = null
|
||||
|
||||
object VERSION {
|
||||
@JvmField
|
||||
var CODENAME: String? = null
|
||||
|
||||
@JvmField
|
||||
var INCREMENTAL: String? = null
|
||||
|
||||
@JvmField
|
||||
var RELEASE: String? = null
|
||||
|
||||
@JvmField
|
||||
var SDK: String? = null
|
||||
|
||||
@JvmField
|
||||
var SDK_INT: Int = 0
|
||||
}
|
||||
}
|
|
@ -0,0 +1,231 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2021, microG Project Team
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package org.microg.gms.profile
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.ContentValues
|
||||
import android.content.Context
|
||||
import android.util.Log
|
||||
import org.microg.gms.settings.SettingsContract
|
||||
import org.microg.gms.settings.SettingsContract.Profile
|
||||
import org.xmlpull.v1.XmlPullParser
|
||||
import kotlin.random.Random
|
||||
|
||||
object ProfileManager {
|
||||
private const val TAG = "ProfileManager"
|
||||
const val PROFILE_REAL = "real"
|
||||
const val PROFILE_AUTO = "auto"
|
||||
const val PROFILE_NATIVE = "native"
|
||||
|
||||
private var initialized = false
|
||||
|
||||
private fun getProfileFromSettings(context: Context) = SettingsContract.getSettings(context, Profile.getContentUri(context), arrayOf(Profile.PROFILE)) { it.getString(0) }
|
||||
private fun getAutoProfile(context: Context): String {
|
||||
val profile = "${android.os.Build.DEVICE}_${android.os.Build.VERSION.SDK_INT}"
|
||||
if (hasProfile(context, profile)) return profile
|
||||
return PROFILE_NATIVE
|
||||
}
|
||||
|
||||
private fun getProfileResId(context: Context, profile: String) = context.resources.getIdentifier("${context.packageName}:xml/profile_$profile", null, null)
|
||||
private fun hasProfile(context: Context, profile: String): Boolean = getProfileResId(context, profile) != 0
|
||||
private fun getProfileData(context: Context, profile: String, realData: Map<String, String>): Map<String, String>? {
|
||||
try {
|
||||
if (profile in listOf(PROFILE_REAL, PROFILE_NATIVE)) return null
|
||||
val profileResId = getProfileResId(context, profile)
|
||||
if (profileResId == 0) return null
|
||||
val resultData = mutableMapOf<String, String>()
|
||||
resultData.putAll(realData)
|
||||
context.resources.getXml(profileResId).use {
|
||||
var next = it.next()
|
||||
while (next != XmlPullParser.END_DOCUMENT) {
|
||||
when (next) {
|
||||
XmlPullParser.START_TAG -> when (it.name) {
|
||||
"data" -> {
|
||||
val key = it.getAttributeValue(null, "key")
|
||||
val value = it.getAttributeValue(null, "value")
|
||||
resultData[key] = value
|
||||
Log.d(TAG, "Overwrite from profile: $key = $value")
|
||||
}
|
||||
}
|
||||
}
|
||||
next = it.next()
|
||||
}
|
||||
}
|
||||
for (entry in resultData) {
|
||||
Log.d(TAG, "<data key=\"${entry.key}\" value=\"${entry.value}\" />")
|
||||
}
|
||||
return resultData
|
||||
} catch (e: Exception) {
|
||||
Log.w(TAG, e)
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
private fun getActiveProfile(context: Context) = getProfileFromSettings(context).let { if (it != PROFILE_AUTO) it else getAutoProfile(context) }
|
||||
private fun getSerialFromSettings(context: Context): String? = SettingsContract.getSettings(context, Profile.getContentUri(context), arrayOf(Profile.SERIAL)) { it.getString(0) }
|
||||
private fun saveSerial(context: Context, serial: String) = SettingsContract.setSettings(context, Profile.getContentUri(context)) { put(Profile.SERIAL, serial) }
|
||||
|
||||
private fun randomSerial(template: String, prefixLength: Int = (template.length / 2).coerceAtMost(6)): String {
|
||||
val serial = StringBuilder()
|
||||
template.forEachIndexed { index, c ->
|
||||
serial.append(when {
|
||||
index < prefixLength -> c
|
||||
c.isDigit() -> '0' + Random.nextInt(10)
|
||||
c.isLowerCase() && c <= 'f' -> 'a' + Random.nextInt(6)
|
||||
c.isLowerCase() -> 'a' + Random.nextInt(26)
|
||||
c.isUpperCase() && c <= 'F' -> 'A' + Random.nextInt(6)
|
||||
c.isUpperCase() -> 'A' + Random.nextInt(26)
|
||||
else -> c
|
||||
})
|
||||
}
|
||||
return serial.toString()
|
||||
}
|
||||
|
||||
@SuppressLint("MissingPermission")
|
||||
private fun getProfileSerialTemplate(context: Context, profile: String): String {
|
||||
// Native
|
||||
if (profile in listOf(PROFILE_REAL, PROFILE_NATIVE)) {
|
||||
return kotlin.runCatching {
|
||||
if (android.os.Build.VERSION.SDK_INT >= 26) {
|
||||
android.os.Build.getSerial()
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}.getOrNull()?.takeIf { it != android.os.Build.UNKNOWN } ?: android.os.Build.SERIAL
|
||||
}
|
||||
|
||||
// From profile
|
||||
try {
|
||||
val profileResId = getProfileResId(context, profile)
|
||||
if (profileResId != 0) {
|
||||
context.resources.getXml(profileResId).use {
|
||||
var next = it.next()
|
||||
while (next != XmlPullParser.END_DOCUMENT) {
|
||||
when (next) {
|
||||
XmlPullParser.START_TAG -> when (it.name) {
|
||||
"serial" -> return it.getAttributeValue(null, "template")
|
||||
}
|
||||
}
|
||||
next = it.next()
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
Log.w(TAG, e)
|
||||
}
|
||||
|
||||
// Fallback
|
||||
return "008741A0B2C4D6E8"
|
||||
}
|
||||
|
||||
@SuppressLint("MissingPermission")
|
||||
private fun getEffectiveProfileSerial(context: Context, profile: String): String {
|
||||
getSerialFromSettings(context)?.let { return it }
|
||||
val serialTemplate = getProfileSerialTemplate(context, profile)
|
||||
val serial = when {
|
||||
profile == PROFILE_REAL && serialTemplate != android.os.Build.UNKNOWN -> serialTemplate
|
||||
else -> randomSerial(serialTemplate)
|
||||
}
|
||||
saveSerial(context, serial)
|
||||
return serial
|
||||
}
|
||||
|
||||
private fun getRealData(): Map<String, String> = mutableMapOf(
|
||||
"Build.BOARD" to android.os.Build.BOARD,
|
||||
"Build.BOOTLOADER" to android.os.Build.BOOTLOADER,
|
||||
"Build.BRAND" to android.os.Build.BRAND,
|
||||
"Build.CPU_ABI" to android.os.Build.CPU_ABI,
|
||||
"Build.CPU_ABI2" to android.os.Build.CPU_ABI2,
|
||||
"Build.DEVICE" to android.os.Build.DEVICE,
|
||||
"Build.DISPLAY" to android.os.Build.DISPLAY,
|
||||
"Build.FINGERPRINT" to android.os.Build.FINGERPRINT,
|
||||
"Build.HARDWARE" to android.os.Build.HARDWARE,
|
||||
"Build.HOST" to android.os.Build.HOST,
|
||||
"Build.ID" to android.os.Build.ID,
|
||||
"Build.MANUFACTURER" to android.os.Build.MANUFACTURER,
|
||||
"Build.MODEL" to android.os.Build.MODEL,
|
||||
"Build.PRODUCT" to android.os.Build.PRODUCT,
|
||||
"Build.RADIO" to android.os.Build.RADIO,
|
||||
"Build.SERIAL" to android.os.Build.SERIAL,
|
||||
"Build.TAGS" to android.os.Build.TAGS,
|
||||
"Build.TIME" to android.os.Build.TIME.toString(),
|
||||
"Build.TYPE" to android.os.Build.TYPE,
|
||||
"Build.USER" to android.os.Build.USER,
|
||||
"Build.VERSION.CODENAME" to android.os.Build.VERSION.CODENAME,
|
||||
"Build.VERSION.INCREMENTAL" to android.os.Build.VERSION.INCREMENTAL,
|
||||
"Build.VERSION.RELEASE" to android.os.Build.VERSION.RELEASE,
|
||||
"Build.VERSION.SDK" to android.os.Build.VERSION.SDK,
|
||||
"Build.VERSION.SDK_INT" to android.os.Build.VERSION.SDK_INT.toString()
|
||||
).apply {
|
||||
if (android.os.Build.VERSION.SDK_INT > 21) {
|
||||
put("Build.SUPPORTED_ABIS", android.os.Build.SUPPORTED_ABIS.joinToString(","))
|
||||
}
|
||||
}
|
||||
|
||||
private fun applyProfileData(profileData: Map<String, String>) {
|
||||
fun applyStringField(key: String, valueSetter: (String) -> Unit) = profileData[key]?.let { valueSetter(it) }
|
||||
fun applyIntField(key: String, valueSetter: (Int) -> Unit) = profileData[key]?.toIntOrNull()?.let { valueSetter(it) }
|
||||
fun applyLongField(key: String, valueSetter: (Long) -> Unit) = profileData[key]?.toLongOrNull()?.let { valueSetter(it) }
|
||||
|
||||
applyStringField("Build.BOARD") { Build.BOARD = it }
|
||||
applyStringField("Build.BOOTLOADER") { Build.BOOTLOADER = it }
|
||||
applyStringField("Build.BRAND") { Build.BRAND = it }
|
||||
applyStringField("Build.CPU_ABI") { Build.CPU_ABI = it }
|
||||
applyStringField("Build.CPU_ABI2") { Build.CPU_ABI2 = it }
|
||||
applyStringField("Build.DEVICE") { Build.DEVICE = it }
|
||||
applyStringField("Build.DISPLAY") { Build.DISPLAY = it }
|
||||
applyStringField("Build.FINGERPRINT") { Build.FINGERPRINT = it }
|
||||
applyStringField("Build.HARDWARE") { Build.HARDWARE = it }
|
||||
applyStringField("Build.HOST") { Build.HOST = it }
|
||||
applyStringField("Build.ID") { Build.ID = it }
|
||||
applyStringField("Build.MANUFACTURER") { Build.MANUFACTURER = it }
|
||||
applyStringField("Build.MODEL") { Build.MODEL = it }
|
||||
applyStringField("Build.PRODUCT") { Build.PRODUCT = it }
|
||||
applyStringField("Build.RADIO") { Build.RADIO = it }
|
||||
applyStringField("Build.SERIAL") { Build.SERIAL = it }
|
||||
applyStringField("Build.TAGS") { Build.TAGS = it }
|
||||
applyLongField("Build.TIME") { Build.TIME = it }
|
||||
applyStringField("Build.TYPE") { Build.TYPE = it }
|
||||
applyStringField("Build.USER") { Build.USER = it }
|
||||
applyStringField("Build.VERSION.CODENAME") { Build.VERSION.CODENAME = it }
|
||||
applyStringField("Build.VERSION.INCREMENTAL") { Build.VERSION.INCREMENTAL = it }
|
||||
applyStringField("Build.VERSION.RELEASE") { Build.VERSION.RELEASE = it }
|
||||
applyStringField("Build.VERSION.SDK") { Build.VERSION.SDK = it }
|
||||
applyIntField("Build.VERSION.SDK_INT") { Build.VERSION.SDK_INT = it }
|
||||
if (android.os.Build.VERSION.SDK_INT > 21) {
|
||||
Build.SUPPORTED_ABIS = profileData["Build.SUPPORTED_ABIS"]?.split(",")?.toTypedArray() ?: emptyArray()
|
||||
}
|
||||
}
|
||||
|
||||
private fun applyProfile(context: Context, profile: String) {
|
||||
val profileData = getProfileData(context, profile, getRealData()) ?: getRealData()
|
||||
applyProfileData(profileData)
|
||||
Build.SERIAL = getEffectiveProfileSerial(context, profile)
|
||||
Log.d(TAG, "Using Serial ${Build.SERIAL}")
|
||||
}
|
||||
|
||||
fun setProfile(context: Context, profile: String?) {
|
||||
SettingsContract.setSettings(context, Profile.getContentUri(context)) {
|
||||
put(Profile.PROFILE, profile)
|
||||
put(Profile.SERIAL, null as String?)
|
||||
}
|
||||
applyProfile(context, profile ?: PROFILE_AUTO)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun ensureInitialized(context: Context) {
|
||||
if (initialized) return
|
||||
try {
|
||||
val profile = getActiveProfile(context)
|
||||
applyProfile(context, profile)
|
||||
initialized = true
|
||||
} catch (e: Exception) {
|
||||
Log.w(TAG, e)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -131,6 +131,20 @@ object SettingsContract {
|
|||
)
|
||||
}
|
||||
|
||||
object Profile {
|
||||
private const val id = "profile"
|
||||
fun getContentUri(context: Context) = Uri.withAppendedPath(getAuthorityUri(context), id)
|
||||
fun getContentType(context: Context) = "vnd.android.cursor.item/vnd.${getAuthority(context)}.$id"
|
||||
|
||||
const val PROFILE = "device_profile"
|
||||
const val SERIAL = "device_profile_serial"
|
||||
|
||||
val PROJECTION = arrayOf(
|
||||
PROFILE,
|
||||
SERIAL
|
||||
)
|
||||
}
|
||||
|
||||
private fun <T> withoutCallingIdentity(f: () -> T): T {
|
||||
val identity = Binder.clearCallingIdentity()
|
||||
try {
|
||||
|
|
|
@ -20,6 +20,7 @@ import org.microg.gms.settings.SettingsContract.CheckIn
|
|||
import org.microg.gms.settings.SettingsContract.DroidGuard
|
||||
import org.microg.gms.settings.SettingsContract.Exposure
|
||||
import org.microg.gms.settings.SettingsContract.Gcm
|
||||
import org.microg.gms.settings.SettingsContract.Profile
|
||||
import org.microg.gms.settings.SettingsContract.SafetyNet
|
||||
import org.microg.gms.settings.SettingsContract.getAuthority
|
||||
import java.io.File
|
||||
|
@ -65,6 +66,7 @@ class SettingsProvider : ContentProvider() {
|
|||
Exposure.getContentUri(context!!) -> queryExposure(projection ?: Exposure.PROJECTION)
|
||||
SafetyNet.getContentUri(context!!) -> querySafetyNet(projection ?: SafetyNet.PROJECTION)
|
||||
DroidGuard.getContentUri(context!!) -> queryDroidGuard(projection ?: DroidGuard.PROJECTION)
|
||||
Profile.getContentUri(context!!) -> queryProfile(projection ?: Profile.PROJECTION)
|
||||
else -> null
|
||||
}
|
||||
|
||||
|
@ -83,6 +85,7 @@ class SettingsProvider : ContentProvider() {
|
|||
Exposure.getContentUri(context!!) -> updateExposure(values)
|
||||
SafetyNet.getContentUri(context!!) -> updateSafetyNet(values)
|
||||
DroidGuard.getContentUri(context!!) -> updateDroidGuard(values)
|
||||
Profile.getContentUri(context!!) -> updateProfile(values)
|
||||
else -> return 0
|
||||
}
|
||||
return 1
|
||||
|
@ -264,6 +267,27 @@ class SettingsProvider : ContentProvider() {
|
|||
editor.apply()
|
||||
}
|
||||
|
||||
private fun queryProfile(p: Array<out String>): Cursor = MatrixCursor(p).addRow(p) { key ->
|
||||
when (key) {
|
||||
Profile.PROFILE -> getSettingsString(key, "auto")
|
||||
Profile.SERIAL -> getSettingsString(key)
|
||||
else -> throw IllegalArgumentException("Unknown key: $key")
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateProfile(values: ContentValues) {
|
||||
if (values.size() == 0) return
|
||||
val editor = preferences.edit()
|
||||
values.valueSet().forEach { (key, value) ->
|
||||
when (key) {
|
||||
Profile.PROFILE -> editor.putString(key, value as String?)
|
||||
Profile.SERIAL -> editor.putString(key, value as String?)
|
||||
else -> throw IllegalArgumentException("Unknown key: $key")
|
||||
}
|
||||
}
|
||||
editor.apply()
|
||||
}
|
||||
|
||||
private fun MatrixCursor.addRow(
|
||||
p: Array<out String>,
|
||||
valueGetter: (String) -> Any?
|
||||
|
|
|
@ -19,10 +19,11 @@ package org.microg.gms.auth;
|
|||
import android.content.Context;
|
||||
|
||||
import org.microg.gms.checkin.LastCheckinInfo;
|
||||
import org.microg.gms.common.Build;
|
||||
import org.microg.gms.profile.Build;
|
||||
import org.microg.gms.common.Constants;
|
||||
import org.microg.gms.common.HttpFormClient;
|
||||
import org.microg.gms.common.Utils;
|
||||
import org.microg.gms.profile.ProfileManager;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Locale;
|
||||
|
@ -91,10 +92,11 @@ public class AuthRequest extends HttpFormClient.Request {
|
|||
userAgent = String.format(USER_AGENT, deviceName, buildVersion);
|
||||
}
|
||||
|
||||
public AuthRequest build(Build build) {
|
||||
sdkVersion = build.version_sdk_int;
|
||||
deviceName = build.device;
|
||||
buildVersion = build.id;
|
||||
public AuthRequest build(Context context) {
|
||||
ProfileManager.ensureInitialized(context);
|
||||
sdkVersion = Build.VERSION.SDK_INT;
|
||||
deviceName = Build.DEVICE;
|
||||
buildVersion = Build.ID;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -111,7 +113,7 @@ public class AuthRequest extends HttpFormClient.Request {
|
|||
}
|
||||
|
||||
public AuthRequest fromContext(Context context) {
|
||||
build(Utils.getBuild(context));
|
||||
build(context);
|
||||
locale(Utils.getLocale(context));
|
||||
androidIdHex = Long.toHexString(LastCheckinInfo.read(context).getAndroidId());
|
||||
return this;
|
||||
|
|
|
@ -16,13 +16,15 @@
|
|||
|
||||
package org.microg.gms.checkin;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.Log;
|
||||
|
||||
import org.microg.gms.common.Build;
|
||||
import org.microg.gms.common.DeviceConfiguration;
|
||||
import org.microg.gms.common.DeviceIdentifier;
|
||||
import org.microg.gms.common.PhoneInfo;
|
||||
import org.microg.gms.common.Utils;
|
||||
import org.microg.gms.profile.Build;
|
||||
import org.microg.gms.profile.ProfileManager;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
@ -76,29 +78,30 @@ public class CheckinClient {
|
|||
return response;
|
||||
}
|
||||
|
||||
public static CheckinRequest makeRequest(Build build, DeviceConfiguration deviceConfiguration,
|
||||
public static CheckinRequest makeRequest(Context context, DeviceConfiguration deviceConfiguration,
|
||||
DeviceIdentifier deviceIdent, PhoneInfo phoneInfo,
|
||||
LastCheckinInfo checkinInfo, Locale locale,
|
||||
List<Account> accounts) {
|
||||
ProfileManager.ensureInitialized(context);
|
||||
CheckinRequest.Builder builder = new CheckinRequest.Builder()
|
||||
.accountCookie(new ArrayList<>())
|
||||
.androidId(checkinInfo.getAndroidId())
|
||||
.checkin(new CheckinRequest.Checkin.Builder()
|
||||
.build(new CheckinRequest.Checkin.Build.Builder()
|
||||
.bootloader(build.bootloader)
|
||||
.brand(build.brand)
|
||||
.bootloader(Build.BOOTLOADER)
|
||||
.brand(Build.BRAND)
|
||||
.clientId("android-google")
|
||||
.device(build.device)
|
||||
.fingerprint(build.fingerprint)
|
||||
.hardware(build.hardware)
|
||||
.manufacturer(build.manufacturer)
|
||||
.model(build.model)
|
||||
.device(Build.DEVICE)
|
||||
.fingerprint(Build.FINGERPRINT)
|
||||
.hardware(Build.HARDWARE)
|
||||
.manufacturer(Build.MANUFACTURER)
|
||||
.model(Build.MODEL)
|
||||
.otaInstalled(false) // TODO?
|
||||
//.packageVersionCode(Constants.MAX_REFERENCE_VERSION)
|
||||
.product(build.product)
|
||||
.radio(build.radio)
|
||||
.sdkVersion(build.version_sdk_int)
|
||||
.time(build.time / 1000)
|
||||
.product(Build.PRODUCT)
|
||||
.radio(Build.RADIO)
|
||||
.sdkVersion(Build.VERSION.SDK_INT)
|
||||
.time(Build.TIME / 1000)
|
||||
.build())
|
||||
.cellOperator(phoneInfo.cellOperator)
|
||||
.event(Collections.singletonList(new CheckinRequest.Checkin.Event.Builder()
|
||||
|
@ -137,7 +140,7 @@ public class CheckinClient {
|
|||
.loggingId(new Random().nextLong()) // TODO: static
|
||||
.meid(deviceIdent.meid)
|
||||
.otaCert(Collections.singletonList("71Q6Rn2DDZl1zPDVaaeEHItd"))
|
||||
.serial(build.serial)
|
||||
.serial(Build.SERIAL)
|
||||
.timeZone(TimeZone.getDefault().getID())
|
||||
.userName((String) TODO)
|
||||
.userSerialNumber((Integer) TODO)
|
||||
|
|
|
@ -56,7 +56,7 @@ public class CheckinManager {
|
|||
accounts.add(new CheckinClient.Account(account.name, token));
|
||||
}
|
||||
}
|
||||
CheckinRequest request = CheckinClient.makeRequest(Utils.getBuild(context),
|
||||
CheckinRequest request = CheckinClient.makeRequest(context,
|
||||
new DeviceConfiguration(context), Utils.getDeviceIdentifier(context),
|
||||
Utils.getPhoneInfo(context), info, Utils.getLocale(context), accounts);
|
||||
return handleResponse(context, CheckinClient.request(request));
|
||||
|
|
|
@ -41,7 +41,7 @@ public class PushRegisterManager {
|
|||
RegisterResponse response = new RegisterResponse();
|
||||
try {
|
||||
response = new RegisterRequest()
|
||||
.build(Utils.getBuild(context))
|
||||
.build(context)
|
||||
.sender(sender)
|
||||
.info(info)
|
||||
.checkin(LastCheckinInfo.read(context))
|
||||
|
|
|
@ -16,12 +16,14 @@
|
|||
|
||||
package org.microg.gms.gcm;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import org.microg.gms.checkin.LastCheckinInfo;
|
||||
import org.microg.gms.common.Build;
|
||||
import org.microg.gms.common.HttpFormClient;
|
||||
import org.microg.gms.profile.Build;
|
||||
import org.microg.gms.profile.ProfileManager;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.LinkedHashMap;
|
||||
|
@ -103,9 +105,10 @@ public class RegisterRequest extends HttpFormClient.Request {
|
|||
return this;
|
||||
}
|
||||
|
||||
public RegisterRequest build(Build build) {
|
||||
deviceName = build.device;
|
||||
buildVersion = build.id;
|
||||
public RegisterRequest build(Context context) {
|
||||
ProfileManager.ensureInitialized(context);
|
||||
deviceName = Build.DEVICE;
|
||||
buildVersion = Build.ID;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
|
|
@ -13,10 +13,11 @@ import android.content.pm.Signature;
|
|||
import android.util.Base64;
|
||||
import android.util.Log;
|
||||
|
||||
import org.microg.gms.common.Build;
|
||||
import org.microg.gms.common.Constants;
|
||||
import org.microg.gms.common.PackageUtils;
|
||||
import org.microg.gms.common.Utils;
|
||||
import org.microg.gms.profile.Build;
|
||||
import org.microg.gms.profile.ProfileManager;
|
||||
import org.microg.gms.snet.AttestRequest;
|
||||
import org.microg.gms.snet.AttestResponse;
|
||||
import org.microg.gms.snet.FileState;
|
||||
|
@ -154,6 +155,7 @@ public class Attestation {
|
|||
}
|
||||
|
||||
private AttestResponse attest(AttestRequest request, String apiKey) throws IOException {
|
||||
ProfileManager.ensureInitialized(context);
|
||||
String requestUrl = SafetyNetPrefs.get(context).getServiceUrl() + "?alt=PROTO&key=" + apiKey;
|
||||
HttpURLConnection connection = (HttpURLConnection) new URL(requestUrl).openConnection();
|
||||
connection.setRequestMethod("POST");
|
||||
|
@ -163,8 +165,7 @@ public class Attestation {
|
|||
connection.setRequestProperty("Accept-Encoding", "gzip");
|
||||
connection.setRequestProperty("X-Android-Package", packageName);
|
||||
connection.setRequestProperty("X-Android-Cert", PackageUtils.firstSignatureDigest(context, packageName));
|
||||
Build build = Utils.getBuild(context);
|
||||
connection.setRequestProperty("User-Agent", "SafetyNet/" + Constants.GMS_VERSION_CODE + " (" + build.device + " " + build.id + "); gzip");
|
||||
connection.setRequestProperty("User-Agent", "SafetyNet/" + Constants.GMS_VERSION_CODE + " (" + Build.DEVICE + " " + Build.ID + "); gzip");
|
||||
|
||||
OutputStream os = connection.getOutputStream();
|
||||
os.write(request.encode());
|
||||
|
|
|
@ -24,7 +24,7 @@ import com.google.android.gms.wearable.ConnectionConfiguration;
|
|||
import com.google.android.gms.wearable.internal.MessageEventParcelable;
|
||||
|
||||
import org.microg.gms.checkin.LastCheckinInfo;
|
||||
import org.microg.gms.common.Build;
|
||||
import org.microg.gms.profile.Build;
|
||||
import org.microg.wearable.ServerMessageListener;
|
||||
import org.microg.wearable.proto.AckAsset;
|
||||
import org.microg.wearable.proto.Connect;
|
||||
|
@ -48,7 +48,7 @@ public class MessageHandler extends ServerMessageListener {
|
|||
private String peerNodeId;
|
||||
|
||||
public MessageHandler(WearableImpl wearable, ConnectionConfiguration config) {
|
||||
this(wearable, config, new Build().model, config.nodeId, LastCheckinInfo.read(wearable.getContext()).getAndroidId());
|
||||
this(wearable, config, Build.MODEL, config.nodeId, LastCheckinInfo.read(wearable.getContext()).getAndroidId());
|
||||
}
|
||||
|
||||
private MessageHandler(WearableImpl wearable, ConnectionConfiguration config, String name, String networkId, long androidId) {
|
||||
|
|
|
@ -148,7 +148,7 @@ class PushRegisterService : LifecycleService() {
|
|||
Log.d(TAG, "register[req]: " + intent.toString() + " extras=" + intent!!.extras)
|
||||
val bundle = completeRegisterRequest(this, database,
|
||||
RegisterRequest()
|
||||
.build(Utils.getBuild(this))
|
||||
.build(this)
|
||||
.sender(intent.getStringExtra(EXTRA_SENDER))
|
||||
.checkin(LastCheckinInfo.read(this))
|
||||
.app(packageName)
|
||||
|
@ -164,7 +164,7 @@ class PushRegisterService : LifecycleService() {
|
|||
val packageName = intent.appPackageName ?: throw RuntimeException("No package provided")
|
||||
Log.d(TAG, "unregister[req]: " + intent.toString() + " extras=" + intent.extras)
|
||||
val bundle = completeRegisterRequest(this, database, RegisterRequest()
|
||||
.build(Utils.getBuild(this))
|
||||
.build(this)
|
||||
.sender(intent.getStringExtra(EXTRA_SENDER))
|
||||
.checkin(LastCheckinInfo.read(this))
|
||||
.app(packageName)
|
||||
|
@ -314,7 +314,7 @@ internal class PushRegisterHandler(private val context: Context, private val dat
|
|||
if (!delete) ensureAppRegistrationAllowed(context, database, packageName)
|
||||
val bundle = completeRegisterRequest(context, database,
|
||||
RegisterRequest()
|
||||
.build(Utils.getBuild(context))
|
||||
.build(context)
|
||||
.sender(sender)
|
||||
.checkin(LastCheckinInfo.read(context))
|
||||
.app(packageName)
|
||||
|
|
35
play-services-core/src/main/res/xml/profile_bullhead_27.xml
Normal file
35
play-services-core/src/main/res/xml/profile_bullhead_27.xml
Normal file
|
@ -0,0 +1,35 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
~ SPDX-FileCopyrightText: 2021, microG Project Team
|
||||
~ SPDX-License-Identifier: Apache-2.0
|
||||
-->
|
||||
<profile name="Google Nexus 5X (Android 8.1.0)" device="bullhead" sdk="27" id="bullhead_27">
|
||||
<!-- Data from OPM3.171019.016, Mar 2018 -->
|
||||
<data key="Build.BOARD" value="bullhead" />
|
||||
<data key="Build.BOOTLOADER" value="BHZ31b" />
|
||||
<data key="Build.BRAND" value="google" />
|
||||
<data key="Build.CPU_ABI" value="arm64-v8a" />
|
||||
<data key="Build.CPU_ABI2" value="" />
|
||||
<data key="Build.DEVICE" value="bullhead" />
|
||||
<data key="Build.DISPLAY" value="bullhead-user 8.1.0 OPM3.171019.016 4565142 release-keys" />
|
||||
<data key="Build.FINGERPRINT" value="google/bullhead/bullhead:8.1.0/OPM3.171019.016/4565142:user/release-keys" />
|
||||
<data key="Build.HARDWARE" value="bullhead" />
|
||||
<data key="Build.HOST" value="wpdt4.hot.corp.google.com" />
|
||||
<data key="Build.ID" value="OPM3.171019.016" />
|
||||
<data key="Build.MANUFACTURER" value="LGE" />
|
||||
<data key="Build.MODEL" value="Nexus 5X" />
|
||||
<data key="Build.PRODUCT" value="bullhead" />
|
||||
<data key="Build.RADIO" value="unknown" />
|
||||
<data key="Build.TAGS" value="release-keys" />
|
||||
<data key="Build.TIME" value="1516849845000" />
|
||||
<data key="Build.TYPE" value="user" />
|
||||
<data key="Build.USER" value="android-build" />
|
||||
<data key="Build.VERSION.CODENAME" value="REL" />
|
||||
<data key="Build.VERSION.INCREMENTAL" value="6d95f5a143" />
|
||||
<data key="Build.VERSION.RELEASE" value="8.1.0" />
|
||||
<data key="Build.VERSION.SDK" value="27" />
|
||||
<data key="Build.VERSION.SDK_INT" value="27" />
|
||||
<data key="Build.SUPPORTED_ABIS" value="arm64-v8a,armeabi-v7a,armeabi" />
|
||||
|
||||
<serial template="005b56ffff999999" />
|
||||
</profile>
|
|
@ -40,7 +40,7 @@ public abstract class TracingIntentService extends IntentService {
|
|||
public PackageInfo getPackageInfo(@NonNull String packageName, int flags) {
|
||||
PackageInfo packageInfo = super.getPackageInfo(packageName, flags);
|
||||
if ("com.google.android.gms".equals(packageName)) {
|
||||
VersionUtil versionUtil = new VersionUtil(TracingIntentService.this, new org.microg.gms.common.Build());
|
||||
VersionUtil versionUtil = new VersionUtil(TracingIntentService.this);
|
||||
packageInfo.versionCode = versionUtil.getVersionCode();
|
||||
packageInfo.versionName = versionUtil.getVersionString();
|
||||
packageInfo.sharedUserId = "com.google.uid.shared";
|
||||
|
|
|
@ -14,8 +14,9 @@ import com.google.android.gms.droidguard.internal.DroidGuardResultsRequest
|
|||
import dalvik.system.DexClassLoader
|
||||
import okio.ByteString.Companion.decodeHex
|
||||
import okio.ByteString.Companion.of
|
||||
import org.microg.gms.common.Build
|
||||
import org.microg.gms.droidguard.core.BuildConfig
|
||||
import org.microg.gms.profile.Build
|
||||
import org.microg.gms.profile.ProfileManager
|
||||
import java.io.File
|
||||
import java.io.IOException
|
||||
import java.security.MessageDigest
|
||||
|
@ -25,10 +26,9 @@ import com.android.volley.Request as VolleyRequest
|
|||
import com.android.volley.Response as VolleyResponse
|
||||
|
||||
class HandleProxyFactory(private val context: Context) {
|
||||
private val build: Build = Build()
|
||||
private val classMap = hashMapOf<String, Class<*>>()
|
||||
private val dgDb: DgDatabaseHelper = DgDatabaseHelper(context)
|
||||
private val version = VersionUtil(context, build)
|
||||
private val version = VersionUtil(context)
|
||||
private val queue = Volley.newRequestQueue(context)
|
||||
|
||||
fun createHandle(packageName: String, flow: String?, callback: GuardCallback, request: DroidGuardResultsRequest?): HandleProxy {
|
||||
|
@ -55,40 +55,42 @@ class HandleProxyFactory(private val context: Context) {
|
|||
}
|
||||
|
||||
private fun readFromDatabase(flow: String?): Triple<String, ByteArray, ByteArray>? {
|
||||
val id = "$flow/${version.versionString}/${build.fingerprint}"
|
||||
ProfileManager.ensureInitialized(context)
|
||||
val id = "$flow/${version.versionString}/${Build.FINGERPRINT}"
|
||||
return dgDb.get(id)
|
||||
}
|
||||
|
||||
fun createRequest(flow: String?, packageName: String, pingData: PingData? = null, extra: ByteArray? = null): Request {
|
||||
ProfileManager.ensureInitialized(context)
|
||||
return Request(
|
||||
usage = Usage(flow, packageName),
|
||||
info = listOf(
|
||||
KeyValuePair("BOARD", build.board),
|
||||
KeyValuePair("BOOTLOADER", build.bootloader),
|
||||
KeyValuePair("BRAND", build.brand),
|
||||
KeyValuePair("CPU_ABI", build.cpu_abi),
|
||||
KeyValuePair("CPU_ABI2", build.cpu_abi2),
|
||||
KeyValuePair("SUPPORTED_ABIS", build.supported_abis.joinToString(",")),
|
||||
KeyValuePair("DEVICE", build.device),
|
||||
KeyValuePair("DISPLAY", build.display),
|
||||
KeyValuePair("FINGERPRINT", build.fingerprint),
|
||||
KeyValuePair("HARDWARE", build.hardware),
|
||||
KeyValuePair("HOST", build.host),
|
||||
KeyValuePair("ID", build.id),
|
||||
KeyValuePair("MANUFACTURER", build.manufacturer),
|
||||
KeyValuePair("MODEL", build.model),
|
||||
KeyValuePair("PRODUCT", build.product),
|
||||
KeyValuePair("RADIO", build.radio),
|
||||
KeyValuePair("SERIAL", build.serial),
|
||||
KeyValuePair("TAGS", build.tags),
|
||||
KeyValuePair("TIME", build.time.toString()),
|
||||
KeyValuePair("TYPE", build.type),
|
||||
KeyValuePair("USER", build.user),
|
||||
KeyValuePair("VERSION.CODENAME", build.version_codename),
|
||||
KeyValuePair("VERSION.INCREMENTAL", build.version_incremental),
|
||||
KeyValuePair("VERSION.RELEASE", build.version_release),
|
||||
KeyValuePair("VERSION.SDK", build.version_sdk),
|
||||
KeyValuePair("VERSION.SDK_INT", build.version_sdk_int.toString()),
|
||||
KeyValuePair("BOARD", Build.BOARD),
|
||||
KeyValuePair("BOOTLOADER", Build.BOOTLOADER),
|
||||
KeyValuePair("BRAND", Build.BRAND),
|
||||
KeyValuePair("CPU_ABI", Build.CPU_ABI),
|
||||
KeyValuePair("CPU_ABI2", Build.CPU_ABI2),
|
||||
KeyValuePair("SUPPORTED_ABIS", Build.SUPPORTED_ABIS.joinToString(",")),
|
||||
KeyValuePair("DEVICE", Build.DEVICE),
|
||||
KeyValuePair("DISPLAY", Build.DISPLAY),
|
||||
KeyValuePair("FINGERPRINT", Build.FINGERPRINT),
|
||||
KeyValuePair("HARDWARE", Build.HARDWARE),
|
||||
KeyValuePair("HOST", Build.HOST),
|
||||
KeyValuePair("ID", Build.ID),
|
||||
KeyValuePair("MANUFACTURER", Build.MANUFACTURER),
|
||||
KeyValuePair("MODEL", Build.MODEL),
|
||||
KeyValuePair("PRODUCT", Build.PRODUCT),
|
||||
KeyValuePair("RADIO", Build.RADIO),
|
||||
KeyValuePair("SERIAL", Build.SERIAL),
|
||||
KeyValuePair("TAGS", Build.TAGS),
|
||||
KeyValuePair("TIME", Build.TIME.toString()),
|
||||
KeyValuePair("TYPE", Build.TYPE),
|
||||
KeyValuePair("USER", Build.USER),
|
||||
KeyValuePair("VERSION.CODENAME", Build.VERSION.CODENAME),
|
||||
KeyValuePair("VERSION.INCREMENTAL", Build.VERSION.INCREMENTAL),
|
||||
KeyValuePair("VERSION.RELEASE", Build.VERSION.RELEASE),
|
||||
KeyValuePair("VERSION.SDK", Build.VERSION.SDK),
|
||||
KeyValuePair("VERSION.SDK_INT", Build.VERSION.SDK_INT.toString()),
|
||||
),
|
||||
versionName = version.versionString,
|
||||
versionCode = BuildConfig.VERSION_CODE,
|
||||
|
@ -107,6 +109,7 @@ class HandleProxyFactory(private val context: Context) {
|
|||
}
|
||||
|
||||
fun fetchFromServer(flow: String?, request: Request): Triple<String, ByteArray, ByteArray> {
|
||||
ProfileManager.ensureInitialized(context)
|
||||
val future = RequestFuture.newFuture<SignedResponse>()
|
||||
queue.add(object : VolleyRequest<SignedResponse>(Method.POST, SERVER_URL, future) {
|
||||
override fun parseNetworkResponse(response: NetworkResponse): VolleyResponse<SignedResponse> {
|
||||
|
@ -146,11 +149,13 @@ class HandleProxyFactory(private val context: Context) {
|
|||
throw IllegalStateException()
|
||||
}
|
||||
}
|
||||
val id = "$flow/${version.versionString}/${build.fingerprint}"
|
||||
val id = "$flow/${version.versionString}/${Build.FINGERPRINT}"
|
||||
val expiry = (response.expiryTimeSecs ?: 0).toLong()
|
||||
val byteCode = response.byteCode!!.toByteArray()
|
||||
val extra = response.extra!!.toByteArray()
|
||||
dgDb.put(id, expiry, vmKey, byteCode, extra)
|
||||
val byteCode = response.byteCode?.toByteArray() ?: ByteArray(0)
|
||||
val extra = response.extra?.toByteArray() ?: ByteArray(0)
|
||||
if (response.save != false) {
|
||||
dgDb.put(id, expiry, vmKey, byteCode, extra)
|
||||
}
|
||||
return Triple(vmKey, byteCode, extra)
|
||||
}
|
||||
|
||||
|
|
|
@ -6,14 +6,16 @@
|
|||
package org.microg.gms.droidguard
|
||||
|
||||
import android.content.Context
|
||||
import org.microg.gms.common.Build
|
||||
import org.microg.gms.droidguard.core.BuildConfig
|
||||
import org.microg.gms.profile.Build
|
||||
import org.microg.gms.profile.ProfileManager
|
||||
|
||||
class VersionUtil(private val context: Context, private val build: Build = Build()) {
|
||||
class VersionUtil(private val context: Context) {
|
||||
val buildType: String
|
||||
get() {
|
||||
ProfileManager.ensureInitialized(context)
|
||||
// Note: Android TV and Watch use different version codes
|
||||
val versionCode = when (build.version_sdk_int) {
|
||||
val versionCode = when (Build.VERSION.SDK_INT) {
|
||||
31 -> "19"
|
||||
30 -> "15"
|
||||
29 -> "12"
|
||||
|
@ -22,14 +24,14 @@ class VersionUtil(private val context: Context, private val build: Build = Build
|
|||
21, 22 -> "02"
|
||||
else -> "00"
|
||||
}
|
||||
val architectureCode = when (build.cpu_abi) {
|
||||
val architectureCode = when (Build.CPU_ABI) {
|
||||
"x86_64" -> "08"
|
||||
"x86" -> "07"
|
||||
"arm64-v8a" -> "04"
|
||||
"arm", "armeabi", "armeabi-v7a" -> "03"
|
||||
else -> "00"
|
||||
}
|
||||
val dpiCode = when (context.resources.displayMetrics.densityDpi) {
|
||||
val dpiCode = when (context.resources.displayMetrics.densityDpi) { // TODO: Also something to get from profile
|
||||
160 -> "02"
|
||||
240 -> "04"
|
||||
320 -> "06"
|
||||
|
|
Loading…
Reference in a new issue