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.role.controller.util; 18 19 import android.app.NotificationManager; 20 import android.content.ComponentName; 21 import android.content.Context; 22 import android.content.Intent; 23 import android.content.pm.PackageManager; 24 import android.content.pm.ResolveInfo; 25 import android.content.pm.ServiceInfo; 26 import android.os.UserHandle; 27 import android.service.notification.NotificationListenerService; 28 import android.util.Log; 29 30 import androidx.annotation.NonNull; 31 32 import java.util.ArrayList; 33 import java.util.List; 34 import java.util.Objects; 35 36 /** 37 * Utility methods about Notification permissions. 38 */ 39 public final class NotificationUtils { 40 41 public static final String LOG_TAG = NotificationUtils.class.getSimpleName(); 42 NotificationUtils()43 private NotificationUtils() {} 44 45 /** 46 * Grants the NotificationListener access. 47 * 48 * @param packageName the package name implements the NotificationListener 49 * @param user the user of the component 50 * @param context the {@code Context} to retrieve system services 51 */ grantNotificationAccessForPackageAsUser(@onNull String packageName, @NonNull UserHandle user, @NonNull Context context)52 public static void grantNotificationAccessForPackageAsUser(@NonNull String packageName, 53 @NonNull UserHandle user, @NonNull Context context) { 54 setNotificationGrantStateForPackageAsUser(packageName, true, user, context); 55 } 56 57 /** 58 * Revokes the NotificationListener access. 59 * 60 * @param packageName the package name implements the NotificationListener 61 * @param user the user of the component 62 * @param context the {@code Context} to retrieve system services 63 */ revokeNotificationAccessForPackageAsUser(@onNull String packageName, @NonNull UserHandle user, @NonNull Context context)64 public static void revokeNotificationAccessForPackageAsUser(@NonNull String packageName, 65 @NonNull UserHandle user, @NonNull Context context) { 66 setNotificationGrantStateForPackageAsUser(packageName, false, user, context); 67 } 68 69 setNotificationGrantStateForPackageAsUser(@onNull String packageName, boolean granted, @NonNull UserHandle user, @NonNull Context context)70 private static void setNotificationGrantStateForPackageAsUser(@NonNull String packageName, 71 boolean granted, @NonNull UserHandle user, @NonNull Context context) { 72 List<ComponentName> notificationListenersForPackage = 73 getNotificationListenersForPackageAsUser(packageName, user, context); 74 Context userContext = UserUtils.getUserContext(context, user); 75 NotificationManager userNotificationManager = 76 userContext.getSystemService(NotificationManager.class); 77 for (ComponentName componentName : notificationListenersForPackage) { 78 userNotificationManager.setNotificationListenerAccessGranted( 79 componentName, granted, false); 80 } 81 } 82 getNotificationListenersForPackageAsUser( @onNull String packageName, @NonNull UserHandle user, @NonNull Context context)83 private static List<ComponentName> getNotificationListenersForPackageAsUser( 84 @NonNull String packageName, @NonNull UserHandle user, @NonNull Context context) { 85 Context userContext = UserUtils.getUserContext(context, user); 86 List<ResolveInfo> allListeners = userContext.getPackageManager().queryIntentServices( 87 new Intent(NotificationListenerService.SERVICE_INTERFACE).setPackage(packageName), 88 PackageManager.MATCH_DIRECT_BOOT_AWARE | PackageManager.MATCH_DIRECT_BOOT_UNAWARE); 89 ArrayList<ComponentName> pkgListeners = new ArrayList<>(); 90 for (ResolveInfo service : allListeners) { 91 ServiceInfo serviceInfo = service.serviceInfo; 92 if (Objects.equals(serviceInfo.permission, 93 android.Manifest.permission.BIND_NOTIFICATION_LISTENER_SERVICE) 94 && packageName.equals(serviceInfo.packageName)) { 95 pkgListeners.add(new ComponentName(serviceInfo.packageName, serviceInfo.name)); 96 } 97 } 98 Log.d(LOG_TAG, "getNotificationListenersForPackage(" + packageName + "): " + pkgListeners); 99 return pkgListeners; 100 } 101 102 } 103