diff options
-rw-r--r-- | AndroidManifest.xml | 19 | ||||
-rw-r--r-- | res/values/strings.xml | 11 | ||||
-rw-r--r-- | res/xml/notification_settings.xml | 13 | ||||
-rw-r--r-- | src/com/android/settings/Settings.java | 1 | ||||
-rw-r--r-- | src/com/android/settings/SettingsActivity.java | 2 | ||||
-rw-r--r-- | src/com/android/settings/notification/NotificationSettings.java | 30 | ||||
-rw-r--r-- | src/com/android/settings/notification/ZenAccessSettings.java | 169 |
7 files changed, 231 insertions, 14 deletions
diff --git a/AndroidManifest.xml b/AndroidManifest.xml index 12551d0..500c0aa 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -2251,7 +2251,24 @@ <meta-data android:name="com.android.settings.FRAGMENT_CLASS" android:value="com.android.settings.notification.NotificationAccessSettings" /> <meta-data android:name="com.android.settings.TOP_LEVEL_HEADER_ID" - android:resource="@id/security_settings" /> + android:resource="@id/notification_settings" /> + </activity> + + <activity android:name="Settings$ZenAccessSettingsActivity" + android:label="@string/manage_zen_access_title" + android:taskAffinity=""> + <intent-filter android:priority="1"> + <action android:name="android.settings.ZEN_ACCESS_SETTINGS" /> + <category android:name="android.intent.category.DEFAULT" /> + </intent-filter> + <intent-filter> + <action android:name="android.intent.action.MAIN" /> + <category android:name="android.intent.category.DEFAULT" /> + </intent-filter> + <meta-data android:name="com.android.settings.FRAGMENT_CLASS" + android:value="com.android.settings.notification.ZenAccessSettings" /> + <meta-data android:name="com.android.settings.TOP_LEVEL_HEADER_ID" + android:resource="@id/notification_settings" /> </activity> <activity android:name="Settings$NotificationSettingsActivity" diff --git a/res/values/strings.xml b/res/values/strings.xml index 9db8e8c..253638a 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -5934,6 +5934,9 @@ <!-- Sound & notification: Notification section header [CHAR LIMIT=30] --> <string name="notification_section_header">Notification</string> + <!-- Sound & notification: Advanced section header [CHAR LIMIT=30] --> + <string name="advanced_section_header">Advanced</string> + <!-- Sound & notification > Notification section: Title for the pulse notification light option. [CHAR LIMIT=30] --> <string name="notification_pulse_title">Pulse notification light</string> @@ -5999,7 +6002,7 @@ <!-- Sound & notification > Other sounds: Value for the emergency tone option with value 2: vibrate. [CHAR LIMIT=30] --> <string name="emergency_tone_vibrate">Vibrate</string> - <!-- Sound & notification > Notification section: Title for managing notification listeners option. [CHAR LIMIT=30] --> + <!-- Sound & notification > Advanced section: Title for managing notification listeners option. [CHAR LIMIT=30] --> <string name="manage_notification_access_title">Notification access</string> <!-- Summary of preference to manage notification listeners, when none are enabled --> @@ -6028,6 +6031,12 @@ to dismiss these notifications or touch action buttons within them. </string> + <!-- Sound & notification > Advanced section: Title for managing Do Not Disturb access option. [CHAR LIMIT=40] --> + <string name="manage_zen_access_title">Do Not Disturb access</string> + + <!-- Sound & notification > Do Not Disturb access > Text to display when the list is empty. [CHAR LIMIT=NONE] --> + <string name="zen_access_empty_text">No installed apps have requested Do Not Disturb access</string> + <!-- [CHAR LIMIT=NONE] Text when loading app list in notification settings --> <string name="loading_notification_apps">Loading apps...</string> diff --git a/res/xml/notification_settings.xml b/res/xml/notification_settings.xml index 7956a6d..72a189d 100644 --- a/res/xml/notification_settings.xml +++ b/res/xml/notification_settings.xml @@ -120,6 +120,12 @@ android:value="com.android.settings.Settings$NotificationAppListActivity" /> </PreferenceScreen> + </PreferenceCategory> + + <PreferenceCategory + android:key="advanced" + android:title="@string/advanced_section_header" > + <!-- Notification access --> <Preference android:key="manage_notification_access" @@ -127,6 +133,13 @@ android:persistent="false" android:fragment="com.android.settings.notification.NotificationAccessSettings" /> + <!-- Do Not Disturb access --> + <Preference + android:key="manage_zen_access" + android:title="@string/manage_zen_access_title" + android:persistent="false" + android:fragment="com.android.settings.notification.ZenAccessSettings" /> + </PreferenceCategory> </PreferenceScreen> diff --git a/src/com/android/settings/Settings.java b/src/com/android/settings/Settings.java index b91275a..5a6a2f0 100644 --- a/src/com/android/settings/Settings.java +++ b/src/com/android/settings/Settings.java @@ -91,6 +91,7 @@ public class Settings extends SettingsActivity { public static class NotificationStationActivity extends SettingsActivity { /* empty */ } public static class UserSettingsActivity extends SettingsActivity { /* empty */ } public static class NotificationAccessSettingsActivity extends SettingsActivity { /* empty */ } + public static class ZenAccessSettingsActivity extends SettingsActivity { /* empty */ } public static class ConditionProviderSettingsActivity extends SettingsActivity { /* empty */ } public static class UsbSettingsActivity extends SettingsActivity { /* empty */ } public static class TrustedCredentialsSettingsActivity extends SettingsActivity { /* empty */ } diff --git a/src/com/android/settings/SettingsActivity.java b/src/com/android/settings/SettingsActivity.java index 89dbc99..aa492f3 100644 --- a/src/com/android/settings/SettingsActivity.java +++ b/src/com/android/settings/SettingsActivity.java @@ -103,6 +103,7 @@ import com.android.settings.notification.NotificationAccessSettings; import com.android.settings.notification.NotificationSettings; import com.android.settings.notification.NotificationStation; import com.android.settings.notification.OtherSoundSettings; +import com.android.settings.notification.ZenAccessSettings; import com.android.settings.notification.ZenModeEventRuleSettings; import com.android.settings.notification.ZenModeExternalRuleSettings; import com.android.settings.notification.ZenModePrioritySettings; @@ -328,6 +329,7 @@ public class SettingsActivity extends Activity DreamSettings.class.getName(), UserSettings.class.getName(), NotificationAccessSettings.class.getName(), + ZenAccessSettings.class.getName(), PrintSettingsFragment.class.getName(), PrintJobSettingsFragment.class.getName(), TrustedCredentialsSettings.class.getName(), diff --git a/src/com/android/settings/notification/NotificationSettings.java b/src/com/android/settings/notification/NotificationSettings.java index cdff32f..00f5497 100644 --- a/src/com/android/settings/notification/NotificationSettings.java +++ b/src/com/android/settings/notification/NotificationSettings.java @@ -79,6 +79,7 @@ public class NotificationSettings extends SettingsPreferenceFragment implements private static final String KEY_NOTIFICATION_PULSE = "notification_pulse"; private static final String KEY_LOCK_SCREEN_NOTIFICATIONS = "lock_screen_notifications"; private static final String KEY_NOTIFICATION_ACCESS = "manage_notification_access"; + private static final String KEY_ZEN_ACCESS = "manage_zen_access"; private static final int SAMPLE_CUTOFF = 2000; // manually cap sample playback at 2 seconds @@ -101,6 +102,7 @@ public class NotificationSettings extends SettingsPreferenceFragment implements private TwoStatePreference mNotificationPulse; private DropDownPreference mLockscreen; private Preference mNotificationAccess; + private Preference mZenAccess; private boolean mSecure; private int mLockscreenSelectedValue; private ComponentName mSuppressor; @@ -153,6 +155,8 @@ public class NotificationSettings extends SettingsPreferenceFragment implements mNotificationAccess = findPreference(KEY_NOTIFICATION_ACCESS); refreshNotificationListeners(); + mZenAccess = findPreference(KEY_ZEN_ACCESS); + refreshZenAccess(); updateRingerMode(); updateEffectsSuppressor(); } @@ -161,6 +165,7 @@ public class NotificationSettings extends SettingsPreferenceFragment implements public void onResume() { super.onResume(); refreshNotificationListeners(); + refreshZenAccess(); lookupRingtoneNames(); mSettingsObserver.register(true); mReceiver.register(true); @@ -471,23 +476,24 @@ public class NotificationSettings extends SettingsPreferenceFragment implements private void refreshNotificationListeners() { if (mNotificationAccess != null) { - final int total = NotificationAccessSettings.getListenersCount(mPM); - if (total == 0) { - getPreferenceScreen().removePreference(mNotificationAccess); + final int n = NotificationAccessSettings.getEnabledListenersCount(mContext); + if (n == 0) { + mNotificationAccess.setSummary(getResources().getString( + R.string.manage_notification_access_summary_zero)); } else { - final int n = NotificationAccessSettings.getEnabledListenersCount(mContext); - if (n == 0) { - mNotificationAccess.setSummary(getResources().getString( - R.string.manage_notification_access_summary_zero)); - } else { - mNotificationAccess.setSummary(String.format(getResources().getQuantityString( - R.plurals.manage_notification_access_summary_nonzero, - n, n))); - } + mNotificationAccess.setSummary(String.format(getResources().getQuantityString( + R.plurals.manage_notification_access_summary_nonzero, + n, n))); } } } + // === Zen access === + + private void refreshZenAccess() { + // noop for now + } + // === Callbacks === private final class SettingsObserver extends ContentObserver { diff --git a/src/com/android/settings/notification/ZenAccessSettings.java b/src/com/android/settings/notification/ZenAccessSettings.java new file mode 100644 index 0000000..a9f02a9 --- /dev/null +++ b/src/com/android/settings/notification/ZenAccessSettings.java @@ -0,0 +1,169 @@ +/* + * 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.notification; + +import android.app.ListFragment; +import android.app.NotificationManager; +import android.content.Context; +import android.content.pm.ApplicationInfo; +import android.content.pm.PackageItemInfo; +import android.content.pm.PackageManager; +import android.os.Bundle; +import android.util.ArraySet; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ArrayAdapter; +import android.widget.CheckBox; +import android.widget.ImageView; +import android.widget.ListView; +import android.widget.TextView; + +import com.android.settings.R; + +import java.util.List; + +public class ZenAccessSettings extends ListFragment { + private static final boolean SHOW_PACKAGE_NAME = false; + + private Context mContext; + private PackageManager mPkgMan; + private NotificationManager mNoMan; + private Adapter mAdapter; + + @Override + public void onCreate(Bundle icicle) { + super.onCreate(icicle); + + mContext = getActivity(); + mPkgMan = mContext.getPackageManager(); + mNoMan = mContext.getSystemService(NotificationManager.class); + mAdapter = new Adapter(mContext); + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + final View v = inflater.inflate(R.layout.managed_service_settings, container, false); + final TextView empty = (TextView) v.findViewById(android.R.id.empty); + empty.setText(R.string.zen_access_empty_text); + return v; + } + + @Override + public void onResume() { + super.onResume(); + reloadList(); + } + + private void reloadList() { + mAdapter.clear(); + final ArraySet<String> requesting = mNoMan.getPackagesRequestingNotificationPolicyAccess(); + if (requesting != null && !requesting.isEmpty()) { + final List<ApplicationInfo> apps = mPkgMan.getInstalledApplications(0); + if (apps != null) { + for (ApplicationInfo app : apps) { + if (requesting.contains(app.packageName)) { + mAdapter.add(app); + } + } + } + } + mAdapter.sort(new PackageItemInfo.DisplayNameComparator(mPkgMan)); + getListView().setAdapter(mAdapter); + } + + @Override + public void onListItemClick(ListView l, View v, int position, long id) { + final ApplicationInfo info = mAdapter.getItem(position); + final boolean hasAccess = hasAccess(info.packageName); + setAccess(info.packageName, !hasAccess); + mAdapter.notifyDataSetChanged(); + } + + private boolean hasAccess(String pkg) { + return mNoMan.isNotificationPolicyAccessGrantedForPackage(pkg); + } + + private void setAccess(String pkg, boolean access) { + mNoMan.setNotificationPolicyAccessGranted(pkg, access); + } + + private static class ViewHolder { + ImageView icon; + TextView name; + CheckBox checkbox; + TextView description; + } + + private final class Adapter extends ArrayAdapter<ApplicationInfo> { + final LayoutInflater mInflater; + + Adapter(Context context) { + super(context, 0, 0); + mInflater = (LayoutInflater) + getActivity().getSystemService(Context.LAYOUT_INFLATER_SERVICE); + } + + public boolean hasStableIds() { + return true; + } + + public long getItemId(int position) { + return position; + } + + public View getView(int position, View convertView, ViewGroup parent) { + View v; + if (convertView == null) { + v = newView(parent); + } else { + v = convertView; + } + bindView(v, position); + return v; + } + + public View newView(ViewGroup parent) { + View v = mInflater.inflate(R.layout.managed_service_item, parent, false); + ViewHolder h = new ViewHolder(); + h.icon = (ImageView) v.findViewById(R.id.icon); + h.name = (TextView) v.findViewById(R.id.name); + h.checkbox = (CheckBox) v.findViewById(R.id.checkbox); + h.description = (TextView) v.findViewById(R.id.description); + v.setTag(h); + return v; + } + + public void bindView(View view, int position) { + ViewHolder vh = (ViewHolder) view.getTag(); + ApplicationInfo info = getItem(position); + + vh.icon.setImageDrawable(info.loadIcon(mPkgMan)); + vh.name.setText(info.loadLabel(mPkgMan)); + if (SHOW_PACKAGE_NAME) { + vh.description.setText(info.packageName); + vh.description.setVisibility(View.VISIBLE); + } else { + vh.description.setVisibility(View.GONE); + } + vh.checkbox.setChecked(hasAccess(info.packageName)); + } + + } + +} |