Settings: New DND access settings page.

 - New advanced notification settings subpage for managing apps
   that have requested the ability to manage notification policy.
 - Create new "Advanced" section at the bottom of notification settings
   for this and the existing Notification access settings page.

Bug: 18298798
Change-Id: Ib415e634980d37d6492799f67a6619700ee2a01c
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 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.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 @@
             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 @@
     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 @@
     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 @@
 
         mNotificationAccess = findPreference(KEY_NOTIFICATION_ACCESS);
         refreshNotificationListeners();
+        mZenAccess = findPreference(KEY_ZEN_ACCESS);
+        refreshZenAccess();
         updateRingerMode();
         updateEffectsSuppressor();
     }
@@ -161,6 +165,7 @@
     public void onResume() {
         super.onResume();
         refreshNotificationListeners();
+        refreshZenAccess();
         lookupRingtoneNames();
         mSettingsObserver.register(true);
         mReceiver.register(true);
@@ -471,23 +476,24 @@
 
     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));
+        }
+
+    }
+
+}