1 /*
2  * Copyright (C) 2019 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.settings.notification;
18 
19 import android.app.settings.SettingsEnums;
20 import android.content.ComponentName;
21 import android.content.Context;
22 import android.content.pm.PackageItemInfo;
23 import android.content.pm.PackageManager;
24 import android.content.pm.ServiceInfo;
25 import android.graphics.drawable.Drawable;
26 import android.provider.Settings;
27 import android.service.notification.NotificationAssistantService;
28 import android.text.TextUtils;
29 
30 import com.android.internal.annotations.VisibleForTesting;
31 import com.android.settings.R;
32 import com.android.settings.applications.defaultapps.DefaultAppPickerFragment;
33 import com.android.settings.search.BaseSearchIndexProvider;
34 import com.android.settingslib.applications.DefaultAppInfo;
35 import com.android.settingslib.applications.ServiceListing;
36 import com.android.settingslib.widget.CandidateInfo;
37 
38 import java.util.ArrayList;
39 import java.util.List;
40 
41 public class NotificationAssistantPicker extends DefaultAppPickerFragment implements
42         ServiceListing.Callback {
43 
44     private static final String TAG = "NotiAssistantPicker";
45 
46     @VisibleForTesting
47     protected NotificationBackend mNotificationBackend;
48     private List<CandidateInfo> mCandidateInfos = new ArrayList<>();
49     @VisibleForTesting
50     protected Context mContext;
51     private ServiceListing mServiceListing;
52 
53     @Override
onAttach(Context context)54     public void onAttach(Context context) {
55         super.onAttach(context);
56         mContext = context;
57         mNotificationBackend = new NotificationBackend();
58         mServiceListing = new ServiceListing.Builder(context)
59                 .setTag(TAG)
60                 .setSetting(Settings.Secure.ENABLED_NOTIFICATION_ASSISTANT)
61                 .setIntentAction(NotificationAssistantService.SERVICE_INTERFACE)
62                 .setPermission(android.Manifest.permission.BIND_NOTIFICATION_ASSISTANT_SERVICE)
63                 .setNoun("notification assistant")
64                 .build();
65         mServiceListing.addCallback(this);
66         mServiceListing.reload();
67     }
68 
69     @Override
onDetach()70     public void onDetach() {
71         super.onDetach();
72         mServiceListing.removeCallback(this);
73     }
74 
75     @Override
getPreferenceScreenResId()76     protected int getPreferenceScreenResId() {
77         return R.xml.notification_assistant_settings;
78     }
79 
80     @Override
getCandidates()81     protected List<? extends CandidateInfo> getCandidates() {
82         return mCandidateInfos;
83     }
84 
85     @Override
getDefaultKey()86     protected String getDefaultKey() {
87         ComponentName cn = mNotificationBackend.getAllowedNotificationAssistant();
88         return (cn != null) ? cn.flattenToString() : "";
89     }
90 
91     @Override
setDefaultKey(String key)92     protected boolean setDefaultKey(String key) {
93         return mNotificationBackend.setNotificationAssistantGranted(
94                 ComponentName.unflattenFromString(key));
95     }
96 
97     @Override
getMetricsCategory()98     public int getMetricsCategory() {
99         return SettingsEnums.DEFAULT_NOTIFICATION_ASSISTANT;
100     }
101 
102     @Override
getConfirmationMessage(CandidateInfo info)103     protected CharSequence getConfirmationMessage(CandidateInfo info) {
104         if (TextUtils.isEmpty(info.getKey())) {
105             return null;
106         }
107         return mContext.getString(R.string.notification_assistant_security_warning_summary,
108                 info.loadLabel());
109     }
110 
111     @Override
onServicesReloaded(List<ServiceInfo> services)112     public void onServicesReloaded(List<ServiceInfo> services) {
113         List<CandidateInfo> list = new ArrayList<>();
114         services.sort(new PackageItemInfo.DisplayNameComparator(mPm));
115         for (ServiceInfo service : services) {
116             if (mContext.getPackageManager().checkPermission(
117                     android.Manifest.permission.REQUEST_NOTIFICATION_ASSISTANT_SERVICE,
118                     service.packageName) == PackageManager.PERMISSION_GRANTED) {
119                 final ComponentName cn = new ComponentName(service.packageName, service.name);
120                 list.add(new DefaultAppInfo(mContext, mPm, mUserId, cn));
121             }
122         }
123         list.add(new CandidateNone(mContext));
124         mCandidateInfos = list;
125     }
126 
127     public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
128             new BaseSearchIndexProvider(R.xml.notification_assistant_settings);
129 
130     public static class CandidateNone extends CandidateInfo {
131 
132         public Context mContext;
133 
CandidateNone(Context context)134         public CandidateNone(Context context) {
135             super(true);
136             mContext = context;
137         }
138 
139         @Override
loadLabel()140         public CharSequence loadLabel() {
141             return mContext.getString(R.string.no_notification_assistant);
142         }
143 
144         @Override
loadIcon()145         public Drawable loadIcon() {
146             return null;
147         }
148 
149         @Override
getKey()150         public String getKey() {
151             return "";
152         }
153     }
154 }
155