19881907c47b2658fa85954bfb339c4b1eab9fc8eIsaac Katzenelson/*
29881907c47b2658fa85954bfb339c4b1eab9fc8eIsaac Katzenelson * Copyright (C) 2009 The Android Open Source Project
39881907c47b2658fa85954bfb339c4b1eab9fc8eIsaac Katzenelson *
49881907c47b2658fa85954bfb339c4b1eab9fc8eIsaac Katzenelson * Licensed under the Apache License, Version 2.0 (the "License");
59881907c47b2658fa85954bfb339c4b1eab9fc8eIsaac Katzenelson * you may not use this file except in compliance with the License.
69881907c47b2658fa85954bfb339c4b1eab9fc8eIsaac Katzenelson * You may obtain a copy of the License at
79881907c47b2658fa85954bfb339c4b1eab9fc8eIsaac Katzenelson *
89881907c47b2658fa85954bfb339c4b1eab9fc8eIsaac Katzenelson *      http://www.apache.org/licenses/LICENSE-2.0
99881907c47b2658fa85954bfb339c4b1eab9fc8eIsaac Katzenelson *
109881907c47b2658fa85954bfb339c4b1eab9fc8eIsaac Katzenelson * Unless required by applicable law or agreed to in writing, software
119881907c47b2658fa85954bfb339c4b1eab9fc8eIsaac Katzenelson * distributed under the License is distributed on an "AS IS" BASIS,
129881907c47b2658fa85954bfb339c4b1eab9fc8eIsaac Katzenelson * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139881907c47b2658fa85954bfb339c4b1eab9fc8eIsaac Katzenelson * See the License for the specific language governing permissions and
149881907c47b2658fa85954bfb339c4b1eab9fc8eIsaac Katzenelson * limitations under the License
159881907c47b2658fa85954bfb339c4b1eab9fc8eIsaac Katzenelson */
169881907c47b2658fa85954bfb339c4b1eab9fc8eIsaac Katzenelson
179881907c47b2658fa85954bfb339c4b1eab9fc8eIsaac Katzenelsonpackage com.android.calendar.alerts;
189881907c47b2658fa85954bfb339c4b1eab9fc8eIsaac Katzenelson
199881907c47b2658fa85954bfb339c4b1eab9fc8eIsaac Katzenelsonimport android.app.IntentService;
20132eeb8acba46be5d0a3dc69b3a4dc0876430b08Michael Chanimport android.app.NotificationManager;
219881907c47b2658fa85954bfb339c4b1eab9fc8eIsaac Katzenelsonimport android.content.ContentResolver;
229881907c47b2658fa85954bfb339c4b1eab9fc8eIsaac Katzenelsonimport android.content.ContentValues;
23132eeb8acba46be5d0a3dc69b3a4dc0876430b08Michael Chanimport android.content.Context;
249881907c47b2658fa85954bfb339c4b1eab9fc8eIsaac Katzenelsonimport android.content.Intent;
259881907c47b2658fa85954bfb339c4b1eab9fc8eIsaac Katzenelsonimport android.net.Uri;
269881907c47b2658fa85954bfb339c4b1eab9fc8eIsaac Katzenelsonimport android.os.IBinder;
279881907c47b2658fa85954bfb339c4b1eab9fc8eIsaac Katzenelsonimport android.provider.CalendarContract.CalendarAlerts;
28bb768dfe3a03187401b9476cacbdcc5cbcfa9babIsaac Katzenelsonimport android.support.v4.app.TaskStackBuilder;
299881907c47b2658fa85954bfb339c4b1eab9fc8eIsaac Katzenelson
309675253917e4207a811386ace164f5238ec0d25cPaul Sliwowskiimport android.util.Log;
310ef732f240516f9f8b8add982f82244e01ec509bIsaac Katzenelsonimport com.android.calendar.EventInfoActivity;
32fec5bff4f2d3c50bc7d644b21acca37f320358e0Chris Wrenimport com.android.calendar.alerts.GlobalDismissManager.AlarmId;
33fec5bff4f2d3c50bc7d644b21acca37f320358e0Chris Wren
34fec5bff4f2d3c50bc7d644b21acca37f320358e0Chris Wrenimport java.util.LinkedList;
35fec5bff4f2d3c50bc7d644b21acca37f320358e0Chris Wrenimport java.util.List;
360ef732f240516f9f8b8add982f82244e01ec509bIsaac Katzenelson
379881907c47b2658fa85954bfb339c4b1eab9fc8eIsaac Katzenelson/**
3842ba5efed5945b0e96735ec9ca4b388ae35b56f7Sara Ting * Service for asynchronously marking fired alarms as dismissed.
399881907c47b2658fa85954bfb339c4b1eab9fc8eIsaac Katzenelson */
409881907c47b2658fa85954bfb339c4b1eab9fc8eIsaac Katzenelsonpublic class DismissAlarmsService extends IntentService {
419675253917e4207a811386ace164f5238ec0d25cPaul Sliwowski    private static final String TAG = "DismissAlarmsService";
42c0e5679492faf8b3d437e658449083324d062119Paul Sliwowski    public static final String SHOW_ACTION = "com.android.calendar.SHOW";
43c0e5679492faf8b3d437e658449083324d062119Paul Sliwowski    public static final String DISMISS_ACTION = "com.android.calendar.DISMISS";
449675253917e4207a811386ace164f5238ec0d25cPaul Sliwowski
459881907c47b2658fa85954bfb339c4b1eab9fc8eIsaac Katzenelson    private static final String[] PROJECTION = new String[] {
469881907c47b2658fa85954bfb339c4b1eab9fc8eIsaac Katzenelson            CalendarAlerts.STATE,
479881907c47b2658fa85954bfb339c4b1eab9fc8eIsaac Katzenelson    };
489881907c47b2658fa85954bfb339c4b1eab9fc8eIsaac Katzenelson    private static final int COLUMN_INDEX_STATE = 0;
499881907c47b2658fa85954bfb339c4b1eab9fc8eIsaac Katzenelson
509881907c47b2658fa85954bfb339c4b1eab9fc8eIsaac Katzenelson    public DismissAlarmsService() {
519881907c47b2658fa85954bfb339c4b1eab9fc8eIsaac Katzenelson        super("DismissAlarmsService");
529881907c47b2658fa85954bfb339c4b1eab9fc8eIsaac Katzenelson    }
539881907c47b2658fa85954bfb339c4b1eab9fc8eIsaac Katzenelson
549881907c47b2658fa85954bfb339c4b1eab9fc8eIsaac Katzenelson    @Override
559881907c47b2658fa85954bfb339c4b1eab9fc8eIsaac Katzenelson    public IBinder onBind(Intent intent) {
569881907c47b2658fa85954bfb339c4b1eab9fc8eIsaac Katzenelson        return null;
579881907c47b2658fa85954bfb339c4b1eab9fc8eIsaac Katzenelson    }
589881907c47b2658fa85954bfb339c4b1eab9fc8eIsaac Katzenelson
599881907c47b2658fa85954bfb339c4b1eab9fc8eIsaac Katzenelson    @Override
609881907c47b2658fa85954bfb339c4b1eab9fc8eIsaac Katzenelson    public void onHandleIntent(Intent intent) {
61c0e5679492faf8b3d437e658449083324d062119Paul Sliwowski        if (AlertService.DEBUG) {
62c0e5679492faf8b3d437e658449083324d062119Paul Sliwowski            Log.d(TAG, "onReceive: a=" + intent.getAction() + " " + intent.toString());
639675253917e4207a811386ace164f5238ec0d25cPaul Sliwowski        }
649881907c47b2658fa85954bfb339c4b1eab9fc8eIsaac Katzenelson
659881907c47b2658fa85954bfb339c4b1eab9fc8eIsaac Katzenelson        long eventId = intent.getLongExtra(AlertUtils.EVENT_ID_KEY, -1);
669881907c47b2658fa85954bfb339c4b1eab9fc8eIsaac Katzenelson        long eventStart = intent.getLongExtra(AlertUtils.EVENT_START_KEY, -1);
679881907c47b2658fa85954bfb339c4b1eab9fc8eIsaac Katzenelson        long eventEnd = intent.getLongExtra(AlertUtils.EVENT_END_KEY, -1);
68660f1b4ab88bed6e8066ad05b324e95a9940cf73Sara Ting        long[] eventIds = intent.getLongArrayExtra(AlertUtils.EVENT_IDS_KEY);
69fec5bff4f2d3c50bc7d644b21acca37f320358e0Chris Wren        long[] eventStarts = intent.getLongArrayExtra(AlertUtils.EVENT_STARTS_KEY);
70ff23072c5ab5433db376db88f23554c45297db05Sara Ting        int notificationId = intent.getIntExtra(AlertUtils.NOTIFICATION_ID_KEY, -1);
71fec5bff4f2d3c50bc7d644b21acca37f320358e0Chris Wren        List<AlarmId> alarmIds = new LinkedList<AlarmId>();
729881907c47b2658fa85954bfb339c4b1eab9fc8eIsaac Katzenelson
739881907c47b2658fa85954bfb339c4b1eab9fc8eIsaac Katzenelson        Uri uri = CalendarAlerts.CONTENT_URI;
749881907c47b2658fa85954bfb339c4b1eab9fc8eIsaac Katzenelson        String selection;
759881907c47b2658fa85954bfb339c4b1eab9fc8eIsaac Katzenelson
769881907c47b2658fa85954bfb339c4b1eab9fc8eIsaac Katzenelson        // Dismiss a specific fired alarm if id is present, otherwise, dismiss all alarms
779881907c47b2658fa85954bfb339c4b1eab9fc8eIsaac Katzenelson        if (eventId != -1) {
78fec5bff4f2d3c50bc7d644b21acca37f320358e0Chris Wren            alarmIds.add(new AlarmId(eventId, eventStart));
799881907c47b2658fa85954bfb339c4b1eab9fc8eIsaac Katzenelson            selection = CalendarAlerts.STATE + "=" + CalendarAlerts.STATE_FIRED + " AND " +
809881907c47b2658fa85954bfb339c4b1eab9fc8eIsaac Katzenelson            CalendarAlerts.EVENT_ID + "=" + eventId;
81fec5bff4f2d3c50bc7d644b21acca37f320358e0Chris Wren        } else if (eventIds != null && eventIds.length > 0 &&
82fec5bff4f2d3c50bc7d644b21acca37f320358e0Chris Wren                eventStarts != null && eventIds.length == eventStarts.length) {
83660f1b4ab88bed6e8066ad05b324e95a9940cf73Sara Ting            selection = buildMultipleEventsQuery(eventIds);
84b07322485b83b86f5807faacbb6a18e38bec5d6bChris Wren            for (int i = 0; i < eventIds.length; i++) {
85fec5bff4f2d3c50bc7d644b21acca37f320358e0Chris Wren                alarmIds.add(new AlarmId(eventIds[i], eventStarts[i]));
86fec5bff4f2d3c50bc7d644b21acca37f320358e0Chris Wren            }
879881907c47b2658fa85954bfb339c4b1eab9fc8eIsaac Katzenelson        } else {
88fec5bff4f2d3c50bc7d644b21acca37f320358e0Chris Wren            // NOTE: I don't believe that this ever happens.
899881907c47b2658fa85954bfb339c4b1eab9fc8eIsaac Katzenelson            selection = CalendarAlerts.STATE + "=" + CalendarAlerts.STATE_FIRED;
909881907c47b2658fa85954bfb339c4b1eab9fc8eIsaac Katzenelson        }
91660f1b4ab88bed6e8066ad05b324e95a9940cf73Sara Ting
92fec5bff4f2d3c50bc7d644b21acca37f320358e0Chris Wren        GlobalDismissManager.dismissGlobally(getApplicationContext(), alarmIds);
93fec5bff4f2d3c50bc7d644b21acca37f320358e0Chris Wren
949881907c47b2658fa85954bfb339c4b1eab9fc8eIsaac Katzenelson        ContentResolver resolver = getContentResolver();
959881907c47b2658fa85954bfb339c4b1eab9fc8eIsaac Katzenelson        ContentValues values = new ContentValues();
969881907c47b2658fa85954bfb339c4b1eab9fc8eIsaac Katzenelson        values.put(PROJECTION[COLUMN_INDEX_STATE], CalendarAlerts.STATE_DISMISSED);
979881907c47b2658fa85954bfb339c4b1eab9fc8eIsaac Katzenelson        resolver.update(uri, values, selection, null);
9842ba5efed5945b0e96735ec9ca4b388ae35b56f7Sara Ting
9942ba5efed5945b0e96735ec9ca4b388ae35b56f7Sara Ting        // Remove from notification bar.
100ff23072c5ab5433db376db88f23554c45297db05Sara Ting        if (notificationId != -1) {
101ff23072c5ab5433db376db88f23554c45297db05Sara Ting            NotificationManager nm =
102ff23072c5ab5433db376db88f23554c45297db05Sara Ting                    (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
103ff23072c5ab5433db376db88f23554c45297db05Sara Ting            nm.cancel(notificationId);
104ff23072c5ab5433db376db88f23554c45297db05Sara Ting        }
10542ba5efed5945b0e96735ec9ca4b388ae35b56f7Sara Ting
106c0e5679492faf8b3d437e658449083324d062119Paul Sliwowski        if (SHOW_ACTION.equals(intent.getAction())) {
1070ef732f240516f9f8b8add982f82244e01ec509bIsaac Katzenelson            // Show event on Calendar app by building an intent and task stack to start
1080ef732f240516f9f8b8add982f82244e01ec509bIsaac Katzenelson            // EventInfoActivity with AllInOneActivity as the parent activity rooted to home.
1099881907c47b2658fa85954bfb339c4b1eab9fc8eIsaac Katzenelson            Intent i = AlertUtils.buildEventViewIntent(this, eventId, eventStart, eventEnd);
110693ca60d79650af15ab226f7ce6958f61fb7de39Michael Chan
111bb768dfe3a03187401b9476cacbdcc5cbcfa9babIsaac Katzenelson            TaskStackBuilder.create(this)
112bb768dfe3a03187401b9476cacbdcc5cbcfa9babIsaac Katzenelson                    .addParentStack(EventInfoActivity.class).addNextIntent(i).startActivities();
1139881907c47b2658fa85954bfb339c4b1eab9fc8eIsaac Katzenelson        }
1149881907c47b2658fa85954bfb339c4b1eab9fc8eIsaac Katzenelson    }
115660f1b4ab88bed6e8066ad05b324e95a9940cf73Sara Ting
116660f1b4ab88bed6e8066ad05b324e95a9940cf73Sara Ting    private String buildMultipleEventsQuery(long[] eventIds) {
117660f1b4ab88bed6e8066ad05b324e95a9940cf73Sara Ting        StringBuilder selection = new StringBuilder();
118660f1b4ab88bed6e8066ad05b324e95a9940cf73Sara Ting        selection.append(CalendarAlerts.STATE);
119660f1b4ab88bed6e8066ad05b324e95a9940cf73Sara Ting        selection.append("=");
120660f1b4ab88bed6e8066ad05b324e95a9940cf73Sara Ting        selection.append(CalendarAlerts.STATE_FIRED);
121660f1b4ab88bed6e8066ad05b324e95a9940cf73Sara Ting        if (eventIds.length > 0) {
122660f1b4ab88bed6e8066ad05b324e95a9940cf73Sara Ting            selection.append(" AND (");
123660f1b4ab88bed6e8066ad05b324e95a9940cf73Sara Ting            selection.append(CalendarAlerts.EVENT_ID);
124660f1b4ab88bed6e8066ad05b324e95a9940cf73Sara Ting            selection.append("=");
125660f1b4ab88bed6e8066ad05b324e95a9940cf73Sara Ting            selection.append(eventIds[0]);
126660f1b4ab88bed6e8066ad05b324e95a9940cf73Sara Ting            for (int i = 1; i < eventIds.length; i++) {
127660f1b4ab88bed6e8066ad05b324e95a9940cf73Sara Ting                selection.append(" OR ");
128660f1b4ab88bed6e8066ad05b324e95a9940cf73Sara Ting                selection.append(CalendarAlerts.EVENT_ID);
129660f1b4ab88bed6e8066ad05b324e95a9940cf73Sara Ting                selection.append("=");
130660f1b4ab88bed6e8066ad05b324e95a9940cf73Sara Ting                selection.append(eventIds[i]);
131660f1b4ab88bed6e8066ad05b324e95a9940cf73Sara Ting            }
132660f1b4ab88bed6e8066ad05b324e95a9940cf73Sara Ting            selection.append(")");
133660f1b4ab88bed6e8066ad05b324e95a9940cf73Sara Ting        }
134660f1b4ab88bed6e8066ad05b324e95a9940cf73Sara Ting        return selection.toString();
135660f1b4ab88bed6e8066ad05b324e95a9940cf73Sara Ting    }
1369881907c47b2658fa85954bfb339c4b1eab9fc8eIsaac Katzenelson}
137