Merge "Support DISALLOW_CONFIG_LOCALE user restriction"
diff --git a/res/values/strings.xml b/res/values/strings.xml
index d1920a6..d08d314 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -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 -->
<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 -->
<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]-->
diff --git a/src/com/android/settings/localepicker/LocaleDragAndDropAdapter.java b/src/com/android/settings/localepicker/LocaleDragAndDropAdapter.java
index 0b40bbd..1d21c12 100644
--- a/src/com/android/settings/localepicker/LocaleDragAndDropAdapter.java
+++ b/src/com/android/settings/localepicker/LocaleDragAndDropAdapter.java
@@ -82,14 +82,13 @@
}
public LocaleDragAndDropAdapter(Context context, List<LocaleStore.LocaleInfo> feedItemList) {
- this.mFeedItemList = feedItemList;
-
- this.mContext = context;
+ mFeedItemList = feedItemList;
+ mContext = context;
final float dragElevation = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 8,
context.getResources().getDisplayMetrics());
- this.mItemTouchHelper = new ItemTouchHelper(new ItemTouchHelper.SimpleCallback(
+ mItemTouchHelper = new ItemTouchHelper(new ItemTouchHelper.SimpleCallback(
ItemTouchHelper.UP | ItemTouchHelper.DOWN, 0 /* no swipe */) {
@Override
@@ -248,15 +247,6 @@
return result;
}
- LocaleStore.LocaleInfo getFirstChecked() {
- for (LocaleStore.LocaleInfo li : mFeedItemList) {
- if (li.getChecked()) {
- return li;
- }
- }
- return null;
- }
-
void addLocale(LocaleStore.LocaleInfo li) {
mFeedItemList.add(li);
notifyItemInserted(mFeedItemList.size() - 1);
diff --git a/src/com/android/settings/localepicker/LocaleListEditor.java b/src/com/android/settings/localepicker/LocaleListEditor.java
index 165be90..79d538f 100644
--- a/src/com/android/settings/localepicker/LocaleListEditor.java
+++ b/src/com/android/settings/localepicker/LocaleListEditor.java
@@ -18,7 +18,6 @@
import android.app.AlertDialog;
import android.app.FragmentTransaction;
-import android.content.Context;
import android.content.DialogInterface;
import android.os.Bundle;
import android.os.LocaleList;
@@ -30,21 +29,24 @@
import android.view.View;
import android.view.ViewGroup;
+import android.widget.TextView;
import com.android.internal.app.LocalePicker;
import com.android.internal.app.LocalePickerWithRegion;
import com.android.internal.app.LocaleStore;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settings.R;
-import com.android.settings.SettingsPreferenceFragment;
+import com.android.settings.RestrictedSettingsFragment;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
+import static android.os.UserManager.DISALLOW_CONFIG_LOCALE;
+
/**
* Drag-and-drop editor for the user-ordered locale lists.
*/
-public class LocaleListEditor extends SettingsPreferenceFragment
+public class LocaleListEditor extends RestrictedSettingsFragment
implements LocalePickerWithRegion.LocaleSelectedListener {
private static final String CFGKEY_REMOVE_MODE = "localeRemoveMode";
@@ -56,6 +58,11 @@
private View mAddLanguage;
private boolean mRemoveMode;
private boolean mShowingRemoveDialog;
+ private boolean mIsUiRestricted;
+
+ public LocaleListEditor() {
+ super(DISALLOW_CONFIG_LOCALE);
+ }
@Override
public int getMetricsCategory() {
@@ -68,7 +75,7 @@
setHasOptionsMenu(true);
LocaleStore.fillCache(this.getContext());
- final List<LocaleStore.LocaleInfo> feedsList = getUserLocaleList(this.getContext());
+ final List<LocaleStore.LocaleInfo> feedsList = getUserLocaleList();
mAdapter = new LocaleDragAndDropAdapter(this.getContext(), feedsList);
}
@@ -82,6 +89,25 @@
}
@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
public void onViewStateRestored(Bundle savedInstanceState) {
super.onViewStateRestored(savedInstanceState);
if (savedInstanceState != null) {
@@ -217,20 +243,18 @@
updateVisibilityOfRemoveMenu();
}
- private static List<LocaleStore.LocaleInfo> getUserLocaleList(Context context) {
+ private List<LocaleStore.LocaleInfo> getUserLocaleList() {
final List<LocaleStore.LocaleInfo> result = new ArrayList<>();
-
final LocaleList localeList = LocalePicker.getLocales();
for (int i = 0; i < localeList.size(); i++) {
Locale locale = localeList.get(i);
result.add(LocaleStore.getLocaleInfo(locale));
}
-
return result;
}
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);
llm.setAutoMeasureEnabled(true);
list.setLayoutManager(llm);
@@ -272,7 +296,8 @@
if (menuItemRemove != null) {
menuItemRemove.setShowAsAction(
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);
}
}
}
diff --git a/tests/robotests/src/com/android/settings/localepicker/LocaleListEditorTest.java b/tests/robotests/src/com/android/settings/localepicker/LocaleListEditorTest.java
new file mode 100644
index 0000000..1ee52ca
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/localepicker/LocaleListEditorTest.java
@@ -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());
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowSettingsPreferenceFragment.java b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowSettingsPreferenceFragment.java
new file mode 100644
index 0000000..586ff48
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowSettingsPreferenceFragment.java
@@ -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
+ }
+}
\ No newline at end of file