1 /*
2  * Copyright (C) 2021 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.server.notification;
18 
19 import android.companion.ICompanionDeviceManager;
20 import android.content.ComponentName;
21 import android.content.Context;
22 import android.service.notification.StatusBarNotification;
23 
24 import androidx.annotation.Nullable;
25 
26 import com.android.internal.logging.InstanceIdSequence;
27 import com.android.server.notification.ManagedServices.ManagedServiceInfo;
28 
29 import java.util.HashSet;
30 import java.util.Set;
31 
32 public class TestableNotificationManagerService extends NotificationManagerService {
33     int countSystemChecks = 0;
34     boolean isSystemUid = true;
35     boolean isSystemAppId = true;
36     int countLogSmartSuggestionsVisible = 0;
37     Set<Integer> mChannelToastsSent = new HashSet<>();
38 
39     String stringArrayResourceValue;
40     @Nullable
41     NotificationAssistantAccessGrantedCallback mNotificationAssistantAccessGrantedCallback;
42 
43     @Nullable
44     Boolean mIsVisibleToListenerReturnValue = null;
45 
46     ComponentPermissionChecker permissionChecker;
47 
TestableNotificationManagerService(Context context, NotificationRecordLogger logger, InstanceIdSequence notificationInstanceIdSequence)48     TestableNotificationManagerService(Context context, NotificationRecordLogger logger,
49             InstanceIdSequence notificationInstanceIdSequence) {
50         super(context, logger, notificationInstanceIdSequence);
51     }
52 
getRankingHelper()53     RankingHelper getRankingHelper() {
54         return mRankingHelper;
55     }
56 
57     @Override
isCallingUidSystem()58     protected boolean isCallingUidSystem() {
59         countSystemChecks++;
60         return isSystemUid;
61     }
62 
63     @Override
isCallingAppIdSystem()64     protected boolean isCallingAppIdSystem() {
65         countSystemChecks++;
66         return isSystemUid || isSystemAppId;
67     }
68 
69     @Override
isCallerSystemOrPhone()70     protected boolean isCallerSystemOrPhone() {
71         countSystemChecks++;
72         return isSystemUid || isSystemAppId;
73     }
74 
75     @Override
isCallerIsSystemOrSystemUi()76     protected boolean isCallerIsSystemOrSystemUi() {
77         countSystemChecks++;
78         return isSystemUid || isSystemAppId;
79     }
80 
81     @Override
getCompanionManager()82     protected ICompanionDeviceManager getCompanionManager() {
83         return null;
84     }
85 
86     @Override
reportUserInteraction(NotificationRecord r)87     protected void reportUserInteraction(NotificationRecord r) {
88         return;
89     }
90 
91     @Override
handleSavePolicyFile()92     protected void handleSavePolicyFile() {
93         return;
94     }
95 
96     @Override
logSmartSuggestionsVisible(NotificationRecord r, int notificationLocation)97     void logSmartSuggestionsVisible(NotificationRecord r, int notificationLocation) {
98         super.logSmartSuggestionsVisible(r, notificationLocation);
99         countLogSmartSuggestionsVisible++;
100     }
101 
102     @Override
setNotificationAssistantAccessGrantedForUserInternal( ComponentName assistant, int userId, boolean granted, boolean userSet)103     protected void setNotificationAssistantAccessGrantedForUserInternal(
104             ComponentName assistant, int userId, boolean granted, boolean userSet) {
105         if (mNotificationAssistantAccessGrantedCallback != null) {
106             mNotificationAssistantAccessGrantedCallback.onGranted(assistant, userId, granted,
107                     userSet);
108             return;
109         }
110         super.setNotificationAssistantAccessGrantedForUserInternal(assistant, userId, granted,
111                 userSet);
112     }
113 
114     @Override
getStringArrayResource(int key)115     protected String[] getStringArrayResource(int key) {
116         return new String[] {stringArrayResourceValue};
117     }
118 
setStringArrayResourceValue(String value)119     protected void setStringArrayResourceValue(String value) {
120         stringArrayResourceValue = value;
121     }
122 
setNotificationAssistantAccessGrantedCallback( @ullable NotificationAssistantAccessGrantedCallback callback)123     void setNotificationAssistantAccessGrantedCallback(
124             @Nullable NotificationAssistantAccessGrantedCallback callback) {
125         this.mNotificationAssistantAccessGrantedCallback = callback;
126     }
127 
128     interface NotificationAssistantAccessGrantedCallback {
onGranted(ComponentName assistant, int userId, boolean granted, boolean userSet)129         void onGranted(ComponentName assistant, int userId, boolean granted, boolean userSet);
130     }
131 
132     @Override
doChannelWarningToast(int uid, CharSequence toastText)133     protected void doChannelWarningToast(int uid, CharSequence toastText) {
134         mChannelToastsSent.add(uid);
135     }
136 
137     // Helper method for testing behavior when turning on/off the review permissions notification.
setShowReviewPermissionsNotification(boolean setting)138     protected void setShowReviewPermissionsNotification(boolean setting) {
139         mShowReviewPermissionsNotification = setting;
140     }
141 
setIsVisibleToListenerReturnValue(boolean value)142     protected void setIsVisibleToListenerReturnValue(boolean value) {
143         mIsVisibleToListenerReturnValue = value;
144     }
145 
146     @Override
isVisibleToListener(StatusBarNotification sbn, int notificationType, ManagedServiceInfo listener)147     boolean isVisibleToListener(StatusBarNotification sbn, int notificationType,
148             ManagedServiceInfo listener) {
149         if (mIsVisibleToListenerReturnValue != null) {
150             return mIsVisibleToListenerReturnValue;
151         }
152         return super.isVisibleToListener(sbn, notificationType, listener);
153     }
154 
155     @Override
checkComponentPermission(String permission, int uid, int owningUid, boolean exported)156     protected int checkComponentPermission(String permission, int uid, int owningUid,
157             boolean exported) {
158         return permissionChecker.check(permission, uid, owningUid, exported);
159     }
160 
161     public class StrongAuthTrackerFake extends NotificationManagerService.StrongAuthTracker {
162         private int mGetStrongAuthForUserReturnValue = 0;
StrongAuthTrackerFake(Context context)163         StrongAuthTrackerFake(Context context) {
164             super(context);
165         }
166 
setGetStrongAuthForUserReturnValue(int val)167         public void setGetStrongAuthForUserReturnValue(int val) {
168             mGetStrongAuthForUserReturnValue = val;
169         }
170 
171         @Override
getStrongAuthForUser(int userId)172         public int getStrongAuthForUser(int userId) {
173             return mGetStrongAuthForUserReturnValue;
174         }
175     }
176 
177     public interface ComponentPermissionChecker {
check(String permission, int uid, int owningUid, boolean exported)178         int check(String permission, int uid, int owningUid, boolean exported);
179     }
180 }
181