Support DISALLOW_CONFIG_LOCALE user restriction
Bug: 67586452 Test: make ROBOTEST_FILTER="(LocaleListEditorTest)" RunSettingsRoboTests\ && make cts && cts-tradefed run cts-dev -m DevicePolicyManager \ -t com.android.cts.devicepolicy.UserRestrictionsTest Change-Id: I2260b106a111078a62ae7628d6f60e976b70069c
This commit is contained in:
@@ -4057,6 +4057,8 @@
|
|||||||
|
|
||||||
<!-- Title of setting on main settings screen. This item will take the user to the screen to tweak settings realted to locale and text -->
|
<!-- Title of setting on main settings screen. This item will take the user to the screen to tweak settings realted to locale and text -->
|
||||||
<string name="language_settings">Languages & input</string>
|
<string name="language_settings">Languages & input</string>
|
||||||
|
<!-- Text displayed when user has restriction DISALLOW_CONFIG_LOCALE [CHAR LIMIT=NONE]-->
|
||||||
|
<string name="language_empty_list_user_restricted">You don\u2019t have permission to change the device language.</string>
|
||||||
<!-- Title of Languages & input settings screen -->
|
<!-- Title of Languages & input settings screen -->
|
||||||
<string name="language_keyboard_settings_title">Languages & input</string>
|
<string name="language_keyboard_settings_title">Languages & input</string>
|
||||||
<!-- Title of preference category that lists all settings about helping user text input such as spell checker [CHAR LIMIT=60]-->
|
<!-- Title of preference category that lists all settings about helping user text input such as spell checker [CHAR LIMIT=60]-->
|
||||||
|
@@ -82,14 +82,13 @@ class LocaleDragAndDropAdapter
|
|||||||
}
|
}
|
||||||
|
|
||||||
public LocaleDragAndDropAdapter(Context context, List<LocaleStore.LocaleInfo> feedItemList) {
|
public LocaleDragAndDropAdapter(Context context, List<LocaleStore.LocaleInfo> feedItemList) {
|
||||||
this.mFeedItemList = feedItemList;
|
mFeedItemList = feedItemList;
|
||||||
|
mContext = context;
|
||||||
this.mContext = context;
|
|
||||||
|
|
||||||
final float dragElevation = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 8,
|
final float dragElevation = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 8,
|
||||||
context.getResources().getDisplayMetrics());
|
context.getResources().getDisplayMetrics());
|
||||||
|
|
||||||
this.mItemTouchHelper = new ItemTouchHelper(new ItemTouchHelper.SimpleCallback(
|
mItemTouchHelper = new ItemTouchHelper(new ItemTouchHelper.SimpleCallback(
|
||||||
ItemTouchHelper.UP | ItemTouchHelper.DOWN, 0 /* no swipe */) {
|
ItemTouchHelper.UP | ItemTouchHelper.DOWN, 0 /* no swipe */) {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -248,15 +247,6 @@ class LocaleDragAndDropAdapter
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
LocaleStore.LocaleInfo getFirstChecked() {
|
|
||||||
for (LocaleStore.LocaleInfo li : mFeedItemList) {
|
|
||||||
if (li.getChecked()) {
|
|
||||||
return li;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
void addLocale(LocaleStore.LocaleInfo li) {
|
void addLocale(LocaleStore.LocaleInfo li) {
|
||||||
mFeedItemList.add(li);
|
mFeedItemList.add(li);
|
||||||
notifyItemInserted(mFeedItemList.size() - 1);
|
notifyItemInserted(mFeedItemList.size() - 1);
|
||||||
|
@@ -18,7 +18,6 @@ package com.android.settings.localepicker;
|
|||||||
|
|
||||||
import android.app.AlertDialog;
|
import android.app.AlertDialog;
|
||||||
import android.app.FragmentTransaction;
|
import android.app.FragmentTransaction;
|
||||||
import android.content.Context;
|
|
||||||
import android.content.DialogInterface;
|
import android.content.DialogInterface;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.LocaleList;
|
import android.os.LocaleList;
|
||||||
@@ -30,21 +29,24 @@ import android.view.MenuItem;
|
|||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
|
|
||||||
|
import android.widget.TextView;
|
||||||
import com.android.internal.app.LocalePicker;
|
import com.android.internal.app.LocalePicker;
|
||||||
import com.android.internal.app.LocalePickerWithRegion;
|
import com.android.internal.app.LocalePickerWithRegion;
|
||||||
import com.android.internal.app.LocaleStore;
|
import com.android.internal.app.LocaleStore;
|
||||||
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
||||||
import com.android.settings.R;
|
import com.android.settings.R;
|
||||||
import com.android.settings.SettingsPreferenceFragment;
|
import com.android.settings.RestrictedSettingsFragment;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
|
||||||
|
import static android.os.UserManager.DISALLOW_CONFIG_LOCALE;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Drag-and-drop editor for the user-ordered locale lists.
|
* Drag-and-drop editor for the user-ordered locale lists.
|
||||||
*/
|
*/
|
||||||
public class LocaleListEditor extends SettingsPreferenceFragment
|
public class LocaleListEditor extends RestrictedSettingsFragment
|
||||||
implements LocalePickerWithRegion.LocaleSelectedListener {
|
implements LocalePickerWithRegion.LocaleSelectedListener {
|
||||||
|
|
||||||
private static final String CFGKEY_REMOVE_MODE = "localeRemoveMode";
|
private static final String CFGKEY_REMOVE_MODE = "localeRemoveMode";
|
||||||
@@ -56,6 +58,11 @@ public class LocaleListEditor extends SettingsPreferenceFragment
|
|||||||
private View mAddLanguage;
|
private View mAddLanguage;
|
||||||
private boolean mRemoveMode;
|
private boolean mRemoveMode;
|
||||||
private boolean mShowingRemoveDialog;
|
private boolean mShowingRemoveDialog;
|
||||||
|
private boolean mIsUiRestricted;
|
||||||
|
|
||||||
|
public LocaleListEditor() {
|
||||||
|
super(DISALLOW_CONFIG_LOCALE);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getMetricsCategory() {
|
public int getMetricsCategory() {
|
||||||
@@ -68,7 +75,7 @@ public class LocaleListEditor extends SettingsPreferenceFragment
|
|||||||
setHasOptionsMenu(true);
|
setHasOptionsMenu(true);
|
||||||
|
|
||||||
LocaleStore.fillCache(this.getContext());
|
LocaleStore.fillCache(this.getContext());
|
||||||
final List<LocaleStore.LocaleInfo> feedsList = getUserLocaleList(this.getContext());
|
final List<LocaleStore.LocaleInfo> feedsList = getUserLocaleList();
|
||||||
mAdapter = new LocaleDragAndDropAdapter(this.getContext(), feedsList);
|
mAdapter = new LocaleDragAndDropAdapter(this.getContext(), feedsList);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -81,6 +88,25 @@ public class LocaleListEditor extends SettingsPreferenceFragment
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onResume() {
|
||||||
|
super.onResume();
|
||||||
|
|
||||||
|
final boolean previouslyRestricted = mIsUiRestricted;
|
||||||
|
mIsUiRestricted = isUiRestricted();
|
||||||
|
final TextView emptyView = getEmptyTextView();
|
||||||
|
if (mIsUiRestricted && !previouslyRestricted) {
|
||||||
|
// Lock it down.
|
||||||
|
emptyView.setText(R.string.language_empty_list_user_restricted);
|
||||||
|
emptyView.setVisibility(View.VISIBLE);
|
||||||
|
updateVisibilityOfRemoveMenu();
|
||||||
|
} else if (!mIsUiRestricted && previouslyRestricted) {
|
||||||
|
// Unlock it.
|
||||||
|
emptyView.setVisibility(View.GONE);
|
||||||
|
updateVisibilityOfRemoveMenu();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onViewStateRestored(Bundle savedInstanceState) {
|
public void onViewStateRestored(Bundle savedInstanceState) {
|
||||||
super.onViewStateRestored(savedInstanceState);
|
super.onViewStateRestored(savedInstanceState);
|
||||||
@@ -217,20 +243,18 @@ public class LocaleListEditor extends SettingsPreferenceFragment
|
|||||||
updateVisibilityOfRemoveMenu();
|
updateVisibilityOfRemoveMenu();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static List<LocaleStore.LocaleInfo> getUserLocaleList(Context context) {
|
private List<LocaleStore.LocaleInfo> getUserLocaleList() {
|
||||||
final List<LocaleStore.LocaleInfo> result = new ArrayList<>();
|
final List<LocaleStore.LocaleInfo> result = new ArrayList<>();
|
||||||
|
|
||||||
final LocaleList localeList = LocalePicker.getLocales();
|
final LocaleList localeList = LocalePicker.getLocales();
|
||||||
for (int i = 0; i < localeList.size(); i++) {
|
for (int i = 0; i < localeList.size(); i++) {
|
||||||
Locale locale = localeList.get(i);
|
Locale locale = localeList.get(i);
|
||||||
result.add(LocaleStore.getLocaleInfo(locale));
|
result.add(LocaleStore.getLocaleInfo(locale));
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void configureDragAndDrop(View view) {
|
private void configureDragAndDrop(View view) {
|
||||||
final RecyclerView list = (RecyclerView) view.findViewById(R.id.dragList);
|
final RecyclerView list = view.findViewById(R.id.dragList);
|
||||||
final LocaleLinearLayoutManager llm = new LocaleLinearLayoutManager(getContext(), mAdapter);
|
final LocaleLinearLayoutManager llm = new LocaleLinearLayoutManager(getContext(), mAdapter);
|
||||||
llm.setAutoMeasureEnabled(true);
|
llm.setAutoMeasureEnabled(true);
|
||||||
list.setLayoutManager(llm);
|
list.setLayoutManager(llm);
|
||||||
@@ -272,7 +296,8 @@ public class LocaleListEditor extends SettingsPreferenceFragment
|
|||||||
if (menuItemRemove != null) {
|
if (menuItemRemove != null) {
|
||||||
menuItemRemove.setShowAsAction(
|
menuItemRemove.setShowAsAction(
|
||||||
mRemoveMode ? MenuItem.SHOW_AS_ACTION_ALWAYS : MenuItem.SHOW_AS_ACTION_NEVER);
|
mRemoveMode ? MenuItem.SHOW_AS_ACTION_ALWAYS : MenuItem.SHOW_AS_ACTION_NEVER);
|
||||||
menuItemRemove.setVisible(mAdapter.getItemCount() > 1);
|
final boolean hasMultipleLanguages = mAdapter.getItemCount() > 1;
|
||||||
|
menuItemRemove.setVisible(hasMultipleLanguages && !mIsUiRestricted);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -0,0 +1,66 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2017 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.localepicker;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.view.View;
|
||||||
|
import android.widget.TextView;
|
||||||
|
import com.android.settings.TestConfig;
|
||||||
|
import com.android.settings.testutils.SettingsRobolectricTestRunner;
|
||||||
|
import com.android.settings.testutils.shadow.ShadowSettingsPreferenceFragment;
|
||||||
|
|
||||||
|
import org.junit.Assert;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.robolectric.RuntimeEnvironment;
|
||||||
|
import org.robolectric.annotation.Config;
|
||||||
|
import org.robolectric.util.ReflectionHelpers;
|
||||||
|
|
||||||
|
@RunWith(SettingsRobolectricTestRunner.class)
|
||||||
|
@Config(manifest = TestConfig.MANIFEST_PATH,
|
||||||
|
sdk = TestConfig.SDK_VERSION,
|
||||||
|
shadows = { ShadowSettingsPreferenceFragment.class })
|
||||||
|
public class LocaleListEditorTest {
|
||||||
|
|
||||||
|
private LocaleListEditor mLocaleListEditor;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp() {
|
||||||
|
mLocaleListEditor = new LocaleListEditor();
|
||||||
|
ReflectionHelpers.setField(mLocaleListEditor, "mEmptyTextView",
|
||||||
|
new TextView(RuntimeEnvironment.application));
|
||||||
|
ReflectionHelpers.setField(mLocaleListEditor, "mRestrictionsManager",
|
||||||
|
RuntimeEnvironment.application.getSystemService(Context.RESTRICTIONS_SERVICE));
|
||||||
|
ReflectionHelpers.setField(mLocaleListEditor, "mUserManager",
|
||||||
|
RuntimeEnvironment.application.getSystemService(Context.USER_SERVICE));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testDisallowConfigLocale_unrestrict() {
|
||||||
|
ReflectionHelpers.setField(mLocaleListEditor, "mIsUiRestricted", true);
|
||||||
|
mLocaleListEditor.onResume();
|
||||||
|
Assert.assertEquals(View.GONE, mLocaleListEditor.getEmptyTextView().getVisibility());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testDisallowConfigLocale_restrict() {
|
||||||
|
ReflectionHelpers.setField(mLocaleListEditor, "mIsUiRestricted", false);
|
||||||
|
mLocaleListEditor.onResume();
|
||||||
|
Assert.assertEquals(View.VISIBLE, mLocaleListEditor.getEmptyTextView().getVisibility());
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,38 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2017 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.testutils.shadow;
|
||||||
|
|
||||||
|
import android.os.Bundle;
|
||||||
|
|
||||||
|
import com.android.settings.SettingsPreferenceFragment;
|
||||||
|
import org.robolectric.annotation.Implementation;
|
||||||
|
import org.robolectric.annotation.Implements;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shadow of {@link SettingsPreferenceFragment}.
|
||||||
|
*
|
||||||
|
* Override the {@link #onCreate(Bundle)} to skip a null pointer exception in
|
||||||
|
* {@link android.content.res.Resources.Theme}, much the same as {@link ShadowDashboardFragment}.
|
||||||
|
*/
|
||||||
|
@Implements(SettingsPreferenceFragment.class)
|
||||||
|
public class ShadowSettingsPreferenceFragment {
|
||||||
|
|
||||||
|
@Implementation
|
||||||
|
public void onCreate(Bundle savedInstanceState) {
|
||||||
|
// do nothing
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user