From 5d6e9ac01c979efe28d7846afa56c412aa49b051 Mon Sep 17 00:00:00 2001 From: Marvin W Date: Wed, 3 Jul 2019 11:14:28 +0200 Subject: [PATCH 01/24] Make mapbox the default and vtm the variant --- play-services-core/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/play-services-core/build.gradle b/play-services-core/build.gradle index ed54aa5fb..3077b28cb 100644 --- a/play-services-core/build.gradle +++ b/play-services-core/build.gradle @@ -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 { -- GitLab From 8a0010a1d8beec67d05c01fb739e306c96e81d1c Mon Sep 17 00:00:00 2001 From: Marvin W Date: Wed, 3 Jul 2019 11:24:34 +0200 Subject: [PATCH 02/24] Fix incomplete certificate requests causing crashes --- .../android/gms/common/GoogleCertificatesImpl.java | 11 ++++++++++- .../main/java/org/microg/gms/common/PackageUtils.java | 11 ++++++++++- 2 files changed, 20 insertions(+), 2 deletions(-) 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 bb9c6df2f..06a8a7cce 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/org/microg/gms/common/PackageUtils.java b/play-services-core/src/main/java/org/microg/gms/common/PackageUtils.java index 8660dcdbe..d698f0035 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 @@ -69,6 +69,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 +107,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); -- GitLab From dfb1e7fbb7d6225353cd31b94558a2bce5a2f5a2 Mon Sep 17 00:00:00 2001 From: Marvin W Date: Thu, 4 Jul 2019 23:53:04 +0200 Subject: [PATCH 03/24] Fix mapbox native library loading if app targets armeabi non-v7a --- .../main/kotlin/org/microg/gms/maps/mapbox/MapFragment.kt | 4 +--- .../org/microg/gms/maps/mapbox/utils/MultiArchLoader.kt | 5 ++++- 2 files changed, 5 insertions(+), 4 deletions(-) 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 78636e93a..8cb70a55e 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()) } 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 bfcda14e0..598860f03 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") -- GitLab From 06c8b765ba6862857b77b5866d17f4e69fa955ac Mon Sep 17 00:00:00 2001 From: Marvin W Date: Fri, 5 Jul 2019 00:47:12 +0200 Subject: [PATCH 04/24] Update Conscrypt to 2.1.0, activate the default cipher suite in cross-arch loader --- play-services-core/build.gradle | 2 +- .../security/ProviderInstallerImpl.java | 48 ++++++++++++++++++- 2 files changed, 47 insertions(+), 3 deletions(-) diff --git a/play-services-core/build.gradle b/play-services-core/build.gradle index 3077b28cb..2598b5331 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" 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 fa72252da..4817dea1d 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 @@ -35,8 +35,8 @@ import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.security.Security; 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; @@ -86,13 +86,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) { -- GitLab From 0d9bb345a897aca9dbfd5d79d83efd4e78eb8a70 Mon Sep 17 00:00:00 2001 From: Niklas Sombert Date: Wed, 11 Sep 2019 20:51:24 +0200 Subject: [PATCH 05/24] Make requestLocationSettingsDialog return success --- .../microg/gms/location/GoogleLocationManagerServiceImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 97b035705..c66c0be43 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 -- GitLab From d2735650af8b93e048cc798e13452ca9b3fd130c Mon Sep 17 00:00:00 2001 From: AsavarTzeth Date: Fri, 23 Aug 2019 18:14:38 +0200 Subject: [PATCH 06/24] Exclude com.bankid.bus from provider installer MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The addition of the ProviderInstallerImpl broke com.bankid.bus (BankID säkerhetsapp). This app is essential to Swedish users since it is effectively the de facto Swedish online id. This issue is resolved by adding the app id to the existing black list. Fixes #824 --- .../android/gms/common/security/ProviderInstallerImpl.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) 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 4817dea1d..6d702279f 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,6 +34,7 @@ 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.List; import java.util.Set; @@ -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()); -- GitLab From ee8e5427c4feb1dcd9c5a36e9df1a9181b3e9017 Mon Sep 17 00:00:00 2001 From: Marvin W Date: Tue, 15 Oct 2019 14:54:05 +0200 Subject: [PATCH 07/24] Update build system and deps --- .travis.yml | 2 +- build.gradle | 6 +++--- extern/GmsApi | 2 +- extern/GmsLib | 2 +- gradle.properties | 1 - gradle/wrapper/gradle-wrapper.properties | 2 +- proguard.flags | 2 +- 7 files changed, 8 insertions(+), 9 deletions(-) delete mode 100644 gradle.properties diff --git a/.travis.yml b/.travis.yml index 822e0de02..87ad538a6 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 76056a023..b6ffdcde0 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 51509859a..2a43448e4 160000 --- a/extern/GmsApi +++ b/extern/GmsApi @@ -1 +1 @@ -Subproject commit 51509859ae51097ad5789ba4ca2e9ffb9658f80e +Subproject commit 2a43448e49dc0aec0d6c53c8a27dd58245fdaba6 diff --git a/extern/GmsLib b/extern/GmsLib index 39d20ec1f..15cd4491b 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 dfbe47874..000000000 --- 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 7919ae6e6..d757f3d33 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/proguard.flags b/proguard.flags index 6be46b9c2..bc1febc58 100644 --- a/proguard.flags +++ b/proguard.flags @@ -3,7 +3,7 @@ -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.** -- GitLab From 6ba9bbb03bd8bc2dc7c944dd0252cb82e178fac1 Mon Sep 17 00:00:00 2001 From: Marvin W Date: Tue, 15 Oct 2019 14:56:24 +0200 Subject: [PATCH 08/24] Add dummy TapAndPay service --- .../src/main/AndroidManifest.xml | 36 +++++--- .../microg/gms/tapandpay/TapAndPayImpl.java | 33 +++++++ .../gms/tapandpay/TapAndPayService.java | 38 +++++++++ .../gms/wearable/CapabilityManager.java | 85 +++++++++++++++++++ 4 files changed, 181 insertions(+), 11 deletions(-) create mode 100644 play-services-core/src/main/java/org/microg/gms/tapandpay/TapAndPayImpl.java create mode 100644 play-services-core/src/main/java/org/microg/gms/tapandpay/TapAndPayService.java create mode 100644 play-services-core/src/main/java/org/microg/gms/wearable/CapabilityManager.java diff --git a/play-services-core/src/main/AndroidManifest.xml b/play-services-core/src/main/AndroidManifest.xml index 535180fe6..d851521e0 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/org/microg/gms/tapandpay/TapAndPayImpl.java b/play-services-core/src/main/java/org/microg/gms/tapandpay/TapAndPayImpl.java new file mode 100644 index 000000000..406326503 --- /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 000000000..082234e64 --- /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 000000000..0c8f59ffc --- /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; + } +} -- GitLab From 3c5e68404b92d6732082a8c42351809f93dad2be Mon Sep 17 00:00:00 2001 From: Marvin W Date: Tue, 15 Oct 2019 14:58:07 +0200 Subject: [PATCH 09/24] Improvements to Wear code for emulator --- .../gms/common/RemoteListenerProxy.java | 15 +- .../org/microg/gms/wearable/WearableImpl.java | 213 +++++++++--------- .../gms/wearable/WearableServiceImpl.java | 56 ++++- 3 files changed, 160 insertions(+), 124 deletions(-) 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 1e2fa5ead..46ebca3b9 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/wearable/WearableImpl.java b/play-services-core/src/main/java/org/microg/gms/wearable/WearableImpl.java index 852438921..0406005de 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 ef830d3b4..e091ba729 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); } -- GitLab From fc3e24c0ea008d6dd9ca6619b6bb61986b45edf7 Mon Sep 17 00:00:00 2001 From: Marvin W Date: Tue, 15 Oct 2019 14:59:34 +0200 Subject: [PATCH 10/24] Various improvements and fixes for MapBox maps implementation --- .../gms/maps/internal/CreatorImpl.java | 4 +- .../maps/mapbox/CameraBoundsWithSizeUpdate.kt | 8 +- .../gms/maps/mapbox/CameraUpdateFactory.kt | 7 +- .../org/microg/gms/maps/mapbox/GoogleMap.kt | 195 ++++++++++++------ .../org/microg/gms/maps/mapbox/MapFragment.kt | 1 - .../mapbox/model/BitmapDescriptorFactory.kt | 71 +++++-- .../microg/gms/maps/mapbox/model/Circle.kt | 8 + .../microg/gms/maps/mapbox/model/Markup.kt | 5 + .../microg/gms/maps/mapbox/model/Polygon.kt | 99 ++++++--- .../microg/gms/maps/mapbox/model/Polyline.kt | 63 ++++-- .../gms/maps/mapbox/utils/typeConverter.kt | 40 ++-- .../res/drawable-hdpi/maps_default_marker.png | Bin 0 -> 1974 bytes .../res/drawable-ldpi/maps_default_marker.png | Bin 0 -> 946 bytes .../res/drawable-mdpi/maps_default_marker.png | Bin 0 -> 1277 bytes .../drawable-xhdpi/maps_default_marker.png | Bin 0 -> 2745 bytes .../drawable-xxhdpi/maps_default_marker.png | Bin 0 -> 4277 bytes .../drawable-xxxhdpi/maps_default_marker.png | Bin 0 -> 5890 bytes 17 files changed, 351 insertions(+), 150 deletions(-) create mode 100644 play-services-maps-core-mapbox/src/main/res/drawable-hdpi/maps_default_marker.png create mode 100644 play-services-maps-core-mapbox/src/main/res/drawable-ldpi/maps_default_marker.png create mode 100644 play-services-maps-core-mapbox/src/main/res/drawable-mdpi/maps_default_marker.png create mode 100644 play-services-maps-core-mapbox/src/main/res/drawable-xhdpi/maps_default_marker.png create mode 100644 play-services-maps-core-mapbox/src/main/res/drawable-xxhdpi/maps_default_marker.png create mode 100644 play-services-maps-core-mapbox/src/main/res/drawable-xxxhdpi/maps_default_marker.png 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 df0fb3e98..96a3c191b 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 654feca6b..eea4304f5 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 03e92de20..150afb4bc 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 f809b4f4a..b31472cb4 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 8cb70a55e..0ef6c589a 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 @@ -78,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 bf5cf153d..32f524343 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 90c4309ee..48f465e8a 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 f0994173a..c737afccd 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 9e5ca9f54..1790e2b10 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 75ee07368..5871b6a7c 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/typeConverter.kt b/play-services-maps-core-mapbox/src/main/kotlin/org/microg/gms/maps/mapbox/utils/typeConverter.kt index 7cb5e5beb..d49cef35e 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 GIT binary patch literal 1974 zcmeAS@N?(olHy`uVBq!ia0y~yU{GOTV6fp}V_;z5Yn8}jU|?V=cJd72;Nak>;YjIV zU|`@Z@Q5sCU|_ESVaBV^kG^MMV2~_vjVKAuPb(=;EJ|f4FE7{2%*!rLPAo{(%P&fw z{mw>;fq~uF)5S3)qw(m>%AAnvqQ~}s-gYxLSy*~cVpCJObdI>CXLNz^5);o>uMRFx zDRn;HEkarsR{73$X*F4uu_`P!AV_tEhcA;B>t&r&m&_(OHAv_OOio~CWV?NXsXzDF zX`T0H&%BhMDY>V|_I+i~Z_mXW-&;SwbN^2D^LxeT1$eq<1~cd!xDc>z|If=u8{e&q z;pw+vU?{siVam+AiL2Jw@wYE#ZkXJ0$L-N%KMuwNNpJU`)!y^|N`3I}JzE=ouX|qD zF?EI`Yf$Dpo8>_J zs~0S&aj)zCx^ek8?Q-4!(t@!w#RQDKC1fIA{`>k(_ti=N>;sA?1x~Q&IZobR^!(wI z^lks;JU#y_Eo#V9NZXdF>+8R(+-CpO-@nDwn2h3*UfuETdmjI1ZcNn1*&Q~8jWcd8 zle64%^6zZ%I-d3FxoU}v=0>eqw{w4N9T8Bql<8SBH>>8<-%H=3*_avL zd_5z3XX9JVtj99HbtKfm{J>)JDO%-K3-vVMJBZ@ERXY! z7%r_XTo;s`8^_2XWPD!o&(rhonfw19I~u%y)x(Pa3RZjT3_efqbva?Cy~5AeZI|aY z`5wiJ`|I}i&-~8CAeNCH{kiu*N!4GA3vZp;kCzLxG0eF5^y}kO}1g z=d&-r7D!64khpTUQHtwe{*&3yzusV-BoexQuS3HU?WNq^9Ge#0Zxopv?@+Yqw1c>Z z`B5LC$ zPP0|l#ZEig;>7$x<#b+fYUyqU&s|Ds&ttB<x@dD*7%ADOeK zd%_YvPKV_&A!T|6KOY6{JtrjiZf7o^*QA^s25(xuuQD*K+|*+IChUy)>-coRlSfmZ zGnRO|JmLLPBKzg<=ez6?mu1|VQf7#xNJKoD>@}%fH~ZRE;fdi4425ym40rB%mGWrf za`mN2Hwz85ze@=C*>}8H_4VV|-wG!WZ{~I0WRp@`^S4gvRUZ>$Lrlo7`@hy+Wlxhn zvFX)A<|46O+CJ5>;3AP9cpJ>&e+WAh?+dF`XhhJ=J?r}5}R&S zO|IMYHdV<=`1Q{voqK0Y{JC!JyWjP!iB;j9H!N~i*ZwLswEn&Jq>dV^(jvjrtJ?o7 zO%JUx3by!k>D2!Sxv1~2elRubEiee#o&0(8`Uy8}CK&YIy!8CWr_JG=FYbh-6~0eO z@;k>qEj0VpSpgQ z1v6Z&j?Ue*{{9wrmtV$zIye-w-?r6CY-dzsadBaM`uhHg>0Dks=`2NsH#v*Xp4#sp z7Cc8RAR_l$uYC>kq9y;6)V%C&x1G&r%DDb|k#t8#gq~itzvg8L_FD%lf5o4fAI8AIz~JfX=d#Wzp$P!B-L3Ng literal 0 HcmV?d00001 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 GIT binary patch literal 946 zcmeAS@N?(olHy`uVBq!ia0y~yU=U(pV36ZrV_;xV;YjIV zU|`@Z@Q5sCU|`+{!i>$n&cO@}43Z_T5hcO-X(i=}MX3zs<>h*rdD+Fui3O>8`9-tcWxUUX*2W>1YT?tj5BQ6)sCeU36Tf z6@#1>ZDa2gP*M`)l-tv(Ffkze(hcE|j|Oo^g0`BxEs?sKdG=b_w0n;om))9K?EdrK zx$=FVt)JJQ|100*uxG2Kb;0Jm&^0fe1^L->7#tR#jkC<(bb3ott!!#)t#6F;VFtVT zXX{_xc=+M9c(!17pI|Oi{E>?uI)?fNhh9}aI&1c_?y{^8zdo2=VK3k-=$jTG zKd-X(Q1DT^T8#-67xKk@>$tzFSL*Jq6$m}qT(?{04wHu-V}lP%Bd@>?7q#N)942Sy zOnc%hTEXCumOWkNxn=C4lT52Qm%a?^xoX^V(fG{P=zttkZbzN+uI?SzU%$AuVb4VO zL&7a9_jgES`|qzw-{w+QJ-hDSA?^Rnj0}I9j!r+3SN=aw@SN{m>FL+|x14`;saN{{ zowA?TjFh-M7#v&}FZb0}E1tgZ?lW)({M2~AZ0grl$M-6vdd}=q-_~9F)a8ow_qM+iT&`H}+V#xBgDWdY zg==YO*jx!NPbS8Oy1<*tscsK-b^C%0KJTjYJo;FrZjqzQs*P#a1C!P$XZCF@dwuTi z@eYr_+8hi#H-FBbawxJ~xHin_yP0K?UH7#Nv$Y$GUPpRdda&EkYUlBQy-(+a#R(tz z^!fhj$wg9+l4HyKm`|U|{go~txYFz58TOAGgCdIJzvQ~9y!&WjecH=uZtCWyJ8#c< zPn{Y($;imYKq6YzQ_3MN?UF9v)U-^7lA}kDiWp1$5j^JPx7;|@?rP_Z(@%qLO?$VW zk-_)+J52@=hQz>#FHHQlYZ)01zjy0nc+u__{GUnnlE92R%AQdS3=9mOu6{1-oD!M< D9b%+_ literal 0 HcmV?d00001 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 GIT binary patch literal 1277 zcmeAS@N?(olHy`uVBq!ia0y~yV31&7V9?-TV_;x-!fO@Ez`(##?Bp53!NI{%!;#X# zz`(#+;1OBOz`*hkgcEamT(YbbdwvSAx$npQr&z(7UpsZYzTlC;5r}!M_P>S%AnVw&Ma_{s1zwdV%7eC{3RJVAp_P=2N-SVx=9Au?#tnl-TVrZD@ zllLtps6Qs+Pxq7!`?@>Swn{8v{bqJ$nooG>9_bga&pHJ3@~upJvv9_oPvIe+H~GEl z0!0OVTTLGyrbFO>2o@9?(Gjh zS!v&Xjy)PJJ4$n(`R}(;OMRCSm2`le{jyxmmwQVe-1wV%FughQvDMo2{rU@CqSYA; z9_+U*pZn|4?Wua$9BS6)e2x`t+CY-*4xhpHuNGW5HfickRN2TkX3hvVUN`x^tuZsxG;H@z*Jw zhLes>KC{zhk;#cG7blABy?VdEx8bwE>_e7$JJh}`2{_&sJk!c>W0-a$v&6@rri{sU z_Dl=Ur1Rc+7r}PvoC1ST>l-x&hDHvZlI=4Y1=7!CTw7~=bVbHFRd?+KtC}>UUgN~Q zYkkivXkX(A?vTzDVSTeH>dO*=N#5&j##JX&A%{PO6k6y(IUTZ1S%za(D|J>{~96UESrlq`ISDxtc?aS+q?$;?UPXhV& zmGQCMPk!;Wd7{7Nk6)Hbp9~lRiuhy9Qr@nM)ZI5{>+^I~_4QIe>UWpzHn+U5xp&d7 zIhopxo3~!md)+VIeIjWm>zR^Z28HgY(?0%vtgc{i{?p4d$u>cCMPmC7FfdG+{#k44 z^iSH;Plp$AX-#Q*#QJOL{giW)=j4lBU#09U+0UHb>3?_2zmQlL7iR8b;_5;d8(zNH znD1~#+H!8qvF)eM>$J6-FfbgRHz!Lo`S(_jpGD8kv8CSs_iDnug>0QCvj04IJXz)R z;l!70KkGt%wlD9Ad9+?hpWX^ZXXj{TRAt5qu^ZbxxEg#;SgwsvY&&t1huuPKG0xk)dFH`Q*)89?Y^bO^sGC znfd-m=(V@%t~=K*zrL1%LE*IRrEhPZsUEhD&uG)R&#BIz?ciebtKep(!L0Y&dTIjM z`R1xG+TgzAgD8W*2U literal 0 HcmV?d00001 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 GIT binary patch literal 2745 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 Z5`PN0b9ppQFfcGMc)I$ztaD0e0sueC0-68- literal 0 HcmV?d00001 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 GIT binary patch literal 4277 zcmeAS@N?(olHy`uVBq!ia0y~yVDMmIV5sC^V_;yIbvoUjfq{Xg*vT`5gM)*kh9jke zfq{Xuz$3Dlfr0NQ2s65?2VG-eV2~_vjVKAuPb(=;EJ|f4FE7{2%*!rLPAo{(%P&fw z{mw>;fkD8?)5S5QV$RdKl?7KrryaNdzJ0GP<002m^BKri%Px;+cmN1 zZJ_&Hz1B+?uf@&S=C=CwyjOb5vsbNNmX$SU+P2%NQ?`i~IG8zJo924WL145{7BKrc zFtZ4-E6v>B>rnfwSa63z%Y?F*I&0QBc)euoY7jh7aA2ZU`8iqJ4cF(}RNB~A?yFkB z(>}*Y%(TO8E`x=PV4_9Rp{IQ-oZI3GQ z?p&nVq0@cg&Zrt2)8nxYA81;H=Q{+}UGSO3*^<+EpuwSmWU zG~(jtzP|VSe);|XC&CZdJt$UmS!KSd%5}n&OYAy6SLbMF{P|eyExi1c`Zu?}s~5Ps z|Ihh-`TG9_KiESV>xG<5zJ|EHg0)AJ6Dr znig{L?WVi60bZ7T5dwd1uCko?RbHPl^QXe)6p!b3ShH*N_ihr5&~LH0HP`9xriPxU zIvF*UPh~giZ@YI-Tz4~v;Ln`DNs_%*MgM+2ck+@HcbfBN)r3n|nP=wxIrreT{oJp- zYR`=p-8TQ9`{AnmT`rw7d!m=Wn6khpf9sB?=KFV9Zu+)3f98_pYl1g7loftnUvJ2} zBiifc%Y<#tO-7IBv|cjVl|Jywg)xdVoHc|Kfl#`!W1L<8JB)s>iV4$oV+j8D^1$y zhRKGP>gVgZcSL$w?%11tOJK^(igWyX|K5Kr^z?Y%rl^xS%5`r%A~U|$Ph;4gcJHs& zmUPFZE2ll!a6$gwpYFm_v5H^LtD;?-kQ9v_EoHW$J-lb=Aq&e3{zr${!MK%ioHAK zS^e+pGmWG^-dLNkO))vp|8)Mn8Gg4Cv9vzt`8LaMtIKN@cGaF<+j97C z!^XAuV?6^rPrtvfHF07=-`%d($(rZflR~z*Slkp^rY5x5GV#~1>gf|E2IRfid-bsg zyL7{ulu)miEN(}))rO@_H~Ki`NkB07a;LL==`{yEakk@npr8}=S=6lSwe(pVQozBZGTR0~i2=~=}vyNZLuPjfsbfZP-MhkYS z=owR9rxw}kui8*{Z1Nf_Q^nBe$AN6Tnhbnf|LG_n%C^_oRK=*HsVdF^Wr(Nme9wMKrXWBzZ}FXe zyX#12@=phQ))Ss#^SA13D_y0UG&MuZ>Do!Zu=!snE1sCi)qW=|wB#Dg@jDyeaD}iv2SjWJ&u|t(bb;*{RGnXzkGp6?o^ja}E zGqSAg3;+6?iM4SbjnOb3@6N+q+VXwNtxI)CE~Hf= zKIFm1K836HJNPn!8q`v6bXcv{`jn|<{_Bi<8gHqk#H%eiB~4aEPgIRqVvW@9-dVh6 z^}I!E=JU5F&D$K-l5ngc=JJ!R?6sH9K5wjIU2(OmtNGB|mD^VttzTAjdjaDz)2%Zr zcm9yQwv-!G4w@}nAh{y2fnh=jJO9c}Yupl+oIdzw&mFtTCQIk{b6Q?=TRP>Svp+NE zgGG}(@7u4RK1FW(mav4HzIJQ&=U-RtTET@2wA;s`JC>3 zwH#~iyBc45`rw~n^NyAC*H?3Ya0+-)`f={VpFNuo+}s|#ute|A?!yN(e^|MHToM)_ z67u)o<&y_m1H)E72oYVzd*b2xqP-z)heFyGnH&>t5%LULQajB*Sn_3&!Li4O(l2K0 zv|UkGKQ$~whDA%kd4j+qN3Tjp{n`7pf1YfgCVYi!`>KFPp93E4u2Z^u?26=WkN2M0 z4Xc$`x7+aBZWE8)p2zsSs(qRJ-S74J@&y~duGZ$XTJ_}T?5~d|?fsTrR_n08@KD~- z_xw!9qxSFinINFVCiCUr-^>5I7u}MVIBzDR`m*jxXYZ2lvt#4#?%1~f?&{w85*Lp3 z-cMa$cC$S$=vQl?m8C;f@V(R+*MPMD&+G1A*1opz<+ZgP@%b0NbbNm~^>yQ4r;gQ5 z```B7D9bdT5@P-QOni2K+0FLidrkdY4;7j^%$|0+O+nE`dh;=sH|@>ieDk`+vIgvS!JBUHju;bjB@D#UmTP$-T@8 z+Hy~0cG%OXlJnJKE2o$45WD+%onfgP>xO-c)2&oA9>1#$3PEtpe!{wL4eWed~MlHENqqwt36#%M(6-TK%8-&FMYK?Jv&l zI{f_90>#jG?(=K78@C2JL@O+L{_yzypf=vsEZfSzmP}_!-4?vQSohbr!o@ki+=NZe zX!T?o+m-76JQsNBw$bi6h9%igy*LUvZ_N6=`1&=iO6L6=WA_^w{4aUOA0Nw}BkC0M zCT!+AE^((f$DdlgjQ;p2zjf8DGPAZ=fv#B}YXASd|FB?=h|`<*c{}H=tF6oOnOk~n zhUIr@^HXMN=YQYWky<9YVWIldDwlw?b=y>*FAbFr{r@2Ez3q9kkovmNbKI-Vm}j>N zoVC@w{rGCJ;*oHTs@Cr_pWhQ(l@;l8Ux&lhx8ncDpWBTWKRs-#d;fOEy|$9z+2wc5 zO^?s{S^vuSa+d3Q4k0I&#uxRKIb(lUTC&XH>+|rR|6Zy`d-%IlU)d6M@pZ)p zfky(f!k*T?y16}Y%IkdAAVJOZkMGyB`>qyos=1nNSR0buoP6z%@vkGZw|x!ldugC{ zf6vXr*G-oXq}NWotlng_aN=Ie^Xq@P?6}KYJ26$Q<@V(V)&GvaZn*2zVfR#K#>AqH z-XDLT-z|3kcO&N}pT_Kym%dN6sn^}GeEp_hJ^^WVn@@gz5&ZkA;Nq&g*UmOs)jSbA zf7oA!#cXDw)I3d3Yo`va1$TBoVt>!+yIDnXOLWzWtTVsgbiZdj-YPIP?SzRjYw6@b ztDjB(u5bTxQu7<@u`M&Ddpd)&8g$c6n)EI>W0AZ)|0%zD%Hc%r<-0HbKEplR!}?iV zZ{@A#o1SNWPq}l)`&{Mr@*T&rMdxh4`*GtX`}aa0(v6?a@(MVnS@*E^*Uq_KdG+3( z<<_@c%6I7fzEZTh;cc2+FxRtafdh#qZ}()MyksAxuse3gyVz}PzPlZMU5E}&v~ryJ zIe7c->Gnk~vQ~TUMogX=(8go^Fz(lZz)P!JmZhJF+%!??^3i$UZ2mlv%D()o<%`{y z8&V6jjIS8ThP^Yn`D(^*^XFTXUMFQ$1%8Y>{--sa;q_{0vLqFlE6R{pgpK zA3DD-`=#V~>hFQ%`Ak!tI=Gje%w;c=S-I)>47<%?(zf3kBAK=}J^Cy8dZUf-xuT{P zf%L|#@3p6WyH8n(-`_21q298>%sb6}!}9>S8*d{Do@W|6xt@Bk@aekN@^Hr8z86-% z{`F>sN^xEBfx_Rhwew!?7Q3^xvt&_uYJ6%bds(Ewfw=R`{PICI_u}*$xwbFAxA)CL z<(SExS*mYTUa)lCTjW3MlWRV!L~8K%#hJPeJ3FgNxo&fu(m5+vrvLw5UtDXai0R9H z|1Zv6BD^=3+xTXtBLn-^MUT{Sue^|JZ`gVpEid98MsyqJ*=e95=%>~!g=H61sX5mzPbig&YBr(>4sd7+kEN^Dex~Wf%;*Wky6nAv9zQ2>fR)p(nJ9pP@ zozxbt<5SJe&CMr#v%kKJskfwft4!J4+NTTN_CI8LaeaNf^TE00{3cS;k8Um9)fjYn zvF_y4X6$*o1lF7TuG$t_V^yl5UI_>V3txc!@z1Vs^PTDm4+M38& z%Pbj%I$bJWUt4=SuHs?qHPZzW1#cfk&De5zn@E}9lFQffw|vWBN;osa@Ybf((|;IN zhp*=g2?^N}<8=@CZP+P8idcu;mC%4_KHPf3O>S_IU9#4>JrgvA;V+FxY&H>sY``)d)+N0OB oo-^a^(x}<9)*jjN=s$zX)3^xv#1A_e7#J8lUHx3vIVCg!0K)7_r2qf` literal 0 HcmV?d00001 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 GIT binary patch literal 5890 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 WQNvru+ocQ)3=E#GelF{r5}E)%=w_7w literal 0 HcmV?d00001 -- GitLab From 6c27c2474e699bdad1e9a110a04158ba148d6edc Mon Sep 17 00:00:00 2001 From: Marvin W Date: Wed, 16 Oct 2019 01:29:20 +0200 Subject: [PATCH 11/24] Ensure form data is not optimized by proguard --- .../org/microg/gms/auth/login/LoginActivity.java | 14 ++++++++++++-- proguard.flags | 5 +++++ 2 files changed, 17 insertions(+), 2 deletions(-) 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 d37a99c63..7a7bfacf5 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 @@ -308,7 +308,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 +344,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; } }); } diff --git a/proguard.flags b/proguard.flags index bc1febc58..6127c42ee 100644 --- a/proguard.flags +++ b/proguard.flags @@ -33,6 +33,11 @@ @org.microg.safeparcel.SafeParceled *; } +# Keep form data +-keepclassmembers class * { + @org.microg.gms.common.HttpFormClient$* *; +} + # Keep asInterface method cause it's accessed from SafeParcel -keepattributes InnerClasses -keepclassmembers interface * extends android.os.IInterface { -- GitLab From 855b4c6d4ec7ecd95483f873f0cdadeed38f77e8 Mon Sep 17 00:00:00 2001 From: Marvin W Date: Tue, 22 Oct 2019 11:39:43 +0200 Subject: [PATCH 12/24] Bump version code --- play-services-core/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/play-services-core/build.gradle b/play-services-core/build.gradle index 2598b5331..0aef5a42d 100644 --- a/play-services-core/build.gradle +++ b/play-services-core/build.gradle @@ -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")) -- GitLab From b0724f1243b9383fa361acb5891122b6a36d5967 Mon Sep 17 00:00:00 2001 From: Marvin W Date: Wed, 23 Oct 2019 01:38:37 +0200 Subject: [PATCH 13/24] Invalidate auth tokens as needed This seems to fix issues with Google Maps stopping to connect to internet after adding an Account. --- .../main/java/org/microg/gms/auth/AuthManagerServiceImpl.java | 2 ++ 1 file changed, 2 insertions(+) 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 1f5c26a79..0e6faf89e 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; } -- GitLab From 9d0bb9670b562c4a02a236ceab97d2098750ad06 Mon Sep 17 00:00:00 2001 From: Marvin W Date: Wed, 23 Oct 2019 11:16:00 +0200 Subject: [PATCH 14/24] Allow access to Google contact data based on READ_CONTACTS permission --- .../main/java/org/microg/gms/people/PeopleServiceImpl.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) 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 9d9af368c..a2f100158 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; -- GitLab From cb5fe5560642cd5093e790c5e30f393a3d5012a3 Mon Sep 17 00:00:00 2001 From: Marvin W Date: Wed, 23 Oct 2019 11:16:18 +0200 Subject: [PATCH 15/24] Add Hangouts Meet to known google packages --- .../src/main/java/org/microg/gms/common/PackageUtils.java | 1 + 1 file changed, 1 insertion(+) 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 d698f0035..a2b65de19 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) { -- GitLab From 2c5c30bdde71f51f97ac9872de8299c7df2a9a7e Mon Sep 17 00:00:00 2001 From: Marvin W Date: Wed, 23 Oct 2019 15:18:03 +0200 Subject: [PATCH 16/24] Add additional sync permissions --- play-services-core/src/main/AndroidManifest.xml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/play-services-core/src/main/AndroidManifest.xml b/play-services-core/src/main/AndroidManifest.xml index d851521e0..823085688 100644 --- a/play-services-core/src/main/AndroidManifest.xml +++ b/play-services-core/src/main/AndroidManifest.xml @@ -78,6 +78,9 @@ + + + -- GitLab From 0b5525007f9b1eac10811e5eee2a260790681fc2 Mon Sep 17 00:00:00 2001 From: Romain Hunault Date: Mon, 3 Jun 2019 11:20:20 +0200 Subject: [PATCH 17/24] Build mapbox --- .gitlab-ci.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 3e12b08d2..5fc65bcb3 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -27,6 +27,7 @@ build: - echo sdk.dir $ANDROID_HOME > local.properties - export TERM=dumb - export JAVA_OPTS="-XX:+CMSClassUnloadingEnabled -XX:+HeapDumpOnOutOfMemoryError -Xmx2048m" + - echo mapbox.enabled true >> local.properties - ./gradlew build only: - tags -- GitLab From cfc90b45bdff16393930185c78be5360d6073794 Mon Sep 17 00:00:00 2001 From: Marvin W Date: Fri, 25 Oct 2019 20:46:31 +0200 Subject: [PATCH 18/24] Ensure ProGuard does not "optimize" away our code --- proguard.flags | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/proguard.flags b/proguard.flags index 6127c42ee..1b6700d51 100644 --- a/proguard.flags +++ b/proguard.flags @@ -1,7 +1,3 @@ -# 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 -dontwarn java.awt.** @@ -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 @@ -38,6 +35,10 @@ @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 { -- GitLab From 3cae1179d07e4ffa7aa6967016ed348ce61c3598 Mon Sep 17 00:00:00 2001 From: Romain Hunault Date: Mon, 28 Oct 2019 12:03:01 +0100 Subject: [PATCH 19/24] Fix build process --- .gitlab-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 5fc65bcb3..fa3e0835f 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -28,7 +28,7 @@ build: - export TERM=dumb - export JAVA_OPTS="-XX:+CMSClassUnloadingEnabled -XX:+HeapDumpOnOutOfMemoryError -Xmx2048m" - echo mapbox.enabled true >> local.properties - - ./gradlew build + - ./gradlew assemble only: - tags artifacts: -- GitLab From 93e070b7f9e6d36eaacb0bce87ae0ca8cb8a875a Mon Sep 17 00:00:00 2001 From: Romain Hunault Date: Wed, 30 Oct 2019 10:16:10 +0100 Subject: [PATCH 20/24] Revert "Build mapbox" This reverts commit 0b5525007f9b1eac10811e5eee2a260790681fc2. --- .gitlab-ci.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index fa3e0835f..edfb9a300 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -27,7 +27,6 @@ build: - echo sdk.dir $ANDROID_HOME > local.properties - export TERM=dumb - export JAVA_OPTS="-XX:+CMSClassUnloadingEnabled -XX:+HeapDumpOnOutOfMemoryError -Xmx2048m" - - echo mapbox.enabled true >> local.properties - ./gradlew assemble only: - tags -- GitLab From 74049927a92706d323b8aedebafde9227e4ff70f Mon Sep 17 00:00:00 2001 From: Romain Hunault Date: Mon, 4 Nov 2019 17:09:01 +0000 Subject: [PATCH 21/24] Always build --- .gitlab-ci.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index edfb9a300..ea086073a 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -28,8 +28,6 @@ build: - export TERM=dumb - export JAVA_OPTS="-XX:+CMSClassUnloadingEnabled -XX:+HeapDumpOnOutOfMemoryError -Xmx2048m" - ./gradlew assemble - only: - - tags artifacts: paths: - play-services-core/build/outputs/apk/ -- GitLab From d89632ca8eecdb68cd5a5fda2f162a48bcae9a5b Mon Sep 17 00:00:00 2001 From: Romain Hunault Date: Mon, 25 Nov 2019 17:02:15 +0000 Subject: [PATCH 22/24] Enable mapbox --- .gitlab-ci.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index ea086073a..3ea467079 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -25,6 +25,8 @@ 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 assemble -- GitLab From cdbe42fd5b4485448c58c14b603266692639f2cd Mon Sep 17 00:00:00 2001 From: Alexandru Chircu Date: Fri, 29 Nov 2019 16:03:57 +0000 Subject: [PATCH 23/24] Resolve "Push Notifications don't work" --- .../src/main/java/org/microg/gms/auth/login/LoginActivity.java | 2 ++ 1 file changed, 2 insertions(+) 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 7a7bfacf5..a538c55ff 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; @@ -357,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); -- GitLab From 0069eecff0e2aff598a58617435639295ad52a1b Mon Sep 17 00:00:00 2001 From: Alexandru Chircu Date: Fri, 29 Nov 2019 16:04:10 +0000 Subject: [PATCH 24/24] Return v1 for maps module --- .../android/gms/chimera/container/DynamiteLoaderImpl.java | 4 ++++ 1 file changed, 4 insertions(+) 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 43bd5cafe..a841984c7 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; } -- GitLab