diff --git a/extern/UnifiedNlp b/extern/UnifiedNlp index 74fb8b69..29df26c7 160000 --- a/extern/UnifiedNlp +++ b/extern/UnifiedNlp @@ -1 +1 @@ -Subproject commit 74fb8b696aaf35584b97c86eb7d9e67aaaf0e685 +Subproject commit 29df26c727263728a17665d8824b5d7c7d748eba diff --git a/play-services-core/src/main/java/org/microg/gms/checkin/CheckinClient.java b/play-services-core/src/main/java/org/microg/gms/checkin/CheckinClient.java index 53d1181b..c1fc1b07 100644 --- a/play-services-core/src/main/java/org/microg/gms/checkin/CheckinClient.java +++ b/play-services-core/src/main/java/org/microg/gms/checkin/CheckinClient.java @@ -21,11 +21,11 @@ import android.util.Log; import com.squareup.wire.Wire; import org.microg.gms.common.Build; -import org.microg.gms.common.Constants; import org.microg.gms.common.DeviceConfiguration; import org.microg.gms.common.DeviceIdentifier; import org.microg.gms.common.PhoneInfo; +import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; @@ -33,7 +33,14 @@ import java.net.HttpURLConnection; import java.net.URL; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; +import java.util.Date; import java.util.List; +import java.util.Locale; +import java.util.Random; +import java.util.TimeZone; +import java.util.zip.GZIPInputStream; +import java.util.zip.GZIPOutputStream; public class CheckinClient { private static final String TAG = "GmsCheckinClient"; @@ -46,104 +53,113 @@ public class CheckinClient { connection.setDoInput(true); connection.setDoOutput(true); connection.setRequestProperty("Content-Type", "application/x-protobuffer"); - connection.setRequestProperty("User-Agent", "Android-Checkin/2.0"); + connection.setRequestProperty("Content-Encoding", "gzip"); + connection.setRequestProperty("Accept-Encoding", "gzip"); + connection.setRequestProperty("User-Agent", "Android-Checkin/2.0 (vbox86p JLS36G); gzip"); Log.d(TAG, "-- Request --\n" + request); - OutputStream os = connection.getOutputStream(); + OutputStream os = new GZIPOutputStream(connection.getOutputStream()); os.write(request.toByteArray()); os.close(); if (connection.getResponseCode() != 200) { - throw new IOException(connection.getResponseMessage()); + try { + InputStream is = new GZIPInputStream(connection.getErrorStream()); + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + if (is != null) { + final byte[] buff = new byte[1024]; + while (true) { + final int nb = is.read(buff); + if (nb < 0) { + break; + } + bos.write(buff, 0, nb); + } + is.close(); + } + throw new IOException(bos.toString()); + } catch (Exception e) { + throw new IOException(connection.getResponseMessage(), e); + } } InputStream is = connection.getInputStream(); - CheckinResponse response = new Wire().parseFrom(is, CheckinResponse.class); + CheckinResponse response = new Wire().parseFrom(new GZIPInputStream(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(Constants.MAX_REFERENCE_VERSION) - .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) - .glEsVersion(deviceConfiguration.glEsVersion) - .glExtension(deviceConfiguration.glExtensions) - .hasFiveWayNavigation(deviceConfiguration.hasFiveWayNavigation) - .hasHardKeyboard(deviceConfiguration.hasHardKeyboard) - .heightPixels(deviceConfiguration.heightPixels) - .keyboardType(deviceConfiguration.keyboardType) - .locale(deviceConfiguration.locales) - .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, - List accounts) { + public static CheckinRequest makeRequest(Build build, DeviceConfiguration deviceConfiguration, + DeviceIdentifier deviceIdent, PhoneInfo phoneInfo, + LastCheckinInfo checkinInfo, Locale locale, + List accounts) { CheckinRequest.Builder builder = new CheckinRequest.Builder() - .accountCookie(Arrays.asList("")) // TODO + .accountCookie(new ArrayList()) .androidId(checkinInfo.androidId) - .checkin(checkin) - .deviceConfiguration(deviceConfig) + .checkin(new CheckinRequest.Checkin.Builder() + .build(new CheckinRequest.Checkin.Build.Builder() + .bootloader(build.bootloader) + .brand(build.brand) + .clientId("android-google") + .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.sdk) + .time(build.time / 1000) + .build()) + .cellOperator(phoneInfo.cellOperator) + .event(Collections.singletonList(new CheckinRequest.Checkin.Event.Builder() + .tag(checkinInfo.androidId == 0 ? "event_log_start" : "system_update") + .value(checkinInfo.androidId == 0 ? null : "1536,0,-1,NULL") + .timeMs(new Date().getTime()) + .build())) + .lastCheckinMs(checkinInfo.lastCheckin) + .requestedGroup((List) TODO) + .roaming(phoneInfo.roaming) + .simOperator(phoneInfo.simOperator) + .stat((List) TODO) + .userNumber(0) + .build()) + .deviceConfiguration(new CheckinRequest.DeviceConfig.Builder() + .availableFeature(deviceConfiguration.availableFeatures) + .densityDpi(deviceConfiguration.densityDpi) + .glEsVersion(deviceConfiguration.glEsVersion) + .glExtension(deviceConfiguration.glExtensions) + .hasFiveWayNavigation(deviceConfiguration.hasFiveWayNavigation) + .hasHardKeyboard(deviceConfiguration.hasHardKeyboard) + .heightPixels(deviceConfiguration.heightPixels) + .keyboardType(deviceConfiguration.keyboardType) + .locale(deviceConfiguration.locales) + .nativePlatform(deviceConfiguration.nativePlatforms) + .navigation(deviceConfiguration.navigation) + .screenLayout(deviceConfiguration.screenLayout) + .sharedLibrary(deviceConfiguration.sharedLibraries) + .touchScreen(deviceConfiguration.touchScreen) + .widthPixels(deviceConfiguration.widthPixels) + .build()) .digest(checkinInfo.digest) .esn(deviceIdent.esn) .fragment(0) - .locale((String) TODO) - .loggingId((Long) TODO) + .locale(locale.toString()) + .loggingId(new Random().nextLong()) // TODO: static .meid(deviceIdent.meid) - .otaCert((List) TODO) - .serial((String) TODO) - .timeZone((String) TODO) + .otaCert(Collections.singletonList("71Q6Rn2DDZl1zPDVaaeEHItd")) + .serial(build.serial) + .timeZone(TimeZone.getDefault().getID()) .userName((String) TODO) .userSerialNumber((Integer) TODO) .version(3); - builder.accountCookie(new ArrayList()); for (Account account : accounts) { builder.accountCookie.add("[" + account.name + "]"); builder.accountCookie.add(account.authToken); } + if (builder.accountCookie.isEmpty()) builder.accountCookie.add(""); if (deviceIdent.wifiMac != null) { builder.macAddress(Arrays.asList(deviceIdent.wifiMac)) .macAddressType(Arrays.asList("wifi")); @@ -153,15 +169,6 @@ public class CheckinClient { .fragment(1); } return builder.build(); - - } - - public static CheckinRequest makeRequest(Build build, DeviceConfiguration deviceConfiguration, - DeviceIdentifier deviceIdent, PhoneInfo phoneInfo, - LastCheckinInfo checkinInfo, - List accounts) { - return makeRequest(makeCheckin(makeBuild(build), phoneInfo, checkinInfo), - makeDeviceConfig(deviceConfiguration), deviceIdent, checkinInfo, accounts); } public static class Account { diff --git a/play-services-core/src/main/java/org/microg/gms/checkin/CheckinManager.java b/play-services-core/src/main/java/org/microg/gms/checkin/CheckinManager.java index c59ee24b..86bbbca3 100644 --- a/play-services-core/src/main/java/org/microg/gms/checkin/CheckinManager.java +++ b/play-services-core/src/main/java/org/microg/gms/checkin/CheckinManager.java @@ -24,6 +24,7 @@ import android.content.Context; import com.google.android.gms.R; import org.microg.gms.auth.AuthManager; +import org.microg.gms.auth.AuthRequest; import org.microg.gms.common.Constants; import org.microg.gms.common.DeviceConfiguration; import org.microg.gms.common.DeviceIdentifier; @@ -46,12 +47,18 @@ public class CheckinManager { AccountManager accountManager = AccountManager.get(context); String accountType = context.getString(R.string.google_account_type); for (Account account : accountManager.getAccountsByType(accountType)) { - String token = new AuthManager(context, account.name, Constants.GMS_PACKAGE_NAME, "ac2dm").getAuthToken(); - accounts.add(new CheckinClient.Account(account.name, token)); + String token = new AuthRequest() + .email(account.name).token(accountManager.getPassword(account)) + .hasPermission().service("ac2dm") + .app("com.google.android.gsf", Constants.GMS_PACKAGE_SIGNATURE_SHA1) + .getResponse().LSid; + if (token != null) { + accounts.add(new CheckinClient.Account(account.name, token)); + } } - CheckinRequest request = - CheckinClient.makeRequest(Utils.getBuild(context), new DeviceConfiguration(context), - new DeviceIdentifier(), new PhoneInfo(), info, accounts); // TODO + CheckinRequest request = CheckinClient.makeRequest(Utils.getBuild(context), + new DeviceConfiguration(context), new DeviceIdentifier(), new PhoneInfo(), info, + Utils.getLocale(context), accounts); // TODO return handleResponse(context, CheckinClient.request(request)); } diff --git a/play-services-core/src/main/java/org/microg/gms/common/Build.java b/play-services-core/src/main/java/org/microg/gms/common/Build.java index 31fc69bb..32a4b602 100644 --- a/play-services-core/src/main/java/org/microg/gms/common/Build.java +++ b/play-services-core/src/main/java/org/microg/gms/common/Build.java @@ -16,6 +16,8 @@ package org.microg.gms.common; +import java.util.Random; + public class Build { public String fingerprint = android.os.Build.FINGERPRINT; public String hardware = android.os.Build.HARDWARE; @@ -29,6 +31,7 @@ public class Build { public String manufacturer = android.os.Build.MANUFACTURER; public String product = android.os.Build.PRODUCT; public String id = android.os.Build.ID; + public String serial = generateSerialNumber(); // TODO: static private static String getRadio() { if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.ICE_CREAM_SANDWICH) { @@ -38,4 +41,13 @@ public class Build { return android.os.Build.RADIO; } } + + 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(); + return serial; + } } diff --git a/play-services-core/src/main/java/org/microg/gms/common/DeviceConfiguration.java b/play-services-core/src/main/java/org/microg/gms/common/DeviceConfiguration.java index 336eeb3a..7f0591e2 100644 --- a/play-services-core/src/main/java/org/microg/gms/common/DeviceConfiguration.java +++ b/play-services-core/src/main/java/org/microg/gms/common/DeviceConfiguration.java @@ -28,7 +28,10 @@ import android.util.DisplayMetrics; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; +import java.util.HashSet; import java.util.List; +import java.util.Set; import javax.microedition.khronos.egl.EGL10; import javax.microedition.khronos.egl.EGLConfig; @@ -65,11 +68,18 @@ public class DeviceConfiguration { densityDpi = displayMetrics.densityDpi; glEsVersion = configurationInfo.reqGlEsVersion; PackageManager packageManager = context.getPackageManager(); - sharedLibraries = Arrays.asList(packageManager.getSystemSharedLibraryNames()); + sharedLibraries = new ArrayList(Arrays.asList(packageManager.getSystemSharedLibraryNames())); + for (String s : new String[]{"com.google.android.maps", "com.google.android.media.effects", "com.google.widevine.software.drm"}) { + if (!sharedLibraries.contains(s)) { + sharedLibraries.add(s); + } + } + Collections.sort(sharedLibraries); availableFeatures = new ArrayList(); for (FeatureInfo featureInfo : packageManager.getSystemAvailableFeatures()) { if (featureInfo.name != null) availableFeatures.add(featureInfo.name); } + Collections.sort(availableFeatures); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { nativePlatforms = Arrays.asList(Build.SUPPORTED_ABIS); } else { @@ -79,12 +89,18 @@ public class DeviceConfiguration { } widthPixels = displayMetrics.widthPixels; heightPixels = displayMetrics.heightPixels; - locales = Arrays.asList(context.getAssets().getLocales()); - glExtensions = new ArrayList(); + locales = new ArrayList(Arrays.asList(context.getAssets().getLocales())); + for (int i = 0; i < locales.size(); i++) { + locales.set(i, locales.get(i).replace("-", "_")); + } + Collections.sort(locales); + Set glExtensions = new HashSet(); addEglExtensions(glExtensions); + this.glExtensions = new ArrayList(glExtensions); + Collections.sort(this.glExtensions); } - private static void addEglExtensions(List glExtensions) { + private static void addEglExtensions(Set glExtensions) { EGL10 egl10 = (EGL10) EGLContext.getEGL(); if (egl10 != null) { EGLDisplay display = egl10.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY); @@ -120,7 +136,7 @@ public class DeviceConfiguration { } private static void addExtensionsForConfig(EGL10 egl10, EGLDisplay egldisplay, EGLConfig eglconfig, int ai[], - int ai1[], List set) { + int ai1[], Set set) { EGLContext eglcontext = egl10.eglCreateContext(egldisplay, eglconfig, EGL10.EGL_NO_CONTEXT, ai1); if (eglcontext != EGL10.EGL_NO_CONTEXT) { javax.microedition.khronos.egl.EGLSurface eglsurface = diff --git a/play-services-core/src/main/java/org/microg/gms/common/DeviceIdentifier.java b/play-services-core/src/main/java/org/microg/gms/common/DeviceIdentifier.java index 0129f5fd..e159d809 100644 --- a/play-services-core/src/main/java/org/microg/gms/common/DeviceIdentifier.java +++ b/play-services-core/src/main/java/org/microg/gms/common/DeviceIdentifier.java @@ -16,8 +16,46 @@ package org.microg.gms.common; +import java.util.Random; + public class DeviceIdentifier { - public String wifiMac; - public String meid; + public String wifiMac = randomMacAddress(); // TODO: static + public String meid = randomMeid(); public String esn; + + + private static String randomMacAddress() { + String mac = "b407f9"; + Random rand = new Random(); + for (int i = 0; i < 6; i++) { + mac += Integer.toString(rand.nextInt(16), 16); + } + return mac; + } + + private static String randomMeid() { + // http://en.wikipedia.org/wiki/International_Mobile_Equipment_Identity + // We start with a known base, and generate random MEID + String meid = "35503104"; + Random rand = new Random(); + for (int i = 0; i < 6; i++) { + meid += Integer.toString(rand.nextInt(10)); + } + + // Luhn algorithm (check digit) + int sum = 0; + for (int i = 0; i < meid.length(); i++) { + int c = Integer.parseInt(String.valueOf(meid.charAt(i))); + if ((meid.length() - i - 1) % 2 == 0) { + c *= 2; + c = c % 10 + c / 10; + } + + sum += c; + } + final int check = (100 - sum) % 10; + meid += Integer.toString(check); + + return meid; + } } diff --git a/play-services-core/src/main/java/org/microg/gms/common/PhoneInfo.java b/play-services-core/src/main/java/org/microg/gms/common/PhoneInfo.java index a40d6b15..5352e1f3 100644 --- a/play-services-core/src/main/java/org/microg/gms/common/PhoneInfo.java +++ b/play-services-core/src/main/java/org/microg/gms/common/PhoneInfo.java @@ -17,7 +17,7 @@ package org.microg.gms.common; public class PhoneInfo { - public String cellOperator; - public String roaming; - public String simOperator; + public String cellOperator = "26207"; + public String roaming = "mobile-notroaming"; + public String simOperator = "26207"; } diff --git a/play-services-core/src/main/java/org/microg/gms/ui/SettingsActivity.java b/play-services-core/src/main/java/org/microg/gms/ui/SettingsActivity.java index ea5a0e37..bdef1143 100644 --- a/play-services-core/src/main/java/org/microg/gms/ui/SettingsActivity.java +++ b/play-services-core/src/main/java/org/microg/gms/ui/SettingsActivity.java @@ -19,14 +19,17 @@ package org.microg.gms.ui; import android.os.Bundle; import android.support.v4.app.FragmentActivity; import android.support.v4.preference.PreferenceFragment; +import android.support.v7.app.AppCompatActivity; +import android.support.v7.widget.Toolbar; import com.google.android.gms.R; -public class SettingsActivity extends FragmentActivity { +public class SettingsActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.settings_activity); + setSupportActionBar((Toolbar) findViewById(R.id.toolbar)); getSupportFragmentManager().beginTransaction() .replace(R.id.content_wrapper, new MyPreferenceFragment()).commit(); } diff --git a/play-services-core/src/main/res/layout/toolbar.xml b/play-services-core/src/main/res/layout/toolbar.xml deleted file mode 100644 index a5be1e8f..00000000 --- a/play-services-core/src/main/res/layout/toolbar.xml +++ /dev/null @@ -1,22 +0,0 @@ - - -