From fd8ce71a836c8bf8ac9786d6ce0f58807a4a23c5 Mon Sep 17 00:00:00 2001 From: Marvin W Date: Tue, 18 Jan 2022 18:49:35 +0100 Subject: [PATCH] Add initial UI for new features --- LICENSES/CC0-1.0.txt | 121 ++++++++++++++++++ .../src/main/res/drawable/ic_radio.xml | 16 +++ .../main/res/drawable/ic_radio_checked.xml | 16 +++ .../main/res/drawable/ic_radio_unchecked.xml | 16 +++ play-services-core/build.gradle | 9 +- .../gms/ui/SafetyNetAdvancedFragment.java | 108 ++++++++-------- .../gms/ui/SafetyNetAdvancedFragment.kt | 12 ++ .../org/microg/gms/ui/SafetyNetFragment.kt | 21 ++- .../gms/ui/SafetyNetPreferencesFragment.kt | 105 +++++++++++++++ .../src/main/res/drawable/ic_circle_check.xml | 16 +++ .../src/main/res/drawable/ic_circle_error.xml | 17 +++ .../main/res/drawable/ic_circle_pending.xml | 19 +++ .../src/main/res/drawable/ic_circle_warn.xml | 16 +++ .../layout/safety_net_advanced_fragment.xml | 17 +++ .../src/main/res/values-be/strings.xml | 18 +-- .../src/main/res/values-de/strings.xml | 18 +-- .../src/main/res/values-es/strings.xml | 18 +-- .../src/main/res/values-fr/strings.xml | 17 +-- .../src/main/res/values-it/strings.xml | 18 +-- .../src/main/res/values-ja/strings.xml | 18 +-- .../src/main/res/values-pl/strings.xml | 16 +-- .../src/main/res/values-ru/strings.xml | 18 +-- .../src/main/res/values-uk/strings.xml | 16 +-- .../src/main/res/values-zh-rTW/strings.xml | 13 +- .../src/main/res/values/strings.xml | 42 ++---- .../xml/preferences_device_registration.xml | 16 ++- .../src/main/res/xml/preferences_gcm.xml | 32 ----- .../xml/preferences_push_notifications.xml | 2 +- .../main/res/xml/preferences_safetynet.xml | 29 +++-- .../res/xml/preferences_snet_advanced.xml | 33 ++--- .../gms/ui/NearbyPreferencesIntegration.kt | 3 +- play-services-droidguard-core-ui/build.gradle | 53 ++++++++ .../src/main/AndroidManifest.xml | 11 ++ .../core/ui/ContainedEditTextPreference.kt | 69 ++++++++++ .../core/ui/DroidGuardPreferencesFragment.kt | 53 ++++++++ .../res/layout/preference_edit_widget.xml | 20 +++ .../preference_material_with_widget_below.xml | 75 +++++++++++ .../src/main/res/values/strings.xml | 12 ++ .../main/res/xml/preferences_droidguard.xml | 15 +++ settings.gradle | 4 + 40 files changed, 838 insertions(+), 310 deletions(-) create mode 100644 LICENSES/CC0-1.0.txt create mode 100644 play-services-base-core-ui/src/main/res/drawable/ic_radio.xml create mode 100644 play-services-base-core-ui/src/main/res/drawable/ic_radio_checked.xml create mode 100644 play-services-base-core-ui/src/main/res/drawable/ic_radio_unchecked.xml create mode 100644 play-services-core/src/main/kotlin/org/microg/gms/ui/SafetyNetAdvancedFragment.kt create mode 100644 play-services-core/src/main/res/drawable/ic_circle_check.xml create mode 100644 play-services-core/src/main/res/drawable/ic_circle_error.xml create mode 100644 play-services-core/src/main/res/drawable/ic_circle_pending.xml create mode 100644 play-services-core/src/main/res/drawable/ic_circle_warn.xml create mode 100644 play-services-core/src/main/res/layout/safety_net_advanced_fragment.xml delete mode 100644 play-services-core/src/main/res/xml/preferences_gcm.xml create mode 100644 play-services-droidguard-core-ui/build.gradle create mode 100644 play-services-droidguard-core-ui/src/main/AndroidManifest.xml create mode 100644 play-services-droidguard-core-ui/src/main/kotlin/org/microg/gms/droidguard/core/ui/ContainedEditTextPreference.kt create mode 100644 play-services-droidguard-core-ui/src/main/kotlin/org/microg/gms/droidguard/core/ui/DroidGuardPreferencesFragment.kt create mode 100644 play-services-droidguard-core-ui/src/main/res/layout/preference_edit_widget.xml create mode 100644 play-services-droidguard-core-ui/src/main/res/layout/preference_material_with_widget_below.xml create mode 100644 play-services-droidguard-core-ui/src/main/res/values/strings.xml create mode 100644 play-services-droidguard-core-ui/src/main/res/xml/preferences_droidguard.xml diff --git a/LICENSES/CC0-1.0.txt b/LICENSES/CC0-1.0.txt new file mode 100644 index 00000000..0e259d42 --- /dev/null +++ b/LICENSES/CC0-1.0.txt @@ -0,0 +1,121 @@ +Creative Commons Legal Code + +CC0 1.0 Universal + + CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE + LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN + ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS + INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES + REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS + PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM + THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED + HEREUNDER. + +Statement of Purpose + +The laws of most jurisdictions throughout the world automatically confer +exclusive Copyright and Related Rights (defined below) upon the creator +and subsequent owner(s) (each and all, an "owner") of an original work of +authorship and/or a database (each, a "Work"). + +Certain owners wish to permanently relinquish those rights to a Work for +the purpose of contributing to a commons of creative, cultural and +scientific works ("Commons") that the public can reliably and without fear +of later claims of infringement build upon, modify, incorporate in other +works, reuse and redistribute as freely as possible in any form whatsoever +and for any purposes, including without limitation commercial purposes. +These owners may contribute to the Commons to promote the ideal of a free +culture and the further production of creative, cultural and scientific +works, or to gain reputation or greater distribution for their Work in +part through the use and efforts of others. + +For these and/or other purposes and motivations, and without any +expectation of additional consideration or compensation, the person +associating CC0 with a Work (the "Affirmer"), to the extent that he or she +is an owner of Copyright and Related Rights in the Work, voluntarily +elects to apply CC0 to the Work and publicly distribute the Work under its +terms, with knowledge of his or her Copyright and Related Rights in the +Work and the meaning and intended legal effect of CC0 on those rights. + +1. Copyright and Related Rights. A Work made available under CC0 may be +protected by copyright and related or neighboring rights ("Copyright and +Related Rights"). Copyright and Related Rights include, but are not +limited to, the following: + + i. the right to reproduce, adapt, distribute, perform, display, + communicate, and translate a Work; + ii. moral rights retained by the original author(s) and/or performer(s); +iii. publicity and privacy rights pertaining to a person's image or + likeness depicted in a Work; + iv. rights protecting against unfair competition in regards to a Work, + subject to the limitations in paragraph 4(a), below; + v. rights protecting the extraction, dissemination, use and reuse of data + in a Work; + vi. database rights (such as those arising under Directive 96/9/EC of the + European Parliament and of the Council of 11 March 1996 on the legal + protection of databases, and under any national implementation + thereof, including any amended or successor version of such + directive); and +vii. other similar, equivalent or corresponding rights throughout the + world based on applicable law or treaty, and any national + implementations thereof. + +2. Waiver. To the greatest extent permitted by, but not in contravention +of, applicable law, Affirmer hereby overtly, fully, permanently, +irrevocably and unconditionally waives, abandons, and surrenders all of +Affirmer's Copyright and Related Rights and associated claims and causes +of action, whether now known or unknown (including existing as well as +future claims and causes of action), in the Work (i) in all territories +worldwide, (ii) for the maximum duration provided by applicable law or +treaty (including future time extensions), (iii) in any current or future +medium and for any number of copies, and (iv) for any purpose whatsoever, +including without limitation commercial, advertising or promotional +purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each +member of the public at large and to the detriment of Affirmer's heirs and +successors, fully intending that such Waiver shall not be subject to +revocation, rescission, cancellation, termination, or any other legal or +equitable action to disrupt the quiet enjoyment of the Work by the public +as contemplated by Affirmer's express Statement of Purpose. + +3. Public License Fallback. Should any part of the Waiver for any reason +be judged legally invalid or ineffective under applicable law, then the +Waiver shall be preserved to the maximum extent permitted taking into +account Affirmer's express Statement of Purpose. In addition, to the +extent the Waiver is so judged Affirmer hereby grants to each affected +person a royalty-free, non transferable, non sublicensable, non exclusive, +irrevocable and unconditional license to exercise Affirmer's Copyright and +Related Rights in the Work (i) in all territories worldwide, (ii) for the +maximum duration provided by applicable law or treaty (including future +time extensions), (iii) in any current or future medium and for any number +of copies, and (iv) for any purpose whatsoever, including without +limitation commercial, advertising or promotional purposes (the +"License"). The License shall be deemed effective as of the date CC0 was +applied by Affirmer to the Work. Should any part of the License for any +reason be judged legally invalid or ineffective under applicable law, such +partial invalidity or ineffectiveness shall not invalidate the remainder +of the License, and in such case Affirmer hereby affirms that he or she +will not (i) exercise any of his or her remaining Copyright and Related +Rights in the Work or (ii) assert any associated claims and causes of +action with respect to the Work, in either case contrary to Affirmer's +express Statement of Purpose. + +4. Limitations and Disclaimers. + + a. No trademark or patent rights held by Affirmer are waived, abandoned, + surrendered, licensed or otherwise affected by this document. + b. Affirmer offers the Work as-is and makes no representations or + warranties of any kind concerning the Work, express, implied, + statutory or otherwise, including without limitation warranties of + title, merchantability, fitness for a particular purpose, non + infringement, or the absence of latent or other defects, accuracy, or + the present or absence of errors, whether or not discoverable, all to + the greatest extent permissible under applicable law. + c. Affirmer disclaims responsibility for clearing rights of other persons + that may apply to the Work or any use thereof, including without + limitation any person's Copyright and Related Rights in the Work. + Further, Affirmer disclaims responsibility for obtaining any necessary + consents, permissions or other rights required for any use of the + Work. + d. Affirmer understands and acknowledges that Creative Commons is not a + party to this document and has no duty or obligation with respect to + this CC0 or use of the Work. diff --git a/play-services-base-core-ui/src/main/res/drawable/ic_radio.xml b/play-services-base-core-ui/src/main/res/drawable/ic_radio.xml new file mode 100644 index 00000000..689b57ad --- /dev/null +++ b/play-services-base-core-ui/src/main/res/drawable/ic_radio.xml @@ -0,0 +1,16 @@ + + + + + + + diff --git a/play-services-base-core-ui/src/main/res/drawable/ic_radio_checked.xml b/play-services-base-core-ui/src/main/res/drawable/ic_radio_checked.xml new file mode 100644 index 00000000..8aad3213 --- /dev/null +++ b/play-services-base-core-ui/src/main/res/drawable/ic_radio_checked.xml @@ -0,0 +1,16 @@ + + + + + diff --git a/play-services-base-core-ui/src/main/res/drawable/ic_radio_unchecked.xml b/play-services-base-core-ui/src/main/res/drawable/ic_radio_unchecked.xml new file mode 100644 index 00000000..2b79fb0f --- /dev/null +++ b/play-services-base-core-ui/src/main/res/drawable/ic_radio_unchecked.xml @@ -0,0 +1,16 @@ + + + + + diff --git a/play-services-core/build.gradle b/play-services-core/build.gradle index 1209c603..05d07ce5 100644 --- a/play-services-core/build.gradle +++ b/play-services-core/build.gradle @@ -44,11 +44,12 @@ dependencies { implementation project(':play-services-base-core-ui') implementation project(':play-services-conscrypt-provider-core') implementation project(':play-services-cronet-core') - implementation project(':play-services-droidguard') // TODO: Move to play-services-safetynet-core once we have it implementation project(':play-services-droidguard-core') + implementation project(':play-services-droidguard-core-ui') implementation project(':play-services-location-core') withNearbyImplementation project(':play-services-nearby-core') withNearbyImplementation project(':play-services-nearby-core-ui') + implementation project(':play-services-safetynet-core') implementation project(':play-services-tapandpay-core') implementation project(':play-services-vision-core') @@ -58,7 +59,11 @@ dependencies { implementation project(':play-services-cast-api') implementation project(':play-services-wearable') implementation "org.microg:wearable:$wearableVersion" - implementation "org.microg.gms:remote-droid-guard:$remoteDroidGuardVersion" + + runtimeOnly "org.microg.nlp:geocode-v1:$nlpVersion" + runtimeOnly "org.microg.nlp:location-v2:$nlpVersion" + runtimeOnly "org.microg.nlp:location-v3:$nlpVersion" + implementation "org.microg.nlp:ui:$nlpVersion" withMapboxImplementation project(':play-services-maps-core-mapbox') withVtmImplementation project(':play-services-maps-core-vtm') diff --git a/play-services-core/src/main/java/org/microg/gms/ui/SafetyNetAdvancedFragment.java b/play-services-core/src/main/java/org/microg/gms/ui/SafetyNetAdvancedFragment.java index 97111a3b..906c1c8e 100644 --- a/play-services-core/src/main/java/org/microg/gms/ui/SafetyNetAdvancedFragment.java +++ b/play-services-core/src/main/java/org/microg/gms/ui/SafetyNetAdvancedFragment.java @@ -28,58 +28,58 @@ import org.microg.tools.ui.AbstractSettingsActivity; import org.microg.tools.ui.RadioButtonPreference; import org.microg.tools.ui.ResourceSettingsFragment; -import static org.microg.gms.safetynet.SafetyNetPrefs.PREF_SNET_OFFICIAL; -import static org.microg.gms.safetynet.SafetyNetPrefs.PREF_SNET_SELF_SIGNED; -import static org.microg.gms.safetynet.SafetyNetPrefs.PREF_SNET_THIRD_PARTY; +//import static org.microg.gms.safetynet.SafetyNetPrefs.PREF_SNET_OFFICIAL; +//import static org.microg.gms.safetynet.SafetyNetPrefs.PREF_SNET_SELF_SIGNED; +//import static org.microg.gms.safetynet.SafetyNetPrefs.PREF_SNET_THIRD_PARTY; -public class SafetyNetAdvancedFragment extends ResourceSettingsFragment { - - public SafetyNetAdvancedFragment() { - preferencesResource = R.xml.preferences_snet_advanced; - } - - private RadioButtonPreference radioOfficial; - private RadioButtonPreference radioSelfSigned; - private RadioButtonPreference radioThirdParty; - - @Override - public void onCreatePreferences(@Nullable Bundle savedInstanceState, String rootKey) { - super.onCreatePreferences(savedInstanceState, rootKey); - - radioOfficial = (RadioButtonPreference) findPreference(PREF_SNET_OFFICIAL); - radioSelfSigned = (RadioButtonPreference) findPreference(PREF_SNET_SELF_SIGNED); - radioThirdParty = (RadioButtonPreference) findPreference(PREF_SNET_THIRD_PARTY); - } - - @Override - public boolean onPreferenceTreeClick(Preference preference) { - if (preference == radioOfficial) { - radioOfficial.setChecked(true); - radioSelfSigned.setChecked(false); - radioThirdParty.setChecked(false); - return true; - } else if (preference == radioSelfSigned) { - radioOfficial.setChecked(false); - radioSelfSigned.setChecked(true); - radioThirdParty.setChecked(false); - return true; - } else if (preference == radioThirdParty) { - radioOfficial.setChecked(false); - radioSelfSigned.setChecked(false); - radioThirdParty.setChecked(true); - return true; - } - return super.onPreferenceTreeClick(preference); - } - - public static class AsActivity extends AbstractSettingsActivity { - public AsActivity() { - showHomeAsUp = true; - } - - @Override - protected Fragment getFragment() { - return new SafetyNetAdvancedFragment(); - } - } -} +//public class SafetyNetAdvancedFragment extends ResourceSettingsFragment { +// +// public SafetyNetAdvancedFragment() { +// preferencesResource = R.xml.preferences_snet_advanced; +// } +// +// private RadioButtonPreference radioOfficial; +// private RadioButtonPreference radioSelfSigned; +// private RadioButtonPreference radioThirdParty; +// +// @Override +// public void onCreatePreferences(@Nullable Bundle savedInstanceState, String rootKey) { +// super.onCreatePreferences(savedInstanceState, rootKey); +// +// radioOfficial = (RadioButtonPreference) findPreference(PREF_SNET_OFFICIAL); +// radioSelfSigned = (RadioButtonPreference) findPreference(PREF_SNET_SELF_SIGNED); +// radioThirdParty = (RadioButtonPreference) findPreference(PREF_SNET_THIRD_PARTY); +// } +// +// @Override +// public boolean onPreferenceTreeClick(Preference preference) { +// if (preference == radioOfficial) { +// radioOfficial.setChecked(true); +// radioSelfSigned.setChecked(false); +// radioThirdParty.setChecked(false); +// return true; +// } else if (preference == radioSelfSigned) { +// radioOfficial.setChecked(false); +// radioSelfSigned.setChecked(true); +// radioThirdParty.setChecked(false); +// return true; +// } else if (preference == radioThirdParty) { +// radioOfficial.setChecked(false); +// radioSelfSigned.setChecked(false); +// radioThirdParty.setChecked(true); +// return true; +// } +// return super.onPreferenceTreeClick(preference); +// } +// +// public static class AsActivity extends AbstractSettingsActivity { +// public AsActivity() { +// showHomeAsUp = true; +// } +// +// @Override +// protected Fragment getFragment() { +// return new SafetyNetAdvancedFragment(); +// } +// } +//} diff --git a/play-services-core/src/main/kotlin/org/microg/gms/ui/SafetyNetAdvancedFragment.kt b/play-services-core/src/main/kotlin/org/microg/gms/ui/SafetyNetAdvancedFragment.kt new file mode 100644 index 00000000..668a6314 --- /dev/null +++ b/play-services-core/src/main/kotlin/org/microg/gms/ui/SafetyNetAdvancedFragment.kt @@ -0,0 +1,12 @@ +/* + * SPDX-FileCopyrightText: 2021 microG Project Team + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.microg.gms.ui + +import androidx.fragment.app.Fragment +import com.google.android.gms.R + +class SafetyNetAdvancedFragment : Fragment(R.layout.safety_net_advanced_fragment) { +} diff --git a/play-services-core/src/main/kotlin/org/microg/gms/ui/SafetyNetFragment.kt b/play-services-core/src/main/kotlin/org/microg/gms/ui/SafetyNetFragment.kt index bae598e8..88656d7c 100644 --- a/play-services-core/src/main/kotlin/org/microg/gms/ui/SafetyNetFragment.kt +++ b/play-services-core/src/main/kotlin/org/microg/gms/ui/SafetyNetFragment.kt @@ -12,10 +12,9 @@ import androidx.lifecycle.lifecycleScope import androidx.navigation.fragment.findNavController import com.google.android.gms.R import com.google.android.gms.databinding.SafetyNetFragmentBinding -import org.microg.gms.checkin.getCheckinServiceInfo -import org.microg.gms.safetynet.ServiceInfo -import org.microg.gms.safetynet.getSafetyNetServiceInfo -import org.microg.gms.safetynet.setSafetyNetServiceConfiguration +import org.microg.gms.checkin.CheckinPrefs +import org.microg.gms.droidguard.core.DroidGuardPreferences +import org.microg.gms.safetynet.SafetyNetPreferences class SafetyNetFragment : Fragment(R.layout.safety_net_fragment) { @@ -34,22 +33,22 @@ class SafetyNetFragment : Fragment(R.layout.safety_net_fragment) { fun setEnabled(newStatus: Boolean) { val appContext = requireContext().applicationContext lifecycleScope.launchWhenResumed { - val info = getSafetyNetServiceInfo(appContext) - val newConfiguration = info.configuration.copy(enabled = newStatus) - displayServiceInfo(setSafetyNetServiceConfiguration(appContext, newConfiguration)) + SafetyNetPreferences.setEnabled(appContext, newStatus) + DroidGuardPreferences.setEnabled(appContext, newStatus) + displayServiceInfo() } } - fun displayServiceInfo(serviceInfo: ServiceInfo) { - binding.safetynetEnabled = serviceInfo.configuration.enabled + fun displayServiceInfo() { + binding.safetynetEnabled = SafetyNetPreferences.isEnabled(requireContext()) && DroidGuardPreferences.isEnabled(requireContext()) } override fun onResume() { super.onResume() val appContext = requireContext().applicationContext lifecycleScope.launchWhenResumed { - binding.checkinEnabled = getCheckinServiceInfo(appContext).configuration.enabled - displayServiceInfo(getSafetyNetServiceInfo(appContext)) + binding.checkinEnabled = CheckinPrefs.isEnabled(appContext) + displayServiceInfo() } } diff --git a/play-services-core/src/main/kotlin/org/microg/gms/ui/SafetyNetPreferencesFragment.kt b/play-services-core/src/main/kotlin/org/microg/gms/ui/SafetyNetPreferencesFragment.kt index 2a4b4ab2..0643ce06 100644 --- a/play-services-core/src/main/kotlin/org/microg/gms/ui/SafetyNetPreferencesFragment.kt +++ b/play-services-core/src/main/kotlin/org/microg/gms/ui/SafetyNetPreferencesFragment.kt @@ -6,12 +6,117 @@ package org.microg.gms.ui import android.os.Bundle +import android.os.Handler +import android.os.Looper +import android.util.Base64 +import android.util.Log +import androidx.lifecycle.lifecycleScope +import androidx.preference.Preference import androidx.preference.PreferenceFragmentCompat import com.google.android.gms.R +import com.google.android.gms.common.api.Status +import com.google.android.gms.safetynet.AttestationData +import com.google.android.gms.safetynet.RecaptchaResultData +import com.google.android.gms.safetynet.internal.ISafetyNetCallbacks +import org.json.JSONException +import org.json.JSONObject +import org.microg.gms.safetynet.SafetyNetClientService +import org.microg.gms.safetynet.SafetyNetClientServiceImpl +import kotlin.random.Random class SafetyNetPreferencesFragment : PreferenceFragmentCompat() { + private lateinit var runAttest: Preference + private lateinit var runReCaptcha: Preference override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) { addPreferencesFromResource(R.xml.preferences_safetynet) } + + override fun onBindPreferences() { + runAttest = preferenceScreen.findPreference("pref_snet_run_attest") ?: runAttest + runReCaptcha = preferenceScreen.findPreference("pref_recaptcha_run_test") ?: runReCaptcha + + // TODO: Use SafetyNet client library once ready + runAttest.setOnPreferenceClickListener { + val context = context ?: return@setOnPreferenceClickListener false + runAttest.setIcon(R.drawable.ic_circle_pending) + runAttest.setSummary(R.string.pref_test_summary_running) + val handler = Handler(Looper.myLooper()!!) + SafetyNetClientServiceImpl(context, "com.scottyab.safetynet.sample", lifecycle).attestWithApiKey(object : ISafetyNetCallbacks.Default() { + override fun onAttestationData(status: Status?, attestationData: AttestationData?) { + handler.post { + if (status?.isSuccess == true) { + if (attestationData?.jwsResult == null) { + runAttest.setIcon(R.drawable.ic_circle_warn) + runAttest.summary = context.getString(R.string.pref_test_summary_failed, "No result") + } else { + val (_, payload, _) = try { + attestationData.jwsResult.split(".") + } catch (e: Exception) { + runAttest.setIcon(R.drawable.ic_circle_error) + runAttest.summary = context.getString(R.string.pref_test_summary_failed, "Invalid JWS") + return@post + } + val (basicIntegrity, ctsProfileMatch, advice) = try { + JSONObject(Base64.decode(payload, Base64.URL_SAFE).decodeToString()).let { + Triple(it.optBoolean("basicIntegrity", false), it.optBoolean("ctsProfileMatch", false), it.optString("advice", "")) + } + } catch (e: Exception) { + Log.w(TAG, e) + runAttest.setIcon(R.drawable.ic_circle_error) + runAttest.summary = context.getString(R.string.pref_test_summary_failed, "Invalid JSON") + return@post + } + val adviceText = if (advice == "") "" else "\n" + advice.split(",").map { + when (it) { + "LOCK_BOOTLOADER" -> "Bootloader is not locked" + "RESTORE_TO_FACTORY_ROM" -> "ROM is not clean" + else -> it + } + }.joinToString("\n") + when { + basicIntegrity && ctsProfileMatch -> { + runAttest.setIcon(R.drawable.ic_circle_check) + runAttest.setSummary(R.string.pref_test_summary_passed) + } + basicIntegrity -> { + runAttest.setIcon(R.drawable.ic_circle_warn) + runAttest.summary = context.getString(R.string.pref_test_summary_warn, "CTS profile does not match$adviceText") + } + else -> { + runAttest.setIcon(R.drawable.ic_circle_error) + runAttest.summary = context.getString(R.string.pref_test_summary_failed, "integrity check failed$adviceText") + } + } + } + } else { + runAttest.setIcon(R.drawable.ic_circle_error) + runAttest.summary = context.getString(R.string.pref_test_summary_failed, status?.statusMessage) + } + } + } + }, Random.nextBytes(32), "AIzaSyAfcNLBpWkqrt50mluU6GswUmtysmLn9cY") + true + } + runReCaptcha.setOnPreferenceClickListener { + val context = context ?: return@setOnPreferenceClickListener false + runReCaptcha.setIcon(R.drawable.ic_circle_pending) + runReCaptcha.setSummary(R.string.pref_test_summary_running) + val handler = Handler(Looper.myLooper()!!) + SafetyNetClientServiceImpl(context, "com.blogspot.android_er.recaptcha", lifecycle).verifyWithRecaptcha(object : ISafetyNetCallbacks.Default() { + override fun onRecaptchaResult(status: Status?, recaptchaResultData: RecaptchaResultData?) { + handler.post { + if (status?.isSuccess == true) { + runReCaptcha.setIcon(R.drawable.ic_circle_check) + runReCaptcha.setSummary(R.string.pref_test_summary_passed) + } else { + runReCaptcha.setIcon(R.drawable.ic_circle_error) + runReCaptcha.summary = context.getString(R.string.pref_test_summary_failed, status?.statusMessage) + } + } + } + }, "6LdMKyUUAAAAAN0ndw7byI03_qpbpjxKY-mTQnLw") + true + } + } } diff --git a/play-services-core/src/main/res/drawable/ic_circle_check.xml b/play-services-core/src/main/res/drawable/ic_circle_check.xml new file mode 100644 index 00000000..748f055a --- /dev/null +++ b/play-services-core/src/main/res/drawable/ic_circle_check.xml @@ -0,0 +1,16 @@ + + + + + diff --git a/play-services-core/src/main/res/drawable/ic_circle_error.xml b/play-services-core/src/main/res/drawable/ic_circle_error.xml new file mode 100644 index 00000000..30e18f04 --- /dev/null +++ b/play-services-core/src/main/res/drawable/ic_circle_error.xml @@ -0,0 +1,17 @@ + + + + + + diff --git a/play-services-core/src/main/res/drawable/ic_circle_pending.xml b/play-services-core/src/main/res/drawable/ic_circle_pending.xml new file mode 100644 index 00000000..9d2c37e7 --- /dev/null +++ b/play-services-core/src/main/res/drawable/ic_circle_pending.xml @@ -0,0 +1,19 @@ + + + + + + diff --git a/play-services-core/src/main/res/drawable/ic_circle_warn.xml b/play-services-core/src/main/res/drawable/ic_circle_warn.xml new file mode 100644 index 00000000..842fc461 --- /dev/null +++ b/play-services-core/src/main/res/drawable/ic_circle_warn.xml @@ -0,0 +1,16 @@ + + + + + diff --git a/play-services-core/src/main/res/layout/safety_net_advanced_fragment.xml b/play-services-core/src/main/res/layout/safety_net_advanced_fragment.xml new file mode 100644 index 00000000..2e72a670 --- /dev/null +++ b/play-services-core/src/main/res/layout/safety_net_advanced_fragment.xml @@ -0,0 +1,17 @@ + + + + + + diff --git a/play-services-core/src/main/res/values-be/strings.xml b/play-services-core/src/main/res/values-be/strings.xml index 8cd7f17c..fa3f09f4 100644 --- a/play-services-core/src/main/res/values-be/strings.xml +++ b/play-services-core/src/main/res/values-be/strings.xml @@ -114,7 +114,6 @@ Канфігурацыя Google сэрвісы Служба вызначэння месцазнаходжання - Рэжым работы Сэрвісы Тэст @@ -181,21 +180,10 @@ Незарэгістраваныя прыкладанні Сеткі для прыёму push-паведамленняў - Google SafetyNet гэта сістэма сертыфікацыі прылады, якая гарантуе, што прылада карэктна абаронена і сумяшчальна з Android CTS. Пэўныя праграмы выкарыстоўваюць SafetyNet з меркаванняў бяспекі або ў якасці папярэдняй сістэмы абароны ад узлому.\n\nmicroG GmsCore змяшчае свабодную рэалізацыю SafetyNet, але афіцыйны сервер патрабуе, каб запыты былі падпісаны з дапамогай прапрыетарнай сістэмы DroidGuard. Ізаляваная версія DroidGuard даступная як асобнае прыкладанне "DroidGuard Helper". + Google SafetyNet гэта сістэма сертыфікацыі прылады, якая гарантуе, што прылада карэктна абаронена і сумяшчальна з Android CTS. Пэўныя праграмы выкарыстоўваюць SafetyNet з меркаванняў бяспекі або ў якасці папярэдняй сістэмы абароны ад узлому.\n\nmicroG GmsCore змяшчае свабодную рэалізацыю SafetyNet, але афіцыйны сервер патрабуе, каб запыты былі падпісаны з дапамогай прапрыетарнай сістэмы DroidGuard. Дазволіць праверку статусу прылады - Тэст верыфікацыі SafetyNet - - Выкарыстоўваць афіцыйны сервер - Патрабуецца сістэма без root і ўсталяваны microG DroidGuard Helper - афіцыйны сервер - Выкарыстоўваць іншы сервер - Іншыя серверы могуць быць у стане адказаць на запыты SafetyNet без подпісу DroidGuard - іншы сервер - URL іншага сервера - Поўны URL іншага сервера, які адказвае на праверачныя запыты SafetyNet - Выкарыстоўваць самастойна падпісаны сертыфікат - Замест запытаў на сервер падпісваць SafetyNet лакальна, выкарыстоўваючы самастойна створаны сертыфікат. Большасць прыкладанняў будуць адмаўляцца выкарыстоўваць самастойна падпісаныя адказы. - самастойна падпісаны сертыфікат + Тэст верыфікацыі SafetyNet + Рэжым работы diff --git a/play-services-core/src/main/res/values-de/strings.xml b/play-services-core/src/main/res/values-de/strings.xml index 08e3579f..028a0acb 100644 --- a/play-services-core/src/main/res/values-de/strings.xml +++ b/play-services-core/src/main/res/values-de/strings.xml @@ -114,7 +114,6 @@ Dies kann einige Minuten dauern." Einstellungen Google-Dienste Standortdienst - Modus Dienste Test @@ -180,21 +179,10 @@ Dies kann einige Minuten dauern." Nicht-registrierte Apps Verwendbare Netzwerke - Google SafetyNet ist ein System, um Geräte zu zertifizieren und so sicherzustellen, dass sie ausreichend geschützt und kompatibel mit Android sind. Einige Anwendungen benutzen SafetyNet aus Sicherheitsgründen oder um einen Kopierschutz zu erzwingen.\n\nmicroG GmsCore enthält eine freie Implementierung von SafetyNet, jedoch verlangen die Google-Server, dass die Anfragen durch das proprietäre DroidGuard signiert sind. Eine unschädliche gemachte Version von DroidGuard ist als separate \"DroidGuard Helper\"-App verfügbar. + Google SafetyNet ist ein System, um Geräte zu zertifizieren und so sicherzustellen, dass sie ausreichend geschützt und kompatibel mit Android sind. Einige Anwendungen benutzen SafetyNet aus Sicherheitsgründen oder um einen Kopierschutz zu erzwingen.\n\nmicroG GmsCore enthält eine freie Implementierung von SafetyNet, jedoch verlangen die Google-Server, dass die Anfragen durch das proprietäre DroidGuard signiert sind. Geräte-Zertifizierung erlauben - SafetyNet-Zertifizierung testen - - Offizielle Server nutzen - Erfordert eine ungerootetes ROM und den microG DroidGuard Helper - offizieller Server - Alternativen Server nutzen - Alternative Server können auch SafetyNet-Anfragen beantworten, die nicht durch DroidGuard signiert wurden - Dritt-Server - Alternative Server URL - Vollständige URL des alternativen Servers, der SafetyNet-Anfragen beantwortet - Selbst signieren - Statt einen Server zu nutzen, die SafetyNet Signatur lokal mit einem eigens erstellten Zertifikat signieren. Die meisten Apps werden diese Signaturen nicht akzeptieren. - Selbst-signiertes Zertifikat + SafetyNet-Zertifizierung testen + Modus diff --git a/play-services-core/src/main/res/values-es/strings.xml b/play-services-core/src/main/res/values-es/strings.xml index 28e9a118..f3ebc241 100644 --- a/play-services-core/src/main/res/values-es/strings.xml +++ b/play-services-core/src/main/res/values-es/strings.xml @@ -112,7 +112,6 @@ Esto podría tardar algunos minutos." Configuración Servicios de Google Servicio de localización - Modo de operación Servicios Prueba @@ -179,21 +178,10 @@ Esto podría tardar algunos minutos." Aplicaciones no registradas Redes a utilizar para las notificaciones push - Google SafetyNet es un sistema de certificación de dispositivos, que garantiza que el dispositivo está correctamente asegurado y es compatible con Android CTS. Algunas aplicaciones utilizan SafetyNet por razones de seguridad o como un prerrequisito para la protección contra manipulaciones.\n\nmicroG GmsCore contiene una implementación gratuita de SafetyNet, pero el servidor oficial requiere que las solicitudes de SafetyNet sean firmadas utilizando el sistema propietario DroidGuard. Una versión en sandbox de DroidGuard está disponible como una aplicación separada "DroidGuard Helper". + Google SafetyNet es un sistema de certificación de dispositivos, que garantiza que el dispositivo está correctamente asegurado y es compatible con Android CTS. Algunas aplicaciones utilizan SafetyNet por razones de seguridad o como un prerrequisito para la protección contra manipulaciones.\n\nmicroG GmsCore contiene una implementación gratuita de SafetyNet, pero el servidor oficial requiere que las solicitudes de SafetyNet sean firmadas utilizando el sistema propietario DroidGuard. Permitir la certificación del dispositivo - Probar el certificado de SafetyNet - - Usar el servidor oficial - Requiere un sistema no root y un microG DroidGuard Helper instalado - servidor oficial - Usar un servidor de terceros - Los servidores de terceros podrían responder a las solicitudes de SafetyNet sin la firma de DroidGuard - servidor de terceros - URL del servidor personalizada - URL completa del servidor de terceros que responde a las solicitudes de certificación de SafetyNet - Usar un certificado autofirmado - En lugar de solicitar un servidor, firma las respuestas de SafetyNet localmente usando un certificado autofirmado. La mayoría de las aplicaciones se negarán a usar respuestas autofirmadas. - certificado autofirmado + Probar el certificado de SafetyNet + Modo de operación diff --git a/play-services-core/src/main/res/values-fr/strings.xml b/play-services-core/src/main/res/values-fr/strings.xml index 02d823dd..e0b44f25 100644 --- a/play-services-core/src/main/res/values-fr/strings.xml +++ b/play-services-core/src/main/res/values-fr/strings.xml @@ -102,7 +102,6 @@ Ceci peut prendre plusieurs minutes." Configuration Services Google Service de localisation - Mode d’opération Services Test @@ -149,18 +148,8 @@ Ceci peut prendre plusieurs minutes." Déconnecté Connecté depuis %1$s - Google SafetyNet est un système de certification du terminal, assurant que celui-ci est correctement sécurisé et compatible avec Android CTS. Certaines applications utilisent SafetyNet pour des raisons de sécurité ou comme prérequis anti-altérations.\n\nmicroG GmsCore contient une implantation libre de SafetyNet, mais les serveurs officiels requièrent que les requêtes SafetyNet soient signées par le système propriétaire DroidGuard. Une version mise en « bac-à-sable » de DroidGuard est disponible dans une application séparée « DroidGuard Helper ». - - - Tester la certification SafetyNet - - Utiliser les serveurs officiels - Nécessite un système non-rooté et microG DroidGuard Helper installé - Utiliser un serveur tiers - Les serveurs tiers peuvent être capable de répondre aux requêtes SafetyNet sans signature de DroidGuard. - URL serveur tiers - URL complète du serveur tiers répondant aux requêtes de certification SafetyNet - Utiliser un certificat auto-signé - Au lieu de requérir un serveur, signer les réponses SafetyNet localement en utilisant un certificat auto-signé. La plupart des applications refuseront d’utiliser des réponses auto-signées. + Google SafetyNet est un système de certification du terminal, assurant que celui-ci est correctement sécurisé et compatible avec Android CTS. Certaines applications utilisent SafetyNet pour des raisons de sécurité ou comme prérequis anti-altérations.\n\nmicroG GmsCore contient une implantation libre de SafetyNet, mais les serveurs officiels requièrent que les requêtes SafetyNet soient signées par le système propriétaire DroidGuard. + Tester la certification SafetyNet + Mode d’opération diff --git a/play-services-core/src/main/res/values-it/strings.xml b/play-services-core/src/main/res/values-it/strings.xml index 30ed69ad..dc17c400 100644 --- a/play-services-core/src/main/res/values-it/strings.xml +++ b/play-services-core/src/main/res/values-it/strings.xml @@ -106,7 +106,6 @@ Questa operazione può richiedere alcuni secondi." Configurazione Servizi Google Servizi di localizzazione - Modalità operativa Servizi Sperimentale @@ -174,21 +173,10 @@ Questa operazione può richiedere alcuni secondi." Applicazioni non registrate Reti da utilizzare per le notifiche push - SafetyNet di Google è un sistema di certificazione del dispositivo che ne garantisce la sicurezza e la compatibilità con Android CTS. Alcune applicazioni utilizzano SafetyNet per ragioni di sicurezza o come prerequisito per la protezione da manomissione.\n\nUn\'implementazione libera di SafetyNet è contenuta in microG, tuttavia i server ufficiali richiedono che le richieste SafetyNet siano firmate utilizzando il sistema proprietario DroidGuard. Una versione isolata di DroidGuard è disponibile all\'interno dell\'applicazione “microG DroidGuard Helper”. + SafetyNet di Google è un sistema di certificazione del dispositivo che ne garantisce la sicurezza e la compatibilità con Android CTS. Alcune applicazioni utilizzano SafetyNet per ragioni di sicurezza o come prerequisito per la protezione da manomissione.\n\nUn\'implementazione libera di SafetyNet è contenuta in microG, tuttavia i server ufficiali richiedono che le richieste SafetyNet siano firmate utilizzando il sistema proprietario DroidGuard. Permetti l\'attestazione del dispositivo - Prova l\'attestazione di SafetyNet - - Utilizza i server ufficiali - Richiede un sistema senza privilegi di root e con l\'applicazione "microG DroidGuard Helper" installata - Server ufficiale - Utilizza un server di terze parti - I server di terze parti potrebbero essere in grado di rispondere alle richieste di SafetyNet senza la firma di DroidGuard - Server di terze parti - URL del server personalizzato - URL completo del server personalizzato che risponde alle richieste di attestazione SafetyNet - Utilizza un certificato auto-firmato - Anziché inoltrare le richieste a un server, firma localmente le risposte SafetyNet utilizzando un certificato auto-firmato. La maggior parte delle applicazioni rifiuteranno l\'uso di risposte auto-firmate. - Certificato auto-firmato + Prova l\'attestazione di SafetyNet + Modalità operativa diff --git a/play-services-core/src/main/res/values-ja/strings.xml b/play-services-core/src/main/res/values-ja/strings.xml index 2cc5b3f2..d37a1429 100644 --- a/play-services-core/src/main/res/values-ja/strings.xml +++ b/play-services-core/src/main/res/values-ja/strings.xml @@ -109,7 +109,6 @@ 設定 Googleサービス 位置情報サービス - 動作モード サービス テスト @@ -171,20 +170,9 @@ Google SafetyNetはデバイス認証システムであり、デバイスが適切に保護され、Android CTSと互換性があることを保証します。 一部のアプリケーションは、セキュリティ上の理由または改ざん防止の前提条件としてSafetyNetを使用します。 - microG GmsCoreにはSafetyNetのオープンソースな実装が含まれていますが、公式サーバーでは、プロプライエタリなDroidGuardシステムを使用してSafetyNetリクエストに署名する必要があります。 DroidGuardのサンドボックスバージョンは、個別の「DroidGuardHelper」アプリとして利用できます。 + microG GmsCoreにはSafetyNetのオープンソースな実装が含まれていますが、公式サーバーでは、プロプライエタリなDroidGuardシステムを使用してSafetyNetリクエストに署名する必要があります。 デバイスの認証を許可 - SafetyNetテストの実行 - - 公式サーバーを使用 - root化されていないシステムと、microG DroidGuardHelperのインストールが必要です。 - 公式サーバー - サードパーティのサーバーを使用 - サードパーティのサーバーは、DroidGuardの署名がないSafetyNetリクエストに応答できる場合があります - third-party server - カスタムサーバーのURL - SafetyNet認証リクエストに応答するサードパーティサーバーの完全なURL - 自己署名証明書を使用 - サーバーにリクエストする代わりに、自己署名証明書を使用してローカルでSafetyNet応答に署名します。 ほとんどのアプリは、自己署名証明書を使用した応答の使用を拒否します。 - 自己署名証明書 + SafetyNetテストの実行 + 動作モード diff --git a/play-services-core/src/main/res/values-pl/strings.xml b/play-services-core/src/main/res/values-pl/strings.xml index 16b8a046..bc2206b2 100644 --- a/play-services-core/src/main/res/values-pl/strings.xml +++ b/play-services-core/src/main/res/values-pl/strings.xml @@ -102,7 +102,6 @@ To zajmie kilka minut. Konfiguracja Usługi Google Usługa lokalizacji - Tryb działania Usługi w tle Test @@ -147,17 +146,8 @@ To zajmie kilka minut. Odmówiłeś już zarejestrowanej aplikacji zarejestrować się w usłudze powiadomień ‘push’.\nCzy chcesz ją wyrejestrować, aby nie otrzymywała powiadomień ‘push’ w przyszłości? Wiadomości: %1$d (%2$d bajtów) - Google SafetyNet jest systemem certyfikacji urządzenia, który upewnia się czy urządzenie jest poprawnie zabezpieczone i kompatybilne z Android CTS. Niektóre aplikacje używają SafetyNet ze względów bezpieczeństwa lub jako przeciwśrodek do modyfikacji.\n\nUsługa microG GmsCore zawiera wolną implementację SafetyNet, ale oficjalny serwer wymaga by SafetyNet był podpisany przez własnościowy system DroidGuard. Specjalna wersja DroidGuard-a jest dostępna do pobrania jako oddzielna aplikacja “DroidGuard Helper” w repozytorium miroG w F-Droid. - - Wypróbuj działanie SafetyNet - - Użyj oficjalnego serwera - Wymaga niezrootowanego ROM-u i zainstalowanego microG DroidGuard Helper - Użyj serwera strony trzeciej - Serwery stron trzecich mogą być w stanie odpowiedzieć na zapytania SafetyNet bez sygnatury DroidGuard - URL własnego serwera - Pełny adres URL serwera strony trzeciej odpowiadającego na zapytania SafetyNet - Użyj samo-podpisanego certyfikatu - Zamiast sprawdzać serwer, podpisuj odpowiedzi SafetyNet lokalnie używając samo-podpisanego certyfikatu. Większość aplikacji odmówi użycia samo-podpisanych odpowiedzi. + Google SafetyNet jest systemem certyfikacji urządzenia, który upewnia się czy urządzenie jest poprawnie zabezpieczone i kompatybilne z Android CTS. Niektóre aplikacje używają SafetyNet ze względów bezpieczeństwa lub jako przeciwśrodek do modyfikacji.\n\nUsługa microG GmsCore zawiera wolną implementację SafetyNet, ale oficjalny serwer wymaga by SafetyNet był podpisany przez własnościowy system DroidGuard. + Wypróbuj działanie SafetyNet + Tryb działania diff --git a/play-services-core/src/main/res/values-ru/strings.xml b/play-services-core/src/main/res/values-ru/strings.xml index 2eec92ba..172223c7 100644 --- a/play-services-core/src/main/res/values-ru/strings.xml +++ b/play-services-core/src/main/res/values-ru/strings.xml @@ -114,7 +114,6 @@ Конфигурация Google сервисы Служба определения местоположения - Режим работы Сервисы Тест @@ -181,22 +180,11 @@ Незарегистрированные приложения Сети для приёма push-уведомлений - Google SafetyNet это система сертификации устройства, гарантирующая, что устройство корректно защищено и совместимо с Android CTS. Некоторые приложения используют SafetyNet из соображений безопасности или в качестве предварительной системы защиты от взлома.\n\nmicroG GmsCore содержит свободную реализацию SafetyNet, но официальный сервер требует, чтобы запросы были подписаны с помощью проприетарной системы DroidGuard. Изолированная версия DroidGuard доступна как отдельное приложение "DroidGuard Helper". + Google SafetyNet это система сертификации устройства, гарантирующая, что устройство корректно защищено и совместимо с Android CTS. Некоторые приложения используют SafetyNet из соображений безопасности или в качестве предварительной системы защиты от взлома.\n\nmicroG GmsCore содержит свободную реализацию SafetyNet, но официальный сервер требует, чтобы запросы были подписаны с помощью проприетарной системы DroidGuard. Разрешить проверку статуса устройства - Тест верификации SafetyNet - - Использовать официальный сервер - Требуется система без root и установленный microG DroidGuard Helper - официальный сервер - Использовать сторонний сервер - Сторонние сервера могут быть в состоянии ответить на запросы SafetyNet без подписи DroidGuard - сторонний сервер - URL стороннего сервера - Полный URL стороннего сервера, который отвечает на проверочные запросы SafetyNet - Использовать самоподписанный сертификат - Вместо запросов на сервер подписывать SafetyNet локально, используя самостоятельно созданный сертификат. Большинство приложений будут отказываться использовать самоподписанные ответы. - самоподписанный сертификат + Тест верификации SafetyNet + Режим работы diff --git a/play-services-core/src/main/res/values-uk/strings.xml b/play-services-core/src/main/res/values-uk/strings.xml index ace13272..f9246c9c 100644 --- a/play-services-core/src/main/res/values-uk/strings.xml +++ b/play-services-core/src/main/res/values-uk/strings.xml @@ -109,7 +109,6 @@ Конфігурація Сервіси Google Сервіси позиціювання - Режим роботи Сервіси Тест @@ -154,17 +153,8 @@ Ви заборонили додатку push-повідомлення, який вже був прив\'язаний.\nВи бажаєте відв\'язати його зараз, аби більше не отримувати від нього push-повідомлень? Повідомлень: %1$d (%2$d байт) - Google SafetyNet це система сертифікації пристрою, яка гарантує, що пристрій коректно захищено та сумісне із Android CTS. Деякі додатки використовують SafetyNet для безпеки або в якості попередньої системи захисту від злому.\n\nmicroG GmsCore містить вільну реалізацію SafetyNet, але офіційний сервер вимагає, аби запити були підписані за допомогою закритої програмної системи DroidGuard. Ізольована версія DroidGuard доступна для встановлення як окремий додаток \"DroidGuard Helper\". - - Протестувати SafetyNet перевірку - - Використовувати офіційний сервер - Потребує систему з адміністративними правами та встановленим microG DroidGuard Helper - Використовувати сторонній сервер - Сторонні сервери можуть відповідати на SafetyNet запити без підпису DroidGuard - Посилання стороннього серверу - Повне посилання стороннього серверу, який відповідає на запити SafetyNet - Використовувати самостійно підписаний сертифікат - Підписувати SafetyNet локально, замість запитів на сервер, використовуючи само-підписний сертифікат. Більшість додатків будуть відхиляти само-підписні відповіді. + Google SafetyNet це система сертифікації пристрою, яка гарантує, що пристрій коректно захищено та сумісне із Android CTS. Деякі додатки використовують SafetyNet для безпеки або в якості попередньої системи захисту від злому.\n\nmicroG GmsCore містить вільну реалізацію SafetyNet, але офіційний сервер вимагає, аби запити були підписані за допомогою закритої програмної системи DroidGuard. + Протестувати SafetyNet перевірку + Режим роботи diff --git a/play-services-core/src/main/res/values-zh-rTW/strings.xml b/play-services-core/src/main/res/values-zh-rTW/strings.xml index 1a9c71cd..aad94624 100644 --- a/play-services-core/src/main/res/values-zh-rTW/strings.xml +++ b/play-services-core/src/main/res/values-zh-rTW/strings.xml @@ -138,16 +138,7 @@ Google SafetyNet是一個確認手機被確實保護和相容於Android CTS的驗證系統。一些程式基於安全因素使用SafetyNet,一些則是以必須通過的形式來防止篡改。 - microG GmsCore包含了SafetyNet的自由執行,但官方伺服器需要SafetyNet請求經非自由軟體性質的DroidGuard系統簽名。有一個可用的沙盒測試版本DroidGuard:獨立程式“DroidGuard Helper”。 + microG GmsCore包含了SafetyNet的自由執行,但官方伺服器需要SafetyNet請求經非自由軟體性質的DroidGuard系統簽名。 - 測試SafetyNet驗證 - - 使用官方伺服器 - 需要未root的系統及安裝microG DroidGuard Helper - 使用第三方伺服器 - 第三方伺服器可能不需要DroidGuard簽名便能回應SafetyNet請求 - 自訂伺服器網址 - 回應SafetyNet驗證請求之第三方伺服器的完整網址 - 使用自行簽名認證 - 不向伺服器請求簽名,而是用本地的認證文件自行簽名SafetyNet。大部分的程式都會拒絕自行簽名認證。 + 測試SafetyNet驗證 diff --git a/play-services-core/src/main/res/values/strings.xml b/play-services-core/src/main/res/values/strings.xml index 2f2e5752..499d43fc 100644 --- a/play-services-core/src/main/res/values/strings.xml +++ b/play-services-core/src/main/res/values/strings.xml @@ -1,19 +1,8 @@ - - microG Services Core microG Settings @@ -114,7 +103,6 @@ This can take a couple of minutes." Configuration Google Services Location service - Operation mode Services Test @@ -182,21 +170,15 @@ This can take a couple of minutes." Unregistered apps Networks to use for push notifications - Google SafetyNet is a device certification system, ensuring that the device is properly secured and compatible with Android CTS. Some applications use SafetyNet for security reasons or as a prerequisite for tamper-protection.\n\nmicroG GmsCore contains a free implementation of SafetyNet, but the official server requires SafetyNet requests to be signed using the proprietary DroidGuard system. A sandboxed version of DroidGuard is available as a separate “DroidGuard Helper” app. + Google SafetyNet is a device certification system, ensuring that the device is properly secured and compatible with Android CTS. Some applications use SafetyNet for security reasons or as a prerequisite for tamper-protection.\n\nmicroG GmsCore contains a free implementation of SafetyNet, but the official server requires SafetyNet requests to be signed using the proprietary DroidGuard system. Allow device attestation - Try SafetyNet attestation - - Use official server - Requires an unrooted system and microG DroidGuard Helper installed - official server - Use third-party server - Third-party servers might be able to reply to SafetyNet requests without DroidGuard signature - third-party server - Custom server URL - Full URL of the third-party server answering SafetyNet attestation requests - Use self-signed certificate - Instead of requesting a server, sign SafetyNet responses locally using a self-signed certificate. Most apps will refuse to use self-signed responses. - self-signed certificate + Test SafetyNet attestation + Test ReCAPTCHA + Passed all tests + Failed: %s + Warning: %s + Running… + Operation mode diff --git a/play-services-core/src/main/res/xml/preferences_device_registration.xml b/play-services-core/src/main/res/xml/preferences_device_registration.xml index 1f73af33..6c82e63c 100644 --- a/play-services-core/src/main/res/xml/preferences_device_registration.xml +++ b/play-services-core/src/main/res/xml/preferences_device_registration.xml @@ -6,17 +6,29 @@ + + + + diff --git a/play-services-core/src/main/res/xml/preferences_gcm.xml b/play-services-core/src/main/res/xml/preferences_gcm.xml deleted file mode 100644 index bcfc63bb..00000000 --- a/play-services-core/src/main/res/xml/preferences_gcm.xml +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - - - - - \ No newline at end of file diff --git a/play-services-core/src/main/res/xml/preferences_push_notifications.xml b/play-services-core/src/main/res/xml/preferences_push_notifications.xml index 0fd4e926..871ad6cf 100644 --- a/play-services-core/src/main/res/xml/preferences_push_notifications.xml +++ b/play-services-core/src/main/res/xml/preferences_push_notifications.xml @@ -26,7 +26,7 @@ android:layout="@layout/preference_category_no_label"> diff --git a/play-services-core/src/main/res/xml/preferences_safetynet.xml b/play-services-core/src/main/res/xml/preferences_safetynet.xml index 2c4dfbbf..438395af 100644 --- a/play-services-core/src/main/res/xml/preferences_safetynet.xml +++ b/play-services-core/src/main/res/xml/preferences_safetynet.xml @@ -17,19 +17,26 @@ - + xmlns:app="http://schemas.android.com/apk/res-auto" + xmlns:tools="http://schemas.android.com/tools"> + android:layout="@layout/preference_category_no_label"> + android:title="@string/pref_safetynet_test_title" + tools:icon="@drawable/ic_circle_check" + tools:summary="@string/pref_test_summary_passed" /> + + + + diff --git a/play-services-core/src/main/res/xml/preferences_snet_advanced.xml b/play-services-core/src/main/res/xml/preferences_snet_advanced.xml index e87859af..e50f5ba9 100644 --- a/play-services-core/src/main/res/xml/preferences_snet_advanced.xml +++ b/play-services-core/src/main/res/xml/preferences_snet_advanced.xml @@ -15,29 +15,12 @@ ~ limitations under the License. --> - - - - - - + + + - \ No newline at end of file + diff --git a/play-services-core/src/withNearby/kotlin/org/microg/gms/ui/NearbyPreferencesIntegration.kt b/play-services-core/src/withNearby/kotlin/org/microg/gms/ui/NearbyPreferencesIntegration.kt index 17d20c37..d4f940e1 100644 --- a/play-services-core/src/withNearby/kotlin/org/microg/gms/ui/NearbyPreferencesIntegration.kt +++ b/play-services-core/src/withNearby/kotlin/org/microg/gms/ui/NearbyPreferencesIntegration.kt @@ -12,11 +12,12 @@ import android.net.Uri import androidx.core.content.ContextCompat import com.google.android.gms.R import org.microg.gms.nearby.exposurenotification.Constants +import org.microg.gms.nearby.exposurenotification.ExposurePreferences import org.microg.gms.nearby.exposurenotification.getExposureNotificationsServiceInfo interface NearbyPreferencesIntegration { companion object { - suspend fun getExposurePreferenceSummary(context: Context): String = if (isAvailable && getExposureNotificationsServiceInfo(context).configuration.enabled) { + suspend fun getExposurePreferenceSummary(context: Context): String = if (isAvailable && ExposurePreferences(context).enabled) { context.getString(R.string.service_status_enabled_short) } else { context.getString(R.string.service_status_disabled_short) diff --git a/play-services-droidguard-core-ui/build.gradle b/play-services-droidguard-core-ui/build.gradle new file mode 100644 index 00000000..90ad5e30 --- /dev/null +++ b/play-services-droidguard-core-ui/build.gradle @@ -0,0 +1,53 @@ +/* + * SPDX-FileCopyrightText: 2021, microG Project Team + * SPDX-License-Identifier: Apache-2.0 + */ + +apply plugin: 'com.android.library' +apply plugin: 'kotlin-android' +apply plugin: 'kotlin-kapt' +apply plugin: 'maven-publish' +apply plugin: 'signing' + +dependencies { + implementation project(':play-services-droidguard-core') + implementation project(':play-services-base-core-ui') + + implementation "androidx.appcompat:appcompat:$appcompatVersion" + implementation "androidx.preference:preference-ktx:$preferenceVersion" + implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlinVersion" +} + +android { + compileSdkVersion androidCompileSdk + buildToolsVersion "$androidBuildVersionTools" + + defaultConfig { + versionName version + minSdkVersion androidMinSdk + targetSdkVersion androidTargetSdk + } + + sourceSets { + main { + java.srcDirs = ['src/main/kotlin'] + } + } + + lintOptions { + disable 'MissingTranslation' + } + + compileOptions { + sourceCompatibility = 1.8 + targetCompatibility = 1.8 + } + + kotlinOptions { + jvmTarget = 1.8 + } +} + +apply from: '../gradle/publish-android.gradle' + +description = 'UI for microG service implementation for play-services-droidguard' diff --git a/play-services-droidguard-core-ui/src/main/AndroidManifest.xml b/play-services-droidguard-core-ui/src/main/AndroidManifest.xml new file mode 100644 index 00000000..400eff15 --- /dev/null +++ b/play-services-droidguard-core-ui/src/main/AndroidManifest.xml @@ -0,0 +1,11 @@ + + + + + + diff --git a/play-services-droidguard-core-ui/src/main/kotlin/org/microg/gms/droidguard/core/ui/ContainedEditTextPreference.kt b/play-services-droidguard-core-ui/src/main/kotlin/org/microg/gms/droidguard/core/ui/ContainedEditTextPreference.kt new file mode 100644 index 00000000..5fcde75b --- /dev/null +++ b/play-services-droidguard-core-ui/src/main/kotlin/org/microg/gms/droidguard/core/ui/ContainedEditTextPreference.kt @@ -0,0 +1,69 @@ +/* + * SPDX-FileCopyrightText: 2021 microG Project Team + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.microg.gms.droidguard.core.ui + +import android.content.Context +import android.text.TextWatcher +import android.util.AttributeSet +import android.view.inputmethod.InputMethodManager +import android.widget.EditText +import androidx.core.widget.addTextChangedListener +import androidx.preference.Preference +import androidx.preference.PreferenceViewHolder + +class ContainedEditTextPreference : Preference { + constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int, defStyleRes: Int) : super(context, attrs, defStyleAttr, defStyleRes) + constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr) + constructor(context: Context?, attrs: AttributeSet?) : super(context, attrs) + constructor(context: Context) : super(context) + + override fun onBindViewHolder(holder: PreferenceViewHolder) { + super.onBindViewHolder(holder) + val editText = holder.itemView.findViewById(android.R.id.edit) + (editText as? TextWatcher)?.let { editText.removeTextChangedListener(it) } + editText.addTextChangedListener { textChangedListener(it?.toString() ?: "") } + editText.tag = this + editText.hint = hint + editText.text.replace(0, editText.text.length, text) + editText.isEnabled = editable + if (requestFocus) { + editText.requestFocus() + (editText.context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager).showSoftInput(editText, InputMethodManager.SHOW_IMPLICIT) + requestFocus = false + } + } + + private var requestFocus: Boolean = false + fun editRequestFocus() { + requestFocus = true + notifyChanged() + } + + var textChangedListener: (String) -> Unit = {} + + var editable: Boolean = true + set(value) { + field = value + notifyChanged() + } + + var text: String = "" + set(value) { + field = value + notifyChanged() + } + + var hint: String = "" + set(value) { + field = value + notifyChanged() + } + + init { + layoutResource = R.layout.preference_material_with_widget_below + widgetLayoutResource = R.layout.preference_edit_widget + } +} diff --git a/play-services-droidguard-core-ui/src/main/kotlin/org/microg/gms/droidguard/core/ui/DroidGuardPreferencesFragment.kt b/play-services-droidguard-core-ui/src/main/kotlin/org/microg/gms/droidguard/core/ui/DroidGuardPreferencesFragment.kt new file mode 100644 index 00000000..db3eed15 --- /dev/null +++ b/play-services-droidguard-core-ui/src/main/kotlin/org/microg/gms/droidguard/core/ui/DroidGuardPreferencesFragment.kt @@ -0,0 +1,53 @@ +/* + * SPDX-FileCopyrightText: 2021 microG Project Team + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.microg.gms.droidguard.core.ui + +import android.os.Bundle +import androidx.preference.Preference +import androidx.preference.PreferenceFragmentCompat +import org.microg.gms.droidguard.core.DroidGuardPreferences +import org.microg.gms.droidguard.core.DroidGuardPreferences.Mode.Embedded +import org.microg.gms.droidguard.core.DroidGuardPreferences.Mode.Network +import org.microg.gms.droidguard.core.ui.R.drawable.ic_radio_checked +import org.microg.gms.droidguard.core.ui.R.drawable.ic_radio_unchecked + +class DroidGuardPreferencesFragment : PreferenceFragmentCompat() { + private lateinit var modeEmbedded: Preference + private lateinit var modeNetwork: ContainedEditTextPreference + + override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) { + addPreferencesFromResource(R.xml.preferences_droidguard) + } + + override fun onBindPreferences() { + modeEmbedded = preferenceScreen.findPreference("pref_droidguard_mode_embedded") ?: modeEmbedded + modeNetwork = preferenceScreen.findPreference("pref_droidguard_mode_network") ?: modeNetwork + modeEmbedded.setOnPreferenceClickListener { + DroidGuardPreferences.setMode(it.context, Embedded) + updateConfiguration() + true + } + modeNetwork.setOnPreferenceClickListener { + DroidGuardPreferences.setMode(it.context, Network) + modeNetwork.editRequestFocus() + updateConfiguration() + true + } + modeNetwork.textChangedListener = { + DroidGuardPreferences.setNetworkServerUrl(requireContext(), it) + } + updateConfiguration() + } + + fun updateConfiguration() { + val mode = DroidGuardPreferences.getMode(requireContext()) + modeEmbedded.setIcon(if (mode == Embedded) ic_radio_checked else ic_radio_unchecked) + modeNetwork.setIcon(if (mode == Network) ic_radio_checked else ic_radio_unchecked) + modeNetwork.text = DroidGuardPreferences.getNetworkServerUrl(requireContext()) ?: "" + modeNetwork.editable = mode == Network + modeNetwork.hint = "https://example.com/droidguard/" + } +} diff --git a/play-services-droidguard-core-ui/src/main/res/layout/preference_edit_widget.xml b/play-services-droidguard-core-ui/src/main/res/layout/preference_edit_widget.xml new file mode 100644 index 00000000..193a6cd7 --- /dev/null +++ b/play-services-droidguard-core-ui/src/main/res/layout/preference_edit_widget.xml @@ -0,0 +1,20 @@ + + + + + + + diff --git a/play-services-droidguard-core-ui/src/main/res/layout/preference_material_with_widget_below.xml b/play-services-droidguard-core-ui/src/main/res/layout/preference_material_with_widget_below.xml new file mode 100644 index 00000000..72c619e9 --- /dev/null +++ b/play-services-droidguard-core-ui/src/main/res/layout/preference_material_with_widget_below.xml @@ -0,0 +1,75 @@ + + + + + + + + + + + + + + + + + + + diff --git a/play-services-droidguard-core-ui/src/main/res/values/strings.xml b/play-services-droidguard-core-ui/src/main/res/values/strings.xml new file mode 100644 index 00000000..a7a66403 --- /dev/null +++ b/play-services-droidguard-core-ui/src/main/res/values/strings.xml @@ -0,0 +1,12 @@ + + + + DroidGuard operation mode + Embedded + Use local DroidGuard runtime + Remote + Connect to DroidGuard runtime via network + diff --git a/play-services-droidguard-core-ui/src/main/res/xml/preferences_droidguard.xml b/play-services-droidguard-core-ui/src/main/res/xml/preferences_droidguard.xml new file mode 100644 index 00000000..995f0a1d --- /dev/null +++ b/play-services-droidguard-core-ui/src/main/res/xml/preferences_droidguard.xml @@ -0,0 +1,15 @@ + + + + + + + diff --git a/settings.gradle b/settings.gradle index 601c7f71..f8812b76 100644 --- a/settings.gradle +++ b/settings.gradle @@ -10,6 +10,7 @@ include ':play-services-droidguard-api' include ':play-services-iid-api' include ':play-services-location-api' include ':play-services-nearby-api' +include ':play-services-safetynet-api' include ':play-services-tapandpay-api' include ':play-services-vision-api' include ':play-services-vision-common-api' @@ -38,6 +39,7 @@ include ':firebase-dynamic-links-api' include ':play-services-core-proto' include ':play-services-droidguard-core-proto' include ':play-services-nearby-core-proto' +include ':play-services-safetynet-core-proto' include ':play-services-wearable-proto' include ':play-services-basement-ktx' @@ -53,10 +55,12 @@ include ':play-services-maps-core-mapbox' include ':play-services-maps-core-vtm' include ':play-services-maps-core-vtm:vtm-microg-theme' include ':play-services-nearby-core' +include ':play-services-safetynet-core' include ':play-services-tapandpay-core' include ':play-services-vision-core' include ':play-services-base-core-ui' +include ':play-services-droidguard-core-ui' include ':play-services-nearby-core-ui' include ':firebase-auth-core'