Show all apps that requested cross profile permission
show all apps that requested the permission, show the admin restricted dialog if the app is not whitelisted by the admin, and show a link to install the app if the app is missing in one of the profiles. Bug: 149742043 Test: make RunSettingsRoboTests ROBOTEST_FILTER=InteractAcrossProfilesPreferenceControllerTest Test: make RunSettingsRoboTests ROBOTEST_FILTER=InteractAcrossProfilesControllerTest Test: make RunSettingsRoboTests ROBOTEST_FILTER=InteractAcrossProfilesSettingsTest Test: make RunSettingsRoboTests ROBOTEST_FILTER=InteractAcrossProfilesDetailsTest Change-Id: I2bc86b9966a2e14a12ee8f4b7f1b75f866ed98e3
This commit is contained in:
@@ -15,15 +15,25 @@
|
||||
*/
|
||||
package com.android.settings.applications.specialaccess.interactacrossprofiles;
|
||||
|
||||
import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_AWARE;
|
||||
import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_UNAWARE;
|
||||
|
||||
import android.Manifest;
|
||||
import android.annotation.UserIdInt;
|
||||
import android.app.ActionBar;
|
||||
import android.app.AppOpsManager;
|
||||
import android.app.admin.DevicePolicyManager;
|
||||
import android.app.settings.SettingsEnums;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.content.PermissionChecker;
|
||||
import android.content.pm.CrossProfileApps;
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.UserInfo;
|
||||
import android.graphics.ColorMatrix;
|
||||
import android.graphics.ColorMatrixColorFilter;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.Bundle;
|
||||
import android.os.UserHandle;
|
||||
import android.os.UserManager;
|
||||
@@ -32,13 +42,15 @@ import android.view.View;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.preference.Preference;
|
||||
import androidx.preference.SwitchPreference;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.applications.AppInfoBase;
|
||||
import com.android.settings.applications.AppStoreUtil;
|
||||
import com.android.settings.widget.CardPreference;
|
||||
import com.android.settingslib.RestrictedLockUtils;
|
||||
import com.android.settingslib.RestrictedSwitchPreference;
|
||||
import com.android.settingslib.widget.LayoutPreference;
|
||||
|
||||
public class InteractAcrossProfilesDetails extends AppInfoBase
|
||||
@@ -47,13 +59,21 @@ public class InteractAcrossProfilesDetails extends AppInfoBase
|
||||
private static final String INTERACT_ACROSS_PROFILES_SETTINGS_SWITCH =
|
||||
"interact_across_profiles_settings_switch";
|
||||
private static final String INTERACT_ACROSS_PROFILES_HEADER = "interact_across_profiles_header";
|
||||
public static final String INSTALL_APP_BANNER_KEY = "install_app_banner";
|
||||
|
||||
private Context mContext;
|
||||
private CrossProfileApps mCrossProfileApps;
|
||||
private UserManager mUserManager;
|
||||
private SwitchPreference mSwitchPref;
|
||||
private RestrictedSwitchPreference mSwitchPref;
|
||||
private LayoutPreference mHeader;
|
||||
private CardPreference mInstallBanner;
|
||||
private PackageManager mPackageManager;
|
||||
private UserHandle mPersonalProfile;
|
||||
private UserHandle mWorkProfile;
|
||||
private boolean mInstalledInPersonal;
|
||||
private boolean mInstalledInWork;
|
||||
private String mAppLabel;
|
||||
private Intent mInstallAppIntent;
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
@@ -64,19 +84,30 @@ public class InteractAcrossProfilesDetails extends AppInfoBase
|
||||
mUserManager = mContext.getSystemService(UserManager.class);
|
||||
mPackageManager = mContext.getPackageManager();
|
||||
|
||||
mWorkProfile = InteractAcrossProfilesSettings.getWorkProfile(mUserManager);
|
||||
mPersonalProfile = mUserManager.getProfileParent(mWorkProfile);
|
||||
mInstalledInWork = isPackageInstalled(mPackageName, mWorkProfile.getIdentifier());
|
||||
mInstalledInPersonal = isPackageInstalled(mPackageName, mPersonalProfile.getIdentifier());
|
||||
|
||||
mAppLabel = mPackageInfo.applicationInfo.loadLabel(mPackageManager).toString();
|
||||
mInstallAppIntent = AppStoreUtil.getAppStoreLink(mContext, mPackageName);
|
||||
|
||||
addPreferencesFromResource(R.xml.interact_across_profiles_permissions_details);
|
||||
mSwitchPref = findPreference(INTERACT_ACROSS_PROFILES_SETTINGS_SWITCH);
|
||||
mSwitchPref.setOnPreferenceClickListener(this);
|
||||
|
||||
mHeader = findPreference(INTERACT_ACROSS_PROFILES_HEADER);
|
||||
|
||||
mInstallBanner = findPreference(INSTALL_APP_BANNER_KEY);
|
||||
mInstallBanner.setOnPreferenceClickListener(this);
|
||||
|
||||
// refreshUi checks that the user can still configure the appOp, return to the
|
||||
// previous page if it can't.
|
||||
if (!refreshUi()) {
|
||||
setIntentAndFinish(true/* appChanged */);
|
||||
}
|
||||
final UserHandle workProfile = getWorkProfile();
|
||||
final UserHandle personalProfile = mUserManager.getProfileParent(workProfile);
|
||||
addAppTitleAndIcons(personalProfile, workProfile);
|
||||
addAppTitleAndIcons(mPersonalProfile, mWorkProfile);
|
||||
styleActionBar();
|
||||
}
|
||||
|
||||
private void addAppTitleAndIcons(UserHandle personalProfile, UserHandle workProfile) {
|
||||
@@ -89,70 +120,101 @@ public class InteractAcrossProfilesDetails extends AppInfoBase
|
||||
|
||||
final ImageView personalIconView = mHeader.findViewById(R.id.entity_header_icon_personal);
|
||||
if (personalIconView != null) {
|
||||
personalIconView.setImageDrawable(IconDrawableFactory.newInstance(mContext)
|
||||
.getBadgedIcon(mPackageInfo.applicationInfo, personalProfile.getIdentifier()));
|
||||
Drawable icon = IconDrawableFactory.newInstance(mContext)
|
||||
.getBadgedIcon(mPackageInfo.applicationInfo, personalProfile.getIdentifier())
|
||||
.mutate();
|
||||
if (!mInstalledInPersonal) {
|
||||
icon.setColorFilter(createSuspendedColorMatrix());
|
||||
}
|
||||
personalIconView.setImageDrawable(icon);
|
||||
}
|
||||
final ImageView workIconView2 = mHeader.findViewById(R.id.entity_header_icon_work);
|
||||
if (workIconView2 != null) {
|
||||
workIconView2.setImageDrawable(IconDrawableFactory.newInstance(mContext)
|
||||
.getBadgedIcon(mPackageInfo.applicationInfo, workProfile.getIdentifier()));
|
||||
|
||||
final ImageView workIconView = mHeader.findViewById(R.id.entity_header_icon_work);
|
||||
if (workIconView != null) {
|
||||
Drawable icon = IconDrawableFactory.newInstance(mContext)
|
||||
.getBadgedIcon(mPackageInfo.applicationInfo, workProfile.getIdentifier())
|
||||
.mutate();
|
||||
if (!mInstalledInWork) {
|
||||
icon.setColorFilter(createSuspendedColorMatrix());
|
||||
}
|
||||
workIconView.setImageDrawable(icon);
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private UserHandle getWorkProfile() {
|
||||
for (UserInfo user : mUserManager.getProfiles(UserHandle.myUserId())) {
|
||||
if (mUserManager.isManagedProfile(user.id)) {
|
||||
return user.getUserHandle();
|
||||
}
|
||||
private void styleActionBar() {
|
||||
final ActionBar actionBar = getActivity().getActionBar();
|
||||
if (actionBar != null) {
|
||||
actionBar.setElevation(0);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private ColorMatrixColorFilter createSuspendedColorMatrix() {
|
||||
int grayValue = 127;
|
||||
float scale = 0.5f; // half bright
|
||||
|
||||
ColorMatrix tempBrightnessMatrix = new ColorMatrix();
|
||||
float[] mat = tempBrightnessMatrix.getArray();
|
||||
mat[0] = scale;
|
||||
mat[6] = scale;
|
||||
mat[12] = scale;
|
||||
mat[4] = grayValue;
|
||||
mat[9] = grayValue;
|
||||
mat[14] = grayValue;
|
||||
|
||||
ColorMatrix matrix = new ColorMatrix();
|
||||
matrix.setSaturation(0.0f);
|
||||
matrix.preConcat(tempBrightnessMatrix);
|
||||
return new ColorMatrixColorFilter(matrix);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onPreferenceClick(Preference preference) {
|
||||
if (preference != mSwitchPref) {
|
||||
return false;
|
||||
}
|
||||
// refreshUi checks that the user can still configure the appOp, return to the
|
||||
// previous page if it can't.
|
||||
if (!refreshUi()) {
|
||||
setIntentAndFinish(true/* appChanged */);
|
||||
}
|
||||
if (preference == mSwitchPref) {
|
||||
handleSwitchPreferenceClick();
|
||||
return true;
|
||||
}
|
||||
if (preference == mInstallBanner) {
|
||||
handleInstallBannerClick();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void handleSwitchPreferenceClick() {
|
||||
if (isInteractAcrossProfilesEnabled()) {
|
||||
enableInteractAcrossProfiles(false);
|
||||
refreshUi();
|
||||
return true;
|
||||
}
|
||||
if (!isInteractAcrossProfilesEnabled()) {
|
||||
} else {
|
||||
showConsentDialog();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private void showConsentDialog() {
|
||||
final String appLabel = mPackageInfo.applicationInfo.loadLabel(mPackageManager).toString();
|
||||
|
||||
final View dialogView = getLayoutInflater().inflate(
|
||||
R.layout.interact_across_profiles_consent_dialog, null);
|
||||
|
||||
final TextView dialogTitle = dialogView.findViewById(
|
||||
R.id.interact_across_profiles_consent_dialog_title);
|
||||
dialogTitle.setText(
|
||||
getString(R.string.interact_across_profiles_consent_dialog_title, appLabel));
|
||||
getString(R.string.interact_across_profiles_consent_dialog_title, mAppLabel));
|
||||
|
||||
final TextView dialogSummary = dialogView.findViewById(
|
||||
R.id.interact_across_profiles_consent_dialog_summary);
|
||||
dialogSummary.setText(
|
||||
getString(R.string.interact_across_profiles_consent_dialog_summary, appLabel));
|
||||
getString(R.string.interact_across_profiles_consent_dialog_summary, mAppLabel));
|
||||
|
||||
final TextView appDataSummary = dialogView.findViewById(R.id.app_data_summary);
|
||||
appDataSummary.setText(getString(
|
||||
R.string.interact_across_profiles_consent_dialog_app_data_summary, appLabel));
|
||||
R.string.interact_across_profiles_consent_dialog_app_data_summary, mAppLabel));
|
||||
|
||||
final TextView permissionsSummary = dialogView.findViewById(R.id.permissions_summary);
|
||||
permissionsSummary.setText(getString(
|
||||
R.string.interact_across_profiles_consent_dialog_permissions_summary, appLabel));
|
||||
R.string.interact_across_profiles_consent_dialog_permissions_summary, mAppLabel));
|
||||
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
|
||||
builder.setView(dialogView)
|
||||
@@ -171,18 +233,38 @@ public class InteractAcrossProfilesDetails extends AppInfoBase
|
||||
}
|
||||
|
||||
private boolean isInteractAcrossProfilesEnabled() {
|
||||
return isInteractAcrossProfilesEnabled(
|
||||
mContext, mPackageName, mPackageInfo.applicationInfo.uid);
|
||||
return isInteractAcrossProfilesEnabled(mContext, mPackageName);
|
||||
}
|
||||
|
||||
static boolean isInteractAcrossProfilesEnabled(Context context, String packageName, int uid) {
|
||||
static boolean isInteractAcrossProfilesEnabled(
|
||||
Context context, String packageName) {
|
||||
UserManager userManager = context.getSystemService(UserManager.class);
|
||||
UserHandle workProfile = InteractAcrossProfilesSettings.getWorkProfile(userManager);
|
||||
UserHandle personalProfile = userManager.getProfileParent(workProfile);
|
||||
return context.getSystemService(
|
||||
CrossProfileApps.class).canConfigureInteractAcrossProfiles(packageName)
|
||||
&& isInteractAcrossProfilesEnabledInProfile(context, packageName, personalProfile)
|
||||
&& isInteractAcrossProfilesEnabledInProfile(context, packageName, workProfile);
|
||||
|
||||
}
|
||||
|
||||
private static boolean isInteractAcrossProfilesEnabledInProfile(
|
||||
Context context, String packageName, UserHandle userHandle) {
|
||||
final PackageManager packageManager = context.getPackageManager();
|
||||
final int uid;
|
||||
try {
|
||||
uid = packageManager.getApplicationInfoAsUser(
|
||||
packageName, /* flags= */0, userHandle).uid;
|
||||
} catch (PackageManager.NameNotFoundException e) {
|
||||
return false;
|
||||
}
|
||||
return PermissionChecker.PERMISSION_GRANTED
|
||||
== PermissionChecker.checkPermissionForPreflight(
|
||||
context,
|
||||
Manifest.permission.INTERACT_ACROSS_PROFILES,
|
||||
PermissionChecker.PID_UNKNOWN,
|
||||
uid,
|
||||
packageName);
|
||||
context,
|
||||
Manifest.permission.INTERACT_ACROSS_PROFILES,
|
||||
PermissionChecker.PID_UNKNOWN,
|
||||
uid,
|
||||
packageName);
|
||||
}
|
||||
|
||||
private void enableInteractAcrossProfiles(boolean newState) {
|
||||
@@ -190,14 +272,28 @@ public class InteractAcrossProfilesDetails extends AppInfoBase
|
||||
mPackageName, newState ? AppOpsManager.MODE_ALLOWED : AppOpsManager.MODE_IGNORED);
|
||||
}
|
||||
|
||||
private void handleInstallBannerClick() {
|
||||
if (mInstallAppIntent == null) {
|
||||
return;
|
||||
}
|
||||
if (!mInstalledInWork) {
|
||||
mContext.startActivityAsUser(mInstallAppIntent, mWorkProfile);
|
||||
return;
|
||||
}
|
||||
if (!mInstalledInPersonal) {
|
||||
mContext.startActivityAsUser(mInstallAppIntent, mPersonalProfile);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the summary for the current state of whether the app associated with the given
|
||||
* {@code packageName} is allowed to interact across profiles.
|
||||
*/
|
||||
public static CharSequence getPreferenceSummary(Context context, String packageName, int uid) {
|
||||
return context.getString(isInteractAcrossProfilesEnabled(context, packageName, uid)
|
||||
? R.string.app_permission_summary_allowed
|
||||
: R.string.app_permission_summary_not_allowed);
|
||||
public static CharSequence getPreferenceSummary(
|
||||
Context context, String packageName) {
|
||||
return context.getString(isInteractAcrossProfilesEnabled(context, packageName)
|
||||
? R.string.interact_across_profiles_summary_allowed
|
||||
: R.string.interact_across_profiles_summary_not_allowed);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -205,31 +301,99 @@ public class InteractAcrossProfilesDetails extends AppInfoBase
|
||||
if (mPackageInfo == null || mPackageInfo.applicationInfo == null) {
|
||||
return false;
|
||||
}
|
||||
if (!mCrossProfileApps.canConfigureInteractAcrossProfiles(mPackageName)) {
|
||||
if (!mCrossProfileApps.canUserAttemptToConfigureInteractAcrossProfiles(mPackageName)) {
|
||||
// Invalid app entry. Should not allow changing permission
|
||||
mSwitchPref.setEnabled(false);
|
||||
return false;
|
||||
}
|
||||
|
||||
final ImageView horizontalArrowIcon = mHeader.findViewById(R.id.entity_header_swap_horiz);
|
||||
if (isInteractAcrossProfilesEnabled()) {
|
||||
mSwitchPref.setChecked(true);
|
||||
mSwitchPref.setTitle(R.string.interact_across_profiles_switch_enabled);
|
||||
if (horizontalArrowIcon != null) {
|
||||
horizontalArrowIcon.setImageDrawable(
|
||||
mContext.getDrawable(R.drawable.ic_swap_horiz_blue));
|
||||
}
|
||||
} else {
|
||||
mSwitchPref.setChecked(false);
|
||||
mSwitchPref.setTitle(R.string.interact_across_profiles_switch_disabled);
|
||||
if (horizontalArrowIcon != null) {
|
||||
horizontalArrowIcon.setImageDrawable(
|
||||
mContext.getDrawable(R.drawable.ic_swap_horiz_grey));
|
||||
}
|
||||
if (!mCrossProfileApps.canConfigureInteractAcrossProfiles(mPackageName)) {
|
||||
return refreshUiForNonConfigurableApps();
|
||||
}
|
||||
refreshUiForConfigurableApps();
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean refreshUiForNonConfigurableApps() {
|
||||
mSwitchPref.setChecked(false);
|
||||
mSwitchPref.setTitle(R.string.interact_across_profiles_switch_disabled);
|
||||
if (!isCrossProfilePackageWhitelisted(mPackageName)) {
|
||||
mInstallBanner.setVisible(false);
|
||||
mSwitchPref.setDisabledByAdmin(RestrictedLockUtils.getProfileOrDeviceOwner(
|
||||
mContext, mWorkProfile));
|
||||
return true;
|
||||
}
|
||||
mSwitchPref.setEnabled(false);
|
||||
if (!mInstalledInPersonal && !mInstalledInWork) {
|
||||
return false;
|
||||
}
|
||||
if (!mInstalledInPersonal) {
|
||||
mInstallBanner.setTitle(getString(
|
||||
R.string.interact_across_profiles_install_personal_app_title,
|
||||
mAppLabel));
|
||||
mInstallBanner.setSummary(
|
||||
R.string.interact_across_profiles_install_app_summary);
|
||||
mInstallBanner.setVisible(true);
|
||||
return true;
|
||||
}
|
||||
if (!mInstalledInWork) {
|
||||
mInstallBanner.setTitle(getString(
|
||||
R.string.interact_across_profiles_install_work_app_title,
|
||||
mAppLabel));
|
||||
mInstallBanner.setSummary(
|
||||
R.string.interact_across_profiles_install_app_summary);
|
||||
mInstallBanner.setVisible(true);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean isCrossProfilePackageWhitelisted(String packageName) {
|
||||
return mContext.getSystemService(DevicePolicyManager.class)
|
||||
.getAllCrossProfilePackages().contains(packageName);
|
||||
}
|
||||
|
||||
private boolean isPackageInstalled(String packageName, @UserIdInt int userId) {
|
||||
final PackageInfo info;
|
||||
try {
|
||||
info = mContext.createContextAsUser(UserHandle.of(userId), /* flags= */0)
|
||||
.getPackageManager().getPackageInfo(packageName,
|
||||
MATCH_DIRECT_BOOT_AWARE | MATCH_DIRECT_BOOT_UNAWARE);
|
||||
} catch (PackageManager.NameNotFoundException e) {
|
||||
return false;
|
||||
}
|
||||
return info != null;
|
||||
}
|
||||
|
||||
private void refreshUiForConfigurableApps() {
|
||||
mInstallBanner.setVisible(false);
|
||||
mSwitchPref.setEnabled(true);
|
||||
if (isInteractAcrossProfilesEnabled()) {
|
||||
enableSwitchPref();
|
||||
} else {
|
||||
disableSwitchPref();
|
||||
}
|
||||
}
|
||||
|
||||
private void enableSwitchPref() {
|
||||
mSwitchPref.setChecked(true);
|
||||
mSwitchPref.setTitle(R.string.interact_across_profiles_switch_enabled);
|
||||
final ImageView horizontalArrowIcon = mHeader.findViewById(R.id.entity_header_swap_horiz);
|
||||
if (horizontalArrowIcon != null) {
|
||||
horizontalArrowIcon.setImageDrawable(
|
||||
mContext.getDrawable(R.drawable.ic_swap_horiz_blue));
|
||||
}
|
||||
}
|
||||
|
||||
private void disableSwitchPref() {
|
||||
mSwitchPref.setChecked(false);
|
||||
mSwitchPref.setTitle(R.string.interact_across_profiles_switch_disabled);
|
||||
final ImageView horizontalArrowIcon = mHeader.findViewById(R.id.entity_header_swap_horiz);
|
||||
if (horizontalArrowIcon != null) {
|
||||
horizontalArrowIcon.setImageDrawable(
|
||||
mContext.getDrawable(R.drawable.ic_swap_horiz_grey));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected AlertDialog createDialog(int id, int errorCode) {
|
||||
return null;
|
||||
|
@@ -35,7 +35,7 @@ public class InteractAcrossProfilesDetailsPreferenceController
|
||||
|
||||
@Override
|
||||
public int getAvailabilityStatus() {
|
||||
return canConfigureInteractAcrossProfiles() ? AVAILABLE : DISABLED_FOR_USER;
|
||||
return canUserAttemptToConfigureInteractAcrossProfiles() ? AVAILABLE : DISABLED_FOR_USER;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -49,13 +49,12 @@ public class InteractAcrossProfilesDetailsPreferenceController
|
||||
}
|
||||
|
||||
private CharSequence getPreferenceSummary() {
|
||||
return InteractAcrossProfilesDetails.getPreferenceSummary(mContext, mPackageName,
|
||||
mParent.getPackageInfo().applicationInfo.uid);
|
||||
return InteractAcrossProfilesDetails.getPreferenceSummary(mContext, mPackageName);
|
||||
}
|
||||
|
||||
private boolean canConfigureInteractAcrossProfiles() {
|
||||
private boolean canUserAttemptToConfigureInteractAcrossProfiles() {
|
||||
return mContext.getSystemService(CrossProfileApps.class)
|
||||
.canConfigureInteractAcrossProfiles(mPackageName);
|
||||
.canUserAttemptToConfigureInteractAcrossProfiles(mPackageName);
|
||||
}
|
||||
|
||||
public void setPackageName(String packageName) {
|
||||
|
@@ -85,8 +85,8 @@ public class InteractAcrossProfilesSettings extends EmptyTextSettings {
|
||||
final Preference pref = new AppPreference(prefContext);
|
||||
pref.setIcon(mIconDrawableFactory.getBadgedIcon(appInfo, user.getIdentifier()));
|
||||
pref.setTitle(mPackageManager.getUserBadgedLabel(label, user));
|
||||
pref.setSummary(InteractAcrossProfilesDetails.getPreferenceSummary(prefContext,
|
||||
packageName, appInfo.uid));
|
||||
pref.setSummary(InteractAcrossProfilesDetails.getPreferenceSummary(
|
||||
prefContext, packageName));
|
||||
pref.setOnPreferenceClickListener(new OnPreferenceClickListener() {
|
||||
@Override
|
||||
public boolean onPreferenceClick(Preference preference) {
|
||||
@@ -127,49 +127,78 @@ public class InteractAcrossProfilesSettings extends EmptyTextSettings {
|
||||
static ArrayList<Pair<ApplicationInfo, UserHandle>> collectConfigurableApps(
|
||||
PackageManager packageManager, UserManager userManager,
|
||||
CrossProfileApps crossProfileApps) {
|
||||
final UserHandle personalProfile = getPersonalProfileForCallingUser(userManager);
|
||||
final UserHandle workProfile = getWorkProfile(userManager);
|
||||
if (workProfile == null) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
final UserHandle personalProfile = userManager.getProfileParent(workProfile);
|
||||
if (personalProfile == null) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
final ArrayList<Pair<ApplicationInfo, UserHandle>> apps = new ArrayList<>();
|
||||
final List<PackageInfo> installedPackages = packageManager.getInstalledPackagesAsUser(
|
||||
GET_ACTIVITIES, personalProfile.getIdentifier());
|
||||
for (PackageInfo packageInfo : installedPackages) {
|
||||
if (crossProfileApps.canConfigureInteractAcrossProfiles(packageInfo.packageName)) {
|
||||
for (PackageInfo packageInfo : getAllInstalledPackages(
|
||||
packageManager, personalProfile, workProfile)) {
|
||||
if (crossProfileApps.canUserAttemptToConfigureInteractAcrossProfiles(
|
||||
packageInfo.packageName)) {
|
||||
apps.add(new Pair<>(packageInfo.applicationInfo, personalProfile));
|
||||
}
|
||||
}
|
||||
return apps;
|
||||
}
|
||||
|
||||
private static List<PackageInfo> getAllInstalledPackages(
|
||||
PackageManager packageManager, UserHandle personalProfile, UserHandle workProfile) {
|
||||
List<PackageInfo> personalPackages = packageManager.getInstalledPackagesAsUser(
|
||||
GET_ACTIVITIES, personalProfile.getIdentifier());
|
||||
List<PackageInfo> workPackages = packageManager.getInstalledPackagesAsUser(
|
||||
GET_ACTIVITIES, workProfile.getIdentifier());
|
||||
List<PackageInfo> allPackages = new ArrayList<>(personalPackages);
|
||||
for (PackageInfo workPackage : workPackages) {
|
||||
if (allPackages.stream().noneMatch(
|
||||
p -> workPackage.packageName.equals(p.packageName))) {
|
||||
allPackages.add(workPackage);
|
||||
}
|
||||
}
|
||||
return allPackages;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the number of applications that can interact across profiles.
|
||||
*/
|
||||
static int getNumberOfEnabledApps(
|
||||
Context context, PackageManager packageManager, UserManager userManager,
|
||||
CrossProfileApps crossProfileApps) {
|
||||
UserHandle workProfile = getWorkProfile(userManager);
|
||||
if (workProfile == null) {
|
||||
return 0;
|
||||
}
|
||||
UserHandle personalProfile = userManager.getProfileParent(workProfile);
|
||||
if (personalProfile == null) {
|
||||
return 0;
|
||||
}
|
||||
final ArrayList<Pair<ApplicationInfo, UserHandle>> apps =
|
||||
collectConfigurableApps(packageManager, userManager, crossProfileApps);
|
||||
apps.removeIf(
|
||||
app -> !InteractAcrossProfilesDetails.isInteractAcrossProfilesEnabled(
|
||||
context, app.first.packageName, app.first.uid));
|
||||
context, app.first.packageName)
|
||||
|| !crossProfileApps.canConfigureInteractAcrossProfiles(
|
||||
app.first.packageName));
|
||||
return apps.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the personal profile in the profile group of the calling user.
|
||||
* Returns null if user is not in a profile group.
|
||||
* Returns the work profile in the profile group of the calling user.
|
||||
* Returns null if not found.
|
||||
*/
|
||||
@Nullable
|
||||
private static UserHandle getPersonalProfileForCallingUser(UserManager userManager) {
|
||||
final int callingUser = UserHandle.myUserId();
|
||||
if (userManager.getProfiles(callingUser).isEmpty()) {
|
||||
return null;
|
||||
static UserHandle getWorkProfile(UserManager userManager) {
|
||||
for (UserInfo user : userManager.getProfiles(UserHandle.myUserId())) {
|
||||
if (userManager.isManagedProfile(user.id)) {
|
||||
return user.getUserHandle();
|
||||
}
|
||||
}
|
||||
final UserInfo parentProfile = userManager.getProfileParent(callingUser);
|
||||
return parentProfile == null
|
||||
? UserHandle.of(callingUser) : parentProfile.getUserHandle();
|
||||
return null;
|
||||
}
|
||||
|
||||
public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
|
||||
|
Reference in New Issue
Block a user