summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--java/src/com/android/intentresolver/v2/data/repository/UserScopedService.kt46
1 files changed, 46 insertions, 0 deletions
diff --git a/java/src/com/android/intentresolver/v2/data/repository/UserScopedService.kt b/java/src/com/android/intentresolver/v2/data/repository/UserScopedService.kt
new file mode 100644
index 00000000..7ee78d91
--- /dev/null
+++ b/java/src/com/android/intentresolver/v2/data/repository/UserScopedService.kt
@@ -0,0 +1,46 @@
+package com.android.intentresolver.v2.data.repository
+
+import android.content.Context
+import androidx.core.content.getSystemService
+import com.android.intentresolver.v2.data.model.User
+
+/**
+ * Provides cached instances of a [system service][Context.getSystemService] created with
+ * [the context of a specified user][Context.createContextAsUser].
+ *
+ * System services which have only `@UserHandleAware` APIs operate on the user id available from
+ * [Context.getUser], the context used to retrieve the service. This utility helps adapt a per-user
+ * API model to work in multi-user manner.
+ *
+ * Example usage:
+ * ```
+ * val usageStats = userScopedService<UsageStatsManager>(context)
+ *
+ * fun getStatsForUser(
+ * user: User,
+ * from: Long,
+ * to: Long
+ * ): UsageStats {
+ * return usageStats.forUser(user)
+ * .queryUsageStats(INTERVAL_BEST, from, to)
+ * }
+ * ```
+ */
+interface UserScopedService<T> {
+ fun forUser(user: User): T
+}
+
+inline fun <reified T> userScopedService(context: Context): UserScopedService<T> {
+ return object : UserScopedService<T> {
+ private val map = mutableMapOf<User, T>()
+
+ override fun forUser(user: User): T {
+ return synchronized(this) {
+ map.getOrPut(user) {
+ val userContext = context.createContextAsUser(user.handle, 0)
+ requireNotNull(userContext.getSystemService())
+ }
+ }
+ }
+ }
+}