Merge "Move a bunch of app restrictions logic to SettingsLib"
diff --git a/res/drawable/ic_settings_lock_outline.xml b/res/drawable/ic_settings_lock_outline.xml
index 1c4202c..a13700b 100644
--- a/res/drawable/ic_settings_lock_outline.xml
+++ b/res/drawable/ic_settings_lock_outline.xml
@@ -16,12 +16,12 @@
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="24dp"
- android:height="24dp"
- android:viewportWidth="24.0"
- android:viewportHeight="22.0"
+ android:width="21dp"
+ android:height="21dp"
+ android:viewportWidth="21.0"
+ android:viewportHeight="21.0"
android:tint="?android:attr/colorAccent">
<path
android:fillColor="@android:color/white"
- android:pathData="M12 17c1.1 0 2-.9 2-2s-.9-2-2-2-2 .9-2 2 .9 2 2 2zm6-9h-1V6c0-2.76-2.24-5-5-5S7 3.24 7 6v2H6c-1.1 0-2 .9-2 2v10c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2V10c0-1.1-.9-2-2-2zM8.9 6c0-1.71 1.39-3.1 3.1-3.1s3.1 1.39 3.1 3.1v2H8.9V6zM18 20H6V10h12v10z" />
+ android:pathData="M8,16c1.1,0,2-0.9,2-2s-0.9-2-2-2s-2,0.9-2,2S6.9,16,8,16zM14,7h-1V5c0-2.8-2.2-5-5-5S3,2.2,3,5v2H2C0.9,7,0,7.9,0,9v10c0,1.1,0.9,2,2,2h12c1.1,0,2-0.9,2-2V9C16,7.9,15.1,7,14,7z M4.9,5c0-1.7,1.4-3.1,3.1-3.1s3.1,1.4,3.1,3.1v2H4.9V5z M14,19H2V9h12V19z" />
</vector>
diff --git a/res/layout/font_size_activity.xml b/res/layout/font_size_activity.xml
new file mode 100644
index 0000000..9072d38
--- /dev/null
+++ b/res/layout/font_size_activity.xml
@@ -0,0 +1,90 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2015 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.
+-->
+
+<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <LinearLayout
+ android:orientation="vertical"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingTop="16dp"
+ android:paddingStart="?android:attr/listPreferredItemPaddingStart"
+ android:paddingEnd="?android:attr/listPreferredItemPaddingEnd">
+
+ <FrameLayout
+ android:layout_width="match_parent"
+ android:layout_height="@dimen/font_size_preview_height"
+ android:background="?android:attr/colorBackgroundFloating"
+ android:elevation="2dp">
+
+ <view class="com.android.settings.TouchBlockingFrameLayout"
+ android:id="@+id/preview_frame"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" />
+
+ <TextView
+ android:id="@+id/current_label"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_horizontal|bottom"
+ android:padding="8dp"
+ android:theme="@android:style/Theme.Material"
+ android:background="?android:attr/colorBackgroundFloating"
+ android:textAppearance="@android:style/TextAppearance.Material.Caption"
+ android:textAllCaps="true"
+ android:elevation="2dp" />
+ </FrameLayout>
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingTop="8dp">
+
+ <ImageView
+ android:id="@+id/smaller"
+ android:layout_width="48dp"
+ android:layout_height="48dp"
+ android:background="?android:attr/selectableItemBackgroundBorderless"
+ android:src="@drawable/ic_remove_24dp"
+ android:tint="?android:attr/colorControlNormal"
+ android:tintMode="src_in"
+ android:scaleType="center"
+ android:focusable="true"
+ android:contentDescription="@string/font_size_make_smaller_desc" />
+
+ <SeekBar
+ android:id="@+id/seek_bar"
+ android:layout_width="0dp"
+ android:layout_height="48dp"
+ android:layout_weight="1"
+ style="@android:style/Widget.Material.SeekBar.Discrete"/>
+
+ <ImageView
+ android:id="@+id/larger"
+ android:layout_width="48dp"
+ android:layout_height="48dp"
+ android:background="?android:attr/selectableItemBackgroundBorderless"
+ android:src="@drawable/ic_add_24dp"
+ android:tint="?android:attr/colorControlNormal"
+ android:tintMode="src_in"
+ android:scaleType="center"
+ android:focusable="true"
+ android:contentDescription="@string/font_size_make_larger_desc" />
+ </LinearLayout>
+ </LinearLayout>
+</ScrollView>
diff --git a/res/layout/font_size_preview.xml b/res/layout/font_size_preview.xml
new file mode 100644
index 0000000..1e3f69a
--- /dev/null
+++ b/res/layout/font_size_preview.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2015 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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical">
+
+ <TextView
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/font_size_preview_text_title"
+ android:textAppearance="@android:style/TextAppearance.Material.Title"/>
+
+ <TextView
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/font_size_preview_text_subhead"
+ android:textAppearance="@android:style/TextAppearance.Material.Subhead"/>
+
+ <TextView
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/font_size_preview_text_body"
+ android:textAppearance="@android:style/TextAppearance.Material.Body1"/>
+</LinearLayout>
diff --git a/res/layout/screen_zoom_activity.xml b/res/layout/screen_zoom_activity.xml
index 81ce102..a00e7bd 100644
--- a/res/layout/screen_zoom_activity.xml
+++ b/res/layout/screen_zoom_activity.xml
@@ -23,7 +23,7 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="16dp"
- android:paddingLeft="?android:attr/listPreferredItemPaddingStart"
+ android:paddingStart="?android:attr/listPreferredItemPaddingStart"
android:paddingEnd="?android:attr/listPreferredItemPaddingEnd">
<TextView
@@ -39,13 +39,13 @@
android:background="?android:attr/colorBackgroundFloating"
android:elevation="2dp">
- <com.android.settings.display.TouchBlockingFrameLayout
+ <view class="com.android.settings.TouchBlockingFrameLayout"
android:id="@+id/preview_frame"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<TextView
- android:id="@+id/current_density"
+ android:id="@+id/current_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal|bottom"
@@ -78,7 +78,8 @@
android:id="@+id/seek_bar"
android:layout_width="0dp"
android:layout_height="48dp"
- android:layout_weight="1" />
+ android:layout_weight="1"
+ style="@android:style/Widget.Material.SeekBar.Discrete"/>
<ImageView
android:id="@+id/larger"
diff --git a/res/layout/spinner_dropdown_restricted_item.xml b/res/layout/spinner_dropdown_restricted_item.xml
new file mode 100644
index 0000000..a965ad8
--- /dev/null
+++ b/res/layout/spinner_dropdown_restricted_item.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2015 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.
+-->
+<TextView xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@android:id/text1"
+ style="?android:attr/spinnerDropDownItemStyle"
+ android:singleLine="true"
+ android:layout_width="wrap_content"
+ android:layout_height="?android:attr/listPreferredItemHeightSmall"
+ android:ellipsize="marquee" />
\ No newline at end of file
diff --git a/res/values/colors.xml b/res/values/colors.xml
index f3fea10..5cf98fe 100644
--- a/res/values/colors.xml
+++ b/res/values/colors.xml
@@ -102,4 +102,6 @@
<!-- Accent color that matches the settings launcher icon -->
<color name="icon_accent">#ffabffec</color>
+ <color name="disabled_text_color">#66000000</color> <!-- 38% black -->
+
</resources>
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index f7c3437..792582a 100755
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -270,4 +270,7 @@
<!-- Accessibility Settings -->
<dimen name="accessibility_layout_margin_start_end">24dp</dimen>
<dimen name="accessibility_button_preference_padding_top_bottom">18dp</dimen>
+
+ <!-- Accessibility, Font size -->
+ <dimen name="font_size_preview_height">240dp</dimen>
</resources>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index bb6bbc0..d14c37a 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -154,8 +154,16 @@
<!-- choice for the font size spinner -->
<string name="large_font">Large</string>
+ <!-- Description for the button that makes interface elements smaller. [CHAR_LIMIT=NONE] -->
+ <string name="font_size_make_smaller_desc">Make smaller</string>
+ <!-- Description for the button that makes interface elements larger. [CHAR_LIMIT=NONE] -->
+ <string name="font_size_make_larger_desc">Make larger</string>
+
<!-- Do not translate. label for font size preview. Does not need to be translated. -->
<string name="font_size_preview_text">Servez à ce monsieur une bière et des kiwis.</string>
+ <string name="font_size_preview_text_title" translatable="false">Twenty Thousand Leagues Under The Sea</string>
+ <string name="font_size_preview_text_subhead" translatable="false">Chapter 23: The Coral Kingdom</string>
+ <string name="font_size_preview_text_body" translatable="false">The next day I woke with my head singularly clear. To my great surprise, I was in my own room. My companions, no doubt, had been reinstated in their cabin, without having perceived it any more than I. Of what had passed during the night they were as ignorant as I was, and to penetrate this mystery I only reckoned upon the chances of the future.</string>
<!-- Button. Chosen when they want to save the chosen text size. -->
<string name="font_size_save">OK</string>
@@ -164,23 +172,6 @@
<!-- Title for a notification shown. -->
<string name="sdcard_setting" product="default">SD card</string>
- <!-- Battery Info screen. Value for a status item. Used for diagnostic info screens, precise translation isn't needed -->
- <string name="battery_info_status_unknown">Unknown</string>
- <!-- [CHAR_LIMIT=20] Battery use screen. Battery status shown in chart label when charging from an unknown source. -->
- <string name="battery_info_status_charging">Charging</string>
- <!-- [CHAR_LIMIT=20] Battery use screen. Battery status shown in chart label when charging on AC. -->
- <string name="battery_info_status_charging_ac">Charging on AC</string>
- <!-- [CHAR_LIMIT=20] Battery use screen. Battery status shown in chart label when charging over USB. -->
- <string name="battery_info_status_charging_usb">Charging over USB</string>
- <!-- [CHAR_LIMIT=20] Battery use screen. Battery status shown in chart label when charging over a wireless connection. -->
- <string name="battery_info_status_charging_wireless">Charging wirelessly</string>
- <!-- Battery Info screen. Value for a status item. Used for diagnostic info screens, precise translation isn't needed -->
- <string name="battery_info_status_discharging">Not charging</string>
- <!-- Battery Info screen. Value for a status item. Used for diagnostic info screens, precise translation isn't needed -->
- <string name="battery_info_status_not_charging">Not charging</string>
- <!-- Battery Info screen. Value for a status item. Used for diagnostic info screens, precise translation isn't needed -->
- <string name="battery_info_status_full">Full</string>
-
<!-- Used as setting title (for checkbox) on second screen after selecting Bluetooth settings -->
<string name="bluetooth">Bluetooth</string>
<!-- Bluetooth settings screen, summary after selecting Discoverable check box [CHAR LIMIT=50] -->
@@ -3940,24 +3931,7 @@
<string name="power_discharge_remaining"><xliff:g id="remain">%1$s</xliff:g> remaining</string>
<!-- Display time remaining until battery is charged [CHAR_LIMIT=60] -->
<string name="power_charge_remaining"><xliff:g id="until_charged">%1$s</xliff:g> to charge</string>
- <!-- [CHAR_LIMIT=40] Label for battery level chart when discharging with duration -->
- <string name="power_discharging_duration"><xliff:g id="level">%1$s</xliff:g>
- - approx. <xliff:g id="time">%2$s</xliff:g> left</string>
- <!-- [CHAR_LIMIT=40] Label for battery level chart when charging -->
- <string name="power_charging"><xliff:g id="level">%1$s</xliff:g> -
- <xliff:g id="state">%2$s</xliff:g></string>
- <!-- [CHAR_LIMIT=40] Label for battery level chart when charging with duration -->
- <string name="power_charging_duration"><xliff:g id="level">%1$s</xliff:g> -
- <xliff:g id="time">%2$s</xliff:g> until full</string>
- <!-- [CHAR_LIMIT=40] Label for battery level chart when charging with duration -->
- <string name="power_charging_duration_ac"><xliff:g id="level">%1$s</xliff:g> -
- <xliff:g id="time">%2$s</xliff:g> until full on AC</string>
- <!-- [CHAR_LIMIT=40] Label for battery level chart when charging with duration -->
- <string name="power_charging_duration_usb"><xliff:g id="level">%1$s</xliff:g> -
- <xliff:g id="time">%2$s</xliff:g> until full over USB</string>
- <!-- [CHAR_LIMIT=40] Label for battery level chart when charging with duration -->
- <string name="power_charging_duration_wireless"><xliff:g id="level">%1$s</xliff:g> -
- <xliff:g id="time">%2$s</xliff:g> until full from wireless</string>
+
<!-- [CHAR_LIMIT=40] Label for list of apps using battery in power use UI -->
<string name="power_usage_list_summary">Use since last full charge</string>
<!-- Battery usage since unplugged -->
diff --git a/res/xml/accessibility_settings.xml b/res/xml/accessibility_settings.xml
index 591bdad..42537b0 100644
--- a/res/xml/accessibility_settings.xml
+++ b/res/xml/accessibility_settings.xml
@@ -44,6 +44,11 @@
android:title="@string/accessibility_screen_magnification_title"/>
<PreferenceScreen
+ android:fragment="com.android.settings.accessibility.ToggleFontSizePreferenceFragment"
+ android:key="font_size_preference_screen"
+ android:title="@string/title_font_size"/>
+
+ <PreferenceScreen
android:fragment="com.android.settings.accessibility.ToggleAutoclickPreferenceFragment"
android:key="autoclick_preference_screen"
android:title="@string/accessibility_autoclick_preference_title"/>
diff --git a/res/xml/accessibility_settings_for_setup_wizard.xml b/res/xml/accessibility_settings_for_setup_wizard.xml
index 742b897..f35d708 100644
--- a/res/xml/accessibility_settings_for_setup_wizard.xml
+++ b/res/xml/accessibility_settings_for_setup_wizard.xml
@@ -30,7 +30,7 @@
android:layout="@layout/preference_button"
android:title="@string/title_font_size" />
- <com.android.settings.DisplayDensityPreference
+ <com.android.settings.display.ScreenZoomPreference
android:key="force_density_preference"
android:layout="@layout/preference_button"
settings:keywords="@string/screen_zoom_keywords"
diff --git a/res/xml/configure_notification_settings.xml b/res/xml/configure_notification_settings.xml
index d64132a..f9980dd 100644
--- a/res/xml/configure_notification_settings.xml
+++ b/res/xml/configure_notification_settings.xml
@@ -26,7 +26,7 @@
android:persistent="false" />
<!-- When device is locked -->
- <DropDownPreference
+ <com.android.settings.RestrictedDropDownPreference
android:key="lock_screen_notifications"
android:title="@string/lock_screen_notifications_title"
android:summary="%s"
diff --git a/src/com/android/settings/InstrumentedFragment.java b/src/com/android/settings/InstrumentedFragment.java
index cc0014d..2d39961 100644
--- a/src/com/android/settings/InstrumentedFragment.java
+++ b/src/com/android/settings/InstrumentedFragment.java
@@ -33,6 +33,7 @@
public static final int CONFIGURE_NOTIFICATION = UNDECLARED + 3;
public static final int CONFIGURE_WIFI = UNDECLARED + 4;
public static final int DISPLAY_SCREEN_ZOOM = UNDECLARED + 5;
+ public static final int ACCESSIBILITY_FONT_SIZE = UNDECLARED + 6;
/**
* Declare the view of this category.
diff --git a/src/com/android/settings/PreviewSeekBarPreferenceFragment.java b/src/com/android/settings/PreviewSeekBarPreferenceFragment.java
new file mode 100644
index 0000000..7a9efd3
--- /dev/null
+++ b/src/com/android/settings/PreviewSeekBarPreferenceFragment.java
@@ -0,0 +1,222 @@
+/*
+ * Copyright (C) 2015 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;
+
+import android.annotation.Nullable;
+import android.content.Context;
+import android.content.res.Configuration;
+import android.os.Bundle;
+import android.util.AttributeSet;
+import android.view.LayoutInflater;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.view.ViewGroup;
+import android.view.animation.AccelerateInterpolator;
+import android.view.animation.DecelerateInterpolator;
+import android.view.animation.Interpolator;
+import android.widget.FrameLayout;
+import android.widget.SeekBar;
+import android.widget.SeekBar.OnSeekBarChangeListener;
+import android.widget.TextView;
+
+
+/**
+ * Preference fragment shows a preview and a seek bar to adjust a specific settings.
+ */
+public abstract class PreviewSeekBarPreferenceFragment extends SettingsPreferenceFragment {
+
+ /** List of entries corresponding the settings being set. */
+ protected String[] mEntries;
+
+ /** Index of the entry corresponding to initial value of the settings. */
+ protected int mInitialIndex;
+
+ /** Index of the entry corresponding to current value of the settings. */
+ protected int mCurrentIndex;
+
+ /** Resource id of the layout for this preference fragment. */
+ protected int mActivityLayoutResId;
+
+ /** Resource id of the layout that defines the contents instide preview screen. */
+ protected int mPreviewSampleResId;
+
+ /** Duration to use when cross-fading between previews. */
+ private static final long CROSS_FADE_DURATION_MS = 400;
+
+ /** Interpolator to use when cross-fading between previews. */
+ private static final Interpolator FADE_IN_INTERPOLATOR = new DecelerateInterpolator();
+
+ /** Interpolator to use when cross-fading between previews. */
+ private static final Interpolator FADE_OUT_INTERPOLATOR = new AccelerateInterpolator();
+
+ private ViewGroup mPreviewFrame;
+ private TextView mLabel;
+ private View mLarger;
+ private View mSmaller;
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState) {
+ final View root = super.onCreateView(inflater, container, savedInstanceState);
+ final ViewGroup listContainer = (ViewGroup) root.findViewById(android.R.id.list_container);
+ listContainer.removeAllViews();
+
+ final View content = inflater.inflate(mActivityLayoutResId, listContainer, false);
+ listContainer.addView(content);
+
+ mLabel = (TextView) content.findViewById(R.id.current_label);
+
+ // The maximum SeekBar value always needs to be non-zero. If there's
+ // only one available value, we'll handle this by disabling the
+ // seek bar.
+ final int max = Math.max(1, mEntries.length - 1);
+
+ final SeekBar seekBar = (SeekBar) content.findViewById(R.id.seek_bar);
+ seekBar.setMax(max);
+ seekBar.setProgress(mInitialIndex);
+ seekBar.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {
+ @Override
+ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
+ setPreviewLayer(progress, true);
+ }
+
+ @Override
+ public void onStartTrackingTouch(SeekBar seekBar) {}
+
+ @Override
+ public void onStopTrackingTouch(SeekBar seekBar) {}
+ });
+
+ mSmaller = content.findViewById(R.id.smaller);
+ mSmaller.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ final int progress = seekBar.getProgress();
+ if (progress > 0) {
+ seekBar.setProgress(progress - 1, true);
+ }
+ }
+ });
+
+ mLarger = content.findViewById(R.id.larger);
+ mLarger.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ final int progress = seekBar.getProgress();
+ if (progress < seekBar.getMax()) {
+ seekBar.setProgress(progress + 1, true);
+ }
+ }
+ });
+
+ if (mEntries.length == 1) {
+ // The larger and smaller buttons will be disabled when we call
+ // setPreviewLayer() later in this method.
+ seekBar.setEnabled(false);
+ }
+
+ mPreviewFrame = (FrameLayout) content.findViewById(R.id.preview_frame);
+
+ // Populate the sample layouts.
+ final Context context = getContext();
+ final Configuration origConfig = context.getResources().getConfiguration();
+ for (int i = 0; i < mEntries.length; ++i) {
+ final Configuration config = createConfig(origConfig, i);
+
+ // Create a new configuration for the specified value. It won't
+ // have any theme set, so manually apply the current theme.
+ final Context configContext = context.createConfigurationContext(config);
+ configContext.setTheme(context.getThemeResId());
+
+ final LayoutInflater configInflater = LayoutInflater.from(configContext);
+ final View sampleView = configInflater.inflate(mPreviewSampleResId, mPreviewFrame, false);
+ sampleView.setAlpha(0);
+ sampleView.setVisibility(View.INVISIBLE);
+
+ mPreviewFrame.addView(sampleView);
+ }
+
+ setPreviewLayer(mInitialIndex, false);
+
+ return root;
+ }
+
+ @Override
+ public void onDetach() {
+ super.onDetach();
+
+ // This will commit the change SLIGHTLY after the activity has
+ // finished, which could be considered a feature or a bug...
+ commit();
+ }
+
+ /**
+ * Creates new configuration based on the current position of the SeekBar.
+ */
+ protected abstract Configuration createConfig(Configuration origConfig, int index);
+
+ private void setPreviewLayer(int index, boolean animate) {
+ mLabel.setText(mEntries[index]);
+
+ if (mCurrentIndex >= 0) {
+ final View lastLayer = mPreviewFrame.getChildAt(mCurrentIndex);
+ if (animate) {
+ lastLayer.animate()
+ .alpha(0)
+ .setInterpolator(FADE_OUT_INTERPOLATOR)
+ .setDuration(CROSS_FADE_DURATION_MS)
+ .withEndAction(new Runnable() {
+ @Override
+ public void run() {
+ lastLayer.setVisibility(View.INVISIBLE);
+ }
+ });
+ } else {
+ lastLayer.setAlpha(0);
+ lastLayer.setVisibility(View.INVISIBLE);
+ }
+ }
+
+ final View nextLayer = mPreviewFrame.getChildAt(index);
+ if (animate) {
+ nextLayer.animate()
+ .alpha(1)
+ .setInterpolator(FADE_IN_INTERPOLATOR)
+ .setDuration(CROSS_FADE_DURATION_MS)
+ .withStartAction(new Runnable() {
+ @Override
+ public void run() {
+ nextLayer.setVisibility(View.VISIBLE);
+ }
+ });
+ } else {
+ nextLayer.setVisibility(View.VISIBLE);
+ nextLayer.setAlpha(1);
+ }
+
+ mSmaller.setEnabled(index > 0);
+ mLarger.setEnabled(index < mEntries.length - 1);
+
+ mCurrentIndex = index;
+ }
+
+ /**
+ * Persists the selected value and sends a configuration change.
+ */
+ protected abstract void commit();
+}
diff --git a/src/com/android/settings/RestrictedDropDownPreference.java b/src/com/android/settings/RestrictedDropDownPreference.java
new file mode 100644
index 0000000..bed45fc
--- /dev/null
+++ b/src/com/android/settings/RestrictedDropDownPreference.java
@@ -0,0 +1,155 @@
+/*
+ * Copyright (C) 2016 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;
+
+import android.content.Context;
+import android.graphics.drawable.Drawable;
+import android.support.v7.preference.DropDownPreference;
+import android.support.v7.preference.PreferenceViewHolder;
+import android.util.AttributeSet;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.AdapterView;
+import android.widget.AdapterView.OnItemSelectedListener;
+import android.widget.ArrayAdapter;
+import android.widget.Spinner;
+import android.widget.TextView;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import com.android.settings.RestrictedLockUtils;
+
+import static com.android.settings.RestrictedLockUtils.EnforcedAdmin;
+
+public class RestrictedDropDownPreference extends DropDownPreference {
+ private Spinner mSpinner;
+ private final Drawable mRestrictedPadlock;
+ private final int mRestrictedPadlockPadding;
+ private List<RestrictedItem> mRestrictedItems = new ArrayList<>();
+
+ public RestrictedDropDownPreference(Context context) {
+ this(context, null);
+ }
+
+ public RestrictedDropDownPreference(Context context, AttributeSet attrs) {
+ super(context, attrs);
+
+ mRestrictedPadlock = RestrictedLockUtils.getRestrictedPadlock(context);
+ mRestrictedPadlockPadding = context.getResources().getDimensionPixelSize(
+ R.dimen.restricted_lock_icon_padding);
+ }
+
+ private final OnItemSelectedListener mItemSelectedListener = new OnItemSelectedListener() {
+ @Override
+ public void onItemSelected(AdapterView<?> parent, View v, int position, long id) {
+ if (position >= 0) {
+ String value = getEntryValues()[position].toString();
+ RestrictedItem item = getRestrictedItemForEntryValue(value);
+ if (item != null) {
+ RestrictedLockUtils.sendShowAdminSupportDetailsIntent(getContext(),
+ item.enforcedAdmin);
+ mSpinner.setSelection(findIndexOfValue(getValue()));
+ } else if (!value.equals(getValue()) && callChangeListener(value)) {
+ setValue(value);
+ }
+ }
+ }
+
+ @Override
+ public void onNothingSelected(AdapterView<?> parent) {
+ // noop
+ }
+ };
+
+ @Override
+ protected ArrayAdapter createAdapter() {
+ return new RestrictedArrayItemAdapter(getContext());
+ }
+
+ @Override
+ public void setValue(String value) {
+ if (getRestrictedItemForEntryValue(value) != null) {
+ return;
+ }
+ super.setValue(value);
+ }
+
+ @Override
+ public void onBindViewHolder(PreferenceViewHolder view) {
+ super.onBindViewHolder(view);
+ mSpinner = (Spinner) view.itemView.findViewById(R.id.spinner);
+ mSpinner.setOnItemSelectedListener(mItemSelectedListener);
+ }
+
+ private class RestrictedArrayItemAdapter extends ArrayAdapter<String> {
+ public RestrictedArrayItemAdapter(Context context) {
+ super(context, R.layout.spinner_dropdown_restricted_item);
+ }
+
+ @Override
+ public View getDropDownView(int position, View convertView, ViewGroup parent) {
+ TextView view = (TextView) super.getView(position, convertView, parent);
+ CharSequence entry = getItem(position);
+ boolean isEntryRestricted = isRestrictedForEntry(entry);
+ RestrictedLockUtils.setTextViewPadlock(getContext(), view, isEntryRestricted);
+ view.setEnabled(!isEntryRestricted);
+ return view;
+ }
+ }
+
+ private boolean isRestrictedForEntry(CharSequence entry) {
+ if (entry == null) {
+ return false;
+ }
+ for (RestrictedItem item : mRestrictedItems) {
+ if (entry.equals(item.entry)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private RestrictedItem getRestrictedItemForEntryValue(CharSequence entryValue) {
+ if (entryValue == null) {
+ return null;
+ }
+ for (RestrictedItem item : mRestrictedItems) {
+ if (entryValue.equals(item.entryValue)) {
+ return item;
+ }
+ }
+ return null;
+ }
+
+ public void addRestrictedItem(RestrictedItem item) {
+ mRestrictedItems.add(item);
+ }
+
+ public static class RestrictedItem {
+ public CharSequence entry;
+ public CharSequence entryValue;
+ public EnforcedAdmin enforcedAdmin;
+
+ public RestrictedItem(CharSequence entry, CharSequence entryValue,
+ EnforcedAdmin enforcedAdmin) {
+ this.entry = entry;
+ this.entryValue = entryValue;
+ this.enforcedAdmin = enforcedAdmin;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/com/android/settings/RestrictedLockImageSpan.java b/src/com/android/settings/RestrictedLockImageSpan.java
new file mode 100644
index 0000000..66c60cb
--- /dev/null
+++ b/src/com/android/settings/RestrictedLockImageSpan.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2016 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;
+
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.drawable.Drawable;
+import android.text.style.ImageSpan;
+
+import java.lang.ref.WeakReference;
+
+/**
+ * An extension of ImageSpan which adds a padding before the image.
+ */
+public class RestrictedLockImageSpan extends ImageSpan {
+ private Context mContext;
+ private final float mExtraPadding;
+ private final Drawable mRestrictedPadlock;
+
+ public RestrictedLockImageSpan(Context context) {
+ // we are overriding getDrawable, so passing null to super class here.
+ super((Drawable) null);
+
+ mContext = context;
+ mExtraPadding = mContext.getResources().getDimensionPixelSize(
+ R.dimen.restricted_lock_icon_padding);
+ mRestrictedPadlock = RestrictedLockUtils.getRestrictedPadlock(mContext);
+ }
+
+ @Override
+ public Drawable getDrawable() {
+ return mRestrictedPadlock;
+ }
+
+ @Override
+ public void draw(Canvas canvas, CharSequence text, int start, int end, float x, int top, int y,
+ int bottom, Paint paint) {
+ Drawable drawable = getDrawable();
+ canvas.save();
+
+ // Add extra padding before the padlock.
+ float transX = x + mExtraPadding;
+ float transY = bottom - drawable.getBounds().bottom - paint.getFontMetricsInt().descent;
+
+ canvas.translate(transX, transY);
+ drawable.draw(canvas);
+ canvas.restore();
+ }
+
+ @Override
+ public int getSize(Paint paint, CharSequence text, int start, int end,
+ Paint.FontMetricsInt fontMetrics) {
+ int size = super.getSize(paint, text, start, end, fontMetrics);
+ size += 2 * mExtraPadding;
+ return size;
+ }
+}
\ No newline at end of file
diff --git a/src/com/android/settings/RestrictedLockUtils.java b/src/com/android/settings/RestrictedLockUtils.java
new file mode 100644
index 0000000..1a38763
--- /dev/null
+++ b/src/com/android/settings/RestrictedLockUtils.java
@@ -0,0 +1,228 @@
+/*
+ * Copyright (C) 2016 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;
+
+import android.app.admin.DevicePolicyManager;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.graphics.Color;
+import android.graphics.drawable.Drawable;
+import android.os.Bundle;
+import android.os.UserHandle;
+import android.text.Spanned;
+import android.text.SpannableStringBuilder;
+import android.text.style.ForegroundColorSpan;
+import android.text.style.ImageSpan;
+import android.view.MenuItem;
+import android.widget.TextView;
+
+import java.util.List;
+
+/**
+ * Utility class to host methods usable in adding a restricted padlock icon and showing admin
+ * support message dialog.
+ */
+public class RestrictedLockUtils {
+ /**
+ * @return drawables for displaying with settings that are locked by a device admin.
+ */
+ public static Drawable getRestrictedPadlock(Context context) {
+ Drawable restrictedPadlock = context.getDrawable(R.drawable.ic_settings_lock_outline);
+ final int iconSize = context.getResources().getDimensionPixelSize(
+ R.dimen.restricted_lock_icon_size);
+ restrictedPadlock.setBounds(0, 0, iconSize, iconSize);
+ return restrictedPadlock;
+ }
+
+ /**
+ * Checks if a restriction is enforced on a user and returns the enforced admin and
+ * admin userId.
+ *
+ * @param userRestriction Restriction to check
+ * @param userId User which we need to check if restriction is enforced on.
+ * @return EnforcedAdmin Object containing the enforce admin and admin user details, or
+ * {@code null} If the restriction is not set. If the restriction is set by both device owner
+ * and profile owner, then the admin will be set to {@code null} and userId to
+ * {@link UserHandle#USER_NULL}.
+ */
+ public static EnforcedAdmin checkIfRestrictionEnforced(Context context,
+ String userRestriction, int userId) {
+ DevicePolicyManager dpm = (DevicePolicyManager) context.getSystemService(
+ Context.DEVICE_POLICY_SERVICE);
+ ComponentName deviceOwner = dpm.getDeviceOwnerComponentOnAnyUser();
+ int deviceOwnerUserId = dpm.getDeviceOwnerUserId();
+ boolean enforcedByDeviceOwner = false;
+ if (deviceOwner != null && deviceOwnerUserId != UserHandle.USER_NULL) {
+ Bundle enforcedRestrictions = dpm.getUserRestrictions(deviceOwner, deviceOwnerUserId);
+ if (enforcedRestrictions != null
+ && enforcedRestrictions.getBoolean(userRestriction, false)) {
+ enforcedByDeviceOwner = true;
+ }
+ }
+
+ ComponentName profileOwner = null;
+ boolean enforcedByProfileOwner = false;
+ if (userId != UserHandle.USER_NULL) {
+ profileOwner = dpm.getProfileOwnerAsUser(userId);
+ if (profileOwner != null) {
+ Bundle enforcedRestrictions = dpm.getUserRestrictions(profileOwner, userId);
+ if (enforcedRestrictions != null
+ && enforcedRestrictions.getBoolean(userRestriction, false)) {
+ enforcedByProfileOwner = true;
+ }
+ }
+ }
+
+ if (!enforcedByDeviceOwner && !enforcedByProfileOwner) {
+ return null;
+ }
+
+ EnforcedAdmin admin = null;
+ if (enforcedByDeviceOwner && enforcedByProfileOwner) {
+ admin = new EnforcedAdmin();
+ } else if (enforcedByDeviceOwner) {
+ admin = new EnforcedAdmin(deviceOwner, deviceOwnerUserId);
+ } else {
+ admin = new EnforcedAdmin(profileOwner, userId);
+ }
+ return admin;
+ }
+
+ /**
+ * Checks if lock screen notification features are disabled by policy. This should be
+ * only used for keyguard notification features but not the keyguard features
+ * (e.g. KEYGUARD_DISABLE_FINGERPRINT) where a profile owner can set them on the parent user
+ * as it won't work for that case.
+ *
+ * @param keyguardNotificationFeatures Could be any of notification features that can be
+ * disabled by {@link android.app.admin.DevicePolicyManager#setKeyguardDisabledFeatures}.
+ * @return EnforcedAdmin Object containing the enforce admin and admin user details, or
+ * {@code null} If the notification features are not disabled. If the restriction is set by
+ * multiple admins, then the admin will be set to {@code null} and userId to
+ * {@link UserHandle#USER_NULL}.
+ */
+ public static EnforcedAdmin checkIfKeyguardNotificationFeaturesDisabled(Context context,
+ int keyguardNotificationFeatures) {
+ final DevicePolicyManager dpm = (DevicePolicyManager) context.getSystemService(
+ Context.DEVICE_POLICY_SERVICE);
+ boolean isDisabledByMultipleAdmins = false;
+ ComponentName adminComponent = null;
+ List<ComponentName> admins = dpm.getActiveAdmins();
+ int disabledKeyguardFeatures;
+ for (ComponentName admin : admins) {
+ disabledKeyguardFeatures = dpm.getKeyguardDisabledFeatures(admin);
+ if ((disabledKeyguardFeatures & keyguardNotificationFeatures) != 0) {
+ if (adminComponent == null) {
+ adminComponent = admin;
+ } else {
+ isDisabledByMultipleAdmins = true;
+ break;
+ }
+ }
+ }
+ EnforcedAdmin enforcedAdmin = null;
+ if (adminComponent != null) {
+ if (!isDisabledByMultipleAdmins) {
+ enforcedAdmin = new EnforcedAdmin(adminComponent, UserHandle.myUserId());
+ } else {
+ enforcedAdmin = new EnforcedAdmin();
+ }
+ }
+ return enforcedAdmin;
+ }
+
+ /**
+ * Set the menu item as disabled by admin by adding a restricted padlock at the end of the
+ * text and set the click listener which will send an intent to show the admin support details
+ * dialog.
+ */
+ public static void setMenuItemAsDisabledByAdmin(final Context context,
+ final MenuItem item, final EnforcedAdmin admin) {
+ SpannableStringBuilder sb = new SpannableStringBuilder(item.getTitle());
+ removeExistingRestrictedSpans(sb);
+
+ final int disabledColor = context.getColor(R.color.disabled_text_color);
+ sb.setSpan(new ForegroundColorSpan(disabledColor), 0, sb.length(),
+ Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+ ImageSpan image = new RestrictedLockImageSpan(context);
+ sb.append(" ", image, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+ item.setTitle(sb);
+
+ item.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
+ @Override
+ public boolean onMenuItemClick(MenuItem item) {
+ sendShowAdminSupportDetailsIntent(context, admin);
+ return true;
+ }
+ });
+ }
+
+ private static void removeExistingRestrictedSpans(SpannableStringBuilder sb) {
+ final int length = sb.length();
+ RestrictedLockImageSpan[] imageSpans = sb.getSpans(length - 1, length,
+ RestrictedLockImageSpan.class);
+ for (ImageSpan span : imageSpans) {
+ sb.removeSpan(span);
+ }
+ ForegroundColorSpan[] colorSpans = sb.getSpans(0, length, ForegroundColorSpan.class);
+ for (ForegroundColorSpan span : colorSpans) {
+ sb.removeSpan(span);
+ }
+ }
+
+ /**
+ * Send the intent to trigger the {@link android.settings.ShowAdminSupportDetailsDialog}.
+ */
+ public static void sendShowAdminSupportDetailsIntent(Context context, EnforcedAdmin admin) {
+ Intent intent = new Intent(context, ShowAdminSupportDetailsDialog.class);
+ int adminUserId = UserHandle.myUserId();
+ if (admin != null) {
+ if (admin.component != null) {
+ intent.putExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN, admin.component);
+ }
+ if (admin.userId != UserHandle.USER_NULL) {
+ adminUserId = admin.userId;
+ }
+ intent.putExtra(Intent.EXTRA_USER_ID, adminUserId);
+ }
+ context.startActivityAsUser(intent, new UserHandle(adminUserId));
+ }
+
+ public static void setTextViewPadlock(Context context,
+ TextView textView, boolean showPadlock) {
+ final SpannableStringBuilder sb = new SpannableStringBuilder(textView.getText());
+ removeExistingRestrictedSpans(sb);
+ if (showPadlock) {
+ final ImageSpan image = new RestrictedLockImageSpan(context);
+ sb.append(" ", image, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+ }
+ textView.setText(sb);
+ }
+
+ public static class EnforcedAdmin {
+ public ComponentName component = null;
+ public int userId = UserHandle.USER_NULL;
+
+ public EnforcedAdmin(ComponentName component, int userId) {
+ this.component = component;
+ this.userId = userId;
+ }
+
+ public EnforcedAdmin() {}
+ }
+}
\ No newline at end of file
diff --git a/src/com/android/settings/RestrictedPreference.java b/src/com/android/settings/RestrictedPreference.java
index 7903f93..5ac52cb 100644
--- a/src/com/android/settings/RestrictedPreference.java
+++ b/src/com/android/settings/RestrictedPreference.java
@@ -16,7 +16,6 @@
package com.android.settings;
-import android.content.ComponentName;
import android.content.Context;
import android.os.UserHandle;
import android.support.v4.content.res.TypedArrayUtils;
@@ -25,6 +24,8 @@
import android.support.v7.preference.PreferenceViewHolder;
import android.util.AttributeSet;
+import static com.android.settings.RestrictedLockUtils.EnforcedAdmin;
+
/**
* Preference class that supports being disabled by a user restriction
* set by a device admin.
@@ -78,12 +79,8 @@
mHelper.checkRestrictionAndSetDisabled(userRestriction, userId);
}
- public void setDisabledByAdmin(boolean disabled) {
- mHelper.setDisabledByAdmin(disabled, null, UserHandle.USER_NULL);
- }
-
- public void setDisabledByAdmin(boolean disabled, ComponentName admin, int userId) {
- if (mHelper.setDisabledByAdmin(disabled, admin, userId)) {
+ public void setDisabledByAdmin(EnforcedAdmin admin) {
+ if (mHelper.setDisabledByAdmin(admin)) {
notifyChanged();
}
}
diff --git a/src/com/android/settings/RestrictedPreferenceHelper.java b/src/com/android/settings/RestrictedPreferenceHelper.java
index 385a8a2..f0c0bf7 100644
--- a/src/com/android/settings/RestrictedPreferenceHelper.java
+++ b/src/com/android/settings/RestrictedPreferenceHelper.java
@@ -16,36 +16,33 @@
package com.android.settings;
-import android.app.admin.DevicePolicyManager;
-import android.content.ComponentName;
import android.content.Context;
-import android.content.Intent;
import android.content.res.TypedArray;
import android.graphics.drawable.Drawable;
-import android.os.Bundle;
import android.os.UserHandle;
import android.support.v7.preference.Preference;
import android.support.v7.preference.PreferenceViewHolder;
+import android.text.Spanned;
+import android.text.SpannableStringBuilder;
+import android.text.style.ImageSpan;
import android.util.AttributeSet;
import android.util.TypedValue;
-import android.view.View;
import android.widget.TextView;
+import static com.android.settings.RestrictedLockUtils.EnforcedAdmin;
+
/**
* Helper class for managing settings preferences that can be disabled
* by device admins via user restrictions.
- *
- **/
+ */
public class RestrictedPreferenceHelper {
private final Context mContext;
private final Preference mPreference;
private final Drawable mRestrictedPadlock;
private final int mRestrictedPadlockPadding;
- private final DevicePolicyManager mDevicePolicyManager;
private boolean mDisabledByAdmin;
- private ComponentName mEnforcedAdmin;
- private int mUserId = UserHandle.USER_NULL;
+ private EnforcedAdmin mEnforcedAdmin;
private String mAttrUserRestriction = null;
RestrictedPreferenceHelper(Context context, Preference preference,
@@ -53,13 +50,10 @@
mContext = context;
mPreference = preference;
- mRestrictedPadlock = getRestrictedPadlock(mContext);
+ mRestrictedPadlock = RestrictedLockUtils.getRestrictedPadlock(mContext);
mRestrictedPadlockPadding = mContext.getResources().getDimensionPixelSize(
R.dimen.restricted_lock_icon_padding);
- mDevicePolicyManager = (DevicePolicyManager) mContext.getSystemService(
- Context.DEVICE_POLICY_SERVICE);
-
mAttrUserRestriction = attrs.getAttributeValue(
R.styleable.RestrictedPreference_userRestriction);
final TypedArray attributes = context.obtainStyledAttributes(attrs,
@@ -83,12 +77,9 @@
public void onBindViewHolder(PreferenceViewHolder holder) {
final TextView titleView = (TextView) holder.findViewById(android.R.id.title);
if (titleView != null) {
+ RestrictedLockUtils.setTextViewPadlock(mContext, titleView, mDisabledByAdmin);
if (mDisabledByAdmin) {
- titleView.setCompoundDrawablesRelative(null, null, mRestrictedPadlock, null);
- titleView.setCompoundDrawablePadding(mRestrictedPadlockPadding);
holder.itemView.setEnabled(true);
- } else {
- titleView.setCompoundDrawablesRelative(null, null, null, null);
}
}
}
@@ -100,14 +91,7 @@
*/
public boolean performClick() {
if (mDisabledByAdmin) {
- Intent intent = new Intent(mContext, ShowAdminSupportDetailsDialog.class);
- if (mEnforcedAdmin != null) {
- intent.putExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN, mEnforcedAdmin);
- }
- if (mUserId != UserHandle.USER_NULL) {
- intent.putExtra(Intent.EXTRA_USER_ID, mUserId);
- }
- mContext.startActivity(intent);
+ RestrictedLockUtils.sendShowAdminSupportDetailsIntent(mContext, mEnforcedAdmin);
return true;
}
return false;
@@ -129,57 +113,23 @@
* @param userId user to check the restriction for.
*/
public void checkRestrictionAndSetDisabled(String userRestriction, int userId) {
- ComponentName deviceOwner = mDevicePolicyManager.getDeviceOwnerComponentOnAnyUser();
- int deviceOwnerUserId = mDevicePolicyManager.getDeviceOwnerUserId();
- boolean enforcedByDeviceOwner = false;
- if (deviceOwner != null && deviceOwnerUserId != UserHandle.USER_NULL) {
- enforcedByDeviceOwner = isEnforcedByAdmin(
- deviceOwner, userRestriction, deviceOwnerUserId);
- }
-
- ComponentName profileOwner = mDevicePolicyManager.getProfileOwnerAsUser(userId);
- boolean enforcedByProfileOwner = false;
- if (profileOwner != null && userId != UserHandle.USER_NULL) {
- enforcedByProfileOwner = isEnforcedByAdmin(
- profileOwner, userRestriction, userId);
- }
-
- if (!enforcedByDeviceOwner && !enforcedByProfileOwner) {
- setDisabledByAdmin(false, null, UserHandle.USER_NULL);
- return;
- }
-
- if (enforcedByDeviceOwner && enforcedByProfileOwner) {
- setDisabledByAdmin(true, null, UserHandle.USER_NULL);
- } else if (enforcedByDeviceOwner) {
- setDisabledByAdmin(true, deviceOwner, deviceOwnerUserId);
- } else {
- setDisabledByAdmin(true, profileOwner, userId);
- }
- }
-
- private boolean isEnforcedByAdmin(ComponentName admin, String userRestriction, int userId) {
- Bundle enforcedRestrictions = mDevicePolicyManager.getUserRestrictions(admin, userId);
- if (enforcedRestrictions != null
- && enforcedRestrictions.getBoolean(userRestriction, false)) {
- return true;
- }
- return false;
+ EnforcedAdmin admin = RestrictedLockUtils.checkIfRestrictionEnforced(mContext,
+ userRestriction, userId);
+ setDisabledByAdmin(admin);
}
/**
- * Disable this preference.
+ * Disable this preference based on the enforce admin.
*
- * @param disabled true if preference should be disabled.
- * @param admin Device admin that disabled the preference.
- * @param userId userId the device admin is installed for.
+ * @param EnforcedAdmin Details of the admin who enforced the restriction. If it
+ * is {@code null}, then this preference will be enabled. Otherwise, it will be disabled.
* @return true if the disabled state was changed.
*/
- public boolean setDisabledByAdmin(boolean disabled, ComponentName admin, int userId) {
+ public boolean setDisabledByAdmin(EnforcedAdmin admin) {
+ final boolean disabled = (admin != null ? true : false);
+ mEnforcedAdmin = (disabled ? admin : null);
if (mDisabledByAdmin != disabled) {
mDisabledByAdmin = disabled;
- mEnforcedAdmin = admin;
- mUserId = userId;
mPreference.setEnabled(!disabled);
return true;
}
@@ -189,15 +139,4 @@
public boolean isDisabledByAdmin() {
return mDisabledByAdmin;
}
-
- /**
- * @return drawables for displaying with settings that are locked by a device admin.
- */
- public static Drawable getRestrictedPadlock(Context context) {
- Drawable restrictedPadlock = context.getDrawable(R.drawable.ic_settings_lock_outline);
- final int iconSize = context.getResources().getDimensionPixelSize(
- R.dimen.restricted_lock_icon_size);
- restrictedPadlock.setBounds(0, 0, iconSize, iconSize);
- return restrictedPadlock;
- }
}
diff --git a/src/com/android/settings/RestrictedSwitchPreference.java b/src/com/android/settings/RestrictedSwitchPreference.java
index 526bd42..f0c3315 100644
--- a/src/com/android/settings/RestrictedSwitchPreference.java
+++ b/src/com/android/settings/RestrictedSwitchPreference.java
@@ -16,7 +16,6 @@
package com.android.settings;
-import android.content.ComponentName;
import android.content.Context;
import android.os.UserHandle;
import android.support.v4.content.res.TypedArrayUtils;
@@ -25,6 +24,8 @@
import android.support.v14.preference.SwitchPreference;
import android.util.AttributeSet;
+import static com.android.settings.RestrictedLockUtils.EnforcedAdmin;
+
/**
* Version of SwitchPreference that can be disabled by a device admin
* using a user restriction.
@@ -78,12 +79,8 @@
mHelper.checkRestrictionAndSetDisabled(userRestriction, userId);
}
- public void setDisabledByAdmin(boolean disabled) {
- mHelper.setDisabledByAdmin(disabled, null, UserHandle.USER_NULL);
- }
-
- public void setDisabledByAdmin(boolean disabled, ComponentName admin, int userId) {
- if (mHelper.setDisabledByAdmin(disabled, admin, userId)) {
+ public void setDisabledByAdmin(EnforcedAdmin admin) {
+ if (mHelper.setDisabledByAdmin(admin)) {
notifyChanged();
}
}
diff --git a/src/com/android/settings/display/TouchBlockingFrameLayout.java b/src/com/android/settings/TouchBlockingFrameLayout.java
similarity index 96%
rename from src/com/android/settings/display/TouchBlockingFrameLayout.java
rename to src/com/android/settings/TouchBlockingFrameLayout.java
index 3f5483d..8b36635 100644
--- a/src/com/android/settings/display/TouchBlockingFrameLayout.java
+++ b/src/com/android/settings/TouchBlockingFrameLayout.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.settings.display;
+package com.android.settings;
import android.annotation.Nullable;
import android.content.Context;
diff --git a/src/com/android/settings/Utils.java b/src/com/android/settings/Utils.java
index 9aa0403..709277b 100644
--- a/src/com/android/settings/Utils.java
+++ b/src/com/android/settings/Utils.java
@@ -88,7 +88,6 @@
import java.io.IOException;
import java.io.InputStream;
import java.net.InetAddress;
-import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
@@ -96,7 +95,8 @@
import static android.content.Intent.EXTRA_USER;
-public final class Utils {
+public final class Utils extends com.android.settingslib.Utils {
+
private static final String TAG = "Settings";
/**
@@ -262,21 +262,6 @@
}
}
- /** Formats the ratio of amount/total as a percentage. */
- public static String formatPercentage(long amount, long total) {
- return formatPercentage(((double) amount) / total);
- }
-
- /** Formats an integer from 0..100 as a percentage. */
- public static String formatPercentage(int percentage) {
- return formatPercentage(((double) percentage) / 100.0);
- }
-
- /** Formats a double from 0.0..1.0 as a percentage. */
- private static String formatPercentage(double percentage) {
- return NumberFormat.getPercentInstance().format(percentage);
- }
-
public static boolean isBatteryPresent(Intent batteryChangedIntent) {
return batteryChangedIntent.getBooleanExtra(BatteryManager.EXTRA_PRESENT, true);
}
@@ -285,44 +270,6 @@
return formatPercentage(getBatteryLevel(batteryChangedIntent));
}
- public static int getBatteryLevel(Intent batteryChangedIntent) {
- int level = batteryChangedIntent.getIntExtra(BatteryManager.EXTRA_LEVEL, 0);
- int scale = batteryChangedIntent.getIntExtra(BatteryManager.EXTRA_SCALE, 100);
- return (level * 100) / scale;
- }
-
- public static String getBatteryStatus(Resources res, Intent batteryChangedIntent) {
- final Intent intent = batteryChangedIntent;
-
- int plugType = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, 0);
- int status = intent.getIntExtra(BatteryManager.EXTRA_STATUS,
- BatteryManager.BATTERY_STATUS_UNKNOWN);
- String statusString;
- if (status == BatteryManager.BATTERY_STATUS_CHARGING) {
- int resId;
- if (plugType == BatteryManager.BATTERY_PLUGGED_AC) {
- resId = R.string.battery_info_status_charging_ac;
- } else if (plugType == BatteryManager.BATTERY_PLUGGED_USB) {
- resId = R.string.battery_info_status_charging_usb;
- } else if (plugType == BatteryManager.BATTERY_PLUGGED_WIRELESS) {
- resId = R.string.battery_info_status_charging_wireless;
- } else {
- resId = R.string.battery_info_status_charging;
- }
- statusString = res.getString(resId);
- } else if (status == BatteryManager.BATTERY_STATUS_DISCHARGING) {
- statusString = res.getString(R.string.battery_info_status_discharging);
- } else if (status == BatteryManager.BATTERY_STATUS_NOT_CHARGING) {
- statusString = res.getString(R.string.battery_info_status_not_charging);
- } else if (status == BatteryManager.BATTERY_STATUS_FULL) {
- statusString = res.getString(R.string.battery_info_status_full);
- } else {
- statusString = res.getString(R.string.battery_info_status_unknown);
- }
-
- return statusString;
- }
-
public static void forcePrepareCustomPreferencesList(
ViewGroup parent, View child, ListView list, boolean ignoreSidePadding) {
list.setScrollBarStyle(View.SCROLLBARS_OUTSIDE_OVERLAY);
diff --git a/src/com/android/settings/accessibility/ToggleFontSizePreferenceFragment.java b/src/com/android/settings/accessibility/ToggleFontSizePreferenceFragment.java
new file mode 100644
index 0000000..8b9e27b
--- /dev/null
+++ b/src/com/android/settings/accessibility/ToggleFontSizePreferenceFragment.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2015 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.accessibility;
+
+import com.android.settings.InstrumentedFragment;
+import com.android.settings.R;
+import com.android.settings.PreviewSeekBarPreferenceFragment;
+
+import android.annotation.Nullable;
+import android.app.ActivityManagerNative;
+import android.content.res.Configuration;
+import android.content.res.Resources;
+import android.os.Bundle;
+import android.os.RemoteException;
+import android.util.Log;
+
+/**
+ * Preference fragment used to control font size.
+ */
+public class ToggleFontSizePreferenceFragment extends PreviewSeekBarPreferenceFragment {
+ private static final String LOG_TAG = "ToggleFontSizePreferenceFragment";
+
+ private float[] mValues;
+
+ @Override
+ public void onCreate(@Nullable Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ mActivityLayoutResId = R.layout.font_size_activity;
+ mPreviewSampleResId = R.layout.font_size_preview;
+
+ Resources res = getContext().getResources();
+ // Mark the appropriate item in the preferences list.
+ final Configuration origConfig = res.getConfiguration();
+ mEntries = res.getStringArray(R.array.entries_font_size);
+ final String[] strEntryValues = res.getStringArray(R.array.entryvalues_font_size);
+ mInitialIndex = floatToIndex(origConfig.fontScale, strEntryValues);
+ mValues = new float[strEntryValues.length];
+ for (int i = 0; i < strEntryValues.length; ++i) {
+ mValues[i] = Float.parseFloat(strEntryValues[i]);
+ }
+ }
+
+ @Override
+ protected Configuration createConfig(Configuration origConfig, int index) {
+ // Populate the sample layouts.
+ final Configuration config = new Configuration(origConfig);
+ config.fontScale = mValues[index];
+ return config;
+ }
+
+ /**
+ * Persists the selected font size and sends a configuration change.
+ */
+ @Override
+ protected void commit() {
+ Configuration config = getContext().getResources().getConfiguration();
+ config.fontScale = mValues[mCurrentIndex];
+ try {
+ ActivityManagerNative.getDefault().updatePersistentConfiguration(config);
+ } catch (RemoteException e) {
+ Log.w(LOG_TAG, "Unable to save font size setting");
+ }
+ }
+
+ @Override
+ protected int getMetricsCategory() {
+ return InstrumentedFragment.ACCESSIBILITY_FONT_SIZE;
+ }
+
+ private int floatToIndex(float val, String[] indices) {
+ float lastVal = Float.parseFloat(indices[0]);
+ for (int i=1; i<indices.length; i++) {
+ float thisVal = Float.parseFloat(indices[i]);
+ if (val < (lastVal + (thisVal-lastVal)*.5f)) {
+ return i-1;
+ }
+ lastVal = thisVal;
+ }
+ return indices.length-1;
+ }
+
+}
\ No newline at end of file
diff --git a/src/com/android/settings/accounts/AccountSyncSettings.java b/src/com/android/settings/accounts/AccountSyncSettings.java
index 0590cbd..a060c76 100644
--- a/src/com/android/settings/accounts/AccountSyncSettings.java
+++ b/src/com/android/settings/accounts/AccountSyncSettings.java
@@ -28,11 +28,13 @@
import android.content.ContentResolver;
import android.content.Context;
import android.content.DialogInterface;
+import android.content.Intent;
import android.content.SyncAdapterType;
import android.content.SyncInfo;
import android.content.SyncStatusInfo;
import android.content.pm.ProviderInfo;
import android.content.pm.UserInfo;
+import android.graphics.Color;
import android.os.Binder;
import android.os.Bundle;
import android.os.UserHandle;
@@ -52,6 +54,8 @@
import com.android.internal.logging.MetricsLogger;
import com.android.settings.R;
+import com.android.settings.RestrictedLockUtils;
+import com.android.settings.ShowAdminSupportDetailsDialog;
import com.android.settings.Utils;
import com.google.android.collect.Lists;
@@ -61,6 +65,8 @@
import java.util.Date;
import java.util.List;
+import static com.android.settings.RestrictedLockUtils.EnforcedAdmin;
+
public class AccountSyncSettings extends AccountPreferenceBase {
public static final String ACCOUNT_KEY = "account";
@@ -259,13 +265,17 @@
MenuItem syncCancel = menu.add(0, MENU_SYNC_CANCEL_ID, 0,
getString(R.string.sync_menu_sync_cancel))
.setIcon(com.android.internal.R.drawable.ic_menu_close_clear_cancel);
- final UserManager um = (UserManager) getSystemService(Context.USER_SERVICE);
- if (!um.hasUserRestriction(UserManager.DISALLOW_MODIFY_ACCOUNTS, mUserHandle)) {
- MenuItem removeAccount = menu.add(0, MENU_REMOVE_ACCOUNT_ID, 0,
- getString(R.string.remove_account_label))
- .setIcon(R.drawable.ic_menu_delete);
- removeAccount.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER |
- MenuItem.SHOW_AS_ACTION_WITH_TEXT);
+ MenuItem removeAccount = menu.add(0, MENU_REMOVE_ACCOUNT_ID, 0,
+ getString(R.string.remove_account_label))
+ .setIcon(R.drawable.ic_menu_delete);
+ removeAccount.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER |
+ MenuItem.SHOW_AS_ACTION_WITH_TEXT);
+ final EnforcedAdmin admin = RestrictedLockUtils.checkIfRestrictionEnforced(
+ getPrefContext(), UserManager.DISALLOW_MODIFY_ACCOUNTS,
+ mUserHandle.getIdentifier());
+ if (admin != null) {
+ RestrictedLockUtils.setMenuItemAsDisabledByAdmin(getPrefContext(),
+ removeAccount, admin);
}
syncNow.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER |
MenuItem.SHOW_AS_ACTION_WITH_TEXT);
diff --git a/src/com/android/settings/display/ScreenZoomSettings.java b/src/com/android/settings/display/ScreenZoomSettings.java
index 1ddcaab..7e8ac22 100644
--- a/src/com/android/settings/display/ScreenZoomSettings.java
+++ b/src/com/android/settings/display/ScreenZoomSettings.java
@@ -18,7 +18,7 @@
import com.android.settings.InstrumentedFragment;
import com.android.settings.R;
-import com.android.settings.SettingsPreferenceFragment;
+import com.android.settings.PreviewSeekBarPreferenceFragment;
import com.android.settings.search.BaseSearchIndexProvider;
import com.android.settings.search.Indexable;
import com.android.settings.search.SearchIndexableRaw;
@@ -29,17 +29,6 @@
import android.content.res.Resources;
import android.os.Bundle;
import android.view.Display;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.View.OnClickListener;
-import android.view.ViewGroup;
-import android.view.animation.AccelerateInterpolator;
-import android.view.animation.DecelerateInterpolator;
-import android.view.animation.Interpolator;
-import android.widget.FrameLayout;
-import android.widget.SeekBar;
-import android.widget.SeekBar.OnSeekBarChangeListener;
-import android.widget.TextView;
import java.util.ArrayList;
import java.util.List;
@@ -47,32 +36,17 @@
/**
* Preference fragment used to control screen zoom.
*/
-public class ScreenZoomSettings extends SettingsPreferenceFragment implements Indexable {
- /** Duration to use when cross-fading between previews. */
- private static final long CROSS_FADE_DURATION_MS = 400;
+public class ScreenZoomSettings extends PreviewSeekBarPreferenceFragment implements Indexable {
- /** Interpolator to use when cross-fading between previews. */
- private static final Interpolator FADE_IN_INTERPOLATOR = new DecelerateInterpolator();
-
- /** Interpolator to use when cross-fading between previews. */
- private static final Interpolator FADE_OUT_INTERPOLATOR = new AccelerateInterpolator();
-
- private ViewGroup mPreviewFrame;
- private TextView mLabel;
- private View mLarger;
- private View mSmaller;
-
- private String[] mEntries;
- private int[] mValues;
private int mNormalDensity;
- private int mInitialIndex;
-
- private int mCurrentIndex;
+ private int[] mValues;
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
+ mActivityLayoutResId = R.layout.screen_zoom_activity;
+ mPreviewSampleResId = R.layout.screen_zoom_preview;
final DisplayDensityUtils density = new DisplayDensityUtils(getContext());
final int initialIndex = density.getCurrentIndex();
@@ -94,152 +68,18 @@
}
@Override
- public View onCreateView(LayoutInflater inflater, ViewGroup container,
- Bundle savedInstanceState) {
- final View root = super.onCreateView(inflater, container, savedInstanceState);
- final ViewGroup list_container = (ViewGroup) root.findViewById(android.R.id.list_container);
- list_container.removeAllViews();
-
- final View content = inflater.inflate(R.layout.screen_zoom_activity, list_container, false);
- list_container.addView(content);
-
- mLabel = (TextView) content.findViewById(R.id.current_density);
-
- // The maximum SeekBar value always needs to be non-zero. If there's
- // only one available zoom level, we'll handle this by disabling the
- // seek bar.
- final int max = Math.max(1, mValues.length - 1);
-
- final SeekBar seekBar = (SeekBar) content.findViewById(R.id.seek_bar);
- seekBar.setMax(max);
- seekBar.setProgress(mInitialIndex);
- seekBar.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {
- @Override
- public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
- setPreviewLayer(progress, true);
- }
-
- @Override
- public void onStartTrackingTouch(SeekBar seekBar) {}
-
- @Override
- public void onStopTrackingTouch(SeekBar seekBar) {}
- });
-
- mSmaller = content.findViewById(R.id.smaller);
- mSmaller.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- final int progress = seekBar.getProgress();
- if (progress > 0) {
- seekBar.setProgress(progress - 1, true);
- }
- }
- });
-
- mLarger = content.findViewById(R.id.larger);
- mLarger.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- final int progress = seekBar.getProgress();
- if (progress < seekBar.getMax()) {
- seekBar.setProgress(progress + 1, true);
- }
- }
- });
-
- if (mValues.length == 1) {
- // The larger and smaller buttons will be disabled when we call
- // setPreviewLayer() later in this method.
- seekBar.setEnabled(false);
- }
-
- mPreviewFrame = (FrameLayout) content.findViewById(R.id.preview_frame);
-
+ protected Configuration createConfig(Configuration origConfig, int index) {
// Populate the sample layouts.
- final Context context = getContext();
- final Configuration origConfig = context.getResources().getConfiguration();
- for (int mValue : mValues) {
- final Configuration config = new Configuration(origConfig);
- config.densityDpi = mValue;
-
- // Create a new configuration for the specified density. It won't
- // have any theme set, so manually apply the current theme.
- final Context configContext = context.createConfigurationContext(config);
- configContext.setTheme(context.getThemeResId());
-
- final LayoutInflater configInflater = LayoutInflater.from(configContext);
- final View sampleView = configInflater.inflate(
- R.layout.screen_zoom_preview, mPreviewFrame, false);
- sampleView.setAlpha(0);
- sampleView.setVisibility(View.INVISIBLE);
-
- mPreviewFrame.addView(sampleView);
- }
-
- setPreviewLayer(mInitialIndex, false);
-
- return root;
- }
-
- @Override
- public void onDetach() {
- super.onDetach();
-
- // This will adjust the density SLIGHTLY after the activity has
- // finished, which could be considered a feature or a bug...
- commit();
- }
-
- private void setPreviewLayer(int index, boolean animate) {
- mLabel.setText(mEntries[index]);
-
- if (mCurrentIndex >= 0) {
- final View lastLayer = mPreviewFrame.getChildAt(mCurrentIndex);
- if (animate) {
- lastLayer.animate()
- .alpha(0)
- .setInterpolator(FADE_OUT_INTERPOLATOR)
- .setDuration(CROSS_FADE_DURATION_MS)
- .withEndAction(new Runnable() {
- @Override
- public void run() {
- lastLayer.setVisibility(View.INVISIBLE);
- }
- });
- } else {
- lastLayer.setAlpha(0);
- lastLayer.setVisibility(View.INVISIBLE);
- }
- }
-
- final View nextLayer = mPreviewFrame.getChildAt(index);
- if (animate) {
- nextLayer.animate()
- .alpha(1)
- .setInterpolator(FADE_IN_INTERPOLATOR)
- .setDuration(CROSS_FADE_DURATION_MS)
- .withStartAction(new Runnable() {
- @Override
- public void run() {
- nextLayer.setVisibility(View.VISIBLE);
- }
- });
- } else {
- nextLayer.setVisibility(View.VISIBLE);
- nextLayer.setAlpha(1);
- }
-
- mSmaller.setEnabled(index > 0);
- mLarger.setEnabled(index < mEntries.length - 1);
-
- mCurrentIndex = index;
+ final Configuration config = new Configuration(origConfig);
+ config.densityDpi = mValues[index];
+ return config;
}
/**
* Persists the selected density and sends a configuration change.
*/
- private void commit() {
+ @Override
+ protected void commit() {
final int densityDpi = mValues[mCurrentIndex];
if (densityDpi == mNormalDensity) {
DisplayDensityUtils.clearForcedDisplayDensity(Display.DEFAULT_DISPLAY);
diff --git a/src/com/android/settings/fuelgauge/BatteryHistoryChart.java b/src/com/android/settings/fuelgauge/BatteryHistoryChart.java
index 6c4d457..7b89fb1 100644
--- a/src/com/android/settings/fuelgauge/BatteryHistoryChart.java
+++ b/src/com/android/settings/fuelgauge/BatteryHistoryChart.java
@@ -26,7 +26,6 @@
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Typeface;
-import android.os.BatteryManager;
import android.os.BatteryStats;
import android.os.BatteryStats.HistoryItem;
import android.os.SystemClock;
@@ -39,10 +38,9 @@
import android.util.TimeUtils;
import android.util.TypedValue;
import android.view.View;
-
import com.android.settings.R;
import com.android.settings.Utils;
-
+import com.android.settingslib.BatteryInfo;
import libcore.icu.LocaleData;
import java.util.ArrayList;
@@ -509,7 +507,8 @@
mMaxPercentLabelString = Utils.formatPercentage(100);
mMinPercentLabelString = Utils.formatPercentage(0);
- mInfo = getBatteryInfo(getContext(), mBatteryBroadcast, mStats, elapsedRealtimeUs);
+ mInfo = BatteryInfo.getBatteryInfo(getContext(), mBatteryBroadcast, mStats,
+ elapsedRealtimeUs);
mDrainString = "";
mChargeDurationString = "";
setContentDescription(mInfo.mChargeLabelString);
@@ -1359,59 +1358,4 @@
}
}
}
-
- public static class BatteryInfo {
- public String mChargeLabelString;
- public int mBatteryLevel;
- public boolean mDischarging = true;
- public long remainingTimeUs = 0;
- }
-
- public static BatteryInfo getBatteryInfo(Context context, Intent batteryBroadcast,
- BatteryStats stats, long elapsedRealtimeUs) {
- BatteryInfo info = new BatteryInfo();
- info.mBatteryLevel = com.android.settings.Utils.getBatteryLevel(batteryBroadcast);
- String batteryPercentString = Utils.formatPercentage(info.mBatteryLevel);
- if (batteryBroadcast.getIntExtra(BatteryManager.EXTRA_PLUGGED, 0) == 0) {
- final long drainTime = stats.computeBatteryTimeRemaining(elapsedRealtimeUs);
- if (drainTime > 0) {
- info.remainingTimeUs = drainTime;
- String timeString = Formatter.formatShortElapsedTime(context,
- drainTime / 1000);
- info.mChargeLabelString = context.getResources().getString(
- R.string.power_discharging_duration, batteryPercentString, timeString);
- } else {
- info.mChargeLabelString = batteryPercentString;
- }
- } else {
- final long chargeTime = stats.computeChargeTimeRemaining(elapsedRealtimeUs);
- final String statusLabel = com.android.settings.Utils.getBatteryStatus(
- context.getResources(), batteryBroadcast);
- final int status = batteryBroadcast.getIntExtra(BatteryManager.EXTRA_STATUS,
- BatteryManager.BATTERY_STATUS_UNKNOWN);
- if (chargeTime > 0 && status != BatteryManager.BATTERY_STATUS_FULL) {
- info.mDischarging = false;
- info.remainingTimeUs = chargeTime;
- String timeString = Formatter.formatShortElapsedTime(context,
- chargeTime / 1000);
- int plugType = batteryBroadcast.getIntExtra(BatteryManager.EXTRA_PLUGGED, 0);
- int resId;
- if (plugType == BatteryManager.BATTERY_PLUGGED_AC) {
- resId = R.string.power_charging_duration_ac;
- } else if (plugType == BatteryManager.BATTERY_PLUGGED_USB) {
- resId = R.string.power_charging_duration_usb;
- } else if (plugType == BatteryManager.BATTERY_PLUGGED_WIRELESS) {
- resId = R.string.power_charging_duration_wireless;
- } else {
- resId = R.string.power_charging_duration;
- }
- info.mChargeLabelString = context.getResources().getString(
- resId, batteryPercentString, timeString);
- } else {
- info.mChargeLabelString = context.getResources().getString(
- R.string.power_charging, batteryPercentString, statusLabel);
- }
- }
- return info;
- }
}
diff --git a/src/com/android/settings/fuelgauge/PowerUsageSummary.java b/src/com/android/settings/fuelgauge/PowerUsageSummary.java
index 25c0fc2..153ccd7 100644
--- a/src/com/android/settings/fuelgauge/PowerUsageSummary.java
+++ b/src/com/android/settings/fuelgauge/PowerUsageSummary.java
@@ -18,17 +18,13 @@
import android.app.Activity;
import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
import android.graphics.drawable.Drawable;
-import android.os.AsyncTask;
import android.os.BatteryStats;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.os.Process;
-import android.os.SystemClock;
import android.os.UserHandle;
import android.support.v7.preference.Preference;
import android.support.v7.preference.PreferenceGroup;
@@ -40,13 +36,13 @@
import com.android.internal.logging.MetricsLogger;
import com.android.internal.os.BatterySipper;
import com.android.internal.os.BatterySipper.DrainType;
-import com.android.internal.os.BatteryStatsHelper;
import com.android.internal.os.PowerProfile;
import com.android.settings.R;
import com.android.settings.Settings.HighPowerApplicationsActivity;
import com.android.settings.SettingsActivity;
import com.android.settings.applications.ManageApplications;
import com.android.settings.dashboard.SummaryLoader;
+import com.android.settingslib.BatteryInfo;
import java.util.ArrayList;
import java.util.Collections;
@@ -451,25 +447,12 @@
public void setListening(boolean listening) {
if (listening) {
// TODO: Listen.
- new AsyncTask<Void, Void, BatteryStats>() {
+ BatteryInfo.getBatteryInfo(mContext, new BatteryInfo.Callback() {
@Override
- protected BatteryStats doInBackground(Void... params) {
- BatteryStatsHelper statsHelper = new BatteryStatsHelper(mContext, true);
- statsHelper.create((Bundle) null);
- return statsHelper.getStats();
+ public void onBatteryInfoLoaded(BatteryInfo info) {
+ mLoader.setSummary(SummaryProvider.this, info.mChargeLabelString);
}
-
- @Override
- protected void onPostExecute(BatteryStats batteryStats) {
- final long elapsedRealtimeUs = SystemClock.elapsedRealtime() * 1000;
- Intent batteryBroadcast = mContext.registerReceiver(null,
- new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
- BatteryHistoryChart.BatteryInfo batteryInfo = BatteryHistoryChart
- .getBatteryInfo(mContext, batteryBroadcast, batteryStats,
- elapsedRealtimeUs);
- mLoader.setSummary(SummaryProvider.this, batteryInfo.mChargeLabelString);
- }
- }.execute();
+ });
}
}
}
diff --git a/src/com/android/settings/notification/ConfigureNotificationSettings.java b/src/com/android/settings/notification/ConfigureNotificationSettings.java
index f3f74a7..9f0767b 100644
--- a/src/com/android/settings/notification/ConfigureNotificationSettings.java
+++ b/src/com/android/settings/notification/ConfigureNotificationSettings.java
@@ -19,9 +19,11 @@
import com.android.internal.widget.LockPatternUtils;
import com.android.settings.InstrumentedFragment;
import com.android.settings.R;
+import com.android.settings.RestrictedDropDownPreference;
+import com.android.settings.RestrictedDropDownPreference.RestrictedItem;
+import com.android.settings.RestrictedLockUtils;
import com.android.settings.SettingsPreferenceFragment;
-import android.app.admin.DevicePolicyManager;
import android.content.ContentResolver;
import android.content.Context;
import android.database.ContentObserver;
@@ -30,13 +32,18 @@
import android.os.Handler;
import android.os.UserHandle;
import android.provider.Settings;
-import android.support.v7.preference.DropDownPreference;
import android.support.v7.preference.Preference;
import android.support.v7.preference.Preference.OnPreferenceChangeListener;
import android.support.v7.preference.TwoStatePreference;
import android.util.Log;
import java.util.ArrayList;
+import java.util.List;
+
+import static android.app.admin.DevicePolicyManager.KEYGUARD_DISABLE_SECURE_NOTIFICATIONS;
+import static android.app.admin.DevicePolicyManager.KEYGUARD_DISABLE_UNREDACTED_NOTIFICATIONS;
+
+import static com.android.settings.RestrictedLockUtils.EnforcedAdmin;
public class ConfigureNotificationSettings extends SettingsPreferenceFragment {
private static final String TAG = "ConfigNotiSettings";
@@ -49,7 +56,7 @@
private Context mContext;
private TwoStatePreference mNotificationPulse;
- private DropDownPreference mLockscreen;
+ private RestrictedDropDownPreference mLockscreen;
private boolean mSecure;
private int mLockscreenSelectedValue;
@@ -124,28 +131,36 @@
// === Lockscreen (public / private) notifications ===
private void initLockscreenNotifications() {
- mLockscreen = (DropDownPreference) getPreferenceScreen().findPreference(
+ mLockscreen = (RestrictedDropDownPreference) getPreferenceScreen().findPreference(
KEY_LOCK_SCREEN_NOTIFICATIONS);
if (mLockscreen == null) {
Log.i(TAG, "Preference not found: " + KEY_LOCK_SCREEN_NOTIFICATIONS);
return;
}
- boolean isSecureNotificationsDisabled = isSecureNotificationsDisabled();
- boolean isUnredactedNotificationsDisabled = isUnredactedNotificationsDisabled();
ArrayList<CharSequence> entries = new ArrayList<>();
ArrayList<CharSequence> values = new ArrayList<>();
- if (!isSecureNotificationsDisabled && !isUnredactedNotificationsDisabled) {
- entries.add(getString(R.string.lock_screen_notifications_summary_show));
- values.add(Integer.toString(R.string.lock_screen_notifications_summary_show));
- }
- if (mSecure && !isSecureNotificationsDisabled) {
- entries.add(getString(R.string.lock_screen_notifications_summary_hide));
- values.add(Integer.toString(R.string.lock_screen_notifications_summary_hide));
- }
entries.add(getString(R.string.lock_screen_notifications_summary_disable));
values.add(Integer.toString(R.string.lock_screen_notifications_summary_disable));
+ String summaryShowEntry = getString(R.string.lock_screen_notifications_summary_show);
+ String summaryShowEntryValue = Integer.toString(
+ R.string.lock_screen_notifications_summary_show);
+ entries.add(summaryShowEntry);
+ values.add(summaryShowEntryValue);
+ setRestrictedIfNotificationFeaturesDisabled(summaryShowEntry, summaryShowEntryValue,
+ KEYGUARD_DISABLE_SECURE_NOTIFICATIONS | KEYGUARD_DISABLE_UNREDACTED_NOTIFICATIONS);
+
+ if (mSecure) {
+ String summaryHideEntry = getString(R.string.lock_screen_notifications_summary_hide);
+ String summaryHideEntryValue = Integer.toString(
+ R.string.lock_screen_notifications_summary_hide);
+ entries.add(summaryHideEntry);
+ values.add(summaryHideEntryValue);
+ setRestrictedIfNotificationFeaturesDisabled(summaryHideEntry, summaryHideEntryValue,
+ KEYGUARD_DISABLE_SECURE_NOTIFICATIONS);
+ }
+
mLockscreen.setEntries(entries.toArray(new CharSequence[entries.size()]));
mLockscreen.setEntryValues(values.toArray(new CharSequence[values.size()]));
updateLockscreenNotifications();
@@ -174,18 +189,14 @@
}
}
- private boolean isSecureNotificationsDisabled() {
- final DevicePolicyManager dpm =
- (DevicePolicyManager) getSystemService(Context.DEVICE_POLICY_SERVICE);
- return dpm != null && (dpm.getKeyguardDisabledFeatures(null)
- & DevicePolicyManager.KEYGUARD_DISABLE_SECURE_NOTIFICATIONS) != 0;
- }
-
- private boolean isUnredactedNotificationsDisabled() {
- final DevicePolicyManager dpm =
- (DevicePolicyManager) getSystemService(Context.DEVICE_POLICY_SERVICE);
- return dpm != null && (dpm.getKeyguardDisabledFeatures(null)
- & DevicePolicyManager.KEYGUARD_DISABLE_UNREDACTED_NOTIFICATIONS) != 0;
+ private void setRestrictedIfNotificationFeaturesDisabled(CharSequence entry,
+ CharSequence entryValue, int keyguardNotificationFeatures) {
+ EnforcedAdmin admin = RestrictedLockUtils.checkIfKeyguardNotificationFeaturesDisabled(
+ mContext, keyguardNotificationFeatures);
+ if (admin != null) {
+ RestrictedItem item = new RestrictedItem(entry, entryValue, admin);
+ mLockscreen.addRestrictedItem(item);
+ }
}
private void updateLockscreenNotifications() {
diff --git a/src/com/android/settings/users/RestrictionUtils.java b/src/com/android/settings/users/RestrictionUtils.java
index fbdc7596..33b6a95 100644
--- a/src/com/android/settings/users/RestrictionUtils.java
+++ b/src/com/android/settings/users/RestrictionUtils.java
@@ -81,14 +81,6 @@
for (RestrictionEntry entry : entries) {
um.setUserRestriction(entry.getKey(), !entry.getSelectedState());
-
- // TODO This will no longer be needed once b/23902097 is fixed. um.setUserRestriction
- // should do it.
- if (entry.getKey().equals(UserManager.DISALLOW_SHARE_LOCATION)
- && !entry.getSelectedState()) {
- Secure.putIntForUser(context.getContentResolver(),
- Secure.LOCATION_MODE, Secure.LOCATION_MODE_OFF, user.getIdentifier());
- }
}
}
}