Merge "Add policy transparency to app notification settings on lockscreen." into nyc-dev

am: 938501cf76

* commit '938501cf7634843460b03b6fe954e927166e1257':
  Add policy transparency to app notification settings on lockscreen.

Change-Id: I7d9b313218cce94d6711d4ffa5df9a3c99d391c0
This commit is contained in:
Sudheer Shanka
2016-05-11 19:13:46 +00:00
committed by android-build-merger
6 changed files with 350 additions and 11 deletions

View File

@@ -0,0 +1,30 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ 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
-->
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<view android:id="@+id/spinner"
class="com.android.settings.notification.RestrictedDropDownPreference$ReselectionSpinner"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:visibility="invisible" />
<include layout="@layout/preference_material" />
</FrameLayout>

View File

@@ -0,0 +1,36 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- 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.
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:gravity="center_vertical">
<TextView android:id="@android:id/text1"
style="?android:attr/spinnerDropDownItemStyle"
android:singleLine="true"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="?android:attr/listPreferredItemHeightSmall"
android:ellipsize="marquee" />
<ImageView android:id="@+id/restricted_icon"
android:layout_width="@dimen/restricted_icon_size"
android:layout_height="@dimen/restricted_icon_size"
android:src="@drawable/ic_info"
android:baselineAlignBottom="true"
android:layout_marginEnd="@dimen/restricted_icon_padding"
android:gravity="end|center_vertical"
android:visibility="gone" />
</LinearLayout>

View File

@@ -17,8 +17,7 @@
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:settings="http://schemas.android.com/apk/res/com.android.settings"
android:title="@string/app_notifications_title"
android:key="app_notification_settings"
settings:keywords="@string/keywords_date_and_time">
android:key="app_notification_settings">
<!-- Importance -->
<!-- Block -->
@@ -43,7 +42,7 @@
android:order="4"/>
<!-- Visibility Override -->
<DropDownPreference
<com.android.settings.notification.RestrictedDropDownPreference
android:key="visibility_override"
android:title="@string/app_notification_visibility_override_title"
android:order="5" />

View File

@@ -26,7 +26,6 @@ import android.content.pm.UserInfo;
import android.os.Bundle;
import android.os.UserHandle;
import android.service.notification.NotificationListenerService.Ranking;
import android.support.v7.preference.DropDownPreference;
import android.util.ArrayMap;
import android.util.Log;
@@ -76,7 +75,7 @@ public class AppNotificationSettings extends NotificationSettingsBase {
mPriority =
(RestrictedSwitchPreference) getPreferenceScreen().findPreference(KEY_BYPASS_DND);
mVisibilityOverride =
(DropDownPreference) getPreferenceScreen().findPreference(
(RestrictedDropDownPreference) getPreferenceScreen().findPreference(
KEY_VISIBILITY_OVERRIDE);
mBlock = (RestrictedSwitchPreference) getPreferenceScreen().findPreference(KEY_BLOCK);
mSilent = (RestrictedSwitchPreference) getPreferenceScreen().findPreference(KEY_SILENT);

View File

@@ -23,6 +23,7 @@ import com.android.settingslib.RestrictedLockUtils;
import com.android.settingslib.RestrictedSwitchPreference;
import android.app.Notification;
import android.app.admin.DevicePolicyManager;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageInfo;
@@ -33,7 +34,6 @@ import android.os.UserHandle;
import android.os.UserManager;
import android.provider.Settings;
import android.service.notification.NotificationListenerService.Ranking;
import android.support.v7.preference.DropDownPreference;
import android.support.v7.preference.Preference;
import android.text.TextUtils;
import android.util.Log;
@@ -41,6 +41,7 @@ import android.widget.Toast;
import java.util.ArrayList;
import static com.android.settings.notification.RestrictedDropDownPreference.RestrictedItem;
import static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
abstract public class NotificationSettingsBase extends SettingsPreferenceFragment {
@@ -65,7 +66,7 @@ abstract public class NotificationSettingsBase extends SettingsPreferenceFragmen
protected PackageInfo mPkgInfo;
protected ImportanceSeekBarPreference mImportance;
protected RestrictedSwitchPreference mPriority;
protected DropDownPreference mVisibilityOverride;
protected RestrictedDropDownPreference mVisibilityOverride;
protected RestrictedSwitchPreference mBlock;
protected RestrictedSwitchPreference mSilent;
protected EnforcedAdmin mSuspendedAppsAdmin;
@@ -148,6 +149,9 @@ abstract public class NotificationSettingsBase extends SettingsPreferenceFragmen
if (mSilent != null) {
mSilent.setDisabledByAdmin(mSuspendedAppsAdmin);
}
if (mVisibilityOverride != null) {
mVisibilityOverride.setDisabledByAdmin(mSuspendedAppsAdmin);
}
}
protected void setupImportancePrefs(boolean isSystemApp, int importance, boolean banned) {
@@ -216,13 +220,24 @@ abstract public class NotificationSettingsBase extends SettingsPreferenceFragmen
ArrayList<CharSequence> entries = new ArrayList<>();
ArrayList<CharSequence> values = new ArrayList<>();
mVisibilityOverride.clearRestrictedItems();
if (getLockscreenNotificationsEnabled() && getLockscreenAllowPrivateNotifications()) {
entries.add(getString(R.string.lock_screen_notifications_summary_show));
values.add(Integer.toString(Ranking.VISIBILITY_NO_OVERRIDE));
final String summaryShowEntry =
getString(R.string.lock_screen_notifications_summary_show);
final String summaryShowEntryValue = Integer.toString(Ranking.VISIBILITY_NO_OVERRIDE);
entries.add(summaryShowEntry);
values.add(summaryShowEntryValue);
setRestrictedIfNotificationFeaturesDisabled(summaryShowEntry, summaryShowEntryValue,
DevicePolicyManager.KEYGUARD_DISABLE_SECURE_NOTIFICATIONS
| DevicePolicyManager.KEYGUARD_DISABLE_UNREDACTED_NOTIFICATIONS);
}
entries.add(getString(R.string.lock_screen_notifications_summary_hide));
values.add(Integer.toString(Notification.VISIBILITY_PRIVATE));
final String summaryHideEntry = getString(R.string.lock_screen_notifications_summary_hide);
final String summaryHideEntryValue = Integer.toString(Notification.VISIBILITY_PRIVATE);
entries.add(summaryHideEntry);
values.add(summaryHideEntryValue);
setRestrictedIfNotificationFeaturesDisabled(summaryHideEntry, summaryHideEntryValue,
DevicePolicyManager.KEYGUARD_DISABLE_SECURE_NOTIFICATIONS);
entries.add(getString(R.string.lock_screen_notifications_summary_disable));
values.add(Integer.toString(Notification.VISIBILITY_SECRET));
mVisibilityOverride.setEntries(entries.toArray(new CharSequence[entries.size()]));
@@ -248,6 +263,16 @@ abstract public class NotificationSettingsBase extends SettingsPreferenceFragmen
});
}
private void setRestrictedIfNotificationFeaturesDisabled(CharSequence entry,
CharSequence entryValue, int keyguardNotificationFeatures) {
EnforcedAdmin admin = RestrictedLockUtils.checkIfKeyguardFeaturesDisabled(
mContext, keyguardNotificationFeatures, mUserId);
if (admin != null) {
RestrictedItem item = new RestrictedItem(entry, entryValue, admin);
mVisibilityOverride.addRestrictedItem(item);
}
}
private int getGlobalVisibility() {
int globalVis = Ranking.VISIBILITY_NO_OVERRIDE;
if (!getLockscreenNotificationsEnabled()) {

View File

@@ -0,0 +1,250 @@
/*
* 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.notification;
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 com.android.settings.R;
import com.android.settingslib.RestrictedLockUtils;
import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
import com.android.settingslib.RestrictedPreferenceHelper;
import java.util.ArrayList;
import java.util.List;
public class RestrictedDropDownPreference extends DropDownPreference {
private final RestrictedPreferenceHelper mHelper;
private ReselectionSpinner mSpinner;
private List<RestrictedItem> mRestrictedItems = new ArrayList<>();
private boolean mUserClicked = false;
public RestrictedDropDownPreference(Context context, AttributeSet attrs) {
super(context, attrs);
setLayoutResource(R.layout.restricted_preference_dropdown);
setWidgetLayoutResource(R.layout.restricted_icon);
mHelper = new RestrictedPreferenceHelper(context, this, attrs);
}
@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) {
mSpinner = (ReselectionSpinner) view.itemView.findViewById(R.id.spinner);
mSpinner.setPreference(this);
super.onBindViewHolder(view);
mHelper.onBindViewHolder(view);
mSpinner.setOnItemSelectedListener(mItemSelectedListener);
final View restrictedIcon = view.findViewById(R.id.restricted_icon);
if (restrictedIcon != null) {
restrictedIcon.setVisibility(isDisabledByAdmin() ? View.VISIBLE : View.GONE);
}
}
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;
}
private RestrictedItem getRestrictedItemForPosition(int position) {
if (position < 0 || position >= getEntryValues().length) {
return null;
}
CharSequence entryValue = getEntryValues()[position];
return getRestrictedItemForEntryValue(entryValue);
}
public void addRestrictedItem(RestrictedItem item) {
mRestrictedItems.add(item);
}
public void clearRestrictedItems() {
mRestrictedItems.clear();
}
@Override
public void performClick() {
if (!mHelper.performClick()) {
mUserClicked = true;
super.performClick();
}
}
@Override
public void setEnabled(boolean enabled) {
if (enabled && isDisabledByAdmin()) {
mHelper.setDisabledByAdmin(null);
return;
}
super.setEnabled(enabled);
}
public void setDisabledByAdmin(EnforcedAdmin admin) {
if (mHelper.setDisabledByAdmin(admin)) {
notifyChanged();
}
}
public boolean isDisabledByAdmin() {
return mHelper.isDisabledByAdmin();
}
private void setUserClicked(boolean userClicked) {
mUserClicked = userClicked;
}
private boolean isUserClicked() {
return mUserClicked;
}
private final OnItemSelectedListener mItemSelectedListener = new OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View v, int position, long id) {
if (mUserClicked) {
mUserClicked = false;
} else {
return;
}
if (position >= 0 && position < getEntryValues().length) {
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
}
};
/**
* Extension of {@link ArrayAdapter} which updates the state of the dropdown item
* depending on whether it is restricted by the admin.
*/
private class RestrictedArrayItemAdapter extends ArrayAdapter<String> {
private static final int TEXT_RES_ID = android.R.id.text1;
public RestrictedArrayItemAdapter(Context context) {
super(context, R.layout.spinner_dropdown_restricted_item, TEXT_RES_ID);
}
@Override
public View getDropDownView(int position, View convertView, ViewGroup parent) {
View rootView = super.getView(position, convertView, parent);
CharSequence entry = getItem(position);
boolean isEntryRestricted = isRestrictedForEntry(entry);
TextView text = (TextView) rootView.findViewById(TEXT_RES_ID);
if (text != null) {
text.setEnabled(!isEntryRestricted);
}
View restrictedIcon = rootView.findViewById(R.id.restricted_icon);
if (restrictedIcon != null) {
restrictedIcon.setVisibility(isEntryRestricted ? View.VISIBLE : View.GONE);
}
return rootView;
}
}
/**
* Extension of {@link Spinner} which triggers the admin support dialog on user clicking a
* restricted item even if was already selected.
*/
public static class ReselectionSpinner extends Spinner {
private RestrictedDropDownPreference pref;
public ReselectionSpinner(Context context, AttributeSet attrs) {
super(context, attrs);
}
public void setPreference(RestrictedDropDownPreference pref) {
this.pref = pref;
}
@Override
public void setSelection(int position) {
int previousSelectedPosition = getSelectedItemPosition();
super.setSelection(position);
if (position == previousSelectedPosition && pref.isUserClicked()) {
pref.setUserClicked(false);
RestrictedItem item = pref.getRestrictedItemForPosition(position);
if (item != null) {
RestrictedLockUtils.sendShowAdminSupportDetailsIntent(getContext(),
item.enforcedAdmin);
}
}
}
}
public static class RestrictedItem {
public final CharSequence entry;
public final CharSequence entryValue;
public final EnforcedAdmin enforcedAdmin;
public RestrictedItem(CharSequence entry, CharSequence entryValue,
EnforcedAdmin enforcedAdmin) {
this.entry = entry;
this.entryValue = entryValue;
this.enforcedAdmin = enforcedAdmin;
}
}
}