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 48 private static class SensitiveLog { 49 public boolean hasPosted; 50 public boolean hasSensitiveContent; 51 public long lifetime; 52 } 53 public SensitiveLog lastSensitiveLog = null; 54 TestableNotificationManagerService(Context context, NotificationRecordLogger logger, InstanceIdSequence notificationInstanceIdSequence)55 TestableNotificationManagerService(Context context, NotificationRecordLogger logger, 56 InstanceIdSequence notificationInstanceIdSequence) { 57 super(context, logger, notificationInstanceIdSequence); 58 } 59 getRankingHelper()60 RankingHelper getRankingHelper() { 61 return mRankingHelper; 62 } 63 64 /** 65 * Sets {@link #isSystemUid} and {@link #isSystemAppId} to {@code false}, so that calls to NMS 66 * methods don't succeed {@link #isCallingUidSystem()} and similar checks. 67 */ setCallerIsNormalPackage()68 void setCallerIsNormalPackage() { 69 isSystemUid = false; 70 isSystemAppId = false; 71 } 72 73 @Override isCallingUidSystem()74 protected boolean isCallingUidSystem() { 75 countSystemChecks++; 76 return isSystemUid; 77 } 78 79 @Override isCallingAppIdSystem()80 protected boolean isCallingAppIdSystem() { 81 countSystemChecks++; 82 return isSystemUid || isSystemAppId; 83 } 84 85 @Override isCallerSystemOrPhone()86 protected boolean isCallerSystemOrPhone() { 87 countSystemChecks++; 88 return isSystemUid || isSystemAppId; 89 } 90 91 @Override isCallerSystemOrSystemUi()92 protected boolean isCallerSystemOrSystemUi() { 93 countSystemChecks++; 94 return isSystemUid || isSystemAppId; 95 } 96 97 @Override getCompanionManager()98 protected ICompanionDeviceManager getCompanionManager() { 99 return null; 100 } 101 102 @Override reportUserInteraction(NotificationRecord r)103 protected void reportUserInteraction(NotificationRecord r) { 104 return; 105 } 106 107 @Override handleSavePolicyFile()108 protected void handleSavePolicyFile() { 109 return; 110 } 111 112 @Override logSmartSuggestionsVisible(NotificationRecord r, int notificationLocation)113 void logSmartSuggestionsVisible(NotificationRecord r, int notificationLocation) { 114 super.logSmartSuggestionsVisible(r, notificationLocation); 115 countLogSmartSuggestionsVisible++; 116 } 117 118 @Override setNotificationAssistantAccessGrantedForUserInternal( ComponentName assistant, int userId, boolean granted, boolean userSet)119 protected void setNotificationAssistantAccessGrantedForUserInternal( 120 ComponentName assistant, int userId, boolean granted, boolean userSet) { 121 if (mNotificationAssistantAccessGrantedCallback != null) { 122 mNotificationAssistantAccessGrantedCallback.onGranted(assistant, userId, granted, 123 userSet); 124 return; 125 } 126 super.setNotificationAssistantAccessGrantedForUserInternal(assistant, userId, granted, 127 userSet); 128 } 129 130 @Override getStringArrayResource(int key)131 protected String[] getStringArrayResource(int key) { 132 return new String[] {stringArrayResourceValue}; 133 } 134 setStringArrayResourceValue(String value)135 protected void setStringArrayResourceValue(String value) { 136 stringArrayResourceValue = value; 137 } 138 setNotificationAssistantAccessGrantedCallback( @ullable NotificationAssistantAccessGrantedCallback callback)139 void setNotificationAssistantAccessGrantedCallback( 140 @Nullable NotificationAssistantAccessGrantedCallback callback) { 141 this.mNotificationAssistantAccessGrantedCallback = callback; 142 } 143 144 interface NotificationAssistantAccessGrantedCallback { onGranted(ComponentName assistant, int userId, boolean granted, boolean userSet)145 void onGranted(ComponentName assistant, int userId, boolean granted, boolean userSet); 146 } 147 148 @Override doChannelWarningToast(int uid, CharSequence toastText)149 protected void doChannelWarningToast(int uid, CharSequence toastText) { 150 mChannelToastsSent.add(uid); 151 } 152 153 // Helper method for testing behavior when turning on/off the review permissions notification. setShowReviewPermissionsNotification(boolean setting)154 protected void setShowReviewPermissionsNotification(boolean setting) { 155 mShowReviewPermissionsNotification = setting; 156 } 157 setIsVisibleToListenerReturnValue(boolean value)158 protected void setIsVisibleToListenerReturnValue(boolean value) { 159 mIsVisibleToListenerReturnValue = value; 160 } 161 162 @Override isVisibleToListener(StatusBarNotification sbn, int notificationType, ManagedServiceInfo listener)163 boolean isVisibleToListener(StatusBarNotification sbn, int notificationType, 164 ManagedServiceInfo listener) { 165 if (mIsVisibleToListenerReturnValue != null) { 166 return mIsVisibleToListenerReturnValue; 167 } 168 return super.isVisibleToListener(sbn, notificationType, listener); 169 } 170 171 @Override checkComponentPermission(String permission, int uid, int owningUid, boolean exported)172 protected int checkComponentPermission(String permission, int uid, int owningUid, 173 boolean exported) { 174 return permissionChecker.check(permission, uid, owningUid, exported); 175 } 176 177 @Override logSensitiveAdjustmentReceived(boolean hasPosted, boolean hasSensitiveContent, int lifetimeMs)178 protected void logSensitiveAdjustmentReceived(boolean hasPosted, boolean hasSensitiveContent, 179 int lifetimeMs) { 180 lastSensitiveLog = new SensitiveLog(); 181 lastSensitiveLog.hasPosted = hasPosted; 182 lastSensitiveLog.hasSensitiveContent = hasSensitiveContent; 183 lastSensitiveLog.lifetime = lifetimeMs; 184 } 185 186 public class StrongAuthTrackerFake extends NotificationManagerService.StrongAuthTracker { 187 private int mGetStrongAuthForUserReturnValue = 0; StrongAuthTrackerFake(Context context)188 StrongAuthTrackerFake(Context context) { 189 super(context); 190 } 191 setGetStrongAuthForUserReturnValue(int val)192 public void setGetStrongAuthForUserReturnValue(int val) { 193 mGetStrongAuthForUserReturnValue = val; 194 } 195 196 @Override getStrongAuthForUser(int userId)197 public int getStrongAuthForUser(int userId) { 198 return mGetStrongAuthForUserReturnValue; 199 } 200 } 201 checkLastSensitiveLog(boolean hasPosted, boolean hasSensitive, int lifetime)202 public boolean checkLastSensitiveLog(boolean hasPosted, boolean hasSensitive, int lifetime) { 203 if (lastSensitiveLog == null) { 204 return false; 205 } 206 return hasPosted == lastSensitiveLog.hasPosted 207 && hasSensitive == lastSensitiveLog.hasSensitiveContent 208 && lifetime == lastSensitiveLog.lifetime; 209 } 210 211 public interface ComponentPermissionChecker { check(String permission, int uid, int owningUid, boolean exported)212 int check(String permission, int uid, int owningUid, boolean exported); 213 } 214 } 215