summaryrefslogtreecommitdiff
path: root/java/src
diff options
context:
space:
mode:
author Mark Renouf <mrenouf@google.com> 2024-03-15 17:27:43 +0000
committer Android (Google) Code Review <android-gerrit@google.com> 2024-03-15 17:27:43 +0000
commitca4cdfeeff66ac180e75fdd59b448375caa56cd5 (patch)
tree296f2dbef284ede2f929e5377c9f8cf973294fd4 /java/src
parent3e5527c7e60aade6609abc7e0a903ec9e128817e (diff)
parent1a887c18ad79b5a935799f5100233db1be982ee1 (diff)
Merge changes Ia8dfe178,I348558b3 into main
* changes: Correct all Kotlin formatting errors Readability clean up for UserRepository
Diffstat (limited to 'java/src')
-rw-r--r--java/src/com/android/intentresolver/EnterTransitionAnimationDelegate.kt35
-rw-r--r--java/src/com/android/intentresolver/ItemRevealAnimationTracker.kt4
-rw-r--r--java/src/com/android/intentresolver/SecureSettings.kt4
-rw-r--r--java/src/com/android/intentresolver/contentpreview/IsHttpUri.kt11
-rw-r--r--java/src/com/android/intentresolver/inject/SystemServices.kt3
-rw-r--r--java/src/com/android/intentresolver/shortcuts/AppPredictorFactory.kt34
-rw-r--r--java/src/com/android/intentresolver/util/Flow.kt10
-rw-r--r--java/src/com/android/intentresolver/v2/annotation/JavaInterop.kt6
-rw-r--r--java/src/com/android/intentresolver/v2/data/repository/UserRepository.kt134
-rw-r--r--java/src/com/android/intentresolver/v2/data/repository/UserScopedService.kt6
-rw-r--r--java/src/com/android/intentresolver/v2/domain/interactor/UserInteractor.kt4
-rw-r--r--java/src/com/android/intentresolver/v2/platform/AppPredictionModule.kt7
-rw-r--r--java/src/com/android/intentresolver/v2/ui/ProfilePagerResources.kt4
-rw-r--r--java/src/com/android/intentresolver/v2/ui/ShortcutPolicyModule.kt27
-rw-r--r--java/src/com/android/intentresolver/v2/ui/model/ResolverRequest.kt2
-rw-r--r--java/src/com/android/intentresolver/v2/validation/types/IntentOrUri.kt10
-rw-r--r--java/src/com/android/intentresolver/v2/validation/types/ParceledArray.kt11
-rw-r--r--java/src/com/android/intentresolver/v2/validation/types/SimpleValue.kt25
-rw-r--r--java/src/com/android/intentresolver/widget/ActionRow.kt4
-rw-r--r--java/src/com/android/intentresolver/widget/ImagePreviewView.kt13
-rw-r--r--java/src/com/android/intentresolver/widget/RecyclerViewExtensions.kt8
-rw-r--r--java/src/com/android/intentresolver/widget/ViewExtensions.kt27
22 files changed, 229 insertions, 160 deletions
diff --git a/java/src/com/android/intentresolver/EnterTransitionAnimationDelegate.kt b/java/src/com/android/intentresolver/EnterTransitionAnimationDelegate.kt
index b1178aa5..6a4fe65a 100644
--- a/java/src/com/android/intentresolver/EnterTransitionAnimationDelegate.kt
+++ b/java/src/com/android/intentresolver/EnterTransitionAnimationDelegate.kt
@@ -21,14 +21,14 @@ import androidx.activity.ComponentActivity
import androidx.lifecycle.lifecycleScope
import com.android.intentresolver.widget.ImagePreviewView.TransitionElementStatusCallback
import com.android.internal.annotations.VisibleForTesting
+import java.util.function.Supplier
import kotlinx.coroutines.Job
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
-import java.util.function.Supplier
/**
- * A helper class to track app's readiness for the scene transition animation.
- * The app is ready when both the image is laid out and the drawer offset is calculated.
+ * A helper class to track app's readiness for the scene transition animation. The app is ready when
+ * both the image is laid out and the drawer offset is calculated.
*/
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
class EnterTransitionAnimationDelegate(
@@ -45,21 +45,22 @@ class EnterTransitionAnimationDelegate(
activity.setEnterSharedElementCallback(
object : SharedElementCallback() {
override fun onMapSharedElements(
- names: MutableList<String>, sharedElements: MutableMap<String, View>
+ names: MutableList<String>,
+ sharedElements: MutableMap<String, View>
) {
- this@EnterTransitionAnimationDelegate.onMapSharedElements(
- names, sharedElements
- )
+ this@EnterTransitionAnimationDelegate.onMapSharedElements(names, sharedElements)
}
- })
+ }
+ )
}
fun postponeTransition() {
activity.postponeEnterTransition()
- timeoutJob = activity.lifecycleScope.launch {
- delay(activity.resources.getInteger(R.integer.config_shortAnimTime).toLong())
- onTimeout()
- }
+ timeoutJob =
+ activity.lifecycleScope.launch {
+ delay(activity.resources.getInteger(R.integer.config_shortAnimTime).toLong())
+ onTimeout()
+ }
}
private fun onTimeout() {
@@ -110,8 +111,14 @@ class EnterTransitionAnimationDelegate(
override fun onLayoutChange(
v: View,
- left: Int, top: Int, right: Int, bottom: Int,
- oldLeft: Int, oldTop: Int, oldRight: Int, oldBottom: Int
+ left: Int,
+ top: Int,
+ right: Int,
+ bottom: Int,
+ oldLeft: Int,
+ oldTop: Int,
+ oldRight: Int,
+ oldBottom: Int
) {
v.removeOnLayoutChangeListener(this)
startPostponedEnterTransition()
diff --git a/java/src/com/android/intentresolver/ItemRevealAnimationTracker.kt b/java/src/com/android/intentresolver/ItemRevealAnimationTracker.kt
index d3e07c6b..7deb0d10 100644
--- a/java/src/com/android/intentresolver/ItemRevealAnimationTracker.kt
+++ b/java/src/com/android/intentresolver/ItemRevealAnimationTracker.kt
@@ -37,9 +37,7 @@ internal class ItemRevealAnimationTracker {
fun animateLabel(view: View, info: TargetInfo) = animateView(view, info, labelProgress)
private fun animateView(view: View, info: TargetInfo, map: MutableMap<TargetInfo, Record>) {
- val record = map.getOrPut(info) {
- Record()
- }
+ val record = map.getOrPut(info) { Record() }
if ((view.animation as? RevealAnimation)?.record === record) return
view.clearAnimation()
diff --git a/java/src/com/android/intentresolver/SecureSettings.kt b/java/src/com/android/intentresolver/SecureSettings.kt
index a4853fd8..1e938895 100644
--- a/java/src/com/android/intentresolver/SecureSettings.kt
+++ b/java/src/com/android/intentresolver/SecureSettings.kt
@@ -19,9 +19,7 @@ package com.android.intentresolver
import android.content.ContentResolver
import android.provider.Settings
-/**
- * A proxy class for secure settings, for easier testing.
- */
+/** 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/contentpreview/IsHttpUri.kt b/java/src/com/android/intentresolver/contentpreview/IsHttpUri.kt
index 80232537..ac002ab6 100644
--- a/java/src/com/android/intentresolver/contentpreview/IsHttpUri.kt
+++ b/java/src/com/android/intentresolver/contentpreview/IsHttpUri.kt
@@ -15,13 +15,16 @@
*/
@file:JvmName("HttpUriMatcher")
+
package com.android.intentresolver.contentpreview
import java.net.URI
internal fun String.isHttpUri() =
- kotlin.runCatching {
- URI(this).scheme.takeIf { scheme ->
- "http".compareTo(scheme, true) == 0 || "https".compareTo(scheme, true) == 0
+ kotlin
+ .runCatching {
+ URI(this).scheme.takeIf { scheme ->
+ "http".compareTo(scheme, true) == 0 || "https".compareTo(scheme, true) == 0
+ }
}
- }.getOrNull() != null
+ .getOrNull() != null
diff --git a/java/src/com/android/intentresolver/inject/SystemServices.kt b/java/src/com/android/intentresolver/inject/SystemServices.kt
index 069c926c..9e7c67b6 100644
--- a/java/src/com/android/intentresolver/inject/SystemServices.kt
+++ b/java/src/com/android/intentresolver/inject/SystemServices.kt
@@ -103,7 +103,8 @@ class UserManagerModule {
@Provides
fun userManager(@ApplicationContext ctx: Context): UserManager = ctx.requireSystemService()
- @Provides fun scopedUserManager(ctx: UserScopedContext): UserScopedService<UserManager> {
+ @Provides
+ fun scopedUserManager(ctx: UserScopedContext): UserScopedService<UserManager> {
return UserScopedServiceImpl(ctx, UserManager::class)
}
}
diff --git a/java/src/com/android/intentresolver/shortcuts/AppPredictorFactory.kt b/java/src/com/android/intentresolver/shortcuts/AppPredictorFactory.kt
index e544e064..c7bd0336 100644
--- a/java/src/com/android/intentresolver/shortcuts/AppPredictorFactory.kt
+++ b/java/src/com/android/intentresolver/shortcuts/AppPredictorFactory.kt
@@ -31,12 +31,13 @@ private const val SHARED_TEXT_KEY = "shared_text"
/**
* A factory to create an AppPredictor instance for a profile, if available.
+ *
* @param context, application context
- * @param sharedText, a shared text associated with the Chooser's target intent
- * (see [android.content.Intent.EXTRA_TEXT]).
- * Will be mapped to app predictor's "shared_text" parameter.
- * @param targetIntentFilter, an IntentFilter to match direct share targets against.
- * Will be mapped app predictor's "intent_filter" parameter.
+ * @param sharedText, a shared text associated with the Chooser's target intent (see
+ * [android.content.Intent.EXTRA_TEXT]). Will be mapped to app predictor's "shared_text"
+ * parameter.
+ * @param targetIntentFilter, an IntentFilter to match direct share targets against. Will be mapped
+ * app predictor's "intent_filter" parameter.
*/
class AppPredictorFactory(
private val context: Context,
@@ -50,16 +51,19 @@ class AppPredictorFactory(
fun create(userHandle: UserHandle): AppPredictor? {
if (!appPredictionAvailable) return null
val contextAsUser = context.createContextAsUser(userHandle, 0 /* flags */)
- val extras = Bundle().apply {
- putParcelable(APP_PREDICTION_INTENT_FILTER_KEY, targetIntentFilter)
- putString(SHARED_TEXT_KEY, sharedText)
- }
- val appPredictionContext = AppPredictionContext.Builder(contextAsUser)
- .setUiSurface(APP_PREDICTION_SHARE_UI_SURFACE)
- .setPredictedTargetCount(APP_PREDICTION_SHARE_TARGET_QUERY_PACKAGE_LIMIT)
- .setExtras(extras)
- .build()
- return contextAsUser.getSystemService(AppPredictionManager::class.java)
+ val extras =
+ Bundle().apply {
+ putParcelable(APP_PREDICTION_INTENT_FILTER_KEY, targetIntentFilter)
+ putString(SHARED_TEXT_KEY, sharedText)
+ }
+ val appPredictionContext =
+ AppPredictionContext.Builder(contextAsUser)
+ .setUiSurface(APP_PREDICTION_SHARE_UI_SURFACE)
+ .setPredictedTargetCount(APP_PREDICTION_SHARE_TARGET_QUERY_PACKAGE_LIMIT)
+ .setExtras(extras)
+ .build()
+ return contextAsUser
+ .getSystemService(AppPredictionManager::class.java)
?.createAppPredictionSession(appPredictionContext)
}
}
diff --git a/java/src/com/android/intentresolver/util/Flow.kt b/java/src/com/android/intentresolver/util/Flow.kt
index 1155b9fe..598379f3 100644
--- a/java/src/com/android/intentresolver/util/Flow.kt
+++ b/java/src/com/android/intentresolver/util/Flow.kt
@@ -31,7 +31,6 @@ import kotlinx.coroutines.launch
* latest value is emitted.
*
* Example:
- *
* ```kotlin
* flow {
* emit(1) // t=0ms
@@ -70,10 +69,11 @@ fun <T> Flow<T>.throttle(periodMs: Long): Flow<T> = channelFlow {
// We create delayJob to allow cancellation during the delay period
delayJob = launch {
delay(timeUntilNextEmit)
- sendJob = outerScope.launch(start = CoroutineStart.UNDISPATCHED) {
- send(it)
- previousEmitTimeMs = SystemClock.elapsedRealtime()
- }
+ sendJob =
+ outerScope.launch(start = CoroutineStart.UNDISPATCHED) {
+ send(it)
+ previousEmitTimeMs = SystemClock.elapsedRealtime()
+ }
}
} else {
send(it)
diff --git a/java/src/com/android/intentresolver/v2/annotation/JavaInterop.kt b/java/src/com/android/intentresolver/v2/annotation/JavaInterop.kt
index 15c5018a..a813358e 100644
--- a/java/src/com/android/intentresolver/v2/annotation/JavaInterop.kt
+++ b/java/src/com/android/intentresolver/v2/annotation/JavaInterop.kt
@@ -21,6 +21,8 @@ package com.android.intentresolver.v2.annotation
*
* The goal is to prevent usage from Kotlin when a more idiomatic alternative is available.
*/
-@RequiresOptIn("This is a a property, function or class specifically supporting Java " +
- "interoperability. Usage from Kotlin should be limited to interactions with Java.")
+@RequiresOptIn(
+ "This is a a property, function or class specifically supporting Java " +
+ "interoperability. Usage from Kotlin should be limited to interactions with Java."
+)
annotation class JavaInterop
diff --git a/java/src/com/android/intentresolver/v2/data/repository/UserRepository.kt b/java/src/com/android/intentresolver/v2/data/repository/UserRepository.kt
index 4c42e2cd..40672249 100644
--- a/java/src/com/android/intentresolver/v2/data/repository/UserRepository.kt
+++ b/java/src/com/android/intentresolver/v2/data/repository/UserRepository.kt
@@ -28,6 +28,7 @@ import android.content.Intent.EXTRA_QUIET_MODE
import android.content.Intent.EXTRA_USER
import android.content.IntentFilter
import android.content.pm.UserInfo
+import android.os.Build
import android.os.UserHandle
import android.os.UserManager
import android.util.Log
@@ -36,7 +37,6 @@ import com.android.intentresolver.inject.Background
import com.android.intentresolver.inject.Main
import com.android.intentresolver.inject.ProfileParent
import com.android.intentresolver.v2.data.broadcastFlow
-import com.android.intentresolver.v2.data.repository.UserRepositoryImpl.UserEvent
import com.android.intentresolver.v2.shared.model.User
import dagger.hilt.android.qualifiers.ApplicationContext
import javax.inject.Inject
@@ -73,7 +73,7 @@ interface UserRepository {
* stopping a profile user (along with their many associated processes).
*
* If successful, the change will be applied after the call returns and can be observed using
- * [UserRepository.isAvailable] for the given user.
+ * [UserRepository.availability] for the given user.
*
* No actions are taken if the user is already in requested state.
*
@@ -84,9 +84,9 @@ interface UserRepository {
private const val TAG = "UserRepository"
-private data class UserWithState(val user: User, val available: Boolean)
+internal data class UserWithState(val user: User, val available: Boolean)
-private typealias UserStates = List<UserWithState>
+internal typealias UserStates = List<UserWithState>
/** Tracks and publishes state for the parent user and associated profiles. */
class UserRepositoryImpl
@@ -114,13 +114,21 @@ constructor(
background
)
- data class UserEvent(val action: String, val user: UserHandle, val quietMode: Boolean = false)
+ private fun debugLog(msg: () -> String) {
+ if (Build.IS_USERDEBUG || Build.IS_ENG) {
+ Log.d(TAG, msg())
+ }
+ }
+
+ private fun errorLog(msg: String, caught: Throwable? = null) {
+ Log.e(TAG, msg, caught)
+ }
/**
* An exception which indicates that an inconsistency exists between the user state map and the
* rest of the system.
*/
- internal class UserStateException(
+ private class UserStateException(
override val message: String,
val event: UserEvent,
override val cause: Throwable? = null
@@ -129,35 +137,34 @@ constructor(
private val sharingScope = CoroutineScope(scope.coroutineContext + backgroundDispatcher)
private val usersWithState: Flow<UserStates> =
userEvents
- .onStart { emit(UserEvent(INITIALIZE, profileParent)) }
- .onEach { Log.i(TAG, "userEvent: $it") }
- .runningFold<UserEvent, UserStates>(emptyList()) { users, event ->
- try {
- // Handle an action by performing some operation, then returning a new map
- when (event.action) {
- INITIALIZE -> createNewUserStates(profileParent)
- ACTION_PROFILE_ADDED -> handleProfileAdded(event, users)
- ACTION_PROFILE_REMOVED -> handleProfileRemoved(event, users)
- ACTION_MANAGED_PROFILE_UNAVAILABLE,
- ACTION_MANAGED_PROFILE_AVAILABLE,
- ACTION_PROFILE_AVAILABLE,
- ACTION_PROFILE_UNAVAILABLE -> handleAvailability(event, users)
- else -> {
- Log.w(TAG, "Unhandled event: $event)")
- users
- }
- }
- } catch (e: UserStateException) {
- Log.e(TAG, "An error occurred handling an event: ${e.event}", e)
- Log.e(TAG, "Attempting to recover...")
- createNewUserStates(profileParent)
- }
- }
+ .onStart { emit(Initialize) }
+ .onEach { debugLog { "userEvent: $it" } }
+ .runningFold(emptyList(), ::handleEvent)
.distinctUntilChanged()
- .onEach { Log.i(TAG, "userStateList: $it") }
+ .onEach { debugLog { "userStateList: $it" } }
.stateIn(sharingScope, SharingStarted.Eagerly, emptyList())
.filterNot { it.isEmpty() }
+ private suspend fun handleEvent(users: UserStates, event: UserEvent): UserStates {
+ return try {
+ // Handle an action by performing some operation, then returning a new map
+ when (event) {
+ is Initialize -> createNewUserStates(profileParent)
+ is ProfileAdded -> handleProfileAdded(event, users)
+ is ProfileRemoved -> handleProfileRemoved(event, users)
+ is AvailabilityChange -> handleAvailability(event, users)
+ is UnknownEvent -> {
+ debugLog { "Unhandled event: $event)" }
+ users
+ }
+ }
+ } catch (e: UserStateException) {
+ errorLog("An error occurred handling an event: ${e.event}")
+ errorLog("Attempting to recover...", e)
+ createNewUserStates(profileParent)
+ }
+ }
+
override val users: Flow<List<User>> =
usersWithState.map { userStateMap -> userStateMap.map { it.user } }.distinctUntilChanged()
@@ -168,7 +175,7 @@ constructor(
override suspend fun requestState(user: User, available: Boolean) {
return withContext(backgroundDispatcher) {
- Log.i(TAG, "requestQuietModeEnabled: ${!available} for user $user")
+ debugLog { "requestQuietModeEnabled: ${!available} for user $user" }
userManager.requestQuietModeEnabled(/* enableQuietMode = */ !available, user.handle)
}
}
@@ -176,28 +183,28 @@ constructor(
private fun List<UserWithState>.update(handle: UserHandle, user: UserWithState) =
filter { it.user.id != handle.identifier } + user
- private fun handleAvailability(event: UserEvent, current: UserStates): UserStates {
+ private fun handleAvailability(event: AvailabilityChange, current: UserStates): UserStates {
val userEntry =
current.firstOrNull { it.user.id == event.user.identifier }
?: throw UserStateException("User was not present in the map", event)
return current.update(event.user, userEntry.copy(available = !event.quietMode))
}
- private fun handleProfileRemoved(event: UserEvent, current: UserStates): UserStates {
+ private fun handleProfileRemoved(event: ProfileRemoved, current: UserStates): UserStates {
if (!current.any { it.user.id == event.user.identifier }) {
throw UserStateException("User was not present in the map", event)
}
return current.filter { it.user.id != event.user.identifier }
}
- private suspend fun handleProfileAdded(event: UserEvent, current: UserStates): UserStates {
+ private suspend fun handleProfileAdded(event: ProfileAdded, current: UserStates): UserStates {
val user =
try {
requireNotNull(readUser(event.user))
} catch (e: Exception) {
throw UserStateException("Failed to read user from UserManager", event, e)
}
- return current + UserWithState(user, !event.quietMode)
+ return current + UserWithState(user, true)
}
private suspend fun createNewUserStates(user: UserHandle): UserStates {
@@ -224,29 +231,64 @@ constructor(
}
}
+/** A Model representing changes to profiles and availability */
+sealed interface UserEvent
+
+/** Used as a an initial value to trigger a fetch of all profile data. */
+data object Initialize : UserEvent
+
+/** A profile was added to the profile group. */
+data class ProfileAdded(
+ /** The handle for the added profile. */
+ val user: UserHandle,
+) : UserEvent
+
+/** A profile was removed from the profile group. */
+data class ProfileRemoved(
+ /** The handle for the removed profile. */
+ val user: UserHandle,
+) : UserEvent
+
+/** A profile has changed availability. */
+data class AvailabilityChange(
+ /** THe handle for the profile with availability change. */
+ val user: UserHandle,
+ /** The new quietMode state. */
+ val quietMode: Boolean = false,
+) : UserEvent
+
+/** An unhandled event, logged and ignored. */
+data class UnknownEvent(
+ /** The broadcast intent action received */
+ val action: String?,
+) : UserEvent
+
/** Used with [broadcastFlow] to transform a UserManager broadcast action into a [UserEvent]. */
-private fun Intent.toUserEvent(): UserEvent? {
+private fun Intent.toUserEvent(): UserEvent {
val action = action
val user = extras?.getParcelable(EXTRA_USER, UserHandle::class.java)
- val quietMode = extras?.getBoolean(EXTRA_QUIET_MODE, false) ?: false
- return if (user == null || action == null) {
- null
- } else {
- UserEvent(action, user, quietMode)
+ val quietMode = extras?.getBoolean(EXTRA_QUIET_MODE, false)
+ return when (action) {
+ ACTION_PROFILE_ADDED -> ProfileAdded(requireNotNull(user))
+ ACTION_PROFILE_REMOVED -> ProfileRemoved(requireNotNull(user))
+ ACTION_MANAGED_PROFILE_UNAVAILABLE,
+ ACTION_MANAGED_PROFILE_AVAILABLE,
+ ACTION_PROFILE_AVAILABLE,
+ ACTION_PROFILE_UNAVAILABLE ->
+ AvailabilityChange(requireNotNull(user), requireNotNull(quietMode))
+ else -> UnknownEvent(action)
}
}
-const val INITIALIZE = "INITIALIZE"
-
private fun createFilter(actions: Iterable<String>): IntentFilter {
return IntentFilter().apply { actions.forEach(::addAction) }
}
-private fun UserInfo?.isAvailable(): Boolean {
+internal fun UserInfo?.isAvailable(): Boolean {
return this?.isQuietModeEnabled != true
}
-private fun userBroadcastFlow(context: Context, profileParent: UserHandle): Flow<UserEvent> {
+internal fun userBroadcastFlow(context: Context, profileParent: UserHandle): Flow<UserEvent> {
val userActions =
setOf(
ACTION_PROFILE_ADDED,
diff --git a/java/src/com/android/intentresolver/v2/data/repository/UserScopedService.kt b/java/src/com/android/intentresolver/v2/data/repository/UserScopedService.kt
index 07903a7b..507979a0 100644
--- a/java/src/com/android/intentresolver/v2/data/repository/UserScopedService.kt
+++ b/java/src/com/android/intentresolver/v2/data/repository/UserScopedService.kt
@@ -76,10 +76,8 @@ class UserScopedContext @Inject constructor(private val applicationContext: Cont
}
/** Returns a cache of service instances, distinct by user */
-class UserScopedServiceImpl<T : Any>(
- contexts: UserScopedContext,
- serviceType: KClass<T>
-): UserScopedService<T> {
+class UserScopedServiceImpl<T : Any>(contexts: UserScopedContext, serviceType: KClass<T>) :
+ UserScopedService<T> {
private val instances =
object : LruCache<UserHandle, T>(8) {
override fun create(key: UserHandle): T {
diff --git a/java/src/com/android/intentresolver/v2/domain/interactor/UserInteractor.kt b/java/src/com/android/intentresolver/v2/domain/interactor/UserInteractor.kt
index 72b604c2..69374f88 100644
--- a/java/src/com/android/intentresolver/v2/domain/interactor/UserInteractor.kt
+++ b/java/src/com/android/intentresolver/v2/domain/interactor/UserInteractor.kt
@@ -71,9 +71,7 @@ constructor(
*/
val availability: Flow<Map<Profile, Boolean>> =
combine(profiles, userRepository.availability) { profiles, availability ->
- profiles.associateWith {
- availability.getOrDefault(it.primary, false)
- }
+ profiles.associateWith { availability.getOrDefault(it.primary, false) }
}
/**
diff --git a/java/src/com/android/intentresolver/v2/platform/AppPredictionModule.kt b/java/src/com/android/intentresolver/v2/platform/AppPredictionModule.kt
index 9ca9d871..090fab6b 100644
--- a/java/src/com/android/intentresolver/v2/platform/AppPredictionModule.kt
+++ b/java/src/com/android/intentresolver/v2/platform/AppPredictionModule.kt
@@ -18,7 +18,6 @@ package com.android.intentresolver.v2.platform
import android.content.pm.PackageManager
import dagger.Module
import dagger.Provides
-import dagger.Reusable
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
import javax.inject.Qualifier
@@ -33,13 +32,11 @@ annotation class AppPredictionAvailable
@InstallIn(SingletonComponent::class)
object AppPredictionModule {
- /**
- * Eventually replaced with: Optional<AppPredictionRepository>, etc.
- */
+ /** Eventually replaced with: Optional<AppPredictionRepository>, etc. */
@Provides
@Singleton
@AppPredictionAvailable
fun isAppPredictionAvailable(packageManager: PackageManager): Boolean {
return packageManager.appPredictionServicePackageName != null
}
-} \ No newline at end of file
+}
diff --git a/java/src/com/android/intentresolver/v2/ui/ProfilePagerResources.kt b/java/src/com/android/intentresolver/v2/ui/ProfilePagerResources.kt
index 1cd72ba5..ca7ae0fc 100644
--- a/java/src/com/android/intentresolver/v2/ui/ProfilePagerResources.kt
+++ b/java/src/com/android/intentresolver/v2/ui/ProfilePagerResources.kt
@@ -17,11 +17,11 @@
package com.android.intentresolver.v2.ui
import android.content.res.Resources
+import com.android.intentresolver.R
import com.android.intentresolver.inject.ApplicationOwned
import com.android.intentresolver.v2.data.repository.DevicePolicyResources
import com.android.intentresolver.v2.shared.model.Profile
import javax.inject.Inject
-import com.android.intentresolver.R
class ProfilePagerResources
@Inject
@@ -50,4 +50,4 @@ constructor(
Profile.Type.PRIVATE -> privateTabAccessibilityLabel
}
}
-} \ No newline at end of file
+}
diff --git a/java/src/com/android/intentresolver/v2/ui/ShortcutPolicyModule.kt b/java/src/com/android/intentresolver/v2/ui/ShortcutPolicyModule.kt
index 9ed5f9dd..5e098cd5 100644
--- a/java/src/com/android/intentresolver/v2/ui/ShortcutPolicyModule.kt
+++ b/java/src/com/android/intentresolver/v2/ui/ShortcutPolicyModule.kt
@@ -29,11 +29,19 @@ import javax.inject.Qualifier
import javax.inject.Singleton
@Qualifier
-@MustBeDocumented @Retention(AnnotationRetention.RUNTIME) annotation class AppShortcutLimit
+@MustBeDocumented
+@Retention(AnnotationRetention.RUNTIME)
+annotation class AppShortcutLimit
+
@Qualifier
-@MustBeDocumented @Retention(AnnotationRetention.RUNTIME) annotation class EnforceShortcutLimit
+@MustBeDocumented
+@Retention(AnnotationRetention.RUNTIME)
+annotation class EnforceShortcutLimit
+
@Qualifier
-@MustBeDocumented @Retention(AnnotationRetention.RUNTIME) annotation class ShortcutRowLimit
+@MustBeDocumented
+@Retention(AnnotationRetention.RUNTIME)
+annotation class ShortcutRowLimit
@Module
@InstallIn(SingletonComponent::class)
@@ -41,8 +49,8 @@ object ShortcutPolicyModule {
/**
* Defines the limit for the number of shortcut targets provided for any single app.
*
- * This value applies to both results from Shortcut-service and app-provided targets on
- * a per-package basis.
+ * This value applies to both results from Shortcut-service and app-provided targets on a
+ * per-package basis.
*/
@Provides
@Singleton
@@ -64,8 +72,11 @@ object ShortcutPolicyModule {
@Singleton
@EnforceShortcutLimit
fun applyShortcutLimit(): Boolean {
- return DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_SYSTEMUI,
- SystemUiDeviceConfigFlags.APPLY_SHARING_APP_LIMITS_IN_SYSUI, true)
+ return DeviceConfig.getBoolean(
+ DeviceConfig.NAMESPACE_SYSTEMUI,
+ SystemUiDeviceConfigFlags.APPLY_SHARING_APP_LIMITS_IN_SYSUI,
+ true
+ )
}
/**
@@ -80,4 +91,4 @@ object ShortcutPolicyModule {
fun shortcutRowLimit(@ApplicationOwned resources: Resources): Int {
return resources.getInteger(R.integer.config_chooser_max_targets_per_row)
}
-} \ No newline at end of file
+}
diff --git a/java/src/com/android/intentresolver/v2/ui/model/ResolverRequest.kt b/java/src/com/android/intentresolver/v2/ui/model/ResolverRequest.kt
index a4f74ca9..44010caf 100644
--- a/java/src/com/android/intentresolver/v2/ui/model/ResolverRequest.kt
+++ b/java/src/com/android/intentresolver/v2/ui/model/ResolverRequest.kt
@@ -19,8 +19,8 @@ package com.android.intentresolver.v2.ui.model
import android.content.Intent
import android.content.pm.ResolveInfo
import android.os.UserHandle
-import com.android.intentresolver.v2.shared.model.Profile
import com.android.intentresolver.v2.ext.isHomeIntent
+import com.android.intentresolver.v2.shared.model.Profile
/** All of the things that are consumed from an incoming Intent Resolution request (+Extras). */
data class ResolverRequest(
diff --git a/java/src/com/android/intentresolver/v2/validation/types/IntentOrUri.kt b/java/src/com/android/intentresolver/v2/validation/types/IntentOrUri.kt
index 050bd895..fc51ba1e 100644
--- a/java/src/com/android/intentresolver/v2/validation/types/IntentOrUri.kt
+++ b/java/src/com/android/intentresolver/v2/validation/types/IntentOrUri.kt
@@ -31,7 +31,6 @@ class IntentOrUri(override val key: String) : Validator<Intent> {
source: (String) -> Any?,
importance: Importance
): ValidationResult<Intent> {
-
return when (val value = source(key)) {
// An intent, return it.
is Intent -> Valid(value)
@@ -41,10 +40,11 @@ class IntentOrUri(override val key: String) : Validator<Intent> {
is Uri -> Valid(Intent.parseUri(value.toString(), Intent.URI_INTENT_SCHEME))
// No value present.
- null -> when (importance) {
- Importance.WARNING -> Invalid() // No warnings if optional, but missing
- Importance.CRITICAL -> Invalid(NoValue(key, importance, Intent::class))
- }
+ null ->
+ when (importance) {
+ Importance.WARNING -> Invalid() // No warnings if optional, but missing
+ Importance.CRITICAL -> Invalid(NoValue(key, importance, Intent::class))
+ }
// Some other type.
else -> {
diff --git a/java/src/com/android/intentresolver/v2/validation/types/ParceledArray.kt b/java/src/com/android/intentresolver/v2/validation/types/ParceledArray.kt
index 78adfd36..b68d972f 100644
--- a/java/src/com/android/intentresolver/v2/validation/types/ParceledArray.kt
+++ b/java/src/com/android/intentresolver/v2/validation/types/ParceledArray.kt
@@ -15,7 +15,6 @@
*/
package com.android.intentresolver.v2.validation.types
-import android.content.Intent
import com.android.intentresolver.v2.validation.Importance
import com.android.intentresolver.v2.validation.Invalid
import com.android.intentresolver.v2.validation.NoValue
@@ -36,13 +35,13 @@ class ParceledArray<T : Any>(
source: (String) -> Any?,
importance: Importance
): ValidationResult<List<T>> {
-
return when (val value: Any? = source(key)) {
// No value present.
- null -> when (importance) {
- Importance.WARNING -> Invalid() // No warnings if optional, but missing
- Importance.CRITICAL -> Invalid(NoValue(key, importance, elementType))
- }
+ null ->
+ when (importance) {
+ Importance.WARNING -> Invalid() // No warnings if optional, but missing
+ Importance.CRITICAL -> Invalid(NoValue(key, importance, elementType))
+ }
// A parcel does not transfer the element type information for parcelable
// arrays. This leads to a restored type of Array<Parcelable>, which is
// incompatible with Array<T : Parcelable>.
diff --git a/java/src/com/android/intentresolver/v2/validation/types/SimpleValue.kt b/java/src/com/android/intentresolver/v2/validation/types/SimpleValue.kt
index 0105541d..0badebc4 100644
--- a/java/src/com/android/intentresolver/v2/validation/types/SimpleValue.kt
+++ b/java/src/com/android/intentresolver/v2/validation/types/SimpleValue.kt
@@ -37,21 +37,24 @@ class SimpleValue<T : Any>(
expected.isInstance(value) -> return Valid(expected.cast(value))
// No value is present.
- value == null -> when (importance) {
- Importance.WARNING -> Invalid() // No warnings if optional, but missing
- Importance.CRITICAL -> Invalid(NoValue(key, importance, expected))
- }
+ value == null ->
+ when (importance) {
+ Importance.WARNING -> Invalid() // No warnings if optional, but missing
+ Importance.CRITICAL -> Invalid(NoValue(key, importance, expected))
+ }
// The value is some other type.
else ->
- Invalid(listOf(
- ValueIsWrongType(
- key,
- importance,
- actualType = value::class,
- allowedTypes = listOf(expected)
+ Invalid(
+ listOf(
+ ValueIsWrongType(
+ key,
+ importance,
+ actualType = value::class,
+ allowedTypes = listOf(expected)
+ )
)
- ))
+ )
}
}
}
diff --git a/java/src/com/android/intentresolver/widget/ActionRow.kt b/java/src/com/android/intentresolver/widget/ActionRow.kt
index 6764d3ae..c1f03751 100644
--- a/java/src/com/android/intentresolver/widget/ActionRow.kt
+++ b/java/src/com/android/intentresolver/widget/ActionRow.kt
@@ -22,7 +22,9 @@ import android.graphics.drawable.Drawable
interface ActionRow {
fun setActions(actions: List<Action>)
- class Action @JvmOverloads constructor(
+ class Action
+ @JvmOverloads
+ constructor(
// TODO: apparently, IDs set to this field are used in unit tests only; evaluate whether we
// get rid of them
val id: Int = ID_NULL,
diff --git a/java/src/com/android/intentresolver/widget/ImagePreviewView.kt b/java/src/com/android/intentresolver/widget/ImagePreviewView.kt
index 3f0458ee..55418c49 100644
--- a/java/src/com/android/intentresolver/widget/ImagePreviewView.kt
+++ b/java/src/com/android/intentresolver/widget/ImagePreviewView.kt
@@ -24,15 +24,16 @@ interface ImagePreviewView {
/**
* [ImagePreviewView] progressively prepares views for shared element transition and reports
- * each successful preparation with [onTransitionElementReady] call followed by
- * closing [onAllTransitionElementsReady] invocation. Thus the overall invocation pattern is
- * zero or more [onTransitionElementReady] calls followed by the final
- * [onAllTransitionElementsReady] call.
+ * each successful preparation with [onTransitionElementReady] call followed by closing
+ * [onAllTransitionElementsReady] invocation. Thus the overall invocation pattern is zero or
+ * more [onTransitionElementReady] calls followed by the final [onAllTransitionElementsReady]
+ * call.
*/
interface TransitionElementStatusCallback {
/**
- * Invoked when a view for a shared transition animation element is ready i.e. the image
- * is loaded and the view is laid out.
+ * Invoked when a view for a shared transition animation element is ready i.e. the image is
+ * loaded and the view is laid out.
+ *
* @param name shared element name.
*/
fun onTransitionElementReady(name: String)
diff --git a/java/src/com/android/intentresolver/widget/RecyclerViewExtensions.kt b/java/src/com/android/intentresolver/widget/RecyclerViewExtensions.kt
index a7906001..a8aa633b 100644
--- a/java/src/com/android/intentresolver/widget/RecyclerViewExtensions.kt
+++ b/java/src/com/android/intentresolver/widget/RecyclerViewExtensions.kt
@@ -26,10 +26,10 @@ internal val RecyclerView.areAllChildrenVisible: Boolean
val first = getChildAt(0)
val last = getChildAt(count - 1)
val itemCount = adapter?.itemCount ?: 0
- return getChildAdapterPosition(first) == 0
- && getChildAdapterPosition(last) == itemCount - 1
- && isFullyVisible(first)
- && isFullyVisible(last)
+ return getChildAdapterPosition(first) == 0 &&
+ getChildAdapterPosition(last) == itemCount - 1 &&
+ isFullyVisible(first) &&
+ isFullyVisible(last)
}
private fun RecyclerView.isFullyVisible(view: View): Boolean =
diff --git a/java/src/com/android/intentresolver/widget/ViewExtensions.kt b/java/src/com/android/intentresolver/widget/ViewExtensions.kt
index 11b7c146..d19933f5 100644
--- a/java/src/com/android/intentresolver/widget/ViewExtensions.kt
+++ b/java/src/com/android/intentresolver/widget/ViewExtensions.kt
@@ -19,21 +19,26 @@ package com.android.intentresolver.widget
import android.util.Log
import android.view.View
import androidx.core.view.OneShotPreDrawListener
-import kotlinx.coroutines.suspendCancellableCoroutine
import java.util.concurrent.atomic.AtomicBoolean
+import kotlinx.coroutines.suspendCancellableCoroutine
internal suspend fun View.waitForPreDraw(): Unit = suspendCancellableCoroutine { continuation ->
val isResumed = AtomicBoolean(false)
- val callback = OneShotPreDrawListener.add(
- this,
- Runnable {
- if (isResumed.compareAndSet(false, true)) {
- continuation.resumeWith(Result.success(Unit))
- } else {
- // it's not really expected but in some unknown corner-case let's not crash
- Log.e("waitForPreDraw", "An attempt to resume a completed coroutine", Exception())
+ val callback =
+ OneShotPreDrawListener.add(
+ this,
+ Runnable {
+ if (isResumed.compareAndSet(false, true)) {
+ continuation.resumeWith(Result.success(Unit))
+ } else {
+ // it's not really expected but in some unknown corner-case let's not crash
+ Log.e(
+ "waitForPreDraw",
+ "An attempt to resume a completed coroutine",
+ Exception()
+ )
+ }
}
- }
- )
+ )
continuation.invokeOnCancellation { callback.removeListener() }
}