• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 static android.app.NotificationManager.IMPORTANCE_DEFAULT;
20 
21 import android.companion.ICompanionDeviceManager;
22 import android.content.ComponentName;
23 import android.content.Context;
24 import android.service.notification.StatusBarNotification;
25 
26 import androidx.annotation.Nullable;
27 
28 import com.android.internal.logging.InstanceIdSequence;
29 import com.android.server.notification.ManagedServices.ManagedServiceInfo;
30 import com.android.server.notification.NotificationRecordLogger.NotificationReportedEvent;
31 
32 import java.util.HashSet;
33 import java.util.Set;
34 
35 public class TestableNotificationManagerService extends NotificationManagerService {
36     int countSystemChecks = 0;
37     boolean isSystemUid = true;
38     boolean isSystemAppId = true;
39     int countLogSmartSuggestionsVisible = 0;
40     Set<Integer> mChannelToastsSent = new HashSet<>();
41 
42     String stringArrayResourceValue;
43     @Nullable
44     NotificationAssistantAccessGrantedCallback mNotificationAssistantAccessGrantedCallback;
45 
46     @Nullable
47     Boolean mIsVisibleToListenerReturnValue = null;
48 
49     ComponentPermissionChecker permissionChecker;
50 
51     private static class SensitiveLog {
52         public boolean hasPosted;
53         public boolean hasSensitiveContent;
54         public long lifetime;
55     }
56     public SensitiveLog lastSensitiveLog = null;
57 
58     private static class ClassificationChannelLog {
59         public boolean hasPosted;
60         public boolean isAlerting;
61         public long classification;
62         public long lifetime;
63         public long eventId;
64         public long instanceId;
65         public long uid;
66     }
67     public ClassificationChannelLog  lastClassificationChannelLog = null;
68 
TestableNotificationManagerService(Context context, NotificationRecordLogger logger, InstanceIdSequence notificationInstanceIdSequence)69     TestableNotificationManagerService(Context context, NotificationRecordLogger logger,
70             InstanceIdSequence notificationInstanceIdSequence) {
71         super(context, logger, notificationInstanceIdSequence);
72     }
73 
getRankingHelper()74     RankingHelper getRankingHelper() {
75         return mRankingHelper;
76     }
77 
78     /**
79      * Sets {@link #isSystemUid} and {@link #isSystemAppId} to {@code false}, so that calls to NMS
80      * methods don't succeed {@link #isCallingUidSystem()} and similar checks.
81      */
setCallerIsNormalPackage()82     void setCallerIsNormalPackage() {
83         isSystemUid = false;
84         isSystemAppId = false;
85     }
86 
87     @Override
isCallingUidSystem()88     protected boolean isCallingUidSystem() {
89         countSystemChecks++;
90         return isSystemUid;
91     }
92 
93     @Override
isCallingAppIdSystem()94     protected boolean isCallingAppIdSystem() {
95         countSystemChecks++;
96         return isSystemUid || isSystemAppId;
97     }
98 
99     @Override
isCallerSystemOrPhone()100     protected boolean isCallerSystemOrPhone() {
101         countSystemChecks++;
102         return isSystemUid || isSystemAppId;
103     }
104 
105     @Override
isCallerSystemOrSystemUi()106     protected boolean isCallerSystemOrSystemUi() {
107         countSystemChecks++;
108         return isSystemUid || isSystemAppId;
109     }
110 
111     @Override
getCompanionManager()112     protected ICompanionDeviceManager getCompanionManager() {
113         return null;
114     }
115 
116     @Override
reportUserInteraction(NotificationRecord r)117     protected void reportUserInteraction(NotificationRecord r) {
118         return;
119     }
120 
121     @Override
handleSavePolicyFile()122     protected void handleSavePolicyFile() {
123         return;
124     }
125 
126     @Override
logSmartSuggestionsVisible(NotificationRecord r, int notificationLocation)127     void logSmartSuggestionsVisible(NotificationRecord r, int notificationLocation) {
128         super.logSmartSuggestionsVisible(r, notificationLocation);
129         countLogSmartSuggestionsVisible++;
130     }
131 
132     @Override
setNotificationAssistantAccessGrantedForUserInternal( ComponentName assistant, int userId, boolean granted, boolean userSet)133     protected void setNotificationAssistantAccessGrantedForUserInternal(
134             ComponentName assistant, int userId, boolean granted, boolean userSet) {
135         if (mNotificationAssistantAccessGrantedCallback != null) {
136             mNotificationAssistantAccessGrantedCallback.onGranted(assistant, userId, granted,
137                     userSet);
138             return;
139         }
140         super.setNotificationAssistantAccessGrantedForUserInternal(assistant, userId, granted,
141                 userSet);
142     }
143 
144     @Override
getStringArrayResource(int key)145     protected String[] getStringArrayResource(int key) {
146         return new String[] {stringArrayResourceValue};
147     }
148 
setStringArrayResourceValue(String value)149     protected void setStringArrayResourceValue(String value) {
150         stringArrayResourceValue = value;
151     }
152 
setNotificationAssistantAccessGrantedCallback( @ullable NotificationAssistantAccessGrantedCallback callback)153     void setNotificationAssistantAccessGrantedCallback(
154             @Nullable NotificationAssistantAccessGrantedCallback callback) {
155         this.mNotificationAssistantAccessGrantedCallback = callback;
156     }
157 
158     interface NotificationAssistantAccessGrantedCallback {
onGranted(ComponentName assistant, int userId, boolean granted, boolean userSet)159         void onGranted(ComponentName assistant, int userId, boolean granted, boolean userSet);
160     }
161 
162     @Override
doChannelWarningToast(int uid, CharSequence toastText)163     protected void doChannelWarningToast(int uid, CharSequence toastText) {
164         mChannelToastsSent.add(uid);
165     }
166 
167     // Helper method for testing behavior when turning on/off the review permissions notification.
setShowReviewPermissionsNotification(boolean setting)168     protected void setShowReviewPermissionsNotification(boolean setting) {
169         mShowReviewPermissionsNotification = setting;
170     }
171 
setIsVisibleToListenerReturnValue(boolean value)172     protected void setIsVisibleToListenerReturnValue(boolean value) {
173         mIsVisibleToListenerReturnValue = value;
174     }
175 
176     @Override
isVisibleToListener(StatusBarNotification sbn, int notificationType, ManagedServiceInfo listener)177     boolean isVisibleToListener(StatusBarNotification sbn, int notificationType,
178             ManagedServiceInfo listener) {
179         if (mIsVisibleToListenerReturnValue != null) {
180             return mIsVisibleToListenerReturnValue;
181         }
182         return super.isVisibleToListener(sbn, notificationType, listener);
183     }
184 
185     @Override
checkComponentPermission(String permission, int uid, int owningUid, boolean exported)186     protected int checkComponentPermission(String permission, int uid, int owningUid,
187             boolean exported) {
188         return permissionChecker.check(permission, uid, owningUid, exported);
189     }
190 
191     @Override
logSensitiveAdjustmentReceived(boolean hasPosted, boolean hasSensitiveContent, int lifetimeMs)192     protected void logSensitiveAdjustmentReceived(boolean hasPosted, boolean hasSensitiveContent,
193             int lifetimeMs) {
194         lastSensitiveLog = new SensitiveLog();
195         lastSensitiveLog.hasPosted = hasPosted;
196         lastSensitiveLog.hasSensitiveContent = hasSensitiveContent;
197         lastSensitiveLog.lifetime = lifetimeMs;
198     }
199 
200     public class StrongAuthTrackerFake extends NotificationManagerService.StrongAuthTracker {
201         private int mGetStrongAuthForUserReturnValue = 0;
StrongAuthTrackerFake(Context context)202         StrongAuthTrackerFake(Context context) {
203             super(context);
204         }
205 
setGetStrongAuthForUserReturnValue(int val)206         public void setGetStrongAuthForUserReturnValue(int val) {
207             mGetStrongAuthForUserReturnValue = val;
208         }
209 
210         @Override
getStrongAuthForUser(int userId)211         public int getStrongAuthForUser(int userId) {
212             return mGetStrongAuthForUserReturnValue;
213         }
214     }
215 
checkLastSensitiveLog(boolean hasPosted, boolean hasSensitive, int lifetime)216     public boolean checkLastSensitiveLog(boolean hasPosted, boolean hasSensitive, int lifetime) {
217         if (lastSensitiveLog == null) {
218             return false;
219         }
220         return hasPosted == lastSensitiveLog.hasPosted
221                 && hasSensitive == lastSensitiveLog.hasSensitiveContent
222                 && lifetime == lastSensitiveLog.lifetime;
223     }
224 
225     public interface ComponentPermissionChecker {
check(String permission, int uid, int owningUid, boolean exported)226         int check(String permission, int uid, int owningUid, boolean exported);
227     }
228 
229     @Override
logClassificationChannelAdjustmentReceived(NotificationRecord r, boolean hasPosted, int classification)230     protected void logClassificationChannelAdjustmentReceived(NotificationRecord r,
231                                                               boolean hasPosted,
232                                                               int classification) {
233 
234         boolean isAlerting = r.getChannel().getImportance() >= IMPORTANCE_DEFAULT;
235         int instanceId = r.getSbn().getInstanceId() == null
236                 ? 0 : r.getSbn().getInstanceId().getId();
237         int lifetimeMs = r.getLifespanMs(System.currentTimeMillis());
238         int uid = r.getUid();
239 
240         lastClassificationChannelLog = new ClassificationChannelLog();
241         lastClassificationChannelLog.hasPosted = hasPosted;
242         lastClassificationChannelLog.isAlerting = isAlerting;
243         lastClassificationChannelLog.classification = classification;
244         lastClassificationChannelLog.lifetime = lifetimeMs;
245         lastClassificationChannelLog.eventId =
246                 NotificationReportedEvent.NOTIFICATION_ADJUSTED.getId();
247         lastClassificationChannelLog.instanceId = instanceId;
248         lastClassificationChannelLog.uid = uid;
249     }
250 
251     /**
252      * Returns true if the last recorded classification channel log has all the values specified.
253      */
checkLastClassificationChannelLog(boolean hasPosted, boolean isAlerting, int classification, int lifetime, int eventId, int instanceId, int uid)254     public boolean checkLastClassificationChannelLog(boolean hasPosted, boolean isAlerting,
255                                                      int classification, int lifetime,
256                                                      int eventId, int instanceId,
257                                                      int uid) {
258         if (lastClassificationChannelLog == null) {
259             return false;
260         }
261 
262         return hasPosted == lastClassificationChannelLog.hasPosted
263                 && isAlerting == lastClassificationChannelLog.isAlerting
264                 && classification == lastClassificationChannelLog.classification
265                 && lifetime == lastClassificationChannelLog.lifetime
266                 && eventId == lastClassificationChannelLog.eventId
267                 && instanceId == lastClassificationChannelLog.instanceId
268                 && uid == lastClassificationChannelLog.uid;
269     }
270 }
271