summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--app/src/main/java/app/passwordstore/ui/autofill/AutofillPublisherChangedActivity.kt12
-rw-r--r--app/src/main/java/app/passwordstore/ui/crypto/BasePgpActivity.kt12
-rw-r--r--app/src/main/java/app/passwordstore/ui/crypto/DecryptActivity.kt2
-rw-r--r--app/src/main/java/app/passwordstore/ui/crypto/PasswordCreationActivity.kt2
-rw-r--r--app/src/main/java/app/passwordstore/ui/folderselect/SelectFolderActivity.kt2
-rw-r--r--app/src/main/java/app/passwordstore/ui/git/config/GitConfigActivity.kt2
-rw-r--r--app/src/main/java/app/passwordstore/ui/git/config/GitServerConfigActivity.kt2
-rw-r--r--app/src/main/java/app/passwordstore/ui/onboarding/activity/OnboardingActivity.kt13
-rw-r--r--app/src/main/java/app/passwordstore/ui/passwords/PasswordStore.kt19
-rw-r--r--app/src/main/java/app/passwordstore/ui/settings/SettingsActivity.kt5
-rw-r--r--app/src/main/java/app/passwordstore/ui/sshkeygen/SshKeyGenActivity.kt2
-rw-r--r--app/src/main/java/app/passwordstore/util/autofill/Api30AutofillResponseBuilder.kt43
-rw-r--r--app/src/main/java/app/passwordstore/util/autofill/AutofillResponseBuilder.kt3
-rw-r--r--app/src/main/java/app/passwordstore/util/extensions/AndroidExtensions.kt49
-rw-r--r--app/src/main/java/app/passwordstore/util/services/ClipboardService.kt12
-rw-r--r--app/src/main/java/app/passwordstore/util/services/PasswordExportService.kt3
-rw-r--r--app/src/main/res/values-de/strings.xml2
-rw-r--r--app/src/main/res/values-fr/strings.xml2
-rw-r--r--app/src/main/res/values-gl/strings.xml2
-rw-r--r--app/src/main/res/values-it/strings.xml2
-rw-r--r--app/src/main/res/values-pt-rBR/strings.xml2
-rw-r--r--app/src/main/res/values-ru/strings.xml2
-rw-r--r--app/src/main/res/values/strings.xml2
-rw-r--r--autofill-parser/src/main/java/com/github/androidpasswordstore/autofillparser/AutofillFormParser.kt12
-rw-r--r--autofill-parser/src/main/java/com/github/androidpasswordstore/autofillparser/AutofillHelper.kt10
-rw-r--r--autofill-parser/src/main/java/com/github/androidpasswordstore/autofillparser/AutofillScenario.kt39
-rw-r--r--autofill-parser/src/main/java/com/github/androidpasswordstore/autofillparser/FeatureAndTrustDetection.kt11
-rw-r--r--build-logic/android-plugins/src/main/kotlin/app/passwordstore/gradle/AndroidCommon.kt2
-rw-r--r--config/detekt/detekt.yml10
29 files changed, 210 insertions, 71 deletions
diff --git a/app/src/main/java/app/passwordstore/ui/autofill/AutofillPublisherChangedActivity.kt b/app/src/main/java/app/passwordstore/ui/autofill/AutofillPublisherChangedActivity.kt
index dd54b8eb..ac85a92a 100644
--- a/app/src/main/java/app/passwordstore/ui/autofill/AutofillPublisherChangedActivity.kt
+++ b/app/src/main/java/app/passwordstore/ui/autofill/AutofillPublisherChangedActivity.kt
@@ -22,6 +22,9 @@ import app.passwordstore.databinding.ActivityOreoAutofillPublisherChangedBinding
import app.passwordstore.util.autofill.AutofillMatcher
import app.passwordstore.util.autofill.AutofillPublisherChangedException
import app.passwordstore.util.extensions.asLog
+import app.passwordstore.util.extensions.getApplicationInfoCompat
+import app.passwordstore.util.extensions.getPackageInfoCompat
+import app.passwordstore.util.extensions.getParcelableExtraCompat
import app.passwordstore.util.extensions.viewBinding
import com.github.androidpasswordstore.autofillparser.FormOrigin
import com.github.androidpasswordstore.autofillparser.computeCertificatesHash
@@ -93,7 +96,8 @@ class AutofillPublisherChangedActivity : AppCompatActivity() {
this@AutofillPublisherChangedActivity,
FormOrigin.App(appPackage)
)
- val fillResponse = intent.getParcelableExtra<FillResponse>(EXTRA_FILL_RESPONSE_AFTER_RESET)
+ val fillResponse =
+ intent.getParcelableExtraCompat<FillResponse>(EXTRA_FILL_RESPONSE_AFTER_RESET)
setResult(
RESULT_OK,
Intent().apply { putExtra(AutofillManager.EXTRA_AUTHENTICATION_RESULT, fillResponse) }
@@ -106,11 +110,13 @@ class AutofillPublisherChangedActivity : AppCompatActivity() {
private fun showPackageInfo() {
runCatching {
with(binding) {
- val packageInfo = packageManager.getPackageInfo(appPackage, PackageManager.GET_META_DATA)
+ val packageInfo =
+ packageManager.getPackageInfoCompat(appPackage, PackageManager.GET_META_DATA)
val installTime = DateUtils.getRelativeTimeSpanString(packageInfo.firstInstallTime)
warningAppInstallDate.text =
getString(R.string.oreo_autofill_warning_publisher_install_time, installTime)
- val appInfo = packageManager.getApplicationInfo(appPackage, PackageManager.GET_META_DATA)
+ val appInfo =
+ packageManager.getApplicationInfoCompat(appPackage, PackageManager.GET_META_DATA)
warningAppName.text =
getString(
R.string.oreo_autofill_warning_publisher_app_name,
diff --git a/app/src/main/java/app/passwordstore/ui/crypto/BasePgpActivity.kt b/app/src/main/java/app/passwordstore/ui/crypto/BasePgpActivity.kt
index b6bb481f..fa85ffdd 100644
--- a/app/src/main/java/app/passwordstore/ui/crypto/BasePgpActivity.kt
+++ b/app/src/main/java/app/passwordstore/ui/crypto/BasePgpActivity.kt
@@ -10,6 +10,7 @@ import android.content.Intent
import android.content.SharedPreferences
import android.os.Build
import android.os.Bundle
+import android.os.PersistableBundle
import android.view.WindowManager
import androidx.annotation.CallSuper
import androidx.annotation.StringRes
@@ -68,8 +69,12 @@ open class BasePgpActivity : AppCompatActivity() {
) {
val clipboard = clipboard ?: return
val clip = ClipData.newPlainText("pgp_handler_result_pm", text)
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
+ clip.description.extras =
+ PersistableBundle().apply { putBoolean("android.content.extra.IS_SENSITIVE", true) }
+ }
clipboard.setPrimaryClip(clip)
- if (showSnackbar) {
+ if (showSnackbar && Build.VERSION.SDK_INT < Build.VERSION_CODES.R) {
snackbar(message = resources.getString(snackbarTextRes))
}
}
@@ -80,7 +85,7 @@ open class BasePgpActivity : AppCompatActivity() {
* clearing the clipboard.
*/
fun copyPasswordToClipboard(password: String?) {
- copyTextToClipboard(password, showSnackbar = false)
+ copyTextToClipboard(password)
val clearAfter = settings.getString(PreferenceKeys.GENERAL_SHOW_TIME)?.toIntOrNull() ?: 45
@@ -95,9 +100,6 @@ open class BasePgpActivity : AppCompatActivity() {
} else {
startService(service)
}
- snackbar(message = resources.getString(R.string.clipboard_password_toast_text, clearAfter))
- } else {
- snackbar(message = resources.getString(R.string.clipboard_password_no_clear_toast_text))
}
}
diff --git a/app/src/main/java/app/passwordstore/ui/crypto/DecryptActivity.kt b/app/src/main/java/app/passwordstore/ui/crypto/DecryptActivity.kt
index 7b288ca6..3fb0d52f 100644
--- a/app/src/main/java/app/passwordstore/ui/crypto/DecryptActivity.kt
+++ b/app/src/main/java/app/passwordstore/ui/crypto/DecryptActivity.kt
@@ -78,7 +78,7 @@ class DecryptActivity : BasePgpActivity() {
override fun onOptionsItemSelected(item: MenuItem): Boolean {
when (item.itemId) {
- android.R.id.home -> onBackPressed()
+ android.R.id.home -> onBackPressedDispatcher.onBackPressed()
R.id.edit_password -> editPassword()
R.id.share_password_as_plaintext -> shareAsPlaintext()
R.id.copy_password -> copyPasswordToClipboard(passwordEntry?.password)
diff --git a/app/src/main/java/app/passwordstore/ui/crypto/PasswordCreationActivity.kt b/app/src/main/java/app/passwordstore/ui/crypto/PasswordCreationActivity.kt
index b8221a46..8fee21b4 100644
--- a/app/src/main/java/app/passwordstore/ui/crypto/PasswordCreationActivity.kt
+++ b/app/src/main/java/app/passwordstore/ui/crypto/PasswordCreationActivity.kt
@@ -262,7 +262,7 @@ class PasswordCreationActivity : BasePgpActivity() {
when (item.itemId) {
android.R.id.home -> {
setResult(RESULT_CANCELED)
- onBackPressed()
+ onBackPressedDispatcher.onBackPressed()
}
R.id.save_password -> {
copy = false
diff --git a/app/src/main/java/app/passwordstore/ui/folderselect/SelectFolderActivity.kt b/app/src/main/java/app/passwordstore/ui/folderselect/SelectFolderActivity.kt
index 009267e2..9ab146fe 100644
--- a/app/src/main/java/app/passwordstore/ui/folderselect/SelectFolderActivity.kt
+++ b/app/src/main/java/app/passwordstore/ui/folderselect/SelectFolderActivity.kt
@@ -49,7 +49,7 @@ class SelectFolderActivity : AppCompatActivity(R.layout.select_folder_layout) {
when (item.itemId) {
android.R.id.home -> {
setResult(RESULT_CANCELED)
- onBackPressed()
+ onBackPressedDispatcher.onBackPressed()
}
R.id.crypto_select -> selectFolder()
else -> return super.onOptionsItemSelected(item)
diff --git a/app/src/main/java/app/passwordstore/ui/git/config/GitConfigActivity.kt b/app/src/main/java/app/passwordstore/ui/git/config/GitConfigActivity.kt
index 2b5ecae5..5b9a04be 100644
--- a/app/src/main/java/app/passwordstore/ui/git/config/GitConfigActivity.kt
+++ b/app/src/main/java/app/passwordstore/ui/git/config/GitConfigActivity.kt
@@ -69,7 +69,7 @@ class GitConfigActivity : BaseGitActivity() {
override fun onOptionsItemSelected(item: MenuItem): Boolean {
return when (item.itemId) {
android.R.id.home -> {
- onBackPressed()
+ onBackPressedDispatcher.onBackPressed()
true
}
else -> super.onOptionsItemSelected(item)
diff --git a/app/src/main/java/app/passwordstore/ui/git/config/GitServerConfigActivity.kt b/app/src/main/java/app/passwordstore/ui/git/config/GitServerConfigActivity.kt
index a7ecd697..a07b409f 100644
--- a/app/src/main/java/app/passwordstore/ui/git/config/GitServerConfigActivity.kt
+++ b/app/src/main/java/app/passwordstore/ui/git/config/GitServerConfigActivity.kt
@@ -202,7 +202,7 @@ class GitServerConfigActivity : BaseGitActivity() {
override fun onOptionsItemSelected(item: MenuItem): Boolean {
return when (item.itemId) {
android.R.id.home -> {
- onBackPressed()
+ onBackPressedDispatcher.onBackPressed()
true
}
else -> super.onOptionsItemSelected(item)
diff --git a/app/src/main/java/app/passwordstore/ui/onboarding/activity/OnboardingActivity.kt b/app/src/main/java/app/passwordstore/ui/onboarding/activity/OnboardingActivity.kt
index 2fe92098..f5257530 100644
--- a/app/src/main/java/app/passwordstore/ui/onboarding/activity/OnboardingActivity.kt
+++ b/app/src/main/java/app/passwordstore/ui/onboarding/activity/OnboardingActivity.kt
@@ -6,6 +6,7 @@
package app.passwordstore.ui.onboarding.activity
import android.os.Bundle
+import androidx.activity.addCallback
import androidx.appcompat.app.AppCompatActivity
import app.passwordstore.R
@@ -14,13 +15,11 @@ class OnboardingActivity : AppCompatActivity(R.layout.activity_onboarding) {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
supportActionBar?.hide()
- }
-
- override fun onBackPressed() {
- if (supportFragmentManager.backStackEntryCount == 0) {
- finishAffinity()
- } else {
- super.onBackPressed()
+ val callback = onBackPressedDispatcher.addCallback(enabled = false) { finishAffinity() }
+ supportFragmentManager.addOnBackStackChangedListener {
+ if (supportFragmentManager.backStackEntryCount == 0) {
+ callback.isEnabled = true
+ }
}
}
}
diff --git a/app/src/main/java/app/passwordstore/ui/passwords/PasswordStore.kt b/app/src/main/java/app/passwordstore/ui/passwords/PasswordStore.kt
index 0078f08e..c97782b0 100644
--- a/app/src/main/java/app/passwordstore/ui/passwords/PasswordStore.kt
+++ b/app/src/main/java/app/passwordstore/ui/passwords/PasswordStore.kt
@@ -4,7 +4,6 @@
*/
package app.passwordstore.ui.passwords
-import android.annotation.SuppressLint
import android.content.ComponentName
import android.content.Context
import android.content.Intent
@@ -14,7 +13,6 @@ import android.view.Menu
import android.view.MenuItem
import android.view.MenuItem.OnActionExpandListener
import android.view.WindowManager
-import androidx.activity.result.contract.ActivityResultContracts.RequestPermission
import androidx.activity.result.contract.ActivityResultContracts.StartActivityForResult
import androidx.activity.viewModels
import androidx.appcompat.widget.SearchView
@@ -77,18 +75,6 @@ class PasswordStore : BaseGitActivity() {
ViewModelProvider.AndroidViewModelFactory(application)
}
- private val storagePermissionRequest =
- registerForActivityResult(RequestPermission()) { granted ->
- if (granted) checkLocalRepository()
- }
-
- private val directorySelectAction =
- registerForActivityResult(StartActivityForResult()) { result ->
- if (result.resultCode == RESULT_OK) {
- checkLocalRepository()
- }
- }
-
private val listRefreshAction =
registerForActivityResult(StartActivityForResult()) { result ->
if (result.resultCode == RESULT_OK) {
@@ -196,7 +182,6 @@ class PasswordStore : BaseGitActivity() {
return super.onKeyDown(keyCode, event)
}
- @SuppressLint("NewApi")
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_pwdstore)
@@ -313,12 +298,14 @@ class PasswordStore : BaseGitActivity() {
}
}
R.id.refresh -> refreshPasswordList()
- android.R.id.home -> onBackPressed()
+ android.R.id.home -> onBackPressedDispatcher.onBackPressed()
else -> return super.onOptionsItemSelected(item)
}
return true
}
+ @Deprecated("Deprecated in Java")
+ @Suppress("DEPRECATION")
override fun onBackPressed() {
if (getPasswordFragment()?.onBackPressedInActivity() != true) super.onBackPressed()
}
diff --git a/app/src/main/java/app/passwordstore/ui/settings/SettingsActivity.kt b/app/src/main/java/app/passwordstore/ui/settings/SettingsActivity.kt
index 7fc20d5d..e4a9de8c 100644
--- a/app/src/main/java/app/passwordstore/ui/settings/SettingsActivity.kt
+++ b/app/src/main/java/app/passwordstore/ui/settings/SettingsActivity.kt
@@ -10,6 +10,7 @@ import android.view.MenuItem
import androidx.appcompat.app.AppCompatActivity
import app.passwordstore.R
import app.passwordstore.databinding.ActivityPreferenceRecyclerviewBinding
+import app.passwordstore.util.extensions.getParcelableCompat
import app.passwordstore.util.extensions.viewBinding
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import de.Maxr1998.modernpreferences.Preference
@@ -84,7 +85,7 @@ class SettingsActivity : AppCompatActivity() {
}
}
savedInstanceState
- ?.getParcelable<PreferencesAdapter.SavedState>("adapter")
+ ?.getParcelableCompat<PreferencesAdapter.SavedState>("adapter")
?.let(adapter::loadSavedState)
binding.preferenceRecyclerView.adapter = adapter
}
@@ -106,6 +107,8 @@ class SettingsActivity : AppCompatActivity() {
}
}
+ @Deprecated("Deprecated in Java")
+ @Suppress("DEPRECATION")
override fun onBackPressed() {
if (!preferencesAdapter.goBack()) super.onBackPressed()
}
diff --git a/app/src/main/java/app/passwordstore/ui/sshkeygen/SshKeyGenActivity.kt b/app/src/main/java/app/passwordstore/ui/sshkeygen/SshKeyGenActivity.kt
index 8a3d3edf..67528d24 100644
--- a/app/src/main/java/app/passwordstore/ui/sshkeygen/SshKeyGenActivity.kt
+++ b/app/src/main/java/app/passwordstore/ui/sshkeygen/SshKeyGenActivity.kt
@@ -103,7 +103,7 @@ class SshKeyGenActivity : AppCompatActivity() {
override fun onOptionsItemSelected(item: MenuItem): Boolean {
return when (item.itemId) {
android.R.id.home -> {
- onBackPressed()
+ onBackPressedDispatcher.onBackPressed()
true
}
else -> super.onOptionsItemSelected(item)
diff --git a/app/src/main/java/app/passwordstore/util/autofill/Api30AutofillResponseBuilder.kt b/app/src/main/java/app/passwordstore/util/autofill/Api30AutofillResponseBuilder.kt
index f46d3c1a..997e27b4 100644
--- a/app/src/main/java/app/passwordstore/util/autofill/Api30AutofillResponseBuilder.kt
+++ b/app/src/main/java/app/passwordstore/util/autofill/Api30AutofillResponseBuilder.kt
@@ -7,9 +7,11 @@ package app.passwordstore.util.autofill
import android.content.Context
import android.content.IntentSender
+import android.os.Build
import android.service.autofill.Dataset
import android.service.autofill.FillCallback
import android.service.autofill.FillResponse
+import android.service.autofill.Presentations
import android.service.autofill.SaveInfo
import android.view.inputmethod.InlineSuggestionsRequest
import android.widget.inline.InlinePresentationSpec
@@ -61,6 +63,23 @@ constructor(
metadata: DatasetMetadata,
imeSpec: InlinePresentationSpec?,
): Dataset {
+ return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
+ makeIntentDataSetTiramisu(context, action, intentSender, metadata, imeSpec)
+ } else {
+ makeIntentDataSetR(context, action, intentSender, metadata, imeSpec)
+ }
+ }
+
+ /** Helper for creating an Autofill [Dataset]s for Android R and above. */
+ @RequiresApi(Build.VERSION_CODES.R)
+ @Suppress("DEPRECATION")
+ private fun makeIntentDataSetR(
+ context: Context,
+ action: AutofillAction,
+ intentSender: IntentSender,
+ metadata: DatasetMetadata,
+ imeSpec: InlinePresentationSpec?,
+ ): Dataset {
return Dataset.Builder(makeRemoteView(context, metadata)).run {
fillWith(scenario, action, credentials = null)
setAuthentication(intentSender)
@@ -74,6 +93,30 @@ constructor(
}
}
+ /** Helper for creating Autofill [Dataset]s for Android Tiramisu and above. */
+ @RequiresApi(Build.VERSION_CODES.TIRAMISU)
+ private fun makeIntentDataSetTiramisu(
+ context: Context,
+ action: AutofillAction,
+ intentSender: IntentSender,
+ metadata: DatasetMetadata,
+ imeSpec: InlinePresentationSpec?,
+ ): Dataset {
+ val presentationsBuilder = Presentations.Builder()
+ if (imeSpec != null) {
+ val inlinePresentation = makeInlinePresentation(context, imeSpec, metadata)
+ if (inlinePresentation != null) {
+ presentationsBuilder.setInlinePresentation(inlinePresentation)
+ }
+ }
+ val presentations = presentationsBuilder.build()
+ return Dataset.Builder(presentations).run {
+ fillWith(scenario, action, credentials = null)
+ setAuthentication(intentSender)
+ build()
+ }
+ }
+
private fun makeMatchDataset(
context: Context,
file: File,
diff --git a/app/src/main/java/app/passwordstore/util/autofill/AutofillResponseBuilder.kt b/app/src/main/java/app/passwordstore/util/autofill/AutofillResponseBuilder.kt
index 94a4a564..a198297c 100644
--- a/app/src/main/java/app/passwordstore/util/autofill/AutofillResponseBuilder.kt
+++ b/app/src/main/java/app/passwordstore/util/autofill/AutofillResponseBuilder.kt
@@ -54,6 +54,7 @@ constructor(
private val scenarioSupportsSave = scenario.hasPasswordFieldsToSave
private val canBeSaved = saveFlags != null && scenarioSupportsSave
+ @Suppress("DEPRECATION")
private fun makeIntentDataset(
context: Context,
action: AutofillAction,
@@ -212,7 +213,7 @@ constructor(
if (Build.VERSION.SDK_INT >= 28) {
Dataset.Builder()
} else {
- Dataset.Builder(makeRemoteView(context, makeEmptyMetadata()))
+ @Suppress("DEPRECATION") Dataset.Builder(makeRemoteView(context, makeEmptyMetadata()))
}
return builder.run {
if (scenario != null) fillWith(scenario, action, credentials)
diff --git a/app/src/main/java/app/passwordstore/util/extensions/AndroidExtensions.kt b/app/src/main/java/app/passwordstore/util/extensions/AndroidExtensions.kt
index ebb24a78..948d3827 100644
--- a/app/src/main/java/app/passwordstore/util/extensions/AndroidExtensions.kt
+++ b/app/src/main/java/app/passwordstore/util/extensions/AndroidExtensions.kt
@@ -10,7 +10,14 @@ import android.content.ClipboardManager
import android.content.Context
import android.content.Intent
import android.content.SharedPreferences
+import android.content.pm.ApplicationInfo
+import android.content.pm.PackageInfo
import android.content.pm.PackageManager
+import android.content.pm.PackageManager.ApplicationInfoFlags
+import android.content.pm.PackageManager.PackageInfoFlags
+import android.os.Build
+import android.os.Bundle
+import android.os.Parcelable
import android.util.Base64
import android.util.TypedValue
import android.view.View
@@ -132,3 +139,45 @@ fun SharedPreferences.getString(key: String): String? = getString(key, null)
fun String.base64(): String {
return Base64.encodeToString(encodeToByteArray(), Base64.NO_WRAP)
}
+
+inline fun <reified T> Bundle.getParcelableCompat(key: String): T? {
+ return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
+ getParcelable(key, T::class.java)
+ } else {
+ @Suppress("DEPRECATION") getParcelable(key)
+ }
+}
+
+inline fun <reified T : Parcelable> Bundle.getParcelableArrayListCompat(
+ key: String
+): ArrayList<T>? {
+ return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
+ getParcelableArrayList(key, T::class.java)
+ } else {
+ @Suppress("DEPRECATION") getParcelableArrayList(key)
+ }
+}
+
+inline fun <reified T : Parcelable> Intent.getParcelableExtraCompat(key: String): T? {
+ return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
+ getParcelableExtra(key, T::class.java)
+ } else {
+ @Suppress("DEPRECATION") getParcelableExtra(key)
+ }
+}
+
+fun PackageManager.getPackageInfoCompat(packageName: String, flags: Int): PackageInfo {
+ return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
+ getPackageInfo(packageName, PackageInfoFlags.of(flags.toLong()))
+ } else {
+ @Suppress("DEPRECATION") getPackageInfo(packageName, flags)
+ }
+}
+
+fun PackageManager.getApplicationInfoCompat(packageName: String, flags: Int): ApplicationInfo {
+ return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
+ getApplicationInfo(packageName, ApplicationInfoFlags.of(flags.toLong()))
+ } else {
+ @Suppress("DEPRECATION") getApplicationInfo(packageName, flags)
+ }
+}
diff --git a/app/src/main/java/app/passwordstore/util/services/ClipboardService.kt b/app/src/main/java/app/passwordstore/util/services/ClipboardService.kt
index 3d57e29b..c56c319b 100644
--- a/app/src/main/java/app/passwordstore/util/services/ClipboardService.kt
+++ b/app/src/main/java/app/passwordstore/util/services/ClipboardService.kt
@@ -39,7 +39,11 @@ class ClipboardService : Service() {
when (intent.action) {
ACTION_CLEAR -> {
clearClipboard()
- stopForeground(true)
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
+ stopForeground(STOP_FOREGROUND_REMOVE)
+ } else {
+ @Suppress("DEPRECATION") stopForeground(true)
+ }
stopSelf()
return super.onStartCommand(intent, flags, startId)
}
@@ -55,7 +59,11 @@ class ClipboardService : Service() {
withContext(Dispatchers.IO) { startTimer(time) }
withContext(Dispatchers.Main) {
clearClipboard()
- stopForeground(true)
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
+ stopForeground(STOP_FOREGROUND_REMOVE)
+ } else {
+ @Suppress("DEPRECATION") stopForeground(true)
+ }
stopSelf()
}
}
diff --git a/app/src/main/java/app/passwordstore/util/services/PasswordExportService.kt b/app/src/main/java/app/passwordstore/util/services/PasswordExportService.kt
index 536006f6..4d587621 100644
--- a/app/src/main/java/app/passwordstore/util/services/PasswordExportService.kt
+++ b/app/src/main/java/app/passwordstore/util/services/PasswordExportService.kt
@@ -17,6 +17,7 @@ import androidx.core.content.getSystemService
import androidx.documentfile.provider.DocumentFile
import app.passwordstore.R
import app.passwordstore.data.repo.PasswordRepository
+import app.passwordstore.util.extensions.getParcelableExtraCompat
import java.time.LocalDateTime
import java.time.format.DateTimeFormatter
import java.util.Calendar
@@ -29,7 +30,7 @@ class PasswordExportService : Service() {
if (intent != null) {
when (intent.action) {
ACTION_EXPORT_PASSWORD -> {
- val uri = intent.getParcelableExtra<Uri>("uri")
+ val uri = intent.getParcelableExtraCompat<Uri>("uri")
if (uri != null) {
val targetDirectory = DocumentFile.fromTreeUri(applicationContext, uri)
diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml
index bb54499a..885293f7 100644
--- a/app/src/main/res/values-de/strings.xml
+++ b/app/src/main/res/values-de/strings.xml
@@ -33,8 +33,6 @@
<string name="git_commit_move_text">Benenne %1$s in %2$s um.</string>
<string name="git_commit_move_multiple_text">Verschiebe mehrere Passwörter nach %1$s.</string>
<!-- PGPHandler -->
- <string name="clipboard_password_toast_text">Passwort ist in der Zwischenablage, du hast %d Sekunden, um es einzufügen.</string>
- <string name="clipboard_password_no_clear_toast_text">Passwort wurde in die Zwischenablage kopiert</string>
<string name="clipboard_copied_text">In die Zwischenablage kopiert</string>
<string name="file_toast_text">Bitte setze einen Pfad</string>
<string name="path_toast_text">Bitte setze einen Pfad</string>
diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml
index 711e91ed..ae0f27da 100644
--- a/app/src/main/res/values-fr/strings.xml
+++ b/app/src/main/res/values-fr/strings.xml
@@ -37,8 +37,6 @@
<string name="git_commit_move_text">Renommer %1$sà %2$s. </string>
<string name="git_commit_move_multiple_text">Déplacement de mots de passe vers %1$s.</string>
<!-- PGPHandler -->
- <string name="clipboard_password_toast_text">Mot de passe copié dans le presse papier, vous avez %d secondes pour coller celui-ci.</string>
- <string name="clipboard_password_no_clear_toast_text">Mot de passe copié dans le presse-papiers</string>
<string name="clipboard_copied_text">Copié dans le presse-papiers</string>
<string name="file_toast_text">Veuillez fournir un nom de fichier</string>
<string name="path_toast_text">Veuillez fournir un chemin d\'accès au fichier</string>
diff --git a/app/src/main/res/values-gl/strings.xml b/app/src/main/res/values-gl/strings.xml
index c2974b1c..2341f6b0 100644
--- a/app/src/main/res/values-gl/strings.xml
+++ b/app/src/main/res/values-gl/strings.xml
@@ -37,8 +37,6 @@
<string name="git_commit_move_text">Mudar nome %1$s a %2$s.</string>
<string name="git_commit_move_multiple_text">Mover varios contrasinais a %1$s.</string>
<!-- PGPHandler -->
- <string name="clipboard_password_toast_text">Contrasinal copiado ao portapapeis, tes %d segundos para pegala nalgures.</string>
- <string name="clipboard_password_no_clear_toast_text">Contrasinal copiado ao portapapeis</string>
<string name="clipboard_copied_text">Copiada ó portapapeis</string>
<string name="file_toast_text">Debes proporcionar un nome de ficheiro</string>
<string name="path_toast_text">Por favor indica a ruta ao ficheiro</string>
diff --git a/app/src/main/res/values-it/strings.xml b/app/src/main/res/values-it/strings.xml
index 1b994b28..ee70dd4f 100644
--- a/app/src/main/res/values-it/strings.xml
+++ b/app/src/main/res/values-it/strings.xml
@@ -37,8 +37,6 @@
<string name="git_commit_move_text">Rinomina %1$s in %2$s.</string>
<string name="git_commit_move_multiple_text">Sposta più password in %1$s.</string>
<!-- PGPHandler -->
- <string name="clipboard_password_toast_text">Password copiata negli appunti, hai %d secondi per incollarla da qualche parte.</string>
- <string name="clipboard_password_no_clear_toast_text">Password copiata negli appunti</string>
<string name="clipboard_copied_text">Copiato negli appunti</string>
<string name="file_toast_text">Sei pregato di fornire il nome di un file</string>
<string name="path_toast_text">Sei pregato di fornire il percorso di un file</string>
diff --git a/app/src/main/res/values-pt-rBR/strings.xml b/app/src/main/res/values-pt-rBR/strings.xml
index bd3290bb..847a89cd 100644
--- a/app/src/main/res/values-pt-rBR/strings.xml
+++ b/app/src/main/res/values-pt-rBR/strings.xml
@@ -37,8 +37,6 @@
<string name="git_commit_move_text">Renomear %1$s para %2$s.</string>
<string name="git_commit_move_multiple_text">Mova múltiplas senhas para %1$s.</string>
<!-- PGPHandler -->
- <string name="clipboard_password_toast_text">Senha copiada para área de transferência, você tem %d segundos para colá-la em algum lugar.</string>
- <string name="clipboard_password_no_clear_toast_text">Senha copiada para área de transferência</string>
<string name="clipboard_copied_text">Copiado para a área de transferência</string>
<string name="file_toast_text">Por favor, informe um nome de arquivo</string>
<string name="path_toast_text">Por favor, forneça o caminho do arquivo</string>
diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml
index 5119ed4d..54f2669f 100644
--- a/app/src/main/res/values-ru/strings.xml
+++ b/app/src/main/res/values-ru/strings.xml
@@ -41,8 +41,6 @@
<string name="git_commit_move_text">Переименовать %1$sв%2$s.</string>
<string name="git_commit_move_multiple_text">Переместить несколько паролей в %1$s.</string>
<!-- PGPHandler -->
- <string name="clipboard_password_toast_text">Пароль скопирован в буфер обмена, у вас есть %d секунд чтобы вставить его.</string>
- <string name="clipboard_password_no_clear_toast_text">Пароль скопирован в буфер обмена</string>
<string name="clipboard_copied_text">Скопировано в буфер обмена</string>
<string name="file_toast_text">Пожалуйста, укажите имя файла</string>
<string name="path_toast_text">Пожалуйста, задайте путь к файлу</string>
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 66e9374d..d2c9ab06 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -45,8 +45,6 @@
<string name="git_commit_move_multiple_text">Move multiple passwords to %1$s.</string>
<!-- PGPHandler -->
- <string name="clipboard_password_toast_text">Password copied to clipboard, you have %d seconds to paste it somewhere.</string>
- <string name="clipboard_password_no_clear_toast_text">Password copied to clipboard</string>
<string name="clipboard_copied_text">Copied to clipboard</string>
<string name="file_toast_text">Please provide a file name</string>
<string name="path_toast_text">Please provide a file path</string>
diff --git a/autofill-parser/src/main/java/com/github/androidpasswordstore/autofillparser/AutofillFormParser.kt b/autofill-parser/src/main/java/com/github/androidpasswordstore/autofillparser/AutofillFormParser.kt
index 78af009d..952bc3f0 100644
--- a/autofill-parser/src/main/java/com/github/androidpasswordstore/autofillparser/AutofillFormParser.kt
+++ b/autofill-parser/src/main/java/com/github/androidpasswordstore/autofillparser/AutofillFormParser.kt
@@ -7,7 +7,9 @@ package com.github.androidpasswordstore.autofillparser
import android.app.assist.AssistStructure
import android.content.Context
import android.content.pm.PackageManager
+import android.content.pm.PackageManager.ApplicationInfoFlags
import android.net.Uri
+import android.os.Build
import android.os.Bundle
import android.view.autofill.AutofillId
import androidx.annotation.RequiresApi
@@ -41,7 +43,15 @@ public sealed class FormOrigin(public open val identifier: String) {
is Web -> identifier
is App -> {
val info =
- context.packageManager.getApplicationInfo(identifier, PackageManager.GET_META_DATA)
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
+ context.packageManager.getApplicationInfo(
+ identifier,
+ ApplicationInfoFlags.of(PackageManager.GET_META_DATA.toLong())
+ )
+ } else {
+ @Suppress("DEPRECATION")
+ context.packageManager.getApplicationInfo(identifier, PackageManager.GET_META_DATA)
+ }
val label = context.packageManager.getApplicationLabel(info)
if (untrusted) "“$label”" else "$label"
}
diff --git a/autofill-parser/src/main/java/com/github/androidpasswordstore/autofillparser/AutofillHelper.kt b/autofill-parser/src/main/java/com/github/androidpasswordstore/autofillparser/AutofillHelper.kt
index 5874bf77..7e5a3d33 100644
--- a/autofill-parser/src/main/java/com/github/androidpasswordstore/autofillparser/AutofillHelper.kt
+++ b/autofill-parser/src/main/java/com/github/androidpasswordstore/autofillparser/AutofillHelper.kt
@@ -54,7 +54,15 @@ public fun computeCertificatesHash(context: Context, appPackage: String): String
val stableHashOld = stableHash(signaturesOld.map { it.toByteArray() })
if (Build.VERSION.SDK_INT >= 28) {
val info =
- context.packageManager.getPackageInfo(appPackage, PackageManager.GET_SIGNING_CERTIFICATES)
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
+ context.packageManager.getPackageInfo(
+ appPackage,
+ PackageManager.PackageInfoFlags.of(PackageManager.GET_SIGNING_CERTIFICATES.toLong())
+ )
+ } else {
+ @Suppress("DEPRECATION")
+ context.packageManager.getPackageInfo(appPackage, PackageManager.GET_SIGNING_CERTIFICATES)
+ }
val signaturesNew =
info.signingInfo.signingCertificateHistory ?: info.signingInfo.apkContentsSigners
val stableHashNew = stableHash(signaturesNew.map { it.toByteArray() })
diff --git a/autofill-parser/src/main/java/com/github/androidpasswordstore/autofillparser/AutofillScenario.kt b/autofill-parser/src/main/java/com/github/androidpasswordstore/autofillparser/AutofillScenario.kt
index 7476f56c..d2a95b40 100644
--- a/autofill-parser/src/main/java/com/github/androidpasswordstore/autofillparser/AutofillScenario.kt
+++ b/autofill-parser/src/main/java/com/github/androidpasswordstore/autofillparser/AutofillScenario.kt
@@ -5,8 +5,11 @@
package com.github.androidpasswordstore.autofillparser
import android.app.assist.AssistStructure
+import android.os.Build
import android.os.Bundle
+import android.os.Parcelable
import android.service.autofill.Dataset
+import android.service.autofill.Field
import android.view.autofill.AutofillId
import android.view.autofill.AutofillValue
import androidx.annotation.RequiresApi
@@ -54,17 +57,19 @@ public sealed class AutofillScenario<out T : Any> {
return try {
Builder<AutofillId>()
.apply {
- username = clientState.getParcelable(BUNDLE_KEY_USERNAME_ID)
+ username = clientState.getParcelableCompat(BUNDLE_KEY_USERNAME_ID)
fillUsername = clientState.getBoolean(BUNDLE_KEY_FILL_USERNAME)
- otp = clientState.getParcelable(BUNDLE_KEY_OTP_ID)
+ otp = clientState.getParcelableCompat(BUNDLE_KEY_OTP_ID)
currentPassword.addAll(
- clientState.getParcelableArrayList(BUNDLE_KEY_CURRENT_PASSWORD_IDS) ?: emptyList()
+ clientState.getParcelableArrayListCompat(BUNDLE_KEY_CURRENT_PASSWORD_IDS)
+ ?: emptyList()
)
newPassword.addAll(
- clientState.getParcelableArrayList(BUNDLE_KEY_NEW_PASSWORD_IDS) ?: emptyList()
+ clientState.getParcelableArrayListCompat(BUNDLE_KEY_NEW_PASSWORD_IDS) ?: emptyList()
)
genericPassword.addAll(
- clientState.getParcelableArrayList(BUNDLE_KEY_GENERIC_PASSWORD_IDS) ?: emptyList()
+ clientState.getParcelableArrayListCompat(BUNDLE_KEY_GENERIC_PASSWORD_IDS)
+ ?: emptyList()
)
}
.build()
@@ -73,6 +78,24 @@ public sealed class AutofillScenario<out T : Any> {
null
}
}
+
+ private inline fun <reified T> Bundle.getParcelableCompat(key: String): T? {
+ return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
+ getParcelable(key, T::class.java)
+ } else {
+ @Suppress("DEPRECATION") getParcelable(key)
+ }
+ }
+
+ private inline fun <reified T : Parcelable> Bundle.getParcelableArrayListCompat(
+ key: String
+ ): ArrayList<T>? {
+ return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
+ getParcelableArrayList(key, T::class.java)
+ } else {
+ @Suppress("DEPRECATION") getParcelableArrayList(key)
+ }
+ }
}
internal class Builder<T : Any> {
@@ -231,7 +254,11 @@ public fun Dataset.Builder.fillWith(
scenario.otp -> credentialsToFill.otp
else -> credentialsToFill.password
}
- setValue(field, AutofillValue.forText(value))
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
+ setField(field, Field.Builder().setValue(AutofillValue.forText(value)).build())
+ } else {
+ @Suppress("DEPRECATION") setValue(field, AutofillValue.forText(value))
+ }
}
}
diff --git a/autofill-parser/src/main/java/com/github/androidpasswordstore/autofillparser/FeatureAndTrustDetection.kt b/autofill-parser/src/main/java/com/github/androidpasswordstore/autofillparser/FeatureAndTrustDetection.kt
index 58f400ef..7c4d0c2e 100644
--- a/autofill-parser/src/main/java/com/github/androidpasswordstore/autofillparser/FeatureAndTrustDetection.kt
+++ b/autofill-parser/src/main/java/com/github/androidpasswordstore/autofillparser/FeatureAndTrustDetection.kt
@@ -7,6 +7,7 @@ package com.github.androidpasswordstore.autofillparser
import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
+import android.content.pm.PackageManager.ResolveInfoFlags
import android.net.Uri
import android.os.Build
import android.provider.Settings
@@ -247,7 +248,15 @@ public fun getInstalledBrowsersWithAutofillSupportLevel(
): List<Pair<String, BrowserAutofillSupportLevel>> {
val testWebIntent = Intent(Intent.ACTION_VIEW).apply { data = Uri.parse("https://example.org") }
val installedBrowsers =
- context.packageManager.queryIntentActivities(testWebIntent, PackageManager.MATCH_ALL)
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
+ context.packageManager.queryIntentActivities(
+ testWebIntent,
+ ResolveInfoFlags.of(PackageManager.MATCH_ALL.toLong())
+ )
+ } else {
+ @Suppress("DEPRECATION")
+ context.packageManager.queryIntentActivities(testWebIntent, PackageManager.MATCH_ALL)
+ }
return installedBrowsers
.map { it to getBrowserAutofillSupportLevel(context, it.activityInfo.packageName) }
.filter { it.first.isDefault || it.second != BrowserAutofillSupportLevel.None }
diff --git a/build-logic/android-plugins/src/main/kotlin/app/passwordstore/gradle/AndroidCommon.kt b/build-logic/android-plugins/src/main/kotlin/app/passwordstore/gradle/AndroidCommon.kt
index b90666c9..52357171 100644
--- a/build-logic/android-plugins/src/main/kotlin/app/passwordstore/gradle/AndroidCommon.kt
+++ b/build-logic/android-plugins/src/main/kotlin/app/passwordstore/gradle/AndroidCommon.kt
@@ -10,7 +10,7 @@ import org.gradle.kotlin.dsl.configure
object AndroidCommon {
fun configure(project: Project) {
project.extensions.configure<TestedExtension> {
- setCompileSdkVersion(32)
+ setCompileSdkVersion(33)
defaultConfig {
minSdk = 23
targetSdk = 31
diff --git a/config/detekt/detekt.yml b/config/detekt/detekt.yml
index 69a60690..78d50515 100644
--- a/config/detekt/detekt.yml
+++ b/config/detekt/detekt.yml
@@ -158,11 +158,11 @@ complexity:
TooManyFunctions:
active: true
excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**']
- thresholdInFiles: 11
- thresholdInClasses: 11
- thresholdInInterfaces: 11
- thresholdInObjects: 11
- thresholdInEnums: 11
+ thresholdInFiles: 15
+ thresholdInClasses: 15
+ thresholdInInterfaces: 15
+ thresholdInObjects: 15
+ thresholdInEnums: 15
ignoreDeprecated: false
ignorePrivate: false
ignoreOverridden: false