diff --git a/res/values/strings.xml b/res/values/strings.xml index d1920a616b1..d08d3145a83 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -4057,6 +4057,8 @@ Languages & input + + You don\u2019t have permission to change the device language. Languages & input diff --git a/src/com/android/settings/localepicker/LocaleDragAndDropAdapter.java b/src/com/android/settings/localepicker/LocaleDragAndDropAdapter.java index 0b40bbd7703..1d21c123c9e 100644 --- a/src/com/android/settings/localepicker/LocaleDragAndDropAdapter.java +++ b/src/com/android/settings/localepicker/LocaleDragAndDropAdapter.java @@ -82,14 +82,13 @@ class LocaleDragAndDropAdapter } public LocaleDragAndDropAdapter(Context context, List 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 @@ class LocaleDragAndDropAdapter 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 165be900edb..79d538f7a79 100644 --- a/src/com/android/settings/localepicker/LocaleListEditor.java +++ b/src/com/android/settings/localepicker/LocaleListEditor.java @@ -18,7 +18,6 @@ package com.android.settings.localepicker; 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.MenuItem; 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 @@ public class LocaleListEditor extends SettingsPreferenceFragment 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 @@ public class LocaleListEditor extends SettingsPreferenceFragment setHasOptionsMenu(true); LocaleStore.fillCache(this.getContext()); - final List feedsList = getUserLocaleList(this.getContext()); + final List feedsList = getUserLocaleList(); mAdapter = new LocaleDragAndDropAdapter(this.getContext(), feedsList); } @@ -81,6 +88,25 @@ public class LocaleListEditor extends SettingsPreferenceFragment 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 public void onViewStateRestored(Bundle savedInstanceState) { super.onViewStateRestored(savedInstanceState); @@ -217,20 +243,18 @@ public class LocaleListEditor extends SettingsPreferenceFragment updateVisibilityOfRemoveMenu(); } - private static List getUserLocaleList(Context context) { + private List getUserLocaleList() { final List 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 @@ public class LocaleListEditor extends SettingsPreferenceFragment 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 00000000000..1ee52ca463c --- /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 00000000000..586ff488351 --- /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