Add policy transparency to app notification settings on lockscreen.

Bug: 28390118
Change-Id: I395440b0f7e93da90f9f346574afa5501761d473
This commit is contained in:
Sudheer Shanka
2016-04-27 13:11:24 -07:00
parent 8fa3d44596
commit 2ad6adbd58
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;
}
}
}