aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2023-12-14 00:21:49 +0000
committerAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2023-12-14 00:21:49 +0000
commit62cce688e4a2b55fe0c96ce0c78f35822f5a2a14 (patch)
tree2c83afd78128efbe5d93a48e5be4a98054b04583
parent58698ddc38ea3bd26118e99d426c1231370b3066 (diff)
parent35db6fd65cd8364bc3d63e70532130048186456a (diff)
downloadIntentResolver-62cce688e4a2b55fe0c96ce0c78f35822f5a2a14.tar.gz
Snap for 11216811 from 35db6fd65cd8364bc3d63e70532130048186456a to 24Q1-release
Change-Id: Ib475639ffaec308825c889fc9d2512702e443589
-rw-r--r--java/src/com/android/intentresolver/v2/ChooserActivity.java15
-rw-r--r--java/src/com/android/intentresolver/v2/ChooserMultiProfilePagerAdapter.java7
-rw-r--r--java/src/com/android/intentresolver/v2/MultiProfilePagerAdapter.java36
-rw-r--r--java/src/com/android/intentresolver/v2/ResolverActivity.java157
-rw-r--r--java/src/com/android/intentresolver/v2/ResolverMultiProfilePagerAdapter.java9
-rw-r--r--java/src/com/android/intentresolver/v2/data/repository/DevicePolicyResources.kt68
-rw-r--r--java/src/com/android/intentresolver/v2/ui/ActionTitle.java89
7 files changed, 239 insertions, 142 deletions
diff --git a/java/src/com/android/intentresolver/v2/ChooserActivity.java b/java/src/com/android/intentresolver/v2/ChooserActivity.java
index 66705ce..7081264 100644
--- a/java/src/com/android/intentresolver/v2/ChooserActivity.java
+++ b/java/src/com/android/intentresolver/v2/ChooserActivity.java
@@ -981,11 +981,7 @@ public class ChooserActivity extends Hilt_ChooserActivity implements
@Override
protected void applyFooterView(int height) {
- int count = mChooserMultiProfilePagerAdapter.getItemCount();
-
- for (int i = 0; i < count; i++) {
- mChooserMultiProfilePagerAdapter.getAdapterForIndex(i).setFooterHeight(height);
- }
+ mChooserMultiProfilePagerAdapter.setFooterHeightInEveryAdapter(height);
}
private void logDirectShareTargetReceived(UserHandle forUser) {
@@ -1494,14 +1490,13 @@ public class ChooserActivity extends Hilt_ChooserActivity implements
/**
* If we have a tabbed view and are showing 1 row in the current profile and an empty
- * state screen in the other profile, to prevent cropping of the empty state screen we show
+ * state screen in another profile, to prevent cropping of the empty state screen we show
* a second row in the current profile.
*/
private boolean shouldShowExtraRow(int rowsToShow) {
- return shouldShowTabs()
- && rowsToShow == 1
- && mChooserMultiProfilePagerAdapter.shouldShowEmptyStateScreen(
- mChooserMultiProfilePagerAdapter.getInactiveListAdapter());
+ return rowsToShow == 1
+ && mChooserMultiProfilePagerAdapter
+ .shouldShowEmptyStateScreenInAnyInactiveAdapter();
}
/**
diff --git a/java/src/com/android/intentresolver/v2/ChooserMultiProfilePagerAdapter.java b/java/src/com/android/intentresolver/v2/ChooserMultiProfilePagerAdapter.java
index b9ee962..de0a942 100644
--- a/java/src/com/android/intentresolver/v2/ChooserMultiProfilePagerAdapter.java
+++ b/java/src/com/android/intentresolver/v2/ChooserMultiProfilePagerAdapter.java
@@ -169,6 +169,13 @@ public class ChooserMultiProfilePagerAdapter extends MultiProfilePagerAdapter<
return super.rebuildTab(listAdapter, doPostProcessing);
}
+ /** Apply the specified {@code height} as the footer in each tab's adapter. */
+ public void setFooterHeightInEveryAdapter(int height) {
+ for (int i = 0; i < getItemCount(); ++i) {
+ getAdapterForIndex(i).setFooterHeight(height);
+ }
+ }
+
private static class BottomPaddingOverrideSupplier implements Supplier<Optional<Integer>> {
private final Context mContext;
private int mBottomOffset;
diff --git a/java/src/com/android/intentresolver/v2/MultiProfilePagerAdapter.java b/java/src/com/android/intentresolver/v2/MultiProfilePagerAdapter.java
index 6d1870b..f785c11 100644
--- a/java/src/com/android/intentresolver/v2/MultiProfilePagerAdapter.java
+++ b/java/src/com/android/intentresolver/v2/MultiProfilePagerAdapter.java
@@ -414,6 +414,28 @@ public class MultiProfilePagerAdapter<
}
/**
+ * Fully-rebuild the active tab and, if specified, partially-rebuild any other inactive tabs.
+ */
+ public boolean rebuildTabs(boolean includePartialRebuildOfInactiveTabs) {
+ // TODO: we may be able to determine `includePartialRebuildOfInactiveTabs` ourselves as
+ // a function of our own instance state. OTOH the purpose of this "partial rebuild" is to
+ // be able to evaluate the intermediate state of one particular profile tab (i.e. work
+ // profile) that may not generalize well when we have other "inactive tabs." I.e., either we
+ // rebuild *all* the inactive tabs just to evaluate some auto-launch conditions that only
+ // depend on personal and/or work tabs, or we have to explicitly specify the ones we care
+ // about. It's not the pager-adapter's business to know "which ones we care about," so maybe
+ // they should be rebuilt lazily when-and-if it comes up (e.g. during the evaluation of
+ // autolaunch conditions).
+ boolean rebuildCompleted = rebuildActiveTab(true) || getActiveListAdapter().isTabLoaded();
+ if (includePartialRebuildOfInactiveTabs) {
+ boolean rebuildInactiveCompleted =
+ rebuildInactiveTab(false) || getInactiveListAdapter().isTabLoaded();
+ rebuildCompleted = rebuildCompleted && rebuildInactiveCompleted;
+ }
+ return rebuildCompleted;
+ }
+
+ /**
* Rebuilds the tab that is currently visible to the user.
* <p>Returns {@code true} if rebuild has completed.
*/
@@ -428,7 +450,7 @@ public class MultiProfilePagerAdapter<
* Rebuilds the tab that is not currently visible to the user, if such one exists.
* <p>Returns {@code true} if rebuild has completed.
*/
- public final boolean rebuildInactiveTab(boolean doPostProcessing) {
+ private boolean rebuildInactiveTab(boolean doPostProcessing) {
Trace.beginSection("MultiProfilePagerAdapter#rebuildInactiveTab");
if (getItemCount() == 1) {
Trace.endSection();
@@ -537,6 +559,18 @@ public class MultiProfilePagerAdapter<
descriptor.mEmptyStateUi.hide();
}
+ /**
+ * @return whether any "inactive" tab's adapter would show an empty-state screen in our current
+ * application state.
+ */
+ public final boolean shouldShowEmptyStateScreenInAnyInactiveAdapter() {
+ if (getCount() < 2) {
+ return false;
+ }
+ // TODO: check against *any* inactive adapter; for now we only have one.
+ return shouldShowEmptyStateScreen(getInactiveListAdapter());
+ }
+
public boolean shouldShowEmptyStateScreen(ListAdapterT listAdapter) {
int count = listAdapter.getUnfilteredCount();
return (count == 0 && listAdapter.getPlaceholderCount() == 0)
diff --git a/java/src/com/android/intentresolver/v2/ResolverActivity.java b/java/src/com/android/intentresolver/v2/ResolverActivity.java
index 39a4752..3d08735 100644
--- a/java/src/com/android/intentresolver/v2/ResolverActivity.java
+++ b/java/src/com/android/intentresolver/v2/ResolverActivity.java
@@ -20,11 +20,6 @@ import static android.Manifest.permission.INTERACT_ACROSS_PROFILES;
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.app.admin.DevicePolicyResources.Strings.Core.RESOLVER_PERSONAL_TAB;
-import static android.app.admin.DevicePolicyResources.Strings.Core.RESOLVER_PERSONAL_TAB_ACCESSIBILITY;
-import static android.app.admin.DevicePolicyResources.Strings.Core.RESOLVER_WORK_PROFILE_NOT_SUPPORTED;
-import static android.app.admin.DevicePolicyResources.Strings.Core.RESOLVER_WORK_TAB;
-import static android.app.admin.DevicePolicyResources.Strings.Core.RESOLVER_WORK_TAB_ACCESSIBILITY;
import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
import static android.content.PermissionChecker.PID_UNKNOWN;
import static android.stats.devicepolicy.nano.DevicePolicyEnums.RESOLVER_EMPTY_STATE_NO_SHARING_TO_PERSONAL;
@@ -67,7 +62,6 @@ import android.os.StrictMode;
import android.os.Trace;
import android.os.UserHandle;
import android.os.UserManager;
-import android.provider.MediaStore;
import android.provider.Settings;
import android.stats.devicepolicy.DevicePolicyEnums;
import android.text.TextUtils;
@@ -116,10 +110,12 @@ import com.android.intentresolver.model.ResolverRankerServiceResolverComparator;
import com.android.intentresolver.v2.MultiProfilePagerAdapter.MyUserIdProvider;
import com.android.intentresolver.v2.MultiProfilePagerAdapter.OnSwitchOnWorkSelectedListener;
import com.android.intentresolver.v2.MultiProfilePagerAdapter.Profile;
+import com.android.intentresolver.v2.data.repository.DevicePolicyResources;
import com.android.intentresolver.v2.emptystate.NoAppsAvailableEmptyStateProvider;
import com.android.intentresolver.v2.emptystate.NoCrossProfileEmptyStateProvider;
import com.android.intentresolver.v2.emptystate.NoCrossProfileEmptyStateProvider.DevicePolicyBlockerEmptyState;
import com.android.intentresolver.v2.emptystate.WorkProfilePausedEmptyStateProvider;
+import com.android.intentresolver.v2.ui.ActionTitle;
import com.android.intentresolver.widget.ResolverDrawerLayout;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.content.PackageMonitor;
@@ -132,12 +128,9 @@ import kotlin.Unit;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
-import java.util.LinkedList;
import java.util.List;
import java.util.Objects;
-import java.util.Queue;
import java.util.Set;
-import java.util.function.Consumer;
/**
* This is a copy of ResolverActivity to support IntentResolver's ChooserActivity. This code is
@@ -153,6 +146,8 @@ public class ResolverActivity extends FragmentActivity implements
protected ActivityLogic mLogic;
+ private DevicePolicyResources mDevicePolicyResources;
+
public ResolverActivity() {
mIsIntentPicker = getClass().equals(ResolverActivity.class);
}
@@ -233,68 +228,6 @@ public class ResolverActivity extends FragmentActivity implements
protected final LatencyTracker mLatencyTracker = getLatencyTracker();
- private enum ActionTitle {
- VIEW(Intent.ACTION_VIEW,
- R.string.whichViewApplication,
- R.string.whichViewApplicationNamed,
- R.string.whichViewApplicationLabel),
- EDIT(Intent.ACTION_EDIT,
- R.string.whichEditApplication,
- R.string.whichEditApplicationNamed,
- R.string.whichEditApplicationLabel),
- SEND(Intent.ACTION_SEND,
- R.string.whichSendApplication,
- R.string.whichSendApplicationNamed,
- R.string.whichSendApplicationLabel),
- SENDTO(Intent.ACTION_SENDTO,
- R.string.whichSendToApplication,
- R.string.whichSendToApplicationNamed,
- R.string.whichSendToApplicationLabel),
- SEND_MULTIPLE(Intent.ACTION_SEND_MULTIPLE,
- R.string.whichSendApplication,
- R.string.whichSendApplicationNamed,
- R.string.whichSendApplicationLabel),
- CAPTURE_IMAGE(MediaStore.ACTION_IMAGE_CAPTURE,
- R.string.whichImageCaptureApplication,
- R.string.whichImageCaptureApplicationNamed,
- R.string.whichImageCaptureApplicationLabel),
- DEFAULT(null,
- R.string.whichApplication,
- R.string.whichApplicationNamed,
- R.string.whichApplicationLabel),
- HOME(Intent.ACTION_MAIN,
- R.string.whichHomeApplication,
- R.string.whichHomeApplicationNamed,
- R.string.whichHomeApplicationLabel);
-
- // titles for layout that deals with http(s) intents
- public static final int BROWSABLE_TITLE_RES = R.string.whichOpenLinksWith;
- public static final int BROWSABLE_HOST_TITLE_RES = R.string.whichOpenHostLinksWith;
- public static final int BROWSABLE_HOST_APP_TITLE_RES = R.string.whichOpenHostLinksWithApp;
- public static final int BROWSABLE_APP_TITLE_RES = R.string.whichOpenLinksWithApp;
-
- public final String action;
- public final int titleRes;
- public final int namedTitleRes;
- public final @StringRes int labelRes;
-
- ActionTitle(String action, int titleRes, int namedTitleRes, @StringRes int labelRes) {
- this.action = action;
- this.titleRes = titleRes;
- this.namedTitleRes = namedTitleRes;
- this.labelRes = labelRes;
- }
-
- public static ActionTitle forAction(String action) {
- for (ActionTitle title : values()) {
- if (title != HOME && action != null && action.equals(title.action)) {
- return title;
- }
- }
- return DEFAULT;
- }
- }
-
protected PackageMonitor createPackageMonitor(ResolverListAdapter listAdapter) {
return new PackageMonitor() {
@Override
@@ -331,6 +264,8 @@ public class ResolverActivity extends FragmentActivity implements
// Skip initializing anything.
return;
}
+ mDevicePolicyResources = new DevicePolicyResources(getApplication().getResources(),
+ requireNonNull(getSystemService(DevicePolicyManager.class)));
setLogic(new ResolverActivityLogic(
TAG,
() -> this,
@@ -342,6 +277,15 @@ public class ResolverActivity extends FragmentActivity implements
protected final void onPostCreate(@Nullable Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
mInit.forEach(Runnable::run);
+
+ if (savedInstanceState != null) {
+ resetButtonBar();
+ ViewPager viewPager = findViewById(com.android.internal.R.id.profile_pager);
+ if (viewPager != null) {
+ viewPager.setCurrentItem(savedInstanceState.getInt(LAST_SHOWN_TAB_KEY));
+ }
+ mMultiProfilePagerAdapter.clearInactiveProfileCache();
+ }
}
private void init() {
@@ -627,9 +571,9 @@ public class ResolverActivity extends FragmentActivity implements
ResolveInfo ri = mMultiProfilePagerAdapter.getActiveListAdapter()
.resolveInfoForPosition(which, hasIndexBeenFiltered);
if (mLogic.getResolvingHome() && hasManagedProfile() && !supportsManagedProfiles(ri)) {
+ String launcherName = ri.activityInfo.loadLabel(getPackageManager()).toString();
Toast.makeText(this,
- getWorkProfileNotSupportedMsg(
- ri.activityInfo.loadLabel(getPackageManager()).toString()),
+ mDevicePolicyResources.getWorkProfileNotSupportedMessage(launcherName),
Toast.LENGTH_LONG).show();
return;
}
@@ -1367,7 +1311,7 @@ public class ResolverActivity extends FragmentActivity implements
}
@Override
- protected final void onSaveInstanceState(Bundle outState) {
+ protected final void onSaveInstanceState(@NonNull Bundle outState) {
super.onSaveInstanceState(outState);
ViewPager viewPager = findViewById(com.android.internal.R.id.profile_pager);
if (viewPager != null) {
@@ -1375,17 +1319,6 @@ public class ResolverActivity extends FragmentActivity implements
}
}
- @Override
- protected final void onRestoreInstanceState(Bundle savedInstanceState) {
- super.onRestoreInstanceState(savedInstanceState);
- resetButtonBar();
- ViewPager viewPager = findViewById(com.android.internal.R.id.profile_pager);
- if (viewPager != null) {
- viewPager.setCurrentItem(savedInstanceState.getInt(LAST_SHOWN_TAB_KEY));
- }
- mMultiProfilePagerAdapter.clearInactiveProfileCache();
- }
-
private boolean hasManagedProfile() {
UserManager userManager = (UserManager) getSystemService(Context.USER_SERVICE);
if (userManager == null) {
@@ -1467,15 +1400,6 @@ public class ResolverActivity extends FragmentActivity implements
mAlwaysButton.setEnabled(enabled);
}
- private String getWorkProfileNotSupportedMsg(String launcherName) {
- return getSystemService(DevicePolicyManager.class).getResources().getString(
- RESOLVER_WORK_PROFILE_NOT_SUPPORTED,
- () -> getString(
- R.string.activity_resolver_work_profiles_support,
- launcherName),
- launcherName);
- }
-
@Override // ResolverListCommunicator
public final void onPostListReady(ResolverListAdapter listAdapter, boolean doPostProcessing,
boolean rebuildCompleted) {
@@ -1586,13 +1510,7 @@ public class ResolverActivity extends FragmentActivity implements
Trace.beginSection("configureContentView");
// We partially rebuild the inactive adapter to determine if we should auto launch
// isTabLoaded will be true here if the empty state screen is shown instead of the list.
- boolean rebuildCompleted = mMultiProfilePagerAdapter.rebuildActiveTab(true)
- || mMultiProfilePagerAdapter.getActiveListAdapter().isTabLoaded();
- if (shouldShowTabs()) {
- boolean rebuildInactiveCompleted = mMultiProfilePagerAdapter.rebuildInactiveTab(false)
- || mMultiProfilePagerAdapter.getInactiveListAdapter().isTabLoaded();
- rebuildCompleted = rebuildCompleted && rebuildInactiveCompleted;
- }
+ boolean rebuildCompleted = mMultiProfilePagerAdapter.rebuildTabs(shouldShowTabs());
if (shouldUseMiniResolver()) {
configureMiniResolverContent(targetDataLoader);
@@ -1877,8 +1795,9 @@ public class ResolverActivity extends FragmentActivity implements
Button personalButton = (Button) getLayoutInflater().inflate(
R.layout.resolver_profile_tab_button, tabHost.getTabWidget(), false);
- personalButton.setText(getPersonalTabLabel());
- personalButton.setContentDescription(getPersonalTabAccessibilityLabel());
+ personalButton.setText(mDevicePolicyResources.getPersonalTabLabel());
+ personalButton.setContentDescription(
+ mDevicePolicyResources.getPersonalTabAccessibilityLabel());
TabHost.TabSpec tabSpec = tabHost.newTabSpec(TAB_TAG_PERSONAL)
.setContent(com.android.internal.R.id.profile_pager)
@@ -1887,8 +1806,8 @@ public class ResolverActivity extends FragmentActivity implements
Button workButton = (Button) getLayoutInflater().inflate(
R.layout.resolver_profile_tab_button, tabHost.getTabWidget(), false);
- workButton.setText(getWorkTabLabel());
- workButton.setContentDescription(getWorkTabAccessibilityLabel());
+ workButton.setText(mDevicePolicyResources.getWorkTabLabel());
+ workButton.setContentDescription(mDevicePolicyResources.getWorkTabAccessibilityLabel());
tabSpec = tabHost.newTabSpec(TAB_TAG_WORK)
.setContent(com.android.internal.R.id.profile_pager)
@@ -1940,16 +1859,6 @@ public class ResolverActivity extends FragmentActivity implements
};
}
- private String getPersonalTabLabel() {
- return getSystemService(DevicePolicyManager.class).getResources().getString(
- RESOLVER_PERSONAL_TAB, () -> getString(R.string.resolver_personal_tab));
- }
-
- private String getWorkTabLabel() {
- return getSystemService(DevicePolicyManager.class).getResources().getString(
- RESOLVER_WORK_TAB, () -> getString(R.string.resolver_work_tab));
- }
-
private void maybeHideDivider() {
if (!mIsIntentPicker) {
return;
@@ -1966,22 +1875,8 @@ public class ResolverActivity extends FragmentActivity implements
return;
}
mLastSelected = ListView.INVALID_POSITION;
- ListView inactiveListView = (ListView) mMultiProfilePagerAdapter.getInactiveAdapterView();
- if (inactiveListView.getCheckedItemCount() > 0) {
- inactiveListView.setItemChecked(inactiveListView.getCheckedItemPosition(), false);
- }
- }
-
- private String getPersonalTabAccessibilityLabel() {
- return getSystemService(DevicePolicyManager.class).getResources().getString(
- RESOLVER_PERSONAL_TAB_ACCESSIBILITY,
- () -> getString(R.string.resolver_personal_tab_accessibility));
- }
-
- private String getWorkTabAccessibilityLabel() {
- return getSystemService(DevicePolicyManager.class).getResources().getString(
- RESOLVER_WORK_TAB_ACCESSIBILITY,
- () -> getString(R.string.resolver_work_tab_accessibility));
+ ((ResolverMultiProfilePagerAdapter) mMultiProfilePagerAdapter)
+ .clearCheckedItemsInInactiveProfiles();
}
private static int getAttrColor(Context context, int attr) {
diff --git a/java/src/com/android/intentresolver/v2/ResolverMultiProfilePagerAdapter.java b/java/src/com/android/intentresolver/v2/ResolverMultiProfilePagerAdapter.java
index dadc9c0..d96fd15 100644
--- a/java/src/com/android/intentresolver/v2/ResolverMultiProfilePagerAdapter.java
+++ b/java/src/com/android/intentresolver/v2/ResolverMultiProfilePagerAdapter.java
@@ -107,6 +107,15 @@ public class ResolverMultiProfilePagerAdapter extends
mBottomPaddingOverrideSupplier.setUseLayoutWithDefault(useLayoutWithDefault);
}
+ /** Un-check any item(s) that may be checked in any of our inactive adapter(s). */
+ public void clearCheckedItemsInInactiveProfiles() {
+ // TODO: apply to all inactive adapters; for now we just have the one.
+ ListView inactiveListView = getInactiveAdapterView();
+ if (inactiveListView.getCheckedItemCount() > 0) {
+ inactiveListView.setItemChecked(inactiveListView.getCheckedItemPosition(), false);
+ }
+ }
+
private static class BottomPaddingOverrideSupplier implements Supplier<Optional<Integer>> {
private boolean mUseLayoutWithDefault;
diff --git a/java/src/com/android/intentresolver/v2/data/repository/DevicePolicyResources.kt b/java/src/com/android/intentresolver/v2/data/repository/DevicePolicyResources.kt
new file mode 100644
index 0000000..7debdf0
--- /dev/null
+++ b/java/src/com/android/intentresolver/v2/data/repository/DevicePolicyResources.kt
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2023 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.v2.data.repository
+
+import android.app.admin.DevicePolicyManager
+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
+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 com.android.intentresolver.R
+import com.android.intentresolver.inject.ApplicationOwned
+import javax.inject.Inject
+import javax.inject.Singleton
+
+@Singleton
+class DevicePolicyResources @Inject constructor(
+ @ApplicationOwned private val resources: Resources,
+ devicePolicyManager: DevicePolicyManager
+) {
+ private val policyResources = devicePolicyManager.resources
+
+ val personalTabLabel by lazy {
+ requireNotNull(policyResources.getString(RESOLVER_PERSONAL_TAB) {
+ resources.getString(R.string.resolver_personal_tab)
+ })
+ }
+
+ val workTabLabel by lazy {
+ requireNotNull(policyResources.getString(RESOLVER_WORK_TAB) {
+ resources.getString(R.string.resolver_work_tab)
+ })
+ }
+
+ val personalTabAccessibilityLabel by lazy {
+ requireNotNull(policyResources.getString(RESOLVER_PERSONAL_TAB_ACCESSIBILITY) {
+ resources.getString(R.string.resolver_personal_tab_accessibility)
+ })
+ }
+
+ val workTabAccessibilityLabel by lazy {
+ requireNotNull(policyResources.getString(RESOLVER_WORK_TAB_ACCESSIBILITY) {
+ resources.getString(R.string.resolver_work_tab_accessibility)
+ })
+ }
+
+ fun getWorkProfileNotSupportedMessage(launcherName: String): String {
+ return requireNotNull(policyResources.getString(RESOLVER_WORK_PROFILE_NOT_SUPPORTED, {
+ resources.getString(
+ R.string.activity_resolver_work_profiles_support,
+ launcherName)
+ }, launcherName))
+ }
+} \ No newline at end of file
diff --git a/java/src/com/android/intentresolver/v2/ui/ActionTitle.java b/java/src/com/android/intentresolver/v2/ui/ActionTitle.java
new file mode 100644
index 0000000..271c6f3
--- /dev/null
+++ b/java/src/com/android/intentresolver/v2/ui/ActionTitle.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2023 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.v2.ui;
+
+import android.content.Intent;
+import android.provider.MediaStore;
+
+import androidx.annotation.StringRes;
+
+import com.android.intentresolver.R;
+import com.android.intentresolver.v2.ResolverActivity;
+
+/**
+ * Provides a set of related resources for different use cases.
+ */
+public enum ActionTitle {
+ VIEW(Intent.ACTION_VIEW,
+ R.string.whichViewApplication,
+ R.string.whichViewApplicationNamed,
+ R.string.whichViewApplicationLabel),
+ EDIT(Intent.ACTION_EDIT,
+ R.string.whichEditApplication,
+ R.string.whichEditApplicationNamed,
+ R.string.whichEditApplicationLabel),
+ SEND(Intent.ACTION_SEND,
+ R.string.whichSendApplication,
+ R.string.whichSendApplicationNamed,
+ R.string.whichSendApplicationLabel),
+ SENDTO(Intent.ACTION_SENDTO,
+ R.string.whichSendToApplication,
+ R.string.whichSendToApplicationNamed,
+ R.string.whichSendToApplicationLabel),
+ SEND_MULTIPLE(Intent.ACTION_SEND_MULTIPLE,
+ R.string.whichSendApplication,
+ R.string.whichSendApplicationNamed,
+ R.string.whichSendApplicationLabel),
+ CAPTURE_IMAGE(MediaStore.ACTION_IMAGE_CAPTURE,
+ R.string.whichImageCaptureApplication,
+ R.string.whichImageCaptureApplicationNamed,
+ R.string.whichImageCaptureApplicationLabel),
+ DEFAULT(null,
+ R.string.whichApplication,
+ R.string.whichApplicationNamed,
+ R.string.whichApplicationLabel),
+ HOME(Intent.ACTION_MAIN,
+ R.string.whichHomeApplication,
+ R.string.whichHomeApplicationNamed,
+ R.string.whichHomeApplicationLabel);
+
+ // titles for layout that deals with http(s) intents
+ public static final int BROWSABLE_TITLE_RES = R.string.whichOpenLinksWith;
+ public static final int BROWSABLE_HOST_TITLE_RES = R.string.whichOpenHostLinksWith;
+ public static final int BROWSABLE_HOST_APP_TITLE_RES = R.string.whichOpenHostLinksWithApp;
+ public static final int BROWSABLE_APP_TITLE_RES = R.string.whichOpenLinksWithApp;
+
+ public final String action;
+ public final int titleRes;
+ public final int namedTitleRes;
+ public final @StringRes int labelRes;
+
+ ActionTitle(String action, int titleRes, int namedTitleRes, @StringRes int labelRes) {
+ this.action = action;
+ this.titleRes = titleRes;
+ this.namedTitleRes = namedTitleRes;
+ this.labelRes = labelRes;
+ }
+
+ public static ActionTitle forAction(String action) {
+ for (ActionTitle title : values()) {
+ if (title != HOME && action != null && action.equals(title.action)) {
+ return title;
+ }
+ }
+ return DEFAULT;
+ }
+}