From 3454682a864faa226d95e95bc5f047164d041650 Mon Sep 17 00:00:00 2001 From: mar-v-in Date: Thu, 19 Feb 2015 01:29:43 +0100 Subject: [PATCH] Start work on checkin --- UnifiedNlpApi | 2 +- UnifiedNlpLib | 2 +- build.gradle | 3 +- protos-repo/checkin.proto | 115 ++ .../microg/gms/checkin/CheckinRequest.java | 1547 +++++++++++++++++ .../microg/gms/checkin/CheckinResponse.java | 462 +++++ src/org/microg/gms/auth/AuthClient.java | 3 + src/org/microg/gms/checkin/CheckinClient.java | 155 ++ .../microg/gms/checkin/LastCheckinInfo.java | 23 + src/org/microg/gms/common/Build.java | 22 +- .../gms/common/DeviceConfiguration.java | 38 + .../microg/gms/common/DeviceIdentifier.java | 24 + src/org/microg/gms/common/PhoneInfo.java | 23 + 13 files changed, 2414 insertions(+), 5 deletions(-) create mode 100644 protos-repo/checkin.proto create mode 100644 protos-src/org/microg/gms/checkin/CheckinRequest.java create mode 100644 protos-src/org/microg/gms/checkin/CheckinResponse.java create mode 100644 src/org/microg/gms/checkin/CheckinClient.java create mode 100644 src/org/microg/gms/checkin/LastCheckinInfo.java create mode 100644 src/org/microg/gms/common/DeviceConfiguration.java create mode 100644 src/org/microg/gms/common/DeviceIdentifier.java create mode 100644 src/org/microg/gms/common/PhoneInfo.java diff --git a/UnifiedNlpApi b/UnifiedNlpApi index d72e67e4..06d11323 160000 --- a/UnifiedNlpApi +++ b/UnifiedNlpApi @@ -1 +1 @@ -Subproject commit d72e67e45d5eba2d17c1b73ee296fff91d147136 +Subproject commit 06d1132344b4600ae00bda63d4da0acff7de42f0 diff --git a/UnifiedNlpLib b/UnifiedNlpLib index 35713890..1b290720 160000 --- a/UnifiedNlpLib +++ b/UnifiedNlpLib @@ -1 +1 @@ -Subproject commit 35713890ee761a2a5844aa1babd2a1cf737cf06e +Subproject commit 1b2907207fd145efab7a1653d04134574a960a7d diff --git a/build.gradle b/build.gradle index fd196c4d..7575175d 100644 --- a/build.gradle +++ b/build.gradle @@ -37,6 +37,7 @@ dependencies { compile 'com.android.support:appcompat-v7:21.0.3' compile 'de.hdodenhof:circleimageview:1.2.1' + compile 'com.squareup.wire:wire-runtime:1.6.1' compile project(':GmsApi') compile project(':UnifiedNlpLib') @@ -63,7 +64,7 @@ android { sourceSets { main { manifest.srcFile 'AndroidManifest.xml' - java.srcDirs = ['src'] + java.srcDirs = ['src', 'protos-src'] aidl.srcDirs = ['src'] res.srcDirs = ['res'] assets.srcDirs = ['assets'] diff --git a/protos-repo/checkin.proto b/protos-repo/checkin.proto new file mode 100644 index 00000000..7203bf98 --- /dev/null +++ b/protos-repo/checkin.proto @@ -0,0 +1,115 @@ +option java_package = "org.microg.gms.checkin"; + +option java_outer_classname = "CheckinProto"; + +message CheckinRequest { + message DeviceConfig { + optional int32 touchScreen = 1; // ConfigurationInfo.reqTouchScreen + optional int32 keyboardType = 2; // ConfigurationInfo.reqKeyboardType + optional int32 navigation = 3; // ConfigurationInfo.reqNavigation + optional int32 screenLayout = 4; // ConfigurationInfo.screenLayout + optional bool hasHardKeyboard = 5; // ConfigurationInfo.reqInputFeatures & ConfigurationInfo.INPUT_FEATURE_HARD_KEYBOARD + optional bool hasFiveWayNavigation = 6; // ConfigurationInfo.reqInputFeatures & ConfigurationInfo.INPUT_FEATURE_FIVE_WAY_NAV + optional int32 densityDpi = 7; // DisplayMetrics.densityDpi + optional int32 glEsVersion = 8; // ConfigurationInfo.reqGlEsVersion + repeated string sharedLibrary = 9; // PackageManager.getSystemSharedLibraryNames + repeated string availableFeature = 10; // PackageManager.getSystemAvailableFeatures + repeated string nativePlatform = 11; // Build.CPU_ABI (and Build.CPU_ABI2 != "unknown") + optional int32 widthPixels = 12; // DisplayMetrics.widthPixels + optional int32 heightPixels = 13; // DisplayMetrics.heightPixels + repeated string locale = 14; // Context.getAssets.getLocales + repeated string glExtension = 15; // GLES10.glGetString(GLES10.GL_EXTENSIONS) + optional int32 deviceClass = 16; // unused + optional int32 maxApkDownloadSizeMb = 17; // unused + } + message Checkin { + message Event { + optional string tag = 1; + optional string value = 2; + optional int64 timeMs = 3; + } + message Statistic { + optional string tag = 1; + optional int32 count = 2; + optional float sum = 3; + } + message Build { + optional string fingerprint = 1; // Build.FINGERPRINT + optional string hardware = 2; // Build.HARDWARE + optional string brand = 3; // Build.BRAND + optional string radio = 4; // Build.getRadioVersion() + optional string bootloader = 5; // Build.BOOTLOADER + optional string clientId = 6; // GoogleSettingsContract.Partner["client_id"] + optional int64 time = 7; // Build.TIME / 1000L + optional int32 packageVersionCode = 8; // PackageInfo.versionCode + optional string device = 9; // Build.DEVICE + optional int32 sdkVersion = 10; // Build.VERSION.SDK_INT + optional string model = 11; // Build.MODEL + optional string manufacturer = 12; // Build.MANUFACTURER + optional string product = 13; // Build.PRODUCT + optional bool otaInstalled = 14; // fileExists("/system/recovery-from-boot.p") + } + + optional Build build = 1; + optional int64 lastCheckinMs = 2; // or 0 + repeated Event event = 3; + repeated Statistic stat = 4; + repeated string requestedGroup = 5; // unused + optional string cellOperator = 6; // TelephonyManager.getNetworkOperator != null|empty + optional string simOperator = 7; // TelephonyManager.getSimOperator != null|empty + optional string roaming = 8; // "mobile/notmobile/unknown-roaming/notroaming/unknown" + optional int32 userNumber = 9; // UserHandle.myUserId + } + optional string imei = 1; // unused + optional int64 androidId = 2; // Gservices["android_id"] or 0 + optional string digest = 3; // Gservices["digest"] or "" + optional Checkin checkin = 4; + optional string desiredBuild = 5; // unused + optional string locale = 6; // Locale.toString + optional int64 loggingId = 7; // GoogleSettingsContract.Partner["logging_id2"] + optional string marketCheckin = 8; // unused + repeated string macAddress = 9; // NetworkInfo.getExtraInfo, WifiInfo.getMacAddress (12 hex-digits) + optional string meid = 10; // TelephonyManager.getDeviceId (14 hex-digits) + repeated string accountCookie = 11; // "[]" followed by "" + optional string timeZone = 12; // TimeZone.getId + optional fixed64 securityToken = 13; + optional int32 version = 14; // 3 if securityToken != 0 OR androidId == 0 + repeated string otaCert = 15; // SHA-1 of each in /system/etc/security/otacerts.zip or "--IOException--" or "--no-output--" + optional string serial = 16; // Build.SERIAL != "unknown" + optional string esn = 17; // TelephonyManager.getDeviceId (8 hex-digits) + optional DeviceConfig deviceConfiguration = 18; + repeated string macAddressType = 19; // "ethernet", "wifi" + optional int32 fragment = 20; // unknown (use 0) + optional string userName = 21; // unused + optional int32 userSerialNumber = 22; // UserManager.getUserSerialNumber (if != 0) +} + +message CheckinResponse { + message Intent { + message Extra { + optional string name = 6; + optional string value = 7; + } + optional string action = 1; + optional string dataUri = 2; + optional string mimeType = 3; + optional string javaClass = 4; + repeated Extra extra = 5; + } + + message GservicesSetting { + optional bytes name = 1; + optional bytes value = 2; + } + + optional bool statsOk = 1; + repeated Intent intent = 2; + optional int64 timeMs = 3; + optional string digest = 4; + repeated GservicesSetting setting = 5; + optional bool marketOk = 6; + optional fixed64 androidId = 7; + optional fixed64 securityToken = 8; + optional bool settingsDiff = 9; + repeated string deleteSetting = 10; +} diff --git a/protos-src/org/microg/gms/checkin/CheckinRequest.java b/protos-src/org/microg/gms/checkin/CheckinRequest.java new file mode 100644 index 00000000..7515b49c --- /dev/null +++ b/protos-src/org/microg/gms/checkin/CheckinRequest.java @@ -0,0 +1,1547 @@ +// Code generated by Wire protocol buffer compiler, do not edit. +// Source file: protos-repo/checkin.proto +package org.microg.gms.checkin; + +import com.squareup.wire.Message; +import com.squareup.wire.ProtoField; +import java.util.Collections; +import java.util.List; + +import static com.squareup.wire.Message.Datatype.BOOL; +import static com.squareup.wire.Message.Datatype.FIXED64; +import static com.squareup.wire.Message.Datatype.FLOAT; +import static com.squareup.wire.Message.Datatype.INT32; +import static com.squareup.wire.Message.Datatype.INT64; +import static com.squareup.wire.Message.Datatype.STRING; +import static com.squareup.wire.Message.Label.REPEATED; + +public final class CheckinRequest extends Message { + + public static final String DEFAULT_IMEI = ""; + public static final Long DEFAULT_ANDROIDID = 0L; + public static final String DEFAULT_DIGEST = ""; + public static final String DEFAULT_DESIREDBUILD = ""; + public static final String DEFAULT_LOCALE = ""; + public static final Long DEFAULT_LOGGINGID = 0L; + public static final String DEFAULT_MARKETCHECKIN = ""; + public static final List DEFAULT_MACADDRESS = Collections.emptyList(); + public static final String DEFAULT_MEID = ""; + public static final List DEFAULT_ACCOUNTCOOKIE = Collections.emptyList(); + public static final String DEFAULT_TIMEZONE = ""; + public static final Long DEFAULT_SECURITYTOKEN = 0L; + public static final Integer DEFAULT_VERSION = 0; + public static final List DEFAULT_OTACERT = Collections.emptyList(); + public static final String DEFAULT_SERIAL = ""; + public static final String DEFAULT_ESN = ""; + public static final List DEFAULT_MACADDRESSTYPE = Collections.emptyList(); + public static final Integer DEFAULT_FRAGMENT = 0; + public static final String DEFAULT_USERNAME = ""; + public static final Integer DEFAULT_USERSERIALNUMBER = 0; + + @ProtoField(tag = 1, type = STRING) + public final String imei; + + /** + * unused + */ + @ProtoField(tag = 2, type = INT64) + public final Long androidId; + + /** + * Gservices["android_id"] or 0 + */ + @ProtoField(tag = 3, type = STRING) + public final String digest; + + /** + * Gservices["digest"] or "" + */ + @ProtoField(tag = 4) + public final Checkin checkin; + + @ProtoField(tag = 5, type = STRING) + public final String desiredBuild; + + /** + * unused + */ + @ProtoField(tag = 6, type = STRING) + public final String locale; + + /** + * Locale.toString + */ + @ProtoField(tag = 7, type = INT64) + public final Long loggingId; + + /** + * GoogleSettingsContract.Partner["logging_id2"] + */ + @ProtoField(tag = 8, type = STRING) + public final String marketCheckin; + + /** + * unused + */ + @ProtoField(tag = 9, type = STRING, label = REPEATED) + public final List macAddress; + + /** + * NetworkInfo.getExtraInfo, WifiInfo.getMacAddress (12 hex-digits) + */ + @ProtoField(tag = 10, type = STRING) + public final String meid; + + /** + * TelephonyManager.getDeviceId (14 hex-digits) + */ + @ProtoField(tag = 11, type = STRING, label = REPEATED) + public final List accountCookie; + + /** + * "[]" followed by "" + */ + @ProtoField(tag = 12, type = STRING) + public final String timeZone; + + /** + * TimeZone.getId + */ + @ProtoField(tag = 13, type = FIXED64) + public final Long securityToken; + + @ProtoField(tag = 14, type = INT32) + public final Integer version; + + /** + * 3 if securityToken != 0 OR androidId == 0 + */ + @ProtoField(tag = 15, type = STRING, label = REPEATED) + public final List otaCert; + + /** + * SHA-1 of each in /system/etc/security/otacerts.zip or "--IOException--" or "--no-output--" + */ + @ProtoField(tag = 16, type = STRING) + public final String serial; + + /** + * Build.SERIAL != "unknown" + */ + @ProtoField(tag = 17, type = STRING) + public final String esn; + + /** + * TelephonyManager.getDeviceId (8 hex-digits) + */ + @ProtoField(tag = 18) + public final DeviceConfig deviceConfiguration; + + @ProtoField(tag = 19, type = STRING, label = REPEATED) + public final List macAddressType; + + /** + * "ethernet", "wifi" + */ + @ProtoField(tag = 20, type = INT32) + public final Integer fragment; + + /** + * unknown (use 0) + */ + @ProtoField(tag = 21, type = STRING) + public final String userName; + + /** + * unused + */ + @ProtoField(tag = 22, type = INT32) + public final Integer userSerialNumber; + + public CheckinRequest(String imei, Long androidId, String digest, Checkin checkin, String desiredBuild, String locale, Long loggingId, String marketCheckin, List macAddress, String meid, List accountCookie, String timeZone, Long securityToken, Integer version, List otaCert, String serial, String esn, DeviceConfig deviceConfiguration, List macAddressType, Integer fragment, String userName, Integer userSerialNumber) { + this.imei = imei; + this.androidId = androidId; + this.digest = digest; + this.checkin = checkin; + this.desiredBuild = desiredBuild; + this.locale = locale; + this.loggingId = loggingId; + this.marketCheckin = marketCheckin; + this.macAddress = immutableCopyOf(macAddress); + this.meid = meid; + this.accountCookie = immutableCopyOf(accountCookie); + this.timeZone = timeZone; + this.securityToken = securityToken; + this.version = version; + this.otaCert = immutableCopyOf(otaCert); + this.serial = serial; + this.esn = esn; + this.deviceConfiguration = deviceConfiguration; + this.macAddressType = immutableCopyOf(macAddressType); + this.fragment = fragment; + this.userName = userName; + this.userSerialNumber = userSerialNumber; + } + + private CheckinRequest(Builder builder) { + this(builder.imei, builder.androidId, builder.digest, builder.checkin, builder.desiredBuild, builder.locale, builder.loggingId, builder.marketCheckin, builder.macAddress, builder.meid, builder.accountCookie, builder.timeZone, builder.securityToken, builder.version, builder.otaCert, builder.serial, builder.esn, builder.deviceConfiguration, builder.macAddressType, builder.fragment, builder.userName, builder.userSerialNumber); + setBuilder(builder); + } + + @Override + public boolean equals(Object other) { + if (other == this) return true; + if (!(other instanceof CheckinRequest)) return false; + CheckinRequest o = (CheckinRequest) other; + return equals(imei, o.imei) + && equals(androidId, o.androidId) + && equals(digest, o.digest) + && equals(checkin, o.checkin) + && equals(desiredBuild, o.desiredBuild) + && equals(locale, o.locale) + && equals(loggingId, o.loggingId) + && equals(marketCheckin, o.marketCheckin) + && equals(macAddress, o.macAddress) + && equals(meid, o.meid) + && equals(accountCookie, o.accountCookie) + && equals(timeZone, o.timeZone) + && equals(securityToken, o.securityToken) + && equals(version, o.version) + && equals(otaCert, o.otaCert) + && equals(serial, o.serial) + && equals(esn, o.esn) + && equals(deviceConfiguration, o.deviceConfiguration) + && equals(macAddressType, o.macAddressType) + && equals(fragment, o.fragment) + && equals(userName, o.userName) + && equals(userSerialNumber, o.userSerialNumber); + } + + @Override + public int hashCode() { + int result = hashCode; + if (result == 0) { + result = imei != null ? imei.hashCode() : 0; + result = result * 37 + (androidId != null ? androidId.hashCode() : 0); + result = result * 37 + (digest != null ? digest.hashCode() : 0); + result = result * 37 + (checkin != null ? checkin.hashCode() : 0); + result = result * 37 + (desiredBuild != null ? desiredBuild.hashCode() : 0); + result = result * 37 + (locale != null ? locale.hashCode() : 0); + result = result * 37 + (loggingId != null ? loggingId.hashCode() : 0); + result = result * 37 + (marketCheckin != null ? marketCheckin.hashCode() : 0); + result = result * 37 + (macAddress != null ? macAddress.hashCode() : 1); + result = result * 37 + (meid != null ? meid.hashCode() : 0); + result = result * 37 + (accountCookie != null ? accountCookie.hashCode() : 1); + result = result * 37 + (timeZone != null ? timeZone.hashCode() : 0); + result = result * 37 + (securityToken != null ? securityToken.hashCode() : 0); + result = result * 37 + (version != null ? version.hashCode() : 0); + result = result * 37 + (otaCert != null ? otaCert.hashCode() : 1); + result = result * 37 + (serial != null ? serial.hashCode() : 0); + result = result * 37 + (esn != null ? esn.hashCode() : 0); + result = result * 37 + (deviceConfiguration != null ? deviceConfiguration.hashCode() : 0); + result = result * 37 + (macAddressType != null ? macAddressType.hashCode() : 1); + result = result * 37 + (fragment != null ? fragment.hashCode() : 0); + result = result * 37 + (userName != null ? userName.hashCode() : 0); + result = result * 37 + (userSerialNumber != null ? userSerialNumber.hashCode() : 0); + hashCode = result; + } + return result; + } + + public static final class Builder extends Message.Builder { + + public String imei; + public Long androidId; + public String digest; + public Checkin checkin; + public String desiredBuild; + public String locale; + public Long loggingId; + public String marketCheckin; + public List macAddress; + public String meid; + public List accountCookie; + public String timeZone; + public Long securityToken; + public Integer version; + public List otaCert; + public String serial; + public String esn; + public DeviceConfig deviceConfiguration; + public List macAddressType; + public Integer fragment; + public String userName; + public Integer userSerialNumber; + + public Builder() { + } + + public Builder(CheckinRequest message) { + super(message); + if (message == null) return; + this.imei = message.imei; + this.androidId = message.androidId; + this.digest = message.digest; + this.checkin = message.checkin; + this.desiredBuild = message.desiredBuild; + this.locale = message.locale; + this.loggingId = message.loggingId; + this.marketCheckin = message.marketCheckin; + this.macAddress = copyOf(message.macAddress); + this.meid = message.meid; + this.accountCookie = copyOf(message.accountCookie); + this.timeZone = message.timeZone; + this.securityToken = message.securityToken; + this.version = message.version; + this.otaCert = copyOf(message.otaCert); + this.serial = message.serial; + this.esn = message.esn; + this.deviceConfiguration = message.deviceConfiguration; + this.macAddressType = copyOf(message.macAddressType); + this.fragment = message.fragment; + this.userName = message.userName; + this.userSerialNumber = message.userSerialNumber; + } + + public Builder imei(String imei) { + this.imei = imei; + return this; + } + + /** + * unused + */ + public Builder androidId(Long androidId) { + this.androidId = androidId; + return this; + } + + /** + * Gservices["android_id"] or 0 + */ + public Builder digest(String digest) { + this.digest = digest; + return this; + } + + /** + * Gservices["digest"] or "" + */ + public Builder checkin(Checkin checkin) { + this.checkin = checkin; + return this; + } + + public Builder desiredBuild(String desiredBuild) { + this.desiredBuild = desiredBuild; + return this; + } + + /** + * unused + */ + public Builder locale(String locale) { + this.locale = locale; + return this; + } + + /** + * Locale.toString + */ + public Builder loggingId(Long loggingId) { + this.loggingId = loggingId; + return this; + } + + /** + * GoogleSettingsContract.Partner["logging_id2"] + */ + public Builder marketCheckin(String marketCheckin) { + this.marketCheckin = marketCheckin; + return this; + } + + /** + * unused + */ + public Builder macAddress(List macAddress) { + this.macAddress = checkForNulls(macAddress); + return this; + } + + /** + * NetworkInfo.getExtraInfo, WifiInfo.getMacAddress (12 hex-digits) + */ + public Builder meid(String meid) { + this.meid = meid; + return this; + } + + /** + * TelephonyManager.getDeviceId (14 hex-digits) + */ + public Builder accountCookie(List accountCookie) { + this.accountCookie = checkForNulls(accountCookie); + return this; + } + + /** + * "[]" followed by "" + */ + public Builder timeZone(String timeZone) { + this.timeZone = timeZone; + return this; + } + + /** + * TimeZone.getId + */ + public Builder securityToken(Long securityToken) { + this.securityToken = securityToken; + return this; + } + + public Builder version(Integer version) { + this.version = version; + return this; + } + + /** + * 3 if securityToken != 0 OR androidId == 0 + */ + public Builder otaCert(List otaCert) { + this.otaCert = checkForNulls(otaCert); + return this; + } + + /** + * SHA-1 of each in /system/etc/security/otacerts.zip or "--IOException--" or "--no-output--" + */ + public Builder serial(String serial) { + this.serial = serial; + return this; + } + + /** + * Build.SERIAL != "unknown" + */ + public Builder esn(String esn) { + this.esn = esn; + return this; + } + + /** + * TelephonyManager.getDeviceId (8 hex-digits) + */ + public Builder deviceConfiguration(DeviceConfig deviceConfiguration) { + this.deviceConfiguration = deviceConfiguration; + return this; + } + + public Builder macAddressType(List macAddressType) { + this.macAddressType = checkForNulls(macAddressType); + return this; + } + + /** + * "ethernet", "wifi" + */ + public Builder fragment(Integer fragment) { + this.fragment = fragment; + return this; + } + + /** + * unknown (use 0) + */ + public Builder userName(String userName) { + this.userName = userName; + return this; + } + + /** + * unused + */ + public Builder userSerialNumber(Integer userSerialNumber) { + this.userSerialNumber = userSerialNumber; + return this; + } + + @Override + public CheckinRequest build() { + return new CheckinRequest(this); + } + } + + public static final class DeviceConfig extends Message { + + public static final Integer DEFAULT_TOUCHSCREEN = 0; + public static final Integer DEFAULT_KEYBOARDTYPE = 0; + public static final Integer DEFAULT_NAVIGATION = 0; + public static final Integer DEFAULT_SCREENLAYOUT = 0; + public static final Boolean DEFAULT_HASHARDKEYBOARD = false; + public static final Boolean DEFAULT_HASFIVEWAYNAVIGATION = false; + public static final Integer DEFAULT_DENSITYDPI = 0; + public static final Integer DEFAULT_GLESVERSION = 0; + public static final List DEFAULT_SHAREDLIBRARY = Collections.emptyList(); + public static final List DEFAULT_AVAILABLEFEATURE = Collections.emptyList(); + public static final List DEFAULT_NATIVEPLATFORM = Collections.emptyList(); + public static final Integer DEFAULT_WIDTHPIXELS = 0; + public static final Integer DEFAULT_HEIGHTPIXELS = 0; + public static final List DEFAULT_LOCALE = Collections.emptyList(); + public static final List DEFAULT_GLEXTENSION = Collections.emptyList(); + public static final Integer DEFAULT_DEVICECLASS = 0; + public static final Integer DEFAULT_MAXAPKDOWNLOADSIZEMB = 0; + + @ProtoField(tag = 1, type = INT32) + public final Integer touchScreen; + + /** + * ConfigurationInfo.reqTouchScreen + */ + @ProtoField(tag = 2, type = INT32) + public final Integer keyboardType; + + /** + * ConfigurationInfo.reqKeyboardType + */ + @ProtoField(tag = 3, type = INT32) + public final Integer navigation; + + /** + * ConfigurationInfo.reqNavigation + */ + @ProtoField(tag = 4, type = INT32) + public final Integer screenLayout; + + /** + * ConfigurationInfo.screenLayout + */ + @ProtoField(tag = 5, type = BOOL) + public final Boolean hasHardKeyboard; + + /** + * ConfigurationInfo.reqInputFeatures & ConfigurationInfo.INPUT_FEATURE_HARD_KEYBOARD + */ + @ProtoField(tag = 6, type = BOOL) + public final Boolean hasFiveWayNavigation; + + /** + * ConfigurationInfo.reqInputFeatures & ConfigurationInfo.INPUT_FEATURE_FIVE_WAY_NAV + */ + @ProtoField(tag = 7, type = INT32) + public final Integer densityDpi; + + /** + * DisplayMetrics.densityDpi + */ + @ProtoField(tag = 8, type = INT32) + public final Integer glEsVersion; + + /** + * ConfigurationInfo.reqGlEsVersion + */ + @ProtoField(tag = 9, type = STRING, label = REPEATED) + public final List sharedLibrary; + + /** + * PackageManager.getSystemSharedLibraryNames + */ + @ProtoField(tag = 10, type = STRING, label = REPEATED) + public final List availableFeature; + + /** + * PackageManager.getSystemAvailableFeatures + */ + @ProtoField(tag = 11, type = STRING, label = REPEATED) + public final List nativePlatform; + + /** + * Build.CPU_ABI (and Build.CPU_ABI2 != "unknown") + */ + @ProtoField(tag = 12, type = INT32) + public final Integer widthPixels; + + /** + * DisplayMetrics.widthPixels + */ + @ProtoField(tag = 13, type = INT32) + public final Integer heightPixels; + + /** + * DisplayMetrics.heightPixels + */ + @ProtoField(tag = 14, type = STRING, label = REPEATED) + public final List locale; + + /** + * Context.getAssets.getLocales + */ + @ProtoField(tag = 15, type = STRING, label = REPEATED) + public final List glExtension; + + /** + * GLES10.glGetString(GLES10.GL_EXTENSIONS) + */ + @ProtoField(tag = 16, type = INT32) + public final Integer deviceClass; + + /** + * unused + */ + @ProtoField(tag = 17, type = INT32) + public final Integer maxApkDownloadSizeMb; + + public DeviceConfig(Integer touchScreen, Integer keyboardType, Integer navigation, Integer screenLayout, Boolean hasHardKeyboard, Boolean hasFiveWayNavigation, Integer densityDpi, Integer glEsVersion, List sharedLibrary, List availableFeature, List nativePlatform, Integer widthPixels, Integer heightPixels, List locale, List glExtension, Integer deviceClass, Integer maxApkDownloadSizeMb) { + this.touchScreen = touchScreen; + this.keyboardType = keyboardType; + this.navigation = navigation; + this.screenLayout = screenLayout; + this.hasHardKeyboard = hasHardKeyboard; + this.hasFiveWayNavigation = hasFiveWayNavigation; + this.densityDpi = densityDpi; + this.glEsVersion = glEsVersion; + this.sharedLibrary = immutableCopyOf(sharedLibrary); + this.availableFeature = immutableCopyOf(availableFeature); + this.nativePlatform = immutableCopyOf(nativePlatform); + this.widthPixels = widthPixels; + this.heightPixels = heightPixels; + this.locale = immutableCopyOf(locale); + this.glExtension = immutableCopyOf(glExtension); + this.deviceClass = deviceClass; + this.maxApkDownloadSizeMb = maxApkDownloadSizeMb; + } + + private DeviceConfig(Builder builder) { + this(builder.touchScreen, builder.keyboardType, builder.navigation, builder.screenLayout, builder.hasHardKeyboard, builder.hasFiveWayNavigation, builder.densityDpi, builder.glEsVersion, builder.sharedLibrary, builder.availableFeature, builder.nativePlatform, builder.widthPixels, builder.heightPixels, builder.locale, builder.glExtension, builder.deviceClass, builder.maxApkDownloadSizeMb); + setBuilder(builder); + } + + @Override + public boolean equals(Object other) { + if (other == this) return true; + if (!(other instanceof DeviceConfig)) return false; + DeviceConfig o = (DeviceConfig) other; + return equals(touchScreen, o.touchScreen) + && equals(keyboardType, o.keyboardType) + && equals(navigation, o.navigation) + && equals(screenLayout, o.screenLayout) + && equals(hasHardKeyboard, o.hasHardKeyboard) + && equals(hasFiveWayNavigation, o.hasFiveWayNavigation) + && equals(densityDpi, o.densityDpi) + && equals(glEsVersion, o.glEsVersion) + && equals(sharedLibrary, o.sharedLibrary) + && equals(availableFeature, o.availableFeature) + && equals(nativePlatform, o.nativePlatform) + && equals(widthPixels, o.widthPixels) + && equals(heightPixels, o.heightPixels) + && equals(locale, o.locale) + && equals(glExtension, o.glExtension) + && equals(deviceClass, o.deviceClass) + && equals(maxApkDownloadSizeMb, o.maxApkDownloadSizeMb); + } + + @Override + public int hashCode() { + int result = hashCode; + if (result == 0) { + result = touchScreen != null ? touchScreen.hashCode() : 0; + result = result * 37 + (keyboardType != null ? keyboardType.hashCode() : 0); + result = result * 37 + (navigation != null ? navigation.hashCode() : 0); + result = result * 37 + (screenLayout != null ? screenLayout.hashCode() : 0); + result = result * 37 + (hasHardKeyboard != null ? hasHardKeyboard.hashCode() : 0); + result = result * 37 + (hasFiveWayNavigation != null ? hasFiveWayNavigation.hashCode() : 0); + result = result * 37 + (densityDpi != null ? densityDpi.hashCode() : 0); + result = result * 37 + (glEsVersion != null ? glEsVersion.hashCode() : 0); + result = result * 37 + (sharedLibrary != null ? sharedLibrary.hashCode() : 1); + result = result * 37 + (availableFeature != null ? availableFeature.hashCode() : 1); + result = result * 37 + (nativePlatform != null ? nativePlatform.hashCode() : 1); + result = result * 37 + (widthPixels != null ? widthPixels.hashCode() : 0); + result = result * 37 + (heightPixels != null ? heightPixels.hashCode() : 0); + result = result * 37 + (locale != null ? locale.hashCode() : 1); + result = result * 37 + (glExtension != null ? glExtension.hashCode() : 1); + result = result * 37 + (deviceClass != null ? deviceClass.hashCode() : 0); + result = result * 37 + (maxApkDownloadSizeMb != null ? maxApkDownloadSizeMb.hashCode() : 0); + hashCode = result; + } + return result; + } + + public static final class Builder extends Message.Builder { + + public Integer touchScreen; + public Integer keyboardType; + public Integer navigation; + public Integer screenLayout; + public Boolean hasHardKeyboard; + public Boolean hasFiveWayNavigation; + public Integer densityDpi; + public Integer glEsVersion; + public List sharedLibrary; + public List availableFeature; + public List nativePlatform; + public Integer widthPixels; + public Integer heightPixels; + public List locale; + public List glExtension; + public Integer deviceClass; + public Integer maxApkDownloadSizeMb; + + public Builder() { + } + + public Builder(DeviceConfig message) { + super(message); + if (message == null) return; + this.touchScreen = message.touchScreen; + this.keyboardType = message.keyboardType; + this.navigation = message.navigation; + this.screenLayout = message.screenLayout; + this.hasHardKeyboard = message.hasHardKeyboard; + this.hasFiveWayNavigation = message.hasFiveWayNavigation; + this.densityDpi = message.densityDpi; + this.glEsVersion = message.glEsVersion; + this.sharedLibrary = copyOf(message.sharedLibrary); + this.availableFeature = copyOf(message.availableFeature); + this.nativePlatform = copyOf(message.nativePlatform); + this.widthPixels = message.widthPixels; + this.heightPixels = message.heightPixels; + this.locale = copyOf(message.locale); + this.glExtension = copyOf(message.glExtension); + this.deviceClass = message.deviceClass; + this.maxApkDownloadSizeMb = message.maxApkDownloadSizeMb; + } + + public Builder touchScreen(Integer touchScreen) { + this.touchScreen = touchScreen; + return this; + } + + /** + * ConfigurationInfo.reqTouchScreen + */ + public Builder keyboardType(Integer keyboardType) { + this.keyboardType = keyboardType; + return this; + } + + /** + * ConfigurationInfo.reqKeyboardType + */ + public Builder navigation(Integer navigation) { + this.navigation = navigation; + return this; + } + + /** + * ConfigurationInfo.reqNavigation + */ + public Builder screenLayout(Integer screenLayout) { + this.screenLayout = screenLayout; + return this; + } + + /** + * ConfigurationInfo.screenLayout + */ + public Builder hasHardKeyboard(Boolean hasHardKeyboard) { + this.hasHardKeyboard = hasHardKeyboard; + return this; + } + + /** + * ConfigurationInfo.reqInputFeatures & ConfigurationInfo.INPUT_FEATURE_HARD_KEYBOARD + */ + public Builder hasFiveWayNavigation(Boolean hasFiveWayNavigation) { + this.hasFiveWayNavigation = hasFiveWayNavigation; + return this; + } + + /** + * ConfigurationInfo.reqInputFeatures & ConfigurationInfo.INPUT_FEATURE_FIVE_WAY_NAV + */ + public Builder densityDpi(Integer densityDpi) { + this.densityDpi = densityDpi; + return this; + } + + /** + * DisplayMetrics.densityDpi + */ + public Builder glEsVersion(Integer glEsVersion) { + this.glEsVersion = glEsVersion; + return this; + } + + /** + * ConfigurationInfo.reqGlEsVersion + */ + public Builder sharedLibrary(List sharedLibrary) { + this.sharedLibrary = checkForNulls(sharedLibrary); + return this; + } + + /** + * PackageManager.getSystemSharedLibraryNames + */ + public Builder availableFeature(List availableFeature) { + this.availableFeature = checkForNulls(availableFeature); + return this; + } + + /** + * PackageManager.getSystemAvailableFeatures + */ + public Builder nativePlatform(List nativePlatform) { + this.nativePlatform = checkForNulls(nativePlatform); + return this; + } + + /** + * Build.CPU_ABI (and Build.CPU_ABI2 != "unknown") + */ + public Builder widthPixels(Integer widthPixels) { + this.widthPixels = widthPixels; + return this; + } + + /** + * DisplayMetrics.widthPixels + */ + public Builder heightPixels(Integer heightPixels) { + this.heightPixels = heightPixels; + return this; + } + + /** + * DisplayMetrics.heightPixels + */ + public Builder locale(List locale) { + this.locale = checkForNulls(locale); + return this; + } + + /** + * Context.getAssets.getLocales + */ + public Builder glExtension(List glExtension) { + this.glExtension = checkForNulls(glExtension); + return this; + } + + /** + * GLES10.glGetString(GLES10.GL_EXTENSIONS) + */ + public Builder deviceClass(Integer deviceClass) { + this.deviceClass = deviceClass; + return this; + } + + /** + * unused + */ + public Builder maxApkDownloadSizeMb(Integer maxApkDownloadSizeMb) { + this.maxApkDownloadSizeMb = maxApkDownloadSizeMb; + return this; + } + + @Override + public DeviceConfig build() { + return new DeviceConfig(this); + } + } + } + + public static final class Checkin extends Message { + + public static final Long DEFAULT_LASTCHECKINMS = 0L; + public static final List DEFAULT_EVENT = Collections.emptyList(); + public static final List DEFAULT_STAT = Collections.emptyList(); + public static final List DEFAULT_REQUESTEDGROUP = Collections.emptyList(); + public static final String DEFAULT_CELLOPERATOR = ""; + public static final String DEFAULT_SIMOPERATOR = ""; + public static final String DEFAULT_ROAMING = ""; + public static final Integer DEFAULT_USERNUMBER = 0; + + @ProtoField(tag = 1) + public final Checkin.Build build; + + @ProtoField(tag = 2, type = INT64) + public final Long lastCheckinMs; + + /** + * or 0 + */ + @ProtoField(tag = 3, label = REPEATED, messageType = Checkin.Event.class) + public final List event; + + @ProtoField(tag = 4, label = REPEATED, messageType = Checkin.Statistic.class) + public final List stat; + + @ProtoField(tag = 5, type = STRING, label = REPEATED) + public final List requestedGroup; + + /** + * unused + */ + @ProtoField(tag = 6, type = STRING) + public final String cellOperator; + + /** + * TelephonyManager.getNetworkOperator != null|empty + */ + @ProtoField(tag = 7, type = STRING) + public final String simOperator; + + /** + * TelephonyManager.getSimOperator != null|empty + */ + @ProtoField(tag = 8, type = STRING) + public final String roaming; + + /** + * "mobile/notmobile/unknown-roaming/notroaming/unknown" + */ + @ProtoField(tag = 9, type = INT32) + public final Integer userNumber; + + public Checkin(Checkin.Build build, Long lastCheckinMs, List event, List stat, List requestedGroup, String cellOperator, String simOperator, String roaming, Integer userNumber) { + this.build = build; + this.lastCheckinMs = lastCheckinMs; + this.event = immutableCopyOf(event); + this.stat = immutableCopyOf(stat); + this.requestedGroup = immutableCopyOf(requestedGroup); + this.cellOperator = cellOperator; + this.simOperator = simOperator; + this.roaming = roaming; + this.userNumber = userNumber; + } + + private Checkin(Builder builder) { + this(builder.build, builder.lastCheckinMs, builder.event, builder.stat, builder.requestedGroup, builder.cellOperator, builder.simOperator, builder.roaming, builder.userNumber); + setBuilder(builder); + } + + @Override + public boolean equals(Object other) { + if (other == this) return true; + if (!(other instanceof Checkin)) return false; + Checkin o = (Checkin) other; + return equals(build, o.build) + && equals(lastCheckinMs, o.lastCheckinMs) + && equals(event, o.event) + && equals(stat, o.stat) + && equals(requestedGroup, o.requestedGroup) + && equals(cellOperator, o.cellOperator) + && equals(simOperator, o.simOperator) + && equals(roaming, o.roaming) + && equals(userNumber, o.userNumber); + } + + @Override + public int hashCode() { + int result = hashCode; + if (result == 0) { + result = build != null ? build.hashCode() : 0; + result = result * 37 + (lastCheckinMs != null ? lastCheckinMs.hashCode() : 0); + result = result * 37 + (event != null ? event.hashCode() : 1); + result = result * 37 + (stat != null ? stat.hashCode() : 1); + result = result * 37 + (requestedGroup != null ? requestedGroup.hashCode() : 1); + result = result * 37 + (cellOperator != null ? cellOperator.hashCode() : 0); + result = result * 37 + (simOperator != null ? simOperator.hashCode() : 0); + result = result * 37 + (roaming != null ? roaming.hashCode() : 0); + result = result * 37 + (userNumber != null ? userNumber.hashCode() : 0); + hashCode = result; + } + return result; + } + + public static final class Builder extends Message.Builder { + + public Checkin.Build build; + public Long lastCheckinMs; + public List event; + public List stat; + public List requestedGroup; + public String cellOperator; + public String simOperator; + public String roaming; + public Integer userNumber; + + public Builder() { + } + + public Builder(Checkin message) { + super(message); + if (message == null) return; + this.build = message.build; + this.lastCheckinMs = message.lastCheckinMs; + this.event = copyOf(message.event); + this.stat = copyOf(message.stat); + this.requestedGroup = copyOf(message.requestedGroup); + this.cellOperator = message.cellOperator; + this.simOperator = message.simOperator; + this.roaming = message.roaming; + this.userNumber = message.userNumber; + } + + public Builder build(Checkin.Build build) { + this.build = build; + return this; + } + + public Builder lastCheckinMs(Long lastCheckinMs) { + this.lastCheckinMs = lastCheckinMs; + return this; + } + + /** + * or 0 + */ + public Builder event(List event) { + this.event = checkForNulls(event); + return this; + } + + public Builder stat(List stat) { + this.stat = checkForNulls(stat); + return this; + } + + public Builder requestedGroup(List requestedGroup) { + this.requestedGroup = checkForNulls(requestedGroup); + return this; + } + + /** + * unused + */ + public Builder cellOperator(String cellOperator) { + this.cellOperator = cellOperator; + return this; + } + + /** + * TelephonyManager.getNetworkOperator != null|empty + */ + public Builder simOperator(String simOperator) { + this.simOperator = simOperator; + return this; + } + + /** + * TelephonyManager.getSimOperator != null|empty + */ + public Builder roaming(String roaming) { + this.roaming = roaming; + return this; + } + + /** + * "mobile/notmobile/unknown-roaming/notroaming/unknown" + */ + public Builder userNumber(Integer userNumber) { + this.userNumber = userNumber; + return this; + } + + @Override + public Checkin build() { + return new Checkin(this); + } + } + + public static final class Event extends Message { + + public static final String DEFAULT_TAG = ""; + public static final String DEFAULT_VALUE = ""; + public static final Long DEFAULT_TIMEMS = 0L; + + @ProtoField(tag = 1, type = STRING) + public final String tag; + + @ProtoField(tag = 2, type = STRING) + public final String value; + + @ProtoField(tag = 3, type = INT64) + public final Long timeMs; + + public Event(String tag, String value, Long timeMs) { + this.tag = tag; + this.value = value; + this.timeMs = timeMs; + } + + private Event(Builder builder) { + this(builder.tag, builder.value, builder.timeMs); + setBuilder(builder); + } + + @Override + public boolean equals(Object other) { + if (other == this) return true; + if (!(other instanceof Event)) return false; + Event o = (Event) other; + return equals(tag, o.tag) + && equals(value, o.value) + && equals(timeMs, o.timeMs); + } + + @Override + public int hashCode() { + int result = hashCode; + if (result == 0) { + result = tag != null ? tag.hashCode() : 0; + result = result * 37 + (value != null ? value.hashCode() : 0); + result = result * 37 + (timeMs != null ? timeMs.hashCode() : 0); + hashCode = result; + } + return result; + } + + public static final class Builder extends Message.Builder { + + public String tag; + public String value; + public Long timeMs; + + public Builder() { + } + + public Builder(Event message) { + super(message); + if (message == null) return; + this.tag = message.tag; + this.value = message.value; + this.timeMs = message.timeMs; + } + + public Builder tag(String tag) { + this.tag = tag; + return this; + } + + public Builder value(String value) { + this.value = value; + return this; + } + + public Builder timeMs(Long timeMs) { + this.timeMs = timeMs; + return this; + } + + @Override + public Event build() { + return new Event(this); + } + } + } + + public static final class Statistic extends Message { + + public static final String DEFAULT_TAG = ""; + public static final Integer DEFAULT_COUNT = 0; + public static final Float DEFAULT_SUM = 0F; + + @ProtoField(tag = 1, type = STRING) + public final String tag; + + @ProtoField(tag = 2, type = INT32) + public final Integer count; + + @ProtoField(tag = 3, type = FLOAT) + public final Float sum; + + public Statistic(String tag, Integer count, Float sum) { + this.tag = tag; + this.count = count; + this.sum = sum; + } + + private Statistic(Builder builder) { + this(builder.tag, builder.count, builder.sum); + setBuilder(builder); + } + + @Override + public boolean equals(Object other) { + if (other == this) return true; + if (!(other instanceof Statistic)) return false; + Statistic o = (Statistic) other; + return equals(tag, o.tag) + && equals(count, o.count) + && equals(sum, o.sum); + } + + @Override + public int hashCode() { + int result = hashCode; + if (result == 0) { + result = tag != null ? tag.hashCode() : 0; + result = result * 37 + (count != null ? count.hashCode() : 0); + result = result * 37 + (sum != null ? sum.hashCode() : 0); + hashCode = result; + } + return result; + } + + public static final class Builder extends Message.Builder { + + public String tag; + public Integer count; + public Float sum; + + public Builder() { + } + + public Builder(Statistic message) { + super(message); + if (message == null) return; + this.tag = message.tag; + this.count = message.count; + this.sum = message.sum; + } + + public Builder tag(String tag) { + this.tag = tag; + return this; + } + + public Builder count(Integer count) { + this.count = count; + return this; + } + + public Builder sum(Float sum) { + this.sum = sum; + return this; + } + + @Override + public Statistic build() { + return new Statistic(this); + } + } + } + + public static final class Build extends Message { + + public static final String DEFAULT_FINGERPRINT = ""; + public static final String DEFAULT_HARDWARE = ""; + public static final String DEFAULT_BRAND = ""; + public static final String DEFAULT_RADIO = ""; + public static final String DEFAULT_BOOTLOADER = ""; + public static final String DEFAULT_CLIENTID = ""; + public static final Long DEFAULT_TIME = 0L; + public static final Integer DEFAULT_PACKAGEVERSIONCODE = 0; + public static final String DEFAULT_DEVICE = ""; + public static final Integer DEFAULT_SDKVERSION = 0; + public static final String DEFAULT_MODEL = ""; + public static final String DEFAULT_MANUFACTURER = ""; + public static final String DEFAULT_PRODUCT = ""; + public static final Boolean DEFAULT_OTAINSTALLED = false; + + @ProtoField(tag = 1, type = STRING) + public final String fingerprint; + + /** + * Build.FINGERPRINT + */ + @ProtoField(tag = 2, type = STRING) + public final String hardware; + + /** + * Build.HARDWARE + */ + @ProtoField(tag = 3, type = STRING) + public final String brand; + + /** + * Build.BRAND + */ + @ProtoField(tag = 4, type = STRING) + public final String radio; + + /** + * Build.getRadioVersion() + */ + @ProtoField(tag = 5, type = STRING) + public final String bootloader; + + /** + * Build.BOOTLOADER + */ + @ProtoField(tag = 6, type = STRING) + public final String clientId; + + /** + * GoogleSettingsContract.Partner["client_id"] + */ + @ProtoField(tag = 7, type = INT64) + public final Long time; + + /** + * Build.TIME / 1000L + */ + @ProtoField(tag = 8, type = INT32) + public final Integer packageVersionCode; + + /** + * PackageInfo.versionCode + */ + @ProtoField(tag = 9, type = STRING) + public final String device; + + /** + * Build.DEVICE + */ + @ProtoField(tag = 10, type = INT32) + public final Integer sdkVersion; + + /** + * Build.VERSION.SDK_INT + */ + @ProtoField(tag = 11, type = STRING) + public final String model; + + /** + * Build.MODEL + */ + @ProtoField(tag = 12, type = STRING) + public final String manufacturer; + + /** + * Build.MANUFACTURER + */ + @ProtoField(tag = 13, type = STRING) + public final String product; + + /** + * Build.PRODUCT + */ + @ProtoField(tag = 14, type = BOOL) + public final Boolean otaInstalled; + + public Build(String fingerprint, String hardware, String brand, String radio, String bootloader, String clientId, Long time, Integer packageVersionCode, String device, Integer sdkVersion, String model, String manufacturer, String product, Boolean otaInstalled) { + this.fingerprint = fingerprint; + this.hardware = hardware; + this.brand = brand; + this.radio = radio; + this.bootloader = bootloader; + this.clientId = clientId; + this.time = time; + this.packageVersionCode = packageVersionCode; + this.device = device; + this.sdkVersion = sdkVersion; + this.model = model; + this.manufacturer = manufacturer; + this.product = product; + this.otaInstalled = otaInstalled; + } + + private Build(Builder builder) { + this(builder.fingerprint, builder.hardware, builder.brand, builder.radio, builder.bootloader, builder.clientId, builder.time, builder.packageVersionCode, builder.device, builder.sdkVersion, builder.model, builder.manufacturer, builder.product, builder.otaInstalled); + setBuilder(builder); + } + + @Override + public boolean equals(Object other) { + if (other == this) return true; + if (!(other instanceof Build)) return false; + Build o = (Build) other; + return equals(fingerprint, o.fingerprint) + && equals(hardware, o.hardware) + && equals(brand, o.brand) + && equals(radio, o.radio) + && equals(bootloader, o.bootloader) + && equals(clientId, o.clientId) + && equals(time, o.time) + && equals(packageVersionCode, o.packageVersionCode) + && equals(device, o.device) + && equals(sdkVersion, o.sdkVersion) + && equals(model, o.model) + && equals(manufacturer, o.manufacturer) + && equals(product, o.product) + && equals(otaInstalled, o.otaInstalled); + } + + @Override + public int hashCode() { + int result = hashCode; + if (result == 0) { + result = fingerprint != null ? fingerprint.hashCode() : 0; + result = result * 37 + (hardware != null ? hardware.hashCode() : 0); + result = result * 37 + (brand != null ? brand.hashCode() : 0); + result = result * 37 + (radio != null ? radio.hashCode() : 0); + result = result * 37 + (bootloader != null ? bootloader.hashCode() : 0); + result = result * 37 + (clientId != null ? clientId.hashCode() : 0); + result = result * 37 + (time != null ? time.hashCode() : 0); + result = result * 37 + (packageVersionCode != null ? packageVersionCode.hashCode() : 0); + result = result * 37 + (device != null ? device.hashCode() : 0); + result = result * 37 + (sdkVersion != null ? sdkVersion.hashCode() : 0); + result = result * 37 + (model != null ? model.hashCode() : 0); + result = result * 37 + (manufacturer != null ? manufacturer.hashCode() : 0); + result = result * 37 + (product != null ? product.hashCode() : 0); + result = result * 37 + (otaInstalled != null ? otaInstalled.hashCode() : 0); + hashCode = result; + } + return result; + } + + public static final class Builder extends Message.Builder { + + public String fingerprint; + public String hardware; + public String brand; + public String radio; + public String bootloader; + public String clientId; + public Long time; + public Integer packageVersionCode; + public String device; + public Integer sdkVersion; + public String model; + public String manufacturer; + public String product; + public Boolean otaInstalled; + + public Builder() { + } + + public Builder(Build message) { + super(message); + if (message == null) return; + this.fingerprint = message.fingerprint; + this.hardware = message.hardware; + this.brand = message.brand; + this.radio = message.radio; + this.bootloader = message.bootloader; + this.clientId = message.clientId; + this.time = message.time; + this.packageVersionCode = message.packageVersionCode; + this.device = message.device; + this.sdkVersion = message.sdkVersion; + this.model = message.model; + this.manufacturer = message.manufacturer; + this.product = message.product; + this.otaInstalled = message.otaInstalled; + } + + public Builder fingerprint(String fingerprint) { + this.fingerprint = fingerprint; + return this; + } + + /** + * Build.FINGERPRINT + */ + public Builder hardware(String hardware) { + this.hardware = hardware; + return this; + } + + /** + * Build.HARDWARE + */ + public Builder brand(String brand) { + this.brand = brand; + return this; + } + + /** + * Build.BRAND + */ + public Builder radio(String radio) { + this.radio = radio; + return this; + } + + /** + * Build.getRadioVersion() + */ + public Builder bootloader(String bootloader) { + this.bootloader = bootloader; + return this; + } + + /** + * Build.BOOTLOADER + */ + public Builder clientId(String clientId) { + this.clientId = clientId; + return this; + } + + /** + * GoogleSettingsContract.Partner["client_id"] + */ + public Builder time(Long time) { + this.time = time; + return this; + } + + /** + * Build.TIME / 1000L + */ + public Builder packageVersionCode(Integer packageVersionCode) { + this.packageVersionCode = packageVersionCode; + return this; + } + + /** + * PackageInfo.versionCode + */ + public Builder device(String device) { + this.device = device; + return this; + } + + /** + * Build.DEVICE + */ + public Builder sdkVersion(Integer sdkVersion) { + this.sdkVersion = sdkVersion; + return this; + } + + /** + * Build.VERSION.SDK_INT + */ + public Builder model(String model) { + this.model = model; + return this; + } + + /** + * Build.MODEL + */ + public Builder manufacturer(String manufacturer) { + this.manufacturer = manufacturer; + return this; + } + + /** + * Build.MANUFACTURER + */ + public Builder product(String product) { + this.product = product; + return this; + } + + /** + * Build.PRODUCT + */ + public Builder otaInstalled(Boolean otaInstalled) { + this.otaInstalled = otaInstalled; + return this; + } + + @Override + public Build build() { + return new Build(this); + } + } + } + } +} diff --git a/protos-src/org/microg/gms/checkin/CheckinResponse.java b/protos-src/org/microg/gms/checkin/CheckinResponse.java new file mode 100644 index 00000000..155f67bd --- /dev/null +++ b/protos-src/org/microg/gms/checkin/CheckinResponse.java @@ -0,0 +1,462 @@ +// Code generated by Wire protocol buffer compiler, do not edit. +// Source file: protos-repo/checkin.proto +package org.microg.gms.checkin; + +import com.squareup.wire.Message; +import com.squareup.wire.ProtoField; +import java.util.Collections; +import java.util.List; +import okio.ByteString; + +import static com.squareup.wire.Message.Datatype.BOOL; +import static com.squareup.wire.Message.Datatype.BYTES; +import static com.squareup.wire.Message.Datatype.FIXED64; +import static com.squareup.wire.Message.Datatype.INT64; +import static com.squareup.wire.Message.Datatype.STRING; +import static com.squareup.wire.Message.Label.REPEATED; + +public final class CheckinResponse extends Message { + + public static final Boolean DEFAULT_STATSOK = false; + public static final List DEFAULT_INTENT = Collections.emptyList(); + public static final Long DEFAULT_TIMEMS = 0L; + public static final String DEFAULT_DIGEST = ""; + public static final List DEFAULT_SETTING = Collections.emptyList(); + public static final Boolean DEFAULT_MARKETOK = false; + public static final Long DEFAULT_ANDROIDID = 0L; + public static final Long DEFAULT_SECURITYTOKEN = 0L; + public static final Boolean DEFAULT_SETTINGSDIFF = false; + public static final List DEFAULT_DELETESETTING = Collections.emptyList(); + + @ProtoField(tag = 1, type = BOOL) + public final Boolean statsOk; + + @ProtoField(tag = 2, label = REPEATED, messageType = Intent.class) + public final List intent; + + @ProtoField(tag = 3, type = INT64) + public final Long timeMs; + + @ProtoField(tag = 4, type = STRING) + public final String digest; + + @ProtoField(tag = 5, label = REPEATED, messageType = GservicesSetting.class) + public final List setting; + + @ProtoField(tag = 6, type = BOOL) + public final Boolean marketOk; + + @ProtoField(tag = 7, type = FIXED64) + public final Long androidId; + + @ProtoField(tag = 8, type = FIXED64) + public final Long securityToken; + + @ProtoField(tag = 9, type = BOOL) + public final Boolean settingsDiff; + + @ProtoField(tag = 10, type = STRING, label = REPEATED) + public final List deleteSetting; + + public CheckinResponse(Boolean statsOk, List intent, Long timeMs, String digest, List setting, Boolean marketOk, Long androidId, Long securityToken, Boolean settingsDiff, List deleteSetting) { + this.statsOk = statsOk; + this.intent = immutableCopyOf(intent); + this.timeMs = timeMs; + this.digest = digest; + this.setting = immutableCopyOf(setting); + this.marketOk = marketOk; + this.androidId = androidId; + this.securityToken = securityToken; + this.settingsDiff = settingsDiff; + this.deleteSetting = immutableCopyOf(deleteSetting); + } + + private CheckinResponse(Builder builder) { + this(builder.statsOk, builder.intent, builder.timeMs, builder.digest, builder.setting, builder.marketOk, builder.androidId, builder.securityToken, builder.settingsDiff, builder.deleteSetting); + setBuilder(builder); + } + + @Override + public boolean equals(Object other) { + if (other == this) return true; + if (!(other instanceof CheckinResponse)) return false; + CheckinResponse o = (CheckinResponse) other; + return equals(statsOk, o.statsOk) + && equals(intent, o.intent) + && equals(timeMs, o.timeMs) + && equals(digest, o.digest) + && equals(setting, o.setting) + && equals(marketOk, o.marketOk) + && equals(androidId, o.androidId) + && equals(securityToken, o.securityToken) + && equals(settingsDiff, o.settingsDiff) + && equals(deleteSetting, o.deleteSetting); + } + + @Override + public int hashCode() { + int result = hashCode; + if (result == 0) { + result = statsOk != null ? statsOk.hashCode() : 0; + result = result * 37 + (intent != null ? intent.hashCode() : 1); + result = result * 37 + (timeMs != null ? timeMs.hashCode() : 0); + result = result * 37 + (digest != null ? digest.hashCode() : 0); + result = result * 37 + (setting != null ? setting.hashCode() : 1); + result = result * 37 + (marketOk != null ? marketOk.hashCode() : 0); + result = result * 37 + (androidId != null ? androidId.hashCode() : 0); + result = result * 37 + (securityToken != null ? securityToken.hashCode() : 0); + result = result * 37 + (settingsDiff != null ? settingsDiff.hashCode() : 0); + result = result * 37 + (deleteSetting != null ? deleteSetting.hashCode() : 1); + hashCode = result; + } + return result; + } + + public static final class Builder extends Message.Builder { + + public Boolean statsOk; + public List intent; + public Long timeMs; + public String digest; + public List setting; + public Boolean marketOk; + public Long androidId; + public Long securityToken; + public Boolean settingsDiff; + public List deleteSetting; + + public Builder() { + } + + public Builder(CheckinResponse message) { + super(message); + if (message == null) return; + this.statsOk = message.statsOk; + this.intent = copyOf(message.intent); + this.timeMs = message.timeMs; + this.digest = message.digest; + this.setting = copyOf(message.setting); + this.marketOk = message.marketOk; + this.androidId = message.androidId; + this.securityToken = message.securityToken; + this.settingsDiff = message.settingsDiff; + this.deleteSetting = copyOf(message.deleteSetting); + } + + public Builder statsOk(Boolean statsOk) { + this.statsOk = statsOk; + return this; + } + + public Builder intent(List intent) { + this.intent = checkForNulls(intent); + return this; + } + + public Builder timeMs(Long timeMs) { + this.timeMs = timeMs; + return this; + } + + public Builder digest(String digest) { + this.digest = digest; + return this; + } + + public Builder setting(List setting) { + this.setting = checkForNulls(setting); + return this; + } + + public Builder marketOk(Boolean marketOk) { + this.marketOk = marketOk; + return this; + } + + public Builder androidId(Long androidId) { + this.androidId = androidId; + return this; + } + + public Builder securityToken(Long securityToken) { + this.securityToken = securityToken; + return this; + } + + public Builder settingsDiff(Boolean settingsDiff) { + this.settingsDiff = settingsDiff; + return this; + } + + public Builder deleteSetting(List deleteSetting) { + this.deleteSetting = checkForNulls(deleteSetting); + return this; + } + + @Override + public CheckinResponse build() { + return new CheckinResponse(this); + } + } + + public static final class Intent extends Message { + + public static final String DEFAULT_ACTION = ""; + public static final String DEFAULT_DATAURI = ""; + public static final String DEFAULT_MIMETYPE = ""; + public static final String DEFAULT_JAVACLASS = ""; + public static final List DEFAULT_EXTRA = Collections.emptyList(); + + @ProtoField(tag = 1, type = STRING) + public final String action; + + @ProtoField(tag = 2, type = STRING) + public final String dataUri; + + @ProtoField(tag = 3, type = STRING) + public final String mimeType; + + @ProtoField(tag = 4, type = STRING) + public final String javaClass; + + @ProtoField(tag = 5, label = REPEATED, messageType = Intent.Extra.class) + public final List extra; + + public Intent(String action, String dataUri, String mimeType, String javaClass, List extra) { + this.action = action; + this.dataUri = dataUri; + this.mimeType = mimeType; + this.javaClass = javaClass; + this.extra = immutableCopyOf(extra); + } + + private Intent(Builder builder) { + this(builder.action, builder.dataUri, builder.mimeType, builder.javaClass, builder.extra); + setBuilder(builder); + } + + @Override + public boolean equals(Object other) { + if (other == this) return true; + if (!(other instanceof Intent)) return false; + Intent o = (Intent) other; + return equals(action, o.action) + && equals(dataUri, o.dataUri) + && equals(mimeType, o.mimeType) + && equals(javaClass, o.javaClass) + && equals(extra, o.extra); + } + + @Override + public int hashCode() { + int result = hashCode; + if (result == 0) { + result = action != null ? action.hashCode() : 0; + result = result * 37 + (dataUri != null ? dataUri.hashCode() : 0); + result = result * 37 + (mimeType != null ? mimeType.hashCode() : 0); + result = result * 37 + (javaClass != null ? javaClass.hashCode() : 0); + result = result * 37 + (extra != null ? extra.hashCode() : 1); + hashCode = result; + } + return result; + } + + public static final class Builder extends Message.Builder { + + public String action; + public String dataUri; + public String mimeType; + public String javaClass; + public List extra; + + public Builder() { + } + + public Builder(Intent message) { + super(message); + if (message == null) return; + this.action = message.action; + this.dataUri = message.dataUri; + this.mimeType = message.mimeType; + this.javaClass = message.javaClass; + this.extra = copyOf(message.extra); + } + + public Builder action(String action) { + this.action = action; + return this; + } + + public Builder dataUri(String dataUri) { + this.dataUri = dataUri; + return this; + } + + public Builder mimeType(String mimeType) { + this.mimeType = mimeType; + return this; + } + + public Builder javaClass(String javaClass) { + this.javaClass = javaClass; + return this; + } + + public Builder extra(List extra) { + this.extra = checkForNulls(extra); + return this; + } + + @Override + public Intent build() { + return new Intent(this); + } + } + + public static final class Extra extends Message { + + public static final String DEFAULT_NAME = ""; + public static final String DEFAULT_VALUE = ""; + + @ProtoField(tag = 6, type = STRING) + public final String name; + + @ProtoField(tag = 7, type = STRING) + public final String value; + + public Extra(String name, String value) { + this.name = name; + this.value = value; + } + + private Extra(Builder builder) { + this(builder.name, builder.value); + setBuilder(builder); + } + + @Override + public boolean equals(Object other) { + if (other == this) return true; + if (!(other instanceof Extra)) return false; + Extra o = (Extra) other; + return equals(name, o.name) + && equals(value, o.value); + } + + @Override + public int hashCode() { + int result = hashCode; + if (result == 0) { + result = name != null ? name.hashCode() : 0; + result = result * 37 + (value != null ? value.hashCode() : 0); + hashCode = result; + } + return result; + } + + public static final class Builder extends Message.Builder { + + public String name; + public String value; + + public Builder() { + } + + public Builder(Extra message) { + super(message); + if (message == null) return; + this.name = message.name; + this.value = message.value; + } + + public Builder name(String name) { + this.name = name; + return this; + } + + public Builder value(String value) { + this.value = value; + return this; + } + + @Override + public Extra build() { + return new Extra(this); + } + } + } + } + + public static final class GservicesSetting extends Message { + + public static final ByteString DEFAULT_NAME = ByteString.EMPTY; + public static final ByteString DEFAULT_VALUE = ByteString.EMPTY; + + @ProtoField(tag = 1, type = BYTES) + public final ByteString name; + + @ProtoField(tag = 2, type = BYTES) + public final ByteString value; + + public GservicesSetting(ByteString name, ByteString value) { + this.name = name; + this.value = value; + } + + private GservicesSetting(Builder builder) { + this(builder.name, builder.value); + setBuilder(builder); + } + + @Override + public boolean equals(Object other) { + if (other == this) return true; + if (!(other instanceof GservicesSetting)) return false; + GservicesSetting o = (GservicesSetting) other; + return equals(name, o.name) + && equals(value, o.value); + } + + @Override + public int hashCode() { + int result = hashCode; + if (result == 0) { + result = name != null ? name.hashCode() : 0; + result = result * 37 + (value != null ? value.hashCode() : 0); + hashCode = result; + } + return result; + } + + public static final class Builder extends Message.Builder { + + public ByteString name; + public ByteString value; + + public Builder() { + } + + public Builder(GservicesSetting message) { + super(message); + if (message == null) return; + this.name = message.name; + this.value = message.value; + } + + public Builder name(ByteString name) { + this.name = name; + return this; + } + + public Builder value(ByteString value) { + this.value = value; + return this; + } + + @Override + public GservicesSetting build() { + return new GservicesSetting(this); + } + } + } +} diff --git a/src/org/microg/gms/auth/AuthClient.java b/src/org/microg/gms/auth/AuthClient.java index 26c716a3..312d2c63 100644 --- a/src/org/microg/gms/auth/AuthClient.java +++ b/src/org/microg/gms/auth/AuthClient.java @@ -48,13 +48,16 @@ public class AuthClient { content.append("&"); content.append(Uri.encode(key)).append("=").append(Uri.encode(formContent.get(key))); } + Log.d(TAG, "-- Request --\n" + content); OutputStream os = connection.getOutputStream(); os.write(content.toString().getBytes()); os.close(); + if (connection.getResponseCode() != 200) { throw new IOException(connection.getResponseMessage()); } + String result = new String(Utils.readStreamToEnd(connection.getInputStream())); Log.d(TAG, "-- Response --\n" + result); return AuthResponse.parse(result); diff --git a/src/org/microg/gms/checkin/CheckinClient.java b/src/org/microg/gms/checkin/CheckinClient.java new file mode 100644 index 00000000..b40f52e9 --- /dev/null +++ b/src/org/microg/gms/checkin/CheckinClient.java @@ -0,0 +1,155 @@ +/* + * Copyright 2013-2015 µg 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.checkin; + +import android.util.Log; + +import com.squareup.wire.Wire; + +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 java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.HttpURLConnection; +import java.net.URL; +import java.util.Arrays; +import java.util.List; + +public class CheckinClient { + private static final String TAG = "GmsCheckinClient"; + private static final Object TODO = null; + private static final String SERVICE_URL = "https://android.clients.google.com/checkin"; + + public static CheckinResponse request(CheckinRequest request) throws IOException { + HttpURLConnection connection = (HttpURLConnection) new URL(SERVICE_URL).openConnection(); + connection.setRequestMethod("POST"); + connection.setDoInput(true); + connection.setDoOutput(true); + connection.setRequestProperty("Content-Type", "application/x-protobuffer"); + connection.setRequestProperty("User-Agent", "Android-Checkin/2.0"); + + Log.d(TAG, "-- Request --\n" + request); + OutputStream os = connection.getOutputStream(); + os.write(request.toByteArray()); + os.close(); + + if (connection.getResponseCode() != 200) { + throw new IOException(connection.getResponseMessage()); + } + + InputStream is = connection.getInputStream(); + CheckinResponse response = new Wire().parseFrom(is, CheckinResponse.class); + is.close(); + return response; + } + + private static CheckinRequest.Checkin.Build makeBuild(Build build) { + return new CheckinRequest.Checkin.Build.Builder() + .bootloader(build.bootloader) + .brand(build.brand) + .clientId((String) TODO) + .device(build.device) + .fingerprint(build.fingerprint) + .hardware(build.hardware) + .manufacturer(build.manufacturer) + .model(build.model) + .otaInstalled(false) // TODO? + .packageVersionCode(build.sdk) // TODO? + .product(build.product) + .radio(build.radio) + .sdkVersion(build.sdk) + .time(build.time / 1000) + .build(); + } + + private static CheckinRequest.DeviceConfig makeDeviceConfig(DeviceConfiguration deviceConfiguration) { + return new CheckinRequest.DeviceConfig.Builder() + .availableFeature(deviceConfiguration.availableFeatures) + .densityDpi(deviceConfiguration.densityDpi) + .deviceClass(deviceConfiguration.deviceClass) + .glEsVersion(deviceConfiguration.glEsVersion) + .glExtension(deviceConfiguration.glExtensions) + .hasFiveWayNavigation(deviceConfiguration.hasFiveWayNavigation) + .hasHardKeyboard(deviceConfiguration.hasHardKeyboard) + .heightPixels(deviceConfiguration.heightPixels) + .keyboardType(deviceConfiguration.keyboardType) + .locale(deviceConfiguration.locales) + .maxApkDownloadSizeMb((Integer) TODO) + .nativePlatform(deviceConfiguration.nativePlatforms) + .navigation(deviceConfiguration.navigation) + .screenLayout(deviceConfiguration.screenLayout) + .sharedLibrary(deviceConfiguration.sharedLibraries) + .touchScreen(deviceConfiguration.touchScreen) + .widthPixels(deviceConfiguration.widthPixels) + .build(); + } + + private static CheckinRequest.Checkin makeCheckin(CheckinRequest.Checkin.Build build, + PhoneInfo phoneInfo, LastCheckinInfo checkinInfo) { + return new CheckinRequest.Checkin.Builder() + .build(build) + .cellOperator(phoneInfo.cellOperator) + .event((List) TODO) + .lastCheckinMs(checkinInfo.lastCheckin) + .requestedGroup((List) TODO) + .roaming(phoneInfo.roaming) + .simOperator(phoneInfo.simOperator) + .stat((List) TODO) + .userNumber((Integer) TODO) + .build(); + } + + private static CheckinRequest makeRequest(CheckinRequest.Checkin checkin, + CheckinRequest.DeviceConfig deviceConfig, + DeviceIdentifier deviceIdent, LastCheckinInfo checkinInfo) { + return new CheckinRequest.Builder() + .accountCookie((List) TODO) + .androidId(checkinInfo.androidId) + .checkin(checkin) + .desiredBuild((String) TODO) + .deviceConfiguration(deviceConfig) + .digest((String) TODO) + .esn(deviceIdent.esn) + .fragment((Integer) TODO) + .locale((String) TODO) + .loggingId((Long) TODO) + .macAddress(Arrays.asList(deviceIdent.wifiMac, deviceIdent.bluetoothMac)) + .macAddressType(Arrays.asList("wifi", "bt")) // TODO + .marketCheckin((String) TODO) + .meid(deviceIdent.meid) + .otaCert((List) TODO) + .securityToken(checkinInfo.securityToken) + .serial((String) TODO) + .timeZone((String) TODO) + .userName((String) TODO) + .userSerialNumber((Integer) TODO) + .version((Integer) TODO) + .build(); + + } + + private static CheckinRequest makeRequest(Build build, DeviceConfiguration deviceConfiguration, + DeviceIdentifier deviceIdent, PhoneInfo phoneInfo, + LastCheckinInfo checkinInfo) { + return makeRequest(makeCheckin(makeBuild(build), phoneInfo, checkinInfo), + makeDeviceConfig(deviceConfiguration), deviceIdent, checkinInfo); + } +} diff --git a/src/org/microg/gms/checkin/LastCheckinInfo.java b/src/org/microg/gms/checkin/LastCheckinInfo.java new file mode 100644 index 00000000..a20a7de2 --- /dev/null +++ b/src/org/microg/gms/checkin/LastCheckinInfo.java @@ -0,0 +1,23 @@ +/* + * Copyright 2013-2015 µg 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.checkin; + +public class LastCheckinInfo { + public long lastCheckin; + public long androidId; + public long securityToken; +} diff --git a/src/org/microg/gms/common/Build.java b/src/org/microg/gms/common/Build.java index 2a1dcdce..31fc69bb 100644 --- a/src/org/microg/gms/common/Build.java +++ b/src/org/microg/gms/common/Build.java @@ -17,7 +17,25 @@ package org.microg.gms.common; public class Build { - public int sdk = android.os.Build.VERSION.SDK_INT; - public String id = android.os.Build.ID; + public String fingerprint = android.os.Build.FINGERPRINT; + public String hardware = android.os.Build.HARDWARE; + public String brand = android.os.Build.BRAND; + public String radio = getRadio(); + public String bootloader = android.os.Build.BOOTLOADER; + public long time = android.os.Build.TIME; public String device = android.os.Build.DEVICE; + public int sdk = android.os.Build.VERSION.SDK_INT; + public String model = android.os.Build.MODEL; + public String manufacturer = android.os.Build.MANUFACTURER; + public String product = android.os.Build.PRODUCT; + public String id = android.os.Build.ID; + + private static String getRadio() { + if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.ICE_CREAM_SANDWICH) { + return android.os.Build.getRadioVersion(); + } else { + //noinspection deprecation + return android.os.Build.RADIO; + } + } } diff --git a/src/org/microg/gms/common/DeviceConfiguration.java b/src/org/microg/gms/common/DeviceConfiguration.java new file mode 100644 index 00000000..634df154 --- /dev/null +++ b/src/org/microg/gms/common/DeviceConfiguration.java @@ -0,0 +1,38 @@ +/* + * Copyright 2013-2015 µg 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 java.util.List; + +public class DeviceConfiguration { + public List availableFeatures; + public int densityDpi; + public int deviceClass; + public int glEsVersion; + public List glExtensions; + public boolean hasFiveWayNavigation; + public boolean hasHardKeyboard; + public int heightPixels; + public int keyboardType; + public List locales; + public List nativePlatforms; + public int navigation; + public int screenLayout; + public List sharedLibraries; + public int touchScreen; + public int widthPixels; +} diff --git a/src/org/microg/gms/common/DeviceIdentifier.java b/src/org/microg/gms/common/DeviceIdentifier.java new file mode 100644 index 00000000..22743886 --- /dev/null +++ b/src/org/microg/gms/common/DeviceIdentifier.java @@ -0,0 +1,24 @@ +/* + * Copyright 2013-2015 µg 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; + +public class DeviceIdentifier { + public String bluetoothMac; + public String wifiMac; + public String meid; + public String esn; +} diff --git a/src/org/microg/gms/common/PhoneInfo.java b/src/org/microg/gms/common/PhoneInfo.java new file mode 100644 index 00000000..a40d6b15 --- /dev/null +++ b/src/org/microg/gms/common/PhoneInfo.java @@ -0,0 +1,23 @@ +/* + * Copyright 2013-2015 µg 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; + +public class PhoneInfo { + public String cellOperator; + public String roaming; + public String simOperator; +}