summaryrefslogtreecommitdiff
path: root/java/src
diff options
context:
space:
mode:
author Mark Renouf <mrenouf@google.com> 2024-05-24 09:34:52 -0400
committer Mark Renouf <mrenouf@google.com> 2024-05-29 21:45:15 -0400
commit5c9c3a7462dc45907ee30516f43aff68ada3d06d (patch)
tree00325e5d41b4e1bc8eefd1b6011d7778f2578207 /java/src
parent68c1cb781b1ed97398857b7b3054764a1173ec7f (diff)
Disable sharing when device is under active FRP lock
Prevent FRP bypass scenarios involving share intents This CL includes a cleanup of our Settings abstraction to cover Global, Secure and System, and updates existing tests. Bug: 327645387 Test: atest IntentResolver-tests-unit Test: atest ChooserActivityTest#chooserDisabledWhileDeviceFrpLocked Flag: EXEMPT refactor Change-Id: I928b6ea68aa8d6d710dc51eb70acd2cc2ec682c3
Diffstat (limited to 'java/src')
-rw-r--r--java/src/com/android/intentresolver/ChooserHelper.kt9
-rw-r--r--java/src/com/android/intentresolver/SecureSettings.kt27
-rw-r--r--java/src/com/android/intentresolver/platform/NearbyShareModule.kt2
-rw-r--r--java/src/com/android/intentresolver/platform/PlatformSecureSettings.kt46
-rw-r--r--java/src/com/android/intentresolver/platform/SecureSettings.kt41
-rw-r--r--java/src/com/android/intentresolver/platform/SettingsImpl.kt59
-rw-r--r--java/src/com/android/intentresolver/platform/SettingsModule.kt (renamed from java/src/com/android/intentresolver/platform/SecureSettingsModule.kt)7
-rw-r--r--java/src/com/android/intentresolver/platform/SettingsProxy.kt92
8 files changed, 166 insertions, 117 deletions
diff --git a/java/src/com/android/intentresolver/ChooserHelper.kt b/java/src/com/android/intentresolver/ChooserHelper.kt
index 6317ee1d..312911a6 100644
--- a/java/src/com/android/intentresolver/ChooserHelper.kt
+++ b/java/src/com/android/intentresolver/ChooserHelper.kt
@@ -18,6 +18,7 @@ package com.android.intentresolver
import android.app.Activity
import android.os.UserHandle
+import android.provider.Settings
import android.util.Log
import androidx.activity.ComponentActivity
import androidx.activity.viewModels
@@ -30,6 +31,7 @@ import com.android.intentresolver.annotation.JavaInterop
import com.android.intentresolver.contentpreview.payloadtoggle.data.repository.ActivityResultRepository
import com.android.intentresolver.contentpreview.payloadtoggle.data.repository.PendingSelectionCallbackRepository
import com.android.intentresolver.data.model.ChooserRequest
+import com.android.intentresolver.platform.GlobalSettings
import com.android.intentresolver.ui.viewmodel.ChooserViewModel
import com.android.intentresolver.validation.Invalid
import com.android.intentresolver.validation.Valid
@@ -84,6 +86,7 @@ constructor(
hostActivity: Activity,
private val activityResultRepo: ActivityResultRepository,
private val pendingSelectionCallbackRepo: PendingSelectionCallbackRepository,
+ private val globalSettings: GlobalSettings,
) : DefaultLifecycleObserver {
// This is guaranteed by Hilt, since only a ComponentActivity is injectable.
private val activity: ComponentActivity = hostActivity as ComponentActivity
@@ -124,6 +127,12 @@ constructor(
return
}
+ if (globalSettings.getBooleanOrNull(Settings.Global.SECURE_FRP_MODE) == true) {
+ Log.e(TAG, "Sharing disabled due to active FRP lock.")
+ activity.finish()
+ return
+ }
+
when (val request = viewModel.initialRequest) {
is Valid -> initializeActivity(request)
is Invalid -> reportErrorsAndFinish(request)
diff --git a/java/src/com/android/intentresolver/SecureSettings.kt b/java/src/com/android/intentresolver/SecureSettings.kt
deleted file mode 100644
index 1e938895..00000000
--- a/java/src/com/android/intentresolver/SecureSettings.kt
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright (C) 2023 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.
- */
-
-package com.android.intentresolver
-
-import android.content.ContentResolver
-import android.provider.Settings
-
-/** A proxy class for secure settings, for easier testing. */
-open class SecureSettings {
- open fun getString(resolver: ContentResolver, name: String): String? {
- return Settings.Secure.getString(resolver, name)
- }
-}
diff --git a/java/src/com/android/intentresolver/platform/NearbyShareModule.kt b/java/src/com/android/intentresolver/platform/NearbyShareModule.kt
index 6cb30b41..1e4b5241 100644
--- a/java/src/com/android/intentresolver/platform/NearbyShareModule.kt
+++ b/java/src/com/android/intentresolver/platform/NearbyShareModule.kt
@@ -41,7 +41,7 @@ object NearbyShareModule {
fun nearbyShareComponent(@ApplicationOwned resources: Resources, settings: SecureSettings) =
Optional.ofNullable(
ComponentName.unflattenFromString(
- settings.getString(NEARBY_SHARING_COMPONENT)?.ifEmpty { null }
+ settings.getStringOrNull(NEARBY_SHARING_COMPONENT)?.ifEmpty { null }
?: resources.getString(R.string.config_defaultNearbySharingComponent),
)
)
diff --git a/java/src/com/android/intentresolver/platform/PlatformSecureSettings.kt b/java/src/com/android/intentresolver/platform/PlatformSecureSettings.kt
deleted file mode 100644
index 0c802c97..00000000
--- a/java/src/com/android/intentresolver/platform/PlatformSecureSettings.kt
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright (C) 2024 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.
- */
-
-package com.android.intentresolver.platform
-
-import android.content.ContentResolver
-import android.provider.Settings
-import javax.inject.Inject
-
-/**
- * Implements [SecureSettings] backed by Settings.Secure and a ContentResolver.
- *
- * These methods make Binder calls and may block, so use on the Main thread should be avoided.
- */
-class PlatformSecureSettings @Inject constructor(private val resolver: ContentResolver) :
- SecureSettings {
-
- override fun getString(name: String): String? {
- return Settings.Secure.getString(resolver, name)
- }
-
- override fun getInt(name: String): Int? {
- return runCatching { Settings.Secure.getInt(resolver, name) }.getOrNull()
- }
-
- override fun getLong(name: String): Long? {
- return runCatching { Settings.Secure.getLong(resolver, name) }.getOrNull()
- }
-
- override fun getFloat(name: String): Float? {
- return runCatching { Settings.Secure.getFloat(resolver, name) }.getOrNull()
- }
-}
diff --git a/java/src/com/android/intentresolver/platform/SecureSettings.kt b/java/src/com/android/intentresolver/platform/SecureSettings.kt
deleted file mode 100644
index 8a1dc531..00000000
--- a/java/src/com/android/intentresolver/platform/SecureSettings.kt
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright (C) 2024 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.
- */
-
-package com.android.intentresolver.platform
-
-import android.provider.Settings.SettingNotFoundException
-
-/**
- * A component which provides access to values from [android.provider.Settings.Secure].
- *
- * All methods return nullable types instead of throwing [SettingNotFoundException] which yields
- * cleaner, more idiomatic Kotlin code:
- *
- * // apply a default: val foo = settings.getInt(FOO) ?: DEFAULT_FOO
- *
- * // assert if missing: val required = settings.getInt(REQUIRED_VALUE) ?: error("required value
- * missing")
- */
-interface SecureSettings {
-
- fun getString(name: String): String?
-
- fun getInt(name: String): Int?
-
- fun getLong(name: String): Long?
-
- fun getFloat(name: String): Float?
-}
diff --git a/java/src/com/android/intentresolver/platform/SettingsImpl.kt b/java/src/com/android/intentresolver/platform/SettingsImpl.kt
new file mode 100644
index 00000000..c7ff3521
--- /dev/null
+++ b/java/src/com/android/intentresolver/platform/SettingsImpl.kt
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2024 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.
+ */
+
+package com.android.intentresolver.platform
+
+import android.content.ContentResolver
+import android.provider.Settings
+import javax.inject.Inject
+
+object SettingsImpl {
+ /** An implementation of GlobalSettings which forwards to [Settings.Global] */
+ class Global @Inject constructor(private val contentResolver: ContentResolver) :
+ GlobalSettings {
+ override fun getStringOrNull(name: String): String? {
+ return Settings.Global.getString(contentResolver, name)
+ }
+
+ override fun putString(name: String, value: String): Boolean {
+ return Settings.Global.putString(contentResolver, name, value)
+ }
+ }
+
+ /** An implementation of SecureSettings which forwards to [Settings.Secure] */
+ class Secure @Inject constructor(private val contentResolver: ContentResolver) :
+ SecureSettings {
+ override fun getStringOrNull(name: String): String? {
+ return Settings.Secure.getString(contentResolver, name)
+ }
+
+ override fun putString(name: String, value: String): Boolean {
+ return Settings.Secure.putString(contentResolver, name, value)
+ }
+ }
+
+ /** An implementation of SystemSettings which forwards to [Settings.System] */
+ class System @Inject constructor(private val contentResolver: ContentResolver) :
+ SystemSettings {
+ override fun getStringOrNull(name: String): String? {
+ return Settings.System.getString(contentResolver, name)
+ }
+
+ override fun putString(name: String, value: String): Boolean {
+ return Settings.System.putString(contentResolver, name, value)
+ }
+ }
+}
diff --git a/java/src/com/android/intentresolver/platform/SecureSettingsModule.kt b/java/src/com/android/intentresolver/platform/SettingsModule.kt
index fa3ee4fe..3d5c50da 100644
--- a/java/src/com/android/intentresolver/platform/SecureSettingsModule.kt
+++ b/java/src/com/android/intentresolver/platform/SettingsModule.kt
@@ -24,7 +24,10 @@ import dagger.hilt.components.SingletonComponent
@Module
@InstallIn(SingletonComponent::class)
-interface SecureSettingsModule {
+interface SettingsModule {
+ @Binds @Reusable fun globalSettings(settings: SettingsImpl.Global): GlobalSettings
- @Binds @Reusable fun secureSettings(settings: PlatformSecureSettings): SecureSettings
+ @Binds @Reusable fun secureSettings(settings: SettingsImpl.Secure): SecureSettings
+
+ @Binds @Reusable fun systemSettings(settings: SettingsImpl.System): SystemSettings
}
diff --git a/java/src/com/android/intentresolver/platform/SettingsProxy.kt b/java/src/com/android/intentresolver/platform/SettingsProxy.kt
new file mode 100644
index 00000000..d97a0414
--- /dev/null
+++ b/java/src/com/android/intentresolver/platform/SettingsProxy.kt
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2024 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.
+ */
+
+package com.android.intentresolver.platform
+
+/** A proxy to Settings.Global */
+interface GlobalSettings : SettingsProxy
+
+/** A proxy to Settings.Secure */
+interface SecureSettings : SettingsProxy
+
+/** A proxy to Settings.System */
+interface SystemSettings : SettingsProxy
+
+/** A generic Settings proxy interface */
+sealed interface SettingsProxy {
+
+ /** Returns the String value set for the given settings key, or null if no value exists. */
+ fun getStringOrNull(name: String): String?
+
+ /**
+ * Writes a new string value for the given settings key.
+ *
+ * @return true if the value did not previously exist or was modified
+ */
+ fun putString(name: String, value: String): Boolean
+
+ /**
+ * Returns the Int value for the given settings key or null if no value exists or it cannot be
+ * interpreted as an Int.
+ */
+ fun getIntOrNull(name: String): Int? = getStringOrNull(name)?.toIntOrNull()
+
+ /**
+ * Writes a new int value for the given settings key.
+ *
+ * @return true if the value did not previously exist or was modified
+ */
+ fun putInt(name: String, value: Int): Boolean = putString(name, value.toString())
+
+ /**
+ * Returns the Boolean value for the given settings key or null if no value exists or it cannot
+ * be interpreted as a Boolean.
+ */
+ fun getBooleanOrNull(name: String): Boolean? = getIntOrNull(name)?.let { it != 0 }
+
+ /**
+ * Writes a new Boolean value for the given settings key.
+ *
+ * @return true if the value did not previously exist or was modified
+ */
+ fun putBoolean(name: String, value: Boolean): Boolean = putInt(name, if (value) 1 else 0)
+
+ /**
+ * Returns the Long value for the given settings key or null if no value exists or it cannot be
+ * interpreted as a Long.
+ */
+ fun getLongOrNull(name: String): Long? = getStringOrNull(name)?.toLongOrNull()
+
+ /**
+ * Writes a new Long value for the given settings key.
+ *
+ * @return true if the value did not previously exist or was modified
+ */
+ fun putLong(name: String, value: Long): Boolean = putString(name, value.toString())
+
+ /**
+ * Returns the Float value for the given settings key or null if no value exists or it cannot be
+ * interpreted as a Float.
+ */
+ fun getFloatOrNull(name: String): Float? = getStringOrNull(name)?.toFloatOrNull()
+
+ /**
+ * Writes a new float value for the given settings key.
+ *
+ * @return true if the value did not previously exist or was modified
+ */
+ fun putFloat(name: String, value: Float): Boolean = putString(name, value.toString())
+}