125b09db869f377b131052447f62ad02e2505cd87Michael Chan/*
225b09db869f377b131052447f62ad02e2505cd87Michael Chan * Copyright (C) 2012 The Android Open Source Project
325b09db869f377b131052447f62ad02e2505cd87Michael Chan *
425b09db869f377b131052447f62ad02e2505cd87Michael Chan * Licensed under the Apache License, Version 2.0 (the "License"); you may not
525b09db869f377b131052447f62ad02e2505cd87Michael Chan * use this file except in compliance with the License. You may obtain a copy of
625b09db869f377b131052447f62ad02e2505cd87Michael Chan * the License at
725b09db869f377b131052447f62ad02e2505cd87Michael Chan *
825b09db869f377b131052447f62ad02e2505cd87Michael Chan * http://www.apache.org/licenses/LICENSE-2.0
925b09db869f377b131052447f62ad02e2505cd87Michael Chan *
1025b09db869f377b131052447f62ad02e2505cd87Michael Chan * Unless required by applicable law or agreed to in writing, software
1125b09db869f377b131052447f62ad02e2505cd87Michael Chan * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
1225b09db869f377b131052447f62ad02e2505cd87Michael Chan * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
1325b09db869f377b131052447f62ad02e2505cd87Michael Chan * License for the specific language governing permissions and limitations under
1425b09db869f377b131052447f62ad02e2505cd87Michael Chan * the License.
1525b09db869f377b131052447f62ad02e2505cd87Michael Chan */
1625b09db869f377b131052447f62ad02e2505cd87Michael Chan
1725b09db869f377b131052447f62ad02e2505cd87Michael Chanpackage com.android.calendar.alerts;
1825b09db869f377b131052447f62ad02e2505cd87Michael Chan
1925b09db869f377b131052447f62ad02e2505cd87Michael Chanimport static android.app.Notification.PRIORITY_DEFAULT;
2025b09db869f377b131052447f62ad02e2505cd87Michael Chanimport static android.app.Notification.PRIORITY_HIGH;
2125b09db869f377b131052447f62ad02e2505cd87Michael Chanimport static android.app.Notification.PRIORITY_MIN;
2225b09db869f377b131052447f62ad02e2505cd87Michael Chan
23487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Tingimport android.app.AlarmManager;
2425b09db869f377b131052447f62ad02e2505cd87Michael Chanimport android.content.SharedPreferences;
2525b09db869f377b131052447f62ad02e2505cd87Michael Chanimport android.database.MatrixCursor;
2625b09db869f377b131052447f62ad02e2505cd87Michael Chanimport android.provider.CalendarContract.Attendees;
2725b09db869f377b131052447f62ad02e2505cd87Michael Chanimport android.provider.CalendarContract.CalendarAlerts;
2825b09db869f377b131052447f62ad02e2505cd87Michael Chanimport android.test.AndroidTestCase;
2925b09db869f377b131052447f62ad02e2505cd87Michael Chanimport android.test.suitebuilder.annotation.SmallTest;
3025b09db869f377b131052447f62ad02e2505cd87Michael Chanimport android.test.suitebuilder.annotation.Smoke;
31bce26a2a19499790595e48ca36b43eb130e4a3fbSara Tingimport android.text.format.DateUtils;
32bce26a2a19499790595e48ca36b43eb130e4a3fbSara Tingimport android.text.format.Time;
3325b09db869f377b131052447f62ad02e2505cd87Michael Chan
3425b09db869f377b131052447f62ad02e2505cd87Michael Chanimport com.android.calendar.GeneralPreferences;
3521af116207d5728a312e534b898933bb07f96292Sara Tingimport com.android.calendar.alerts.AlertService.NotificationInfo;
3625b09db869f377b131052447f62ad02e2505cd87Michael Chanimport com.android.calendar.alerts.AlertService.NotificationWrapper;
3725b09db869f377b131052447f62ad02e2505cd87Michael Chan
38b5a2a61208857805cc053c6ac476d30100289279Sara Tingimport junit.framework.Assert;
39b5a2a61208857805cc053c6ac476d30100289279Sara Ting
4025b09db869f377b131052447f62ad02e2505cd87Michael Chanimport java.util.ArrayList;
4125b09db869f377b131052447f62ad02e2505cd87Michael Chanimport java.util.Arrays;
4225b09db869f377b131052447f62ad02e2505cd87Michael Chanimport java.util.Map;
4325b09db869f377b131052447f62ad02e2505cd87Michael Chanimport java.util.Set;
4425b09db869f377b131052447f62ad02e2505cd87Michael Chan
4525b09db869f377b131052447f62ad02e2505cd87Michael Chanpublic class AlertServiceTest extends AndroidTestCase {
4625b09db869f377b131052447f62ad02e2505cd87Michael Chan
4725b09db869f377b131052447f62ad02e2505cd87Michael Chan    class MockSharedPreferences implements SharedPreferences {
4825b09db869f377b131052447f62ad02e2505cd87Michael Chan
498e93f66f4617f2f4cb3e2a1919988fdf401b51f4Michael Chan        private Boolean mVibrate;
50b5a2a61208857805cc053c6ac476d30100289279Sara Ting        private String mRingtone;
51b5a2a61208857805cc053c6ac476d30100289279Sara Ting        private Boolean mPopup;
52b5a2a61208857805cc053c6ac476d30100289279Sara Ting
53b5a2a61208857805cc053c6ac476d30100289279Sara Ting        // Strict mode will fail if a preference key is queried more than once.
54b5a2a61208857805cc053c6ac476d30100289279Sara Ting        private boolean mStrict = false;
55b5a2a61208857805cc053c6ac476d30100289279Sara Ting
56b5a2a61208857805cc053c6ac476d30100289279Sara Ting        MockSharedPreferences() {
57b5a2a61208857805cc053c6ac476d30100289279Sara Ting            this(false);
58b5a2a61208857805cc053c6ac476d30100289279Sara Ting        }
59b5a2a61208857805cc053c6ac476d30100289279Sara Ting
60b5a2a61208857805cc053c6ac476d30100289279Sara Ting        MockSharedPreferences(boolean strict) {
61b5a2a61208857805cc053c6ac476d30100289279Sara Ting            super();
62b5a2a61208857805cc053c6ac476d30100289279Sara Ting            init();
63b5a2a61208857805cc053c6ac476d30100289279Sara Ting            this.mStrict = strict;
64b5a2a61208857805cc053c6ac476d30100289279Sara Ting        }
65b5a2a61208857805cc053c6ac476d30100289279Sara Ting
66b5a2a61208857805cc053c6ac476d30100289279Sara Ting        void init() {
678e93f66f4617f2f4cb3e2a1919988fdf401b51f4Michael Chan            mVibrate = true;
68b5a2a61208857805cc053c6ac476d30100289279Sara Ting            mRingtone = "/some/cool/ringtone";
69b5a2a61208857805cc053c6ac476d30100289279Sara Ting            mPopup = true;
70b5a2a61208857805cc053c6ac476d30100289279Sara Ting        }
7125b09db869f377b131052447f62ad02e2505cd87Michael Chan
7225b09db869f377b131052447f62ad02e2505cd87Michael Chan        @Override
7325b09db869f377b131052447f62ad02e2505cd87Michael Chan        public boolean contains(String key) {
748e93f66f4617f2f4cb3e2a1919988fdf401b51f4Michael Chan            if (GeneralPreferences.KEY_ALERTS_VIBRATE.equals(key)) {
7525b09db869f377b131052447f62ad02e2505cd87Michael Chan                return true;
7625b09db869f377b131052447f62ad02e2505cd87Michael Chan            }
7725b09db869f377b131052447f62ad02e2505cd87Michael Chan            return false;
7825b09db869f377b131052447f62ad02e2505cd87Michael Chan        }
7925b09db869f377b131052447f62ad02e2505cd87Michael Chan
8025b09db869f377b131052447f62ad02e2505cd87Michael Chan        @Override
8125b09db869f377b131052447f62ad02e2505cd87Michael Chan        public boolean getBoolean(String key, boolean defValue) {
828e93f66f4617f2f4cb3e2a1919988fdf401b51f4Michael Chan            if (GeneralPreferences.KEY_ALERTS_VIBRATE.equals(key)) {
838e93f66f4617f2f4cb3e2a1919988fdf401b51f4Michael Chan                if (mVibrate == null) {
848e93f66f4617f2f4cb3e2a1919988fdf401b51f4Michael Chan                    Assert.fail(GeneralPreferences.KEY_ALERTS_VIBRATE
858e93f66f4617f2f4cb3e2a1919988fdf401b51f4Michael Chan                            + " fetched more than once.");
868e93f66f4617f2f4cb3e2a1919988fdf401b51f4Michael Chan                }
878e93f66f4617f2f4cb3e2a1919988fdf401b51f4Michael Chan                boolean val = mVibrate;
888e93f66f4617f2f4cb3e2a1919988fdf401b51f4Michael Chan                if (mStrict) {
898e93f66f4617f2f4cb3e2a1919988fdf401b51f4Michael Chan                    mVibrate = null;
908e93f66f4617f2f4cb3e2a1919988fdf401b51f4Michael Chan                }
918e93f66f4617f2f4cb3e2a1919988fdf401b51f4Michael Chan                return val;
928e93f66f4617f2f4cb3e2a1919988fdf401b51f4Michael Chan            }
9325b09db869f377b131052447f62ad02e2505cd87Michael Chan            if (GeneralPreferences.KEY_ALERTS_POPUP.equals(key)) {
94b5a2a61208857805cc053c6ac476d30100289279Sara Ting                if (mPopup == null) {
95b5a2a61208857805cc053c6ac476d30100289279Sara Ting                    Assert.fail(GeneralPreferences.KEY_ALERTS_POPUP + " fetched more than once.");
96b5a2a61208857805cc053c6ac476d30100289279Sara Ting                }
97b5a2a61208857805cc053c6ac476d30100289279Sara Ting                boolean val = mPopup;
98b5a2a61208857805cc053c6ac476d30100289279Sara Ting                if (mStrict) {
99b5a2a61208857805cc053c6ac476d30100289279Sara Ting                    mPopup = null;
100b5a2a61208857805cc053c6ac476d30100289279Sara Ting                }
101b5a2a61208857805cc053c6ac476d30100289279Sara Ting                return val;
10225b09db869f377b131052447f62ad02e2505cd87Michael Chan            }
10325b09db869f377b131052447f62ad02e2505cd87Michael Chan            throw new IllegalArgumentException();
10425b09db869f377b131052447f62ad02e2505cd87Michael Chan        }
10525b09db869f377b131052447f62ad02e2505cd87Michael Chan
10625b09db869f377b131052447f62ad02e2505cd87Michael Chan        @Override
10725b09db869f377b131052447f62ad02e2505cd87Michael Chan        public String getString(String key, String defValue) {
10825b09db869f377b131052447f62ad02e2505cd87Michael Chan            if (GeneralPreferences.KEY_ALERTS_RINGTONE.equals(key)) {
109b5a2a61208857805cc053c6ac476d30100289279Sara Ting                if (mRingtone == null) {
110b5a2a61208857805cc053c6ac476d30100289279Sara Ting                    Assert.fail(GeneralPreferences.KEY_ALERTS_RINGTONE
111b5a2a61208857805cc053c6ac476d30100289279Sara Ting                            + " fetched more than once.");
112b5a2a61208857805cc053c6ac476d30100289279Sara Ting                }
113b5a2a61208857805cc053c6ac476d30100289279Sara Ting                String val = mRingtone;
114b5a2a61208857805cc053c6ac476d30100289279Sara Ting                if (mStrict) {
115b5a2a61208857805cc053c6ac476d30100289279Sara Ting                    mRingtone = null;
116b5a2a61208857805cc053c6ac476d30100289279Sara Ting                }
117b5a2a61208857805cc053c6ac476d30100289279Sara Ting                return val;
11825b09db869f377b131052447f62ad02e2505cd87Michael Chan            }
11925b09db869f377b131052447f62ad02e2505cd87Michael Chan            throw new IllegalArgumentException();
12025b09db869f377b131052447f62ad02e2505cd87Michael Chan        }
12125b09db869f377b131052447f62ad02e2505cd87Michael Chan
12225b09db869f377b131052447f62ad02e2505cd87Michael Chan        @Override
12325b09db869f377b131052447f62ad02e2505cd87Michael Chan        public Map<String, ?> getAll() {
12425b09db869f377b131052447f62ad02e2505cd87Michael Chan            throw new IllegalArgumentException();
12525b09db869f377b131052447f62ad02e2505cd87Michael Chan        }
12625b09db869f377b131052447f62ad02e2505cd87Michael Chan
12725b09db869f377b131052447f62ad02e2505cd87Michael Chan        @Override
12825b09db869f377b131052447f62ad02e2505cd87Michael Chan        public Set<String> getStringSet(String key, Set<String> defValues) {
12925b09db869f377b131052447f62ad02e2505cd87Michael Chan            throw new IllegalArgumentException();
13025b09db869f377b131052447f62ad02e2505cd87Michael Chan        }
13125b09db869f377b131052447f62ad02e2505cd87Michael Chan
13225b09db869f377b131052447f62ad02e2505cd87Michael Chan        @Override
13325b09db869f377b131052447f62ad02e2505cd87Michael Chan        public int getInt(String key, int defValue) {
13425b09db869f377b131052447f62ad02e2505cd87Michael Chan            throw new IllegalArgumentException();
13525b09db869f377b131052447f62ad02e2505cd87Michael Chan        }
13625b09db869f377b131052447f62ad02e2505cd87Michael Chan
13725b09db869f377b131052447f62ad02e2505cd87Michael Chan        @Override
13825b09db869f377b131052447f62ad02e2505cd87Michael Chan        public long getLong(String key, long defValue) {
13925b09db869f377b131052447f62ad02e2505cd87Michael Chan            throw new IllegalArgumentException();
14025b09db869f377b131052447f62ad02e2505cd87Michael Chan        }
14125b09db869f377b131052447f62ad02e2505cd87Michael Chan
14225b09db869f377b131052447f62ad02e2505cd87Michael Chan        @Override
14325b09db869f377b131052447f62ad02e2505cd87Michael Chan        public float getFloat(String key, float defValue) {
14425b09db869f377b131052447f62ad02e2505cd87Michael Chan            throw new IllegalArgumentException();
14525b09db869f377b131052447f62ad02e2505cd87Michael Chan        }
14625b09db869f377b131052447f62ad02e2505cd87Michael Chan
14725b09db869f377b131052447f62ad02e2505cd87Michael Chan        @Override
14825b09db869f377b131052447f62ad02e2505cd87Michael Chan        public Editor edit() {
14925b09db869f377b131052447f62ad02e2505cd87Michael Chan            throw new IllegalArgumentException();
15025b09db869f377b131052447f62ad02e2505cd87Michael Chan        }
15125b09db869f377b131052447f62ad02e2505cd87Michael Chan
15225b09db869f377b131052447f62ad02e2505cd87Michael Chan        @Override
15325b09db869f377b131052447f62ad02e2505cd87Michael Chan        public void registerOnSharedPreferenceChangeListener(
15425b09db869f377b131052447f62ad02e2505cd87Michael Chan                OnSharedPreferenceChangeListener listener) {
15525b09db869f377b131052447f62ad02e2505cd87Michael Chan            throw new IllegalArgumentException();
15625b09db869f377b131052447f62ad02e2505cd87Michael Chan        }
15725b09db869f377b131052447f62ad02e2505cd87Michael Chan
15825b09db869f377b131052447f62ad02e2505cd87Michael Chan        @Override
15925b09db869f377b131052447f62ad02e2505cd87Michael Chan        public void unregisterOnSharedPreferenceChangeListener(
16025b09db869f377b131052447f62ad02e2505cd87Michael Chan                OnSharedPreferenceChangeListener listener) {
16125b09db869f377b131052447f62ad02e2505cd87Michael Chan            throw new IllegalArgumentException();
16225b09db869f377b131052447f62ad02e2505cd87Michael Chan        }
16325b09db869f377b131052447f62ad02e2505cd87Michael Chan
16425b09db869f377b131052447f62ad02e2505cd87Michael Chan    }
16525b09db869f377b131052447f62ad02e2505cd87Michael Chan
16625b09db869f377b131052447f62ad02e2505cd87Michael Chan    // Created these constants so the test cases are shorter
16725b09db869f377b131052447f62ad02e2505cd87Michael Chan    public static final int SCHEDULED = CalendarAlerts.STATE_SCHEDULED;
16825b09db869f377b131052447f62ad02e2505cd87Michael Chan    public static final int FIRED = CalendarAlerts.STATE_FIRED;
16925b09db869f377b131052447f62ad02e2505cd87Michael Chan    public static final int DISMISSED = CalendarAlerts.STATE_DISMISSED;
17025b09db869f377b131052447f62ad02e2505cd87Michael Chan
17125b09db869f377b131052447f62ad02e2505cd87Michael Chan    public static final int ACCEPTED = Attendees.ATTENDEE_STATUS_ACCEPTED;
17225b09db869f377b131052447f62ad02e2505cd87Michael Chan    public static final int DECLINED = Attendees.ATTENDEE_STATUS_DECLINED;
17325b09db869f377b131052447f62ad02e2505cd87Michael Chan    public static final int INVITED = Attendees.ATTENDEE_STATUS_INVITED;
17425b09db869f377b131052447f62ad02e2505cd87Michael Chan    public static final int TENTATIVE = Attendees.ATTENDEE_STATUS_TENTATIVE;
17525b09db869f377b131052447f62ad02e2505cd87Michael Chan
17625b09db869f377b131052447f62ad02e2505cd87Michael Chan    class NotificationInstance {
17725b09db869f377b131052447f62ad02e2505cd87Michael Chan        int mAlertId;
178bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        int[] mAlertIdsInDigest;
17925b09db869f377b131052447f62ad02e2505cd87Michael Chan        int mPriority;
18025b09db869f377b131052447f62ad02e2505cd87Michael Chan
18125b09db869f377b131052447f62ad02e2505cd87Michael Chan        public NotificationInstance(int alertId, int priority) {
18225b09db869f377b131052447f62ad02e2505cd87Michael Chan            mAlertId = alertId;
18325b09db869f377b131052447f62ad02e2505cd87Michael Chan            mPriority = priority;
18425b09db869f377b131052447f62ad02e2505cd87Michael Chan        }
185bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting
186bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        public NotificationInstance(int[] alertIdsInDigest, int priority) {
187bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting            mAlertIdsInDigest = alertIdsInDigest;
188bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting            mPriority = priority;
189bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        }
19025b09db869f377b131052447f62ad02e2505cd87Michael Chan    }
19125b09db869f377b131052447f62ad02e2505cd87Michael Chan
19225b09db869f377b131052447f62ad02e2505cd87Michael Chan    class Alert {
19325b09db869f377b131052447f62ad02e2505cd87Michael Chan        long mEventId;
19425b09db869f377b131052447f62ad02e2505cd87Michael Chan        int mAlertStatus;
19525b09db869f377b131052447f62ad02e2505cd87Michael Chan        int mResponseStatus;
19625b09db869f377b131052447f62ad02e2505cd87Michael Chan        int mAllDay;
19725b09db869f377b131052447f62ad02e2505cd87Michael Chan        long mBegin;
19825b09db869f377b131052447f62ad02e2505cd87Michael Chan        long mEnd;
19925b09db869f377b131052447f62ad02e2505cd87Michael Chan        int mMinute;
20025b09db869f377b131052447f62ad02e2505cd87Michael Chan        long mAlarmTime;
20125b09db869f377b131052447f62ad02e2505cd87Michael Chan
20225b09db869f377b131052447f62ad02e2505cd87Michael Chan        public Alert(long eventId, int alertStatus, int responseStatus, int allDay, long begin,
20325b09db869f377b131052447f62ad02e2505cd87Michael Chan                long end, int minute, long alarmTime) {
20425b09db869f377b131052447f62ad02e2505cd87Michael Chan            mEventId = eventId;
20525b09db869f377b131052447f62ad02e2505cd87Michael Chan            mAlertStatus = alertStatus;
20625b09db869f377b131052447f62ad02e2505cd87Michael Chan            mResponseStatus = responseStatus;
20725b09db869f377b131052447f62ad02e2505cd87Michael Chan            mAllDay = allDay;
20825b09db869f377b131052447f62ad02e2505cd87Michael Chan            mBegin = begin;
20925b09db869f377b131052447f62ad02e2505cd87Michael Chan            mEnd = end;
21025b09db869f377b131052447f62ad02e2505cd87Michael Chan            mMinute = minute;
21125b09db869f377b131052447f62ad02e2505cd87Michael Chan            mAlarmTime = alarmTime;
21225b09db869f377b131052447f62ad02e2505cd87Michael Chan        }
21325b09db869f377b131052447f62ad02e2505cd87Michael Chan
21425b09db869f377b131052447f62ad02e2505cd87Michael Chan    }
21525b09db869f377b131052447f62ad02e2505cd87Michael Chan
21625b09db869f377b131052447f62ad02e2505cd87Michael Chan    class AlertsTable {
21725b09db869f377b131052447f62ad02e2505cd87Michael Chan
21825b09db869f377b131052447f62ad02e2505cd87Michael Chan        ArrayList<Alert> mAlerts = new ArrayList<Alert>();
21925b09db869f377b131052447f62ad02e2505cd87Michael Chan
22025b09db869f377b131052447f62ad02e2505cd87Michael Chan        int addAlertRow(long eventId, int alertStatus, int responseStatus, int allDay, long begin,
221bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting                long end, long alarmTime) {
222bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting            Alert a = new Alert(eventId, alertStatus, responseStatus, allDay, begin, end,
223bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting                    5 /* minute */, alarmTime);
22425b09db869f377b131052447f62ad02e2505cd87Michael Chan            int id = mAlerts.size();
22525b09db869f377b131052447f62ad02e2505cd87Michael Chan            mAlerts.add(a);
22625b09db869f377b131052447f62ad02e2505cd87Michael Chan            return id;
22725b09db869f377b131052447f62ad02e2505cd87Michael Chan        }
22825b09db869f377b131052447f62ad02e2505cd87Michael Chan
22925b09db869f377b131052447f62ad02e2505cd87Michael Chan        public MatrixCursor getAlertCursor() {
23025b09db869f377b131052447f62ad02e2505cd87Michael Chan            MatrixCursor alertCursor = new MatrixCursor(AlertService.ALERT_PROJECTION);
23125b09db869f377b131052447f62ad02e2505cd87Michael Chan
23225b09db869f377b131052447f62ad02e2505cd87Michael Chan            int i = 0;
23325b09db869f377b131052447f62ad02e2505cd87Michael Chan            for (Alert a : mAlerts) {
23425b09db869f377b131052447f62ad02e2505cd87Michael Chan                Object[] ca = {
23525b09db869f377b131052447f62ad02e2505cd87Michael Chan                        i++,
23625b09db869f377b131052447f62ad02e2505cd87Michael Chan                        a.mEventId,
23725b09db869f377b131052447f62ad02e2505cd87Michael Chan                        a.mAlertStatus,
23825b09db869f377b131052447f62ad02e2505cd87Michael Chan                        "Title" + a.mEventId + " " + a.mMinute,
23925b09db869f377b131052447f62ad02e2505cd87Michael Chan                        "Loc" + a.mEventId,
24025b09db869f377b131052447f62ad02e2505cd87Michael Chan                        a.mResponseStatus,
24125b09db869f377b131052447f62ad02e2505cd87Michael Chan                        a.mAllDay,
24225b09db869f377b131052447f62ad02e2505cd87Michael Chan                        a.mAlarmTime > 0 ? a.mAlarmTime : a.mBegin - a.mMinute * 60 * 1000,
24325b09db869f377b131052447f62ad02e2505cd87Michael Chan                        a.mMinute,
24425b09db869f377b131052447f62ad02e2505cd87Michael Chan                        a.mBegin,
24525b09db869f377b131052447f62ad02e2505cd87Michael Chan                        a.mEnd,
24625b09db869f377b131052447f62ad02e2505cd87Michael Chan                        "Desc: " + a.mAlarmTime
24725b09db869f377b131052447f62ad02e2505cd87Michael Chan                };
24825b09db869f377b131052447f62ad02e2505cd87Michael Chan                alertCursor.addRow(ca);
24925b09db869f377b131052447f62ad02e2505cd87Michael Chan            }
25025b09db869f377b131052447f62ad02e2505cd87Michael Chan            return alertCursor;
25125b09db869f377b131052447f62ad02e2505cd87Michael Chan        }
25225b09db869f377b131052447f62ad02e2505cd87Michael Chan
25325b09db869f377b131052447f62ad02e2505cd87Michael Chan    }
25425b09db869f377b131052447f62ad02e2505cd87Michael Chan
255948c590ced6854d2fbe9dc765db4ae8d63646664Sara Ting    class NotificationTestManager extends NotificationMgr {
25625b09db869f377b131052447f62ad02e2505cd87Michael Chan        // Expected notifications
257487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting        NotificationInstance[] mExpectedNotifications;
258487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting        NotificationWrapper[] mActualNotifications;
259487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting        boolean[] mCancelled;
26025b09db869f377b131052447f62ad02e2505cd87Michael Chan
26125b09db869f377b131052447f62ad02e2505cd87Michael Chan        // CalendarAlerts table
26225b09db869f377b131052447f62ad02e2505cd87Michael Chan        private ArrayList<Alert> mAlerts;
26325b09db869f377b131052447f62ad02e2505cd87Michael Chan
264bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        public NotificationTestManager(ArrayList<Alert> alerts, int maxNotifications) {
26525b09db869f377b131052447f62ad02e2505cd87Michael Chan            assertEquals(0, AlertUtils.EXPIRED_GROUP_NOTIFICATION_ID);
26625b09db869f377b131052447f62ad02e2505cd87Michael Chan            mAlerts = alerts;
267487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting            mExpectedNotifications = new NotificationInstance[maxNotifications + 1];
268487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting            mActualNotifications = new NotificationWrapper[mExpectedNotifications.length];
269487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting            mCancelled = new boolean[mExpectedNotifications.length];
27025b09db869f377b131052447f62ad02e2505cd87Michael Chan        }
27125b09db869f377b131052447f62ad02e2505cd87Michael Chan
27225b09db869f377b131052447f62ad02e2505cd87Michael Chan        public void expectTestNotification(int notificationId, int alertId, int highPriority) {
273487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting            mExpectedNotifications[notificationId] = new NotificationInstance(alertId,
274487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting                    highPriority);
27525b09db869f377b131052447f62ad02e2505cd87Michael Chan        }
27625b09db869f377b131052447f62ad02e2505cd87Michael Chan
277bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        public void expectTestNotification(int notificationId, int[] alertIds, int priority) {
278487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting            mExpectedNotifications[notificationId] = new NotificationInstance(alertIds, priority);
279487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting        }
280487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting
281487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting        private <T> boolean nullContents(T[] array) {
282487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting            for (T item : array) {
283487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting                if (item != null) {
284487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting                    return false;
285487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting                }
286487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting            }
287487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting            return true;
288bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        }
289bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting
290487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting        public void validateNotificationsAndReset() {
291487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting            if (nullContents(mExpectedNotifications)) {
292487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting                return;
293487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting            }
294bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting
295487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting            String debugStr = printActualNotifications();
296487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting            for (int id = 0; id < mActualNotifications.length; id++) {
297487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting                NotificationInstance expected = mExpectedNotifications[id];
298487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting                NotificationWrapper actual = mActualNotifications[id];
299487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting                if (expected == null) {
300487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting                    assertNull("Received unexpected notificationId " + id + debugStr, actual);
301487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting                    assertTrue("NotificationId " + id + " should have been cancelled." + debugStr,
302487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting                            mCancelled[id]);
303bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting                } else {
304487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting                    assertNotNull("Expected notificationId " + id + " but it was not posted."
305487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting                            + debugStr, actual);
306487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting                    assertFalse("NotificationId " + id + " should not have been cancelled."
307487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting                            + debugStr, mCancelled[id]);
308487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting                    assertEquals("Priority not as expected for notification " + id + debugStr,
309487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting                            expected.mPriority, actual.mNotification.priority);
310487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting                    if (expected.mAlertIdsInDigest == null) {
311487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting                        Alert a = mAlerts.get(expected.mAlertId);
312487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting                        assertEquals("Event ID not expected for notification " + id + debugStr,
313487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting                                a.mEventId, actual.mEventId);
314487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting                        assertEquals("Begin time not expected for notification " + id + debugStr,
315487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting                                a.mBegin, actual.mBegin);
316487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting                        assertEquals("End time not expected for notification " + id + debugStr,
317487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting                                a.mEnd, actual.mEnd);
318487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting                    } else {
319487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting                        // Notification should be a digest.
320487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting                        assertNotNull("Posted notification not a digest as expected." + debugStr,
321487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting                                actual.mNw);
322487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting                        assertEquals("Number of notifications in digest not as expected."
323487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting                                + debugStr, expected.mAlertIdsInDigest.length, actual.mNw.size());
324487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting                        for (int i = 0; i < actual.mNw.size(); i++) {
325487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting                            Alert a = mAlerts.get(expected.mAlertIdsInDigest[i]);
326487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting                            assertEquals("Digest item " + i + ": Event ID not as expected"
327487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting                                    + debugStr, a.mEventId, actual.mNw.get(i).mEventId);
328487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting                            assertEquals("Digest item " + i + ": Begin time in digest not expected"
329487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting                                    + debugStr, a.mBegin, actual.mNw.get(i).mBegin);
330487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting                            assertEquals("Digest item " + i + ": End time in digest not expected"
331487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting                                    + debugStr, a.mEnd, actual.mNw.get(i).mEnd);
332487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting                        }
333bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting                    }
334bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting                }
335487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting            }
336487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting
337487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting            Arrays.fill(mCancelled, false);
338487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting            Arrays.fill(mExpectedNotifications, null);
339487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting            Arrays.fill(mActualNotifications, null);
34025b09db869f377b131052447f62ad02e2505cd87Michael Chan        }
34125b09db869f377b131052447f62ad02e2505cd87Michael Chan
342487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting        private String printActualNotifications() {
343487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting            StringBuilder s = new StringBuilder();
344487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting            s.append("\n\nNotifications actually posted:\n");
345487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting            for (int i = mActualNotifications.length - 1; i >= 0; i--) {
346487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting                NotificationWrapper actual = mActualNotifications[i];
347487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting                if (actual == null) {
348487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting                    continue;
349487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting                }
350487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting                s.append("Notification " + i + " -- ");
351487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting                s.append("priority:" + actual.mNotification.priority);
352487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting                if (actual.mNw == null) {
353487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting                    s.append(", eventId:" +  actual.mEventId);
354487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting                } else {
355487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting                    s.append(", eventIds:{");
356487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting                    for (int digestIndex = 0; digestIndex < actual.mNw.size(); digestIndex++) {
357487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting                        s.append(actual.mNw.get(digestIndex).mEventId + ",");
358487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting                    }
359487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting                    s.append("}");
360487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting                }
361487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting                s.append("\n");
36225b09db869f377b131052447f62ad02e2505cd87Michael Chan            }
363487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting            return s.toString();
36425b09db869f377b131052447f62ad02e2505cd87Michael Chan        }
36525b09db869f377b131052447f62ad02e2505cd87Michael Chan
36625b09db869f377b131052447f62ad02e2505cd87Michael Chan        ///////////////////////////////
36725b09db869f377b131052447f62ad02e2505cd87Michael Chan        // NotificationMgr methods
36825b09db869f377b131052447f62ad02e2505cd87Michael Chan        @Override
36925b09db869f377b131052447f62ad02e2505cd87Michael Chan        public void cancel(int id) {
37025b09db869f377b131052447f62ad02e2505cd87Michael Chan            assertTrue("id out of bound: " + id, 0 <= id);
371487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting            assertTrue("id out of bound: " + id, id < mCancelled.length);
372487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting            assertNull("id already used", mActualNotifications[id]);
373487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting            assertFalse("id already used", mCancelled[id]);
374487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting            mCancelled[id] = true;
375487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting            assertNull("Unexpected cancel for id " + id, mExpectedNotifications[id]);
37625b09db869f377b131052447f62ad02e2505cd87Michael Chan        }
37725b09db869f377b131052447f62ad02e2505cd87Michael Chan
3788e93f66f4617f2f4cb3e2a1919988fdf401b51f4Michael Chan        @Override
37925b09db869f377b131052447f62ad02e2505cd87Michael Chan        public void notify(int id, NotificationWrapper nw) {
38025b09db869f377b131052447f62ad02e2505cd87Michael Chan            assertTrue("id out of bound: " + id, 0 <= id);
381487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting            assertTrue("id out of bound: " + id, id < mExpectedNotifications.length);
382487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting            assertNull("id already used: " + id, mActualNotifications[id]);
383487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting            mActualNotifications[id] = nw;
38425b09db869f377b131052447f62ad02e2505cd87Michael Chan        }
38525b09db869f377b131052447f62ad02e2505cd87Michael Chan    }
38625b09db869f377b131052447f62ad02e2505cd87Michael Chan
38725b09db869f377b131052447f62ad02e2505cd87Michael Chan    // TODO
38825b09db869f377b131052447f62ad02e2505cd87Michael Chan    // Catch updates of new state, notify time, and received time
38925b09db869f377b131052447f62ad02e2505cd87Michael Chan    // Test ringer, vibrate,
39025b09db869f377b131052447f62ad02e2505cd87Michael Chan    // Test intents, action email
39125b09db869f377b131052447f62ad02e2505cd87Michael Chan
39225b09db869f377b131052447f62ad02e2505cd87Michael Chan    @Smoke
39325b09db869f377b131052447f62ad02e2505cd87Michael Chan    @SmallTest
394487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting    public void testGenerateAlerts_none() {
39525b09db869f377b131052447f62ad02e2505cd87Michael Chan        MockSharedPreferences prefs = new MockSharedPreferences();
39625b09db869f377b131052447f62ad02e2505cd87Michael Chan        AlertsTable at = new AlertsTable();
397bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        NotificationTestManager ntm = new NotificationTestManager(at.mAlerts,
398bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting                AlertService.MAX_NOTIFICATIONS);
39925b09db869f377b131052447f62ad02e2505cd87Michael Chan
40025b09db869f377b131052447f62ad02e2505cd87Michael Chan        // Test no alert
40125b09db869f377b131052447f62ad02e2505cd87Michael Chan        long currentTime = 1000000;
4023a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting        AlertService.generateAlerts(mContext, ntm, new MockAlarmManager(mContext), prefs,
403487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting                at.getAlertCursor(), currentTime, AlertService.MAX_NOTIFICATIONS);
40425b09db869f377b131052447f62ad02e2505cd87Michael Chan        ntm.validateNotificationsAndReset();
40525b09db869f377b131052447f62ad02e2505cd87Michael Chan    }
40625b09db869f377b131052447f62ad02e2505cd87Michael Chan
40725b09db869f377b131052447f62ad02e2505cd87Michael Chan    @Smoke
40825b09db869f377b131052447f62ad02e2505cd87Michael Chan    @SmallTest
409487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting    public void testGenerateAlerts_single() {
41025b09db869f377b131052447f62ad02e2505cd87Michael Chan        MockSharedPreferences prefs = new MockSharedPreferences();
4113a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting        MockAlarmManager alarmMgr = new MockAlarmManager(mContext);
41225b09db869f377b131052447f62ad02e2505cd87Michael Chan        AlertsTable at = new AlertsTable();
413bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        NotificationTestManager ntm = new NotificationTestManager(at.mAlerts,
414bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting                AlertService.MAX_NOTIFICATIONS);
41525b09db869f377b131052447f62ad02e2505cd87Michael Chan
416bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        int id = at.addAlertRow(100, SCHEDULED, ACCEPTED, 0 /* all day */, 1300000, 2300000, 0);
41725b09db869f377b131052447f62ad02e2505cd87Michael Chan
41825b09db869f377b131052447f62ad02e2505cd87Michael Chan        // Test one up coming alert
41925b09db869f377b131052447f62ad02e2505cd87Michael Chan        long currentTime = 1000000;
42025b09db869f377b131052447f62ad02e2505cd87Michael Chan        ntm.expectTestNotification(1, id, PRIORITY_HIGH);
42125b09db869f377b131052447f62ad02e2505cd87Michael Chan
422487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting        AlertService.generateAlerts(mContext, ntm, alarmMgr, prefs, at.getAlertCursor(), currentTime,
423bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting                AlertService.MAX_NOTIFICATIONS);
42425b09db869f377b131052447f62ad02e2505cd87Michael Chan        ntm.validateNotificationsAndReset(); // This wipes out notification
42525b09db869f377b131052447f62ad02e2505cd87Michael Chan                                             // tests added so far
42625b09db869f377b131052447f62ad02e2505cd87Michael Chan
42725b09db869f377b131052447f62ad02e2505cd87Michael Chan        // Test half way into an event
42825b09db869f377b131052447f62ad02e2505cd87Michael Chan        currentTime = 2300000;
429487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting        ntm.expectTestNotification(AlertUtils.EXPIRED_GROUP_NOTIFICATION_ID, id, PRIORITY_MIN);
43025b09db869f377b131052447f62ad02e2505cd87Michael Chan
431487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting        AlertService.generateAlerts(mContext, ntm, alarmMgr, prefs, at.getAlertCursor(), currentTime,
432bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting                AlertService.MAX_NOTIFICATIONS);
43325b09db869f377b131052447f62ad02e2505cd87Michael Chan        ntm.validateNotificationsAndReset();
43425b09db869f377b131052447f62ad02e2505cd87Michael Chan
43525b09db869f377b131052447f62ad02e2505cd87Michael Chan        // Test event ended
43625b09db869f377b131052447f62ad02e2505cd87Michael Chan        currentTime = 4300000;
43725b09db869f377b131052447f62ad02e2505cd87Michael Chan        ntm.expectTestNotification(AlertUtils.EXPIRED_GROUP_NOTIFICATION_ID, id, PRIORITY_MIN);
43825b09db869f377b131052447f62ad02e2505cd87Michael Chan
439487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting        AlertService.generateAlerts(mContext, ntm, alarmMgr, prefs, at.getAlertCursor(), currentTime,
440bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting                AlertService.MAX_NOTIFICATIONS);
441bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        ntm.validateNotificationsAndReset();
442bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting    }
443bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting
444bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting    @SmallTest
445487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting    public void testGenerateAlerts_multiple() {
446bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        int maxNotifications = 10;
447bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        MockSharedPreferences prefs = new MockSharedPreferences();
4483a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting        MockAlarmManager alarmMgr = new MockAlarmManager(mContext);
449bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        AlertsTable at = new AlertsTable();
450bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        NotificationTestManager ntm = new NotificationTestManager(at.mAlerts, maxNotifications);
451bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting
452bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        // Current time - 5:00
453bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        long currentTime = createTimeInMillis(5, 0);
454bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting
455bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        // Set up future alerts.  The real query implementation sorts by descending start
456bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        // time so simulate that here with our order of adds to AlertsTable.
457bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        int id9 = at.addAlertRow(9, SCHEDULED, ACCEPTED, 0, createTimeInMillis(9, 0),
458bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting                createTimeInMillis(10, 0), 0);
459bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        int id8 = at.addAlertRow(8, SCHEDULED, ACCEPTED, 0, createTimeInMillis(8, 0),
460bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting                createTimeInMillis(9, 0), 0);
461bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        int id7 = at.addAlertRow(7, SCHEDULED, ACCEPTED, 0, createTimeInMillis(7, 0),
462bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting                createTimeInMillis(8, 0), 0);
463bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting
464bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        // Set up concurrent alerts (that started recently).
465bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        int id6 = at.addAlertRow(6, SCHEDULED, ACCEPTED, 0, createTimeInMillis(5, 0),
466bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting                createTimeInMillis(5, 40), 0);
467bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        int id5 = at.addAlertRow(5, SCHEDULED, ACCEPTED, 0, createTimeInMillis(4, 55),
468bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting                createTimeInMillis(7, 30), 0);
469bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        int id4 = at.addAlertRow(4, SCHEDULED, ACCEPTED, 0, createTimeInMillis(4, 50),
470bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting                createTimeInMillis(4, 50), 0);
471bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting
472bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        // Set up past alerts.
473bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        int id3 = at.addAlertRow(3, SCHEDULED, ACCEPTED, 0, createTimeInMillis(3, 0),
474bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting                createTimeInMillis(4, 0), 0);
475bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        int id2 = at.addAlertRow(2, SCHEDULED, ACCEPTED, 0, createTimeInMillis(2, 0),
476bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting                createTimeInMillis(3, 0), 0);
477bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        int id1 = at.addAlertRow(1, SCHEDULED, ACCEPTED, 0, createTimeInMillis(1, 0),
478bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting                createTimeInMillis(2, 0), 0);
479bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting
480bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        // Check posted notifications.  The order listed here is the order simulates the
481bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        // order in the real notification bar (last one posted appears on top), so these
482bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        // should be lowest start time on top.
483bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        ntm.expectTestNotification(6, id4, PRIORITY_HIGH); // concurrent
484bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        ntm.expectTestNotification(5, id5, PRIORITY_HIGH); // concurrent
485bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        ntm.expectTestNotification(4, id6, PRIORITY_HIGH); // concurrent
486bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        ntm.expectTestNotification(3, id7, PRIORITY_HIGH); // future
487bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        ntm.expectTestNotification(2, id8, PRIORITY_HIGH); // future
488bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        ntm.expectTestNotification(1, id9, PRIORITY_HIGH); // future
489bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        ntm.expectTestNotification(AlertUtils.EXPIRED_GROUP_NOTIFICATION_ID,
490bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting                new int[] {id3, id2, id1}, PRIORITY_MIN);
491487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting        AlertService.generateAlerts(mContext, ntm, alarmMgr, prefs, at.getAlertCursor(),
492487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting                currentTime, maxNotifications);
493bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        ntm.validateNotificationsAndReset();
494bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting
495bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        // Increase time by 15 minutes to check that some concurrent events dropped
496bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        // to the low priority bucket.
497bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        currentTime = createTimeInMillis(5, 15);
498bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        ntm.expectTestNotification(4, id5, PRIORITY_HIGH); // concurrent
499bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        ntm.expectTestNotification(3, id7, PRIORITY_HIGH); // future
500bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        ntm.expectTestNotification(2, id8, PRIORITY_HIGH); // future
501bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        ntm.expectTestNotification(1, id9, PRIORITY_HIGH); // future
502bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        ntm.expectTestNotification(AlertUtils.EXPIRED_GROUP_NOTIFICATION_ID,
503bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting                new int[] {id6, id4, id3, id2, id1}, PRIORITY_MIN);
504487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting        AlertService.generateAlerts(mContext, ntm, alarmMgr, prefs, at.getAlertCursor(),
505487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting                currentTime, maxNotifications);
506bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        ntm.validateNotificationsAndReset();
507bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting
508bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        // Increase time so some of the previously future ones change state.
509bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        currentTime = createTimeInMillis(8, 15);
510bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        ntm.expectTestNotification(1, id9, PRIORITY_HIGH); // future
511bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        ntm.expectTestNotification(AlertUtils.EXPIRED_GROUP_NOTIFICATION_ID,
512bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting                new int[] {id8, id7, id6, id5, id4, id3, id2, id1}, PRIORITY_MIN);
513487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting        AlertService.generateAlerts(mContext, ntm, alarmMgr, prefs, at.getAlertCursor(),
514487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting                currentTime, maxNotifications);
51525b09db869f377b131052447f62ad02e2505cd87Michael Chan        ntm.validateNotificationsAndReset();
51625b09db869f377b131052447f62ad02e2505cd87Michael Chan    }
51721af116207d5728a312e534b898933bb07f96292Sara Ting
518bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting    @SmallTest
519487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting    public void testGenerateAlerts_maxAlerts() {
520bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        MockSharedPreferences prefs = new MockSharedPreferences();
5213a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting        MockAlarmManager alarmMgr = new MockAlarmManager(mContext);
522bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        AlertsTable at = new AlertsTable();
523bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting
524bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        // Current time - 5:00
525bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        long currentTime = createTimeInMillis(5, 0);
526bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting
527bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        // Set up future alerts.  The real query implementation sorts by descending start
528bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        // time so simulate that here with our order of adds to AlertsTable.
529bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        int id9 = at.addAlertRow(9, SCHEDULED, ACCEPTED, 0, createTimeInMillis(9, 0),
530bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting                createTimeInMillis(10, 0), 0);
531bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        int id8 = at.addAlertRow(8, SCHEDULED, ACCEPTED, 0, createTimeInMillis(8, 0),
532bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting                createTimeInMillis(9, 0), 0);
533bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        int id7 = at.addAlertRow(7, SCHEDULED, ACCEPTED, 0, createTimeInMillis(7, 0),
534bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting                createTimeInMillis(8, 0), 0);
535bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting
536bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        // Set up concurrent alerts (that started recently).
537bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        int id6 = at.addAlertRow(6, SCHEDULED, ACCEPTED, 0, createTimeInMillis(5, 0),
538bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting                createTimeInMillis(5, 40), 0);
539bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        int id5 = at.addAlertRow(5, SCHEDULED, ACCEPTED, 0, createTimeInMillis(4, 55),
540bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting                createTimeInMillis(7, 30), 0);
541bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        int id4 = at.addAlertRow(4, SCHEDULED, ACCEPTED, 0, createTimeInMillis(4, 50),
542bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting                createTimeInMillis(4, 50), 0);
543bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting
544bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        // Set up past alerts.
545bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        int id3 = at.addAlertRow(3, SCHEDULED, ACCEPTED, 0, createTimeInMillis(3, 0),
546bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting                createTimeInMillis(4, 0), 0);
547bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        int id2 = at.addAlertRow(2, SCHEDULED, ACCEPTED, 0, createTimeInMillis(2, 0),
548bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting                createTimeInMillis(3, 0), 0);
549bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        int id1 = at.addAlertRow(1, SCHEDULED, ACCEPTED, 0, createTimeInMillis(1, 0),
550bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting                createTimeInMillis(2, 0), 0);
551bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting
552bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        // Test when # alerts = max.
553bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        int maxNotifications = 6;
554bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        NotificationTestManager ntm = new NotificationTestManager(at.mAlerts, maxNotifications);
555bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        ntm.expectTestNotification(6, id4, PRIORITY_HIGH); // concurrent
556bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        ntm.expectTestNotification(5, id5, PRIORITY_HIGH); // concurrent
557bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        ntm.expectTestNotification(4, id6, PRIORITY_HIGH); // concurrent
558bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        ntm.expectTestNotification(3, id7, PRIORITY_HIGH); // future
559bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        ntm.expectTestNotification(2, id8, PRIORITY_HIGH); // future
560bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        ntm.expectTestNotification(1, id9, PRIORITY_HIGH); // future
561bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        ntm.expectTestNotification(AlertUtils.EXPIRED_GROUP_NOTIFICATION_ID,
562bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting                new int[] {id3, id2, id1}, PRIORITY_MIN);
563487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting        AlertService.generateAlerts(mContext, ntm, alarmMgr, prefs, at.getAlertCursor(),
564487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting                currentTime, maxNotifications);
565bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        ntm.validateNotificationsAndReset();
566bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting
567bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        // Test when # alerts > max.
568bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        maxNotifications = 4;
569bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        ntm = new NotificationTestManager(at.mAlerts, maxNotifications);
570bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        ntm.expectTestNotification(4, id4, PRIORITY_HIGH); // concurrent
571bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        ntm.expectTestNotification(3, id5, PRIORITY_HIGH); // concurrent
572bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        ntm.expectTestNotification(2, id6, PRIORITY_HIGH); // concurrent
573bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        ntm.expectTestNotification(1, id7, PRIORITY_HIGH); // future
574bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        ntm.expectTestNotification(AlertUtils.EXPIRED_GROUP_NOTIFICATION_ID,
575bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting                new int[] {id9, id8, id3, id2, id1}, PRIORITY_MIN);
576487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting        AlertService.generateAlerts(mContext, ntm, alarmMgr, prefs, at.getAlertCursor(),
577487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting                currentTime, maxNotifications);
578bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        ntm.validateNotificationsAndReset();
579bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting    }
58021af116207d5728a312e534b898933bb07f96292Sara Ting
581b5a2a61208857805cc053c6ac476d30100289279Sara Ting    /**
582b5a2a61208857805cc053c6ac476d30100289279Sara Ting     * Test that the SharedPreferences are only fetched once for each setting.
583b5a2a61208857805cc053c6ac476d30100289279Sara Ting     */
584b5a2a61208857805cc053c6ac476d30100289279Sara Ting    @SmallTest
585487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting    public void testGenerateAlerts_sharedPreferences() {
586b5a2a61208857805cc053c6ac476d30100289279Sara Ting        MockSharedPreferences prefs = new MockSharedPreferences(true /* strict mode */);
587b5a2a61208857805cc053c6ac476d30100289279Sara Ting        AlertsTable at = new AlertsTable();
588487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting        NotificationTestManager ntm = new NotificationTestManager(at.mAlerts,
589487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting                AlertService.MAX_NOTIFICATIONS);
590b5a2a61208857805cc053c6ac476d30100289279Sara Ting
591b5a2a61208857805cc053c6ac476d30100289279Sara Ting        // Current time - 5:00
592b5a2a61208857805cc053c6ac476d30100289279Sara Ting        long currentTime = createTimeInMillis(5, 0);
593b5a2a61208857805cc053c6ac476d30100289279Sara Ting
594b5a2a61208857805cc053c6ac476d30100289279Sara Ting        // Set up future alerts.  The real query implementation sorts by descending start
595b5a2a61208857805cc053c6ac476d30100289279Sara Ting        // time so simulate that here with our order of adds to AlertsTable.
596487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting        at.addAlertRow(3, SCHEDULED, ACCEPTED, 0, createTimeInMillis(9, 0),
597b5a2a61208857805cc053c6ac476d30100289279Sara Ting                createTimeInMillis(10, 0), 0);
598487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting        at.addAlertRow(2, SCHEDULED, ACCEPTED, 0, createTimeInMillis(8, 0),
599b5a2a61208857805cc053c6ac476d30100289279Sara Ting                createTimeInMillis(9, 0), 0);
600487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting        at.addAlertRow(1, SCHEDULED, ACCEPTED, 0, createTimeInMillis(7, 0),
601b5a2a61208857805cc053c6ac476d30100289279Sara Ting                createTimeInMillis(8, 0), 0);
602b5a2a61208857805cc053c6ac476d30100289279Sara Ting
603487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting        // If this does not result in a failure (MockSharedPreferences fails for duplicate
604487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting        // queries), then test passes.
6053a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting        AlertService.generateAlerts(mContext, ntm, new MockAlarmManager(mContext), prefs,
606487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting                at.getAlertCursor(), currentTime, AlertService.MAX_NOTIFICATIONS);
607487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting    }
608b5a2a61208857805cc053c6ac476d30100289279Sara Ting
609487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting    public void testGenerateAlerts_refreshTime() {
610487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting        AlertsTable at = new AlertsTable();
611487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting        MockSharedPreferences prefs = new MockSharedPreferences();
6123a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting        MockAlarmManager alarmMgr = new MockAlarmManager(mContext);
613487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting        NotificationTestManager ntm = new NotificationTestManager(at.mAlerts,
614487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting                AlertService.MAX_NOTIFICATIONS);
615b5a2a61208857805cc053c6ac476d30100289279Sara Ting
616487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting        // Since AlertService.processQuery uses DateUtils.isToday instead of checking against
617487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting        // the passed in currentTime (not worth allocating the extra Time objects to do so), use
618487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting        // today's date for this test.
619487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting        Time now = new Time();
620487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting        now.setToNow();
621487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting        int day = now.monthDay;
622487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting        int month = now.month;
623487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting        int year = now.year;
624487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting        Time yesterday = new Time();
625487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting        yesterday.set(System.currentTimeMillis() - DateUtils.DAY_IN_MILLIS);
626487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting        Time tomorrow = new Time();
627487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting        tomorrow.set(System.currentTimeMillis() + DateUtils.DAY_IN_MILLIS);
6283a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting        long allDayStart = Utils.createTimeInMillis(0, 0, 0, day, month, year, Time.TIMEZONE_UTC);
629487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting
630487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting        /* today 10am - 10:30am */
631487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting        int id4 = at.addAlertRow(4, SCHEDULED, ACCEPTED, 0,
6323a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting                Utils.createTimeInMillis(0, 0, 10, day, month, year, Time.getCurrentTimezone()),
6333a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting                Utils.createTimeInMillis(0, 30, 10, day, month, year, Time.getCurrentTimezone()),
6343a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting                        0);
635487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting        /* today 6am - 6am (0 duration event) */
636487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting        int id3 = at.addAlertRow(3, SCHEDULED, ACCEPTED, 0,
6373a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting                Utils.createTimeInMillis(0, 0, 6, day, month, year, Time.getCurrentTimezone()),
6383a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting                Utils.createTimeInMillis(0, 0, 6, day, month, year, Time.getCurrentTimezone()), 0);
639487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting        /* today allDay */
640487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting        int id2 = at.addAlertRow(2, SCHEDULED, ACCEPTED, 1, allDayStart,
641487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting                allDayStart + DateUtils.HOUR_IN_MILLIS * 24, 0);
642487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting        /* yesterday 11pm - today 7am (multiday event) */
643487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting        int id1 = at.addAlertRow(1, SCHEDULED, ACCEPTED, 0,
6443a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting                Utils.createTimeInMillis(0, 0, 23, yesterday.monthDay, yesterday.month,
6453a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting                        yesterday.year, Time.getCurrentTimezone()),
6463a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting                Utils.createTimeInMillis(0, 0, 7, day, month, year, Time.getCurrentTimezone()), 0);
647487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting
648487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting        // Test at midnight - next refresh should be 15 min later (15 min into the all
649487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting        // day event).
6503a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting        long currentTime = Utils.createTimeInMillis(0, 0, 0, day, month, year,
6513a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting                Time.getCurrentTimezone());
652487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting        alarmMgr.expectAlarmTime(AlarmManager.RTC, currentTime + 15 * DateUtils.MINUTE_IN_MILLIS);
653487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting        ntm.expectTestNotification(4, id1, PRIORITY_HIGH);
654487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting        ntm.expectTestNotification(3, id2, PRIORITY_HIGH);
655487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting        ntm.expectTestNotification(2, id3, PRIORITY_HIGH);
656487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting        ntm.expectTestNotification(1, id4, PRIORITY_HIGH);
657487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting        AlertService.generateAlerts(mContext, ntm, alarmMgr, prefs, at.getAlertCursor(),
658487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting                currentTime, AlertService.MAX_NOTIFICATIONS);
659487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting        ntm.validateNotificationsAndReset();
660b5a2a61208857805cc053c6ac476d30100289279Sara Ting
661487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting        // Test at 12:30am - next refresh should be 30 min later (1/4 into event 'id1').
6623a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting        currentTime = Utils.createTimeInMillis(0, 30, 0, day, month, year,
6633a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting                Time.getCurrentTimezone());
664487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting        alarmMgr.expectAlarmTime(AlarmManager.RTC, currentTime + 30 * DateUtils.MINUTE_IN_MILLIS);
665487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting        ntm.expectTestNotification(3, id1, PRIORITY_HIGH);
666487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting        ntm.expectTestNotification(2, id3, PRIORITY_HIGH);
667487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting        ntm.expectTestNotification(1, id4, PRIORITY_HIGH);
668487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting        ntm.expectTestNotification(4, id2, PRIORITY_DEFAULT);
669487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting        AlertService.generateAlerts(mContext, ntm, alarmMgr, prefs, at.getAlertCursor(),
670487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting                currentTime, AlertService.MAX_NOTIFICATIONS);
671487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting        ntm.validateNotificationsAndReset();
672487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting
673487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting        // Test at 5:55am - next refresh should be 20 min later (15 min after 'id3').
6743a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting        currentTime = Utils.createTimeInMillis(0, 55, 5, day, month, year,
6753a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting                Time.getCurrentTimezone());
676487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting        alarmMgr.expectAlarmTime(AlarmManager.RTC, currentTime + 20 * DateUtils.MINUTE_IN_MILLIS);
677487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting        ntm.expectTestNotification(2, id3, PRIORITY_HIGH);
678487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting        ntm.expectTestNotification(1, id4, PRIORITY_HIGH);
679487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting        ntm.expectTestNotification(3, id2, PRIORITY_DEFAULT);
680487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting        ntm.expectTestNotification(AlertUtils.EXPIRED_GROUP_NOTIFICATION_ID, id1, PRIORITY_MIN);
681487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting        AlertService.generateAlerts(mContext, ntm, alarmMgr, prefs, at.getAlertCursor(),
682487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting                currentTime, AlertService.MAX_NOTIFICATIONS);
683487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting        ntm.validateNotificationsAndReset();
684487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting
685487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting        // Test at 10:14am - next refresh should be 1 min later (15 min into event 'id4').
6863a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting        currentTime = Utils.createTimeInMillis(0, 14, 10, day, month, year,
6873a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting                Time.getCurrentTimezone());
688487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting        alarmMgr.expectAlarmTime(AlarmManager.RTC, currentTime + 1 * DateUtils.MINUTE_IN_MILLIS);
689487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting        ntm.expectTestNotification(1, id4, PRIORITY_HIGH);
690487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting        ntm.expectTestNotification(2, id2, PRIORITY_DEFAULT);
691487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting        ntm.expectTestNotification(AlertUtils.EXPIRED_GROUP_NOTIFICATION_ID, new int[] {id3, id1},
692487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting                PRIORITY_MIN);
693487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting        AlertService.generateAlerts(mContext, ntm, alarmMgr, prefs, at.getAlertCursor(),
694487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting                currentTime, AlertService.MAX_NOTIFICATIONS);
695487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting        ntm.validateNotificationsAndReset();
696487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting
697487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting        // Test at 10:15am - next refresh should be tomorrow midnight (end of all day event 'id2').
6983a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting        currentTime = Utils.createTimeInMillis(0, 15, 10, day, month, year,
6993a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting                Time.getCurrentTimezone());
7003a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting        alarmMgr.expectAlarmTime(AlarmManager.RTC, Utils.createTimeInMillis(0, 0, 23,
7013a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting                tomorrow.monthDay, tomorrow.month, tomorrow.year, Time.getCurrentTimezone()));
702487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting        ntm.expectTestNotification(1, id2, PRIORITY_DEFAULT);
703487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting        ntm.expectTestNotification(AlertUtils.EXPIRED_GROUP_NOTIFICATION_ID,
704487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting                new int[] {id4, id3, id1}, PRIORITY_MIN);
705487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting        AlertService.generateAlerts(mContext, ntm, alarmMgr, prefs, at.getAlertCursor(),
706487d52c2789114e0ee3e7ce85694611b8d59dd70Sara Ting                currentTime, AlertService.MAX_NOTIFICATIONS);
707b5a2a61208857805cc053c6ac476d30100289279Sara Ting        ntm.validateNotificationsAndReset();
708b5a2a61208857805cc053c6ac476d30100289279Sara Ting    }
709b5a2a61208857805cc053c6ac476d30100289279Sara Ting
71021af116207d5728a312e534b898933bb07f96292Sara Ting    private NotificationInfo createNotificationInfo(long eventId) {
71121af116207d5728a312e534b898933bb07f96292Sara Ting        return new NotificationInfo("eventName", "location", "description", 100L, 200L, eventId,
71221af116207d5728a312e534b898933bb07f96292Sara Ting                false, false);
71321af116207d5728a312e534b898933bb07f96292Sara Ting    }
71421af116207d5728a312e534b898933bb07f96292Sara Ting
715bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting    private static long createTimeInMillis(int hour, int minute) {
7163a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting        return Utils.createTimeInMillis(0 /* second */, minute, hour, 1 /* day */, 1 /* month */,
717bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting                2012 /* year */, Time.getCurrentTimezone());
718bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting    }
719bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting
720bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting    @SmallTest
721bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting    public void testProcessQuery_skipDeclinedDismissed() {
722bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        int declinedEventId = 1;
723bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        int dismissedEventId = 2;
724bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        int acceptedEventId = 3;
725bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        long acceptedStartTime = createTimeInMillis(10, 0);
726bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        long acceptedEndTime = createTimeInMillis(10, 30);
727bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting
728bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        AlertsTable at = new AlertsTable();
729bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        at.addAlertRow(declinedEventId, SCHEDULED, DECLINED, 0, createTimeInMillis(9, 0),
730bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting                createTimeInMillis(10, 0), 0);
731bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        at.addAlertRow(dismissedEventId, SCHEDULED, DISMISSED, 0, createTimeInMillis(9, 30),
732bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting                createTimeInMillis(11, 0), 0);
733bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        at.addAlertRow(acceptedEventId, SCHEDULED, ACCEPTED, 1, acceptedStartTime, acceptedEndTime,
734bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting                0);
735bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting
736bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        ArrayList<NotificationInfo> highPriority = new ArrayList<NotificationInfo>();
737bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        ArrayList<NotificationInfo> mediumPriority = new ArrayList<NotificationInfo>();
738bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        ArrayList<NotificationInfo> lowPriority = new ArrayList<NotificationInfo>();
739bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        long currentTime = createTimeInMillis(5, 0);
740bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        AlertService.processQuery(at.getAlertCursor(), mContext, currentTime, highPriority,
741bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting                mediumPriority, lowPriority);
742bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting
743bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        assertEquals(0, lowPriority.size());
744bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        assertEquals(0, mediumPriority.size());
745bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        assertEquals(1, highPriority.size());
746bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        assertEquals(acceptedEventId, highPriority.get(0).eventId);
747bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        assertEquals(acceptedStartTime, highPriority.get(0).startMillis);
748bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        assertEquals(acceptedEndTime, highPriority.get(0).endMillis);
749bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        assertTrue(highPriority.get(0).allDay);
750bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting    }
751bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting
752bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting    @SmallTest
753bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting    public void testProcessQuery_newAlert() {
754bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        int scheduledAlertEventId = 1;
755bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        int firedAlertEventId = 2;
756bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting
757bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        AlertsTable at = new AlertsTable();
758bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        at.addAlertRow(scheduledAlertEventId, SCHEDULED, ACCEPTED, 0, createTimeInMillis(9, 0),
759bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting                createTimeInMillis(10, 0), 0);
760b25c663d28585fc9a4a2e31caa82b53a37509c83Sam Blitzstein        at.addAlertRow(firedAlertEventId, FIRED, ACCEPTED, 0, createTimeInMillis(4, 0),
761bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting                createTimeInMillis(10, 30), 0);
762bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting
763bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        ArrayList<NotificationInfo> highPriority = new ArrayList<NotificationInfo>();
764bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        ArrayList<NotificationInfo> mediumPriority = new ArrayList<NotificationInfo>();
765bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        ArrayList<NotificationInfo> lowPriority = new ArrayList<NotificationInfo>();
766bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        long currentTime = createTimeInMillis(5, 0);
767bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        AlertService.processQuery(at.getAlertCursor(), mContext, currentTime, highPriority,
768bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting                mediumPriority, lowPriority);
769bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting
770bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        assertEquals(0, lowPriority.size());
771bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        assertEquals(0, mediumPriority.size());
772bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        assertEquals(2, highPriority.size());
773bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        assertEquals(scheduledAlertEventId, highPriority.get(0).eventId);
774bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        assertTrue("newAlert should be ON for scheduled alerts", highPriority.get(0).newAlert);
775bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        assertEquals(firedAlertEventId, highPriority.get(1).eventId);
776bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        assertFalse("newAlert should be OFF for fired alerts", highPriority.get(1).newAlert);
777bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting    }
778bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting
779bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting    @SmallTest
780bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting    public void testProcessQuery_recurringEvent() {
781bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        int eventId = 1;
782bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        long earlierStartTime = createTimeInMillis(10, 0);
783bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        long laterStartTime = createTimeInMillis(11, 0);
784bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting
785bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        ArrayList<NotificationInfo> highPriority = new ArrayList<NotificationInfo>();
786bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        ArrayList<NotificationInfo> mediumPriority = new ArrayList<NotificationInfo>();
787bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        ArrayList<NotificationInfo> lowPriority = new ArrayList<NotificationInfo>();
788bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting
789bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        AlertsTable at = new AlertsTable();
790bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        at.addAlertRow(eventId, SCHEDULED, ACCEPTED, 0, laterStartTime,
791bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting                laterStartTime + DateUtils.HOUR_IN_MILLIS, 0);
792bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        at.addAlertRow(eventId, FIRED, ACCEPTED, 0, earlierStartTime,
793bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting                earlierStartTime + DateUtils.HOUR_IN_MILLIS, 0);
794bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting
795bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        // Both events in the future: the earliest one should be chosen.
796bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        long currentTime = earlierStartTime - DateUtils.DAY_IN_MILLIS * 5;
797bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        AlertService.processQuery(at.getAlertCursor(), mContext, currentTime, highPriority,
798bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting                mediumPriority, lowPriority);
799bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        assertEquals(0, lowPriority.size());
800bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        assertEquals(0, mediumPriority.size());
801bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        assertEquals(1, highPriority.size());
802bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        assertEquals("Recurring event with earlier start time expected", earlierStartTime,
803bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting                highPriority.get(0).startMillis);
804bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting
805bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        // Increment time just past the earlier event: the earlier one should be chosen.
806bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        highPriority.clear();
807bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        currentTime = earlierStartTime + DateUtils.MINUTE_IN_MILLIS * 10;
808bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        AlertService.processQuery(at.getAlertCursor(), mContext, currentTime, highPriority,
809bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting                mediumPriority, lowPriority);
810bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        assertEquals(0, lowPriority.size());
811bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        assertEquals(0, mediumPriority.size());
812bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        assertEquals(1, highPriority.size());
813bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        assertEquals("Recurring event with earlier start time expected", earlierStartTime,
814bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting                highPriority.get(0).startMillis);
815bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting
816bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        // Increment time to 15 min past the earlier event: the later one should be chosen.
817bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        highPriority.clear();
818bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        currentTime = earlierStartTime + DateUtils.MINUTE_IN_MILLIS * 15;
819bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        AlertService.processQuery(at.getAlertCursor(), mContext, currentTime, highPriority,
820bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting                mediumPriority, lowPriority);
821bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        assertEquals(0, lowPriority.size());
822bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        assertEquals(0, mediumPriority.size());
823bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        assertEquals(1, highPriority.size());
824bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        assertEquals("Recurring event with later start time expected", laterStartTime,
825bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting                highPriority.get(0).startMillis);
826bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting
827bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        // Both events in the past: the later one should be chosen (in the low priority bucket).
828bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        highPriority.clear();
829bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        currentTime = laterStartTime + DateUtils.DAY_IN_MILLIS * 5;
830bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        AlertService.processQuery(at.getAlertCursor(), mContext, currentTime, highPriority,
831bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting                mediumPriority, lowPriority);
832bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        assertEquals(0, highPriority.size());
833bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        assertEquals(0, mediumPriority.size());
834bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        assertEquals(1, lowPriority.size());
835bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        assertEquals("Recurring event with later start time expected", laterStartTime,
836bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting                lowPriority.get(0).startMillis);
837bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting    }
838bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting
839bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting    @SmallTest
840bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting    public void testProcessQuery_recurringAllDayEvent() {
841bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        int eventId = 1;
8423a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting        long day1 = Utils.createTimeInMillis(0, 0, 0, 1, 5, 2012, Time.TIMEZONE_UTC);
8433a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting        long day2 = Utils.createTimeInMillis(0, 0, 0, 2, 5, 2012, Time.TIMEZONE_UTC);
844bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting
845bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        ArrayList<NotificationInfo> highPriority = new ArrayList<NotificationInfo>();
846bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        ArrayList<NotificationInfo> mediumPriority = new ArrayList<NotificationInfo>();
847bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        ArrayList<NotificationInfo> lowPriority = new ArrayList<NotificationInfo>();
848bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting
849bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        AlertsTable at = new AlertsTable();
850bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        at.addAlertRow(eventId, SCHEDULED, ACCEPTED, 1, day2, day2 + DateUtils.HOUR_IN_MILLIS * 24,
851bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting                0);
852bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        at.addAlertRow(eventId, SCHEDULED, ACCEPTED, 1, day1, day1 + DateUtils.HOUR_IN_MILLIS * 24,
853bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting                0);
854bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting
855bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        // Both events in the future: the earliest one should be chosen.
856bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        long currentTime = day1 - DateUtils.DAY_IN_MILLIS * 3;
857bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        AlertService.processQuery(at.getAlertCursor(), mContext, currentTime, highPriority,
858bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting                mediumPriority, lowPriority);
859bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        assertEquals(0, lowPriority.size());
860bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        assertEquals(0, mediumPriority.size());
861bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        assertEquals(1, highPriority.size());
862bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        assertEquals("Recurring event with earlier start time expected", day1,
863bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting                highPriority.get(0).startMillis);
864bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting
865bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        // Increment time just past the earlier event (to 12:10am).  The earlier one should
866bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        // be chosen.
867bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        highPriority.clear();
8683a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting        currentTime = Utils.createTimeInMillis(0, 10, 0, 1, 5, 2012, Time.getCurrentTimezone());
869bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        AlertService.processQuery(at.getAlertCursor(), mContext, currentTime, highPriority,
870bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting                mediumPriority, lowPriority);
871bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        assertEquals(0, lowPriority.size());
872bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        assertEquals(0, mediumPriority.size());
873bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        assertEquals(1, highPriority.size());
874bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        assertEquals("Recurring event with earlier start time expected", day1,
875bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting                highPriority.get(0).startMillis);
876bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting
877bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        // Increment time to 15 min past the earlier event: the later one should be chosen.
878bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        highPriority.clear();
8793a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting        currentTime = Utils.createTimeInMillis(0, 15, 0, 1, 5, 2012, Time.getCurrentTimezone());
880bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        AlertService.processQuery(at.getAlertCursor(), mContext, currentTime, highPriority,
881bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting                mediumPriority, lowPriority);
882bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        assertEquals(0, lowPriority.size());
883bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        assertEquals(0, mediumPriority.size());
884bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        assertEquals(1, highPriority.size());
885bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        assertEquals("Recurring event with earlier start time expected", day2,
886bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting                highPriority.get(0).startMillis);
887bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting
888bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        // Both events in the past: the later one should be chosen (in the low priority bucket).
889bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        highPriority.clear();
890bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        currentTime = day2 + DateUtils.DAY_IN_MILLIS * 1;
891bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        AlertService.processQuery(at.getAlertCursor(), mContext, currentTime, highPriority,
892bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting                mediumPriority, lowPriority);
893bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        assertEquals(0, highPriority.size());
894bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        assertEquals(0, mediumPriority.size());
895bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        assertEquals(1, lowPriority.size());
896bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting        assertEquals("Recurring event with later start time expected", day2,
897bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting                lowPriority.get(0).startMillis);
898bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting    }
899bce26a2a19499790595e48ca36b43eb130e4a3fbSara Ting
90021af116207d5728a312e534b898933bb07f96292Sara Ting    @SmallTest
90121af116207d5728a312e534b898933bb07f96292Sara Ting    public void testRedistributeBuckets_withinLimits() throws Exception {
90221af116207d5728a312e534b898933bb07f96292Sara Ting        int maxNotifications = 3;
90321af116207d5728a312e534b898933bb07f96292Sara Ting        ArrayList<NotificationInfo> threeItemList = new ArrayList<NotificationInfo>();
90421af116207d5728a312e534b898933bb07f96292Sara Ting        threeItemList.add(createNotificationInfo(5));
90521af116207d5728a312e534b898933bb07f96292Sara Ting        threeItemList.add(createNotificationInfo(4));
90621af116207d5728a312e534b898933bb07f96292Sara Ting        threeItemList.add(createNotificationInfo(3));
90721af116207d5728a312e534b898933bb07f96292Sara Ting
90821af116207d5728a312e534b898933bb07f96292Sara Ting        // Test when max notifications at high priority.
90921af116207d5728a312e534b898933bb07f96292Sara Ting        ArrayList<NotificationInfo> high = threeItemList;
91021af116207d5728a312e534b898933bb07f96292Sara Ting        ArrayList<NotificationInfo> medium = new ArrayList<NotificationInfo>();
91121af116207d5728a312e534b898933bb07f96292Sara Ting        ArrayList<NotificationInfo> low = new ArrayList<NotificationInfo>();
91221af116207d5728a312e534b898933bb07f96292Sara Ting        AlertService.redistributeBuckets(high, medium, low, maxNotifications);
91321af116207d5728a312e534b898933bb07f96292Sara Ting        assertEquals(3, high.size());
91421af116207d5728a312e534b898933bb07f96292Sara Ting        assertEquals(0, medium.size());
91521af116207d5728a312e534b898933bb07f96292Sara Ting        assertEquals(0, low.size());
91621af116207d5728a312e534b898933bb07f96292Sara Ting
91721af116207d5728a312e534b898933bb07f96292Sara Ting        // Test when max notifications at medium priority.
91821af116207d5728a312e534b898933bb07f96292Sara Ting        high = new ArrayList<NotificationInfo>();
91921af116207d5728a312e534b898933bb07f96292Sara Ting        medium = threeItemList;
92021af116207d5728a312e534b898933bb07f96292Sara Ting        low = new ArrayList<NotificationInfo>();
92121af116207d5728a312e534b898933bb07f96292Sara Ting        AlertService.redistributeBuckets(high, medium, low, maxNotifications);
92221af116207d5728a312e534b898933bb07f96292Sara Ting        assertEquals(0, high.size());
92321af116207d5728a312e534b898933bb07f96292Sara Ting        assertEquals(3, medium.size());
92421af116207d5728a312e534b898933bb07f96292Sara Ting        assertEquals(0, low.size());
92521af116207d5728a312e534b898933bb07f96292Sara Ting
92621af116207d5728a312e534b898933bb07f96292Sara Ting        // Test when max notifications at high and medium priority
92721af116207d5728a312e534b898933bb07f96292Sara Ting        high = new ArrayList<NotificationInfo>(threeItemList);
92821af116207d5728a312e534b898933bb07f96292Sara Ting        medium = new ArrayList<NotificationInfo>();
92921af116207d5728a312e534b898933bb07f96292Sara Ting        medium.add(high.remove(1));
93021af116207d5728a312e534b898933bb07f96292Sara Ting        low = new ArrayList<NotificationInfo>();
93121af116207d5728a312e534b898933bb07f96292Sara Ting        AlertService.redistributeBuckets(high, medium, low, maxNotifications);
93221af116207d5728a312e534b898933bb07f96292Sara Ting        assertEquals(2, high.size());
93321af116207d5728a312e534b898933bb07f96292Sara Ting        assertEquals(1, medium.size());
93421af116207d5728a312e534b898933bb07f96292Sara Ting        assertEquals(0, low.size());
93521af116207d5728a312e534b898933bb07f96292Sara Ting    }
93621af116207d5728a312e534b898933bb07f96292Sara Ting
93721af116207d5728a312e534b898933bb07f96292Sara Ting    @SmallTest
93821af116207d5728a312e534b898933bb07f96292Sara Ting    public void testRedistributeBuckets_tooManyHighPriority() throws Exception {
93921af116207d5728a312e534b898933bb07f96292Sara Ting        ArrayList<NotificationInfo> high = new ArrayList<NotificationInfo>();
94021af116207d5728a312e534b898933bb07f96292Sara Ting        ArrayList<NotificationInfo> medium = new ArrayList<NotificationInfo>();
94121af116207d5728a312e534b898933bb07f96292Sara Ting        ArrayList<NotificationInfo> low = new ArrayList<NotificationInfo>();
94221af116207d5728a312e534b898933bb07f96292Sara Ting        high.add(createNotificationInfo(5));
94321af116207d5728a312e534b898933bb07f96292Sara Ting        high.add(createNotificationInfo(4));
94421af116207d5728a312e534b898933bb07f96292Sara Ting        high.add(createNotificationInfo(3));
94521af116207d5728a312e534b898933bb07f96292Sara Ting        high.add(createNotificationInfo(2));
94621af116207d5728a312e534b898933bb07f96292Sara Ting        high.add(createNotificationInfo(1));
94721af116207d5728a312e534b898933bb07f96292Sara Ting
94821af116207d5728a312e534b898933bb07f96292Sara Ting        // Invoke the method under test.
94921af116207d5728a312e534b898933bb07f96292Sara Ting        int maxNotifications = 3;
95021af116207d5728a312e534b898933bb07f96292Sara Ting        AlertService.redistributeBuckets(high, medium, low, maxNotifications);
95121af116207d5728a312e534b898933bb07f96292Sara Ting
95221af116207d5728a312e534b898933bb07f96292Sara Ting        // Verify some high priority were kicked out.
95321af116207d5728a312e534b898933bb07f96292Sara Ting        assertEquals(3, high.size());
95421af116207d5728a312e534b898933bb07f96292Sara Ting        assertEquals(3, high.get(0).eventId);
95521af116207d5728a312e534b898933bb07f96292Sara Ting        assertEquals(2, high.get(1).eventId);
95621af116207d5728a312e534b898933bb07f96292Sara Ting        assertEquals(1, high.get(2).eventId);
95721af116207d5728a312e534b898933bb07f96292Sara Ting
95821af116207d5728a312e534b898933bb07f96292Sara Ting        // Verify medium priority untouched.
95921af116207d5728a312e534b898933bb07f96292Sara Ting        assertEquals(0, medium.size());
96021af116207d5728a312e534b898933bb07f96292Sara Ting
96121af116207d5728a312e534b898933bb07f96292Sara Ting        // Verify the extras went to low priority.
96221af116207d5728a312e534b898933bb07f96292Sara Ting        assertEquals(2, low.size());
96321af116207d5728a312e534b898933bb07f96292Sara Ting        assertEquals(5, low.get(0).eventId);
96421af116207d5728a312e534b898933bb07f96292Sara Ting        assertEquals(4, low.get(1).eventId);
96521af116207d5728a312e534b898933bb07f96292Sara Ting    }
96621af116207d5728a312e534b898933bb07f96292Sara Ting
96721af116207d5728a312e534b898933bb07f96292Sara Ting    @SmallTest
96821af116207d5728a312e534b898933bb07f96292Sara Ting    public void testRedistributeBuckets_tooManyMediumPriority() throws Exception {
96921af116207d5728a312e534b898933bb07f96292Sara Ting        ArrayList<NotificationInfo> high = new ArrayList<NotificationInfo>();
97021af116207d5728a312e534b898933bb07f96292Sara Ting        ArrayList<NotificationInfo> medium = new ArrayList<NotificationInfo>();
97121af116207d5728a312e534b898933bb07f96292Sara Ting        ArrayList<NotificationInfo> low = new ArrayList<NotificationInfo>();
97221af116207d5728a312e534b898933bb07f96292Sara Ting        high.add(createNotificationInfo(5));
97321af116207d5728a312e534b898933bb07f96292Sara Ting        high.add(createNotificationInfo(4));
97421af116207d5728a312e534b898933bb07f96292Sara Ting        medium.add(createNotificationInfo(3));
97521af116207d5728a312e534b898933bb07f96292Sara Ting        medium.add(createNotificationInfo(2));
97621af116207d5728a312e534b898933bb07f96292Sara Ting        medium.add(createNotificationInfo(1));
97721af116207d5728a312e534b898933bb07f96292Sara Ting
97821af116207d5728a312e534b898933bb07f96292Sara Ting        // Invoke the method under test.
97921af116207d5728a312e534b898933bb07f96292Sara Ting        int maxNotifications = 3;
98021af116207d5728a312e534b898933bb07f96292Sara Ting        AlertService.redistributeBuckets(high, medium, low, maxNotifications);
98121af116207d5728a312e534b898933bb07f96292Sara Ting
98221af116207d5728a312e534b898933bb07f96292Sara Ting        // Verify high priority untouched.
98321af116207d5728a312e534b898933bb07f96292Sara Ting        assertEquals(2, high.size());
98421af116207d5728a312e534b898933bb07f96292Sara Ting        assertEquals(5, high.get(0).eventId);
98521af116207d5728a312e534b898933bb07f96292Sara Ting        assertEquals(4, high.get(1).eventId);
98621af116207d5728a312e534b898933bb07f96292Sara Ting
98721af116207d5728a312e534b898933bb07f96292Sara Ting        // Verify some medium priority were kicked out (the ones near the end of the
98821af116207d5728a312e534b898933bb07f96292Sara Ting        // list).
98921af116207d5728a312e534b898933bb07f96292Sara Ting        assertEquals(1, medium.size());
99021af116207d5728a312e534b898933bb07f96292Sara Ting        assertEquals(3, medium.get(0).eventId);
99121af116207d5728a312e534b898933bb07f96292Sara Ting
99221af116207d5728a312e534b898933bb07f96292Sara Ting        // Verify the extras went to low priority.
99321af116207d5728a312e534b898933bb07f96292Sara Ting        assertEquals(2, low.size());
99421af116207d5728a312e534b898933bb07f96292Sara Ting        assertEquals(2, low.get(0).eventId);
99521af116207d5728a312e534b898933bb07f96292Sara Ting        assertEquals(1, low.get(1).eventId);
99621af116207d5728a312e534b898933bb07f96292Sara Ting    }
99721af116207d5728a312e534b898933bb07f96292Sara Ting
99821af116207d5728a312e534b898933bb07f96292Sara Ting    @SmallTest
99921af116207d5728a312e534b898933bb07f96292Sara Ting    public void testRedistributeBuckets_tooManyHighMediumPriority() throws Exception {
100021af116207d5728a312e534b898933bb07f96292Sara Ting        ArrayList<NotificationInfo> high = new ArrayList<NotificationInfo>();
100121af116207d5728a312e534b898933bb07f96292Sara Ting        ArrayList<NotificationInfo> medium = new ArrayList<NotificationInfo>();
100221af116207d5728a312e534b898933bb07f96292Sara Ting        ArrayList<NotificationInfo> low = new ArrayList<NotificationInfo>();
100321af116207d5728a312e534b898933bb07f96292Sara Ting        high.add(createNotificationInfo(8));
100421af116207d5728a312e534b898933bb07f96292Sara Ting        high.add(createNotificationInfo(7));
100521af116207d5728a312e534b898933bb07f96292Sara Ting        high.add(createNotificationInfo(6));
100621af116207d5728a312e534b898933bb07f96292Sara Ting        high.add(createNotificationInfo(5));
100721af116207d5728a312e534b898933bb07f96292Sara Ting        high.add(createNotificationInfo(4));
100821af116207d5728a312e534b898933bb07f96292Sara Ting        medium.add(createNotificationInfo(3));
100921af116207d5728a312e534b898933bb07f96292Sara Ting        medium.add(createNotificationInfo(2));
101021af116207d5728a312e534b898933bb07f96292Sara Ting        medium.add(createNotificationInfo(1));
101121af116207d5728a312e534b898933bb07f96292Sara Ting
101221af116207d5728a312e534b898933bb07f96292Sara Ting        // Invoke the method under test.
101321af116207d5728a312e534b898933bb07f96292Sara Ting        int maxNotifications = 3;
101421af116207d5728a312e534b898933bb07f96292Sara Ting        AlertService.redistributeBuckets(high, medium, low, maxNotifications);
101521af116207d5728a312e534b898933bb07f96292Sara Ting
101621af116207d5728a312e534b898933bb07f96292Sara Ting        // Verify high priority.
101721af116207d5728a312e534b898933bb07f96292Sara Ting        assertEquals(3, high.size());
101821af116207d5728a312e534b898933bb07f96292Sara Ting        assertEquals(6, high.get(0).eventId);
101921af116207d5728a312e534b898933bb07f96292Sara Ting        assertEquals(5, high.get(1).eventId);
102021af116207d5728a312e534b898933bb07f96292Sara Ting        assertEquals(4, high.get(2).eventId);
102121af116207d5728a312e534b898933bb07f96292Sara Ting
102221af116207d5728a312e534b898933bb07f96292Sara Ting        // Verify some medium priority.
102321af116207d5728a312e534b898933bb07f96292Sara Ting        assertEquals(0, medium.size());
102421af116207d5728a312e534b898933bb07f96292Sara Ting
102521af116207d5728a312e534b898933bb07f96292Sara Ting        // Verify low priority.
102621af116207d5728a312e534b898933bb07f96292Sara Ting        assertEquals(5, low.size());
102721af116207d5728a312e534b898933bb07f96292Sara Ting        assertEquals(8, low.get(0).eventId);
102821af116207d5728a312e534b898933bb07f96292Sara Ting        assertEquals(7, low.get(1).eventId);
102921af116207d5728a312e534b898933bb07f96292Sara Ting        assertEquals(3, low.get(2).eventId);
103021af116207d5728a312e534b898933bb07f96292Sara Ting        assertEquals(2, low.get(3).eventId);
103121af116207d5728a312e534b898933bb07f96292Sara Ting        assertEquals(1, low.get(4).eventId);
103221af116207d5728a312e534b898933bb07f96292Sara Ting    }
103325b09db869f377b131052447f62ad02e2505cd87Michael Chan}
1034