summaryrefslogtreecommitdiff
path: root/java
diff options
context:
space:
mode:
author Mark Renouf <mrenouf@google.com> 2024-05-06 18:02:25 +0000
committer Android (Google) Code Review <android-gerrit@google.com> 2024-05-06 18:02:25 +0000
commit2d4d3fe6fb73f5ee28f510fbfe1db2ac44c5d780 (patch)
tree29991edc3a18ebe4a8fd4ce98d2095d7b24f9063 /java
parent6f6dd11c347de406ec1877b3634e07acb20c2113 (diff)
parentb772a24d9e639b482bec668e41ee5e69baa28d9a (diff)
Merge "Private profile share policy delegates to parent profile" into main
Diffstat (limited to 'java')
-rw-r--r--java/res/values/strings.xml6
-rw-r--r--java/src/com/android/intentresolver/ChooserActivity.java45
-rw-r--r--java/src/com/android/intentresolver/ProfileHelper.kt8
-rw-r--r--java/src/com/android/intentresolver/ResolverActivity.java41
-rw-r--r--java/src/com/android/intentresolver/data/repository/DevicePolicyResources.kt22
-rw-r--r--java/src/com/android/intentresolver/emptystate/CompositeEmptyStateProvider.kt (renamed from java/src/com/android/intentresolver/emptystate/CompositeEmptyStateProvider.java)28
-rw-r--r--java/src/com/android/intentresolver/emptystate/DefaultEmptyState.kt20
-rw-r--r--java/src/com/android/intentresolver/emptystate/DevicePolicyBlockerEmptyState.java48
-rw-r--r--java/src/com/android/intentresolver/emptystate/NoAppsAvailableEmptyStateProvider.java9
-rw-r--r--java/src/com/android/intentresolver/emptystate/NoCrossProfileEmptyStateProvider.java91
10 files changed, 137 insertions, 181 deletions
diff --git a/java/res/values/strings.xml b/java/res/values/strings.xml
index 17a514d7..32c61327 100644
--- a/java/res/values/strings.xml
+++ b/java/res/values/strings.xml
@@ -284,6 +284,12 @@
<!-- Error message. This message lets the user know that their IT admin doesn't allow them to open this specific content with an app in their personal profile. [CHAR LIMIT=NONE] -->
<string name="resolver_cant_access_personal_apps_explanation">This content can\u2019t be opened with personal apps</string>
+ <!-- Error message. This text is explaining that the user's IT admin doesn't allow this specific content to be shared with apps in the private profile. [CHAR LIMIT=NONE] -->
+ <string name="resolver_cant_share_with_private_apps_explanation">This content can\u2019t be shared with private apps</string>
+
+ <!-- Error message. This message lets the user know that their IT admin doesn't allow them to open this specific content with an app in their private profile. [CHAR LIMIT=NONE] -->
+ <string name="resolver_cant_access_private_apps_explanation">This content can\u2019t be opened with private apps</string>
+
<!-- Error message. This text lets the user know that they need to turn on work apps in order to share or open content. There's also a button a user can tap to turn on the apps. [CHAR LIMIT=NONE] -->
<string name="resolver_turn_on_work_apps">Work apps are paused</string>
<!-- Button text. This button unpauses a user's work apps and data. [CHAR LIMIT=NONE] -->
diff --git a/java/src/com/android/intentresolver/ChooserActivity.java b/java/src/com/android/intentresolver/ChooserActivity.java
index 1922c05c..4608f37b 100644
--- a/java/src/com/android/intentresolver/ChooserActivity.java
+++ b/java/src/com/android/intentresolver/ChooserActivity.java
@@ -17,14 +17,7 @@
package com.android.intentresolver;
import static android.app.VoiceInteractor.PickOptionRequest.Option;
-import static android.app.admin.DevicePolicyResources.Strings.Core.RESOLVER_CANT_ACCESS_PERSONAL;
-import static android.app.admin.DevicePolicyResources.Strings.Core.RESOLVER_CANT_ACCESS_WORK;
-import static android.app.admin.DevicePolicyResources.Strings.Core.RESOLVER_CANT_SHARE_WITH_PERSONAL;
-import static android.app.admin.DevicePolicyResources.Strings.Core.RESOLVER_CANT_SHARE_WITH_WORK;
-import static android.app.admin.DevicePolicyResources.Strings.Core.RESOLVER_CROSS_PROFILE_BLOCKED_TITLE;
import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
-import static android.stats.devicepolicy.nano.DevicePolicyEnums.RESOLVER_EMPTY_STATE_NO_SHARING_TO_PERSONAL;
-import static android.stats.devicepolicy.nano.DevicePolicyEnums.RESOLVER_EMPTY_STATE_NO_SHARING_TO_WORK;
import static android.view.WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS;
import static androidx.lifecycle.LifecycleKt.getCoroutineScope;
@@ -111,8 +104,6 @@ import com.android.intentresolver.data.repository.DevicePolicyResources;
import com.android.intentresolver.domain.interactor.UserInteractor;
import com.android.intentresolver.emptystate.CompositeEmptyStateProvider;
import com.android.intentresolver.emptystate.CrossProfileIntentsChecker;
-import com.android.intentresolver.emptystate.DevicePolicyBlockerEmptyState;
-import com.android.intentresolver.emptystate.EmptyState;
import com.android.intentresolver.emptystate.EmptyStateProvider;
import com.android.intentresolver.emptystate.NoAppsAvailableEmptyStateProvider;
import com.android.intentresolver.emptystate.NoCrossProfileEmptyStateProvider;
@@ -213,7 +204,7 @@ public class ChooserActivity extends Hilt_ChooserActivity implements
private static final String TAB_TAG_WORK = "work";
private static final String LAST_SHOWN_TAB_KEY = "last_shown_tab_key";
- protected static final String METRICS_CATEGORY_CHOOSER = "intent_chooser";
+ public static final String METRICS_CATEGORY_CHOOSER = "intent_chooser";
private int mLayoutId;
private UserHandle mHeaderCreatorUser;
@@ -1450,39 +1441,11 @@ public class ChooserActivity extends Hilt_ChooserActivity implements
}
protected EmptyStateProvider createBlockerEmptyStateProvider() {
- final boolean isSendAction = mRequest.isSendActionTarget();
-
- final EmptyState noWorkToPersonalEmptyState =
- new DevicePolicyBlockerEmptyState(
- /* context= */ this,
- /* devicePolicyStringTitleId= */ RESOLVER_CROSS_PROFILE_BLOCKED_TITLE,
- /* defaultTitleResource= */ R.string.resolver_cross_profile_blocked,
- /* devicePolicyStringSubtitleId= */
- isSendAction ? RESOLVER_CANT_SHARE_WITH_PERSONAL : RESOLVER_CANT_ACCESS_PERSONAL,
- /* defaultSubtitleResource= */
- isSendAction ? R.string.resolver_cant_share_with_personal_apps_explanation
- : R.string.resolver_cant_access_personal_apps_explanation,
- /* devicePolicyEventId= */ RESOLVER_EMPTY_STATE_NO_SHARING_TO_PERSONAL,
- /* devicePolicyEventCategory= */ ResolverActivity.METRICS_CATEGORY_CHOOSER);
-
- final EmptyState noPersonalToWorkEmptyState =
- new DevicePolicyBlockerEmptyState(
- /* context= */ this,
- /* devicePolicyStringTitleId= */ RESOLVER_CROSS_PROFILE_BLOCKED_TITLE,
- /* defaultTitleResource= */ R.string.resolver_cross_profile_blocked,
- /* devicePolicyStringSubtitleId= */
- isSendAction ? RESOLVER_CANT_SHARE_WITH_WORK : RESOLVER_CANT_ACCESS_WORK,
- /* defaultSubtitleResource= */
- isSendAction ? R.string.resolver_cant_share_with_work_apps_explanation
- : R.string.resolver_cant_access_work_apps_explanation,
- /* devicePolicyEventId= */ RESOLVER_EMPTY_STATE_NO_SHARING_TO_WORK,
- /* devicePolicyEventCategory= */ ResolverActivity.METRICS_CATEGORY_CHOOSER);
-
return new NoCrossProfileEmptyStateProvider(
mProfiles,
- noWorkToPersonalEmptyState,
- noPersonalToWorkEmptyState,
- createCrossProfileIntentsChecker());
+ mDevicePolicyResources,
+ createCrossProfileIntentsChecker(),
+ mRequest.isSendActionTarget());
}
private int findSelectedProfile() {
diff --git a/java/src/com/android/intentresolver/ProfileHelper.kt b/java/src/com/android/intentresolver/ProfileHelper.kt
index e1d912c3..53a873a3 100644
--- a/java/src/com/android/intentresolver/ProfileHelper.kt
+++ b/java/src/com/android/intentresolver/ProfileHelper.kt
@@ -80,12 +80,12 @@ constructor(
launchedByUser.handle
}
- fun findProfileType(handle: UserHandle): Profile.Type? {
- val matched =
- profiles.firstOrNull { it.primary.handle == handle || it.clone?.handle == handle }
- return matched?.type
+ fun findProfile(handle: UserHandle): Profile? {
+ return profiles.firstOrNull { it.primary.handle == handle || it.clone?.handle == handle }
}
+ fun findProfileType(handle: UserHandle): Profile.Type? = findProfile(handle)?.type
+
// Name retained for ease of review, to be renamed later
fun getQueryIntentsHandle(handle: UserHandle): UserHandle? {
return if (isLaunchedAsCloneProfile && handle == personalHandle) {
diff --git a/java/src/com/android/intentresolver/ResolverActivity.java b/java/src/com/android/intentresolver/ResolverActivity.java
index 1b08d957..e79cb2d1 100644
--- a/java/src/com/android/intentresolver/ResolverActivity.java
+++ b/java/src/com/android/intentresolver/ResolverActivity.java
@@ -16,12 +16,7 @@
package com.android.intentresolver;
-import static android.app.admin.DevicePolicyResources.Strings.Core.RESOLVER_CANT_ACCESS_PERSONAL;
-import static android.app.admin.DevicePolicyResources.Strings.Core.RESOLVER_CANT_ACCESS_WORK;
-import static android.app.admin.DevicePolicyResources.Strings.Core.RESOLVER_CROSS_PROFILE_BLOCKED_TITLE;
import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
-import static android.stats.devicepolicy.nano.DevicePolicyEnums.RESOLVER_EMPTY_STATE_NO_SHARING_TO_PERSONAL;
-import static android.stats.devicepolicy.nano.DevicePolicyEnums.RESOLVER_EMPTY_STATE_NO_SHARING_TO_WORK;
import static android.view.WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS;
import static androidx.lifecycle.LifecycleKt.getCoroutineScope;
@@ -94,8 +89,6 @@ import com.android.intentresolver.data.repository.DevicePolicyResources;
import com.android.intentresolver.domain.interactor.UserInteractor;
import com.android.intentresolver.emptystate.CompositeEmptyStateProvider;
import com.android.intentresolver.emptystate.CrossProfileIntentsChecker;
-import com.android.intentresolver.emptystate.DevicePolicyBlockerEmptyState;
-import com.android.intentresolver.emptystate.EmptyState;
import com.android.intentresolver.emptystate.EmptyStateProvider;
import com.android.intentresolver.emptystate.NoAppsAvailableEmptyStateProvider;
import com.android.intentresolver.emptystate.NoCrossProfileEmptyStateProvider;
@@ -184,7 +177,6 @@ public class ResolverActivity extends Hilt_ResolverActivity implements
private Space mFooterSpacer = null;
protected static final String METRICS_CATEGORY_RESOLVER = "intent_resolver";
- protected static final String METRICS_CATEGORY_CHOOSER = "intent_chooser";
/** Tracks if we should ignore future broadcasts telling us the work profile is enabled */
private final boolean mWorkProfileHasBeenEnabled = false;
@@ -449,42 +441,17 @@ public class ResolverActivity extends Hilt_ResolverActivity implements
}
protected EmptyStateProvider createBlockerEmptyStateProvider() {
- final boolean shouldShowNoCrossProfileIntentsEmptyState = getUser().equals(getIntentUser());
+ boolean shouldShowNoCrossProfileIntentsEmptyState = getUser().equals(getIntentUser());
if (!shouldShowNoCrossProfileIntentsEmptyState) {
// Implementation that doesn't show any blockers
return new EmptyStateProvider() {};
}
-
- final EmptyState noWorkToPersonalEmptyState =
- new DevicePolicyBlockerEmptyState(
- /* context= */ this,
- /* devicePolicyStringTitleId= */ RESOLVER_CROSS_PROFILE_BLOCKED_TITLE,
- /* defaultTitleResource= */ R.string.resolver_cross_profile_blocked,
- /* devicePolicyStringSubtitleId= */ RESOLVER_CANT_ACCESS_PERSONAL,
- /* defaultSubtitleResource= */
- R.string.resolver_cant_access_personal_apps_explanation,
- /* devicePolicyEventId= */ RESOLVER_EMPTY_STATE_NO_SHARING_TO_PERSONAL,
- /* devicePolicyEventCategory= */
- ResolverActivity.METRICS_CATEGORY_RESOLVER);
-
- final EmptyState noPersonalToWorkEmptyState =
- new DevicePolicyBlockerEmptyState(
- /* context= */ this,
- /* devicePolicyStringTitleId= */ RESOLVER_CROSS_PROFILE_BLOCKED_TITLE,
- /* defaultTitleResource= */ R.string.resolver_cross_profile_blocked,
- /* devicePolicyStringSubtitleId= */ RESOLVER_CANT_ACCESS_WORK,
- /* defaultSubtitleResource= */
- R.string.resolver_cant_access_work_apps_explanation,
- /* devicePolicyEventId= */ RESOLVER_EMPTY_STATE_NO_SHARING_TO_WORK,
- /* devicePolicyEventCategory= */
- ResolverActivity.METRICS_CATEGORY_RESOLVER);
-
return new NoCrossProfileEmptyStateProvider(
mProfiles,
- noWorkToPersonalEmptyState,
- noPersonalToWorkEmptyState,
- createCrossProfileIntentsChecker());
+ mDevicePolicyResources,
+ createCrossProfileIntentsChecker(),
+ /* isShare= */ false);
}
/**
diff --git a/java/src/com/android/intentresolver/data/repository/DevicePolicyResources.kt b/java/src/com/android/intentresolver/data/repository/DevicePolicyResources.kt
index 75faa068..eb35a358 100644
--- a/java/src/com/android/intentresolver/data/repository/DevicePolicyResources.kt
+++ b/java/src/com/android/intentresolver/data/repository/DevicePolicyResources.kt
@@ -27,13 +27,15 @@ import android.app.admin.DevicePolicyResources.Strings.Core.RESOLVER_WORK_PROFIL
import android.app.admin.DevicePolicyResources.Strings.Core.RESOLVER_WORK_TAB
import android.app.admin.DevicePolicyResources.Strings.Core.RESOLVER_WORK_TAB_ACCESSIBILITY
import android.content.res.Resources
+import androidx.annotation.OpenForTesting
import com.android.intentresolver.R
import com.android.intentresolver.inject.ApplicationOwned
import javax.inject.Inject
import javax.inject.Singleton
+@OpenForTesting
@Singleton
-class DevicePolicyResources
+open class DevicePolicyResources
@Inject
constructor(
@ApplicationOwned private val resources: Resources,
@@ -102,7 +104,7 @@ constructor(
)
}
- val crossProfileBlocked by lazy {
+ open val crossProfileBlocked by lazy {
requireNotNull(
policyResources.getString(RESOLVER_CROSS_PROFILE_BLOCKED_TITLE) {
resources.getString(R.string.resolver_cross_profile_blocked)
@@ -110,22 +112,30 @@ constructor(
)
}
- fun toPersonalBlockedByPolicyMessage(sendAction: Boolean): String {
- return if (sendAction) {
+ open fun toPersonalBlockedByPolicyMessage(share: Boolean): String {
+ return if (share) {
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) {
+ open fun toWorkBlockedByPolicyMessage(share: Boolean): String {
+ return if (share) {
resources.getString(R.string.resolver_cant_share_with_work_apps_explanation)
} else {
resources.getString(R.string.resolver_cant_access_work_apps_explanation)
}
}
+ open fun toPrivateBlockedByPolicyMessage(share: Boolean): String {
+ return if (share) {
+ resources.getString(R.string.resolver_cant_share_with_private_apps_explanation)
+ } else {
+ resources.getString(R.string.resolver_cant_access_private_apps_explanation)
+ }
+ }
+
fun getWorkProfileNotSupportedMessage(launcherName: String): String {
return requireNotNull(
policyResources.getString(
diff --git a/java/src/com/android/intentresolver/emptystate/CompositeEmptyStateProvider.java b/java/src/com/android/intentresolver/emptystate/CompositeEmptyStateProvider.kt
index 41422b66..05062a4b 100644
--- a/java/src/com/android/intentresolver/emptystate/CompositeEmptyStateProvider.java
+++ b/java/src/com/android/intentresolver/emptystate/CompositeEmptyStateProvider.kt
@@ -13,34 +13,20 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package com.android.intentresolver.emptystate;
+package com.android.intentresolver.emptystate
-import android.annotation.Nullable;
-
-import com.android.intentresolver.ResolverListAdapter;
+import com.android.intentresolver.ResolverListAdapter
/**
* Empty state provider that combines multiple providers. Providers earlier in the list have
* priority, that is if there is a provider that returns non-null empty state then all further
* providers will be ignored.
*/
-public class CompositeEmptyStateProvider implements EmptyStateProvider {
-
- private final EmptyStateProvider[] mProviders;
-
- public CompositeEmptyStateProvider(EmptyStateProvider... providers) {
- mProviders = providers;
- }
+class CompositeEmptyStateProvider(
+ private vararg val providers: EmptyStateProvider,
+) : EmptyStateProvider {
- @Nullable
- @Override
- public EmptyState getEmptyState(ResolverListAdapter resolverListAdapter) {
- for (EmptyStateProvider provider : mProviders) {
- EmptyState emptyState = provider.getEmptyState(resolverListAdapter);
- if (emptyState != null) {
- return emptyState;
- }
- }
- return null;
+ override fun getEmptyState(resolverListAdapter: ResolverListAdapter): EmptyState? {
+ return providers.firstNotNullOfOrNull { it.getEmptyState(resolverListAdapter) }
}
}
diff --git a/java/src/com/android/intentresolver/emptystate/DefaultEmptyState.kt b/java/src/com/android/intentresolver/emptystate/DefaultEmptyState.kt
new file mode 100644
index 00000000..ea1a03cc
--- /dev/null
+++ b/java/src/com/android/intentresolver/emptystate/DefaultEmptyState.kt
@@ -0,0 +1,20 @@
+/*
+ * 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.emptystate
+
+class DefaultEmptyState : EmptyState {
+ override fun useDefaultEmptyView() = true
+}
diff --git a/java/src/com/android/intentresolver/emptystate/DevicePolicyBlockerEmptyState.java b/java/src/com/android/intentresolver/emptystate/DevicePolicyBlockerEmptyState.java
index b627636e..1cbc6175 100644
--- a/java/src/com/android/intentresolver/emptystate/DevicePolicyBlockerEmptyState.java
+++ b/java/src/com/android/intentresolver/emptystate/DevicePolicyBlockerEmptyState.java
@@ -17,40 +17,26 @@
package com.android.intentresolver.emptystate;
import android.app.admin.DevicePolicyEventLogger;
-import android.app.admin.DevicePolicyManager;
-import android.content.Context;
-import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
-import androidx.annotation.StringRes;
/**
* Empty state that gets strings from the device policy manager and tracks events into
* event logger of the device policy events.
*/
public class DevicePolicyBlockerEmptyState implements EmptyState {
-
- @NonNull
- private final Context mContext;
- private final String mDevicePolicyStringTitleId;
- @StringRes
- private final int mDefaultTitleResource;
- private final String mDevicePolicyStringSubtitleId;
- @StringRes
- private final int mDefaultSubtitleResource;
+ private final String mTitle;
+ private final String mSubtitle;
private final int mEventId;
- @NonNull
private final String mEventCategory;
- public DevicePolicyBlockerEmptyState(@NonNull Context context,
- String devicePolicyStringTitleId, @StringRes int defaultTitleResource,
- String devicePolicyStringSubtitleId, @StringRes int defaultSubtitleResource,
- int devicePolicyEventId, @NonNull String devicePolicyEventCategory) {
- mContext = context;
- mDevicePolicyStringTitleId = devicePolicyStringTitleId;
- mDefaultTitleResource = defaultTitleResource;
- mDevicePolicyStringSubtitleId = devicePolicyStringSubtitleId;
- mDefaultSubtitleResource = defaultSubtitleResource;
+ public DevicePolicyBlockerEmptyState(
+ String title,
+ String subtitle,
+ int devicePolicyEventId,
+ String devicePolicyEventCategory) {
+ mTitle = title;
+ mSubtitle = subtitle;
mEventId = devicePolicyEventId;
mEventCategory = devicePolicyEventCategory;
}
@@ -58,24 +44,22 @@ public class DevicePolicyBlockerEmptyState implements EmptyState {
@Nullable
@Override
public String getTitle() {
- return mContext.getSystemService(DevicePolicyManager.class).getResources().getString(
- mDevicePolicyStringTitleId,
- () -> mContext.getString(mDefaultTitleResource));
+ return mTitle;
}
@Nullable
@Override
public String getSubtitle() {
- return mContext.getSystemService(DevicePolicyManager.class).getResources().getString(
- mDevicePolicyStringSubtitleId,
- () -> mContext.getString(mDefaultSubtitleResource));
+ return mSubtitle;
}
@Override
public void onEmptyStateShown() {
- DevicePolicyEventLogger.createEvent(mEventId)
- .setStrings(mEventCategory)
- .write();
+ if (mEventId != -1) {
+ DevicePolicyEventLogger.createEvent(mEventId)
+ .setStrings(mEventCategory)
+ .write();
+ }
}
@Override
diff --git a/java/src/com/android/intentresolver/emptystate/NoAppsAvailableEmptyStateProvider.java b/java/src/com/android/intentresolver/emptystate/NoAppsAvailableEmptyStateProvider.java
index cd1448e4..b3d3e343 100644
--- a/java/src/com/android/intentresolver/emptystate/NoAppsAvailableEmptyStateProvider.java
+++ b/java/src/com/android/intentresolver/emptystate/NoAppsAvailableEmptyStateProvider.java
@@ -70,13 +70,4 @@ public class NoAppsAvailableEmptyStateProvider implements EmptyStateProvider {
);
}
}
-
-
- public static class DefaultEmptyState implements EmptyState {
- @Override
- public boolean useDefaultEmptyView() {
- return true;
- }
- }
-
}
diff --git a/java/src/com/android/intentresolver/emptystate/NoCrossProfileEmptyStateProvider.java b/java/src/com/android/intentresolver/emptystate/NoCrossProfileEmptyStateProvider.java
index fa33928b..0cf2ea45 100644
--- a/java/src/com/android/intentresolver/emptystate/NoCrossProfileEmptyStateProvider.java
+++ b/java/src/com/android/intentresolver/emptystate/NoCrossProfileEmptyStateProvider.java
@@ -16,15 +16,21 @@
package com.android.intentresolver.emptystate;
+import static android.stats.devicepolicy.DevicePolicyEnums.RESOLVER_EMPTY_STATE_NO_SHARING_TO_PERSONAL;
+import static android.stats.devicepolicy.DevicePolicyEnums.RESOLVER_EMPTY_STATE_NO_SHARING_TO_WORK;
+
+import static com.android.intentresolver.ChooserActivity.METRICS_CATEGORY_CHOOSER;
+
+import static java.util.Objects.requireNonNull;
+
import android.content.Intent;
-import android.os.UserHandle;
import androidx.annotation.Nullable;
import com.android.intentresolver.ProfileHelper;
import com.android.intentresolver.ResolverListAdapter;
+import com.android.intentresolver.data.repository.DevicePolicyResources;
import com.android.intentresolver.shared.model.Profile;
-import com.android.intentresolver.shared.model.User;
import java.util.List;
@@ -35,55 +41,78 @@ import java.util.List;
public class NoCrossProfileEmptyStateProvider implements EmptyStateProvider {
private final ProfileHelper mProfileHelper;
- private final EmptyState mNoWorkToPersonalEmptyState;
- private final EmptyState mNoPersonalToWorkEmptyState;
+ private final DevicePolicyResources mDevicePolicyResources;
+ private final boolean mIsShare;
private final CrossProfileIntentsChecker mCrossProfileIntentsChecker;
public NoCrossProfileEmptyStateProvider(
ProfileHelper profileHelper,
- EmptyState noWorkToPersonalEmptyState,
- EmptyState noPersonalToWorkEmptyState,
- CrossProfileIntentsChecker crossProfileIntentsChecker) {
+ DevicePolicyResources devicePolicyResources,
+ CrossProfileIntentsChecker crossProfileIntentsChecker,
+ boolean isShare) {
mProfileHelper = profileHelper;
- mNoWorkToPersonalEmptyState = noWorkToPersonalEmptyState;
- mNoPersonalToWorkEmptyState = noPersonalToWorkEmptyState;
+ mDevicePolicyResources = devicePolicyResources;
+ mIsShare = isShare;
mCrossProfileIntentsChecker = crossProfileIntentsChecker;
}
- private boolean anyCrossProfileAllowedIntents(ResolverListAdapter selected, UserHandle source) {
- List<Intent> intents = selected.getIntents();
- UserHandle target = selected.getUserHandle();
+ private boolean hasCrossProfileIntents(List<Intent> intents, Profile source, Profile target) {
+ if (source.getPrimary().getHandle().equals(target.getPrimary().getHandle())) {
+ return true;
+ }
+ // Note: Use of getPrimary() here also handles delegation of CLONE profile to parent.
return mCrossProfileIntentsChecker.hasCrossProfileIntents(intents,
- source.getIdentifier(), target.getIdentifier());
+ source.getPrimary().getId(), target.getPrimary().getId());
}
@Nullable
@Override
public EmptyState getEmptyState(ResolverListAdapter adapter) {
- Profile launchedAsProfile = mProfileHelper.getLaunchedAsProfile();
- User launchedAs = mProfileHelper.getLaunchedAsProfile().getPrimary();
- UserHandle tabOwnerHandle = adapter.getUserHandle();
- boolean launchedAsSameUser = launchedAs.getHandle().equals(tabOwnerHandle);
- Profile.Type tabOwnerType = mProfileHelper.findProfileType(tabOwnerHandle);
-
- // Not applicable for private profile.
- if (launchedAsProfile.getType() == Profile.Type.PRIVATE
- || tabOwnerType == Profile.Type.PRIVATE) {
- return null;
+ Profile launchedBy = mProfileHelper.getLaunchedAsProfile();
+ Profile tabOwner = requireNonNull(mProfileHelper.findProfile(adapter.getUserHandle()));
+
+ // When sharing into or out of Private profile, perform the check using the parent profile
+ // instead. (Hard-coded application of CROSS_PROFILE_CONTENT_SHARING_DELEGATE_FROM_PARENT)
+
+ Profile effectiveSource = launchedBy;
+ Profile effectiveTarget = tabOwner;
+
+ // Assumption baked into design: "Personal" profile is the parent of all other profiles.
+ if (launchedBy.getType() == Profile.Type.PRIVATE) {
+ effectiveSource = mProfileHelper.getPersonalProfile();
+ }
+
+ if (tabOwner.getType() == Profile.Type.PRIVATE) {
+ effectiveTarget = mProfileHelper.getPersonalProfile();
}
- // Allow access to the tab when launched by the same user as the tab owner
- // or when there is at least one target which is permitted for cross-profile.
- if (launchedAsSameUser || anyCrossProfileAllowedIntents(adapter,
- /* source = */ launchedAs.getHandle())) {
+ // Allow access to the tab when there is at least one target permitted to cross profiles.
+ if (hasCrossProfileIntents(adapter.getIntents(), effectiveSource, effectiveTarget)) {
return null;
}
- switch (launchedAsProfile.getType()) {
- case WORK: return mNoWorkToPersonalEmptyState;
- case PERSONAL: return mNoPersonalToWorkEmptyState;
+ switch (tabOwner.getType()) {
+ case PERSONAL:
+ return new DevicePolicyBlockerEmptyState(
+ mDevicePolicyResources.getCrossProfileBlocked(),
+ mDevicePolicyResources.toPersonalBlockedByPolicyMessage(mIsShare),
+ RESOLVER_EMPTY_STATE_NO_SHARING_TO_PERSONAL,
+ METRICS_CATEGORY_CHOOSER);
+
+ case WORK:
+ return new DevicePolicyBlockerEmptyState(
+ mDevicePolicyResources.getCrossProfileBlocked(),
+ mDevicePolicyResources.toWorkBlockedByPolicyMessage(mIsShare),
+ RESOLVER_EMPTY_STATE_NO_SHARING_TO_WORK,
+ METRICS_CATEGORY_CHOOSER);
+
+ case PRIVATE:
+ return new DevicePolicyBlockerEmptyState(
+ mDevicePolicyResources.getCrossProfileBlocked(),
+ mDevicePolicyResources.toPrivateBlockedByPolicyMessage(mIsShare),
+ /* Suppress log event. TODO: Define a new metrics event for this? */ -1,
+ METRICS_CATEGORY_CHOOSER);
}
return null;
}
-
}