1 /* 2 * Copyright (C) 2021 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 package com.android.calendar.alerts 17 18 import android.app.IntentService 19 import android.app.NotificationManager 20 import android.content.ContentResolver 21 import android.content.ContentValues 22 import android.content.Context 23 import android.content.Intent 24 import android.net.Uri 25 import android.os.IBinder 26 import android.provider.CalendarContract.CalendarAlerts 27 import androidx.core.app.TaskStackBuilder 28 import android.util.Log 29 import com.android.calendar.EventInfoActivity 30 import com.android.calendar.alerts.GlobalDismissManager.AlarmId 31 import java.util.LinkedList 32 import java.util.List 33 34 /** 35 * Service for asynchronously marking fired alarms as dismissed. 36 */ 37 class DismissAlarmsService : IntentService("DismissAlarmsService") { 38 @Override onBindnull39 override fun onBind(intent: Intent?): IBinder? { 40 return null 41 } 42 43 @Override onHandleIntentnull44 override fun onHandleIntent(intent: Intent?) { 45 if (AlertService.DEBUG) { 46 Log.d(TAG, "onReceive: a=" + intent?.getAction().toString() + " " + intent.toString()) 47 } 48 val eventId = intent?.getLongExtra(AlertUtils.EVENT_ID_KEY, -1) 49 val eventStart = intent?.getLongExtra(AlertUtils.EVENT_START_KEY, -1) 50 val eventEnd = intent?.getLongExtra(AlertUtils.EVENT_END_KEY, -1) 51 val eventIds = intent?.getLongArrayExtra(AlertUtils.EVENT_IDS_KEY) 52 val eventStarts = intent?.getLongArrayExtra(AlertUtils.EVENT_STARTS_KEY) 53 val notificationId = intent?.getIntExtra(AlertUtils.NOTIFICATION_ID_KEY, -1) 54 val alarmIds = LinkedList<AlarmId>() 55 val uri: Uri = CalendarAlerts.CONTENT_URI 56 val selection: String 57 58 // Dismiss a specific fired alarm if id is present, otherwise, dismiss all alarms 59 if (eventId != -1L) { 60 alarmIds.add(AlarmId(eventId as Long, eventStart as Long)) 61 selection = 62 CalendarAlerts.STATE.toString() + "=" + CalendarAlerts.STATE_FIRED + " AND " + 63 CalendarAlerts.EVENT_ID + "=" + eventId 64 } else if (eventIds != null && eventIds.size > 0 && eventStarts != null && 65 eventIds.size == eventStarts.size) { 66 selection = buildMultipleEventsQuery(eventIds) 67 for (i in eventIds.indices) { 68 alarmIds.add(AlarmId(eventIds[i], eventStarts[i])) 69 } 70 } else { 71 // NOTE: I don't believe that this ever happens. 72 selection = CalendarAlerts.STATE.toString() + "=" + CalendarAlerts.STATE_FIRED 73 } 74 GlobalDismissManager.dismissGlobally(getApplicationContext(), 75 alarmIds as List<GlobalDismissManager.AlarmId>) 76 val resolver: ContentResolver = getContentResolver() 77 val values = ContentValues() 78 values.put(PROJECTION[COLUMN_INDEX_STATE], CalendarAlerts.STATE_DISMISSED) 79 resolver.update(uri, values, selection, null) 80 81 // Remove from notification bar. 82 if (notificationId != -1) { 83 val nm: NotificationManager = 84 getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager 85 nm.cancel(notificationId as Int) 86 } 87 if (SHOW_ACTION.equals(intent.getAction())) { 88 // Show event on Calendar app by building an intent and task stack to start 89 // EventInfoActivity with AllInOneActivity as the parent activity rooted to home. 90 val i: Intent = AlertUtils.buildEventViewIntent(this, eventId as Long, 91 eventStart as Long, eventEnd as Long) 92 TaskStackBuilder.create(this) 93 .addParentStack(EventInfoActivity::class.java).addNextIntent(i).startActivities() 94 } 95 } 96 buildMultipleEventsQuerynull97 private fun buildMultipleEventsQuery(eventIds: LongArray): String { 98 val selection = StringBuilder() 99 selection.append(CalendarAlerts.STATE) 100 selection.append("=") 101 selection.append(CalendarAlerts.STATE_FIRED) 102 if (eventIds.size > 0) { 103 selection.append(" AND (") 104 selection.append(CalendarAlerts.EVENT_ID) 105 selection.append("=") 106 selection.append(eventIds[0]) 107 for (i in 1 until eventIds.size) { 108 selection.append(" OR ") 109 selection.append(CalendarAlerts.EVENT_ID) 110 selection.append("=") 111 selection.append(eventIds[i]) 112 } 113 selection.append(")") 114 } 115 return selection.toString() 116 } 117 118 companion object { 119 private const val TAG = "DismissAlarmsService" 120 const val SHOW_ACTION = "com.android.calendar.SHOW" 121 const val DISMISS_ACTION = "com.android.calendar.DISMISS" 122 private val PROJECTION = arrayOf<String>( 123 CalendarAlerts.STATE 124 ) 125 private const val COLUMN_INDEX_STATE = 0 126 } 127 }