diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 3e12b08d23dc95fffa7561e167b94f953673c450..3ea467079a1c8b3d3b783ee68fe35c9517b92173 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -25,11 +25,11 @@ build:
script:
- git submodule update --recursive --init
- echo sdk.dir $ANDROID_HOME > local.properties
+ - echo mapbox.key $MAPBOX_KEY >> local.properties
+ - echo mapbox.enabled true >> local.properties
- export TERM=dumb
- export JAVA_OPTS="-XX:+CMSClassUnloadingEnabled -XX:+HeapDumpOnOutOfMemoryError -Xmx2048m"
- - ./gradlew build
- only:
- - tags
+ - ./gradlew assemble
artifacts:
paths:
- play-services-core/build/outputs/apk/
diff --git a/.travis.yml b/.travis.yml
index 822e0de02263154feb093faf0e4787e9ab6bd026..87ad538a658853850efc446ab60a46d025d475b8 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -10,7 +10,7 @@ android:
components:
- tools
- platform-tools
- - build-tools-28.0.3
+ - build-tools-29.0.2
- android-27
- android-28
- extra-android-m2repository
diff --git a/build.gradle b/build.gradle
index 76056a023c79903aac26a2a7b9ba16b747e7d1ee..b6ffdcde07818031b191fa61a4fb217bfc22c7a5 100644
--- a/build.gradle
+++ b/build.gradle
@@ -21,7 +21,7 @@ buildscript {
google()
}
dependencies {
- classpath 'com.android.tools.build:gradle:3.3.2'
+ classpath 'com.android.tools.build:gradle:3.5.1'
classpath 'com.github.dcendents:android-maven-gradle-plugin:2.0'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
@@ -29,7 +29,7 @@ buildscript {
allprojects {
apply plugin: 'idea'
- ext.androidBuildVersionTools = "28.0.3"
+ ext.androidBuildVersionTools = "29.0.2"
ext.supportLibraryVersion = "28.0.0"
ext.isReleaseVersion = false
ext.slf4jVersion = "1.7.25"
@@ -37,7 +37,7 @@ allprojects {
def androidCompileSdk() { return 28 }
-def androidTargetSdk() { return 28 }
+def androidTargetSdk() { return 29 }
def androidMinSdk() { return 14 }
diff --git a/extern/GmsApi b/extern/GmsApi
index 51509859ae51097ad5789ba4ca2e9ffb9658f80e..2a43448e49dc0aec0d6c53c8a27dd58245fdaba6 160000
--- a/extern/GmsApi
+++ b/extern/GmsApi
@@ -1 +1 @@
-Subproject commit 51509859ae51097ad5789ba4ca2e9ffb9658f80e
+Subproject commit 2a43448e49dc0aec0d6c53c8a27dd58245fdaba6
diff --git a/extern/GmsLib b/extern/GmsLib
index 39d20ec1f28bcc4b134d76f43296bad587362c69..15cd4491bcca57d627796b35b69bdf8c97564792 160000
--- a/extern/GmsLib
+++ b/extern/GmsLib
@@ -1 +1 @@
-Subproject commit 39d20ec1f28bcc4b134d76f43296bad587362c69
+Subproject commit 15cd4491bcca57d627796b35b69bdf8c97564792
diff --git a/gradle.properties b/gradle.properties
deleted file mode 100644
index dfbe478748b40312f4a377f1c3890f6c74d93027..0000000000000000000000000000000000000000
--- a/gradle.properties
+++ /dev/null
@@ -1 +0,0 @@
-android.useDeprecatedNdk=true
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index 7919ae6e6bc1c4aceb8a6689658a1ca95e83d53d..d757f3d33fcc6837851eb73a6963eebcee23c282 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -2,4 +2,4 @@ distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-5.2.1-all.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip
diff --git a/play-services-core/build.gradle b/play-services-core/build.gradle
index c40c2c7dd262618dbede2077c89a4360ba1a8c30..1c0de9b520c45d621786c8b43e5cc12b2154d71c 100644
--- a/play-services-core/build.gradle
+++ b/play-services-core/build.gradle
@@ -30,7 +30,7 @@ dependencies {
implementation "com.squareup.wire:wire-runtime:1.6.1"
implementation "com.takisoft.fix:preference-v7:$supportLibraryVersion.0"
implementation "de.hdodenhof:circleimageview:1.3.0"
- implementation "org.conscrypt:conscrypt-android:2.0.0"
+ implementation "org.conscrypt:conscrypt-android:2.1.0"
// TODO: Switch to upstream once raw requests are merged
// https://github.com/vitalidze/chromecast-java-api-v2/pull/99
// implementation "su.litvak.chromecast:api-v2:0.10.4"
@@ -65,7 +65,7 @@ def execResult(...args) {
return stdout.toString().trim()
}
-def gmsVersion = "17.7.85"
+def gmsVersion = "19.4.20"
def gmsVersionCode = Integer.parseInt(gmsVersion.replaceAll('\\.', ''))
def gitVersionBase = execResult('git', 'describe', '--tags', '--abbrev=0', '--match=v[0-9]*').substring(1)
def gitCommitCount = Integer.parseInt(execResult('git', 'rev-list', '--count', "v$gitVersionBase..HEAD"))
@@ -74,7 +74,7 @@ def gitDirty = execResult('git', 'status', '--porcelain').size() > 0
def ourVersionBase = gitVersionBase.substring(0, gitVersionBase.lastIndexOf('.'))
def ourVersionMinor = Integer.parseInt(ourVersionBase.substring(ourVersionBase.lastIndexOf('.') + 1))
def ourVersionCode = gmsVersionCode * 1000 + ourVersionMinor * 2 + (gitCommitCount > 0 || gitDirty ? 1 : 0)
-def ourVersionName = "$ourVersionBase.$gmsVersionCode" + (gitCommitCount > 0 && !gitDirty ? "-$gitCommitCount" : "") + (gitDirty ? "-dirty" : "") + (useMapbox() ? "-mapbox" : "") + (gitCommitCount > 0 && !gitDirty ? " ($gitCommitId)" : "")
+def ourVersionName = "$ourVersionBase.$gmsVersionCode" + (gitCommitCount > 0 && !gitDirty ? "-$gitCommitCount" : "") + (gitDirty ? "-dirty" : "") + (useMapbox() ? "" : "-vtm") + (gitCommitCount > 0 && !gitDirty ? " ($gitCommitId)" : "")
logger.lifecycle('Starting build for version {} ({})...', ourVersionName, ourVersionCode)
android {
diff --git a/play-services-core/src/main/AndroidManifest.xml b/play-services-core/src/main/AndroidManifest.xml
index 535180fe62e8afee561b504c64fff6ff7361225b..823085688d462ba9965ff1c409061a0c46952d4e 100644
--- a/play-services-core/src/main/AndroidManifest.xml
+++ b/play-services-core/src/main/AndroidManifest.xml
@@ -1,6 +1,6 @@
-
-
-
+
+
+
+
+
+
+
+
+
diff --git a/play-services-core/src/main/java/com/google/android/gms/chimera/container/DynamiteLoaderImpl.java b/play-services-core/src/main/java/com/google/android/gms/chimera/container/DynamiteLoaderImpl.java
index 43bd5cafed9704b3320423a62da76023db72f587..a841984c7642dc8a65196c3e43a104b7d2b72694 100644
--- a/play-services-core/src/main/java/com/google/android/gms/chimera/container/DynamiteLoaderImpl.java
+++ b/play-services-core/src/main/java/com/google/android/gms/chimera/container/DynamiteLoaderImpl.java
@@ -66,6 +66,10 @@ public class DynamiteLoaderImpl extends IDynamiteLoader.Stub {
Log.d(TAG, "returning temp fix module version for " + moduleId + ". Cast API wil not be functional!");
return 1;
}
+ if (moduleId.equals("com.google.android.gms.maps_dynamite")) {
+ Log.d(TAG, "returning v1 for maps");
+ return 1;
+ }
Log.d(TAG, "unimplemented Method: getModuleVersion for " + moduleId);
return 0;
}
diff --git a/play-services-core/src/main/java/com/google/android/gms/common/GoogleCertificatesImpl.java b/play-services-core/src/main/java/com/google/android/gms/common/GoogleCertificatesImpl.java
index bb9c6df2ffb96424b2b72b0e0b86247d1c5dcb7f..06a8a7cce1eb0519c63262629eafc97a1c2d84e4 100644
--- a/play-services-core/src/main/java/com/google/android/gms/common/GoogleCertificatesImpl.java
+++ b/play-services-core/src/main/java/com/google/android/gms/common/GoogleCertificatesImpl.java
@@ -16,6 +16,7 @@
package com.google.android.gms.common;
+import android.content.pm.PackageManager;
import android.os.RemoteException;
import android.support.annotation.Keep;
import android.util.Log;
@@ -55,6 +56,14 @@ public class GoogleCertificatesImpl extends IGoogleCertificatesApi.Stub {
@Override
public boolean isGoogleOrPlatformSigned(GoogleCertificatesQuery query, IObjectWrapper packageManager) throws RemoteException {
- return PackageUtils.isGooglePackage(query.getPackageName(), query.getCertData().getBytes());
+ PackageManager pm = ObjectWrapper.unwrapTyped(packageManager, PackageManager.class);
+ if (query == null || query.getPackageName() == null) {
+ return false;
+ } else if (query.getCertData() == null) {
+ if (pm == null) return false;
+ return PackageUtils.isGooglePackage(pm, query.getPackageName());
+ } else {
+ return PackageUtils.isGooglePackage(query.getPackageName(), query.getCertData().getBytes());
+ }
}
}
diff --git a/play-services-core/src/main/java/com/google/android/gms/common/security/ProviderInstallerImpl.java b/play-services-core/src/main/java/com/google/android/gms/common/security/ProviderInstallerImpl.java
index fa72252da8fd3f47f0306bc0358f975a05797ed2..6d702279f1e4874b909bdd0df05485166f232e25 100644
--- a/play-services-core/src/main/java/com/google/android/gms/common/security/ProviderInstallerImpl.java
+++ b/play-services-core/src/main/java/com/google/android/gms/common/security/ProviderInstallerImpl.java
@@ -34,9 +34,10 @@ import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.security.Security;
+import java.util.Arrays;
import java.util.Collections;
-import java.util.Enumeration;
import java.util.List;
+import java.util.Set;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
@@ -45,7 +46,7 @@ import javax.net.ssl.SSLContext;
public class ProviderInstallerImpl {
private static final String TAG = "GmsProviderInstaller";
- private static final List DISABLED = Collections.singletonList("com.discord");
+ private static final List DISABLED = Collections.unmodifiableList(Arrays.asList("com.discord", "com.bankid.bus"));
public static void insertProvider(Context context) {
String packageName = PackageUtils.packageFromProcessId(context, Process.myPid());
@@ -86,13 +87,57 @@ public class ProviderInstallerImpl {
System.load(cacheFile.getAbsolutePath());
Class clazz = NativeCrypto.class;
+
Field loadError = clazz.getDeclaredField("loadError");
loadError.setAccessible(true);
loadError.set(null, null);
- Method clinit =clazz.getDeclaredMethod("clinit");
+
+ Method clinit = clazz.getDeclaredMethod("clinit");
clinit.setAccessible(true);
+
+ Method get_cipher_names = clazz.getDeclaredMethod("get_cipher_names", String.class);
+ get_cipher_names.setAccessible(true);
+
+ Method cipherSuiteToJava = clazz.getDeclaredMethod("cipherSuiteToJava", String.class);
+ cipherSuiteToJava.setAccessible(true);
+
+ Method EVP_has_aes_hardware = clazz.getDeclaredMethod("EVP_has_aes_hardware");
+ EVP_has_aes_hardware.setAccessible(true);
+
+ Field f = clazz.getDeclaredField("SUPPORTED_TLS_1_2_CIPHER_SUITES_SET");
+ f.setAccessible(true);
+
+ Set SUPPORTED_TLS_1_2_CIPHER_SUITES_SET = (Set) f.get(null);
+ f = clazz.getDeclaredField("SUPPORTED_LEGACY_CIPHER_SUITES_SET");
+ f.setAccessible(true);
+
+ Set SUPPORTED_LEGACY_CIPHER_SUITES_SET = (Set) f.get(null);
+ f = clazz.getDeclaredField("SUPPORTED_TLS_1_2_CIPHER_SUITES");
+ f.setAccessible(true);
+
try {
clinit.invoke(null);
+
+ String[] allCipherSuites = (String[]) get_cipher_names.invoke(null, "ALL:!DHE");
+ int size = allCipherSuites.length;
+
+ String[] SUPPORTED_TLS_1_2_CIPHER_SUITES = new String[size / 2 + 2];
+ for (int i = 0; i < size; i += 2) {
+ String cipherSuite = (String) cipherSuiteToJava.invoke(null, allCipherSuites[i]);
+
+ SUPPORTED_TLS_1_2_CIPHER_SUITES[i / 2] = cipherSuite;
+ SUPPORTED_TLS_1_2_CIPHER_SUITES_SET.add(cipherSuite);
+
+ SUPPORTED_LEGACY_CIPHER_SUITES_SET.add(allCipherSuites[i + 1]);
+ }
+ SUPPORTED_TLS_1_2_CIPHER_SUITES[size / 2] = "TLS_EMPTY_RENEGOTIATION_INFO_SCSV";
+ SUPPORTED_TLS_1_2_CIPHER_SUITES[size / 2 + 1] = "TLS_FALLBACK_SCSV";
+ f.set(null, SUPPORTED_TLS_1_2_CIPHER_SUITES);
+
+ f = clazz.getDeclaredField("HAS_AES_HARDWARE");
+ f.setAccessible(true);
+ f.set(null, (int) EVP_has_aes_hardware.invoke(null) == 1);
+
provider = new OpenSSLProvider("GmsCore_OpenSSL");
} catch (InvocationTargetException inner) {
if (inner.getTargetException() instanceof UnsatisfiedLinkError) {
diff --git a/play-services-core/src/main/java/org/microg/gms/auth/AuthManagerServiceImpl.java b/play-services-core/src/main/java/org/microg/gms/auth/AuthManagerServiceImpl.java
index 1f5c26a796a8e6bf71c0ad0241cb4354ca14d239..0e6faf89ef998697129f20e48f381ae45c8168f9 100644
--- a/play-services-core/src/main/java/org/microg/gms/auth/AuthManagerServiceImpl.java
+++ b/play-services-core/src/main/java/org/microg/gms/auth/AuthManagerServiceImpl.java
@@ -17,6 +17,7 @@
package org.microg.gms.auth;
import android.accounts.Account;
+import android.accounts.AccountManager;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
@@ -167,6 +168,7 @@ public class AuthManagerServiceImpl extends IAuthManagerService.Stub {
packageName = PackageUtils.getAndCheckCallingPackage(context, packageName, extras.getInt(KEY_CALLER_UID, 0), extras.getInt(KEY_CALLER_PID, 0));
Log.d(TAG, "clearToken: token:" + token + " extras:" + extras);
+ AccountManager.get(context).invalidateAuthToken(AuthConstants.DEFAULT_ACCOUNT_TYPE, token);
return null;
}
diff --git a/play-services-core/src/main/java/org/microg/gms/auth/login/LoginActivity.java b/play-services-core/src/main/java/org/microg/gms/auth/login/LoginActivity.java
index d37a99c63ddefd69535a0a5ff29f6ca9af62b943..a538c55ffa3c8cd9d2b23537c023d11d219e24a0 100644
--- a/play-services-core/src/main/java/org/microg/gms/auth/login/LoginActivity.java
+++ b/play-services-core/src/main/java/org/microg/gms/auth/login/LoginActivity.java
@@ -55,6 +55,7 @@ import org.microg.gms.checkin.CheckinManager;
import org.microg.gms.checkin.LastCheckinInfo;
import org.microg.gms.common.HttpFormClient;
import org.microg.gms.common.Utils;
+import org.microg.gms.gcm.McsService;
import org.microg.gms.people.PeopleManager;
import java.io.IOException;
@@ -308,7 +309,12 @@ public class LoginActivity extends AssistantActivity {
@Override
public void onException(Exception exception) {
- Log.w(TAG, "onException: " + exception);
+ Log.w(TAG, "onException", exception);
+ runOnUiThread(() -> {
+ showError(R.string.auth_general_error_desc);
+ setNextButtonText(android.R.string.ok);
+ });
+ state = -2;
}
});
}
@@ -339,7 +345,12 @@ public class LoginActivity extends AssistantActivity {
@Override
public void onException(Exception exception) {
- Log.w(TAG, "onException: " + exception);
+ Log.w(TAG, "onException", exception);
+ runOnUiThread(() -> {
+ showError(R.string.auth_general_error_desc);
+ setNextButtonText(android.R.string.ok);
+ });
+ state = -2;
}
});
}
@@ -347,6 +358,7 @@ public class LoginActivity extends AssistantActivity {
private boolean checkin(boolean force) {
try {
CheckinManager.checkin(LoginActivity.this, force);
+ McsService.scheduleReconnect(this);
return true;
} catch (IOException e) {
Log.w(TAG, "Checkin failed", e);
diff --git a/play-services-core/src/main/java/org/microg/gms/common/PackageUtils.java b/play-services-core/src/main/java/org/microg/gms/common/PackageUtils.java
index 8660dcdbe58a296e172747502c97496ab7009507..a2b65de1976e27161f8e355c92a8f11c50938e80 100644
--- a/play-services-core/src/main/java/org/microg/gms/common/PackageUtils.java
+++ b/play-services-core/src/main/java/org/microg/gms/common/PackageUtils.java
@@ -62,6 +62,7 @@ public class PackageUtils {
KNOWN_GOOGLE_PACKAGES.put("com.google.android.apps.wellbeing", "4ebdd02380f1fa0b6741491f0af35625dba76e9f");
KNOWN_GOOGLE_PACKAGES.put("com.google.android.apps.village.boond", "48e7985b8f901df335b5d5223579c81618431c7b");
KNOWN_GOOGLE_PACKAGES.put("com.google.android.apps.subscriptions.red", "de8304ace744ae4c4e05887a27a790815e610ff0");
+ KNOWN_GOOGLE_PACKAGES.put("com.google.android.apps.meetings", "47a6936b733dbdb45d71997fbe1d610eca36b8bf");
}
public static boolean isGooglePackage(Context context, String packageName) {
@@ -69,6 +70,11 @@ public class PackageUtils {
return isGooglePackage(packageName, signatureDigest);
}
+ public static boolean isGooglePackage(PackageManager packageManager, String packageName) {
+ String signatureDigest = firstSignatureDigest(packageManager, packageName);
+ return isGooglePackage(packageName, signatureDigest);
+ }
+
public static boolean isGooglePackage(String packageName, byte[] bytes) {
return isGooglePackage(packageName, sha1sum(bytes));
}
@@ -102,7 +108,11 @@ public class PackageUtils {
@Nullable
public static String firstSignatureDigest(Context context, String packageName) {
- PackageManager packageManager = context.getPackageManager();
+ return firstSignatureDigest(context.getPackageManager(), packageName);
+ }
+
+ @Nullable
+ public static String firstSignatureDigest(PackageManager packageManager, String packageName) {
final PackageInfo info;
try {
info = packageManager.getPackageInfo(packageName, PackageManager.GET_SIGNATURES);
diff --git a/play-services-core/src/main/java/org/microg/gms/common/RemoteListenerProxy.java b/play-services-core/src/main/java/org/microg/gms/common/RemoteListenerProxy.java
index 1e2fa5ead6bea789f646634060bdf48a3ec5cbbd..46ebca3b9013e24281733958a5b1725652e0cc72 100644
--- a/play-services-core/src/main/java/org/microg/gms/common/RemoteListenerProxy.java
+++ b/play-services-core/src/main/java/org/microg/gms/common/RemoteListenerProxy.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013-2017 microG Project Team
+ * Copyright (C) 2013-2019 microG Project Team
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -66,7 +66,6 @@ public class RemoteListenerProxy implements ServiceConnect
if (!connecting) Log.d(TAG, "Could not connect to: " + intent);
return connecting;
}
- Log.d(TAG, "Unable to resolve: " + searchIntent);
return false;
} catch (Exception e) {
Log.w(TAG, e);
@@ -91,11 +90,17 @@ public class RemoteListenerProxy implements ServiceConnect
synchronized (this) {
remote = service;
if (!waiting.isEmpty()) {
- for (Runnable runnable : waiting) {
- runnable.run();
+ try {
+ for (Runnable runnable : waiting) {
+ runnable.run();
+ }
+ } catch (Exception e) {
}
waiting.clear();
- context.unbindService(RemoteListenerProxy.this);
+ try {
+ context.unbindService(RemoteListenerProxy.this);
+ } catch (Exception e) {
+ }
connecting = false;
remote = null;
}
diff --git a/play-services-core/src/main/java/org/microg/gms/location/GoogleLocationManagerServiceImpl.java b/play-services-core/src/main/java/org/microg/gms/location/GoogleLocationManagerServiceImpl.java
index 97b0357053de282debadb68f7ef34294f690cde1..c66c0be436ea471ce731196f2cea9e077c8f76e7 100644
--- a/play-services-core/src/main/java/org/microg/gms/location/GoogleLocationManagerServiceImpl.java
+++ b/play-services-core/src/main/java/org/microg/gms/location/GoogleLocationManagerServiceImpl.java
@@ -307,7 +307,7 @@ public class GoogleLocationManagerServiceImpl extends IGoogleLocationManagerServ
public void requestLocationSettingsDialog(LocationSettingsRequest settingsRequest, ISettingsCallbacks callback, String packageName) throws RemoteException {
Log.d(TAG, "requestLocationSettingsDialog: " + settingsRequest);
PackageUtils.getAndCheckCallingPackage(context, packageName);
- callback.onLocationSettingsResult(new LocationSettingsResult(new LocationSettingsStates(true, true, false, true, true, false), Status.CANCELED));
+ callback.onLocationSettingsResult(new LocationSettingsResult(new LocationSettingsStates(true, true, false, true, true, false), Status.SUCCESS));
}
@Override
diff --git a/play-services-core/src/main/java/org/microg/gms/people/PeopleServiceImpl.java b/play-services-core/src/main/java/org/microg/gms/people/PeopleServiceImpl.java
index 9d9af368c2dc7ef3f31efadbbfeaabfa26c5d7d9..a2f1001581e8eb7c545fe336505cd6d0f81269d5 100644
--- a/play-services-core/src/main/java/org/microg/gms/people/PeopleServiceImpl.java
+++ b/play-services-core/src/main/java/org/microg/gms/people/PeopleServiceImpl.java
@@ -16,9 +16,11 @@
package org.microg.gms.people;
+import android.Manifest;
import android.accounts.Account;
import android.accounts.AccountManager;
import android.content.Context;
+import android.content.pm.PackageManager;
import android.database.Cursor;
import android.os.Bundle;
import android.os.Parcel;
@@ -26,7 +28,6 @@ import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
import android.util.Log;
-import com.google.android.gms.R;
import com.google.android.gms.common.data.DataHolder;
import com.google.android.gms.common.internal.ICancelToken;
import com.google.android.gms.people.internal.IPeopleCallbacks;
@@ -51,7 +52,9 @@ public class PeopleServiceImpl extends IPeopleService.Stub {
@Override
public void loadOwners(final IPeopleCallbacks callbacks, boolean var2, boolean var3, final String accountName, String var5, int sortOrder) {
Log.d(TAG, "loadOwners: " + var2 + ", " + var3 + ", " + accountName + ", " + var5 + ", " + sortOrder);
- PackageUtils.assertExtendedAccess(context);
+ if (context.checkCallingPermission(Manifest.permission.READ_CONTACTS) != PackageManager.PERMISSION_GRANTED) {
+ PackageUtils.assertExtendedAccess(context);
+ }
AccountManager accountManager = AccountManager.get(context);
Bundle accountMetadata = new Bundle();
String accountType = AuthConstants.DEFAULT_ACCOUNT_TYPE;
diff --git a/play-services-core/src/main/java/org/microg/gms/tapandpay/TapAndPayImpl.java b/play-services-core/src/main/java/org/microg/gms/tapandpay/TapAndPayImpl.java
new file mode 100644
index 0000000000000000000000000000000000000000..406326503ff769707c32611c96b4234dcc94164a
--- /dev/null
+++ b/play-services-core/src/main/java/org/microg/gms/tapandpay/TapAndPayImpl.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2019 microG Project Team
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.microg.gms.tapandpay;
+
+import com.google.android.gms.tapandpay.internal.ITapAndPayService;
+import android.os.Parcel;
+import android.os.RemoteException;
+import android.util.Log;
+
+public class TapAndPayImpl extends ITapAndPayService.Stub {
+ private static final String TAG = "GmsTapAndPayImpl";
+
+ @Override
+ public boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {
+ if (super.onTransact(code, data, reply, flags)) return true;
+ Log.d(TAG, "onTransact [unknown]: " + code + ", " + data + ", " + flags);
+ return false;
+ }
+}
diff --git a/play-services-core/src/main/java/org/microg/gms/tapandpay/TapAndPayService.java b/play-services-core/src/main/java/org/microg/gms/tapandpay/TapAndPayService.java
new file mode 100644
index 0000000000000000000000000000000000000000..082234e643bdc741cfa87af6e17efced1838b244
--- /dev/null
+++ b/play-services-core/src/main/java/org/microg/gms/tapandpay/TapAndPayService.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2019 microG Project Team
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.microg.gms.tapandpay;
+
+import android.os.RemoteException;
+
+import com.google.android.gms.common.api.CommonStatusCodes;
+import com.google.android.gms.common.internal.GetServiceRequest;
+import com.google.android.gms.common.internal.IGmsCallbacks;
+
+import org.microg.gms.BaseService;
+import org.microg.gms.common.GmsService;
+
+public class TapAndPayService extends BaseService {
+ public TapAndPayService() {
+ super("GmsTapAndPaySvc", GmsService.TAP_AND_PAY);
+ }
+
+ @Override
+ public void handleServiceRequest(IGmsCallbacks callback, GetServiceRequest request, GmsService service) throws RemoteException {
+ callback.onPostInitComplete(CommonStatusCodes.SUCCESS, new TapAndPayImpl(), null);
+
+ }
+}
diff --git a/play-services-core/src/main/java/org/microg/gms/wearable/CapabilityManager.java b/play-services-core/src/main/java/org/microg/gms/wearable/CapabilityManager.java
new file mode 100644
index 0000000000000000000000000000000000000000..0c8f59ffc676c1e999f0c1e261cfe4b3bfb0a128
--- /dev/null
+++ b/play-services-core/src/main/java/org/microg/gms/wearable/CapabilityManager.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2019 microG Project Team
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.microg.gms.wearable;
+
+import android.content.Context;
+import android.net.Uri;
+
+import com.google.android.gms.common.api.CommonStatusCodes;
+import com.google.android.gms.common.data.DataHolder;
+import com.google.android.gms.wearable.Node;
+import com.google.android.gms.wearable.WearableStatusCodes;
+import com.google.android.gms.wearable.internal.NodeParcelable;
+
+import org.microg.gms.common.PackageUtils;
+
+import java.util.HashSet;
+import java.util.Set;
+
+public class CapabilityManager {
+ private static final Uri ROOT = Uri.parse("wear:/capabilities/");
+ private final Context context;
+ private final WearableImpl wearable;
+ private final String packageName;
+
+ private Set capabilities = new HashSet();
+
+ public CapabilityManager(Context context, WearableImpl wearable, String packageName) {
+ this.context = context;
+ this.wearable = wearable;
+ this.packageName = packageName;
+ }
+
+ private Uri buildCapabilityUri(String capability, boolean withAuthority) {
+ Uri.Builder builder = ROOT.buildUpon();
+ if (withAuthority) builder.authority(wearable.getLocalNodeId());
+ builder.appendPath(packageName);
+ builder.appendPath(PackageUtils.firstSignatureDigest(context, packageName));
+ builder.appendPath(Uri.encode(capability));
+ return builder.build();
+ }
+
+ public Set getNodesForCapability(String capability) {
+ DataHolder dataHolder = wearable.getDataItemsByUriAsHolder(buildCapabilityUri(capability, false), packageName);
+ Set nodes = new HashSet<>();
+ for (int i = 0; i < dataHolder.getCount(); i++) {
+ nodes.add(dataHolder.getString("host", i, 0));
+ }
+ dataHolder.close();
+ return nodes;
+ }
+
+ public int add(String capability) {
+ if (this.capabilities.contains(capability)) {
+ return WearableStatusCodes.DUPLICATE_CAPABILITY;
+ }
+ DataItemInternal dataItem = new DataItemInternal(buildCapabilityUri(capability, true));
+ DataItemRecord record = wearable.putDataItem(packageName, PackageUtils.firstSignatureDigest(context, packageName), wearable.getLocalNodeId(), dataItem);
+ this.capabilities.add(capability);
+ wearable.syncRecordToAll(record);
+ return CommonStatusCodes.SUCCESS;
+ }
+
+ public int remove(String capability) {
+ if (!this.capabilities.contains(capability)) {
+ return WearableStatusCodes.UNKNOWN_CAPABILITY;
+ }
+ wearable.deleteDataItems(buildCapabilityUri(capability, true), packageName);
+ capabilities.remove(capability);
+ return CommonStatusCodes.SUCCESS;
+ }
+}
diff --git a/play-services-core/src/main/java/org/microg/gms/wearable/WearableImpl.java b/play-services-core/src/main/java/org/microg/gms/wearable/WearableImpl.java
index 852438921943450a16ecb1fafdc732a71e5c2a73..0406005defa3a0db0b32de585dc4c725be152a62 100644
--- a/play-services-core/src/main/java/org/microg/gms/wearable/WearableImpl.java
+++ b/play-services-core/src/main/java/org/microg/gms/wearable/WearableImpl.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013-2017 microG Project Team
+ * Copyright (C) 2013-2019 microG Project Team
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,14 +16,15 @@
package org.microg.gms.wearable;
-import android.annotation.TargetApi;
import android.content.Context;
import android.content.Intent;
+import android.content.IntentFilter;
import android.database.Cursor;
import android.net.Uri;
import android.os.Handler;
import android.os.Looper;
import android.os.RemoteException;
+import android.support.annotation.Nullable;
import android.text.TextUtils;
import android.util.Base64;
import android.util.Log;
@@ -37,7 +38,6 @@ import com.google.android.gms.wearable.internal.MessageEventParcelable;
import com.google.android.gms.wearable.internal.NodeParcelable;
import com.google.android.gms.wearable.internal.PutDataRequest;
-import org.microg.gms.common.MultiListenerProxy;
import org.microg.gms.common.PackageUtils;
import org.microg.gms.common.RemoteListenerProxy;
import org.microg.gms.common.Utils;
@@ -52,6 +52,7 @@ import org.microg.wearable.proto.FilePiece;
import org.microg.wearable.proto.Request;
import org.microg.wearable.proto.RootMessage;
import org.microg.wearable.proto.SetAsset;
+import org.microg.wearable.proto.SetDataItem;
import java.io.File;
import java.io.FileInputStream;
@@ -70,8 +71,6 @@ import java.util.Set;
import okio.ByteString;
-import static android.os.Build.VERSION.SDK_INT;
-
public class WearableImpl {
private static final String TAG = "GmsWear";
@@ -81,7 +80,7 @@ public class WearableImpl {
private final Context context;
private final NodeDatabaseHelper nodeDatabase;
private final ConfigurationDatabaseHelper configDatabase;
- private final Map> listeners = new HashMap>();
+ private final Map> listeners = new HashMap>();
private final Set connectedNodes = new HashSet();
private final Map activeConnections = new HashMap();
private RpcHelper rpcHelper;
@@ -130,12 +129,10 @@ public class WearableImpl {
}
}
}
- try {
- getListener(record.packageName, "com.google.android.gms.wearable.DATA_CHANGED", record.dataItem.uri)
- .onDataChanged(record.toEventDataHolder());
- } catch (RemoteException e) {
- Log.w(TAG, e);
- }
+ Intent intent = new Intent("com.google.android.gms.wearable.DATA_CHANGED");
+ intent.setPackage(record.packageName);
+ intent.setData(record.dataItem.uri);
+ invokeListeners(intent, listener -> listener.onDataChanged(record.toEventDataHolder()));
return record;
}
@@ -247,8 +244,7 @@ public class WearableImpl {
}
- private void syncRecordToAll(DataItemRecord record) {
- Log.d(TAG, "Syncing record " + record + " over " + activeConnections.size() + " connections.");
+ void syncRecordToAll(DataItemRecord record) {
for (String nodeId : new ArrayList(activeConnections.keySet())) {
syncRecordToPeer(nodeId, record);
}
@@ -256,47 +252,45 @@ public class WearableImpl {
private boolean syncRecordToPeer(String nodeId, DataItemRecord record) {
for (Asset asset : record.dataItem.getAssets().values()) {
- syncAssetToPeer(nodeId, record, asset);
+ try {
+ syncAssetToPeer(nodeId, record, asset);
+ } catch (Exception e) {
+ Log.w(TAG, "Could not sync asset " + asset + " for " + nodeId + " and " + record, e);
+ closeConnection(nodeId);
+ return false;
+ }
}
- Log.d(TAG, "Sync over to " + nodeId + ": " + record);
try {
- activeConnections.get(nodeId).writeMessage(new RootMessage.Builder().setDataItem(record.toSetDataItem()).build());
- } catch (IOException e) {
- closeConnection(nodeId);
+ SetDataItem item = record.toSetDataItem();
+ activeConnections.get(nodeId).writeMessage(new RootMessage.Builder().setDataItem(item).build());
+ } catch (Exception e) {
Log.w(TAG, e);
+ closeConnection(nodeId);
return false;
}
return true;
}
- private void syncAssetToPeer(String nodeId, DataItemRecord record, Asset asset) {
- try {
- Log.d(TAG, "Sync over to " + nodeId + ": " + asset);
- RootMessage announceMessage = new RootMessage.Builder().setAsset(new SetAsset.Builder()
- .digest(asset.getDigest())
- .appkeys(new AppKeys(Collections.singletonList(new AppKey(record.packageName, record.signatureDigest))))
- .build()).hasAsset(true).build();
- activeConnections.get(nodeId).writeMessage(announceMessage);
- File assetFile = createAssetFile(asset.getDigest());
- String fileName = calculateDigest(announceMessage.toByteArray());
- FileInputStream fis = new FileInputStream(assetFile);
- byte[] arr = new byte[12215];
- ByteString lastPiece = null;
- int c = 0;
- while ((c = fis.read(arr)) > 0) {
- if (lastPiece != null) {
- Log.d(TAG, "Sync over to " + nodeId + ": Asset piece for fileName " + fileName + ": " + lastPiece);
- activeConnections.get(nodeId).writeMessage(new RootMessage.Builder().filePiece(new FilePiece(fileName, false, lastPiece, null)).build());
- }
- lastPiece = ByteString.of(arr, 0, c);
+ private void syncAssetToPeer(String nodeId, DataItemRecord record, Asset asset) throws IOException {
+ RootMessage announceMessage = new RootMessage.Builder().setAsset(new SetAsset.Builder()
+ .digest(asset.getDigest())
+ .appkeys(new AppKeys(Collections.singletonList(new AppKey(record.packageName, record.signatureDigest))))
+ .build()).hasAsset(true).build();
+ activeConnections.get(nodeId).writeMessage(announceMessage);
+ File assetFile = createAssetFile(asset.getDigest());
+ String fileName = calculateDigest(announceMessage.toByteArray());
+ FileInputStream fis = new FileInputStream(assetFile);
+ byte[] arr = new byte[12215];
+ ByteString lastPiece = null;
+ int c = 0;
+ while ((c = fis.read(arr)) > 0) {
+ if (lastPiece != null) {
+ activeConnections.get(nodeId).writeMessage(new RootMessage.Builder().filePiece(new FilePiece(fileName, false, lastPiece, null)).build());
}
- Log.d(TAG, "Sync over to " + nodeId + ": Last asset piece for fileName " + fileName + ": " + lastPiece);
- activeConnections.get(nodeId).writeMessage(new RootMessage.Builder().filePiece(new FilePiece(fileName, true, lastPiece, asset.getDigest())).build());
- } catch (IOException e) {
- Log.w(TAG, e);
- closeConnection(nodeId);
+ lastPiece = ByteString.of(arr, 0, c);
}
+ activeConnections.get(nodeId).writeMessage(new RootMessage.Builder().filePiece(new FilePiece(fileName, true, lastPiece, asset.getDigest())).build());
}
public void addAssetToDatabase(Asset asset, List appKeys) {
@@ -394,37 +388,59 @@ public class WearableImpl {
return nodes;
}
- public IWearableListener getAllListeners() {
- return MultiListenerProxy.get(IWearableListener.class, new MultiListenerProxy.MultiCollectionListenerPool(listeners.values()));
+ interface ListenerInvoker {
+ void invoke(IWearableListener listener) throws RemoteException;
+ }
+
+ private void invokeListeners(@Nullable Intent intent, ListenerInvoker invoker) {
+ for (String packageName : new ArrayList<>(listeners.keySet())) {
+ List listeners = this.listeners.get(packageName);
+ if (listeners == null) continue;
+ for (int i = 0; i < listeners.size(); i++) {
+ boolean filterMatched = false;
+ if (intent != null) {
+ for (IntentFilter filter : listeners.get(i).filters) {
+ filterMatched |= filter.match(context.getContentResolver(), intent, false, TAG) > 0;
+ }
+ }
+ if (filterMatched || listeners.get(i).filters.length == 0) {
+ try {
+ invoker.invoke(listeners.get(i).listener);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Registered listener at package " + packageName + " failed, removing.");
+ listeners.remove(i);
+ i--;
+ }
+ }
+ }
+ if (listeners.isEmpty()) {
+ this.listeners.remove(packageName);
+ }
+ }
+ if (intent != null) {
+ try {
+ invoker.invoke(RemoteListenerProxy.get(context, intent, IWearableListener.class, "com.google.android.gms.wearable.BIND_LISTENER"));
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failed to deliver message received to " + intent, e);
+ }
+ }
}
public void onPeerConnected(NodeParcelable node) {
Log.d(TAG, "onPeerConnected: " + node);
- try {
- getAllListeners().onPeerConnected(node);
- } catch (RemoteException e) {
- Log.w(TAG, e);
- }
+ invokeListeners(null, listener -> listener.onPeerConnected(node));
addConnectedNode(node);
}
public void onPeerDisconnected(NodeParcelable node) {
Log.d(TAG, "onPeerDisconnected: " + node);
- try {
- getAllListeners().onPeerDisconnected(node);
- } catch (RemoteException e) {
- Log.w(TAG, e);
- }
+ invokeListeners(null, listener -> listener.onPeerDisconnected(node));
removeConnectedNode(node.getId());
}
public void onConnectedNodes(List nodes) {
Log.d(TAG, "onConnectedNodes: " + nodes);
- try {
- getAllListeners().onConnectedNodes(nodes);
- } catch (RemoteException e) {
- Log.w(TAG, e);
- }
+ invokeListeners(null, listener -> listener.onConnectedNodes(nodes));
}
public DataItemRecord putData(PutDataRequest request, String packageName) {
@@ -444,11 +460,6 @@ public class WearableImpl {
public DataHolder getDataItemsAsHolder(String packageName) {
Cursor dataHolderItems = nodeDatabase.getDataItemsForDataHolder(packageName, PackageUtils.firstSignatureDigest(context, packageName));
- while (dataHolderItems.moveToNext()) {
- Log.d(TAG, "getDataItems[]: path=" + Uri.parse(dataHolderItems.getString(1)).getPath());
- }
- dataHolderItems.moveToFirst();
- dataHolderItems.moveToPrevious();
return new DataHolder(dataHolderItems, 0, null);
}
@@ -467,40 +478,26 @@ public class WearableImpl {
return null;
}
Cursor dataHolderItems = nodeDatabase.getDataItemsForDataHolderByHostAndPath(packageName, firstSignature, fixHost(uri.getHost(), false), uri.getPath());
- maybeDebugCursor("getDataItems",dataHolderItems);
- dataHolderItems.moveToFirst();
- dataHolderItems.moveToPrevious();
DataHolder dataHolder = new DataHolder(dataHolderItems, 0, null);
Log.d(TAG, "Returning data holder of size " + dataHolder.getCount() + " for query " + uri);
return dataHolder;
}
- @TargetApi(11)
- private void maybeDebugCursor(String what, Cursor cursor) {
- if (SDK_INT >= 11) {
- int j = 0;
- while (cursor.moveToNext()) {
- for (int i = 0; i < cursor.getColumnCount(); i++) {
- if (cursor.getType(i) == Cursor.FIELD_TYPE_STRING) {
- Log.d(TAG, what+"[" + j + "]: " + cursor.getColumnName(i) + "=" + cursor.getString(i));
- }
- if (cursor.getType(i) == Cursor.FIELD_TYPE_INTEGER)
- Log.d(TAG, what+"[" + j + "]: " + cursor.getColumnName(i) + "=" + cursor.getLong(i));
- }
- }
- }
- }
-
- public synchronized void addListener(String packageName, IWearableListener listener) {
+ public synchronized void addListener(String packageName, IWearableListener listener, IntentFilter[] filters) {
if (!listeners.containsKey(packageName)) {
- listeners.put(packageName, new ArrayList());
+ listeners.put(packageName, new ArrayList());
}
- listeners.get(packageName).add(listener);
+ listeners.get(packageName).add(new ListenerInfo(listener, filters));
}
public void removeListener(IWearableListener listener) {
- for (List list : listeners.values()) {
- list.remove(listener);
+ for (List list : listeners.values()) {
+ for (int i = 0; i < list.size(); i++) {
+ if (list.get(i).listener.equals(listener)) {
+ list.remove(i);
+ i--;
+ }
+ }
}
}
@@ -546,12 +543,10 @@ public class WearableImpl {
public void sendMessageReceived(String packageName, MessageEventParcelable messageEvent) {
Log.d(TAG, "onMessageReceived: " + messageEvent);
- try {
- getListener(packageName, "com.google.android.gms.wearable.MESSAGE_RECEIVED", Uri.parse("wear://" + getLocalNodeId() + "/" + messageEvent.getPath()))
- .onMessageReceived(messageEvent);
- } catch (RemoteException e) {
- Log.w(TAG, e);
- }
+ Intent intent = new Intent("com.google.android.gms.wearable.MESSAGE_RECEIVED");
+ intent.setPackage(packageName);
+ intent.setData(Uri.parse("wear://" + getLocalNodeId() + "/" + messageEvent.getPath()));
+ invokeListeners(intent, listener -> listener.onMessageReceived(messageEvent));
}
public DataItemRecord getDataItemByUri(Uri uri, String packageName) {
@@ -568,17 +563,11 @@ public class WearableImpl {
}
private IWearableListener getListener(String packageName, String action, Uri uri) {
- synchronized (this) {
- List l = new ArrayList(listeners.containsKey(packageName) ? listeners.get(packageName) : Collections.emptyList());
+ Intent intent = new Intent(action);
+ intent.setPackage(packageName);
+ intent.setData(uri);
- Intent intent = new Intent(action);
- intent.setPackage(packageName);
- intent.setData(uri);
-
- l.add(RemoteListenerProxy.get(context, intent, IWearableListener.class, "com.google.android.gms.wearable.BIND_LISTENER"));
-
- return MultiListenerProxy.get(IWearableListener.class, l);
- }
+ return RemoteListenerProxy.get(context, intent, IWearableListener.class, "com.google.android.gms.wearable.BIND_LISTENER");
}
private void closeConnection(String nodeId) {
@@ -594,7 +583,7 @@ public class WearableImpl {
}
activeConnections.remove(nodeId);
for (ConnectionConfiguration config : getConfigurations()) {
- if (config.nodeId.equals(nodeId) || config.peerNodeId.equals(nodeId)) {
+ if (nodeId.equals(config.nodeId) || nodeId.equals(config.peerNodeId)) {
config.connected = false;
}
}
@@ -631,4 +620,14 @@ public class WearableImpl {
public void stop() {
this.networkHandler.getLooper().quit();
}
+
+ private class ListenerInfo {
+ private IWearableListener listener;
+ private IntentFilter[] filters;
+
+ private ListenerInfo(IWearableListener listener, IntentFilter[] filters) {
+ this.listener = listener;
+ this.filters = filters;
+ }
+ }
}
diff --git a/play-services-core/src/main/java/org/microg/gms/wearable/WearableServiceImpl.java b/play-services-core/src/main/java/org/microg/gms/wearable/WearableServiceImpl.java
index ef830d3b49d7ba74f885ce8eac4b83c2b6768891..e091ba729c732ff7a172c6251170f45e3f546eec 100644
--- a/play-services-core/src/main/java/org/microg/gms/wearable/WearableServiceImpl.java
+++ b/play-services-core/src/main/java/org/microg/gms/wearable/WearableServiceImpl.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013-2017 microG Project Team
+ * Copyright (C) 2013-2019 microG Project Team
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -29,8 +29,11 @@ import com.google.android.gms.common.api.Status;
import com.google.android.gms.wearable.Asset;
import com.google.android.gms.wearable.ConnectionConfiguration;
import com.google.android.gms.wearable.internal.AddListenerRequest;
+import com.google.android.gms.wearable.internal.AddLocalCapabilityResponse;
import com.google.android.gms.wearable.internal.AncsNotificationParcelable;
+import com.google.android.gms.wearable.internal.CapabilityInfoParcelable;
import com.google.android.gms.wearable.internal.DeleteDataItemsResponse;
+import com.google.android.gms.wearable.internal.GetCapabilityResponse;
import com.google.android.gms.wearable.internal.GetCloudSyncSettingResponse;
import com.google.android.gms.wearable.internal.GetConfigResponse;
import com.google.android.gms.wearable.internal.GetConfigsResponse;
@@ -45,9 +48,13 @@ import com.google.android.gms.wearable.internal.NodeParcelable;
import com.google.android.gms.wearable.internal.PutDataRequest;
import com.google.android.gms.wearable.internal.PutDataResponse;
import com.google.android.gms.wearable.internal.RemoveListenerRequest;
+import com.google.android.gms.wearable.internal.RemoveLocalCapabilityResponse;
import com.google.android.gms.wearable.internal.SendMessageResponse;
import java.io.FileNotFoundException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
public class WearableServiceImpl extends IWearableService.Stub {
private static final String TAG = "GmsWearSvcImpl";
@@ -56,11 +63,13 @@ public class WearableServiceImpl extends IWearableService.Stub {
private final String packageName;
private final WearableImpl wearable;
private final Handler mainHandler;
+ private final CapabilityManager capabilities;
public WearableServiceImpl(Context context, WearableImpl wearable, String packageName) {
this.context = context;
this.wearable = wearable;
this.packageName = packageName;
+ this.capabilities = new CapabilityManager(context, wearable, packageName);
this.mainHandler = new Handler(context.getMainLooper());
}
@@ -191,8 +200,11 @@ public class WearableServiceImpl extends IWearableService.Stub {
@Override
public void deleteDataItemsWithFilter(IWearableCallbacks callbacks, final Uri uri, int typeFilter) throws RemoteException {
Log.d(TAG, "deleteDataItems: " + uri);
- postMain(callbacks, () -> {
- callbacks.onDeleteDataItemsResponse(new DeleteDataItemsResponse(0, wearable.deleteDataItems(uri, packageName)));
+ this.wearable.networkHandler.post(new CallbackRunnable(callbacks) {
+ @Override
+ public void run(IWearableCallbacks callbacks) throws RemoteException {
+ callbacks.onDeleteDataItemsResponse(new DeleteDataItemsResponse(0, wearable.deleteDataItems(uri, packageName)));
+ }
});
}
@@ -289,29 +301,49 @@ public class WearableServiceImpl extends IWearableService.Stub {
*/
@Override
- public void getConnectedCapability(IWearableCallbacks callbacks, String s1, int i) throws RemoteException {
- Log.d(TAG, "unimplemented Method: getConnectedCapability " + s1 + ", " + i);
+ public void getConnectedCapability(IWearableCallbacks callbacks, String capability, int nodeFilter) throws RemoteException {
+ Log.d(TAG, "unimplemented Method: getConnectedCapability " + capability + ", " + nodeFilter);
+ postMain(callbacks, () -> {
+ List nodes = new ArrayList<>();
+ for (String host : capabilities.getNodesForCapability(capability)) {
+ nodes.add(new NodeParcelable(host, host));
+ }
+ CapabilityInfoParcelable capabilityInfo = new CapabilityInfoParcelable(capability, nodes);
+ callbacks.onGetCapabilityResponse(new GetCapabilityResponse(0, capabilityInfo));
+ });
}
@Override
- public void getConnectedCapaibilties(IWearableCallbacks callbacks, int i) throws RemoteException {
- Log.d(TAG, "unimplemented Method: getConnectedCapaibilties: " + i);
+ public void getConnectedCapaibilties(IWearableCallbacks callbacks, int nodeFilter) throws RemoteException {
+ Log.d(TAG, "unimplemented Method: getConnectedCapaibilties: " + nodeFilter);
}
@Override
- public void addLocalCapability(IWearableCallbacks callbacks, String cap) throws RemoteException {
- Log.d(TAG, "unimplemented Method: addLocalCapability: " + cap);
+ public void addLocalCapability(IWearableCallbacks callbacks, String capability) throws RemoteException {
+ Log.d(TAG, "unimplemented Method: addLocalCapability: " + capability);
+ this.wearable.networkHandler.post(new CallbackRunnable(callbacks) {
+ @Override
+ public void run(IWearableCallbacks callbacks) throws RemoteException {
+ callbacks.onAddLocalCapabilityResponse(new AddLocalCapabilityResponse(capabilities.add(capability)));
+ }
+ });
}
@Override
- public void removeLocalCapability(IWearableCallbacks callbacks, String cap) throws RemoteException {
- Log.d(TAG, "unimplemented Method: removeLocalCapability: " + cap);
+ public void removeLocalCapability(IWearableCallbacks callbacks, String capability) throws RemoteException {
+ Log.d(TAG, "unimplemented Method: removeLocalCapability: " + capability);
+ this.wearable.networkHandler.post(new CallbackRunnable(callbacks) {
+ @Override
+ public void run(IWearableCallbacks callbacks) throws RemoteException {
+ callbacks.onRemoveLocalCapabilityResponse(new RemoveLocalCapabilityResponse(capabilities.remove(capability)));
+ }
+ });
}
@Override
public void addListener(IWearableCallbacks callbacks, AddListenerRequest request) throws RemoteException {
if (request.listener != null) {
- wearable.addListener(packageName, request.listener);
+ wearable.addListener(packageName, request.listener, request.intentFilters);
}
callbacks.onStatus(Status.SUCCESS);
}
diff --git a/play-services-maps-core-mapbox/src/main/java/com/google/android/gms/maps/internal/CreatorImpl.java b/play-services-maps-core-mapbox/src/main/java/com/google/android/gms/maps/internal/CreatorImpl.java
index df0fb3e9823197cc3ed15b5c0a803259f9c2fcb6..96a3c191bb7849514434110b278619ff80c1b493 100644
--- a/play-services-maps-core-mapbox/src/main/java/com/google/android/gms/maps/internal/CreatorImpl.java
+++ b/play-services-maps-core-mapbox/src/main/java/com/google/android/gms/maps/internal/CreatorImpl.java
@@ -65,9 +65,9 @@ public class CreatorImpl extends ICreator.Stub {
@Override
public void initV2(IObjectWrapper resources, int flags) {
- BitmapDescriptorFactoryImpl.INSTANCE.initialize(ObjectWrapper.unwrapTyped(resources, Resources.class));
+ BitmapDescriptorFactoryImpl.INSTANCE.initialize(ObjectWrapper.unwrapTyped(resources, Resources.class), null);
//ResourcesContainer.set((Resources) ObjectWrapper.unwrap(resources));
- Log.d(TAG, "initV2");
+ Log.d(TAG, "initV2 " + flags);
}
@Override
diff --git a/play-services-maps-core-mapbox/src/main/kotlin/org/microg/gms/maps/mapbox/CameraBoundsWithSizeUpdate.kt b/play-services-maps-core-mapbox/src/main/kotlin/org/microg/gms/maps/mapbox/CameraBoundsWithSizeUpdate.kt
index 654feca6b5613d652047690f2ba0443849df4527..eea4304f56161ce47b83bff5400d2bea29595ab7 100644
--- a/play-services-maps-core-mapbox/src/main/kotlin/org/microg/gms/maps/mapbox/CameraBoundsWithSizeUpdate.kt
+++ b/play-services-maps-core-mapbox/src/main/kotlin/org/microg/gms/maps/mapbox/CameraBoundsWithSizeUpdate.kt
@@ -16,6 +16,7 @@
package org.microg.gms.maps.mapbox
+import android.util.Log
import com.mapbox.mapboxsdk.camera.CameraPosition
import com.mapbox.mapboxsdk.camera.CameraUpdate
import com.mapbox.mapboxsdk.geometry.LatLngBounds
@@ -28,12 +29,13 @@ internal class CameraBoundsWithSizeUpdate(val bounds: LatLngBounds, val width: I
override fun getCameraPosition(map: MapboxMap): CameraPosition? {
val padding = this.padding.clone()
- val widthPad = (map.padding[0] + map.padding[2])/2
- val heightPad = (map.padding[1] + map.padding[3])/2
+ val widthPad = ((map.width + map.padding[0] + map.padding[2] - width) / 2).toInt()
+ val heightPad = ((map.height + map.padding[1] + map.padding[3] - height) / 2).toInt()
padding[0] += widthPad
padding[1] += heightPad
padding[2] += widthPad
padding[3] += heightPad
+ Log.d(TAG, "map ${map.width} ${map.height}, set $width $height -> ${padding.map { it.toString() }.reduce { a, b -> "$a,$b"}}")
return map.getCameraForLatLngBounds(bounds, padding)
}
@@ -78,6 +80,6 @@ internal class CameraBoundsWithSizeUpdate(val bounds: LatLngBounds, val width: I
}
companion object {
- val TAG = "GmsCameraBounds"
+ const val TAG = "GmsMapCameraBounds"
}
}
\ No newline at end of file
diff --git a/play-services-maps-core-mapbox/src/main/kotlin/org/microg/gms/maps/mapbox/CameraUpdateFactory.kt b/play-services-maps-core-mapbox/src/main/kotlin/org/microg/gms/maps/mapbox/CameraUpdateFactory.kt
index 03e92de2079d9eb2f018fdc74c17a8f6338137b0..150afb4bc9677575a458cb21a3d4d9e937f84f30 100644
--- a/play-services-maps-core-mapbox/src/main/kotlin/org/microg/gms/maps/mapbox/CameraUpdateFactory.kt
+++ b/play-services-maps-core-mapbox/src/main/kotlin/org/microg/gms/maps/mapbox/CameraUpdateFactory.kt
@@ -61,11 +61,8 @@ class CameraUpdateFactoryImpl : ICameraUpdateFactoryDelegate.Stub() {
return ObjectWrapper.wrap(NoCameraUpdate())
}
- override fun newLatLngBoundsWithSize(bounds: LatLngBounds, width: Int, height: Int, padding: Int): IObjectWrapper {
- Log.d(TAG, "unimplemented Method: newLatLngBoundsWithSize")
-
- return ObjectWrapper.wrap(CameraBoundsWithSizeUpdate(bounds.toMapbox(), width, height, padding))
- }
+ override fun newLatLngBoundsWithSize(bounds: LatLngBounds, width: Int, height: Int, padding: Int): IObjectWrapper =
+ ObjectWrapper.wrap(CameraBoundsWithSizeUpdate(bounds.toMapbox(), width, height, padding))
override fun onTransact(code: Int, data: Parcel?, reply: Parcel?, flags: Int): Boolean =
if (super.onTransact(code, data, reply, flags)) {
diff --git a/play-services-maps-core-mapbox/src/main/kotlin/org/microg/gms/maps/mapbox/GoogleMap.kt b/play-services-maps-core-mapbox/src/main/kotlin/org/microg/gms/maps/mapbox/GoogleMap.kt
index f809b4f4a5d9c13cfe6547a018f6052be355ba70..b31472cb446c847765d7700d7ef3af5963b47739 100644
--- a/play-services-maps-core-mapbox/src/main/kotlin/org/microg/gms/maps/mapbox/GoogleMap.kt
+++ b/play-services-maps-core-mapbox/src/main/kotlin/org/microg/gms/maps/mapbox/GoogleMap.kt
@@ -20,6 +20,7 @@ import android.annotation.SuppressLint
import android.content.Context
import android.location.Location
import android.os.Bundle
+import android.os.IBinder
import android.os.Parcel
import android.support.annotation.IdRes
import android.support.annotation.Keep
@@ -66,12 +67,14 @@ class GoogleMapImpl(private val context: Context, var options: GoogleMapOptions)
val dpiFactor: Float
get() = context.resources.displayMetrics.densityDpi.toFloat() / DisplayMetrics.DENSITY_DEFAULT
- private var mapView: MapView?
+ private var mapView: MapView? = null
private var created = false
private var initialized = false
- private val initializedCallbackList = mutableListOf()
+ private var loaded = false
private val mapLock = Object()
+ private val initializedCallbackList = mutableListOf()
+ private var loadedCallback : IOnMapLoadedCallback? = null
private var cameraChangeListener: IOnCameraChangeListener? = null
private var cameraMoveListener: IOnCameraMoveListener? = null
private var cameraMoveCanceledListener: IOnCameraMoveCanceledListener? = null
@@ -83,7 +86,12 @@ class GoogleMapImpl(private val context: Context, var options: GoogleMapOptions)
private var markerDragListener: IOnMarkerDragListener? = null
var lineManager: LineManager? = null
+ val pendingLines = mutableSetOf()
+ var lineId = 0L
+
var fillManager: FillManager? = null
+ val pendingFills = mutableSetOf()
+ var fillId = 0L
var circleManager: CircleManager? = null
val pendingCircles = mutableSetOf()
@@ -99,6 +107,7 @@ class GoogleMapImpl(private val context: Context, var options: GoogleMapOptions)
init {
val mapContext = MapContext(context)
+ BitmapDescriptorFactoryImpl.initialize(mapContext.resources, context.resources)
LibraryLoader.setLibraryLoader(MultiArchLoader(mapContext, context))
Mapbox.getInstance(mapContext, BuildConfig.MAPBOX_KEY)
@@ -137,8 +146,6 @@ class GoogleMapImpl(private val context: Context, var options: GoogleMapOptions)
return null
}
}
- this.mapView = MapView(mapContext)
- this.view.addView(this.mapView)
}
override fun getCameraPosition(): CameraPosition? = map?.cameraPosition?.toGms()
@@ -147,43 +154,57 @@ class GoogleMapImpl(private val context: Context, var options: GoogleMapOptions)
override fun moveCamera(cameraUpdate: IObjectWrapper?) {
val update = cameraUpdate.unwrap() ?: return
- val map = this.map
- if (map != null) {
- map.moveCamera(update)
- } else {
- waitingCameraUpdates.add(update)
+ synchronized(mapLock) {
+ if (initialized) {
+ this.map?.moveCamera(update)
+ } else {
+ waitingCameraUpdates.add(update)
+ }
}
}
override fun animateCamera(cameraUpdate: IObjectWrapper?) {
val update = cameraUpdate.unwrap() ?: return
- val map = this.map
- if (map != null) {
- map.animateCamera(update)
- } else {
- waitingCameraUpdates.add(update)
+ synchronized(mapLock) {
+ if (initialized) {
+ this.map?.animateCamera(update)
+ } else {
+ waitingCameraUpdates.add(update)
+ }
}
}
+ fun afterInitialized(runnable: () -> Unit) {
+ initializedCallbackList.add(object : IOnMapReadyCallback {
+ override fun onMapReady(map: IGoogleMapDelegate?) {
+ runnable()
+ }
+
+ override fun asBinder(): IBinder? = null
+ })
+ }
+
override fun animateCameraWithCallback(cameraUpdate: IObjectWrapper?, callback: ICancelableCallback?) {
val update = cameraUpdate.unwrap() ?: return
- val map = this.map
- if (map != null) {
- map.animateCamera(update, callback?.toMapbox())
- } else {
- waitingCameraUpdates.add(update)
- callback?.onFinish()
+ synchronized(mapLock) {
+ if (initialized) {
+ this.map?.animateCamera(update, callback?.toMapbox())
+ } else {
+ waitingCameraUpdates.add(update)
+ afterInitialized { callback?.onFinish() }
+ }
}
}
override fun animateCameraWithDurationAndCallback(cameraUpdate: IObjectWrapper?, duration: Int, callback: ICancelableCallback?) {
val update = cameraUpdate.unwrap() ?: return
- val map = this.map
- if (map != null) {
- map.animateCamera(update, duration, callback?.toMapbox())
- } else {
- waitingCameraUpdates.add(update)
- callback?.onFinish()
+ synchronized(mapLock) {
+ if (initialized) {
+ this.map?.animateCamera(update, duration, callback?.toMapbox())
+ } else {
+ waitingCameraUpdates.add(update)
+ afterInitialized { callback?.onFinish() }
+ }
}
}
@@ -207,21 +228,30 @@ class GoogleMapImpl(private val context: Context, var options: GoogleMapOptions)
}
override fun addPolyline(options: PolylineOptions): IPolylineDelegate? {
- val lineOptions = LineOptions()
- .withLatLngs(options.points.map { it.toMapbox() })
- .withLineWidth(options.width / dpiFactor)
- .withLineColor(ColorUtils.colorToRgbaString(options.color))
- .withLineOpacity(if (options.isVisible) 1f else 0f)
- return lineManager?.let { PolylineImpl(this, it.create(lineOptions)) }
+ val line = PolylineImpl(this, "l${lineId++}", options)
+ synchronized(this) {
+ val lineManager = lineManager
+ if (lineManager == null) {
+ pendingLines.add(line)
+ } else {
+ line.update(lineManager)
+ }
+ }
+ return line
}
override fun addPolygon(options: PolygonOptions): IPolygonDelegate? {
- val fillOptions = FillOptions()
- .withLatLngs(listOf(options.points.map { it.toMapbox() }))
- .withFillColor(ColorUtils.colorToRgbaString(options.fillColor))
- .withFillOpacity(if (options.isVisible) 1f else 0f)
- return fillManager?.let { PolygonImpl(this, it.create(fillOptions)) }
+ val fill = PolygonImpl(this, "p${fillId++}", options)
+ synchronized(this) {
+ val fillManager = fillManager
+ if (fillManager == null) {
+ pendingFills.add(fill)
+ } else {
+ fill.update(fillManager)
+ }
+ }
+ return fill
}
override fun addMarker(options: MarkerOptions): IMarkerDelegate? {
@@ -412,7 +442,7 @@ class GoogleMapImpl(private val context: Context, var options: GoogleMapOptions)
}
override fun setPadding(left: Int, top: Int, right: Int, bottom: Int) {
- Log.d(TAG, "padding: $left, $top, $right, $bottom")
+ Log.d(TAG, "setPadding: $left $top $right $bottom")
map?.setPadding(left, top, right, bottom)
val fourDp = mapView?.context?.resources?.getDimension(R.dimen.mapbox_four_dp)?.toInt() ?: 0
val ninetyTwoDp = mapView?.context?.resources?.getDimension(R.dimen.mapbox_ninety_two_dp)?.toInt()
@@ -433,8 +463,23 @@ class GoogleMapImpl(private val context: Context, var options: GoogleMapOptions)
}
override fun setOnMapLoadedCallback(callback: IOnMapLoadedCallback?) {
- Log.d(TAG, "unimplemented Method: setOnMapLoadedCallback")
-
+ if (callback != null) {
+ synchronized(mapLock) {
+ if (loaded) {
+ Log.d(TAG, "Invoking callback instantly, as map is loaded")
+ try {
+ callback.onMapLoaded()
+ } catch (e: Exception) {
+ Log.w(TAG, e)
+ }
+ } else {
+ Log.d(TAG, "Delay callback invocation, as map is not yet loaded")
+ loadedCallback = callback
+ }
+ }
+ } else {
+ loadedCallback = null
+ }
}
override fun setCameraMoveStartedListener(listener: IOnCameraMoveStartedListener?) {
@@ -455,8 +500,12 @@ class GoogleMapImpl(private val context: Context, var options: GoogleMapOptions)
override fun onCreate(savedInstanceState: Bundle?) {
if (!created) {
- mapView?.onCreate(savedInstanceState?.toMapbox())
- mapView?.getMapAsync(this::initMap)
+ Log.d(TAG, "create");
+ val mapView = MapView(MapContext(context))
+ this.mapView = mapView
+ view.addView(mapView)
+ mapView.onCreate(savedInstanceState?.toMapbox())
+ mapView.getMapAsync(this::initMap)
created = true
}
}
@@ -533,9 +582,11 @@ class GoogleMapImpl(private val context: Context, var options: GoogleMapOptions)
options.scrollGesturesEnabled?.let { map.uiSettings.isScrollGesturesEnabled = it }
options.tiltGesturesEnabled?.let { map.uiSettings.isTiltGesturesEnabled = it }
options.camera?.let { map.cameraPosition = it.toMapbox() }
- waitingCameraUpdates.forEach { map.moveCamera(it) }
synchronized(mapLock) {
+ initialized = true
+ waitingCameraUpdates.forEach { map.moveCamera(it) }
+ val initializedCallbackList = ArrayList(initializedCallbackList)
Log.d(TAG, "Invoking ${initializedCallbackList.size} callbacks delayed, as map is initialized")
for (callback in initializedCallbackList) {
try {
@@ -544,30 +595,37 @@ class GoogleMapImpl(private val context: Context, var options: GoogleMapOptions)
Log.w(TAG, e)
}
}
- initialized = true
}
map.getStyle {
mapView?.let { view ->
- circleManager = CircleManager(view, map, it)
- lineManager = LineManager(view, map, it)
- fillManager = FillManager(view, map, it)
- lineManager?.lineCap = LINE_CAP_ROUND
- synchronized(this) {
- val symbolManager = SymbolManager(view, map, it)
- pendingMarkers.forEach { it.update(symbolManager) }
- pendingMarkers.clear()
+ if (loaded) return@let
+ val symbolManager: SymbolManager
+ val lineManager: LineManager
+ val circleManager: CircleManager
+ val fillManager: FillManager
+
+ synchronized(mapLock) {
+ circleManager = CircleManager(view, map, it)
+ fillManager = FillManager(view, map, it)
+ symbolManager = SymbolManager(view, map, it)
+ lineManager = LineManager(view, map, it)
+ lineManager.lineCap = LINE_CAP_ROUND
+
this.symbolManager = symbolManager
+ this.lineManager = lineManager
+ this.circleManager = circleManager
+ this.fillManager = fillManager
}
- symbolManager?.iconAllowOverlap = true
- symbolManager?.addClickListener {
+ symbolManager.iconAllowOverlap = true
+ symbolManager.addClickListener {
try {
markers[it.id]?.let { markerClickListener?.onMarkerClick(it) }
} catch (e: Exception) {
Log.w(TAG, e)
}
}
- symbolManager?.addDragListener(object : OnSymbolDragListener {
+ symbolManager.addDragListener(object : OnSymbolDragListener {
override fun onAnnotationDragStarted(annotation: Symbol?) {
try {
markers[annotation?.id]?.let { markerDragListener?.onMarkerDragStart(it) }
@@ -591,9 +649,23 @@ class GoogleMapImpl(private val context: Context, var options: GoogleMapOptions)
Log.w(TAG, e)
}
}
-
})
-
+ pendingCircles.forEach { it.update(circleManager) }
+ pendingCircles.clear()
+ pendingFills.forEach { it.update(fillManager) }
+ pendingFills.clear()
+ pendingLines.forEach { it.update(lineManager) }
+ pendingLines.clear()
+ pendingMarkers.forEach { it.update(symbolManager) }
+ pendingMarkers.clear()
+
+ synchronized(mapLock) {
+ loaded = true
+ if (loadedCallback != null) {
+ Log.d(TAG, "Invoking callback delayed, as map is loaded")
+ loadedCallback?.onMapLoaded()
+ }
+ }
}
}
}
@@ -606,6 +678,7 @@ class GoogleMapImpl(private val context: Context, var options: GoogleMapOptions)
override fun onResume() = mapView?.onResume() ?: Unit
override fun onPause() = mapView?.onPause() ?: Unit
override fun onDestroy() {
+ Log.d(TAG, "destroy");
circleManager?.onDestroy()
circleManager = null
lineManager?.onDestroy()
@@ -621,14 +694,18 @@ class GoogleMapImpl(private val context: Context, var options: GoogleMapOptions)
// TODO can crash?
mapView?.onDestroy()
mapView = null
+ map = null
+ created = false
+ initialized = false
+ loaded = false
}
override fun onStart() {
- Log.d(TAG, "unimplemented Method: onStart")
+ mapView?.onStart()
}
override fun onStop() {
- Log.d(TAG, "unimplemented Method: onStop")
+ mapView?.onStop()
}
override fun onEnterAmbient(bundle: Bundle?) {
diff --git a/play-services-maps-core-mapbox/src/main/kotlin/org/microg/gms/maps/mapbox/MapFragment.kt b/play-services-maps-core-mapbox/src/main/kotlin/org/microg/gms/maps/mapbox/MapFragment.kt
index 78636e93a13f68d2342849fd72e8503f906730a2..0ef6c589ac9c715cb93633f335a3c59f6695b901 100644
--- a/play-services-maps-core-mapbox/src/main/kotlin/org/microg/gms/maps/mapbox/MapFragment.kt
+++ b/play-services-maps-core-mapbox/src/main/kotlin/org/microg/gms/maps/mapbox/MapFragment.kt
@@ -35,8 +35,7 @@ class MapFragmentImpl(private val activity: Activity) : IMapFragmentDelegate.Stu
private var map: GoogleMapImpl? = null
private var options: GoogleMapOptions? = null
- override fun onInflate(activity: IObjectWrapper, options: GoogleMapOptions, savedInstanceState: Bundle) {
- Log.d(TAG, "onInflate: ${options.camera.target}")
+ override fun onInflate(activity: IObjectWrapper, options: GoogleMapOptions, savedInstanceState: Bundle?) {
this.options = options
map?.options = options
}
@@ -48,7 +47,6 @@ class MapFragmentImpl(private val activity: Activity) : IMapFragmentDelegate.Stu
if (options == null) {
options = GoogleMapOptions()
}
- Log.d(TAG, "onCreate: ${options?.camera?.target}")
map = GoogleMapImpl(activity, options ?: GoogleMapOptions())
}
@@ -80,7 +78,6 @@ class MapFragmentImpl(private val activity: Activity) : IMapFragmentDelegate.Stu
override fun onDestroyView() {
map?.onDestroy()
- map = null
}
override fun onDestroy() {
diff --git a/play-services-maps-core-mapbox/src/main/kotlin/org/microg/gms/maps/mapbox/model/BitmapDescriptorFactory.kt b/play-services-maps-core-mapbox/src/main/kotlin/org/microg/gms/maps/mapbox/model/BitmapDescriptorFactory.kt
index bf5cf153d54e9a0bc93729eeb7f3a8633bc46700..32f5243438868d90cfbbf2eaebb772ed3d07cf07 100644
--- a/play-services-maps-core-mapbox/src/main/kotlin/org/microg/gms/maps/mapbox/model/BitmapDescriptorFactory.kt
+++ b/play-services-maps-core-mapbox/src/main/kotlin/org/microg/gms/maps/mapbox/model/BitmapDescriptorFactory.kt
@@ -17,23 +17,26 @@
package org.microg.gms.maps.mapbox.model
import android.content.res.Resources
-import android.graphics.Bitmap
-import android.graphics.BitmapFactory
+import android.graphics.*
import android.os.Parcel
import android.util.Log
import com.google.android.gms.dynamic.IObjectWrapper
import com.google.android.gms.dynamic.ObjectWrapper
import com.google.android.gms.maps.model.internal.IBitmapDescriptorFactoryDelegate
import com.mapbox.mapboxsdk.maps.MapboxMap
+import org.microg.gms.maps.mapbox.R
+
object BitmapDescriptorFactoryImpl : IBitmapDescriptorFactoryDelegate.Stub() {
private val TAG = "GmsMapBitmap"
private var resources: Resources? = null
+ private var mapResources: Resources? = null
private val maps = hashSetOf()
private val bitmaps = hashMapOf()
- fun initialize(resources: Resources) {
- BitmapDescriptorFactoryImpl.resources = resources
+ fun initialize(mapResources: Resources?, resources: Resources?) {
+ BitmapDescriptorFactoryImpl.mapResources = mapResources ?: resources
+ BitmapDescriptorFactoryImpl.resources = resources ?: mapResources
}
fun registerMap(map: MapboxMap) {
@@ -56,9 +59,13 @@ object BitmapDescriptorFactoryImpl : IBitmapDescriptorFactoryDelegate.Stub() {
?: floatArrayOf(0f, 0f)
private fun registerBitmap(id: String, bitmapCreator: () -> Bitmap?) {
- val bitmap = synchronized(bitmaps) {
+ val bitmap: Bitmap = synchronized(bitmaps) {
if (bitmaps.contains(id)) return
- val bitmap = bitmapCreator() ?: return
+ val bitmap = bitmapCreator()
+ if (bitmap == null) {
+ Log.w(TAG, "Failed to register bitmap $id, creator returned null")
+ return
+ }
bitmaps[id] = bitmap
bitmap
}
@@ -69,7 +76,17 @@ object BitmapDescriptorFactoryImpl : IBitmapDescriptorFactoryDelegate.Stub() {
override fun fromResource(resourceId: Int): IObjectWrapper? {
val id = "resource-$resourceId"
- registerBitmap(id) { BitmapFactory.decodeResource(resources, resourceId) }
+ registerBitmap(id) {
+ val bitmap = BitmapFactory.decodeResource(resources, resourceId)
+ if (bitmap == null) {
+ try {
+ Log.d(TAG, "Resource $resourceId not found in $resources (${resources?.getResourceName(resourceId)})")
+ } catch (e: Resources.NotFoundException) {
+ Log.d(TAG, "Resource $resourceId not found in $resources")
+ }
+ }
+ bitmap
+ }
return ObjectWrapper.wrap(BitmapDescriptorImpl(id, bitmapSize(id)))
}
@@ -86,15 +103,45 @@ object BitmapDescriptorFactoryImpl : IBitmapDescriptorFactoryDelegate.Stub() {
}
override fun defaultMarker(): IObjectWrapper? {
- Log.d(TAG, "unimplemented Method: defaultMarker")
val id = "marker"
- return ObjectWrapper.wrap(BitmapDescriptorImpl("marker", bitmapSize(id)))
+ registerBitmap(id) { BitmapFactory.decodeResource(mapResources, R.drawable.maps_default_marker) }
+ return ObjectWrapper.wrap(BitmapDescriptorImpl(id, bitmapSize(id)))
+ }
+
+ private fun adjustHue(cm: ColorMatrix, value: Float) {
+ var value = value
+ value = cleanValue(value, 180f) / 180f * Math.PI.toFloat()
+ if (value == 0f) {
+ return
+ }
+ val cosVal = Math.cos(value.toDouble()).toFloat()
+ val sinVal = Math.sin(value.toDouble()).toFloat()
+ val lumR = 0.213f
+ val lumG = 0.715f
+ val lumB = 0.072f
+ val mat = floatArrayOf(lumR + cosVal * (1 - lumR) + sinVal * -lumR, lumG + cosVal * -lumG + sinVal * -lumG, lumB + cosVal * -lumB + sinVal * (1 - lumB), 0f, 0f, lumR + cosVal * -lumR + sinVal * 0.143f, lumG + cosVal * (1 - lumG) + sinVal * 0.140f, lumB + cosVal * -lumB + sinVal * -0.283f, 0f, 0f, lumR + cosVal * -lumR + sinVal * -(1 - lumR), lumG + cosVal * -lumG + sinVal * lumG, lumB + cosVal * (1 - lumB) + sinVal * lumB, 0f, 0f, 0f, 0f, 0f, 1f, 0f, 0f, 0f, 0f, 0f, 1f)
+ cm.postConcat(ColorMatrix(mat))
+ }
+
+ private fun cleanValue(p_val: Float, p_limit: Float): Float {
+ return Math.min(p_limit, Math.max(-p_limit, p_val))
}
override fun defaultMarkerWithHue(hue: Float): IObjectWrapper? {
- val id = "marker"
- Log.d(TAG, "unimplemented Method: defaultMarkerWithHue")
- return ObjectWrapper.wrap(ColorBitmapDescriptorImpl("marker", bitmapSize(id), hue))
+ val id = "marker-${hue.toInt()}"
+ registerBitmap(id) {
+ val bitmap = BitmapFactory.decodeResource(mapResources, R.drawable.maps_default_marker).copy(Bitmap.Config.ARGB_8888, true)
+ val paint = Paint()
+ val matrix = ColorMatrix()
+ val huex = hue % 360f
+ adjustHue(matrix, if (huex > 180f) huex - 360f else huex)
+ paint.setColorFilter(ColorMatrixColorFilter(matrix))
+
+ val canvas = Canvas(bitmap)
+ canvas.drawBitmap(bitmap, 0f, 0f, paint)
+ bitmap
+ }
+ return ObjectWrapper.wrap(ColorBitmapDescriptorImpl(id, bitmapSize(id), hue))
}
override fun fromBitmap(bitmap: Bitmap): IObjectWrapper? {
diff --git a/play-services-maps-core-mapbox/src/main/kotlin/org/microg/gms/maps/mapbox/model/Circle.kt b/play-services-maps-core-mapbox/src/main/kotlin/org/microg/gms/maps/mapbox/model/Circle.kt
index 90c4309ee8fe7cad6ba4d8ca165fb4f858295450..48f465e8ad3ba278639f95dcbaad93f184f02b4f 100644
--- a/play-services-maps-core-mapbox/src/main/kotlin/org/microg/gms/maps/mapbox/model/Circle.kt
+++ b/play-services-maps-core-mapbox/src/main/kotlin/org/microg/gms/maps/mapbox/model/Circle.kt
@@ -116,6 +116,14 @@ class CircleImpl(private val map: GoogleMapImpl, private val id: String, options
override fun hashCodeRemote(): Int = hashCode()
+ override fun hashCode(): Int {
+ return id.hashCode()
+ }
+
+ override fun toString(): String {
+ return id
+ }
+
override fun equals(other: Any?): Boolean {
if (other is CircleImpl) {
return other.id == id
diff --git a/play-services-maps-core-mapbox/src/main/kotlin/org/microg/gms/maps/mapbox/model/Markup.kt b/play-services-maps-core-mapbox/src/main/kotlin/org/microg/gms/maps/mapbox/model/Markup.kt
index f0994173a51e406e41e3e2310691a679557410bb..c737afccd4af5be9ddaf052d55386d300ddc6eb1 100644
--- a/play-services-maps-core-mapbox/src/main/kotlin/org/microg/gms/maps/mapbox/model/Markup.kt
+++ b/play-services-maps-core-mapbox/src/main/kotlin/org/microg/gms/maps/mapbox/model/Markup.kt
@@ -16,6 +16,7 @@
package org.microg.gms.maps.mapbox.model
+import android.util.Log
import com.mapbox.mapboxsdk.plugins.annotation.Annotation
import com.mapbox.mapboxsdk.plugins.annotation.AnnotationManager
import com.mapbox.mapboxsdk.plugins.annotation.Options
@@ -37,4 +38,8 @@ interface Markup, S : Options> {
}
}
}
+
+ companion object {
+ private val TAG = "GmsMapMarkup"
+ }
}
\ No newline at end of file
diff --git a/play-services-maps-core-mapbox/src/main/kotlin/org/microg/gms/maps/mapbox/model/Polygon.kt b/play-services-maps-core-mapbox/src/main/kotlin/org/microg/gms/maps/mapbox/model/Polygon.kt
index 9e5ca9f54f38522e21e14691775ca2bcafa9c252..1790e2b10fa0faed4b740cc16307baf66e5703b9 100644
--- a/play-services-maps-core-mapbox/src/main/kotlin/org/microg/gms/maps/mapbox/model/Polygon.kt
+++ b/play-services-maps-core-mapbox/src/main/kotlin/org/microg/gms/maps/mapbox/model/Polygon.kt
@@ -19,57 +19,93 @@ package org.microg.gms.maps.mapbox.model
import android.os.Parcel
import android.util.Log
import com.google.android.gms.maps.model.LatLng
+import com.google.android.gms.maps.model.PolygonOptions
+import com.google.android.gms.maps.model.PolylineOptions
import com.google.android.gms.maps.model.internal.IPolygonDelegate
+import com.mapbox.mapboxsdk.plugins.annotation.AnnotationManager
import com.mapbox.mapboxsdk.plugins.annotation.Fill
+import com.mapbox.mapboxsdk.plugins.annotation.FillOptions
+import com.mapbox.mapboxsdk.utils.ColorUtils
import org.microg.gms.maps.mapbox.GoogleMapImpl
-import org.microg.gms.maps.mapbox.utils.toGms
import org.microg.gms.maps.mapbox.utils.toMapbox
-class PolygonImpl(private val map: GoogleMapImpl, private val fill: Fill) : IPolygonDelegate.Stub() {
+class PolygonImpl(private val map: GoogleMapImpl, private val id: String, options: PolygonOptions) : IPolygonDelegate.Stub(), Markup {
+ private var points = ArrayList(options.points)
+ private var holes: List> = ArrayList(options.holes.map { ArrayList(it) })
+ private var fillColor = options.fillColor
+ private var strokeColor = options.strokeColor
+ private var strokeWidth = options.strokeWidth
+ private var visible: Boolean = options.isVisible
+
+ private var strokes = (listOf(PolylineImpl(map, "$id-stroke-main", PolylineOptions().color(strokeColor).width(strokeWidth).addAll(points)))
+ + holes.mapIndexed { idx, it -> PolylineImpl(map, "$id-stroke-hole-$idx", PolylineOptions().color(strokeColor).width(strokeWidth).addAll(it)) }).toMutableList()
+
+ override var annotation: Fill? = null
+ override var removed: Boolean = false
+ override val annotationOptions: FillOptions
+ get() = FillOptions()
+ .withLatLngs(mutableListOf(points.map { it.toMapbox() }).plus(holes.map { it.map { it.toMapbox() } }))
+ .withFillColor(ColorUtils.colorToRgbaString(fillColor))
+ .withFillOpacity(if (visible) 1f else 0f)
+
override fun remove() {
- map.fillManager?.delete(fill)
+ removed = true
+ map.fillManager?.let { update(it) }
+ strokes.forEach { it.remove() }
+ }
+
+ override fun update(manager: AnnotationManager<*, Fill, FillOptions, *, *, *>) {
+ super.update(manager)
+ map.lineManager?.let { lineManager -> strokes.forEach { it.update(lineManager) } }
}
- override fun getId(): String = "p" + fill.id.toString()
+ override fun getId(): String = id
override fun setPoints(points: List) {
- fill.latLngs = listOf(points.map { it.toMapbox() })
- map.fillManager?.update(fill)
+ this.points = ArrayList(points)
+ annotation?.latLngs = mutableListOf(points.map { it.toMapbox() }).plus(holes.map { it.map { it.toMapbox() } })
+ map.fillManager?.let { update(it) }
+ strokes[0].points = points
}
- override fun getPoints(): List = fill.latLngs[0]?.map { it.toGms() } ?: emptyList()
+ override fun getPoints(): List = points
override fun setHoles(holes: List?) {
- Log.d(TAG, "unimplemented Method: setHoles")
+ this.holes = if (holes == null) emptyList() else ArrayList(holes.mapNotNull { if (it is List<*>) it.mapNotNull { if (it is LatLng) it else null }.let { if (it.isNotEmpty()) it else null } else null })
+ annotation?.latLngs = mutableListOf(points.map { it.toMapbox() }).plus(this.holes.map { it.map { it.toMapbox() } })
+ while (this.holes.size < strokes.size) {
+ val last = strokes.last()
+ last.remove()
+ strokes.remove(last)
+ }
+ strokes.forEachIndexed { idx, it -> it.points = this.holes[idx] }
+ strokes.addAll(this.holes.subList(strokes.size, this.holes.lastIndex).mapIndexed { idx, it -> PolylineImpl(map, "$id-stroke-hole-${strokes.size + idx}", PolylineOptions().color(strokeColor).width(strokeWidth).addAll(it)) })
+ map.fillManager?.let { update(it) }
}
- override fun getHoles(): List {
- Log.d(TAG, "unimplemented Method: getHoles")
- return emptyList()
- }
+ override fun getHoles(): List = holes
override fun setStrokeWidth(width: Float) {
- Log.d(TAG, "unimplemented Method: setStrokeWidth")
+ this.strokeWidth = width
+ strokes.forEach { it.width = width }
}
- override fun getStrokeWidth(): Float {
- Log.d(TAG, "unimplemented Method: getStrokeWidth")
- return 0f
- }
+ override fun getStrokeWidth(): Float = strokeWidth
override fun setStrokeColor(color: Int) {
- fill.setFillOutlineColor(color)
- map.fillManager?.update(fill)
+ this.strokeColor = color
+ strokes.forEach { it.color = color }
}
- override fun getStrokeColor(): Int = fill.fillOutlineColorAsInt
+ override fun getStrokeColor(): Int = strokeColor
override fun setFillColor(color: Int) {
- fill.setFillColor(color)
- map.fillManager?.update(fill)
+ this.fillColor = color
+ annotation?.setFillColor(color)
+ map.fillManager?.let { update(it) }
}
- override fun getFillColor(): Int = fill.fillColorAsInt
+ override fun getFillColor(): Int = fillColor
override fun setZIndex(zIndex: Float) {
Log.d(TAG, "unimplemented Method: setZIndex")
@@ -81,11 +117,12 @@ class PolygonImpl(private val map: GoogleMapImpl, private val fill: Fill) : IPol
}
override fun setVisible(visible: Boolean) {
- fill.fillOpacity = if (visible) 1f else 0f
- map.fillManager?.update(fill)
+ this.visible = visible
+ annotation?.fillOpacity = if (visible) 1f else 0f
+ map.fillManager?.let { update(it) }
}
- override fun isVisible(): Boolean = fill.fillOpacity != 0f
+ override fun isVisible(): Boolean = visible
override fun setGeodesic(geod: Boolean) {
Log.d(TAG, "unimplemented Method: setGeodesic")
@@ -100,9 +137,17 @@ class PolygonImpl(private val map: GoogleMapImpl, private val fill: Fill) : IPol
override fun hashCodeRemote(): Int = hashCode()
+ override fun hashCode(): Int {
+ return id.hashCode()
+ }
+
+ override fun toString(): String {
+ return id
+ }
+
override fun equals(other: Any?): Boolean {
if (other is PolygonImpl) {
- return other.fill == fill
+ return other.id == id
}
return false
}
diff --git a/play-services-maps-core-mapbox/src/main/kotlin/org/microg/gms/maps/mapbox/model/Polyline.kt b/play-services-maps-core-mapbox/src/main/kotlin/org/microg/gms/maps/mapbox/model/Polyline.kt
index 75ee07368aa1930b164dc1e3cda86d9cbadf43f1..5871b6a7c31f19f7bd7262cdb73198b6bc6a1ccf 100644
--- a/play-services-maps-core-mapbox/src/main/kotlin/org/microg/gms/maps/mapbox/model/Polyline.kt
+++ b/play-services-maps-core-mapbox/src/main/kotlin/org/microg/gms/maps/mapbox/model/Polyline.kt
@@ -21,37 +21,57 @@ import android.util.Log
import com.google.android.gms.maps.model.LatLng
import com.google.android.gms.maps.model.internal.IPolylineDelegate
import com.mapbox.mapboxsdk.plugins.annotation.Line
+import com.mapbox.mapboxsdk.plugins.annotation.LineOptions
+import com.mapbox.mapboxsdk.utils.ColorUtils
import org.microg.gms.maps.mapbox.GoogleMapImpl
-import org.microg.gms.maps.mapbox.utils.toGms
import org.microg.gms.maps.mapbox.utils.toMapbox
+import com.google.android.gms.maps.model.PolylineOptions as GmsLineOptions
+
+class PolylineImpl(private val map: GoogleMapImpl, private val id: String, options: GmsLineOptions) : IPolylineDelegate.Stub(), Markup {
+ private var points = ArrayList(options.points)
+ private var width = options.width
+ private var color = options.color
+ private var visible: Boolean = options.isVisible
+
+ override var annotation: Line? = null
+ override var removed: Boolean = false
+ override val annotationOptions: LineOptions
+ get() = LineOptions()
+ .withLatLngs(points.map { it.toMapbox() })
+ .withLineWidth(width / map.dpiFactor)
+ .withLineColor(ColorUtils.colorToRgbaString(color))
+ .withLineOpacity(if (visible) 1f else 0f)
-class PolylineImpl(private val map: GoogleMapImpl, private val line: Line) : IPolylineDelegate.Stub() {
override fun remove() {
- map.lineManager?.delete(line)
+ removed = true
+ map.lineManager?.let { update(it) }
}
- override fun getId(): String = "l" + line.id.toString()
+ override fun getId(): String = id
override fun setPoints(points: List) {
- line.latLngs = points.map { it.toMapbox() }
- map.lineManager?.update(line)
+ this.points = ArrayList(points)
+ annotation?.latLngs = points.map { it.toMapbox() }
+ map.lineManager?.let { update(it) }
}
- override fun getPoints(): List = line.latLngs.map { it.toGms() }
+ override fun getPoints(): List = points
override fun setWidth(width: Float) {
- line.lineWidth = width / map.dpiFactor
- map.lineManager?.update(line)
+ this.width = width
+ annotation?.lineWidth = width / map.dpiFactor
+ map.lineManager?.let { update(it) }
}
- override fun getWidth(): Float = line.lineWidth * map.dpiFactor
+ override fun getWidth(): Float = width
override fun setColor(color: Int) {
- line.setLineColor(color)
- map.lineManager?.update(line)
+ this.color = color
+ annotation?.setLineColor(color)
+ map.lineManager?.let { update(it) }
}
- override fun getColor(): Int = line.lineColorAsInt
+ override fun getColor(): Int = color
override fun setZIndex(zIndex: Float) {
Log.d(TAG, "unimplemented Method: setZIndex")
@@ -63,11 +83,12 @@ class PolylineImpl(private val map: GoogleMapImpl, private val line: Line) : IPo
}
override fun setVisible(visible: Boolean) {
- line.lineOpacity = if (visible) 1f else 0f
- map.lineManager?.update(line)
+ this.visible = visible
+ annotation?.lineOpacity = if (visible) 1f else 0f
+ map.lineManager?.let { update(it) }
}
- override fun isVisible(): Boolean = line.lineOpacity != 0f
+ override fun isVisible(): Boolean = visible
override fun setGeodesic(geod: Boolean) {
Log.d(TAG, "unimplemented Method: setGeodesic")
@@ -82,9 +103,17 @@ class PolylineImpl(private val map: GoogleMapImpl, private val line: Line) : IPo
override fun hashCodeRemote(): Int = hashCode()
+ override fun hashCode(): Int {
+ return id.hashCode()
+ }
+
+ override fun toString(): String {
+ return id
+ }
+
override fun equals(other: Any?): Boolean {
if (other is PolylineImpl) {
- return other.line == line
+ return other.id == id
}
return false
}
diff --git a/play-services-maps-core-mapbox/src/main/kotlin/org/microg/gms/maps/mapbox/utils/MultiArchLoader.kt b/play-services-maps-core-mapbox/src/main/kotlin/org/microg/gms/maps/mapbox/utils/MultiArchLoader.kt
index bfcda14e0fecb345c38abe004e4340d6695634ea..598860f03268e49be5676b1ae1873ffc778e3bea 100644
--- a/play-services-maps-core-mapbox/src/main/kotlin/org/microg/gms/maps/mapbox/utils/MultiArchLoader.kt
+++ b/play-services-maps-core-mapbox/src/main/kotlin/org/microg/gms/maps/mapbox/utils/MultiArchLoader.kt
@@ -29,7 +29,10 @@ class MultiArchLoader(private val mapContext: Context, private val appContext: C
override fun load(name: String) {
try {
val otherAppInfo = mapContext.packageManager.getApplicationInfo(appContext.packageName, 0)
- val primaryCpuAbi = ApplicationInfo::class.java.getField("primaryCpuAbi").get(otherAppInfo) as String?
+ var primaryCpuAbi = ApplicationInfo::class.java.getField("primaryCpuAbi").get(otherAppInfo) as String?
+ if (primaryCpuAbi == "armeabi") {
+ primaryCpuAbi = "armeabi-v7a"
+ }
if (primaryCpuAbi != null) {
val path = "lib/$primaryCpuAbi/lib$name.so"
val cacheFile = File("${appContext.cacheDir.absolutePath}/.gmscore/$path")
diff --git a/play-services-maps-core-mapbox/src/main/kotlin/org/microg/gms/maps/mapbox/utils/typeConverter.kt b/play-services-maps-core-mapbox/src/main/kotlin/org/microg/gms/maps/mapbox/utils/typeConverter.kt
index 7cb5e5beb3a81a94b82bd86384426d8984defad4..d49cef35e92f68183eea547939b35cd9010e5c0b 100644
--- a/play-services-maps-core-mapbox/src/main/kotlin/org/microg/gms/maps/mapbox/utils/typeConverter.kt
+++ b/play-services-maps-core-mapbox/src/main/kotlin/org/microg/gms/maps/mapbox/utils/typeConverter.kt
@@ -17,30 +17,24 @@
package org.microg.gms.maps.mapbox.utils
import android.os.Bundle
-import android.util.Log
import com.google.android.gms.maps.internal.ICancelableCallback
-import com.google.android.gms.maps.model.CircleOptions
-import com.google.android.gms.maps.model.MarkerOptions
-import com.google.android.gms.maps.model.PolylineOptions
import com.mapbox.mapboxsdk.camera.CameraPosition
import com.mapbox.mapboxsdk.geometry.LatLng
import com.mapbox.mapboxsdk.geometry.LatLngBounds
import com.mapbox.mapboxsdk.geometry.VisibleRegion
import com.mapbox.mapboxsdk.maps.MapboxMap
-import com.mapbox.mapboxsdk.plugins.annotation.LineOptions
-import com.mapbox.mapboxsdk.plugins.annotation.SymbolOptions
-import com.mapbox.mapboxsdk.style.layers.Property.ICON_ANCHOR_TOP_LEFT
-import com.mapbox.mapboxsdk.utils.ColorUtils
-import org.microg.gms.kotlin.unwrap
-import org.microg.gms.maps.mapbox.model.BitmapDescriptorImpl
+import com.google.android.gms.maps.model.CameraPosition as GmsCameraPosition
+import com.google.android.gms.maps.model.LatLng as GmsLatLng
+import com.google.android.gms.maps.model.LatLngBounds as GmsLatLngBounds
+import com.google.android.gms.maps.model.VisibleRegion as GmsVisibleRegion
-fun com.google.android.gms.maps.model.LatLng.toMapbox(): LatLng =
+fun GmsLatLng.toMapbox(): LatLng =
LatLng(latitude, longitude)
-fun com.google.android.gms.maps.model.LatLngBounds.toMapbox(): LatLngBounds =
+fun GmsLatLngBounds.toMapbox(): LatLngBounds =
LatLngBounds.from(this.northeast.latitude, this.northeast.longitude, this.southwest.latitude, this.southwest.longitude)
-fun com.google.android.gms.maps.model.CameraPosition.toMapbox(): CameraPosition =
+fun GmsCameraPosition.toMapbox(): CameraPosition =
CameraPosition.Builder()
.target(target.toMapbox())
.zoom(zoom.toDouble() - 1.0)
@@ -60,23 +54,21 @@ fun Bundle.toMapbox(): Bundle {
for (key in newBundle.keySet()) {
val value = newBundle.get(key)
when (value) {
- is com.google.android.gms.maps.model.CameraPosition -> newBundle.putParcelable(key, value.toMapbox())
- is com.google.android.gms.maps.model.LatLng -> newBundle.putParcelable(key, value.toMapbox())
- is com.google.android.gms.maps.model.LatLngBounds -> newBundle.putParcelable(key, value.toMapbox())
+ is GmsCameraPosition -> newBundle.putParcelable(key, value.toMapbox())
+ is GmsLatLng -> newBundle.putParcelable(key, value.toMapbox())
+ is GmsLatLngBounds -> newBundle.putParcelable(key, value.toMapbox())
is Bundle -> newBundle.putBundle(key, value.toMapbox())
}
}
return newBundle
}
-fun LatLng.toGms(): com.google.android.gms.maps.model.LatLng =
- com.google.android.gms.maps.model.LatLng(latitude, longitude)
+fun LatLng.toGms(): GmsLatLng = GmsLatLng(latitude, longitude)
-fun LatLngBounds.toGms(): com.google.android.gms.maps.model.LatLngBounds =
- com.google.android.gms.maps.model.LatLngBounds(southWest.toGms(), northEast.toGms())
+fun LatLngBounds.toGms(): GmsLatLngBounds = GmsLatLngBounds(southWest.toGms(), northEast.toGms())
-fun CameraPosition.toGms(): com.google.android.gms.maps.model.CameraPosition =
- com.google.android.gms.maps.model.CameraPosition(target.toGms(), zoom.toFloat() + 1.0f, tilt.toFloat(), bearing.toFloat())
+fun CameraPosition.toGms(): GmsCameraPosition =
+ GmsCameraPosition(target.toGms(), zoom.toFloat() + 1.0f, tilt.toFloat(), bearing.toFloat())
fun Bundle.toGms(): Bundle {
val newBundle = Bundle(this)
@@ -92,5 +84,5 @@ fun Bundle.toGms(): Bundle {
return newBundle
}
-fun VisibleRegion.toGms(): com.google.android.gms.maps.model.VisibleRegion =
- com.google.android.gms.maps.model.VisibleRegion(nearLeft.toGms(), nearRight.toGms(), farLeft.toGms(), farRight.toGms(), latLngBounds.toGms())
\ No newline at end of file
+fun VisibleRegion.toGms(): GmsVisibleRegion =
+ GmsVisibleRegion(nearLeft.toGms(), nearRight.toGms(), farLeft.toGms(), farRight.toGms(), latLngBounds.toGms())
\ No newline at end of file
diff --git a/play-services-maps-core-mapbox/src/main/res/drawable-hdpi/maps_default_marker.png b/play-services-maps-core-mapbox/src/main/res/drawable-hdpi/maps_default_marker.png
new file mode 100644
index 0000000000000000000000000000000000000000..94c365a3e33b5785ca8d104fbda71a7181b40f38
Binary files /dev/null and b/play-services-maps-core-mapbox/src/main/res/drawable-hdpi/maps_default_marker.png differ
diff --git a/play-services-maps-core-mapbox/src/main/res/drawable-ldpi/maps_default_marker.png b/play-services-maps-core-mapbox/src/main/res/drawable-ldpi/maps_default_marker.png
new file mode 100644
index 0000000000000000000000000000000000000000..a8ca2bf63446acebf3ecfca236b6d528a39424c6
Binary files /dev/null and b/play-services-maps-core-mapbox/src/main/res/drawable-ldpi/maps_default_marker.png differ
diff --git a/play-services-maps-core-mapbox/src/main/res/drawable-mdpi/maps_default_marker.png b/play-services-maps-core-mapbox/src/main/res/drawable-mdpi/maps_default_marker.png
new file mode 100644
index 0000000000000000000000000000000000000000..c79736e70791d059a56c5c9f476cfd2e3cda28ae
Binary files /dev/null and b/play-services-maps-core-mapbox/src/main/res/drawable-mdpi/maps_default_marker.png differ
diff --git a/play-services-maps-core-mapbox/src/main/res/drawable-xhdpi/maps_default_marker.png b/play-services-maps-core-mapbox/src/main/res/drawable-xhdpi/maps_default_marker.png
new file mode 100644
index 0000000000000000000000000000000000000000..0b1b1975b41e8acce97fbddd3fe1cb8700477d08
Binary files /dev/null and b/play-services-maps-core-mapbox/src/main/res/drawable-xhdpi/maps_default_marker.png differ
diff --git a/play-services-maps-core-mapbox/src/main/res/drawable-xxhdpi/maps_default_marker.png b/play-services-maps-core-mapbox/src/main/res/drawable-xxhdpi/maps_default_marker.png
new file mode 100644
index 0000000000000000000000000000000000000000..709bf78d7b41a36aa12ef7db0a4eedb8bbfae25d
Binary files /dev/null and b/play-services-maps-core-mapbox/src/main/res/drawable-xxhdpi/maps_default_marker.png differ
diff --git a/play-services-maps-core-mapbox/src/main/res/drawable-xxxhdpi/maps_default_marker.png b/play-services-maps-core-mapbox/src/main/res/drawable-xxxhdpi/maps_default_marker.png
new file mode 100644
index 0000000000000000000000000000000000000000..0de5d255aea9781fa48f3c13b5c3c5b661b35064
Binary files /dev/null and b/play-services-maps-core-mapbox/src/main/res/drawable-xxxhdpi/maps_default_marker.png differ
diff --git a/proguard.flags b/proguard.flags
index 6be46b9c23bd114ef38c3236ce452dc8e9a5c3a7..1b6700d51373bec144826bc30d75c4b30639b1be 100644
--- a/proguard.flags
+++ b/proguard.flags
@@ -1,9 +1,5 @@
-# We use ProGuard for optimizations, obfuscation is for those who have sth to hide
--dontobfuscate
--optimizations !code/allocation/variable
-
# We're referencing stuff that is unknown to the system
--libraryjar ../unifiednlp-compat/build/classes/java/main
+#-libraryjar ../unifiednlp-compat/build/classes/java/main
-dontwarn java.awt.**
-dontwarn javax.annotation.**
@@ -15,6 +11,7 @@
-dontwarn com.caverock.androidsvg.**
-dontwarn org.slf4j.**
-dontwarn org.codehaus.jackson.**
+-dontwarn com.android.location.provider.**
# Disable ProGuard Notes, they won't help here
-dontnote
@@ -33,6 +30,15 @@
@org.microg.safeparcel.SafeParceled *;
}
+# Keep form data
+-keepclassmembers class * {
+ @org.microg.gms.common.HttpFormClient$* *;
+}
+
+# Keep our stuff
+-keep class org.microg.** { *; }
+-keep class com.google.android.gms.** { *; }
+
# Keep asInterface method cause it's accessed from SafeParcel
-keepattributes InnerClasses
-keepclassmembers interface * extends android.os.IInterface {