mirror of
https://github.com/awfixers-stuff/OwnDroid.git
synced 2026-03-23 11:05:59 +00:00
Skip authentication if it is unavailable
Disable dependency info (#89) Remove unused permissions Use millisecond in security logs GitHub action: upload artifacts to Telegram only on dev branch
This commit is contained in:
5
.github/workflows/build.yml
vendored
5
.github/workflows/build.yml
vendored
@@ -61,10 +61,9 @@ jobs:
|
|||||||
|
|
||||||
upload-telegram:
|
upload-telegram:
|
||||||
name: Upload Builds
|
name: Upload Builds
|
||||||
if: ${{ success() && github.ref_name == 'dev' }}
|
if: ${{ github.ref_name == 'dev' }}
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
needs:
|
needs: ["build"]
|
||||||
- build
|
|
||||||
steps:
|
steps:
|
||||||
- name: Download Artifacts
|
- name: Download Artifacts
|
||||||
uses: actions/download-artifact@v4
|
uses: actions/download-artifact@v4
|
||||||
|
|||||||
@@ -57,6 +57,9 @@ android {
|
|||||||
androidResources {
|
androidResources {
|
||||||
generateLocaleConfig = true
|
generateLocaleConfig = true
|
||||||
}
|
}
|
||||||
|
dependenciesInfo {
|
||||||
|
includeInApk = false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
kotlin {
|
kotlin {
|
||||||
|
|||||||
@@ -2,21 +2,6 @@
|
|||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:tools="http://schemas.android.com/tools">
|
xmlns:tools="http://schemas.android.com/tools">
|
||||||
<uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>
|
<uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>
|
||||||
<uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
|
|
||||||
<uses-permission android:name="android.permission.MANAGE_DEVICE_POLICY_KEYGUARD"/>
|
|
||||||
<uses-permission android:name="android.permission.MANAGE_DEVICE_POLICY_WIPE_DATA"/>
|
|
||||||
<uses-permission android:name="android.permission.MANAGE_DEVICE_POLICY_ACROSS_USERS"/>
|
|
||||||
<uses-permission android:name="android.permission.MANAGE_DEVICE_POLICY_RESET_PASSWORD"/>
|
|
||||||
<uses-permission android:name="android.permission.REQUEST_PASSWORD_COMPLEXITY"/>
|
|
||||||
<uses-permission android:name="android.permission.MANAGE_DEVICE_POLICY_INPUT_METHODS"/>
|
|
||||||
<uses-permission android:name="android.permission.MANAGE_DEVICE_POLICY_LOCK_CREDENTIALS"/>
|
|
||||||
<uses-permission android:name="android.permission.MANAGE_DEVICE_POLICY_APPS_CONTROL"/>
|
|
||||||
<uses-permission android:name="android.permission.MANAGE_DEVICE_POLICY_SYSTEM_UPDATES"/>
|
|
||||||
<uses-permission android:name="android.permission.MANAGE_DEVICE_POLICY_LOCK_TASK"/>
|
|
||||||
<uses-permission android:name="android.permission.MANAGE_DEVICE_POLICY_WIFI"/>
|
|
||||||
<uses-permission android:name="android.permission.MANAGE_DEVICE_POLICY_RUNTIME_PERMISSIONS"/>
|
|
||||||
<uses-permission android:name="android.permission.MANAGE_DEVICE_POLICY_ORGANIZATION_IDENTITY"/>
|
|
||||||
<uses-permission android:name="android.permission.MANAGE_DEVICE_POLICY_PROFILE_INTERACTION"/>
|
|
||||||
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES"/>
|
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES"/>
|
||||||
<uses-permission android:name="android.permission.REQUEST_DELETE_PACKAGES"/>
|
<uses-permission android:name="android.permission.REQUEST_DELETE_PACKAGES"/>
|
||||||
<uses-permission android:name="android.permission.QUERY_ALL_PACKAGES" tools:ignore="QueryAllPackagesPermission" />
|
<uses-permission android:name="android.permission.QUERY_ALL_PACKAGES" tools:ignore="QueryAllPackagesPermission" />
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package com.bintianqi.owndroid
|
package com.bintianqi.owndroid
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
|
import android.widget.Toast
|
||||||
import androidx.activity.compose.BackHandler
|
import androidx.activity.compose.BackHandler
|
||||||
import androidx.biometric.BiometricManager
|
import androidx.biometric.BiometricManager
|
||||||
import androidx.biometric.BiometricPrompt
|
import androidx.biometric.BiometricPrompt
|
||||||
@@ -18,6 +19,7 @@ import androidx.compose.runtime.*
|
|||||||
import androidx.compose.runtime.saveable.rememberSaveable
|
import androidx.compose.runtime.saveable.rememberSaveable
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
import androidx.fragment.app.FragmentActivity
|
import androidx.fragment.app.FragmentActivity
|
||||||
@@ -26,6 +28,7 @@ import kotlinx.coroutines.delay
|
|||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun Authenticate(activity: FragmentActivity, navCtrl: NavHostController) {
|
fun Authenticate(activity: FragmentActivity, navCtrl: NavHostController) {
|
||||||
|
val context = LocalContext.current
|
||||||
BackHandler { activity.moveTaskToBack(true) }
|
BackHandler { activity.moveTaskToBack(true) }
|
||||||
var status by rememberSaveable { mutableIntStateOf(0) } // 0:Prompt automatically, 1:Authenticating, 2:Prompt manually
|
var status by rememberSaveable { mutableIntStateOf(0) } // 0:Prompt automatically, 1:Authenticating, 2:Prompt manually
|
||||||
val onAuthSucceed = { navCtrl.navigateUp() }
|
val onAuthSucceed = { navCtrl.navigateUp() }
|
||||||
@@ -37,7 +40,11 @@ fun Authenticate(activity: FragmentActivity, navCtrl: NavHostController) {
|
|||||||
override fun onAuthenticationError(errorCode: Int, errString: CharSequence) {
|
override fun onAuthenticationError(errorCode: Int, errString: CharSequence) {
|
||||||
super.onAuthenticationError(errorCode, errString)
|
super.onAuthenticationError(errorCode, errString)
|
||||||
when(errorCode) {
|
when(errorCode) {
|
||||||
BiometricPrompt.ERROR_NO_DEVICE_CREDENTIAL -> onAuthSucceed()
|
BiometricPrompt.ERROR_NO_DEVICE_CREDENTIAL, BiometricPrompt.ERROR_NO_SPACE, BiometricPrompt.ERROR_HW_NOT_PRESENT,
|
||||||
|
BiometricPrompt.ERROR_VENDOR, BiometricPrompt.ERROR_NO_BIOMETRICS -> {
|
||||||
|
Toast.makeText(context, R.string.skipped_authentication, Toast.LENGTH_SHORT).show()
|
||||||
|
onAuthSucceed()
|
||||||
|
}
|
||||||
else -> status = 2
|
else -> status = 2
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -195,7 +195,7 @@ fun Home(activity: FragmentActivity, vm: MyViewModel) {
|
|||||||
LaunchedEffect(backToHome) {
|
LaunchedEffect(backToHome) {
|
||||||
if(backToHome) { navCtrl.navigateUp(); backToHomeStateFlow.value = false }
|
if(backToHome) { navCtrl.navigateUp(); backToHomeStateFlow.value = false }
|
||||||
}
|
}
|
||||||
NavHost(
|
@Suppress("NewApi") NavHost(
|
||||||
navController = navCtrl,
|
navController = navCtrl,
|
||||||
startDestination = "HomePage",
|
startDestination = "HomePage",
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
@@ -226,6 +226,7 @@ fun Home(activity: FragmentActivity, vm: MyViewModel) {
|
|||||||
composable(route = "HardwareMonitor") { HardwareMonitor(navCtrl) }
|
composable(route = "HardwareMonitor") { HardwareMonitor(navCtrl) }
|
||||||
composable(route = "ChangeTime") { ChangeTime(navCtrl) }
|
composable(route = "ChangeTime") { ChangeTime(navCtrl) }
|
||||||
composable(route = "ChangeTimeZone") { ChangeTimeZone(navCtrl) }
|
composable(route = "ChangeTimeZone") { ChangeTimeZone(navCtrl) }
|
||||||
|
//composable(route = "KeyPairs") { KeyPairs(navCtrl) }
|
||||||
composable(route = "PermissionPolicy") { PermissionPolicy(navCtrl) }
|
composable(route = "PermissionPolicy") { PermissionPolicy(navCtrl) }
|
||||||
composable(route = "MTEPolicy") { MTEPolicy(navCtrl) }
|
composable(route = "MTEPolicy") { MTEPolicy(navCtrl) }
|
||||||
composable(route = "NearbyStreamingPolicy") { NearbyStreamingPolicy(navCtrl) }
|
composable(route = "NearbyStreamingPolicy") { NearbyStreamingPolicy(navCtrl) }
|
||||||
|
|||||||
@@ -361,7 +361,7 @@ fun processSecurityLogs(securityEvents: List<SecurityLog.SecurityEvent>, outputS
|
|||||||
val buffer = outputStream.bufferedWriter()
|
val buffer = outputStream.bufferedWriter()
|
||||||
securityEvents.forEachIndexed { index, event ->
|
securityEvents.forEachIndexed { index, event ->
|
||||||
val item = buildJsonObject {
|
val item = buildJsonObject {
|
||||||
put("time_nanos", event.timeNanos)
|
put("time", event.timeNanos / 1000)
|
||||||
put("tag", event.tag)
|
put("tag", event.tag)
|
||||||
if(VERSION.SDK_INT >= 28) put("level", event.logLevel)
|
if(VERSION.SDK_INT >= 28) put("level", event.logLevel)
|
||||||
if(VERSION.SDK_INT >= 28) put("id", event.id)
|
if(VERSION.SDK_INT >= 28) put("id", event.id)
|
||||||
|
|||||||
@@ -173,6 +173,8 @@ fun SystemManage(navCtrl: NavHostController) {
|
|||||||
FunctionItem(R.string.change_time, icon = R.drawable.schedule_fill0) { navCtrl.navigate("ChangeTime") }
|
FunctionItem(R.string.change_time, icon = R.drawable.schedule_fill0) { navCtrl.navigate("ChangeTime") }
|
||||||
FunctionItem(R.string.change_timezone, icon = R.drawable.schedule_fill0) { navCtrl.navigate("ChangeTimeZone") }
|
FunctionItem(R.string.change_timezone, icon = R.drawable.schedule_fill0) { navCtrl.navigate("ChangeTimeZone") }
|
||||||
}
|
}
|
||||||
|
/*if(VERSION.SDK_INT >= 28 && (deviceOwner || profileOwner))
|
||||||
|
FunctionItem(R.string.key_pairs, icon = R.drawable.key_vertical_fill0) { navCtrl.navigate("KeyPairs") }*/
|
||||||
if(VERSION.SDK_INT >= 23 && (deviceOwner || profileOwner)) {
|
if(VERSION.SDK_INT >= 23 && (deviceOwner || profileOwner)) {
|
||||||
FunctionItem(R.string.permission_policy, icon = R.drawable.key_fill0) { navCtrl.navigate("PermissionPolicy") }
|
FunctionItem(R.string.permission_policy, icon = R.drawable.key_fill0) { navCtrl.navigate("PermissionPolicy") }
|
||||||
}
|
}
|
||||||
@@ -630,6 +632,186 @@ fun ChangeTimeZone(navCtrl: NavHostController) {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*@RequiresApi(28)
|
||||||
|
@OptIn(ExperimentalLayoutApi::class)
|
||||||
|
@Composable
|
||||||
|
fun KeyPairs(navCtrl: NavHostController) {
|
||||||
|
val context = LocalContext.current
|
||||||
|
val dpm = context.getDPM()
|
||||||
|
val receiver = context.getReceiver()
|
||||||
|
var alias by remember { mutableStateOf("") }
|
||||||
|
var purpose by remember { mutableIntStateOf(0) }
|
||||||
|
//var keySpecType by remember { mutableIntStateOf() }
|
||||||
|
var ecStdName by remember { mutableStateOf("") }
|
||||||
|
var rsaKeySize by remember { mutableStateOf("") }
|
||||||
|
var rsaExponent by remember { mutableStateOf("") }
|
||||||
|
var algorithm by remember { mutableStateOf("") }
|
||||||
|
var idAttestationFlags by remember { mutableIntStateOf(0) }
|
||||||
|
MyScaffold(R.string.key_pairs, 8.dp, navCtrl) {
|
||||||
|
OutlinedTextField(
|
||||||
|
value = alias, onValueChange = { alias = it }, label = { Text(stringResource(R.string.alias)) },
|
||||||
|
modifier = Modifier.fillMaxWidth()
|
||||||
|
)
|
||||||
|
Text(stringResource(R.string.algorithm), style = typography.titleLarge)
|
||||||
|
SingleChoiceSegmentedButtonRow {
|
||||||
|
*//*SegmentedButton(
|
||||||
|
algorithm == "DH", { algorithm = "DH" },
|
||||||
|
shape = SegmentedButtonDefaults.itemShape(index = 0, count = 4)
|
||||||
|
) {
|
||||||
|
Text("DH")
|
||||||
|
}
|
||||||
|
SegmentedButton(
|
||||||
|
algorithm == "DSA", { algorithm = "DSA" },
|
||||||
|
shape = SegmentedButtonDefaults.itemShape(index = 1, count = 4)
|
||||||
|
) {
|
||||||
|
Text("DSA")
|
||||||
|
}*//*
|
||||||
|
SegmentedButton(
|
||||||
|
algorithm == "EC", { algorithm = "EC" },
|
||||||
|
shape = SegmentedButtonDefaults.itemShape(index = 0, count = 2)
|
||||||
|
) {
|
||||||
|
Text("EC")
|
||||||
|
}
|
||||||
|
SegmentedButton(
|
||||||
|
algorithm == "RSA", { algorithm = "RSA" },
|
||||||
|
shape = SegmentedButtonDefaults.itemShape(index = 1, count = 2)
|
||||||
|
) {
|
||||||
|
Text("RSA")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
AnimatedVisibility(algorithm != "") {
|
||||||
|
Text(stringResource(R.string.key_specification), style = typography.titleLarge)
|
||||||
|
}
|
||||||
|
AnimatedVisibility(algorithm == "EC") {
|
||||||
|
OutlinedTextField(
|
||||||
|
value = ecStdName, onValueChange = { ecStdName = it }, label = { Text(stringResource(R.string.standard_name)) },
|
||||||
|
modifier = Modifier.fillMaxWidth()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
AnimatedVisibility(algorithm == "RSA") {
|
||||||
|
Column {
|
||||||
|
OutlinedTextField(
|
||||||
|
value = rsaKeySize, onValueChange = { rsaKeySize = it }, label = { Text(stringResource(R.string.key_size)) },
|
||||||
|
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number),
|
||||||
|
modifier = Modifier.fillMaxWidth()
|
||||||
|
)
|
||||||
|
OutlinedTextField(
|
||||||
|
value = rsaExponent, onValueChange = { rsaExponent = it }, label = { Text(stringResource(R.string.exponent)) },
|
||||||
|
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number),
|
||||||
|
modifier = Modifier.fillMaxWidth()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Text(stringResource(R.string.key_purpose), style = typography.titleLarge)
|
||||||
|
FlowRow {
|
||||||
|
if(VERSION.SDK_INT >= 23) {
|
||||||
|
InputChip(
|
||||||
|
purpose and KeyProperties.PURPOSE_ENCRYPT != 0,
|
||||||
|
{ purpose = purpose xor KeyProperties.PURPOSE_ENCRYPT },
|
||||||
|
{ Text(stringResource(R.string.kp_encrypt)) },
|
||||||
|
Modifier.padding(horizontal = 4.dp)
|
||||||
|
)
|
||||||
|
InputChip(
|
||||||
|
purpose and KeyProperties.PURPOSE_DECRYPT != 0,
|
||||||
|
{ purpose = purpose xor KeyProperties.PURPOSE_DECRYPT },
|
||||||
|
{ Text(stringResource(R.string.kp_decrypt)) },
|
||||||
|
Modifier.padding(horizontal = 4.dp)
|
||||||
|
)
|
||||||
|
InputChip(
|
||||||
|
purpose and KeyProperties.PURPOSE_SIGN != 0,
|
||||||
|
{ purpose = purpose xor KeyProperties.PURPOSE_SIGN },
|
||||||
|
{ Text(stringResource(R.string.kp_sign)) },
|
||||||
|
Modifier.padding(horizontal = 4.dp)
|
||||||
|
)
|
||||||
|
InputChip(
|
||||||
|
purpose and KeyProperties.PURPOSE_VERIFY != 0,
|
||||||
|
{ purpose = purpose xor KeyProperties.PURPOSE_VERIFY },
|
||||||
|
{ Text(stringResource(R.string.kp_verify)) },
|
||||||
|
Modifier.padding(horizontal = 4.dp)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
if(VERSION.SDK_INT >= 28) InputChip(
|
||||||
|
purpose and KeyProperties.PURPOSE_WRAP_KEY != 0,
|
||||||
|
{ purpose = purpose xor KeyProperties.PURPOSE_WRAP_KEY },
|
||||||
|
{ Text(stringResource(R.string.kp_wrap)) },
|
||||||
|
Modifier.padding(horizontal = 4.dp)
|
||||||
|
)
|
||||||
|
if(VERSION.SDK_INT >= 31) {
|
||||||
|
InputChip(
|
||||||
|
purpose and KeyProperties.PURPOSE_AGREE_KEY != 0,
|
||||||
|
{ purpose = purpose xor KeyProperties.PURPOSE_AGREE_KEY },
|
||||||
|
{ Text(stringResource(R.string.kp_agree)) },
|
||||||
|
Modifier.padding(horizontal = 4.dp)
|
||||||
|
)
|
||||||
|
InputChip(
|
||||||
|
purpose and KeyProperties.PURPOSE_ATTEST_KEY != 0,
|
||||||
|
{ purpose = purpose xor KeyProperties.PURPOSE_ATTEST_KEY },
|
||||||
|
{ Text(stringResource(R.string.kp_attest)) },
|
||||||
|
Modifier.padding(horizontal = 4.dp)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Text(stringResource(R.string.attestation_record_identifiers), style = typography.titleLarge)
|
||||||
|
FlowRow {
|
||||||
|
InputChip(
|
||||||
|
idAttestationFlags and DevicePolicyManager.ID_TYPE_BASE_INFO != 0,
|
||||||
|
{ idAttestationFlags = idAttestationFlags xor DevicePolicyManager.ID_TYPE_BASE_INFO },
|
||||||
|
{ Text(stringResource(R.string.base_info)) },
|
||||||
|
Modifier.padding(horizontal = 4.dp)
|
||||||
|
)
|
||||||
|
InputChip(
|
||||||
|
idAttestationFlags and DevicePolicyManager.ID_TYPE_SERIAL != 0,
|
||||||
|
{ idAttestationFlags = idAttestationFlags xor DevicePolicyManager.ID_TYPE_SERIAL },
|
||||||
|
{ Text(stringResource(R.string.serial_number)) },
|
||||||
|
Modifier.padding(horizontal = 4.dp)
|
||||||
|
)
|
||||||
|
InputChip(
|
||||||
|
idAttestationFlags and DevicePolicyManager.ID_TYPE_IMEI != 0,
|
||||||
|
{ idAttestationFlags = idAttestationFlags xor DevicePolicyManager.ID_TYPE_IMEI },
|
||||||
|
{ Text("IMEI") },
|
||||||
|
Modifier.padding(horizontal = 4.dp)
|
||||||
|
)
|
||||||
|
InputChip(
|
||||||
|
idAttestationFlags and DevicePolicyManager.ID_TYPE_MEID != 0,
|
||||||
|
{ idAttestationFlags = idAttestationFlags xor DevicePolicyManager.ID_TYPE_MEID },
|
||||||
|
{ Text("MEID") },
|
||||||
|
Modifier.padding(horizontal = 4.dp)
|
||||||
|
)
|
||||||
|
if(VERSION.SDK_INT >= 30) InputChip(
|
||||||
|
idAttestationFlags and DevicePolicyManager.ID_TYPE_INDIVIDUAL_ATTESTATION != 0,
|
||||||
|
{ idAttestationFlags = idAttestationFlags xor DevicePolicyManager.ID_TYPE_INDIVIDUAL_ATTESTATION },
|
||||||
|
{ Text(stringResource(R.string.individual_certificate)) },
|
||||||
|
Modifier.padding(horizontal = 4.dp)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
Button(
|
||||||
|
onClick = {
|
||||||
|
try {
|
||||||
|
val aps = if(algorithm == "EC") ECGenParameterSpec(ecStdName)
|
||||||
|
else RSAKeyGenParameterSpec(rsaKeySize.toInt(), rsaExponent.toBigInteger())
|
||||||
|
val keySpec = KeyGenParameterSpec.Builder(alias, purpose).run {
|
||||||
|
setAlgorithmParameterSpec(aps)
|
||||||
|
this.setAttestationChallenge()
|
||||||
|
build()
|
||||||
|
}
|
||||||
|
dpm.generateKeyPair(receiver, algorithm, keySpec, idAttestationFlags)
|
||||||
|
} catch(e: Exception) {
|
||||||
|
AlertDialog.Builder(context)
|
||||||
|
.setTitle(R.string.error)
|
||||||
|
.setMessage(e.message ?: "")
|
||||||
|
.setPositiveButton(R.string.confirm) { dialog, _ -> dialog.dismiss() }
|
||||||
|
.show()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
modifier = Modifier.fillMaxWidth(),
|
||||||
|
enabled = alias != "" && purpose != 0 &&
|
||||||
|
((algorithm == "EC") || (algorithm == "RSA" && rsaKeySize.all { it.isDigit() } && rsaExponent.all { it.isDigit() }))
|
||||||
|
) {
|
||||||
|
Text(stringResource(R.string.generate))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}*/
|
||||||
|
|
||||||
@RequiresApi(23)
|
@RequiresApi(23)
|
||||||
@Composable
|
@Composable
|
||||||
fun PermissionPolicy(navCtrl: NavHostController) {
|
fun PermissionPolicy(navCtrl: NavHostController) {
|
||||||
|
|||||||
@@ -169,6 +169,25 @@
|
|||||||
<string name="change_timezone">Change timezone</string>
|
<string name="change_timezone">Change timezone</string>
|
||||||
<string name="timezone_id">Timezone ID</string>
|
<string name="timezone_id">Timezone ID</string>
|
||||||
<string name="disable_auto_time_zone_before_set">Auto timezone should be disabled before set a custom timezone. </string>
|
<string name="disable_auto_time_zone_before_set">Auto timezone should be disabled before set a custom timezone. </string>
|
||||||
|
<!--<string name="key_pairs">Key pairs</string>
|
||||||
|
<string name="generate_key_pair">Generate key pair</string>
|
||||||
|
<string name="algorithm">Algorithm</string>
|
||||||
|
<string name="key_specification">Key specification</string>
|
||||||
|
<string name="standard_name">Standard name</string>
|
||||||
|
<string name="key_size">Key size</string>
|
||||||
|
<string name="exponent">Exponent</string>
|
||||||
|
<string name="key_purpose">Key purpose</string>
|
||||||
|
<string name="kp_encrypt">Encrypt</string>
|
||||||
|
<string name="kp_decrypt">Decrypt</string>
|
||||||
|
<string name="kp_sign">Sign</string>
|
||||||
|
<string name="kp_verify">Verify</string>
|
||||||
|
<string name="kp_wrap">Wrap</string>
|
||||||
|
<string name="kp_agree">Agree</string>
|
||||||
|
<string name="kp_attest">Attest</string>
|
||||||
|
<string name="attestation_record_identifiers">Attestation record identifiers</string>
|
||||||
|
<string name="base_info">Base info</string>
|
||||||
|
<string name="individual_certificate">Individual certificate</string>
|
||||||
|
<string name="generate">Generate</string>-->
|
||||||
<string name="permission_policy">Permission policy</string>
|
<string name="permission_policy">Permission policy</string>
|
||||||
<string name="auto_grant">Auto grant</string>
|
<string name="auto_grant">Auto grant</string>
|
||||||
<string name="auto_deny">Auto deny</string>
|
<string name="auto_deny">Auto deny</string>
|
||||||
@@ -585,6 +604,7 @@
|
|||||||
<string name="authenticate">Authenticate</string>
|
<string name="authenticate">Authenticate</string>
|
||||||
<string name="lock_in_background">Lock when switch to background</string>
|
<string name="lock_in_background">Lock when switch to background</string>
|
||||||
<string name="clear_storage">Clear storage</string>
|
<string name="clear_storage">Clear storage</string>
|
||||||
|
<string name="skipped_authentication">Skipped authentication because it is unavailable.</string>
|
||||||
|
|
||||||
<string name="api_key">API key</string>
|
<string name="api_key">API key</string>
|
||||||
<string name="api_key_exist">The API key already exists, setting a new key will overwrite the current key.</string>
|
<string name="api_key_exist">The API key already exists, setting a new key will overwrite the current key.</string>
|
||||||
|
|||||||
Reference in New Issue
Block a user