summaryrefslogtreecommitdiff
path: root/java/src
diff options
context:
space:
mode:
Diffstat (limited to 'java/src')
-rw-r--r--java/src/com/android/intentresolver/v2/ChooserActivity.java19
-rw-r--r--java/src/com/android/intentresolver/v2/ChooserHelper.kt40
-rw-r--r--java/src/com/android/intentresolver/v2/ProfileAvailability.kt23
-rw-r--r--java/src/com/android/intentresolver/v2/ProfileHelper.kt19
4 files changed, 43 insertions, 58 deletions
diff --git a/java/src/com/android/intentresolver/v2/ChooserActivity.java b/java/src/com/android/intentresolver/v2/ChooserActivity.java
index d624c9e4..5f3129f8 100644
--- a/java/src/com/android/intentresolver/v2/ChooserActivity.java
+++ b/java/src/com/android/intentresolver/v2/ChooserActivity.java
@@ -124,6 +124,7 @@ import com.android.intentresolver.emptystate.EmptyState;
import com.android.intentresolver.emptystate.EmptyStateProvider;
import com.android.intentresolver.grid.ChooserGridAdapter;
import com.android.intentresolver.icons.TargetDataLoader;
+import com.android.intentresolver.inject.Background;
import com.android.intentresolver.logging.EventLog;
import com.android.intentresolver.measurements.Tracer;
import com.android.intentresolver.model.AbstractResolverComparator;
@@ -185,6 +186,8 @@ import java.util.function.Supplier;
import javax.inject.Inject;
+import kotlinx.coroutines.CoroutineDispatcher;
+
/**
* The Chooser Activity handles intent resolution specifically for sharing intents -
* for example, as generated by {@see android.content.Intent#createChooser(Intent, CharSequence)}.
@@ -265,6 +268,7 @@ public class ChooserActivity extends Hilt_ChooserActivity implements
private static final int SCROLL_STATUS_SCROLLING_HORIZONTAL = 2;
@Inject public UserInteractor mUserInteractor;
+ @Inject @Background public CoroutineDispatcher mBackgroundDispatcher;
@Inject public ChooserHelper mChooserHelper;
@Inject public FeatureFlags mFeatureFlags;
@Inject public android.service.chooser.FeatureFlags mChooserServiceFeatureFlags;
@@ -352,7 +356,7 @@ public class ChooserActivity extends Hilt_ChooserActivity implements
setTheme(R.style.Theme_DeviceDefault_Chooser);
// Initializer is invoked when this function returns, via Lifecycle.
- mChooserHelper.setInitializer(this::initializeWith);
+ mChooserHelper.setInitializer(this::initialize);
if (mChooserServiceFeatureFlags.chooserPayloadToggling()) {
mChooserHelper.setOnChooserRequestChanged(this::onChooserRequestChanged);
}
@@ -467,8 +471,7 @@ public class ChooserActivity extends Hilt_ChooserActivity implements
}
/** DO NOT CALL. Only for use from ChooserHelper as a callback. */
- private void initializeWith(InitialState initialState) {
- Log.d(TAG, "initializeWith: " + initialState);
+ private void initialize() {
mViewModel = new ViewModelProvider(this).get(ChooserViewModel.class);
mRequest = mViewModel.getRequest().getValue();
@@ -476,14 +479,14 @@ public class ChooserActivity extends Hilt_ChooserActivity implements
mProfiles = new ProfileHelper(
mUserInteractor,
- mFeatureFlags,
- initialState.getProfiles(),
- initialState.getLaunchedAs());
+ getCoroutineScope(getLifecycle()),
+ mBackgroundDispatcher,
+ mFeatureFlags);
mProfileAvailability = new ProfileAvailability(
- getCoroutineScope(getLifecycle()),
mUserInteractor,
- initialState.getAvailability());
+ getCoroutineScope(getLifecycle()),
+ mBackgroundDispatcher);
mProfileAvailability.setOnProfileStatusChange(this::onWorkProfileStatusUpdated);
diff --git a/java/src/com/android/intentresolver/v2/ChooserHelper.kt b/java/src/com/android/intentresolver/v2/ChooserHelper.kt
index 503e46d8..9da0d605 100644
--- a/java/src/com/android/intentresolver/v2/ChooserHelper.kt
+++ b/java/src/com/android/intentresolver/v2/ChooserHelper.kt
@@ -31,7 +31,6 @@ import com.android.intentresolver.inject.Background
import com.android.intentresolver.v2.annotation.JavaInterop
import com.android.intentresolver.v2.data.model.ChooserRequest
import com.android.intentresolver.v2.domain.interactor.UserInteractor
-import com.android.intentresolver.v2.shared.model.Profile
import com.android.intentresolver.v2.ui.viewmodel.ChooserViewModel
import com.android.intentresolver.v2.validation.Invalid
import com.android.intentresolver.v2.validation.Valid
@@ -43,35 +42,10 @@ import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.flow.filterNotNull
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.launch
-import kotlinx.coroutines.runBlocking
private const val TAG: String = "ChooserHelper"
/**
- * Provides initial values to ChooserActivity and completes initialization from onCreate.
- *
- * This information is collected and provided on behalf of ChooserActivity to eliminate the need for
- * suspending functions within remaining synchronous startup code.
- */
-@JavaInterop
-fun interface ChooserInitializer {
- /** @param initialState the initial state to provide to initialization */
- fun initializeWith(initialState: InitialState)
-}
-
-/**
- * A parameter object for Initialize which contains all the values which are required "early", on
- * the main thread and outside of any coroutines. This supports code which expects to be called by
- * the system on the main thread only. (This includes everything originally called from onCreate).
- */
-@JavaInterop
-data class InitialState(
- val profiles: List<Profile>,
- val availability: Map<Profile, Boolean>,
- val launchedAs: Profile
-)
-
-/**
* __Purpose__
*
* Cleanup aid. Provides a pathway to cleaner code.
@@ -113,7 +87,7 @@ constructor(
private val activity: ComponentActivity = hostActivity as ComponentActivity
private val viewModel by activity.viewModels<ChooserViewModel>()
- private lateinit var activityInitializer: ChooserInitializer
+ private lateinit var activityInitializer: Runnable
var onChooserRequestChanged: Consumer<ChooserRequest> = Consumer {}
@@ -126,7 +100,7 @@ constructor(
*
* This _must_ be called from [ChooserActivity.onCreate].
*/
- fun setInitializer(initializer: ChooserInitializer) {
+ fun setInitializer(initializer: Runnable) {
check(activity.lifecycle.currentState == Lifecycle.State.INITIALIZED) {
"setInitializer must be called before onCreate returns"
}
@@ -189,14 +163,6 @@ constructor(
private fun initializeActivity(request: Valid<ChooserRequest>) {
request.warnings.forEach { it.log(TAG) }
-
- val initialState =
- runBlocking(background) {
- val initialProfiles = userInteractor.profiles.first()
- val initialAvailability = userInteractor.availability.first()
- val launchedAsProfile = userInteractor.launchedAsProfile.first()
- InitialState(initialProfiles, initialAvailability, launchedAsProfile)
- }
- activityInitializer.initializeWith(initialState)
+ activityInitializer.run()
}
}
diff --git a/java/src/com/android/intentresolver/v2/ProfileAvailability.kt b/java/src/com/android/intentresolver/v2/ProfileAvailability.kt
index ddb57991..27d8c6bb 100644
--- a/java/src/com/android/intentresolver/v2/ProfileAvailability.kt
+++ b/java/src/com/android/intentresolver/v2/ProfileAvailability.kt
@@ -16,27 +16,26 @@
package com.android.intentresolver.v2
+import androidx.annotation.MainThread
import com.android.intentresolver.v2.annotation.JavaInterop
import com.android.intentresolver.v2.domain.interactor.UserInteractor
import com.android.intentresolver.v2.shared.model.Profile
+import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Job
-import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.flow.first
-import kotlinx.coroutines.flow.stateIn
+import kotlinx.coroutines.flow.map
import kotlinx.coroutines.launch
+import kotlinx.coroutines.runBlocking
/** Provides availability status for profiles */
@JavaInterop
class ProfileAvailability(
- private val scope: CoroutineScope,
private val userInteractor: UserInteractor,
- initialState: Map<Profile, Boolean>
+ private val scope: CoroutineScope,
+ private val background: CoroutineDispatcher,
) {
- private val availability =
- userInteractor.availability.stateIn(scope, SharingStarted.Eagerly, initialState)
-
/** Used by WorkProfilePausedEmptyStateProvider */
var waitingToEnableProfile = false
private set
@@ -45,8 +44,14 @@ class ProfileAvailability(
var onProfileStatusChange: Runnable? = null
private var waitJob: Job? = null
+
/** Query current profile availability. An unavailable profile is one which is not active. */
- fun isAvailable(profile: Profile) = availability.value[profile] ?: false
+ @MainThread
+ fun isAvailable(profile: Profile): Boolean {
+ return runBlocking(background) {
+ userInteractor.availability.map { it[profile] == true }.first()
+ }
+ }
/** Used by WorkProfilePausedEmptyStateProvider */
fun requestQuietModeState(profile: Profile, quietMode: Boolean) {
@@ -65,7 +70,7 @@ class ProfileAvailability(
val job =
scope.launch {
// Wait for the profile to become available
- availability.filter { it[profile] == true }.first()
+ userInteractor.availability.filter { it[profile] == true }.first()
}
job.invokeOnCompletion {
waitingToEnableProfile = false
diff --git a/java/src/com/android/intentresolver/v2/ProfileHelper.kt b/java/src/com/android/intentresolver/v2/ProfileHelper.kt
index 8a8e6b54..87948150 100644
--- a/java/src/com/android/intentresolver/v2/ProfileHelper.kt
+++ b/java/src/com/android/intentresolver/v2/ProfileHelper.kt
@@ -17,29 +17,40 @@
package com.android.intentresolver.v2
import android.os.UserHandle
+import androidx.annotation.MainThread
import com.android.intentresolver.inject.IntentResolverFlags
import com.android.intentresolver.v2.annotation.JavaInterop
import com.android.intentresolver.v2.domain.interactor.UserInteractor
import com.android.intentresolver.v2.shared.model.Profile
import com.android.intentresolver.v2.shared.model.User
import javax.inject.Inject
+import kotlinx.coroutines.CoroutineDispatcher
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.flow.first
+import kotlinx.coroutines.runBlocking
@JavaInterop
+@MainThread
class ProfileHelper
@Inject
constructor(
interactor: UserInteractor,
+ private val scope: CoroutineScope,
+ private val background: CoroutineDispatcher,
private val flags: IntentResolverFlags,
- val profiles: List<Profile>,
- val launchedAsProfile: Profile,
) {
private val launchedByHandle: UserHandle = interactor.launchedAs
+ val launchedAsProfile by lazy {
+ runBlocking(background) { interactor.launchedAsProfile.first() }
+ }
+ val profiles by lazy { runBlocking(background) { interactor.profiles.first() } }
+
// Map UserHandle back to a user within launchedByProfile
- private val launchedByUser =
+ private val launchedByUser: User =
when (launchedByHandle) {
launchedAsProfile.primary.handle -> launchedAsProfile.primary
- launchedAsProfile.clone?.handle -> launchedAsProfile.clone
+ launchedAsProfile.clone?.handle -> requireNotNull(launchedAsProfile.clone)
else -> error("launchedByUser must be a member of launchedByProfile")
}
val launchedAsProfileType: Profile.Type = launchedAsProfile.type