1 /*
2  * Copyright (C) 2023 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.settings.localepicker;
18 
19 import static com.google.common.truth.Truth.assertThat;
20 
21 import android.content.Context;
22 import android.os.LocaleList;
23 import android.os.SystemClock;
24 
25 import org.junit.After;
26 import org.junit.Before;
27 import org.junit.Test;
28 import org.junit.runner.RunWith;
29 import org.mockito.MockitoAnnotations;
30 import org.robolectric.RobolectricTestRunner;
31 import org.robolectric.RuntimeEnvironment;
32 
33 import java.util.Calendar;
34 import java.util.Set;
35 
36 @RunWith(RobolectricTestRunner.class)
37 public class NotificationControllerTest {
38     private Context mContext;
39     private LocaleNotificationDataManager mDataManager;
40     private NotificationController mNotificationController;
41 
42     @Before
setUp()43     public void setUp() throws Exception {
44         MockitoAnnotations.initMocks(this);
45         mContext = RuntimeEnvironment.application;
46         mNotificationController = NotificationController.getInstance(mContext);
47         mDataManager = mNotificationController.getDataManager();
48         LocaleList.setDefault(LocaleList.forLanguageTags("en-CA"));
49     }
50 
51     @After
tearDown()52     public void tearDown() {
53         mDataManager.clearLocaleNotificationMap();
54     }
55 
56     @Test
incrementDismissCount_addOne()57     public void incrementDismissCount_addOne() throws Exception {
58         String enUS = "en-US";
59         Set<Integer> uidSet = Set.of(100, 101);
60         long lastNotificationTime = Calendar.getInstance().getTimeInMillis();
61         int id = (int) SystemClock.uptimeMillis();
62         initSharedPreference(enUS, uidSet, 0, 1, lastNotificationTime, id);
63 
64         mNotificationController.incrementDismissCount(enUS);
65         NotificationInfo result = mDataManager.getNotificationInfo(enUS);
66 
67         assertThat(result.getDismissCount()).isEqualTo(1); // dismissCount increments
68         assertThat(result.getUidCollection()).isEqualTo(uidSet);
69         assertThat(result.getNotificationCount()).isEqualTo(1);
70         assertThat(result.getLastNotificationTimeMs()).isEqualTo(lastNotificationTime);
71         assertThat(result.getNotificationId()).isEqualTo(id);
72     }
73 
74     @Test
testRemoveNotificationInfo_removed()75     public void testRemoveNotificationInfo_removed() throws Exception {
76         String enUS = "en-US";
77         Set<Integer> uidSet = Set.of(100, 101);
78         long lastNotificationTime = Calendar.getInstance().getTimeInMillis();
79         int id = (int) SystemClock.uptimeMillis();
80         initSharedPreference(enUS, uidSet, 0, 1, lastNotificationTime, id);
81 
82         mNotificationController.removeNotificationInfo(enUS);
83 
84         assertThat(mDataManager.getNotificationInfo(enUS)).isNull();
85     }
86 
87     @Test
testShouldTriggerNotification_inSystemLocale_returnFalse()88     public void testShouldTriggerNotification_inSystemLocale_returnFalse() throws Exception {
89         int uid = 102;
90         // As checking whether app's locales exist in system locales, both app locales and system
91         // locales have to remove the u extension first when doing the comparison. The following
92         // three locales are all in the system locale after removing the u extension so it's
93         // unnecessary to trigger a notification for the suggestion.
94         String locale1 = "en-CA";
95         String locale2 = "ar-JO-u-nu-latn";
96         String locale3 = "ar-JO";
97 
98         LocaleList.setDefault(
99                 LocaleList.forLanguageTags("en-CA-u-mu-fahrenhe,ar-JO-u-mu-fahrenhe-nu-latn"));
100 
101         assertThat(mNotificationController.shouldTriggerNotification(uid, locale1)).isFalse();
102         assertThat(mNotificationController.shouldTriggerNotification(uid, locale2)).isFalse();
103         assertThat(mNotificationController.shouldTriggerNotification(uid, locale3)).isFalse();
104     }
105 
106     @Test
testShouldTriggerNotification_noNotification_returnFalse()107     public void testShouldTriggerNotification_noNotification_returnFalse() throws Exception {
108         int uid = 100;
109         String locale = "en-US";
110 
111         boolean triggered = mNotificationController.shouldTriggerNotification(uid, locale);
112 
113         assertThat(triggered).isFalse();
114     }
115 
116     @Test
testShouldTriggerNotification_return1stTrue()117     public void testShouldTriggerNotification_return1stTrue() throws Exception {
118         // Initialze proto with en-US locale. Its uid contains 100.
119         Set<Integer> uidSet = Set.of(100);
120         String locale = "en-US";
121         long lastNotificationTime = 0L;
122         int notificationId = 0;
123         initSharedPreference(locale, uidSet, 0, 1, lastNotificationTime, notificationId);
124 
125         // When the second app is configured to "en-US", the notification is triggered.
126         int uid = 101;
127         boolean triggered = mNotificationController.shouldTriggerNotification(uid, locale);
128 
129         assertThat(triggered).isTrue();
130     }
131 
132     @Test
testShouldTriggerNotification_returnFalse_dueToOddCount()133     public void testShouldTriggerNotification_returnFalse_dueToOddCount() throws Exception {
134         // Initialze proto with en-US locale. Its uid contains 100,101.
135         Set<Integer> uidSet = Set.of(100, 101);
136         String locale = "en-US";
137         long lastNotificationTime = Calendar.getInstance().getTimeInMillis();
138         int id = (int) SystemClock.uptimeMillis();
139         initSharedPreference(locale, uidSet, 0, 1, lastNotificationTime, id);
140 
141         // When the other app is configured to "en-US", the notification is not triggered because
142         // the app count is odd.
143         int uid = 102;
144         boolean triggered = mNotificationController.shouldTriggerNotification(uid, locale);
145 
146         assertThat(triggered).isFalse();
147     }
148 
149     @Test
testShouldTriggerNotification_returnFalse_dueToFrequency()150     public void testShouldTriggerNotification_returnFalse_dueToFrequency() throws Exception {
151         // Initialze proto with en-US locale. Its uid contains 100,101,102.
152         Set<Integer> uidSet = Set.of(100, 101, 102);
153         String locale = "en-US";
154         long lastNotificationTime = Calendar.getInstance().getTimeInMillis();
155         int id = (int) SystemClock.uptimeMillis();
156         initSharedPreference(locale, uidSet, 0, 1, lastNotificationTime, id);
157 
158         // When the other app is configured to "en-US", the notification is not triggered because it
159         // is too frequent.
160         int uid = 103;
161         boolean triggered = mNotificationController.shouldTriggerNotification(uid, locale);
162 
163         assertThat(triggered).isFalse();
164     }
165 
166     @Test
testShouldTriggerNotification_return2ndTrue()167     public void testShouldTriggerNotification_return2ndTrue() throws Exception {
168         // Initialze proto with en-US locale. Its uid contains 100,101,102,103,104.
169         Set<Integer> uidSet = Set.of(100, 101, 102, 103, 104);
170         String locale = "en-US";
171         int id = (int) SystemClock.uptimeMillis();
172         Calendar time = Calendar.getInstance();
173         time.add(Calendar.MINUTE, 86400 * 8 * (-1));
174         long lastNotificationTime = time.getTimeInMillis();
175         initSharedPreference(locale, uidSet, 0, 1, lastNotificationTime, id);
176 
177         // When the other app is configured to "en-US", the notification is triggered.
178         int uid = 105;
179         boolean triggered = mNotificationController.shouldTriggerNotification(uid, locale);
180 
181         assertThat(triggered).isTrue();
182     }
183 
initSharedPreference(String locale, Set<Integer> uidCollection, int dismissCount, int notificationCount, long lastNotificationTime, int notificationId)184     private void initSharedPreference(String locale, Set<Integer> uidCollection, int dismissCount,
185             int notificationCount, long lastNotificationTime, int notificationId)
186             throws Exception {
187         NotificationInfo info = new NotificationInfo(uidCollection, notificationCount, dismissCount,
188                 lastNotificationTime, notificationId);
189         mDataManager.putNotificationInfo(locale, info);
190     }
191 }
192