1 /*
2  * Copyright (C) 2009 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License
15  */
16 
17 package com.android.calendar.alerts;
18 
19 import android.app.IntentService;
20 import android.app.NotificationManager;
21 import android.content.ContentResolver;
22 import android.content.ContentValues;
23 import android.content.Context;
24 import android.content.Intent;
25 import android.net.Uri;
26 import android.os.IBinder;
27 import android.provider.CalendarContract.CalendarAlerts;
28 import android.support.v4.app.TaskStackBuilder;
29 
30 import android.util.Log;
31 import com.android.calendar.EventInfoActivity;
32 import com.android.calendar.alerts.GlobalDismissManager.AlarmId;
33 
34 import java.util.LinkedList;
35 import java.util.List;
36 
37 /**
38  * Service for asynchronously marking fired alarms as dismissed.
39  */
40 public class DismissAlarmsService extends IntentService {
41     private static final String TAG = "DismissAlarmsService";
42     public static final String SHOW_ACTION = "com.android.calendar.SHOW";
43     public static final String DISMISS_ACTION = "com.android.calendar.DISMISS";
44 
45     private static final String[] PROJECTION = new String[] {
46             CalendarAlerts.STATE,
47     };
48     private static final int COLUMN_INDEX_STATE = 0;
49 
DismissAlarmsService()50     public DismissAlarmsService() {
51         super("DismissAlarmsService");
52     }
53 
54     @Override
onBind(Intent intent)55     public IBinder onBind(Intent intent) {
56         return null;
57     }
58 
59     @Override
onHandleIntent(Intent intent)60     public void onHandleIntent(Intent intent) {
61         if (AlertService.DEBUG) {
62             Log.d(TAG, "onReceive: a=" + intent.getAction() + " " + intent.toString());
63         }
64 
65         long eventId = intent.getLongExtra(AlertUtils.EVENT_ID_KEY, -1);
66         long eventStart = intent.getLongExtra(AlertUtils.EVENT_START_KEY, -1);
67         long eventEnd = intent.getLongExtra(AlertUtils.EVENT_END_KEY, -1);
68         long[] eventIds = intent.getLongArrayExtra(AlertUtils.EVENT_IDS_KEY);
69         long[] eventStarts = intent.getLongArrayExtra(AlertUtils.EVENT_STARTS_KEY);
70         int notificationId = intent.getIntExtra(AlertUtils.NOTIFICATION_ID_KEY, -1);
71         List<AlarmId> alarmIds = new LinkedList<AlarmId>();
72 
73         Uri uri = CalendarAlerts.CONTENT_URI;
74         String selection;
75 
76         // Dismiss a specific fired alarm if id is present, otherwise, dismiss all alarms
77         if (eventId != -1) {
78             alarmIds.add(new AlarmId(eventId, eventStart));
79             selection = CalendarAlerts.STATE + "=" + CalendarAlerts.STATE_FIRED + " AND " +
80             CalendarAlerts.EVENT_ID + "=" + eventId;
81         } else if (eventIds != null && eventIds.length > 0 &&
82                 eventStarts != null && eventIds.length == eventStarts.length) {
83             selection = buildMultipleEventsQuery(eventIds);
84             for (int i = 0; i < eventIds.length; i++) {
85                 alarmIds.add(new AlarmId(eventIds[i], eventStarts[i]));
86             }
87         } else {
88             // NOTE: I don't believe that this ever happens.
89             selection = CalendarAlerts.STATE + "=" + CalendarAlerts.STATE_FIRED;
90         }
91 
92         GlobalDismissManager.dismissGlobally(getApplicationContext(), alarmIds);
93 
94         ContentResolver resolver = getContentResolver();
95         ContentValues values = new ContentValues();
96         values.put(PROJECTION[COLUMN_INDEX_STATE], CalendarAlerts.STATE_DISMISSED);
97         resolver.update(uri, values, selection, null);
98 
99         // Remove from notification bar.
100         if (notificationId != -1) {
101             NotificationManager nm =
102                     (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
103             nm.cancel(notificationId);
104         }
105 
106         if (SHOW_ACTION.equals(intent.getAction())) {
107             // Show event on Calendar app by building an intent and task stack to start
108             // EventInfoActivity with AllInOneActivity as the parent activity rooted to home.
109             Intent i = AlertUtils.buildEventViewIntent(this, eventId, eventStart, eventEnd);
110 
111             TaskStackBuilder.create(this)
112                     .addParentStack(EventInfoActivity.class).addNextIntent(i).startActivities();
113         }
114     }
115 
buildMultipleEventsQuery(long[] eventIds)116     private String buildMultipleEventsQuery(long[] eventIds) {
117         StringBuilder selection = new StringBuilder();
118         selection.append(CalendarAlerts.STATE);
119         selection.append("=");
120         selection.append(CalendarAlerts.STATE_FIRED);
121         if (eventIds.length > 0) {
122             selection.append(" AND (");
123             selection.append(CalendarAlerts.EVENT_ID);
124             selection.append("=");
125             selection.append(eventIds[0]);
126             for (int i = 1; i < eventIds.length; i++) {
127                 selection.append(" OR ");
128                 selection.append(CalendarAlerts.EVENT_ID);
129                 selection.append("=");
130                 selection.append(eventIds[i]);
131             }
132             selection.append(")");
133         }
134         return selection.toString();
135     }
136 }
137