Show a separate tab for the Private Space
This covers all the known Settings pages using the tabbed view model. https://docs.google.com/document/d/1CdjUjAE84-5ZEPRIfw5KYFjLVHtEZxc_sF0w95su8DA/edit?resourcekey=0-dAACT9HRexY1IyoxMmkVlw#heading=h.58jd58rmznte Screenshots: all apps https://screenshot.googleplex.com/3E5Jm7Pi2JfN64r with work tab: https://screenshot.googleplex.com/8egk4yHK5jSENjR PS Apps Special media management apps https://screenshot.googleplex.com/BHHafqW7bgUwSGg with work tab: https://screenshot.googleplex.com/3cocdhruEmCCh5k PS Location Services tab view https://screenshot.googleplex.com/3DqJcT2BFTEpvYT with work tab: https://screenshot.googleplex.com/6Avpx6hxSrdGJw5 PS on screen keyboard tab view https://screenshot.googleplex.com/4FzVNnBWwbUeJNw with work tab: https://screenshot.googleplex.com/8E8UhpWq8PL5nxU PS password account tab view https://screenshot.googleplex.com/6bDR4AKtth2S3EW with work tab: https://screenshot.googleplex.com/9msXV2TdHdJapch PS storage tab view https://screenshot.googleplex.com/5Nk2FTxwdmpEv3B with work tab: https://screenshot.googleplex.com/79tw2EaWZKfMsnC PS appl_languages_work https://screenshot.googleplex.com/3qrREeg3RQdHhhH Bug: 302278487 Test: manual Change-Id: I8cd39170827fbe251bc4075ef306206020b3a022
This commit is contained in:
@@ -15,10 +15,12 @@
|
||||
*/
|
||||
|
||||
package com.android.settings.dashboard.profileselector;
|
||||
|
||||
import androidx.fragment.app.Fragment;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.accounts.AccountPersonalDashboardFragment;
|
||||
import com.android.settings.accounts.AccountPrivateDashboardFragment;
|
||||
import com.android.settings.accounts.AccountWorkProfileDashboardFragment;
|
||||
|
||||
/**
|
||||
@@ -28,10 +30,12 @@ public class ProfileSelectAccountFragment extends ProfileSelectFragment {
|
||||
|
||||
@Override
|
||||
public Fragment[] getFragments() {
|
||||
return new Fragment[] {
|
||||
new AccountPersonalDashboardFragment(),
|
||||
new AccountWorkProfileDashboardFragment()
|
||||
};
|
||||
return ProfileSelectFragment.getFragments(
|
||||
getContext(),
|
||||
null /* bundle */,
|
||||
AccountPersonalDashboardFragment::new,
|
||||
AccountWorkProfileDashboardFragment::new,
|
||||
AccountPrivateDashboardFragment::new);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@@ -17,21 +17,28 @@
|
||||
package com.android.settings.dashboard.profileselector;
|
||||
|
||||
import static android.app.admin.DevicePolicyResources.Strings.Settings.PERSONAL_CATEGORY_HEADER;
|
||||
import static android.app.admin.DevicePolicyResources.Strings.Settings.PRIVATE_CATEGORY_HEADER;
|
||||
import static android.app.admin.DevicePolicyResources.Strings.Settings.WORK_CATEGORY_HEADER;
|
||||
import static android.content.Intent.EXTRA_USER_ID;
|
||||
|
||||
import android.annotation.IntDef;
|
||||
import android.app.Activity;
|
||||
import android.app.admin.DevicePolicyManager;
|
||||
import android.content.Context;
|
||||
import android.content.pm.UserInfo;
|
||||
import android.os.Bundle;
|
||||
import android.os.Flags;
|
||||
import android.os.UserHandle;
|
||||
import android.os.UserManager;
|
||||
import android.util.Log;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.LinearLayout;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
@@ -42,12 +49,14 @@ import com.android.settings.R;
|
||||
import com.android.settings.SettingsActivity;
|
||||
import com.android.settings.Utils;
|
||||
import com.android.settings.dashboard.DashboardFragment;
|
||||
import com.android.settings.privatespace.PrivateSpaceMaintainer;
|
||||
|
||||
import com.google.android.material.tabs.TabLayout;
|
||||
import com.google.android.material.tabs.TabLayoutMediator;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* Base fragment class for profile settings.
|
||||
@@ -77,9 +86,14 @@ public abstract class ProfileSelectFragment extends DashboardFragment {
|
||||
int WORK = 1 << 1;
|
||||
|
||||
/**
|
||||
* It is personal and work profile
|
||||
* It is private profile
|
||||
*/
|
||||
int ALL = PERSONAL | WORK;
|
||||
int PRIVATE = 1 << 2;
|
||||
|
||||
/**
|
||||
* It is personal, work, and private profile
|
||||
*/
|
||||
int ALL = PERSONAL | WORK | PRIVATE;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -97,6 +111,11 @@ public abstract class ProfileSelectFragment extends DashboardFragment {
|
||||
*/
|
||||
public static final int WORK_TAB = 1;
|
||||
|
||||
/**
|
||||
* Used in fragment argument with Extra key {@link SettingsActivity.EXTRA_SHOW_FRAGMENT_TAB}
|
||||
*/
|
||||
public static final int PRIVATE_TAB = 2;
|
||||
|
||||
private ViewGroup mContentView;
|
||||
|
||||
private ViewPager2 mViewPager;
|
||||
@@ -215,12 +234,20 @@ public abstract class ProfileSelectFragment extends DashboardFragment {
|
||||
if (isWorkProfile) {
|
||||
return WORK_TAB;
|
||||
}
|
||||
UserInfo userInfo = UserManager.get(activity).getUserInfo(userId);
|
||||
if (Flags.allowPrivateProfile() && userInfo != null && userInfo.isPrivateProfile()) {
|
||||
return PRIVATE_TAB;
|
||||
}
|
||||
}
|
||||
// Start intent from a specific user eg: adb shell --user 10
|
||||
final int intentUser = activity.getIntent().getContentUserHint();
|
||||
if (UserManager.get(activity).isManagedProfile(intentUser)) {
|
||||
return WORK_TAB;
|
||||
}
|
||||
UserInfo userInfo = UserManager.get(activity).getUserInfo(intentUser);
|
||||
if (Flags.allowPrivateProfile() && userInfo != null && userInfo.isPrivateProfile()) {
|
||||
return PRIVATE_TAB;
|
||||
}
|
||||
|
||||
return PERSONAL_TAB;
|
||||
}
|
||||
@@ -229,13 +256,114 @@ public abstract class ProfileSelectFragment extends DashboardFragment {
|
||||
final DevicePolicyManager devicePolicyManager =
|
||||
getContext().getSystemService(DevicePolicyManager.class);
|
||||
|
||||
if (position == WORK_TAB) {
|
||||
if (Flags.allowPrivateProfile()) {
|
||||
int tabForPosition =
|
||||
((ViewPagerAdapter) mViewPager.getAdapter()).getTabForPosition(position);
|
||||
|
||||
if (tabForPosition == WORK_TAB) {
|
||||
return devicePolicyManager.getResources().getString(WORK_CATEGORY_HEADER,
|
||||
() -> getContext().getString(
|
||||
com.android.settingslib.R.string.category_work));
|
||||
}
|
||||
|
||||
if (tabForPosition == PRIVATE_TAB) {
|
||||
return devicePolicyManager.getResources().getString(PRIVATE_CATEGORY_HEADER,
|
||||
() -> getContext()
|
||||
.getString(com.android.settingslib.R.string.category_private));
|
||||
}
|
||||
|
||||
} else if (position == WORK_TAB) {
|
||||
return devicePolicyManager.getResources().getString(WORK_CATEGORY_HEADER,
|
||||
() -> getContext().getString(com.android.settingslib.R.string.category_work));
|
||||
|
||||
}
|
||||
return devicePolicyManager.getResources().getString(PERSONAL_CATEGORY_HEADER,
|
||||
() -> getContext().getString(
|
||||
com.android.settingslib.R.string.category_personal));
|
||||
}
|
||||
|
||||
/** Creates fragments of passed types, and returns them in an array. */
|
||||
@NonNull static Fragment[] getFragments(
|
||||
Context context,
|
||||
@Nullable Bundle bundle,
|
||||
FragmentConstructor personalFragmentConstructor,
|
||||
FragmentConstructor workFragmentConstructor,
|
||||
FragmentConstructor privateFragmentConstructor) {
|
||||
return getFragments(
|
||||
context,
|
||||
bundle,
|
||||
personalFragmentConstructor,
|
||||
workFragmentConstructor,
|
||||
privateFragmentConstructor,
|
||||
new PrivateSpaceInfoProvider() {},
|
||||
new ManagedProfileInfoProvider() {});
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates fragments of passed types, and returns them in an array. This overload exists only
|
||||
* for helping with testing.
|
||||
*/
|
||||
@NonNull static Fragment[] getFragments(
|
||||
Context context,
|
||||
@Nullable Bundle bundle,
|
||||
FragmentConstructor personalFragmentConstructor,
|
||||
FragmentConstructor workFragmentConstructor,
|
||||
FragmentConstructor privateFragmentConstructor,
|
||||
PrivateSpaceInfoProvider privateSpaceInfoProvider,
|
||||
ManagedProfileInfoProvider managedProfileInfoProvider) {
|
||||
Fragment[] result = new Fragment[0];
|
||||
ArrayList<Fragment> fragments = new ArrayList<>();
|
||||
|
||||
try {
|
||||
final Bundle personalOnly = bundle != null ? bundle : new Bundle();
|
||||
personalOnly.putInt(EXTRA_PROFILE, ProfileType.PERSONAL);
|
||||
final Fragment personalFragment =
|
||||
personalFragmentConstructor.constructAndGetFragment();
|
||||
personalFragment.setArguments(personalOnly);
|
||||
fragments.add(personalFragment);
|
||||
|
||||
if (managedProfileInfoProvider.getManagedProfile(context) != null) {
|
||||
final Bundle workOnly = bundle != null ? bundle : new Bundle();
|
||||
workOnly.putInt(EXTRA_PROFILE, ProfileType.WORK);
|
||||
final Fragment workFragment =
|
||||
workFragmentConstructor.constructAndGetFragment();
|
||||
workFragment.setArguments(workOnly);
|
||||
fragments.add(workFragment);
|
||||
}
|
||||
|
||||
if (Flags.allowPrivateProfile()
|
||||
&& !privateSpaceInfoProvider.isPrivateSpaceLocked(context)) {
|
||||
final Bundle privateOnly = bundle != null ? bundle : new Bundle();
|
||||
privateOnly.putInt(EXTRA_PROFILE, ProfileType.PRIVATE);
|
||||
final Fragment privateFragment =
|
||||
privateFragmentConstructor.constructAndGetFragment();
|
||||
privateFragment.setArguments(privateOnly);
|
||||
fragments.add(privateFragment);
|
||||
}
|
||||
|
||||
result = new Fragment[fragments.size()];
|
||||
fragments.toArray(result);
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "Failed to create fragment");
|
||||
}
|
||||
|
||||
return devicePolicyManager.getResources().getString(PERSONAL_CATEGORY_HEADER,
|
||||
() -> getContext().getString(com.android.settingslib.R.string.category_personal));
|
||||
return result;
|
||||
}
|
||||
|
||||
interface FragmentConstructor {
|
||||
Fragment constructAndGetFragment();
|
||||
}
|
||||
|
||||
interface PrivateSpaceInfoProvider {
|
||||
default boolean isPrivateSpaceLocked(Context context) {
|
||||
return PrivateSpaceMaintainer.getInstance(context).isPrivateSpaceLocked();
|
||||
}
|
||||
}
|
||||
|
||||
interface ManagedProfileInfoProvider {
|
||||
default UserHandle getManagedProfile(Context context) {
|
||||
return Utils.getManagedProfile(context.getSystemService(UserManager.class));
|
||||
}
|
||||
}
|
||||
|
||||
static class ViewPagerAdapter extends FragmentStateAdapter {
|
||||
@@ -256,5 +384,22 @@ public abstract class ProfileSelectFragment extends DashboardFragment {
|
||||
public int getItemCount() {
|
||||
return mChildFragments.length;
|
||||
}
|
||||
|
||||
private int getTabForPosition(int position) {
|
||||
if (position >= mChildFragments.length) {
|
||||
Log.e(TAG, "tab requested for out of bound position " + position);
|
||||
return PERSONAL_TAB;
|
||||
}
|
||||
@ProfileType
|
||||
int profileType = mChildFragments[position].getArguments().getInt(EXTRA_PROFILE);
|
||||
|
||||
if (profileType == ProfileType.WORK) {
|
||||
return WORK_TAB;
|
||||
}
|
||||
if (profileType == ProfileType.PRIVATE) {
|
||||
return PRIVATE_TAB;
|
||||
}
|
||||
return PERSONAL_TAB;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -16,8 +16,6 @@
|
||||
|
||||
package com.android.settings.dashboard.profileselector;
|
||||
|
||||
import android.os.Bundle;
|
||||
|
||||
import androidx.fragment.app.Fragment;
|
||||
|
||||
import com.android.settings.R;
|
||||
@@ -39,19 +37,11 @@ public final class ProfileSelectKeyboardFragment extends ProfileSelectFragment {
|
||||
|
||||
@Override
|
||||
public Fragment[] getFragments() {
|
||||
final Bundle personalOnly = new Bundle();
|
||||
personalOnly.putInt(EXTRA_PROFILE, ProfileType.PERSONAL);
|
||||
final Fragment personalFragment = new AvailableVirtualKeyboardFragment();
|
||||
personalFragment.setArguments(personalOnly);
|
||||
|
||||
final Bundle workOnly = new Bundle();
|
||||
workOnly.putInt(EXTRA_PROFILE, ProfileType.WORK);
|
||||
final Fragment workFragment = new AvailableVirtualKeyboardFragment();
|
||||
workFragment.setArguments(workOnly);
|
||||
|
||||
return new Fragment[]{
|
||||
personalFragment,
|
||||
workFragment
|
||||
};
|
||||
return ProfileSelectFragment.getFragments(
|
||||
getContext(),
|
||||
null /* bundle */,
|
||||
AvailableVirtualKeyboardFragment::new,
|
||||
AvailableVirtualKeyboardFragment::new,
|
||||
AvailableVirtualKeyboardFragment::new);
|
||||
}
|
||||
}
|
||||
|
@@ -45,20 +45,12 @@ public class ProfileSelectLocationFragment extends ProfileSelectFragment {
|
||||
|
||||
@Override
|
||||
public Fragment[] getFragments() {
|
||||
|
||||
final Bundle workOnly = new Bundle();
|
||||
workOnly.putInt(EXTRA_PROFILE, ProfileSelectFragment.ProfileType.WORK);
|
||||
final Fragment workFragment = new LocationWorkProfileSettings();
|
||||
workFragment.setArguments(workOnly);
|
||||
|
||||
final Bundle personalOnly = new Bundle();
|
||||
personalOnly.putInt(EXTRA_PROFILE, ProfileSelectFragment.ProfileType.PERSONAL);
|
||||
final Fragment personalFragment = new LocationPersonalSettings();
|
||||
personalFragment.setArguments(personalOnly);
|
||||
return new Fragment[]{
|
||||
personalFragment,
|
||||
workFragment
|
||||
};
|
||||
return ProfileSelectFragment.getFragments(
|
||||
getContext(),
|
||||
null /* bundle */,
|
||||
LocationPersonalSettings::new,
|
||||
LocationWorkProfileSettings::new,
|
||||
LocationPersonalSettings::new);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@@ -16,8 +16,6 @@
|
||||
|
||||
package com.android.settings.dashboard.profileselector;
|
||||
|
||||
import android.os.Bundle;
|
||||
|
||||
import androidx.fragment.app.Fragment;
|
||||
|
||||
import com.android.settings.R;
|
||||
@@ -31,19 +29,12 @@ public class ProfileSelectLocationServicesFragment extends ProfileSelectFragment
|
||||
|
||||
@Override
|
||||
public Fragment[] getFragments() {
|
||||
final Bundle workOnly = new Bundle();
|
||||
workOnly.putInt(EXTRA_PROFILE, ProfileType.WORK);
|
||||
final Fragment workFragment = new LocationServicesForWork();
|
||||
workFragment.setArguments(workOnly);
|
||||
|
||||
final Bundle personalOnly = new Bundle();
|
||||
personalOnly.putInt(EXTRA_PROFILE, ProfileType.PERSONAL);
|
||||
final Fragment personalFragment = new LocationServices();
|
||||
personalFragment.setArguments(personalOnly);
|
||||
return new Fragment[]{
|
||||
personalFragment, // 0
|
||||
workFragment
|
||||
};
|
||||
return ProfileSelectFragment.getFragments(
|
||||
getContext(),
|
||||
null /* bundle */,
|
||||
LocationServices::new,
|
||||
LocationServicesForWork::new,
|
||||
LocationServices::new);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@@ -31,19 +31,12 @@ public class ProfileSelectManageApplications extends ProfileSelectFragment {
|
||||
|
||||
@Override
|
||||
public Fragment[] getFragments() {
|
||||
final Bundle workOnly = getArguments() != null ? getArguments().deepCopy() : new Bundle();
|
||||
workOnly.putInt(EXTRA_PROFILE, ProfileSelectFragment.ProfileType.WORK);
|
||||
final Fragment workFragment = new ManageApplications();
|
||||
workFragment.setArguments(workOnly);
|
||||
|
||||
final Bundle personalOnly = getArguments() != null ? getArguments() : new Bundle();
|
||||
personalOnly.putInt(EXTRA_PROFILE, ProfileSelectFragment.ProfileType.PERSONAL);
|
||||
final Fragment personalFragment = new ManageApplications();
|
||||
personalFragment.setArguments(personalOnly);
|
||||
return new Fragment[]{
|
||||
personalFragment, //0
|
||||
workFragment
|
||||
};
|
||||
return ProfileSelectFragment.getFragments(
|
||||
getContext(),
|
||||
getArguments(),
|
||||
ManageApplications::new,
|
||||
ManageApplications::new,
|
||||
ManageApplications::new);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@@ -51,22 +51,11 @@ public final class ProfileSelectPhysicalKeyboardFragment extends ProfileSelectFr
|
||||
|
||||
@Override
|
||||
public Fragment[] getFragments() {
|
||||
final Bundle personalOnly = new Bundle();
|
||||
personalOnly.putInt(EXTRA_PROFILE, ProfileType.PERSONAL);
|
||||
final Fragment personalFragment = new NewKeyboardLayoutEnabledLocalesFragment();
|
||||
personalOnly.putParcelable(
|
||||
Settings.EXTRA_INPUT_DEVICE_IDENTIFIER, mInputDeviceIdentifier);
|
||||
personalFragment.setArguments(personalOnly);
|
||||
|
||||
final Bundle workOnly = new Bundle();
|
||||
workOnly.putInt(EXTRA_PROFILE, ProfileType.WORK);
|
||||
final Fragment workFragment = new NewKeyboardLayoutEnabledLocalesFragment();
|
||||
workOnly.putParcelable(Settings.EXTRA_INPUT_DEVICE_IDENTIFIER, mInputDeviceIdentifier);
|
||||
workFragment.setArguments(workOnly);
|
||||
|
||||
return new Fragment[]{
|
||||
personalFragment,
|
||||
workFragment
|
||||
};
|
||||
return ProfileSelectFragment.getFragments(
|
||||
getContext(),
|
||||
null /* bundle */,
|
||||
NewKeyboardLayoutEnabledLocalesFragment::new,
|
||||
NewKeyboardLayoutEnabledLocalesFragment::new,
|
||||
NewKeyboardLayoutEnabledLocalesFragment::new);
|
||||
}
|
||||
}
|
||||
|
@@ -193,20 +193,12 @@ public class ProfileSelectStorageFragment extends ProfileSelectFragment {
|
||||
return mFragments;
|
||||
}
|
||||
|
||||
final Bundle workBundle = new Bundle();
|
||||
workBundle.putInt(EXTRA_PROFILE, ProfileType.WORK);
|
||||
final Fragment workFragment = new StorageCategoryFragment();
|
||||
workFragment.setArguments(workBundle);
|
||||
|
||||
final Bundle personalBundle = new Bundle();
|
||||
personalBundle.putInt(EXTRA_PROFILE, ProfileType.PERSONAL);
|
||||
final Fragment personalFragment = new StorageCategoryFragment();
|
||||
personalFragment.setArguments(personalBundle);
|
||||
|
||||
mFragments = new Fragment[] {
|
||||
personalFragment,
|
||||
workFragment
|
||||
};
|
||||
mFragments = ProfileSelectFragment.getFragments(
|
||||
getContext(),
|
||||
null /* bundle */,
|
||||
StorageCategoryFragment::new,
|
||||
StorageCategoryFragment::new,
|
||||
StorageCategoryFragment::new);
|
||||
return mFragments;
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user