Implement work-profile infra in BasePreferenceController
- Add settings:forWork in xml - Set mIsForWork based on xml attribute - Delete WorkProfilePreferenceController and move its function to BasePreferenceController Fixes: 123376083 Test: Add work profile, go to Settings->System->Language&input, UI should show work profile related items Change-Id: Id2dcbb0e158c117cdfd363466a275f4e133c345e
This commit is contained in:
@@ -68,8 +68,10 @@
|
|||||||
<attr name="searchable" format="boolean" />
|
<attr name="searchable" format="boolean" />
|
||||||
<!-- Classname of a PreferenceController corresponding to the preference -->
|
<!-- Classname of a PreferenceController corresponding to the preference -->
|
||||||
<attr name="controller" format="string" />
|
<attr name="controller" format="string" />
|
||||||
<!-- customized subtitle if it's an unavailable slice -->
|
<!-- Customized subtitle if it's an unavailable slice -->
|
||||||
<attr name="unavailableSliceSubtitle" format="string" />
|
<attr name="unavailableSliceSubtitle" format="string" />
|
||||||
|
<!-- Whether or not the preference is for work profile, by default it's false. -->
|
||||||
|
<attr name="forWork" format="boolean" />
|
||||||
</declare-styleable>
|
</declare-styleable>
|
||||||
|
|
||||||
<declare-styleable name="PreferenceScreen">
|
<declare-styleable name="PreferenceScreen">
|
||||||
@@ -112,10 +114,6 @@
|
|||||||
<attr name="confirmDeviceCredentialsSideMargin" format="dimension" />
|
<attr name="confirmDeviceCredentialsSideMargin" format="dimension" />
|
||||||
<attr name="confirmDeviceCredentialsTopMargin" format="dimension" />
|
<attr name="confirmDeviceCredentialsTopMargin" format="dimension" />
|
||||||
|
|
||||||
<declare-styleable name="WorkPreference">
|
|
||||||
<attr name="forWork" format="boolean" />
|
|
||||||
</declare-styleable>
|
|
||||||
|
|
||||||
<declare-styleable name="VideoPreference">
|
<declare-styleable name="VideoPreference">
|
||||||
<attr name="animation" format="reference" />
|
<attr name="animation" format="reference" />
|
||||||
<attr name="preview" format="reference" />
|
<attr name="preview" format="reference" />
|
||||||
|
@@ -101,18 +101,21 @@
|
|||||||
android:key="virtual_keyboards_for_work_pref"
|
android:key="virtual_keyboards_for_work_pref"
|
||||||
android:title="@string/virtual_keyboards_for_work_title"
|
android:title="@string/virtual_keyboards_for_work_title"
|
||||||
android:fragment="com.android.settings.inputmethod.VirtualKeyboardFragment"
|
android:fragment="com.android.settings.inputmethod.VirtualKeyboardFragment"
|
||||||
|
settings:forWork="true"
|
||||||
settings:controller="com.android.settings.inputmethod.VirtualKeyboardForWorkPreferenceController" />
|
settings:controller="com.android.settings.inputmethod.VirtualKeyboardForWorkPreferenceController" />
|
||||||
|
|
||||||
<Preference
|
<Preference
|
||||||
android:key="spellcheckers_settings_for_work_pref"
|
android:key="spellcheckers_settings_for_work_pref"
|
||||||
android:title="@string/spellcheckers_settings_for_work_title"
|
android:title="@string/spellcheckers_settings_for_work_title"
|
||||||
android:fragment="com.android.settings.inputmethod.SpellCheckersSettings"
|
android:fragment="com.android.settings.inputmethod.SpellCheckersSettings"
|
||||||
|
settings:forWork="true"
|
||||||
settings:controller="com.android.settings.language.UserDictionaryForWorkPreferenceController" />
|
settings:controller="com.android.settings.language.UserDictionaryForWorkPreferenceController" />
|
||||||
|
|
||||||
<Preference
|
<Preference
|
||||||
android:key="user_dictionary_settings_for_work_pref"
|
android:key="user_dictionary_settings_for_work_pref"
|
||||||
android:title="@string/user_dict_settings_for_work_title"
|
android:title="@string/user_dict_settings_for_work_title"
|
||||||
android:fragment="com.android.settings.inputmethod.UserDictionaryList"
|
android:fragment="com.android.settings.inputmethod.UserDictionaryList"
|
||||||
|
settings:forWork="true"
|
||||||
settings:controller="com.android.settings.inputmethod.SpellCheckerForWorkPreferenceController" />
|
settings:controller="com.android.settings.inputmethod.SpellCheckerForWorkPreferenceController" />
|
||||||
</com.android.settings.widget.WorkOnlyCategory>
|
</com.android.settings.widget.WorkOnlyCategory>
|
||||||
|
|
||||||
|
@@ -62,6 +62,7 @@
|
|||||||
android:selectable="true"
|
android:selectable="true"
|
||||||
android:title="@string/managed_profile_location_switch_title"
|
android:title="@string/managed_profile_location_switch_title"
|
||||||
settings:controller="com.android.settings.location.LocationForWorkPreferenceController"
|
settings:controller="com.android.settings.location.LocationForWorkPreferenceController"
|
||||||
|
settings:forWork="true"
|
||||||
settings:useAdminDisabledSummary="true"/>
|
settings:useAdminDisabledSummary="true"/>
|
||||||
|
|
||||||
<PreferenceCategory
|
<PreferenceCategory
|
||||||
@@ -73,6 +74,7 @@
|
|||||||
<PreferenceCategory
|
<PreferenceCategory
|
||||||
android:key="location_services_managed_profile"
|
android:key="location_services_managed_profile"
|
||||||
android:title="@string/managed_profile_location_services"
|
android:title="@string/managed_profile_location_services"
|
||||||
|
settings:forWork="true"
|
||||||
settings:controller="com.android.settings.location.LocationServiceForWorkPreferenceController"/>
|
settings:controller="com.android.settings.location.LocationServiceForWorkPreferenceController"/>
|
||||||
|
|
||||||
</PreferenceCategory>
|
</PreferenceCategory>
|
||||||
|
@@ -13,17 +13,24 @@
|
|||||||
*/
|
*/
|
||||||
package com.android.settings.core;
|
package com.android.settings.core;
|
||||||
|
|
||||||
|
import static com.android.settings.dashboard.DashboardFragment.CATEGORY;
|
||||||
|
|
||||||
import android.annotation.IntDef;
|
import android.annotation.IntDef;
|
||||||
|
import android.app.settings.SettingsEnums;
|
||||||
import android.content.ContentResolver;
|
import android.content.ContentResolver;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
|
import android.os.UserHandle;
|
||||||
|
import android.os.UserManager;
|
||||||
import android.provider.SettingsSlicesContract;
|
import android.provider.SettingsSlicesContract;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
import androidx.preference.Preference;
|
import androidx.preference.Preference;
|
||||||
import androidx.preference.PreferenceScreen;
|
import androidx.preference.PreferenceScreen;
|
||||||
|
|
||||||
|
import com.android.settings.Utils;
|
||||||
import com.android.settings.slices.SettingsSliceProvider;
|
import com.android.settings.slices.SettingsSliceProvider;
|
||||||
import com.android.settings.slices.SliceData;
|
import com.android.settings.slices.SliceData;
|
||||||
import com.android.settings.slices.Sliceable;
|
import com.android.settings.slices.Sliceable;
|
||||||
@@ -109,9 +116,11 @@ public abstract class BasePreferenceController extends AbstractPreferenceControl
|
|||||||
*/
|
*/
|
||||||
public static final int DISABLED_DEPENDENT_SETTING = 5;
|
public static final int DISABLED_DEPENDENT_SETTING = 5;
|
||||||
|
|
||||||
|
|
||||||
protected final String mPreferenceKey;
|
protected final String mPreferenceKey;
|
||||||
protected UiBlockListener mUiBlockListener;
|
protected UiBlockListener mUiBlockListener;
|
||||||
|
private boolean mIsForWork;
|
||||||
|
@Nullable
|
||||||
|
private UserHandle mWorkProfileUser;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiate a controller as specified controller type and user-defined key.
|
* Instantiate a controller as specified controller type and user-defined key.
|
||||||
@@ -151,6 +160,34 @@ public abstract class BasePreferenceController extends AbstractPreferenceControl
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instantiate a controller as specified controller type and work profile
|
||||||
|
* <p/>
|
||||||
|
* This is done through reflection. Do not use this method unless you know what you are doing.
|
||||||
|
*
|
||||||
|
* @param context application context
|
||||||
|
* @param controllerName class name of the {@link BasePreferenceController}
|
||||||
|
* @param key attribute android:key of the {@link Preference}
|
||||||
|
* @param isWorkProfile is this controller only for work profile user?
|
||||||
|
*/
|
||||||
|
public static BasePreferenceController createInstance(Context context, String controllerName,
|
||||||
|
String key, boolean isWorkProfile) {
|
||||||
|
try {
|
||||||
|
final Class<?> clazz = Class.forName(controllerName);
|
||||||
|
final Constructor<?> preferenceConstructor =
|
||||||
|
clazz.getConstructor(Context.class, String.class);
|
||||||
|
final Object[] params = new Object[]{context, key};
|
||||||
|
final BasePreferenceController controller =
|
||||||
|
(BasePreferenceController) preferenceConstructor.newInstance(params);
|
||||||
|
controller.setForWork(isWorkProfile);
|
||||||
|
return controller;
|
||||||
|
} catch (ClassNotFoundException | NoSuchMethodException | InstantiationException
|
||||||
|
| IllegalArgumentException | InvocationTargetException | IllegalAccessException e) {
|
||||||
|
throw new IllegalStateException(
|
||||||
|
"Invalid preference controller: " + controllerName, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public BasePreferenceController(Context context, String preferenceKey) {
|
public BasePreferenceController(Context context, String preferenceKey) {
|
||||||
super(context);
|
super(context);
|
||||||
mPreferenceKey = preferenceKey;
|
mPreferenceKey = preferenceKey;
|
||||||
@@ -166,6 +203,9 @@ public abstract class BasePreferenceController extends AbstractPreferenceControl
|
|||||||
* </p>
|
* </p>
|
||||||
* The status is used for the convenience methods: {@link #isAvailable()},
|
* The status is used for the convenience methods: {@link #isAvailable()},
|
||||||
* {@link #isSupported()}
|
* {@link #isSupported()}
|
||||||
|
* </p>
|
||||||
|
* The inherited class doesn't need to check work profile is existed or not if
|
||||||
|
* android:forWork="true" is set in preference xml.
|
||||||
*/
|
*/
|
||||||
@AvailabilityStatus
|
@AvailabilityStatus
|
||||||
public abstract int getAvailabilityStatus();
|
public abstract int getAvailabilityStatus();
|
||||||
@@ -198,12 +238,18 @@ public abstract class BasePreferenceController extends AbstractPreferenceControl
|
|||||||
* {@link #DISABLED_DEPENDENT_SETTING}, then the setting will be disabled by default in the
|
* {@link #DISABLED_DEPENDENT_SETTING}, then the setting will be disabled by default in the
|
||||||
* DashboardFragment, and it is up to the {@link BasePreferenceController} to enable the
|
* DashboardFragment, and it is up to the {@link BasePreferenceController} to enable the
|
||||||
* preference at the right time.
|
* preference at the right time.
|
||||||
*
|
* <p>
|
||||||
|
* This function also check if work profile is existed when android:forWork="true" is set for
|
||||||
|
* the controller in preference xml.
|
||||||
* TODO (mfritze) Build a dependency mechanism to allow a controller to easily define the
|
* TODO (mfritze) Build a dependency mechanism to allow a controller to easily define the
|
||||||
* dependent setting.
|
* dependent setting.
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public final boolean isAvailable() {
|
public final boolean isAvailable() {
|
||||||
|
if (mIsForWork && mWorkProfileUser == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
final int availabilityStatus = getAvailabilityStatus();
|
final int availabilityStatus = getAvailabilityStatus();
|
||||||
return (availabilityStatus == AVAILABLE
|
return (availabilityStatus == AVAILABLE
|
||||||
|| availabilityStatus == AVAILABLE_UNSEARCHABLE
|
|| availabilityStatus == AVAILABLE_UNSEARCHABLE
|
||||||
@@ -266,6 +312,41 @@ public abstract class BasePreferenceController extends AbstractPreferenceControl
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicates this controller is only for work profile user
|
||||||
|
*/
|
||||||
|
void setForWork(boolean forWork) {
|
||||||
|
mIsForWork = forWork;
|
||||||
|
if (mIsForWork) {
|
||||||
|
mWorkProfileUser = Utils.getManagedProfile(UserManager.get(mContext));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Launches the specified fragment for the work profile user if the associated
|
||||||
|
* {@link Preference} is clicked. Otherwise just forward it to the super class.
|
||||||
|
*
|
||||||
|
* @param preference the preference being clicked.
|
||||||
|
* @return {@code true} if handled.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean handlePreferenceTreeClick(Preference preference) {
|
||||||
|
if (!TextUtils.equals(preference.getKey(), getPreferenceKey())) {
|
||||||
|
return super.handlePreferenceTreeClick(preference);
|
||||||
|
}
|
||||||
|
if (!mIsForWork || mWorkProfileUser == null) {
|
||||||
|
return super.handlePreferenceTreeClick(preference);
|
||||||
|
}
|
||||||
|
new SubSettingLauncher(preference.getContext())
|
||||||
|
.setDestination(preference.getFragment())
|
||||||
|
.setSourceMetricsCategory(preference.getExtras().getInt(CATEGORY,
|
||||||
|
SettingsEnums.PAGE_UNKNOWN))
|
||||||
|
.setArguments(preference.getExtras())
|
||||||
|
.setUserHandle(mWorkProfileUser)
|
||||||
|
.launch();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Updates raw data for search provider.
|
* Updates raw data for search provider.
|
||||||
*
|
*
|
||||||
@@ -316,4 +397,13 @@ public abstract class BasePreferenceController extends AbstractPreferenceControl
|
|||||||
*/
|
*/
|
||||||
public interface UiBlocker {
|
public interface UiBlocker {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Non-{@code null} {@link UserHandle} when a work profile is enabled.
|
||||||
|
* Otherwise {@code null}.
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
protected UserHandle getWorkProfileUser() {
|
||||||
|
return mWorkProfileUser;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -17,6 +17,7 @@
|
|||||||
package com.android.settings.core;
|
package com.android.settings.core;
|
||||||
|
|
||||||
import static com.android.settings.core.PreferenceXmlParserUtils.METADATA_CONTROLLER;
|
import static com.android.settings.core.PreferenceXmlParserUtils.METADATA_CONTROLLER;
|
||||||
|
import static com.android.settings.core.PreferenceXmlParserUtils.METADATA_FOR_WORK;
|
||||||
import static com.android.settings.core.PreferenceXmlParserUtils.METADATA_KEY;
|
import static com.android.settings.core.PreferenceXmlParserUtils.METADATA_KEY;
|
||||||
|
|
||||||
import android.annotation.NonNull;
|
import android.annotation.NonNull;
|
||||||
@@ -55,7 +56,7 @@ public class PreferenceControllerListHelper {
|
|||||||
try {
|
try {
|
||||||
preferenceMetadata = PreferenceXmlParserUtils.extractMetadata(context, xmlResId,
|
preferenceMetadata = PreferenceXmlParserUtils.extractMetadata(context, xmlResId,
|
||||||
MetadataFlag.FLAG_NEED_KEY | MetadataFlag.FLAG_NEED_PREF_CONTROLLER
|
MetadataFlag.FLAG_NEED_KEY | MetadataFlag.FLAG_NEED_PREF_CONTROLLER
|
||||||
| MetadataFlag.FLAG_INCLUDE_PREF_SCREEN);
|
| MetadataFlag.FLAG_INCLUDE_PREF_SCREEN | MetadataFlag.FLAG_FOR_WORK);
|
||||||
} catch (IOException | XmlPullParserException e) {
|
} catch (IOException | XmlPullParserException e) {
|
||||||
Log.e(TAG, "Failed to parse preference xml for getting controllers", e);
|
Log.e(TAG, "Failed to parse preference xml for getting controllers", e);
|
||||||
return controllers;
|
return controllers;
|
||||||
@@ -72,6 +73,7 @@ public class PreferenceControllerListHelper {
|
|||||||
} catch (IllegalStateException e) {
|
} catch (IllegalStateException e) {
|
||||||
Log.d(TAG, "Could not find Context-only controller for pref: " + controllerName);
|
Log.d(TAG, "Could not find Context-only controller for pref: " + controllerName);
|
||||||
final String key = metadata.getString(METADATA_KEY);
|
final String key = metadata.getString(METADATA_KEY);
|
||||||
|
final boolean isWorkProfile = metadata.getBoolean(METADATA_FOR_WORK, false);
|
||||||
if (TextUtils.isEmpty(key)) {
|
if (TextUtils.isEmpty(key)) {
|
||||||
Log.w(TAG, "Controller requires key but it's not defined in xml: "
|
Log.w(TAG, "Controller requires key but it's not defined in xml: "
|
||||||
+ controllerName);
|
+ controllerName);
|
||||||
@@ -79,7 +81,7 @@ public class PreferenceControllerListHelper {
|
|||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
controller = BasePreferenceController.createInstance(context, controllerName,
|
controller = BasePreferenceController.createInstance(context, controllerName,
|
||||||
key);
|
key, isWorkProfile);
|
||||||
} catch (IllegalStateException e2) {
|
} catch (IllegalStateException e2) {
|
||||||
Log.w(TAG, "Cannot instantiate controller from reflection: " + controllerName);
|
Log.w(TAG, "Cannot instantiate controller from reflection: " + controllerName);
|
||||||
continue;
|
continue;
|
||||||
|
@@ -72,7 +72,8 @@ public class PreferenceXmlParserUtils {
|
|||||||
MetadataFlag.FLAG_NEED_PREF_SUMMARY,
|
MetadataFlag.FLAG_NEED_PREF_SUMMARY,
|
||||||
MetadataFlag.FLAG_NEED_PREF_ICON,
|
MetadataFlag.FLAG_NEED_PREF_ICON,
|
||||||
MetadataFlag.FLAG_NEED_SEARCHABLE,
|
MetadataFlag.FLAG_NEED_SEARCHABLE,
|
||||||
MetadataFlag.FLAG_UNAVAILABLE_SLICE_SUBTITLE})
|
MetadataFlag.FLAG_UNAVAILABLE_SLICE_SUBTITLE,
|
||||||
|
MetadataFlag.FLAG_FOR_WORK})
|
||||||
@Retention(RetentionPolicy.SOURCE)
|
@Retention(RetentionPolicy.SOURCE)
|
||||||
public @interface MetadataFlag {
|
public @interface MetadataFlag {
|
||||||
|
|
||||||
@@ -87,6 +88,7 @@ public class PreferenceXmlParserUtils {
|
|||||||
int FLAG_NEED_SEARCHABLE = 1 << 9;
|
int FLAG_NEED_SEARCHABLE = 1 << 9;
|
||||||
int FLAG_NEED_PREF_APPEND = 1 << 10;
|
int FLAG_NEED_PREF_APPEND = 1 << 10;
|
||||||
int FLAG_UNAVAILABLE_SLICE_SUBTITLE = 1 << 11;
|
int FLAG_UNAVAILABLE_SLICE_SUBTITLE = 1 << 11;
|
||||||
|
int FLAG_FOR_WORK = 1 << 12;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final String METADATA_PREF_TYPE = "type";
|
public static final String METADATA_PREF_TYPE = "type";
|
||||||
@@ -98,8 +100,8 @@ public class PreferenceXmlParserUtils {
|
|||||||
public static final String METADATA_KEYWORDS = "keywords";
|
public static final String METADATA_KEYWORDS = "keywords";
|
||||||
public static final String METADATA_SEARCHABLE = "searchable";
|
public static final String METADATA_SEARCHABLE = "searchable";
|
||||||
public static final String METADATA_APPEND = "staticPreferenceLocation";
|
public static final String METADATA_APPEND = "staticPreferenceLocation";
|
||||||
public static final String METADATA_UNAVAILABLE_SLICE_SUBTITLE =
|
public static final String METADATA_UNAVAILABLE_SLICE_SUBTITLE = "unavailable_slice_subtitle";
|
||||||
"unavailable_slice_subtitle";
|
public static final String METADATA_FOR_WORK = "for_work";
|
||||||
|
|
||||||
private static final String ENTRIES_SEPARATOR = "|";
|
private static final String ENTRIES_SEPARATOR = "|";
|
||||||
|
|
||||||
@@ -244,6 +246,10 @@ public class PreferenceXmlParserUtils {
|
|||||||
preferenceMetadata.putString(METADATA_UNAVAILABLE_SLICE_SUBTITLE,
|
preferenceMetadata.putString(METADATA_UNAVAILABLE_SLICE_SUBTITLE,
|
||||||
getUnavailableSliceSubtitle(preferenceAttributes));
|
getUnavailableSliceSubtitle(preferenceAttributes));
|
||||||
}
|
}
|
||||||
|
if (hasFlag(flags, MetadataFlag.FLAG_FOR_WORK)) {
|
||||||
|
preferenceMetadata.putBoolean(METADATA_FOR_WORK,
|
||||||
|
isForWork(preferenceAttributes));
|
||||||
|
}
|
||||||
metadata.add(preferenceMetadata);
|
metadata.add(preferenceMetadata);
|
||||||
|
|
||||||
preferenceAttributes.recycle();
|
preferenceAttributes.recycle();
|
||||||
@@ -329,4 +335,9 @@ public class PreferenceXmlParserUtils {
|
|||||||
return styledAttributes.getString(
|
return styledAttributes.getString(
|
||||||
R.styleable.Preference_unavailableSliceSubtitle);
|
R.styleable.Preference_unavailableSliceSubtitle);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static boolean isForWork(TypedArray styledAttributes) {
|
||||||
|
return styledAttributes.getBoolean(
|
||||||
|
R.styleable.Preference_forWork, false);
|
||||||
|
}
|
||||||
}
|
}
|
@@ -1,97 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2019 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.settings.core;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import android.os.UserHandle;
|
|
||||||
import android.os.UserManager;
|
|
||||||
import android.text.TextUtils;
|
|
||||||
|
|
||||||
import androidx.annotation.Nullable;
|
|
||||||
import androidx.preference.Preference;
|
|
||||||
|
|
||||||
import com.android.settings.Utils;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Abstract class to provide additional logic to deal with optional {@link Preference} entries that
|
|
||||||
* are used only when work profile is enabled.
|
|
||||||
*
|
|
||||||
* <p>TODO(b/123376083): Consider merging this into {@link BasePreferenceController}.</p>
|
|
||||||
*/
|
|
||||||
public abstract class WorkProfilePreferenceController extends BasePreferenceController {
|
|
||||||
@Nullable
|
|
||||||
private final UserHandle mWorkProfileUser;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor of {@link WorkProfilePreferenceController}. Called by
|
|
||||||
* {@link BasePreferenceController#createInstance(Context, String)} through reflection.
|
|
||||||
*
|
|
||||||
* @param context {@link Context} to instantiate this controller.
|
|
||||||
* @param preferenceKey Preference key to be associated with the {@link Preference}.
|
|
||||||
*/
|
|
||||||
public WorkProfilePreferenceController(Context context, String preferenceKey) {
|
|
||||||
super(context, preferenceKey);
|
|
||||||
mWorkProfileUser = Utils.getManagedProfile(UserManager.get(context));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return Non-{@code null} {@link UserHandle} when a work profile is enabled.
|
|
||||||
* Otherwise {@code null}.
|
|
||||||
*/
|
|
||||||
@Nullable
|
|
||||||
protected UserHandle getWorkProfileUser() {
|
|
||||||
return mWorkProfileUser;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called back from {@link #handlePreferenceTreeClick(Preference)} to associate source metrics
|
|
||||||
* category.
|
|
||||||
*
|
|
||||||
* @return One of {@link android.app.settings.SettingsEnums}.
|
|
||||||
*/
|
|
||||||
protected abstract int getSourceMetricsCategory();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*
|
|
||||||
* <p>When you override this method, do not forget to check {@link #getWorkProfileUser()} to
|
|
||||||
* see if work profile user actually exists or not.</p>
|
|
||||||
*/
|
|
||||||
@AvailabilityStatus
|
|
||||||
@Override
|
|
||||||
public int getAvailabilityStatus() {
|
|
||||||
return mWorkProfileUser != null ? AVAILABLE : DISABLED_FOR_USER;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Launches the specified fragment for the work profile user if the associated
|
|
||||||
* {@link Preference} is clicked. Otherwise just forward it to the super class.
|
|
||||||
*
|
|
||||||
* @param preference the preference being clicked.
|
|
||||||
* @return {@code true} if handled.
|
|
||||||
*/
|
|
||||||
public boolean handlePreferenceTreeClick(Preference preference) {
|
|
||||||
if (!TextUtils.equals(preference.getKey(), getPreferenceKey())) {
|
|
||||||
return super.handlePreferenceTreeClick(preference);
|
|
||||||
}
|
|
||||||
new SubSettingLauncher(preference.getContext())
|
|
||||||
.setDestination(preference.getFragment())
|
|
||||||
.setSourceMetricsCategory(getSourceMetricsCategory())
|
|
||||||
.setArguments(preference.getExtras())
|
|
||||||
.setUserHandle(mWorkProfileUser)
|
|
||||||
.launch();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
@@ -65,6 +65,7 @@ public abstract class DashboardFragment extends SettingsPreferenceFragment
|
|||||||
implements SettingsBaseActivity.CategoryListener, Indexable,
|
implements SettingsBaseActivity.CategoryListener, Indexable,
|
||||||
PreferenceGroup.OnExpandButtonClickListener,
|
PreferenceGroup.OnExpandButtonClickListener,
|
||||||
BasePreferenceController.UiBlockListener {
|
BasePreferenceController.UiBlockListener {
|
||||||
|
public static final String CATEGORY = "category";
|
||||||
private static final String TAG = "DashboardFragment";
|
private static final String TAG = "DashboardFragment";
|
||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
@@ -206,6 +207,7 @@ public abstract class DashboardFragment extends SettingsPreferenceFragment
|
|||||||
mMetricsFeatureProvider.logDashboardStartIntent(
|
mMetricsFeatureProvider.logDashboardStartIntent(
|
||||||
getContext(), preference.getIntent(), getMetricsCategory());
|
getContext(), preference.getIntent(), getMetricsCategory());
|
||||||
// Give all controllers a chance to handle click.
|
// Give all controllers a chance to handle click.
|
||||||
|
preference.getExtras().putInt(CATEGORY, getMetricsCategory());
|
||||||
for (List<AbstractPreferenceController> controllerList : controllers) {
|
for (List<AbstractPreferenceController> controllerList : controllers) {
|
||||||
for (AbstractPreferenceController controller : controllerList) {
|
for (AbstractPreferenceController controller : controllerList) {
|
||||||
if (controller.handlePreferenceTreeClick(preference)) {
|
if (controller.handlePreferenceTreeClick(preference)) {
|
||||||
|
@@ -16,34 +16,28 @@
|
|||||||
|
|
||||||
package com.android.settings.inputmethod;
|
package com.android.settings.inputmethod;
|
||||||
|
|
||||||
import android.app.settings.SettingsEnums;
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
|
||||||
import com.android.settings.R;
|
import com.android.settings.R;
|
||||||
import com.android.settings.core.WorkProfilePreferenceController;
|
import com.android.settings.core.BasePreferenceController;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Preference controller for "Spell checker for work".
|
* Preference controller for "Spell checker for work".
|
||||||
*
|
*
|
||||||
* @see SpellCheckerPreferenceController
|
* @see SpellCheckerPreferenceController
|
||||||
*/
|
*/
|
||||||
public final class SpellCheckerForWorkPreferenceController extends WorkProfilePreferenceController {
|
public final class SpellCheckerForWorkPreferenceController extends BasePreferenceController {
|
||||||
|
|
||||||
public SpellCheckerForWorkPreferenceController(Context context, String preferenceKey) {
|
public SpellCheckerForWorkPreferenceController(Context context, String preferenceKey) {
|
||||||
super(context, preferenceKey);
|
super(context, preferenceKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
protected int getSourceMetricsCategory() {
|
|
||||||
return SettingsEnums.SETTINGS_LANGUAGE_CATEGORY;
|
|
||||||
}
|
|
||||||
|
|
||||||
@AvailabilityStatus
|
@AvailabilityStatus
|
||||||
@Override
|
@Override
|
||||||
public int getAvailabilityStatus() {
|
public int getAvailabilityStatus() {
|
||||||
if (!mContext.getResources().getBoolean(R.bool.config_show_spellcheckers_settings)) {
|
if (!mContext.getResources().getBoolean(R.bool.config_show_spellcheckers_settings)) {
|
||||||
return UNSUPPORTED_ON_DEVICE;
|
return UNSUPPORTED_ON_DEVICE;
|
||||||
}
|
}
|
||||||
return super.getAvailabilityStatus();
|
return AVAILABLE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -16,31 +16,25 @@
|
|||||||
|
|
||||||
package com.android.settings.inputmethod;
|
package com.android.settings.inputmethod;
|
||||||
|
|
||||||
import android.app.settings.SettingsEnums;
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
|
||||||
import com.android.settings.R;
|
import com.android.settings.R;
|
||||||
import com.android.settings.core.WorkProfilePreferenceController;
|
import com.android.settings.core.BasePreferenceController;
|
||||||
|
|
||||||
public final class VirtualKeyboardForWorkPreferenceController
|
public final class VirtualKeyboardForWorkPreferenceController
|
||||||
extends WorkProfilePreferenceController {
|
extends BasePreferenceController {
|
||||||
|
|
||||||
public VirtualKeyboardForWorkPreferenceController(Context context,
|
public VirtualKeyboardForWorkPreferenceController(Context context,
|
||||||
String preferenceKey) {
|
String preferenceKey) {
|
||||||
super(context, preferenceKey);
|
super(context, preferenceKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
protected int getSourceMetricsCategory() {
|
|
||||||
return SettingsEnums.SETTINGS_LANGUAGE_CATEGORY;
|
|
||||||
}
|
|
||||||
|
|
||||||
@AvailabilityStatus
|
@AvailabilityStatus
|
||||||
@Override
|
@Override
|
||||||
public int getAvailabilityStatus() {
|
public int getAvailabilityStatus() {
|
||||||
if (!mContext.getResources().getBoolean(R.bool.config_show_virtual_keyboard_pref)) {
|
if (!mContext.getResources().getBoolean(R.bool.config_show_virtual_keyboard_pref)) {
|
||||||
return UNSUPPORTED_ON_DEVICE;
|
return UNSUPPORTED_ON_DEVICE;
|
||||||
}
|
}
|
||||||
return super.getAvailabilityStatus();
|
return AVAILABLE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -16,11 +16,9 @@
|
|||||||
|
|
||||||
package com.android.settings.language;
|
package com.android.settings.language;
|
||||||
|
|
||||||
import android.app.settings.SettingsEnums;
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
|
||||||
import com.android.settings.R;
|
import com.android.settings.core.BasePreferenceController;
|
||||||
import com.android.settings.core.WorkProfilePreferenceController;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Preference controller for "UserDictionary for work".
|
* Preference controller for "UserDictionary for work".
|
||||||
@@ -28,14 +26,15 @@ import com.android.settings.core.WorkProfilePreferenceController;
|
|||||||
* @see UserDictionaryPreferenceController
|
* @see UserDictionaryPreferenceController
|
||||||
*/
|
*/
|
||||||
public final class UserDictionaryForWorkPreferenceController
|
public final class UserDictionaryForWorkPreferenceController
|
||||||
extends WorkProfilePreferenceController {
|
extends BasePreferenceController {
|
||||||
|
|
||||||
public UserDictionaryForWorkPreferenceController(Context context, String preferenceKey) {
|
public UserDictionaryForWorkPreferenceController(Context context, String preferenceKey) {
|
||||||
super(context, preferenceKey);
|
super(context, preferenceKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@AvailabilityStatus
|
||||||
@Override
|
@Override
|
||||||
protected int getSourceMetricsCategory() {
|
public int getAvailabilityStatus() {
|
||||||
return SettingsEnums.SETTINGS_LANGUAGE_CATEGORY;
|
return AVAILABLE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -56,9 +56,7 @@ public class LocationForWorkPreferenceController extends LocationBasePreferenceC
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getAvailabilityStatus() {
|
public int getAvailabilityStatus() {
|
||||||
// Looking for a managed profile. If there are no managed profiles then we are removing the
|
return AVAILABLE;
|
||||||
// managed profile category.
|
|
||||||
return Utils.getManagedProfile(mUserManager) != null ? AVAILABLE : UNSUPPORTED_ON_DEVICE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@@ -15,8 +15,6 @@
|
|||||||
*/
|
*/
|
||||||
package com.android.settings.location;
|
package com.android.settings.location;
|
||||||
|
|
||||||
import static com.google.common.truth.Truth.assertThat;
|
|
||||||
|
|
||||||
import static org.mockito.ArgumentMatchers.any;
|
import static org.mockito.ArgumentMatchers.any;
|
||||||
import static org.mockito.ArgumentMatchers.anyInt;
|
import static org.mockito.ArgumentMatchers.anyInt;
|
||||||
import static org.mockito.Mockito.doReturn;
|
import static org.mockito.Mockito.doReturn;
|
||||||
@@ -114,17 +112,6 @@ public class LocationForWorkPreferenceControllerTest {
|
|||||||
verify(mPreference).setSummary(R.string.switch_off_text);
|
verify(mPreference).setSummary(R.string.switch_off_text);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void isAvailable_noManagedProfile_shouldReturnFalse() {
|
|
||||||
when(mUserManager.getUserProfiles()).thenReturn(new ArrayList<>());
|
|
||||||
assertThat(mController.isAvailable()).isFalse();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void isAvailable_hasManagedProfile_shouldReturnTrue() {
|
|
||||||
assertThat(mController.isAvailable()).isTrue();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void onLocationModeChanged_disabledByAdmin_shouldDisablePreference() {
|
public void onLocationModeChanged_disabledByAdmin_shouldDisablePreference() {
|
||||||
mController.displayPreference(mScreen);
|
mController.displayPreference(mScreen);
|
||||||
|
Reference in New Issue
Block a user