diff options
author | 2024-04-19 18:12:41 +0000 | |
---|---|---|
committer | 2024-04-19 18:12:41 +0000 | |
commit | 767be2d49a2576aa980a4761d9f7c484a9fc18d6 (patch) | |
tree | c850c674de5ab9354b6f55abc760fbf5763fe15c | |
parent | 16b13dc38e94325fcaee07bc94470dc5c7e4b10f (diff) | |
parent | 4ca5dc54a57d61b8bd116a2259f51a7cdc5ea184 (diff) |
Merge "Fix "NoAppsAvailableEmptyStateProvider" message for Private" into main
7 files changed, 112 insertions, 79 deletions
diff --git a/java/res/values/strings.xml b/java/res/values/strings.xml index 5c1210b7..17a514d7 100644 --- a/java/res/values/strings.xml +++ b/java/res/values/strings.xml @@ -295,6 +295,9 @@ <!-- Error message. This text lets the user know that their current personal apps don't support the specific content. [CHAR LIMIT=NONE] --> <string name="resolver_no_personal_apps_available">No personal apps</string> + <!-- Error message. This text lets the user know that their current private apps don't support the specific content. [CHAR LIMIT=NONE] --> + <string name="resolver_no_private_apps_available">No private apps</string> + <!-- Dialog title. User must choose between opening content in a cross-profile app or same-profile browser. [CHAR LIMIT=NONE] --> <string name="miniresolver_open_in_personal">Open <xliff:g id="app" example="YouTube">%s</xliff:g> in your personal profile?</string> <!-- Dialog title. User must choose between opening content in a cross-profile app or same-profile browser. [CHAR LIMIT=NONE] --> diff --git a/java/src/com/android/intentresolver/ChooserActivity.java b/java/src/com/android/intentresolver/ChooserActivity.java index 7e2c9c5a..43d28761 100644 --- a/java/src/com/android/intentresolver/ChooserActivity.java +++ b/java/src/com/android/intentresolver/ChooserActivity.java @@ -1051,11 +1051,10 @@ public class ChooserActivity extends Hilt_ChooserActivity implements getMetricsCategory()); EmptyStateProvider noAppsEmptyStateProvider = new NoAppsAvailableEmptyStateProvider( - this, - profileHelper.getWorkHandle(), - profileHelper.getPersonalHandle(), + mProfiles, + mProfileAvailability, getMetricsCategory(), - profileHelper.getTabOwnerUserHandleForLaunch() + mProfilePagerResources ); // Return composite provider, the order matters (the higher, the more priority) diff --git a/java/src/com/android/intentresolver/ProfileAvailability.kt b/java/src/com/android/intentresolver/ProfileAvailability.kt index cf3e566e..c8e78552 100644 --- a/java/src/com/android/intentresolver/ProfileAvailability.kt +++ b/java/src/com/android/intentresolver/ProfileAvailability.kt @@ -53,6 +53,24 @@ class ProfileAvailability( } } + /** + * The number of profiles which are visible. All profiles count except for private which is + * hidden when locked. + */ + fun visibleProfileCount() = + runBlocking(background) { + val availability = userInteractor.availability.first() + val profiles = userInteractor.profiles.first() + profiles + .filter { + when (it.type) { + Profile.Type.PRIVATE -> availability[it] == true + else -> true + } + } + .size + } + /** Used by WorkProfilePausedEmptyStateProvider */ fun requestQuietModeState(profile: Profile, quietMode: Boolean) { val enableProfile = !quietMode diff --git a/java/src/com/android/intentresolver/ResolverActivity.java b/java/src/com/android/intentresolver/ResolverActivity.java index 2f1f8ee5..4e763f94 100644 --- a/java/src/com/android/intentresolver/ResolverActivity.java +++ b/java/src/com/android/intentresolver/ResolverActivity.java @@ -112,6 +112,7 @@ import com.android.intentresolver.profiles.ResolverMultiProfilePagerAdapter; import com.android.intentresolver.profiles.TabConfig; import com.android.intentresolver.shared.model.Profile; import com.android.intentresolver.ui.ActionTitle; +import com.android.intentresolver.ui.ProfilePagerResources; import com.android.intentresolver.ui.model.ActivityModel; import com.android.intentresolver.ui.model.ResolverRequest; import com.android.intentresolver.ui.viewmodel.ResolverViewModel; @@ -153,6 +154,7 @@ public class ResolverActivity extends Hilt_ResolverActivity implements @Inject public ResolverHelper mResolverHelper; @Inject public PackageManager mPackageManager; @Inject public DevicePolicyResources mDevicePolicyResources; + @Inject public ProfilePagerResources mProfilePagerResources; @Inject public IntentForwarding mIntentForwarding; @Inject public FeatureFlags mFeatureFlags; @@ -963,12 +965,11 @@ public class ResolverActivity extends Hilt_ResolverActivity implements }, getMetricsCategory()); - final EmptyStateProvider noAppsEmptyStateProvider = new NoAppsAvailableEmptyStateProvider( - this, - workProfileUserHandle, - mProfiles.getPersonalHandle(), + EmptyStateProvider noAppsEmptyStateProvider = new NoAppsAvailableEmptyStateProvider( + mProfiles, + mProfileAvailability, getMetricsCategory(), - mProfiles.getTabOwnerUserHandleForLaunch() + mProfilePagerResources ); // Return composite provider, the order matters (the higher, the more priority) diff --git a/java/src/com/android/intentresolver/data/repository/DevicePolicyResources.kt b/java/src/com/android/intentresolver/data/repository/DevicePolicyResources.kt index c396b720..75faa068 100644 --- a/java/src/com/android/intentresolver/data/repository/DevicePolicyResources.kt +++ b/java/src/com/android/intentresolver/data/repository/DevicePolicyResources.kt @@ -18,6 +18,9 @@ package com.android.intentresolver.data.repository import android.app.admin.DevicePolicyManager import android.app.admin.DevicePolicyResources.Strings.Core.FORWARD_INTENT_TO_PERSONAL import android.app.admin.DevicePolicyResources.Strings.Core.FORWARD_INTENT_TO_WORK +import android.app.admin.DevicePolicyResources.Strings.Core.RESOLVER_CROSS_PROFILE_BLOCKED_TITLE +import android.app.admin.DevicePolicyResources.Strings.Core.RESOLVER_NO_PERSONAL_APPS +import android.app.admin.DevicePolicyResources.Strings.Core.RESOLVER_NO_WORK_APPS import android.app.admin.DevicePolicyResources.Strings.Core.RESOLVER_PERSONAL_TAB import android.app.admin.DevicePolicyResources.Strings.Core.RESOLVER_PERSONAL_TAB_ACCESSIBILITY import android.app.admin.DevicePolicyResources.Strings.Core.RESOLVER_WORK_PROFILE_NOT_SUPPORTED @@ -83,6 +86,46 @@ constructor( ) } + val noPersonalApps by lazy { + requireNotNull( + policyResources.getString(RESOLVER_NO_PERSONAL_APPS) { + resources.getString(R.string.resolver_no_personal_apps_available) + } + ) + } + + val noWorkApps by lazy { + requireNotNull( + policyResources.getString(RESOLVER_NO_WORK_APPS) { + resources.getString(R.string.resolver_no_work_apps_available) + } + ) + } + + val crossProfileBlocked by lazy { + requireNotNull( + policyResources.getString(RESOLVER_CROSS_PROFILE_BLOCKED_TITLE) { + resources.getString(R.string.resolver_cross_profile_blocked) + } + ) + } + + fun toPersonalBlockedByPolicyMessage(sendAction: Boolean): String { + return if (sendAction) { + resources.getString(R.string.resolver_cant_share_with_personal_apps_explanation) + } else { + resources.getString(R.string.resolver_cant_access_personal_apps_explanation) + } + } + + fun toWorkBlockedByPolicyMessage(sendAction: Boolean): String { + return if (sendAction) { + resources.getString(R.string.resolver_cant_share_with_work_apps_explanation) + } else { + resources.getString(R.string.resolver_cant_access_work_apps_explanation) + } + } + fun getWorkProfileNotSupportedMessage(launcherName: String): String { return requireNotNull( policyResources.getString( diff --git a/java/src/com/android/intentresolver/emptystate/NoAppsAvailableEmptyStateProvider.java b/java/src/com/android/intentresolver/emptystate/NoAppsAvailableEmptyStateProvider.java index 7bfea4f8..af9d56d1 100644 --- a/java/src/com/android/intentresolver/emptystate/NoAppsAvailableEmptyStateProvider.java +++ b/java/src/com/android/intentresolver/emptystate/NoAppsAvailableEmptyStateProvider.java @@ -16,24 +16,22 @@ package com.android.intentresolver.emptystate; -import static android.app.admin.DevicePolicyResources.Strings.Core.RESOLVER_NO_PERSONAL_APPS; -import static android.app.admin.DevicePolicyResources.Strings.Core.RESOLVER_NO_WORK_APPS; + +import static com.android.intentresolver.shared.model.Profile.Type.PERSONAL; + +import static java.util.Objects.requireNonNull; import android.app.admin.DevicePolicyEventLogger; -import android.app.admin.DevicePolicyManager; -import android.content.Context; -import android.content.pm.ResolveInfo; import android.os.UserHandle; import android.stats.devicepolicy.nano.DevicePolicyEnums; import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import com.android.intentresolver.R; -import com.android.intentresolver.ResolvedComponentInfo; +import com.android.intentresolver.ProfileAvailability; +import com.android.intentresolver.ProfileHelper; import com.android.intentresolver.ResolverListAdapter; - -import java.util.List; +import com.android.intentresolver.shared.model.Profile; +import com.android.intentresolver.ui.ProfilePagerResources; /** * Chooser/ResolverActivity empty state provider that returns empty state which is shown when @@ -41,77 +39,40 @@ import java.util.List; */ public class NoAppsAvailableEmptyStateProvider implements EmptyStateProvider { - @NonNull - private final Context mContext; - @Nullable - private final UserHandle mWorkProfileUserHandle; - @Nullable - private final UserHandle mPersonalProfileUserHandle; - @NonNull - private final String mMetricsCategory; - @NonNull - private final UserHandle mTabOwnerUserHandleForLaunch; - - public NoAppsAvailableEmptyStateProvider(@NonNull Context context, - @Nullable UserHandle workProfileUserHandle, - @Nullable UserHandle personalProfileUserHandle, @NonNull String metricsCategory, - @NonNull UserHandle tabOwnerUserHandleForLaunch) { - mContext = context; - mWorkProfileUserHandle = workProfileUserHandle; - mPersonalProfileUserHandle = personalProfileUserHandle; + @NonNull private final String mMetricsCategory; + private final ProfilePagerResources mProfilePagerResources; + private final ProfileHelper mProfileHelper; + private final ProfileAvailability mProfileAvailability; + + public NoAppsAvailableEmptyStateProvider( + ProfileHelper profileHelper, + ProfileAvailability profileAvailability, + @NonNull String metricsCategory, + ProfilePagerResources profilePagerResources) { + mProfileHelper = profileHelper; + mProfileAvailability = profileAvailability; mMetricsCategory = metricsCategory; - mTabOwnerUserHandleForLaunch = tabOwnerUserHandleForLaunch; + mProfilePagerResources = profilePagerResources; } - @Nullable + @NonNull @Override - @SuppressWarnings("ReferenceEquality") public EmptyState getEmptyState(ResolverListAdapter resolverListAdapter) { UserHandle listUserHandle = resolverListAdapter.getUserHandle(); - - if (mWorkProfileUserHandle != null - && (mTabOwnerUserHandleForLaunch.equals(listUserHandle) - || !hasAppsInOtherProfile(resolverListAdapter))) { - - String title; - if (listUserHandle == mPersonalProfileUserHandle) { - title = mContext.getSystemService( - DevicePolicyManager.class).getResources().getString( - RESOLVER_NO_PERSONAL_APPS, - () -> mContext.getString(R.string.resolver_no_personal_apps_available)); - } else { - title = mContext.getSystemService( - DevicePolicyManager.class).getResources().getString( - RESOLVER_NO_WORK_APPS, - () -> mContext.getString(R.string.resolver_no_work_apps_available)); - } - + if (mProfileAvailability.visibleProfileCount() == 1) { + return new DefaultEmptyState(); + } else { + Profile.Type profileType = + requireNonNull(mProfileHelper.findProfileType(listUserHandle)); + String title = mProfilePagerResources.noAppsMessage(profileType); return new NoAppsAvailableEmptyState( - title, mMetricsCategory, - /* isPersonalProfile= */ listUserHandle == mPersonalProfileUserHandle + title, + mMetricsCategory, + /* isPersonalProfile= */ profileType == PERSONAL ); - } else if (mWorkProfileUserHandle == null) { - // Return default empty state without tracking - return new DefaultEmptyState(); } - - return null; } - private boolean hasAppsInOtherProfile(ResolverListAdapter adapter) { - if (mWorkProfileUserHandle == null) { - return false; - } - List<ResolvedComponentInfo> resolversForIntent = - adapter.getResolversForUser(mTabOwnerUserHandleForLaunch); - for (ResolvedComponentInfo info : resolversForIntent) { - ResolveInfo resolveInfo = info.getResolveInfoAt(0); - if (resolveInfo.targetUserId != UserHandle.USER_CURRENT) { - return true; - } - } - return false; - } public static class DefaultEmptyState implements EmptyState { @Override diff --git a/java/src/com/android/intentresolver/ui/ProfilePagerResources.kt b/java/src/com/android/intentresolver/ui/ProfilePagerResources.kt index baab9a4c..0d07af8f 100644 --- a/java/src/com/android/intentresolver/ui/ProfilePagerResources.kt +++ b/java/src/com/android/intentresolver/ui/ProfilePagerResources.kt @@ -50,4 +50,12 @@ constructor( Profile.Type.PRIVATE -> privateTabAccessibilityLabel } } + + fun noAppsMessage(type: Profile.Type): String { + return when (type) { + Profile.Type.PERSONAL -> devicePolicyResources.noPersonalApps + Profile.Type.WORK -> devicePolicyResources.noWorkApps + Profile.Type.PRIVATE -> resources.getString(R.string.resolver_no_private_apps_available) + } + } } |