Repo Created
This commit is contained in:
parent
eb305e2886
commit
a8c22c65db
4784 changed files with 329907 additions and 2 deletions
72
play-services-droidguard/core/build.gradle
Normal file
72
play-services-droidguard/core/build.gradle
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2021, microG Project Team
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
apply plugin: 'com.android.library'
|
||||
apply plugin: 'com.squareup.wire'
|
||||
apply plugin: 'kotlin-android'
|
||||
apply plugin: 'maven-publish'
|
||||
apply plugin: 'signing'
|
||||
|
||||
dependencies {
|
||||
api project(':play-services-droidguard')
|
||||
|
||||
implementation project(':play-services-base-core')
|
||||
implementation project(':play-services-chimera-core')
|
||||
implementation project(':play-services-tasks-ktx')
|
||||
|
||||
implementation "androidx.appcompat:appcompat:$appcompatVersion"
|
||||
implementation "androidx.core:core-ktx:$coreVersion"
|
||||
implementation "androidx.preference:preference-ktx:$preferenceVersion"
|
||||
|
||||
implementation "com.android.volley:volley:$volleyVersion"
|
||||
implementation "com.squareup.wire:wire-runtime:$wireVersion"
|
||||
|
||||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlinVersion"
|
||||
}
|
||||
|
||||
wire {
|
||||
kotlin {}
|
||||
}
|
||||
|
||||
android {
|
||||
namespace "org.microg.gms.droidguard.core"
|
||||
|
||||
compileSdkVersion androidCompileSdk
|
||||
buildToolsVersion "$androidBuildVersionTools"
|
||||
|
||||
buildFeatures {
|
||||
buildConfig = true
|
||||
}
|
||||
|
||||
defaultConfig {
|
||||
versionName "20.47.14"
|
||||
versionCode 204714000
|
||||
minSdkVersion androidMinSdk
|
||||
targetSdkVersion androidTargetSdk
|
||||
buildConfigField("String", "VERSION_NAME", "\"${defaultConfig.versionName}\"")
|
||||
buildConfigField("int", "VERSION_CODE", "${defaultConfig.versionCode}")
|
||||
}
|
||||
|
||||
sourceSets {
|
||||
main.java.srcDirs += 'src/main/kotlin'
|
||||
}
|
||||
|
||||
lintOptions {
|
||||
disable 'MissingTranslation', 'GetLocales'
|
||||
}
|
||||
|
||||
compileOptions {
|
||||
sourceCompatibility = 1.8
|
||||
targetCompatibility = 1.8
|
||||
}
|
||||
|
||||
kotlinOptions {
|
||||
jvmTarget = 1.8
|
||||
}
|
||||
}
|
||||
|
||||
apply from: '../../gradle/publish-android.gradle'
|
||||
|
||||
description = 'microG service implementation for play-services-droidguard'
|
||||
27
play-services-droidguard/core/src/main/AndroidManifest.xml
Normal file
27
play-services-droidguard/core/src/main/AndroidManifest.xml
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
~ SPDX-FileCopyrightText: 2021, microG Project Team
|
||||
~ SPDX-License-Identifier: Apache-2.0
|
||||
-->
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
|
||||
<application>
|
||||
<service
|
||||
android:name=".DroidGuardService"
|
||||
android:enabled="true"
|
||||
android:exported="true"
|
||||
android:process="com.google.android.gms.unstable">
|
||||
<intent-filter>
|
||||
<action android:name="com.google.android.gms.droidguard.service.INIT" />
|
||||
<action android:name="com.google.android.gms.droidguard.service.PING" />
|
||||
<action android:name="com.google.android.gms.droidguard.service.START" />
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
</intent-filter>
|
||||
</service>
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
|
|
@ -0,0 +1,145 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2021, microG Project Team
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package com.google.android.gms.droidguard;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.os.Handler;
|
||||
import android.os.IBinder;
|
||||
import android.util.Base64;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.google.android.gms.framework.tracing.wrapper.TracingIntentService;
|
||||
|
||||
import org.microg.gms.droidguard.core.DroidGuardPreferences;
|
||||
import org.microg.gms.droidguard.core.DroidGuardServiceBroker;
|
||||
import org.microg.gms.droidguard.GuardCallback;
|
||||
import org.microg.gms.droidguard.core.NetworkHandleProxyFactory;
|
||||
import org.microg.gms.droidguard.PingData;
|
||||
import org.microg.gms.droidguard.Request;
|
||||
import org.microg.gms.droidguard.core.HardwareAttestationBlockingProvider;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
import java.util.concurrent.ThreadPoolExecutor;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class DroidGuardChimeraService extends TracingIntentService {
|
||||
public static final Object a = new Object();
|
||||
// factory
|
||||
public NetworkHandleProxyFactory b;
|
||||
// widevine
|
||||
public Object c;
|
||||
// executor
|
||||
public Executor d;
|
||||
// log
|
||||
public Object e;
|
||||
|
||||
private static final Object f = new Object();
|
||||
|
||||
// ping
|
||||
private Object g;
|
||||
// handler
|
||||
private Handler h;
|
||||
|
||||
|
||||
public DroidGuardChimeraService() {
|
||||
super("DG");
|
||||
setIntentRedelivery(true);
|
||||
}
|
||||
|
||||
public DroidGuardChimeraService(NetworkHandleProxyFactory factory, Object ping, Object database) {
|
||||
super("DG");
|
||||
setIntentRedelivery(true);
|
||||
this.b = factory;
|
||||
this.g = ping;
|
||||
this.h = new Handler();
|
||||
}
|
||||
|
||||
// fsc
|
||||
private final void c(byte[] data) {
|
||||
PingData ping = null;
|
||||
if (data != null) {
|
||||
Log.d("GmsGuardChimera", "c(" + Base64.encodeToString(data, Base64.NO_WRAP) + ")", new RuntimeException().fillInStackTrace());
|
||||
try {
|
||||
ping = PingData.ADAPTER.decode(data);
|
||||
} catch (Exception e) {
|
||||
Log.w("GmsGuardChimera", e);
|
||||
}
|
||||
} else {
|
||||
Log.d("GmsGuardChimera", "c(null)", new RuntimeException().fillInStackTrace());
|
||||
}
|
||||
try {
|
||||
byte[] bytes = b.createPingHandle(getPackageName(), "full", b(""), ping).run(Collections.emptyMap());
|
||||
Log.d("GmsGuardChimera", "c.bytes = " + Base64.encodeToString(bytes, Base64.NO_WRAP));
|
||||
Request fastRequest = b.createRequest("fast", getPackageName(), null, bytes);
|
||||
b.fetchFromServer("fast", fastRequest);
|
||||
} catch (Exception e) {
|
||||
Log.w("GmsGuardChimera", e);
|
||||
}
|
||||
}
|
||||
|
||||
// handle intent
|
||||
public final void a(@Nullable Intent intent) {
|
||||
Log.d("GmsGuardChimera", "a(" + intent + ")");
|
||||
if (intent != null && intent.getAction() != null && intent.getAction().equals("com.google.android.gms.droidguard.service.PING")) {
|
||||
byte[] byteData = intent.getByteArrayExtra("data");
|
||||
if (byteData == null) {
|
||||
int[] intData = intent.getIntArrayExtra("data");
|
||||
if (intData == null) {
|
||||
c(null);
|
||||
return;
|
||||
}
|
||||
byteData = new byte[intData.length];
|
||||
for (int i = 0; i < intData.length; i++) {
|
||||
byteData[i] = (byte) intData[i];
|
||||
}
|
||||
}
|
||||
c(byteData);
|
||||
}
|
||||
}
|
||||
|
||||
// getCallback
|
||||
public final GuardCallback b(String packageName) {
|
||||
Log.d("GmsGuardChimera", "b[getCallback](" + packageName + ")");
|
||||
return new GuardCallback(this, packageName);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public final IBinder onBind(Intent intent) {
|
||||
if (intent != null && intent.getAction() != null && intent.getAction().equals("com.google.android.gms.droidguard.service.START")) {
|
||||
HardwareAttestationBlockingProvider.ensureEnabled(DroidGuardPreferences.isHardwareAttestationBlocked(this));
|
||||
return new DroidGuardServiceBroker(this);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
this.e = new Object();
|
||||
this.b = new NetworkHandleProxyFactory(this);
|
||||
this.g = new Object();
|
||||
this.h = new Handler();
|
||||
this.c = new Object();
|
||||
this.d = new ThreadPoolExecutor(1, 1, 0, TimeUnit.NANOSECONDS, new LinkedBlockingQueue<>(1), new ThreadPoolExecutor.DiscardPolicy());
|
||||
HardwareAttestationBlockingProvider.ensureEnabled(DroidGuardPreferences.isHardwareAttestationBlocked(this));
|
||||
super.onCreate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
super.onDestroy();
|
||||
this.e = null;
|
||||
this.b = null;
|
||||
this.g = null;
|
||||
this.h = null;
|
||||
this.c = null;
|
||||
this.d = null;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2021, microG Project Team
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package com.google.android.gms.framework.tracing.wrapper;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.google.android.chimera.IntentService;
|
||||
|
||||
import org.microg.gms.utils.PackageManagerWrapper;
|
||||
import org.microg.gms.droidguard.core.VersionUtil;
|
||||
|
||||
public abstract class TracingIntentService extends IntentService {
|
||||
private static final String TAG = "TracingIntentService";
|
||||
|
||||
public TracingIntentService(String name) {
|
||||
super(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void attachBaseContext(Context newBase) {
|
||||
super.attachBaseContext(newBase);
|
||||
}
|
||||
|
||||
protected abstract void a(@Nullable Intent intent);
|
||||
|
||||
@Override
|
||||
public PackageManager getPackageManager() {
|
||||
return new PackageManagerWrapper(super.getPackageManager()) {
|
||||
@NonNull
|
||||
@Override
|
||||
public PackageInfo getPackageInfo(@NonNull String packageName, int flags) {
|
||||
PackageInfo packageInfo = super.getPackageInfo(packageName, flags);
|
||||
if ("com.google.android.gms".equals(packageName)) {
|
||||
VersionUtil versionUtil = new VersionUtil(TracingIntentService.this);
|
||||
packageInfo.versionCode = versionUtil.getVersionCode();
|
||||
packageInfo.versionName = versionUtil.getVersionString();
|
||||
packageInfo.sharedUserId = "com.google.uid.shared";
|
||||
}
|
||||
return packageInfo;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onHandleIntent(@Nullable Intent intent) {
|
||||
this.a(intent);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,80 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2021, microG Project Team
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package org.microg.gms.droidguard;
|
||||
|
||||
import android.content.Context;
|
||||
import android.media.MediaDrm;
|
||||
import android.util.Log;
|
||||
|
||||
import org.microg.gms.droidguard.core.FallbackCreator;
|
||||
import org.microg.gms.settings.SettingsContract;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
import static android.os.Build.VERSION.SDK_INT;
|
||||
|
||||
/**
|
||||
* Callbacks invoked from the DroidGuard VM
|
||||
* <p>
|
||||
* We keep this file in Java to ensure ABI compatibility.
|
||||
* Methods are invoked by name from within the VM and thus must keep current name.
|
||||
*/
|
||||
public class GuardCallback {
|
||||
private static final String TAG = "GmsGuardCallback";
|
||||
private final Context context;
|
||||
private final String packageName;
|
||||
|
||||
public GuardCallback(Context context, String packageName) {
|
||||
this.context = context;
|
||||
this.packageName = packageName;
|
||||
}
|
||||
|
||||
public final String a(final byte[] array) {
|
||||
Log.d(TAG, "a[?](" + array + ")");
|
||||
return new String(FallbackCreator.create(new HashMap<>(), array, "", context, null));
|
||||
}
|
||||
|
||||
// getAndroidId
|
||||
public final String b() {
|
||||
try {
|
||||
long androidId = SettingsContract.INSTANCE.getSettings(context, SettingsContract.CheckIn.INSTANCE.getContentUri(context), new String[]{SettingsContract.CheckIn.ANDROID_ID}, cursor -> cursor.getLong(0));
|
||||
Log.d(TAG, "b[getAndroidId]() = " + androidId);
|
||||
return String.valueOf(androidId);
|
||||
} catch (Throwable e) {
|
||||
Log.w(TAG, "Failed to get Android ID, fallback to random", e);
|
||||
}
|
||||
long androidId = (long) (Math.random() * Long.MAX_VALUE);
|
||||
Log.d(TAG, "b[getAndroidId]() = " + androidId + " (random)");
|
||||
return String.valueOf(androidId);
|
||||
}
|
||||
|
||||
// getPackageName
|
||||
public final String c() {
|
||||
Log.d(TAG, "c[getPackageName]() = " + packageName);
|
||||
return packageName;
|
||||
}
|
||||
|
||||
// closeMediaDrmSession
|
||||
public final void d(final Object mediaDrm, final byte[] sessionId) {
|
||||
Log.d(TAG, "d[closeMediaDrmSession](" + mediaDrm + ", " + sessionId + ")");
|
||||
synchronized (MediaDrmLock.LOCK) {
|
||||
if (SDK_INT >= 18) {
|
||||
((MediaDrm) mediaDrm).closeSession(sessionId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public final void e(final int task) {
|
||||
Log.d(TAG, "e[?](" + task + ")");
|
||||
// TODO: Open database
|
||||
if (task == 1) {
|
||||
// TODO
|
||||
} else if (task == 0) {
|
||||
// TODO
|
||||
}
|
||||
// TODO: Set value in database
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2021, microG Project Team
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package org.microg.gms.droidguard;
|
||||
|
||||
public class MediaDrmLock {
|
||||
public static final Object LOCK = new Object();
|
||||
}
|
||||
|
|
@ -0,0 +1,71 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2021, microG Project Team
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package org.microg.gms.droidguard.core
|
||||
|
||||
import android.content.ContentValues
|
||||
import android.content.Context
|
||||
import android.database.sqlite.SQLiteDatabase
|
||||
import android.database.sqlite.SQLiteOpenHelper
|
||||
|
||||
/**
|
||||
* - a: id
|
||||
* - b: timestamp
|
||||
* - c: seconds until expiry
|
||||
* - d: vm key
|
||||
* - e: ?
|
||||
* - f: byte code
|
||||
* - g: extra
|
||||
*/
|
||||
class DgDatabaseHelper(context: Context) : SQLiteOpenHelper(context, "dg.db", null, 2) {
|
||||
override fun onCreate(db: SQLiteDatabase) {
|
||||
// Note: "NON NULL" is actually not a valid sqlite constraint, but this is what we see in the original database 🤷
|
||||
db.execSQL("CREATE TABLE main (a TEXT NOT NULL, b LONG NOT NULL, c LONG NOT NULL, d TEXT NON NULL, e TEXT NON NULL,f BLOB NOT NULL,g BLOB NOT NULL);");
|
||||
}
|
||||
|
||||
override fun onUpgrade(db: SQLiteDatabase, oldVersion: Int, newVersion: Int) {
|
||||
db.execSQL("DROP TABLE IF EXISTS main;");
|
||||
this.onCreate(db);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return vm key, byte code, extra
|
||||
*/
|
||||
fun get(id: String): Triple<String, ByteArray, ByteArray>? = readableDatabase.use { db ->
|
||||
val time = System.currentTimeMillis() / 1000
|
||||
val it = db.query("main", arrayOf("f", "d", "e", "c", "g"), "a = ? AND b <= $time AND $time < (b + c)", arrayOf(id), null, null, "b DESC", "1")
|
||||
try {
|
||||
if (it.moveToNext()) {
|
||||
Triple(it.getString(1), it.getBlob(0), it.getBlob(4))
|
||||
} else {
|
||||
null
|
||||
}
|
||||
} finally {
|
||||
it.close()
|
||||
}
|
||||
}
|
||||
|
||||
fun put(id: String, expiry: Long, vmKey: String, byteCode: ByteArray, extra: ByteArray) {
|
||||
val dbData = ContentValues().apply {
|
||||
put("a", id)
|
||||
put("b", System.currentTimeMillis() / 1000)
|
||||
put("c", expiry)
|
||||
put("d", vmKey)
|
||||
put("e", "")
|
||||
put("f", byteCode)
|
||||
put("g", extra)
|
||||
}
|
||||
writableDatabase.use {
|
||||
it.beginTransaction()
|
||||
if (expiry <= 0) {
|
||||
it.delete("main", "a = ?", arrayOf(id))
|
||||
} else if (it.update("main", dbData, "a = ?", arrayOf(id)) <= 0) {
|
||||
it.insert("main", null, dbData)
|
||||
}
|
||||
it.setTransactionSuccessful()
|
||||
it.endTransaction()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2021, microG Project Team
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package org.microg.gms.droidguard.core
|
||||
|
||||
import android.content.Context
|
||||
import android.database.sqlite.SQLiteDatabase
|
||||
import android.database.sqlite.SQLiteOpenHelper
|
||||
|
||||
class DgpDatabaseHelper(context: Context) : SQLiteOpenHelper(context, "dgp.db", null, 1) {
|
||||
override fun onCreate(db: SQLiteDatabase) {
|
||||
db.execSQL("CREATE TABLE t (a BLOB NOT NULL);");
|
||||
}
|
||||
|
||||
override fun onUpgrade(db: SQLiteDatabase, oldVersion: Int, newVersion: Int) {
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,118 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2021 microG Project Team
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package org.microg.gms.droidguard.core
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.Context
|
||||
import android.os.ConditionVariable
|
||||
import android.os.ParcelFileDescriptor
|
||||
import android.os.Parcelable
|
||||
import android.util.Log
|
||||
import com.google.android.gms.droidguard.internal.DroidGuardInitReply
|
||||
import com.google.android.gms.droidguard.internal.DroidGuardResultsRequest
|
||||
import com.google.android.gms.droidguard.internal.IDroidGuardHandle
|
||||
import org.microg.gms.droidguard.BytesException
|
||||
import org.microg.gms.droidguard.GuardCallback
|
||||
import org.microg.gms.droidguard.HandleProxy
|
||||
import java.io.FileNotFoundException
|
||||
|
||||
class DroidGuardHandleImpl(private val context: Context, private val packageName: String, private val factory: NetworkHandleProxyFactory, private val callback: GuardCallback) : IDroidGuardHandle.Stub() {
|
||||
private val condition = ConditionVariable()
|
||||
|
||||
private var flow: String? = null
|
||||
private var handleProxy: HandleProxy? = null
|
||||
private var handleInitError: Throwable? = null
|
||||
|
||||
override fun init(flow: String?) {
|
||||
Log.d(TAG, "init($flow)")
|
||||
initWithRequest(flow, null)
|
||||
}
|
||||
|
||||
@SuppressLint("SetWorldReadable")
|
||||
override fun initWithRequest(flow: String?, request: DroidGuardResultsRequest?): DroidGuardInitReply {
|
||||
Log.d(TAG, "initWithRequest($flow, $request)")
|
||||
this.flow = flow
|
||||
var handleProxy: HandleProxy? = null
|
||||
try {
|
||||
if (!LOW_LATENCY_ENABLED || flow in NOT_LOW_LATENCY_FLOWS) {
|
||||
handleProxy = null
|
||||
} else {
|
||||
try {
|
||||
handleProxy = factory.createLowLatencyHandle(flow, callback, request)
|
||||
Log.d(TAG, "Using low-latency handle")
|
||||
} catch (e: Exception) {
|
||||
Log.w(TAG, e)
|
||||
handleProxy = null
|
||||
}
|
||||
}
|
||||
if (handleProxy == null) {
|
||||
handleProxy = factory.createHandle(packageName, flow, callback, request)
|
||||
}
|
||||
if (handleProxy.init()) {
|
||||
this.handleProxy = handleProxy
|
||||
} else {
|
||||
throw Exception("init failed")
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
Log.w(TAG, "Error during handle init", e)
|
||||
this.handleInitError = e
|
||||
}
|
||||
this.condition.open()
|
||||
if (handleInitError == null) {
|
||||
try {
|
||||
val `object` = handleProxy!!.handle.javaClass.getDeclaredMethod("rb").invoke(handleProxy.handle) as? Parcelable?
|
||||
if (`object` != null) {
|
||||
val vmKey = handleProxy.vmKey
|
||||
val theApk = factory.getTheApkFile(vmKey)
|
||||
try {
|
||||
theApk.setReadable(true, false)
|
||||
return DroidGuardInitReply(ParcelFileDescriptor.open(theApk, ParcelFileDescriptor.MODE_READ_ONLY), `object`)
|
||||
} catch (e: FileNotFoundException) {
|
||||
throw Exception("Files for VM $vmKey not found on disk")
|
||||
}
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
this.handleProxy = null
|
||||
handleInitError = e
|
||||
}
|
||||
}
|
||||
return DroidGuardInitReply(null, null)
|
||||
}
|
||||
|
||||
override fun snapshot(map: MutableMap<Any?, Any?>): ByteArray {
|
||||
Log.d(TAG, "snapshot($map)")
|
||||
condition.block()
|
||||
handleInitError?.let { return FallbackCreator.create(flow, context, map, it) }
|
||||
val handleProxy = this.handleProxy ?: return FallbackCreator.create(flow, context, map, IllegalStateException())
|
||||
return try {
|
||||
handleProxy.handle::class.java.getDeclaredMethod("ss", Map::class.java).invoke(handleProxy.handle, map) as ByteArray
|
||||
} catch (e: Exception) {
|
||||
try {
|
||||
throw BytesException(handleProxy.extra, e)
|
||||
} catch (e2: Exception) {
|
||||
FallbackCreator.create(flow, context, map, e2)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun close() {
|
||||
Log.d(TAG, "close()")
|
||||
condition.block()
|
||||
try {
|
||||
handleProxy?.close()
|
||||
} catch (e: Exception) {
|
||||
Log.w(TAG, "Error during handle close", e)
|
||||
}
|
||||
handleProxy = null
|
||||
handleInitError = null
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val TAG = "GmsGuardHandleImpl"
|
||||
private val LOW_LATENCY_ENABLED = false
|
||||
private val NOT_LOW_LATENCY_FLOWS = setOf("ad_attest", "attest", "checkin", "federatedMachineLearningReduced", "msa-f", "ad-event-attest-token")
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,69 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2021 microG Project Team
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package org.microg.gms.droidguard.core
|
||||
|
||||
import android.content.ContentValues
|
||||
import android.content.Context
|
||||
import android.database.Cursor
|
||||
import androidx.core.database.getStringOrNull
|
||||
import org.microg.gms.settings.SettingsContract
|
||||
import org.microg.gms.settings.SettingsContract.DroidGuard.ENABLED
|
||||
import org.microg.gms.settings.SettingsContract.DroidGuard.FORCE_LOCAL_DISABLED
|
||||
import org.microg.gms.settings.SettingsContract.DroidGuard.HARDWARE_ATTESTATION_BLOCKED
|
||||
import org.microg.gms.settings.SettingsContract.DroidGuard.MODE
|
||||
import org.microg.gms.settings.SettingsContract.DroidGuard.NETWORK_SERVER_URL
|
||||
|
||||
object DroidGuardPreferences {
|
||||
|
||||
private fun <T> getSettings(context: Context, projection: String, def: T, f: (Cursor) -> T): T {
|
||||
return try {
|
||||
SettingsContract.getSettings(context, SettingsContract.DroidGuard.getContentUri(context), arrayOf(projection), f)
|
||||
} catch (e: Exception) {
|
||||
def
|
||||
}
|
||||
}
|
||||
|
||||
private fun setSettings(context: Context, f: ContentValues.() -> Unit) =
|
||||
SettingsContract.setSettings(context, SettingsContract.DroidGuard.getContentUri(context), f)
|
||||
|
||||
@JvmStatic
|
||||
fun isForcedLocalDisabled(context: Context): Boolean = getSettings(context, FORCE_LOCAL_DISABLED, false) { it.getInt(0) != 0 }
|
||||
|
||||
@JvmStatic
|
||||
fun isEnabled(context: Context): Boolean = getSettings(context, ENABLED, false) { it.getInt(0) != 0 }
|
||||
|
||||
@JvmStatic
|
||||
fun isAvailable(context: Context): Boolean = isEnabled(context) && (!isForcedLocalDisabled(context) || getMode(context) != Mode.Embedded)
|
||||
|
||||
@JvmStatic
|
||||
fun isLocalAvailable(context: Context): Boolean = isEnabled(context) && !isForcedLocalDisabled(context) && getMode(context) == Mode.Embedded
|
||||
|
||||
@JvmStatic
|
||||
fun setEnabled(context: Context, enabled: Boolean) = setSettings(context) { put(ENABLED, enabled) }
|
||||
|
||||
@JvmStatic
|
||||
fun getMode(context: Context): Mode = getSettings(context, MODE, Mode.Embedded) { c -> Mode.valueOf(c.getString(0)) }
|
||||
|
||||
@JvmStatic
|
||||
fun setMode(context: Context, mode: Mode) = setSettings(context) { put(MODE, mode.toString()) }
|
||||
|
||||
@JvmStatic
|
||||
fun getNetworkServerUrl(context: Context): String? = getSettings(context, NETWORK_SERVER_URL, null) { c -> c.getStringOrNull(0) }
|
||||
|
||||
@JvmStatic
|
||||
fun setNetworkServerUrl(context: Context, url: String?) = setSettings(context) { put(NETWORK_SERVER_URL, url) }
|
||||
|
||||
@JvmStatic
|
||||
fun isHardwareAttestationBlocked(context: Context) = getSettings(context, HARDWARE_ATTESTATION_BLOCKED, false) { it.getInt(0) != 0 }
|
||||
|
||||
@JvmStatic
|
||||
fun setHardwareAttestationBlocked(context: Context, value: Boolean) = setSettings(context) { put(HARDWARE_ATTESTATION_BLOCKED, value) }
|
||||
|
||||
enum class Mode {
|
||||
Embedded,
|
||||
Network
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2021, microG Project Team
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
package org.microg.gms.droidguard.core
|
||||
|
||||
import com.google.android.gms.droidguard.DroidGuardChimeraService
|
||||
import org.microg.gms.chimera.ServiceLoader
|
||||
import org.microg.gms.chimera.ServiceProxy
|
||||
|
||||
class DroidGuardService : ServiceProxy(ServiceLoader.static<DroidGuardChimeraService>())
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2021 microG Project Team
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package org.microg.gms.droidguard.core
|
||||
|
||||
import com.google.android.gms.common.internal.GetServiceRequest
|
||||
import com.google.android.gms.common.internal.IGmsCallbacks
|
||||
import com.google.android.gms.droidguard.DroidGuardChimeraService
|
||||
import org.microg.gms.AbstractGmsServiceBroker
|
||||
import org.microg.gms.common.GmsService
|
||||
import org.microg.gms.common.PackageUtils
|
||||
import java.util.*
|
||||
|
||||
class DroidGuardServiceBroker(val service: DroidGuardChimeraService) : AbstractGmsServiceBroker(EnumSet.of(GmsService.DROIDGUARD)) {
|
||||
|
||||
override fun getService(callback: IGmsCallbacks?, request: GetServiceRequest?) {
|
||||
handleServiceRequest(callback, request, null)
|
||||
}
|
||||
|
||||
override fun handleServiceRequest(callback: IGmsCallbacks?, request: GetServiceRequest?, service: GmsService?) {
|
||||
val packageName = PackageUtils.getAndCheckCallingPackageOrImpersonation(this.service, request!!.packageName)
|
||||
callback!!.onPostInitComplete(0, DroidGuardServiceImpl(this.service, packageName!!), null)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2021 microG Project Team
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package org.microg.gms.droidguard.core
|
||||
|
||||
import android.util.Log
|
||||
import com.google.android.gms.droidguard.DroidGuardChimeraService
|
||||
import com.google.android.gms.droidguard.internal.DroidGuardResultsRequest
|
||||
import com.google.android.gms.droidguard.internal.IDroidGuardCallbacks
|
||||
import com.google.android.gms.droidguard.internal.IDroidGuardHandle
|
||||
import com.google.android.gms.droidguard.internal.IDroidGuardService
|
||||
|
||||
class DroidGuardServiceImpl(private val service: DroidGuardChimeraService, private val packageName: String) : IDroidGuardService.Stub() {
|
||||
override fun guard(callbacks: IDroidGuardCallbacks?, flow: String?, map: MutableMap<Any?, Any?>?) {
|
||||
Log.d(TAG, "guard()")
|
||||
guardWithRequest(callbacks, flow, map, null)
|
||||
}
|
||||
|
||||
override fun guardWithRequest(callbacks: IDroidGuardCallbacks?, flow: String?, map: MutableMap<Any?, Any?>?, request: DroidGuardResultsRequest?) {
|
||||
Log.d(TAG, "guardWithRequest()")
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override fun getHandle(): IDroidGuardHandle {
|
||||
Log.d(TAG, "getHandle()")
|
||||
return when (DroidGuardPreferences.getMode(service)) {
|
||||
DroidGuardPreferences.Mode.Embedded -> DroidGuardHandleImpl(service, packageName, service.b, service.b(packageName))
|
||||
DroidGuardPreferences.Mode.Network -> RemoteHandleImpl(service, packageName)
|
||||
}
|
||||
}
|
||||
|
||||
override fun getClientTimeoutMillis(): Int {
|
||||
Log.d(TAG, "getClientTimeoutMillis()")
|
||||
return 60000
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val TAG = "GmsGuardServiceImpl"
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2021 microG Project Team
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package org.microg.gms.droidguard.core
|
||||
|
||||
import android.content.Context
|
||||
import android.util.Log
|
||||
|
||||
object FallbackCreator {
|
||||
private val FAST_FAIL = setOf("ad_attest", "recaptcha-frame", "federatedMachineLearningReduced", "msa-f", "ad-event-attest-token")
|
||||
|
||||
@JvmStatic
|
||||
fun create(flow: String?, context: Context, map: Map<Any?, Any?>, e: Throwable): ByteArray {
|
||||
Log.w("DGFallback", "create($flow)")
|
||||
return if (flow in FAST_FAIL) {
|
||||
"ERROR : no fallback for $flow".encodeToByteArray()
|
||||
} else {
|
||||
try {
|
||||
create(map, null, flow, context, e)
|
||||
} catch (e: Throwable) {
|
||||
Log.w("DGFallback", e)
|
||||
"ERROR : $e".encodeToByteArray()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun create(map: Map<Any?, Any?>, bytes: ByteArray?, flow: String?, context: Context, e: Throwable): ByteArray {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,101 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2025 microG Project Team
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* Notice: This is heavily inspired by "Universal SafetyNet Fix", used under the terms of MIT License,
|
||||
* Copyright (c) 2021 Danny Lin <danny@kdrag0n.dev>
|
||||
*/
|
||||
|
||||
package org.microg.gms.droidguard.core
|
||||
|
||||
import android.util.Log
|
||||
import androidx.annotation.Keep
|
||||
import java.io.InputStream
|
||||
import java.io.OutputStream
|
||||
import java.security.*
|
||||
import java.security.cert.Certificate
|
||||
import java.util.*
|
||||
|
||||
private const val TAG = "DroidGuard"
|
||||
|
||||
class HardwareAttestationBlockingProvider(
|
||||
realProvider: Provider,
|
||||
realSpi: KeyStoreSpi
|
||||
) : Provider(realProvider.name, realProvider.version, realProvider.info) {
|
||||
init {
|
||||
HardwareAttestationBlockingKeyStore.realSpi = realSpi
|
||||
this["KeyStore.$PROVIDER_NAME"] = HardwareAttestationBlockingKeyStore::class.java.name
|
||||
}
|
||||
|
||||
companion object {
|
||||
private var currentlyEnabled = false
|
||||
private lateinit var originalProvider: Provider
|
||||
private const val PROVIDER_NAME = "AndroidKeyStore"
|
||||
private const val FIELD_KEY_STORE_SPI = "keyStoreSpi"
|
||||
|
||||
@JvmStatic
|
||||
fun ensureEnabled(enabled: Boolean = true) {
|
||||
if (currentlyEnabled == enabled) return
|
||||
try {
|
||||
if (enabled) {
|
||||
Log.d(TAG, "Hardware attestation blocking enabled")
|
||||
originalProvider = Security.getProvider(PROVIDER_NAME)
|
||||
val realKeystore = KeyStore.getInstance(PROVIDER_NAME)
|
||||
val realSpi = realKeystore.get<KeyStoreSpi>(FIELD_KEY_STORE_SPI)
|
||||
|
||||
val newProvider = HardwareAttestationBlockingProvider(originalProvider, realSpi)
|
||||
Security.removeProvider(PROVIDER_NAME)
|
||||
Security.insertProviderAt(newProvider, 1)
|
||||
currentlyEnabled = true
|
||||
} else {
|
||||
Log.d(TAG, "Hardware attestation blocking disabled")
|
||||
Security.removeProvider(PROVIDER_NAME)
|
||||
Security.insertProviderAt(originalProvider, 1)
|
||||
currentlyEnabled = false
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
Log.w(TAG, "Failed replacing the security provider", e)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class HardwareAttestationBlockingKeyStore(private val realSpi: KeyStoreSpi) : KeyStoreSpi() {
|
||||
@Keep
|
||||
constructor() : this(Companion.realSpi ?: throw IllegalStateException())
|
||||
|
||||
override fun engineGetCertificateChain(alias: String?): Array<Certificate>? {
|
||||
for (stackTraceElement in Thread.currentThread().getStackTrace()) {
|
||||
if (stackTraceElement.className.lowercase().contains("droidguard")) {
|
||||
Log.d(TAG, "Block DroidGuard from accessing engineGetCertificateChain")
|
||||
throw UnsupportedOperationException()
|
||||
}
|
||||
}
|
||||
return realSpi.engineGetCertificateChain(alias)
|
||||
}
|
||||
|
||||
override fun engineGetKey(alias: String?, password: CharArray?): Key? = realSpi.engineGetKey(alias, password)
|
||||
override fun engineGetCertificate(alias: String?): Certificate? = realSpi.engineGetCertificate(alias)
|
||||
override fun engineGetCreationDate(alias: String?): Date? = realSpi.engineGetCreationDate(alias)
|
||||
override fun engineSetKeyEntry(alias: String?, key: Key?, password: CharArray?, chain: Array<out Certificate>?) = realSpi.engineSetKeyEntry(alias, key, password, chain)
|
||||
override fun engineSetKeyEntry(alias: String?, key: ByteArray?, chain: Array<out Certificate>?) = realSpi.engineSetKeyEntry(alias, key, chain)
|
||||
override fun engineSetCertificateEntry(alias: String?, cert: Certificate?) = realSpi.engineSetCertificateEntry(alias, cert)
|
||||
override fun engineDeleteEntry(alias: String?) = realSpi.engineDeleteEntry(alias)
|
||||
override fun engineAliases(): Enumeration<String>? = realSpi.engineAliases()
|
||||
override fun engineContainsAlias(alias: String?) = realSpi.engineContainsAlias(alias)
|
||||
override fun engineSize() = realSpi.engineSize()
|
||||
override fun engineIsKeyEntry(alias: String?) = realSpi.engineIsKeyEntry(alias)
|
||||
override fun engineIsCertificateEntry(alias: String?) = realSpi.engineIsCertificateEntry(alias)
|
||||
override fun engineGetCertificateAlias(cert: Certificate?): String? = realSpi.engineGetCertificateAlias(cert)
|
||||
override fun engineStore(stream: OutputStream?, password: CharArray?) = realSpi.engineStore(stream, password)
|
||||
override fun engineLoad(stream: InputStream?, password: CharArray?) = realSpi.engineLoad(stream, password)
|
||||
|
||||
companion object {
|
||||
var realSpi: KeyStoreSpi? = null
|
||||
}
|
||||
}
|
||||
|
||||
private fun <T> Any.get(name: String) = this::class.java.getDeclaredField(name).let { field ->
|
||||
field.isAccessible = true
|
||||
@Suppress("unchecked_cast")
|
||||
field.get(this) as T
|
||||
}
|
||||
|
|
@ -0,0 +1,177 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2021 microG Project Team
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package org.microg.gms.droidguard.core
|
||||
|
||||
import android.content.Context
|
||||
import com.android.volley.NetworkResponse
|
||||
import com.android.volley.VolleyError
|
||||
import com.android.volley.toolbox.RequestFuture
|
||||
import com.android.volley.toolbox.Volley
|
||||
import com.google.android.gms.droidguard.internal.DroidGuardResultsRequest
|
||||
import okio.ByteString.Companion.decodeHex
|
||||
import okio.ByteString.Companion.of
|
||||
import org.microg.gms.droidguard.*
|
||||
import org.microg.gms.profile.Build
|
||||
import org.microg.gms.profile.ProfileManager
|
||||
import org.microg.gms.utils.singleInstanceOf
|
||||
import java.io.File
|
||||
import java.util.*
|
||||
import com.android.volley.Request as VolleyRequest
|
||||
import com.android.volley.Response as VolleyResponse
|
||||
|
||||
class NetworkHandleProxyFactory(private val context: Context) : HandleProxyFactory(context) {
|
||||
private val dgDb: DgDatabaseHelper = DgDatabaseHelper(context)
|
||||
private val version = VersionUtil(context)
|
||||
private val queue = singleInstanceOf { Volley.newRequestQueue(context.applicationContext) }
|
||||
|
||||
fun createHandle(packageName: String, flow: String?, callback: GuardCallback, request: DroidGuardResultsRequest?): HandleProxy {
|
||||
if (!DroidGuardPreferences.isLocalAvailable(context)) throw IllegalAccessException("DroidGuard should not be available locally")
|
||||
val (vmKey, byteCode, bytes) = readFromDatabase(flow) ?: fetchFromServer(flow, packageName)
|
||||
return createHandleProxy(flow, vmKey, byteCode, bytes, callback, request)
|
||||
}
|
||||
|
||||
fun createPingHandle(packageName: String, flow: String, callback: GuardCallback, pingData: PingData?): HandleProxy {
|
||||
if (!DroidGuardPreferences.isLocalAvailable(context)) throw IllegalAccessException("DroidGuard should not be available locally")
|
||||
val (vmKey, byteCode, bytes) = fetchFromServer(flow, createRequest(flow, packageName, pingData))
|
||||
return createHandleProxy(flow, vmKey, byteCode, bytes, callback, DroidGuardResultsRequest().also { it.clientVersion = 0 })
|
||||
}
|
||||
|
||||
fun createLowLatencyHandle(flow: String?, callback: GuardCallback, request: DroidGuardResultsRequest?): HandleProxy {
|
||||
if (!DroidGuardPreferences.isLocalAvailable(context)) throw IllegalAccessException("DroidGuard should not be available locally")
|
||||
val (vmKey, byteCode, bytes) = readFromDatabase("fast") ?: throw Exception("low latency (fast) flow not available")
|
||||
return createHandleProxy(flow, vmKey, byteCode, bytes, callback, request)
|
||||
}
|
||||
|
||||
fun SignedResponse.unpack(): Response {
|
||||
if (SignatureVerifier.verifySignature(data_!!.toByteArray(), signature!!.toByteArray())) {
|
||||
return Response.ADAPTER.decode(data_!!)
|
||||
} else {
|
||||
throw SecurityException("Signature invalid")
|
||||
}
|
||||
}
|
||||
|
||||
private fun readFromDatabase(flow: String?): Triple<String, ByteArray, ByteArray>? {
|
||||
ProfileManager.ensureInitialized(context)
|
||||
val id = "$flow/${version.versionString}/${Build.FINGERPRINT}"
|
||||
return dgDb.get(id)
|
||||
}
|
||||
|
||||
fun createRequest(flow: String?, packageName: String, pingData: PingData? = null, extra: ByteArray? = null): Request {
|
||||
ProfileManager.ensureInitialized(context)
|
||||
return Request(
|
||||
usage = Usage(flow, packageName),
|
||||
info = listOf(
|
||||
KeyValuePair("BOARD", Build.BOARD),
|
||||
KeyValuePair("BOOTLOADER", Build.BOOTLOADER),
|
||||
KeyValuePair("BRAND", Build.BRAND),
|
||||
KeyValuePair("CPU_ABI", Build.CPU_ABI),
|
||||
KeyValuePair("CPU_ABI2", Build.CPU_ABI2),
|
||||
KeyValuePair("SUPPORTED_ABIS", Build.SUPPORTED_ABIS.joinToString(",")),
|
||||
KeyValuePair("DEVICE", Build.DEVICE),
|
||||
KeyValuePair("DISPLAY", Build.DISPLAY),
|
||||
KeyValuePair("FINGERPRINT", Build.FINGERPRINT),
|
||||
KeyValuePair("HARDWARE", Build.HARDWARE),
|
||||
KeyValuePair("HOST", Build.HOST),
|
||||
KeyValuePair("ID", Build.ID),
|
||||
KeyValuePair("MANUFACTURER", Build.MANUFACTURER),
|
||||
KeyValuePair("MODEL", Build.MODEL),
|
||||
KeyValuePair("PRODUCT", Build.PRODUCT),
|
||||
KeyValuePair("RADIO", Build.RADIO),
|
||||
KeyValuePair("SERIAL", Build.SERIAL),
|
||||
KeyValuePair("TAGS", Build.TAGS),
|
||||
KeyValuePair("TIME", Build.TIME.toString()),
|
||||
KeyValuePair("TYPE", Build.TYPE),
|
||||
KeyValuePair("USER", Build.USER),
|
||||
KeyValuePair("VERSION.CODENAME", Build.VERSION.CODENAME),
|
||||
KeyValuePair("VERSION.INCREMENTAL", Build.VERSION.INCREMENTAL),
|
||||
KeyValuePair("VERSION.RELEASE", Build.VERSION.RELEASE),
|
||||
KeyValuePair("VERSION.SDK", Build.VERSION.SDK),
|
||||
KeyValuePair("VERSION.SDK_INT", Build.VERSION.SDK_INT.toString()),
|
||||
),
|
||||
versionName = version.versionString,
|
||||
versionCode = BuildConfig.VERSION_CODE,
|
||||
hasAccount = false,
|
||||
isGoogleCn = false,
|
||||
enableInlineVm = true,
|
||||
cached = getCacheDir().list()?.map { it.decodeHex() }.orEmpty(),
|
||||
arch = System.getProperty("os.arch"),
|
||||
ping = pingData,
|
||||
field10 = extra?.let { of(*it) },
|
||||
)
|
||||
}
|
||||
|
||||
fun fetchFromServer(flow: String?, packageName: String): Triple<String, ByteArray, ByteArray> {
|
||||
return fetchFromServer(flow, createRequest(flow, packageName))
|
||||
}
|
||||
|
||||
fun fetchFromServer(flow: String?, request: Request): Triple<String, ByteArray, ByteArray> {
|
||||
ProfileManager.ensureInitialized(context)
|
||||
val future = RequestFuture.newFuture<SignedResponse>()
|
||||
queue.add(object : VolleyRequest<SignedResponse>(Method.POST, SERVER_URL, future) {
|
||||
override fun parseNetworkResponse(response: NetworkResponse): VolleyResponse<SignedResponse> {
|
||||
return try {
|
||||
VolleyResponse.success(SignedResponse.ADAPTER.decode(response.data), null)
|
||||
} catch (e: Exception) {
|
||||
VolleyResponse.error(VolleyError(e))
|
||||
}
|
||||
}
|
||||
|
||||
override fun deliverResponse(response: SignedResponse) {
|
||||
future.onResponse(response)
|
||||
}
|
||||
|
||||
override fun getBody(): ByteArray = request.encode()
|
||||
|
||||
override fun getBodyContentType(): String = "application/x-protobuf"
|
||||
|
||||
override fun getHeaders(): Map<String, String> {
|
||||
return mapOf(
|
||||
"User-Agent" to "DroidGuard/${version.versionCode}"
|
||||
)
|
||||
}
|
||||
})
|
||||
val signed: SignedResponse = future.get()
|
||||
val response = signed.unpack()
|
||||
val vmKey = response.vmChecksum!!.hex()
|
||||
if (!isValidCache(vmKey)) {
|
||||
val temp = File(getCacheDir(), "${UUID.randomUUID()}.apk")
|
||||
temp.parentFile!!.mkdirs()
|
||||
temp.writeBytes(response.content!!.toByteArray())
|
||||
getOptDir(vmKey).mkdirs()
|
||||
temp.renameTo(getTheApkFile(vmKey))
|
||||
updateCacheTimestamp(vmKey)
|
||||
if (!isValidCache(vmKey)) {
|
||||
getCacheDir(vmKey).deleteRecursively()
|
||||
throw IllegalStateException()
|
||||
}
|
||||
}
|
||||
val id = "$flow/${version.versionString}/${Build.FINGERPRINT}"
|
||||
val expiry = (response.expiryTimeSecs ?: 0).toLong()
|
||||
val byteCode = response.byteCode?.toByteArray() ?: ByteArray(0)
|
||||
val extra = response.extra?.toByteArray() ?: ByteArray(0)
|
||||
if (response.save != false) {
|
||||
dgDb.put(id, expiry, vmKey, byteCode, extra)
|
||||
}
|
||||
return Triple(vmKey, byteCode, extra)
|
||||
}
|
||||
|
||||
private fun createHandleProxy(
|
||||
flow: String?,
|
||||
vmKey: String,
|
||||
byteCode: ByteArray,
|
||||
extra: ByteArray,
|
||||
callback: GuardCallback,
|
||||
request: DroidGuardResultsRequest?
|
||||
): HandleProxy {
|
||||
ProfileManager.ensureInitialized(context)
|
||||
val clazz = loadClass(vmKey, extra)
|
||||
return HandleProxy(clazz, context, flow, byteCode, callback, vmKey, extra, request?.bundle)
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val SERVER_URL = "https://www.googleapis.com/androidantiabuse/v1/x/create?alt=PROTO&key=AIzaSyBofcZsgLSS7BOnBjZPEkk4rYwzOIz-lTI"
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,62 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2025 microG Project Team
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package org.microg.gms.droidguard.core
|
||||
|
||||
import android.content.Context
|
||||
import android.net.Uri
|
||||
import android.util.Base64
|
||||
import com.google.android.gms.droidguard.internal.DroidGuardInitReply
|
||||
import com.google.android.gms.droidguard.internal.DroidGuardResultsRequest
|
||||
import com.google.android.gms.droidguard.internal.IDroidGuardHandle
|
||||
import android.util.Log
|
||||
import java.net.HttpURLConnection
|
||||
import java.net.URL
|
||||
|
||||
private const val TAG = "RemoteGuardImpl"
|
||||
|
||||
class RemoteHandleImpl(private val context: Context, private val packageName: String) : IDroidGuardHandle.Stub() {
|
||||
private var flow: String? = null
|
||||
private var request: DroidGuardResultsRequest? = null
|
||||
private val url: String
|
||||
get() = DroidGuardPreferences.getNetworkServerUrl(context) ?: throw IllegalStateException("Network URL required")
|
||||
|
||||
override fun init(flow: String?) {
|
||||
Log.d(TAG, "init($flow)")
|
||||
this.flow = flow
|
||||
}
|
||||
|
||||
override fun snapshot(map: Map<Any?, Any?>?): ByteArray {
|
||||
Log.d(TAG, "snapshot($map)")
|
||||
val paramsMap = mutableMapOf("flow" to flow, "source" to packageName)
|
||||
for (key in request?.bundle?.keySet().orEmpty()) {
|
||||
request?.bundle?.getString(key)?.let { paramsMap["x-request-$key"] = it }
|
||||
}
|
||||
val params = paramsMap.map { Uri.encode(it.key) + "=" + Uri.encode(it.value) }.joinToString("&")
|
||||
val connection = URL("$url?$params").openConnection() as HttpURLConnection
|
||||
val payload = map.orEmpty().map { Uri.encode(it.key as String) + "=" + Uri.encode(it.value as String) }.joinToString("&")
|
||||
Log.d(TAG, "POST ${connection.url}: $payload")
|
||||
connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8")
|
||||
connection.requestMethod = "POST"
|
||||
connection.doInput = true
|
||||
connection.doOutput = true
|
||||
connection.outputStream.use { it.write(payload.encodeToByteArray()) }
|
||||
val bytes = connection.inputStream.use { it.readBytes() }.decodeToString()
|
||||
return Base64.decode(bytes, Base64.URL_SAFE + Base64.NO_WRAP + Base64.NO_PADDING)
|
||||
}
|
||||
|
||||
override fun close() {
|
||||
Log.d(TAG, "close()")
|
||||
this.request = null
|
||||
this.flow = null
|
||||
}
|
||||
|
||||
override fun initWithRequest(flow: String?, request: DroidGuardResultsRequest?): DroidGuardInitReply? {
|
||||
Log.d(TAG, "initWithRequest($flow, $request)")
|
||||
this.flow = flow
|
||||
this.request = request
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2021 microG Project Team
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package org.microg.gms.droidguard.core
|
||||
|
||||
import android.util.Base64
|
||||
import android.util.Log
|
||||
import java.security.KeyFactory
|
||||
import java.security.Signature
|
||||
import java.security.spec.X509EncodedKeySpec
|
||||
|
||||
object SignatureVerifier {
|
||||
const val TAG = "GmsGuardSigVerify"
|
||||
const val PUBLIC_KEY = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxW77dCKJ8mhEIfXXdeidi7/7LMNM/fzwI+wj1Ed8xIKgTYWCnekRko3JxQb4Cv/gEL5hEA8e9lFs3V67VUL6hCo1FxysXj7Q8n3Kp7hARDkbiZ0mdk8bSanqrPAXTPx6pEL2ZOzfFCHEtJdhz5Ozp2C4XTKF1SBv/YbpsqSUJwdhG7ZPGjyCMRloMww6ITpGdVQ8lChklkCek0WPbz2UrY5RC1qIJKmmcB6KNxxE776Dn6QoYbhN5jPeVBp7lDD3UxjfVzTxKKDAome6fUVBop3dpcLM6rq3+nNT2YArgqTD1qtsVM9vHlcLaAYaPg82vtIN80iDUseMlVHgK+nf6wIDAQAB"
|
||||
|
||||
fun verifySignature(data: ByteArray, signature: ByteArray): Boolean {
|
||||
try {
|
||||
val keyFactory = KeyFactory.getInstance("RSA") ?: return false
|
||||
val sig = Signature.getInstance("SHA256withRSA") ?: return false
|
||||
val keySpec = X509EncodedKeySpec(Base64.decode(PUBLIC_KEY, 0))
|
||||
sig.initVerify(keyFactory.generatePublic(keySpec))
|
||||
sig.update(data)
|
||||
return sig.verify(signature)
|
||||
} catch (e: Exception) {
|
||||
Log.w(TAG, e)
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,76 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2021 microG Project Team
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package org.microg.gms.droidguard.core
|
||||
|
||||
import android.content.Context
|
||||
import org.microg.gms.profile.Build
|
||||
import org.microg.gms.profile.ProfileManager
|
||||
|
||||
class VersionUtil(private val context: Context) {
|
||||
val buildType: String
|
||||
get() {
|
||||
ProfileManager.ensureInitialized(context)
|
||||
// Note: Android TV and Watch use different version codes
|
||||
val versionCode = when (Build.VERSION.SDK_INT) {
|
||||
31 -> "19"
|
||||
30 -> "15"
|
||||
29 -> "12"
|
||||
28 -> "10"
|
||||
23, 24, 25, 26, 27 -> "04"
|
||||
21, 22 -> "02"
|
||||
else -> "00"
|
||||
}
|
||||
val architectureCode = when (Build.CPU_ABI) {
|
||||
"x86_64" -> "08"
|
||||
"x86" -> "07"
|
||||
"arm64-v8a" -> "04"
|
||||
"arm", "armeabi", "armeabi-v7a" -> "03"
|
||||
else -> "00"
|
||||
}
|
||||
val dpiCode = when (context.resources.displayMetrics.densityDpi) { // TODO: Also something to get from profile
|
||||
160 -> "02"
|
||||
240 -> "04"
|
||||
320 -> "06"
|
||||
480 -> "08"
|
||||
else -> "00"
|
||||
}
|
||||
val type = "$versionCode$architectureCode$dpiCode"
|
||||
if (isKnown(type)) return type
|
||||
val nodpi = "$versionCode${architectureCode}00"
|
||||
if (isKnown(nodpi)) return nodpi // Fallback to nodpi for increased compat
|
||||
return type // Use unknown build type
|
||||
}
|
||||
val versionString: String
|
||||
get() = "${BuildConfig.VERSION_NAME} ($buildType-{{cl}})"
|
||||
val versionCode: Int
|
||||
get() = BuildConfig.VERSION_CODE + (getVersionOffset(buildType) ?: 0)
|
||||
|
||||
fun isKnown(type: String): Boolean = getVersionOffset(type) != null
|
||||
|
||||
fun getVersionOffset(type: String): Int? {
|
||||
val v1 = type.substring(0, 2)
|
||||
val v2 = type.substring(2, 4)
|
||||
val v3 = type.substring(4, 6)
|
||||
val i1 = BUILD_MAP.indexOfFirst { it.first == v1 }.takeIf { it >= 0 } ?: return null
|
||||
val i2 = BUILD_MAP[i1].second.indexOfFirst { it.first == v2 }.takeIf { it >= 0 } ?: return null
|
||||
val i3 = BUILD_MAP[i1].second[i2].second.indexOf(v3).takeIf { it > 0 } ?: return null
|
||||
val o1 = BUILD_MAP.subList(0, i1).map { it.second.map { it.second.size }.sum() }.sum()
|
||||
val o2 = BUILD_MAP[i1].second.subList(0, i2).map { it.second.size }.sum()
|
||||
return o1 + o2 + i3
|
||||
}
|
||||
|
||||
companion object {
|
||||
val BUILD_MAP = listOf(
|
||||
"00" to listOf("03" to listOf("00", "02", "04", "06", "08"), "07" to listOf("00")),
|
||||
"02" to listOf("03" to listOf("00", "04", "06", "08"), "04" to listOf("00", "06", "08"), "07" to listOf("00"), "08" to listOf("00")),
|
||||
"04" to listOf("03" to listOf("00", "04", "06", "08"), "04" to listOf("00", "06", "08"), "07" to listOf("00"), "08" to listOf("00")),
|
||||
"10" to listOf("03" to listOf("00", "04", "06", "08"), "04" to listOf("00", "06", "08"), "07" to listOf("00"), "08" to listOf("00")),
|
||||
"12" to listOf("03" to listOf("00", "04", "06", "08"), "04" to listOf("00", "06", "08"), "07" to listOf("00"), "08" to listOf("00")),
|
||||
"15" to listOf("03" to listOf("00", "04", "06", "08"), "04" to listOf("00", "06", "08"), "07" to listOf("00"), "08" to listOf("00")),
|
||||
"19" to listOf("03" to listOf("00", "08"), "04" to listOf("00", "08"), "07" to listOf("00"), "08" to listOf("00")),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,70 @@
|
|||
/*
|
||||
* 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
|
||||
import org.microg.gms.droidguard.core.R
|
||||
|
||||
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<EditText>(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
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,66 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2022 microG Project Team
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package org.microg.gms.droidguard.core.ui
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.os.Bundle
|
||||
import androidx.preference.Preference
|
||||
import androidx.preference.PreferenceFragmentCompat
|
||||
import androidx.preference.TwoStatePreference
|
||||
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.R
|
||||
import org.microg.gms.base.core.R.drawable.ic_radio_checked
|
||||
import org.microg.gms.base.core.R.drawable.ic_radio_unchecked
|
||||
|
||||
class DroidGuardPreferencesFragment : PreferenceFragmentCompat() {
|
||||
private lateinit var modeEmbedded: Preference
|
||||
private lateinit var modeNetwork: ContainedEditTextPreference
|
||||
private lateinit var blockHardwareAttestation: TwoStatePreference
|
||||
|
||||
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
|
||||
addPreferencesFromResource(R.xml.preferences_droidguard)
|
||||
}
|
||||
|
||||
@SuppressLint("RestrictedApi")
|
||||
override fun onBindPreferences() {
|
||||
modeEmbedded = preferenceScreen.findPreference("pref_droidguard_mode_embedded") ?: modeEmbedded
|
||||
modeNetwork = preferenceScreen.findPreference("pref_droidguard_mode_network") ?: modeNetwork
|
||||
blockHardwareAttestation = preferenceScreen.findPreference("pref_droidguard_block_hw_attestation") ?: blockHardwareAttestation
|
||||
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)
|
||||
}
|
||||
blockHardwareAttestation.setOnPreferenceChangeListener { _, newValue ->
|
||||
DroidGuardPreferences.setHardwareAttestationBlocked(requireContext(), newValue as Boolean)
|
||||
true
|
||||
}
|
||||
modeEmbedded.isEnabled = !DroidGuardPreferences.isForcedLocalDisabled(requireContext())
|
||||
blockHardwareAttestation.isChecked = DroidGuardPreferences.isHardwareAttestationBlocked(requireContext())
|
||||
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/"
|
||||
blockHardwareAttestation.isEnabled = mode == Embedded
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,73 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2016, microG Project Team
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
option java_package = "org.microg.gms.droidguard";
|
||||
|
||||
message Usage {
|
||||
optional string flow = 1;
|
||||
optional string packageName = 2;
|
||||
}
|
||||
|
||||
message KeyValuePair {
|
||||
optional string key = 1;
|
||||
optional string val = 2;
|
||||
}
|
||||
|
||||
message StackTraceElement {
|
||||
optional string className = 1;
|
||||
optional string methodName = 2;
|
||||
optional string fileName = 3;
|
||||
optional int32 lineNumber = 4;
|
||||
optional bool isNativeMethod = 5;
|
||||
}
|
||||
|
||||
message ExceptionInfo {
|
||||
optional string name = 1;
|
||||
optional string message = 2;
|
||||
repeated StackTraceElement stackTrace = 3;
|
||||
}
|
||||
|
||||
message ExceptionList {
|
||||
repeated ExceptionInfo exceptions = 1;
|
||||
}
|
||||
|
||||
message PingData {
|
||||
optional string field1 = 1;
|
||||
optional int64 field2 = 2;
|
||||
}
|
||||
|
||||
message Request {
|
||||
optional Usage usage = 1;
|
||||
repeated KeyValuePair info = 2;
|
||||
optional string versionName = 3;
|
||||
optional bool hasAccount = 6;
|
||||
optional bool isGoogleCn = 7;
|
||||
optional bool enableInlineVm = 8;
|
||||
repeated bytes cached = 9;
|
||||
optional bytes field10 = 10;
|
||||
optional int32 field11 = 11;
|
||||
optional ExceptionList exceptions = 12;
|
||||
optional int32 versionCode = 13;
|
||||
optional string arch = 14;
|
||||
optional int32 field15 = 15;
|
||||
optional PingData ping = 16;
|
||||
}
|
||||
|
||||
message SignedResponse {
|
||||
optional bytes data = 1;
|
||||
optional bytes signature = 2;
|
||||
}
|
||||
|
||||
message Response {
|
||||
optional bytes byteCode = 1;
|
||||
optional string vmUrl = 2;
|
||||
optional bytes vmChecksum = 3;
|
||||
optional int32 expiryTimeSecs = 4;
|
||||
optional bytes content = 5;
|
||||
optional bool save = 6;
|
||||
optional int32 minWait = 7;
|
||||
optional int32 maxWait = 8;
|
||||
optional bytes extra = 9;
|
||||
}
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
~ SPDX-FileCopyrightText: 2021 microG Project Team
|
||||
~ SPDX-License-Identifier: Apache-2.0
|
||||
-->
|
||||
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
|
||||
<EditText
|
||||
android:id="@android:id/edit"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:focusedByDefault="false"
|
||||
android:inputType="textUri"
|
||||
android:lines="1"
|
||||
android:maxLines="1" />
|
||||
</LinearLayout>
|
||||
|
|
@ -0,0 +1,75 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
~ Copyright (C) 2015 The Android Open Source Project
|
||||
~
|
||||
~ 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
|
||||
-->
|
||||
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:minHeight="?android:attr/listPreferredItemHeightSmall"
|
||||
android:gravity="center_vertical"
|
||||
android:paddingLeft="?android:attr/listPreferredItemPaddingLeft"
|
||||
android:paddingStart="?android:attr/listPreferredItemPaddingStart"
|
||||
android:paddingRight="?android:attr/listPreferredItemPaddingRight"
|
||||
android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
|
||||
android:background="?android:attr/selectableItemBackground"
|
||||
android:clipToPadding="false"
|
||||
android:baselineAligned="false">
|
||||
|
||||
<include layout="@layout/image_frame"/>
|
||||
|
||||
<RelativeLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:paddingTop="16dp"
|
||||
android:paddingBottom="16dp">
|
||||
|
||||
<TextView
|
||||
android:id="@android:id/title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:singleLine="true"
|
||||
android:textAppearance="?android:attr/textAppearanceListItem"
|
||||
android:ellipsize="marquee"/>
|
||||
|
||||
<TextView
|
||||
android:id="@android:id/summary"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@android:id/title"
|
||||
android:layout_alignLeft="@android:id/title"
|
||||
android:layout_alignStart="@android:id/title"
|
||||
android:layout_gravity="start"
|
||||
android:textAlignment="viewStart"
|
||||
android:textColor="?android:attr/textColorSecondary"
|
||||
android:maxLines="10"
|
||||
style="@style/PreferenceSummaryTextStyle"/>
|
||||
|
||||
|
||||
<!-- Preference should place its actual preference widget here. -->
|
||||
<LinearLayout
|
||||
android:id="@android:id/widget_frame"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@android:id/summary"
|
||||
android:layout_alignLeft="@android:id/title"
|
||||
android:layout_alignStart="@android:id/title"
|
||||
android:gravity="end|center_vertical"
|
||||
android:orientation="vertical"/>
|
||||
</RelativeLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="prefcat_droidguard_mode">وضع تشغيل درويدغارد</string>
|
||||
<string name="pref_droidguard_mode_embedded_title">مدمج</string>
|
||||
<string name="pref_droidguard_mode_embedded_summary">استخدم نظام تنفيد درويدغارد المحلي</string>
|
||||
<string name="pref_droidguard_mode_network_title">عن بعد</string>
|
||||
<string name="pref_droidguard_mode_network_summary">اتصل بنظام تنفيذ درويدغارد عبر الشبكة</string>
|
||||
</resources>
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources></resources>
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="pref_droidguard_mode_network_summary">Şəbəkə vasitəsilə DroidGuard iş vaxtına qoşul</string>
|
||||
<string name="prefcat_droidguard_mode">DroidGuard iş rejimi</string>
|
||||
<string name="pref_droidguard_mode_embedded_title">Daxili</string>
|
||||
<string name="pref_droidguard_mode_embedded_summary">Yerli DroidGuard iş vaxtın istifadə et</string>
|
||||
<string name="pref_droidguard_mode_network_title">Uzaqdan</string>
|
||||
</resources>
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
~ SPDX-FileCopyrightText: 2021 microG Project Team
|
||||
~ SPDX-License-Identifier: Apache-2.0
|
||||
-->
|
||||
<resources>
|
||||
<string name="prefcat_droidguard_mode">Рэжым работы DroidGuard</string>
|
||||
<string name="pref_droidguard_mode_embedded_title">Лакальны</string>
|
||||
<string name="pref_droidguard_mode_embedded_summary">Выкарыстоўваць лакальнае асяроддзе выканання DroidGuard</string>
|
||||
<string name="pref_droidguard_mode_network_title">Выдалены</string>
|
||||
<string name="pref_droidguard_mode_network_summary">Падключыцца да асяроддзя выканання DroidGuard па сетцы</string>
|
||||
</resources>
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="pref_droidguard_mode_embedded_summary">Použít místní běhové prostředí DroidGuard</string>
|
||||
<string name="pref_droidguard_mode_network_summary">Připojit se k běhovému prostředí DroidGuard pomocí sítě</string>
|
||||
<string name="prefcat_droidguard_mode">Režim operace DroidGuard</string>
|
||||
<string name="pref_droidguard_mode_embedded_title">Vložený</string>
|
||||
<string name="pref_droidguard_mode_network_title">Vzdálený</string>
|
||||
<string name="pref_droidguard_block_hw_attestation_title">Blokovat hardwarovou atestaci</string>
|
||||
<string name="pref_droidguard_block_hw_attestation_summary">Při používání vložené služby DroidGuard zakázat přístup k hardwarové atestaci. Může pomoci projít kontrolami integrity na některých zařízeních.</string>
|
||||
</resources>
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="prefcat_droidguard_mode">DroidGuard-Betriebsmodus</string>
|
||||
<string name="pref_droidguard_mode_embedded_title">Eingebettet</string>
|
||||
<string name="pref_droidguard_mode_embedded_summary">Lokale DroidGuard-Laufzeit verwenden</string>
|
||||
<string name="pref_droidguard_mode_network_summary">Über das Netzwerk mit der DroidGuard-Laufzeit verbinden</string>
|
||||
<string name="pref_droidguard_mode_network_title">Externe</string>
|
||||
<string name="pref_droidguard_block_hw_attestation_title">Hardware-Attestierung blockieren</string>
|
||||
<string name="pref_droidguard_block_hw_attestation_summary">Bei Verwendung des integrierten DroidGuard den Zugriff auf die Hardware-Attestierung deaktivieren. Dies kann dazu beitragen, dass Integritätsprüfungen auf einigen Geräten erfolgreich durchgeführt werden können.</string>
|
||||
</resources>
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources></resources>
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="prefcat_droidguard_mode">Modo de funcionamiento de DroidGuard</string>
|
||||
<string name="pref_droidguard_mode_network_summary">Conectar a DroidGuard el tiempo de ejecución a través de la red</string>
|
||||
<string name="pref_droidguard_mode_embedded_title">Incorporado</string>
|
||||
<string name="pref_droidguard_mode_embedded_summary">Utilice el tiempo de ejecución local de DroidGuard</string>
|
||||
<string name="pref_droidguard_mode_network_title">A distancia</string>
|
||||
</resources>
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="prefcat_droidguard_mode">حالت عملکرد DroidGuard</string>
|
||||
<string name="pref_droidguard_mode_embedded_title">جاسازی شده</string>
|
||||
<string name="pref_droidguard_mode_embedded_summary">استفاده از زمان اجرا محلی DroidGuard</string>
|
||||
<string name="pref_droidguard_mode_network_title">راه دور</string>
|
||||
<string name="pref_droidguard_mode_network_summary">اتصال به زمان اجرا DroidGuard با شبکه</string>
|
||||
<string name="pref_droidguard_block_hw_attestation_title">تأییدیه بلوک سخت افزار</string>
|
||||
<string name="pref_droidguard_block_hw_attestation_summary">زمانی که از DroidGuard جاسازی شده استفاده میکنید، دسترسی به تأییدیه سخت افزار را غیرفعال کنید. این کار ممکن است به قبولی در بررسیهای یکپارچگی، در برخی دستگاه ها کمک کند.</string>
|
||||
</resources>
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources></resources>
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="pref_droidguard_mode_embedded_summary">Gamitin ang lokal na DroidGuard runtime</string>
|
||||
<string name="pref_droidguard_mode_network_summary">Kumonekta sa DroidGuard runtime sa pamamagitan ng network</string>
|
||||
<string name="pref_droidguard_mode_network_title">Remote</string>
|
||||
<string name="prefcat_droidguard_mode">Mode ng operasyon ng DroidGuard</string>
|
||||
<string name="pref_droidguard_mode_embedded_title">Naka-embed</string>
|
||||
<string name="pref_droidguard_block_hw_attestation_title">Harangan ang pagpapatunay gamit ng hardware</string>
|
||||
<string name="pref_droidguard_block_hw_attestation_summary">Kapag gumagamit ng embedded na DroidGuard, i-disable ang access sa hardware na pagpapatunay. Maaaring makatulong sa pagpasa ng mga pagsusuri sa integridad sa ilang device.</string>
|
||||
</resources>
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="prefcat_droidguard_mode">Mode d\'opération DroidGuard</string>
|
||||
<string name="pref_droidguard_mode_embedded_title">Embarqué</string>
|
||||
<string name="pref_droidguard_mode_network_title">A distance</string>
|
||||
<string name="pref_droidguard_mode_embedded_summary">Exécuter localement DroidGuard</string>
|
||||
<string name="pref_droidguard_mode_network_summary">Exécuter DroidGuard via une connexion réseau</string>
|
||||
<string name="pref_droidguard_block_hw_attestation_title">Bloquer l\'attestation matérielle</string>
|
||||
<string name="pref_droidguard_block_hw_attestation_summary">Désactive l’accès à l’attestation matérielle quand DroidGuard embarqué est utilisé. Peut aider à passer les vérifications d\'intégrité sur certains appareils.</string>
|
||||
</resources>
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="pref_droidguard_mode_network_summary">Ceangail le ham rite DroidGuard tríd an líonra</string>
|
||||
<string name="pref_droidguard_mode_network_title">Cianda</string>
|
||||
<string name="prefcat_droidguard_mode">Modh oibríochta DroidGuard</string>
|
||||
<string name="pref_droidguard_mode_embedded_title">Leabaithe</string>
|
||||
<string name="pref_droidguard_mode_embedded_summary">Úsáid am rite áitiúil DroidGuard</string>
|
||||
<string name="pref_droidguard_block_hw_attestation_title">Deimhniú crua-earraí bloc</string>
|
||||
<string name="pref_droidguard_block_hw_attestation_summary">Agus DroidGuard leabaithe in úsáid agat, díchumasaigh rochtain ar dheimhniú crua-earraí. D’fhéadfadh sé seo cabhrú le seiceálacha sláine a rith ar roinnt gléasanna.</string>
|
||||
</resources>
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="prefcat_droidguard_mode">Mode operasi DroidGuard</string>
|
||||
<string name="pref_droidguard_mode_embedded_summary">Gunakan runtime DroidGuard lokal</string>
|
||||
<string name="pref_droidguard_mode_embedded_title">Tertanam</string>
|
||||
<string name="pref_droidguard_mode_network_title">Jarak jauh</string>
|
||||
<string name="pref_droidguard_mode_network_summary">Hubungkan ke runtime DroidGuard melalui jaringan</string>
|
||||
<string name="pref_droidguard_block_hw_attestation_title">Blokir pengesahan perangkat keras</string>
|
||||
<string name="pref_droidguard_block_hw_attestation_summary">Saat menggunakan DroidGuard yang terintegrasi, nonaktifkan akses ke pengesahan perangkat keras. Hal ini mungkin membantu melewati pemeriksaan integritas pada beberapa perangkat.</string>
|
||||
</resources>
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="prefcat_droidguard_mode">Virknihamur DroidGuard</string>
|
||||
<string name="pref_droidguard_mode_embedded_title">Ívafið</string>
|
||||
<string name="pref_droidguard_mode_network_title">Fjartengt</string>
|
||||
<string name="pref_droidguard_mode_embedded_summary">Nota staðbundna DroidGuard-keyrsluskrá</string>
|
||||
<string name="pref_droidguard_mode_network_summary">Tengjast DroidGuard-keyrsluskrá í gegnum netkerfi</string>
|
||||
<string name="pref_droidguard_block_hw_attestation_title">Loka á sannvottun vélbúnaðar</string>
|
||||
<string name="pref_droidguard_block_hw_attestation_summary">Þegar verið er að nota ívafið DroidGuard (embedded), skal gera sannvottun vélbúnaðar (hardware attestation) óvirka. Þetta gæti hjálpað til við að standast áreiðanleikaprófanir á sumum tækjum.</string>
|
||||
</resources>
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="prefcat_droidguard_mode">Modalità operativa di DroidGuard</string>
|
||||
<string name="pref_droidguard_mode_embedded_title">Integrata</string>
|
||||
<string name="pref_droidguard_mode_embedded_summary">Utilizza il runtime locale di DroidGuard</string>
|
||||
<string name="pref_droidguard_mode_network_title">Remota</string>
|
||||
<string name="pref_droidguard_mode_network_summary">Effettua la connessione al runtime di DroidGuard attraverso la rete</string>
|
||||
<string name="pref_droidguard_block_hw_attestation_title">Blocca attestazione hardware</string>
|
||||
<string name="pref_droidguard_block_hw_attestation_summary">Quando si utilizza DroidGuard integrato, disabilita l\'accesso all\'attestazione hardware. Potrebbe aiutare a superare i controlli di integrità su alcuni dispositivi.</string>
|
||||
</resources>
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="prefcat_droidguard_mode">DroidGuard操作モード</string>
|
||||
<string name="pref_droidguard_mode_embedded_title">組み込み型</string>
|
||||
<string name="pref_droidguard_mode_embedded_summary">ローカルの DroidGuard ランタイムを使用する</string>
|
||||
<string name="pref_droidguard_mode_network_title">リモート</string>
|
||||
<string name="pref_droidguard_mode_network_summary">ネットワーク経由でDroidGuardランタイムに接続する</string>
|
||||
</resources>
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="prefcat_droidguard_mode">DroidGuard 작동 모드</string>
|
||||
<string name="pref_droidguard_mode_embedded_title">임베디드</string>
|
||||
<string name="pref_droidguard_mode_embedded_summary">내장된 DroidGuard 런타임 사용</string>
|
||||
<string name="pref_droidguard_mode_network_title">원격</string>
|
||||
<string name="pref_droidguard_mode_network_summary">네트워크로 DroidGuard 런타임에 연결</string>
|
||||
<string name="pref_droidguard_block_hw_attestation_title">하드웨어 증명 차단</string>
|
||||
<string name="pref_droidguard_block_hw_attestation_summary">임베디드 DroidGuard를 사용할 때, 하드웨어 인증에 대한 접근을 비활성화합니다. 일부 장치에서 무결성 검사를 통과하는 데 도움이 될 수 있습니다.</string>
|
||||
</resources>
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources></resources>
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources></resources>
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="prefcat_droidguard_mode">ഡ്രോയിഡ് ഗാർഡ് പ്രവർത്തന രീതി</string>
|
||||
<string name="pref_droidguard_mode_embedded_title">എംബഡഡ്</string>
|
||||
<string name="pref_droidguard_mode_network_title">റിമോട്ട്</string>
|
||||
<string name="pref_droidguard_mode_embedded_summary">ലോക്കൽ ഡ്രോയിഡ് ഗാർഡ് റൺടൈം ഉപയോഗിക്കുക</string>
|
||||
<string name="pref_droidguard_mode_network_summary">നെറ്റ്വർക്ക് വഴി ഡ്രോയിഡ് ഗാർഡ് റൺടൈമിലേക്ക് കണക്റ്റുചെയ്യുക</string>
|
||||
<string name="pref_droidguard_block_hw_attestation_title">ഹാർഡ്വെയർ അറ്റസ്റ്റേഷൻ തടയുക</string>
|
||||
<string name="pref_droidguard_block_hw_attestation_summary">എംബഡഡ് ഡ്രോയിഡ് ഗാർഡ് ഉപയോഗിക്കുമ്പോൾ, ഹാർഡ്വെയർ അറ്റസ്റ്റേഷനിലേക്കുള്ള ആക്സസ് പ്രവർത്തനരഹിതമാക്കുക. ചില ഉപകരണങ്ങളിൽ സമഗ്രത പരിശോധനകൾ പാസാക്കാൻ സഹായിച്ചേക്കാം.</string>
|
||||
</resources>
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="prefcat_droidguard_mode">DroidGuard-driftsmodus</string>
|
||||
<string name="pref_droidguard_mode_embedded_title">Innebygd</string>
|
||||
<string name="pref_droidguard_mode_embedded_summary">Bruk lokal DroidGuard-runtime</string>
|
||||
<string name="pref_droidguard_mode_network_title">Ekstern</string>
|
||||
<string name="pref_droidguard_mode_network_summary">Koble til DroidGuard-runtime over nettverket</string>
|
||||
<string name="pref_droidguard_block_hw_attestation_title">Klokker maskinvareattestering</string>
|
||||
<string name="pref_droidguard_block_hw_attestation_summary">Blokker tilgang til maskinvareattestering når innebygd Droidguard er i bruk. Kan hjelpe med å få godkjent integritetssjekker på enkelte enheter.</string>
|
||||
</resources>
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources></resources>
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="pref_droidguard_mode_network_summary">Połącz z usługą DroidGuard przez sieć</string>
|
||||
<string name="prefcat_droidguard_mode">Tryb działania DroidGuard</string>
|
||||
<string name="pref_droidguard_mode_embedded_summary">Korzystaj z lokalnej usługi DroidGuard</string>
|
||||
<string name="pref_droidguard_mode_embedded_title">Wbudowany</string>
|
||||
<string name="pref_droidguard_mode_network_title">Zdalny</string>
|
||||
<string name="pref_droidguard_block_hw_attestation_title">Blokowanie zaświadczeń sprzętowych</string>
|
||||
<string name="pref_droidguard_block_hw_attestation_summary">Podczas korzystania z wbudowanego DroidGuard należy wyłączyć dostęp do poświadczeń sprzętowych. Może to pomóc w przejściu kontroli integralności na niektórych urządzeniach.</string>
|
||||
</resources>
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="prefcat_droidguard_mode">Modo de operação do DroidGuard</string>
|
||||
<string name="pref_droidguard_mode_embedded_title">Embutido</string>
|
||||
<string name="pref_droidguard_mode_embedded_summary">Usar runtime local do DroidGuard</string>
|
||||
<string name="pref_droidguard_mode_network_title">Remoto</string>
|
||||
<string name="pref_droidguard_mode_network_summary">Conectar ao runtime do DroidGuard pela rede</string>
|
||||
<string name="pref_droidguard_block_hw_attestation_title">Bloquear atestação por hardware</string>
|
||||
<string name="pref_droidguard_block_hw_attestation_summary">Ao usar o DroidGuard embutido, desativar o acesso à atestação por hardware. Pode ajudar a passar os testes de integridade em alguns dispositivos.</string>
|
||||
</resources>
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="prefcat_droidguard_mode">Modo de operação do DroidGuard</string>
|
||||
<string name="pref_droidguard_mode_embedded_title">Embutido</string>
|
||||
<string name="pref_droidguard_mode_embedded_summary">Usar runtime local do DroidGuard</string>
|
||||
<string name="pref_droidguard_mode_network_title">Remoto</string>
|
||||
<string name="pref_droidguard_mode_network_summary">Conectar ao runtime do DroidGuard pela rede</string>
|
||||
<string name="pref_droidguard_block_hw_attestation_title">Bloquear atestação por hardware</string>
|
||||
<string name="pref_droidguard_block_hw_attestation_summary">Ao usar o DroidGuard embutido, desative o acesso à atestação por hardware. Pode ajudar a passar os testes de integridade em alguns dispositivos.</string>
|
||||
</resources>
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="pref_droidguard_mode_network_summary">Conectează-te la runtime DroidGuard prin rețea</string>
|
||||
<string name="prefcat_droidguard_mode">Modul de operare DroidGuard</string>
|
||||
<string name="pref_droidguard_mode_embedded_summary">Utilizează timpul de rulare local DroidGuard</string>
|
||||
<string name="pref_droidguard_mode_embedded_title">Încorporat</string>
|
||||
<string name="pref_droidguard_mode_network_title">La distanță</string>
|
||||
<string name="pref_droidguard_block_hw_attestation_title">Blochează atestarea hardware</string>
|
||||
<string name="pref_droidguard_block_hw_attestation_summary">Când utilizezi DroidGuard încorporat, dezactivează accesul la atestarea hardware. Ar putea ajuta la trecerea verificărilor de integritate pe unele dispozitive.</string>
|
||||
</resources>
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
~ SPDX-FileCopyrightText: 2021 microG Project Team
|
||||
~ SPDX-License-Identifier: Apache-2.0
|
||||
--><resources>
|
||||
<string name="prefcat_droidguard_mode">Режим работы DroidGuard</string>
|
||||
<string name="pref_droidguard_mode_embedded_title">Локальный</string>
|
||||
<string name="pref_droidguard_mode_embedded_summary">Использовать локальную среду выполнения DroidGuard</string>
|
||||
<string name="pref_droidguard_mode_network_title">Удалённый</string>
|
||||
<string name="pref_droidguard_mode_network_summary">Подключиться к среде выполнения DroidGuard по сети</string>
|
||||
<string name="pref_droidguard_block_hw_attestation_summary">При использовании встроенного DroidGuard отключите доступ к аппаратной аттестации. Это может помочь пройти проверку целостности на некоторых устройствах.</string>
|
||||
<string name="pref_droidguard_block_hw_attestation_title">Блокировать аппаратную аттестацию</string>
|
||||
</resources>
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
</resources>
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="pref_droidguard_mode_network_summary">Повежите се са DroidGuard временом извршавања преко мреже</string>
|
||||
<string name="prefcat_droidguard_mode">DroidGuard режим рада</string>
|
||||
<string name="pref_droidguard_mode_embedded_summary">Користите локално DroidGuard време извршавања</string>
|
||||
<string name="pref_droidguard_mode_embedded_title">Уграђени</string>
|
||||
<string name="pref_droidguard_mode_network_title">Удаљени</string>
|
||||
<string name="pref_droidguard_block_hw_attestation_title">Блокирај атестацију хардвера</string>
|
||||
<string name="pref_droidguard_block_hw_attestation_summary">Када користите уграђени DroidGuard, онемогућите приступ атестацији хардвера. Може помоћи у проласку провера интегритета на неким уређајима.</string>
|
||||
</resources>
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="pref_droidguard_mode_network_summary">Anslut till DroidGuard runtime via nätverk</string>
|
||||
<string name="prefcat_droidguard_mode">DroidGuard driftläge</string>
|
||||
<string name="pref_droidguard_mode_embedded_summary">Använd lokal DroidGuard-körning</string>
|
||||
<string name="pref_droidguard_mode_embedded_title">Inbäddad</string>
|
||||
<string name="pref_droidguard_mode_network_title">Fjärr</string>
|
||||
<string name="pref_droidguard_block_hw_attestation_title">Blockera hårdvaruintyg</string>
|
||||
<string name="pref_droidguard_block_hw_attestation_summary">Inaktivera åtkomst till hårdvaruintyg, när du använder inbäddad DroidGuard. Kan hjälpa för att passera integritetskontroller på vissa enheter.</string>
|
||||
</resources>
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="prefcat_droidguard_mode">டிராய்ட்காப்பு செயல்பாட்டு முறை</string>
|
||||
<string name="pref_droidguard_mode_embedded_title">உட்பொதிக்கப்பட்டது</string>
|
||||
<string name="pref_droidguard_mode_embedded_summary">உள்ளக டிராய்ட்காப்பு இயக்க நேரத்தைப் பயன்படுத்து</string>
|
||||
<string name="pref_droidguard_mode_network_title">தொலைநிலை</string>
|
||||
<string name="pref_droidguard_mode_network_summary">பிணையம் வழியாக டிராய்ட்காப்பு இயக்க நேரத்துடன் இணை</string>
|
||||
<string name="pref_droidguard_block_hw_attestation_title">வன்பொருள் சான்றளிப்பைத் தடு</string>
|
||||
<string name="pref_droidguard_block_hw_attestation_summary">உட்பொதிக்கப்பட்ட DroidGuard ஐப் பயன்படுத்தும்போது, வன்பொருள் சான்றளிப்புக்கான அணுகலை முடக்கவும். சில சாதனங்களில் ஒருமைப்பாடு சோதனைகளை அனுப்ப உதவக்கூடும்.</string>
|
||||
</resources>
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="pref_droidguard_mode_embedded_title">ฝังตัว</string>
|
||||
<string name="pref_droidguard_mode_network_title">ระยะไกล</string>
|
||||
<string name="pref_droidguard_mode_network_summary">เชื่อมต่อกับรันไทม์ DroidGuard ผ่านเครือข่าย</string>
|
||||
<string name="prefcat_droidguard_mode">โหมดการทำงานของ DroidGuard</string>
|
||||
<string name="pref_droidguard_mode_embedded_summary">ใช้รันไทม์ DroidGuard ในเครื่อง</string>
|
||||
<string name="pref_droidguard_block_hw_attestation_title">ปิดกั้นการตรวจสอบฮาร์ดแวร์</string>
|
||||
<string name="pref_droidguard_block_hw_attestation_summary">เมื่อใช้ DroidGuard แบบฝัง (embedded) ให้ ปิดการเข้าถึงการยืนยันฮาร์ดแวร์ (hardware attestation) ซึ่งอาจช่วยให้ ผ่านการตรวจสอบความสมบูรณ์ (integrity checks) บนอุปกรณ์บางเครื่องได้</string>
|
||||
</resources>
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="prefcat_droidguard_mode">DroidGuard çalışma modu</string>
|
||||
<string name="pref_droidguard_mode_embedded_title">Gömülü</string>
|
||||
<string name="pref_droidguard_mode_embedded_summary">Yerel DroidGuard çalıştırıcısını kullan</string>
|
||||
<string name="pref_droidguard_mode_network_title">Uzak</string>
|
||||
<string name="pref_droidguard_mode_network_summary">Ağ üzerinden DroidGuard çalıştırıcısına bağlan</string>
|
||||
<string name="pref_droidguard_block_hw_attestation_title">Donanım dayalı sağlamayı engelle</string>
|
||||
<string name="pref_droidguard_block_hw_attestation_summary">Gömülü DroidGuard\'ı kullanırken donanıma dayalı doğrulamaya erişimi devre dışı bırakır. Bazı cihazlarda bütünlük doğrulama testinden başarıyla geçilmesini sağlayabilir.</string>
|
||||
</resources>
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="pref_droidguard_mode_network_summary">تور ئارقىلىق DroidGuard ئىجرا ۋاقتىغا باغلانغاندا</string>
|
||||
<string name="prefcat_droidguard_mode">DroidGuard مەشغۇلات ھالىتى</string>
|
||||
<string name="pref_droidguard_mode_embedded_title">سىڭدۈرۈلگەن</string>
|
||||
<string name="pref_droidguard_mode_embedded_summary">يەرلىك DroidGuard ئىجرا ۋاقتىنى ئىشلىتىدۇ</string>
|
||||
<string name="pref_droidguard_mode_network_title">يىراق</string>
|
||||
<string name="pref_droidguard_block_hw_attestation_title">قاتتىق دېتال دەلىللەشنى توسىدۇ</string>
|
||||
<string name="pref_droidguard_block_hw_attestation_summary">سىڭدۈرمە DroidGuard ئىشلەتكەندە، قاتتىق دېتال دەلىللەشنى زىيارەت قىلىشنى چەكلەيدۇ. بۇ بەزى ئۈسكۈنىلەردە مۇكەممەللىكنى تەكشۈرۈشتىن ئۆتۈشكە ياردىمى بولۇشى مۇمكىن.</string>
|
||||
</resources>
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="pref_droidguard_mode_network_summary">Під\'єднатися до середовища виконання DroidGuard через мережу</string>
|
||||
<string name="prefcat_droidguard_mode">Режим роботи DroidGuard</string>
|
||||
<string name="pref_droidguard_mode_embedded_summary">Використовувати локальне середовище виконання DroidGuard</string>
|
||||
<string name="pref_droidguard_mode_embedded_title">Вбудований</string>
|
||||
<string name="pref_droidguard_mode_network_title">Віддалений</string>
|
||||
<string name="pref_droidguard_block_hw_attestation_title">Блокувати підтвердження обладнання</string>
|
||||
<string name="pref_droidguard_block_hw_attestation_summary">При використанні вбудованого DroidGuard вимкніть доступ до підтвердження апаратного забезпечення. Це може допомогти пройти перевірку цілісності на деяких пристроях.</string>
|
||||
</resources>
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="prefcat_droidguard_mode">Chế độ hoạt động của DroidGuard</string>
|
||||
<string name="pref_droidguard_mode_embedded_title">Nhúng</string>
|
||||
<string name="pref_droidguard_mode_embedded_summary">Sử dụng runtime DroidGuard cục bộ</string>
|
||||
<string name="pref_droidguard_mode_network_title">Từ xa</string>
|
||||
<string name="pref_droidguard_mode_network_summary">Kết nối đến runtime DroidGuard qua mạng</string>
|
||||
<string name="pref_droidguard_block_hw_attestation_title">Chặn xác thực phần cứng</string>
|
||||
<string name="pref_droidguard_block_hw_attestation_summary">Khi dùng DroidGuard nhúng, vô hiệu hóa truy cập xác thực phần cứng. Có thể giúp vượt qua kiểm tra tính toàn vẹn trên một số thiết bị.</string>
|
||||
</resources>
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="prefcat_droidguard_mode">DroidGuard 运作模式</string>
|
||||
<string name="pref_droidguard_mode_network_summary">通过网络连接到 DroidGuard 运行时</string>
|
||||
<string name="pref_droidguard_mode_embedded_title">内置</string>
|
||||
<string name="pref_droidguard_mode_network_title">远程</string>
|
||||
<string name="pref_droidguard_mode_embedded_summary">使用本地 DroidGuard 运行时</string>
|
||||
<string name="pref_droidguard_block_hw_attestation_title">阻止硬件认证</string>
|
||||
<string name="pref_droidguard_block_hw_attestation_summary">在使用嵌入式DroidGuard时,禁用对硬件认证的访问。这可能有助于在某些设备上通过完整性检查。</string>
|
||||
</resources>
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="pref_droidguard_mode_network_title">遠端</string>
|
||||
<string name="prefcat_droidguard_mode">DroidGuard 運作模式</string>
|
||||
<string name="pref_droidguard_mode_embedded_title">內建</string>
|
||||
<string name="pref_droidguard_mode_embedded_summary">使用本地 DroidGuard runtime</string>
|
||||
<string name="pref_droidguard_mode_network_summary">透過網路連接到 DroidGuard runtime</string>
|
||||
</resources>
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
~ SPDX-FileCopyrightText: 2021 microG Project Team
|
||||
~ SPDX-License-Identifier: Apache-2.0
|
||||
-->
|
||||
<resources>
|
||||
<string name="prefcat_droidguard_mode">DroidGuard operation mode</string>
|
||||
<string name="pref_droidguard_mode_embedded_title">Embedded</string>
|
||||
<string name="pref_droidguard_mode_embedded_summary">Use local DroidGuard runtime</string>
|
||||
<string name="pref_droidguard_mode_network_title">Remote</string>
|
||||
<string name="pref_droidguard_mode_network_summary">Connect to DroidGuard runtime via network</string>
|
||||
<string name="pref_droidguard_block_hw_attestation_title">Block hardware attestation</string>
|
||||
<string name="pref_droidguard_block_hw_attestation_summary">When using embedded DroidGuard, disable access to hardware attestation. Might help passing integrity checks on some devices.</string>
|
||||
</resources>
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
<PreferenceCategory
|
||||
android:title="@string/prefcat_droidguard_mode"
|
||||
app:iconSpaceReserved="false">
|
||||
<Preference
|
||||
android:icon="@drawable/ic_radio_unchecked"
|
||||
android:key="pref_droidguard_mode_embedded"
|
||||
android:persistent="false"
|
||||
android:summary="@string/pref_droidguard_mode_embedded_summary"
|
||||
android:title="@string/pref_droidguard_mode_embedded_title" />
|
||||
<org.microg.gms.droidguard.core.ui.ContainedEditTextPreference
|
||||
android:icon="@drawable/ic_radio_unchecked"
|
||||
android:key="pref_droidguard_mode_network"
|
||||
android:persistent="false"
|
||||
android:summary="@string/pref_droidguard_mode_network_summary"
|
||||
android:title="@string/pref_droidguard_mode_network_title" />
|
||||
</PreferenceCategory>
|
||||
<SwitchPreferenceCompat
|
||||
android:defaultValue="true"
|
||||
android:persistent="false"
|
||||
android:key="pref_droidguard_block_hw_attestation"
|
||||
android:summary="@string/pref_droidguard_block_hw_attestation_summary"
|
||||
android:title="@string/pref_droidguard_block_hw_attestation_title"
|
||||
app:iconSpaceReserved="false" />
|
||||
</PreferenceScreen>
|
||||
Loading…
Add table
Add a link
Reference in a new issue