1 /*
2  * Copyright (C) 2017 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.internal.util;
18 
19 import android.annotation.Nullable;
20 import android.app.Notification;
21 import android.app.NotificationManager;
22 import android.content.Context;
23 import android.database.ContentObserver;
24 import android.net.Uri;
25 import android.os.Handler;
26 import android.os.Looper;
27 import android.os.UserHandle;
28 import android.provider.Settings;
29 import android.service.notification.StatusBarNotification;
30 import android.util.SparseArray;
31 
32 import java.util.Collection;
33 import java.util.Objects;
34 
35 /**
36  * A util to look up messaging related functions for notifications. This is used for both the
37  * ranking and the actual layout.
38  */
39 public class NotificationMessagingUtil {
40 
41     private static final String DEFAULT_SMS_APP_SETTING = Settings.Secure.SMS_DEFAULT_APPLICATION;
42     private final Context mContext;
43     private final SparseArray<String> mDefaultSmsApp = new SparseArray<>();
44     private final Object mStateLock;
45 
NotificationMessagingUtil(Context context, @Nullable Object stateLock)46     public NotificationMessagingUtil(Context context, @Nullable Object stateLock) {
47         mContext = context;
48         mStateLock = stateLock != null ? stateLock : new Object();
49         mContext.getContentResolver().registerContentObserver(
50                 Settings.Secure.getUriFor(DEFAULT_SMS_APP_SETTING), false, mSmsContentObserver);
51     }
52 
isImportantMessaging(StatusBarNotification sbn, int importance)53     public boolean isImportantMessaging(StatusBarNotification sbn, int importance) {
54         if (importance < NotificationManager.IMPORTANCE_LOW) {
55             return false;
56         }
57 
58         return hasMessagingStyle(sbn) || (isCategoryMessage(sbn) && isDefaultMessagingApp(sbn));
59     }
60 
isMessaging(StatusBarNotification sbn)61     public boolean isMessaging(StatusBarNotification sbn) {
62         return hasMessagingStyle(sbn) || isDefaultMessagingApp(sbn) || isCategoryMessage(sbn);
63     }
64 
65     @SuppressWarnings("deprecation")
isDefaultMessagingApp(StatusBarNotification sbn)66     private boolean isDefaultMessagingApp(StatusBarNotification sbn) {
67         final int userId = sbn.getUserId();
68         if (userId == UserHandle.USER_NULL || userId == UserHandle.USER_ALL) return false;
69         synchronized (mStateLock) {
70             if (mDefaultSmsApp.get(userId) == null) {
71                 cacheDefaultSmsApp(userId);
72             }
73             return Objects.equals(mDefaultSmsApp.get(userId), sbn.getPackageName());
74         }
75     }
76 
cacheDefaultSmsApp(int userId)77     private void cacheDefaultSmsApp(int userId) {
78         String smsApp = Settings.Secure.getStringForUser(mContext.getContentResolver(),
79                 Settings.Secure.SMS_DEFAULT_APPLICATION, userId);
80         synchronized (mStateLock) {
81             mDefaultSmsApp.put(userId, smsApp);
82         }
83     }
84 
85     private final ContentObserver mSmsContentObserver = new ContentObserver(
86             new Handler(Looper.getMainLooper())) {
87         @Override
88         public void onChange(boolean selfChange, Collection<Uri> uris, int flags, int userId) {
89             if (uris.contains(Settings.Secure.getUriFor(DEFAULT_SMS_APP_SETTING))) {
90                 cacheDefaultSmsApp(userId);
91             }
92         }
93     };
94 
hasMessagingStyle(StatusBarNotification sbn)95     private boolean hasMessagingStyle(StatusBarNotification sbn) {
96         return sbn.getNotification().isStyle(Notification.MessagingStyle.class);
97     }
98 
isCategoryMessage(StatusBarNotification sbn)99     private boolean isCategoryMessage(StatusBarNotification sbn) {
100         return Notification.CATEGORY_MESSAGE.equals(sbn.getNotification().category);
101     }
102 }
103