1d70f977a2a312353a82ffefeeef67bb23941f78eRahul Ravikumar/* 2d70f977a2a312353a82ffefeeef67bb23941f78eRahul Ravikumar * Copyright 2018 The Android Open Source Project 3d70f977a2a312353a82ffefeeef67bb23941f78eRahul Ravikumar * 4d70f977a2a312353a82ffefeeef67bb23941f78eRahul Ravikumar * Licensed under the Apache License, Version 2.0 (the "License"); 5d70f977a2a312353a82ffefeeef67bb23941f78eRahul Ravikumar * you may not use this file except in compliance with the License. 6d70f977a2a312353a82ffefeeef67bb23941f78eRahul Ravikumar * You may obtain a copy of the License at 7d70f977a2a312353a82ffefeeef67bb23941f78eRahul Ravikumar * 8d70f977a2a312353a82ffefeeef67bb23941f78eRahul Ravikumar * http://www.apache.org/licenses/LICENSE-2.0 9d70f977a2a312353a82ffefeeef67bb23941f78eRahul Ravikumar * 10d70f977a2a312353a82ffefeeef67bb23941f78eRahul Ravikumar * Unless required by applicable law or agreed to in writing, software 11d70f977a2a312353a82ffefeeef67bb23941f78eRahul Ravikumar * distributed under the License is distributed on an "AS IS" BASIS, 12d70f977a2a312353a82ffefeeef67bb23941f78eRahul Ravikumar * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13d70f977a2a312353a82ffefeeef67bb23941f78eRahul Ravikumar * See the License for the specific language governing permissions and 14d70f977a2a312353a82ffefeeef67bb23941f78eRahul Ravikumar * limitations under the License. 15d70f977a2a312353a82ffefeeef67bb23941f78eRahul Ravikumar */ 16d70f977a2a312353a82ffefeeef67bb23941f78eRahul Ravikumar 17d70f977a2a312353a82ffefeeef67bb23941f78eRahul Ravikumarpackage androidx.work.impl.background.systemalarm; 18d70f977a2a312353a82ffefeeef67bb23941f78eRahul Ravikumar 19d70f977a2a312353a82ffefeeef67bb23941f78eRahul Ravikumarimport static android.app.AlarmManager.RTC_WAKEUP; 20d70f977a2a312353a82ffefeeef67bb23941f78eRahul Ravikumar 21d70f977a2a312353a82ffefeeef67bb23941f78eRahul Ravikumarimport android.app.AlarmManager; 22d70f977a2a312353a82ffefeeef67bb23941f78eRahul Ravikumarimport android.app.PendingIntent; 23d70f977a2a312353a82ffefeeef67bb23941f78eRahul Ravikumarimport android.content.Context; 24d70f977a2a312353a82ffefeeef67bb23941f78eRahul Ravikumarimport android.content.Intent; 25d70f977a2a312353a82ffefeeef67bb23941f78eRahul Ravikumarimport android.os.Build; 26d70f977a2a312353a82ffefeeef67bb23941f78eRahul Ravikumarimport android.support.annotation.NonNull; 27d70f977a2a312353a82ffefeeef67bb23941f78eRahul Ravikumarimport android.support.annotation.RestrictTo; 28697d6a4a3797bc71d0dd8685937a318e9934066bRahul Ravikumarimport android.util.Log; 29d70f977a2a312353a82ffefeeef67bb23941f78eRahul Ravikumar 30d70f977a2a312353a82ffefeeef67bb23941f78eRahul Ravikumarimport androidx.work.impl.WorkDatabase; 31d70f977a2a312353a82ffefeeef67bb23941f78eRahul Ravikumarimport androidx.work.impl.WorkManagerImpl; 3218e0a7e02c1198c5b3b33295b148c1017e32f016Rahul Ravikumarimport androidx.work.impl.model.SystemIdInfo; 3318e0a7e02c1198c5b3b33295b148c1017e32f016Rahul Ravikumarimport androidx.work.impl.model.SystemIdInfoDao; 34d70f977a2a312353a82ffefeeef67bb23941f78eRahul Ravikumarimport androidx.work.impl.utils.IdGenerator; 35d70f977a2a312353a82ffefeeef67bb23941f78eRahul Ravikumar 36d70f977a2a312353a82ffefeeef67bb23941f78eRahul Ravikumar/** 37d70f977a2a312353a82ffefeeef67bb23941f78eRahul Ravikumar * A common class for managing Alarms. 38d70f977a2a312353a82ffefeeef67bb23941f78eRahul Ravikumar * 39d70f977a2a312353a82ffefeeef67bb23941f78eRahul Ravikumar * @hide 40d70f977a2a312353a82ffefeeef67bb23941f78eRahul Ravikumar */ 41d70f977a2a312353a82ffefeeef67bb23941f78eRahul Ravikumar@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP) 42d70f977a2a312353a82ffefeeef67bb23941f78eRahul Ravikumarclass Alarms { 43d70f977a2a312353a82ffefeeef67bb23941f78eRahul Ravikumar 44d70f977a2a312353a82ffefeeef67bb23941f78eRahul Ravikumar private static final String TAG = "Alarms"; 45d70f977a2a312353a82ffefeeef67bb23941f78eRahul Ravikumar 46d70f977a2a312353a82ffefeeef67bb23941f78eRahul Ravikumar /** 47d70f977a2a312353a82ffefeeef67bb23941f78eRahul Ravikumar * Sets an exact alarm after cancelling any existing alarms for the given id. 48d70f977a2a312353a82ffefeeef67bb23941f78eRahul Ravikumar * 49d70f977a2a312353a82ffefeeef67bb23941f78eRahul Ravikumar * @param context The application {@link Context}. 50d70f977a2a312353a82ffefeeef67bb23941f78eRahul Ravikumar * @param workManager The instance of {@link WorkManagerImpl}. 51d70f977a2a312353a82ffefeeef67bb23941f78eRahul Ravikumar * @param workSpecId The {@link androidx.work.impl.model.WorkSpec} identifier. 52d70f977a2a312353a82ffefeeef67bb23941f78eRahul Ravikumar * @param triggerAtMillis Determines when to trigger the Alarm. 53d70f977a2a312353a82ffefeeef67bb23941f78eRahul Ravikumar */ 54d70f977a2a312353a82ffefeeef67bb23941f78eRahul Ravikumar public static void setAlarm( 55d70f977a2a312353a82ffefeeef67bb23941f78eRahul Ravikumar @NonNull Context context, 56d70f977a2a312353a82ffefeeef67bb23941f78eRahul Ravikumar @NonNull WorkManagerImpl workManager, 57d70f977a2a312353a82ffefeeef67bb23941f78eRahul Ravikumar @NonNull String workSpecId, 58d70f977a2a312353a82ffefeeef67bb23941f78eRahul Ravikumar long triggerAtMillis) { 59d70f977a2a312353a82ffefeeef67bb23941f78eRahul Ravikumar 60d70f977a2a312353a82ffefeeef67bb23941f78eRahul Ravikumar WorkDatabase workDatabase = workManager.getWorkDatabase(); 6118e0a7e02c1198c5b3b33295b148c1017e32f016Rahul Ravikumar SystemIdInfoDao systemIdInfoDao = workDatabase.systemIdInfoDao(); 6218e0a7e02c1198c5b3b33295b148c1017e32f016Rahul Ravikumar SystemIdInfo systemIdInfo = systemIdInfoDao.getSystemIdInfo(workSpecId); 6318e0a7e02c1198c5b3b33295b148c1017e32f016Rahul Ravikumar if (systemIdInfo != null) { 6418e0a7e02c1198c5b3b33295b148c1017e32f016Rahul Ravikumar cancelExactAlarm(context, workSpecId, systemIdInfo.systemId); 6518e0a7e02c1198c5b3b33295b148c1017e32f016Rahul Ravikumar setExactAlarm(context, workSpecId, systemIdInfo.systemId, triggerAtMillis); 66d70f977a2a312353a82ffefeeef67bb23941f78eRahul Ravikumar } else { 67d70f977a2a312353a82ffefeeef67bb23941f78eRahul Ravikumar IdGenerator idGenerator = new IdGenerator(context); 68d70f977a2a312353a82ffefeeef67bb23941f78eRahul Ravikumar int alarmId = idGenerator.nextAlarmManagerId(); 6918e0a7e02c1198c5b3b33295b148c1017e32f016Rahul Ravikumar SystemIdInfo newSystemIdInfo = new SystemIdInfo(workSpecId, alarmId); 7018e0a7e02c1198c5b3b33295b148c1017e32f016Rahul Ravikumar systemIdInfoDao.insertSystemIdInfo(newSystemIdInfo); 71d70f977a2a312353a82ffefeeef67bb23941f78eRahul Ravikumar setExactAlarm(context, workSpecId, alarmId, triggerAtMillis); 72d70f977a2a312353a82ffefeeef67bb23941f78eRahul Ravikumar } 73d70f977a2a312353a82ffefeeef67bb23941f78eRahul Ravikumar } 74d70f977a2a312353a82ffefeeef67bb23941f78eRahul Ravikumar 75d70f977a2a312353a82ffefeeef67bb23941f78eRahul Ravikumar /** 7618e0a7e02c1198c5b3b33295b148c1017e32f016Rahul Ravikumar * Cancels an existing alarm and removes the {@link SystemIdInfo}. 77d70f977a2a312353a82ffefeeef67bb23941f78eRahul Ravikumar * 78d70f977a2a312353a82ffefeeef67bb23941f78eRahul Ravikumar * @param context The application {@link Context}. 79d70f977a2a312353a82ffefeeef67bb23941f78eRahul Ravikumar * @param workManager The instance of {@link WorkManagerImpl}. 80d70f977a2a312353a82ffefeeef67bb23941f78eRahul Ravikumar * @param workSpecId The {@link androidx.work.impl.model.WorkSpec} identifier. 81d70f977a2a312353a82ffefeeef67bb23941f78eRahul Ravikumar */ 82d70f977a2a312353a82ffefeeef67bb23941f78eRahul Ravikumar public static void cancelAlarm( 83d70f977a2a312353a82ffefeeef67bb23941f78eRahul Ravikumar @NonNull Context context, 84d70f977a2a312353a82ffefeeef67bb23941f78eRahul Ravikumar @NonNull WorkManagerImpl workManager, 85d70f977a2a312353a82ffefeeef67bb23941f78eRahul Ravikumar @NonNull String workSpecId) { 86d70f977a2a312353a82ffefeeef67bb23941f78eRahul Ravikumar 87d70f977a2a312353a82ffefeeef67bb23941f78eRahul Ravikumar WorkDatabase workDatabase = workManager.getWorkDatabase(); 8818e0a7e02c1198c5b3b33295b148c1017e32f016Rahul Ravikumar SystemIdInfoDao systemIdInfoDao = workDatabase.systemIdInfoDao(); 8918e0a7e02c1198c5b3b33295b148c1017e32f016Rahul Ravikumar SystemIdInfo systemIdInfo = systemIdInfoDao.getSystemIdInfo(workSpecId); 9018e0a7e02c1198c5b3b33295b148c1017e32f016Rahul Ravikumar if (systemIdInfo != null) { 9118e0a7e02c1198c5b3b33295b148c1017e32f016Rahul Ravikumar cancelExactAlarm(context, workSpecId, systemIdInfo.systemId); 9218e0a7e02c1198c5b3b33295b148c1017e32f016Rahul Ravikumar Log.d(TAG, String.format("Removing SystemIdInfo for workSpecId (%s)", workSpecId)); 9318e0a7e02c1198c5b3b33295b148c1017e32f016Rahul Ravikumar systemIdInfoDao.removeSystemIdInfo(workSpecId); 94d70f977a2a312353a82ffefeeef67bb23941f78eRahul Ravikumar } 95d70f977a2a312353a82ffefeeef67bb23941f78eRahul Ravikumar } 96d70f977a2a312353a82ffefeeef67bb23941f78eRahul Ravikumar 97d70f977a2a312353a82ffefeeef67bb23941f78eRahul Ravikumar private static void cancelExactAlarm( 98d70f977a2a312353a82ffefeeef67bb23941f78eRahul Ravikumar @NonNull Context context, 99d70f977a2a312353a82ffefeeef67bb23941f78eRahul Ravikumar @NonNull String workSpecId, 100d70f977a2a312353a82ffefeeef67bb23941f78eRahul Ravikumar int alarmId) { 101d70f977a2a312353a82ffefeeef67bb23941f78eRahul Ravikumar 102d70f977a2a312353a82ffefeeef67bb23941f78eRahul Ravikumar AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); 103d70f977a2a312353a82ffefeeef67bb23941f78eRahul Ravikumar Intent delayMet = CommandHandler.createDelayMetIntent(context, workSpecId); 104d70f977a2a312353a82ffefeeef67bb23941f78eRahul Ravikumar PendingIntent pendingIntent = PendingIntent.getService( 105d70f977a2a312353a82ffefeeef67bb23941f78eRahul Ravikumar context, alarmId, delayMet, PendingIntent.FLAG_NO_CREATE); 106d70f977a2a312353a82ffefeeef67bb23941f78eRahul Ravikumar if (pendingIntent != null && alarmManager != null) { 107697d6a4a3797bc71d0dd8685937a318e9934066bRahul Ravikumar Log.d(TAG, String.format( 10818e0a7e02c1198c5b3b33295b148c1017e32f016Rahul Ravikumar "Cancelling existing alarm with (workSpecId, systemId) (%s, %s)", 109697d6a4a3797bc71d0dd8685937a318e9934066bRahul Ravikumar workSpecId, 110697d6a4a3797bc71d0dd8685937a318e9934066bRahul Ravikumar alarmId)); 111d70f977a2a312353a82ffefeeef67bb23941f78eRahul Ravikumar alarmManager.cancel(pendingIntent); 112d70f977a2a312353a82ffefeeef67bb23941f78eRahul Ravikumar } 113d70f977a2a312353a82ffefeeef67bb23941f78eRahul Ravikumar } 114d70f977a2a312353a82ffefeeef67bb23941f78eRahul Ravikumar 115d70f977a2a312353a82ffefeeef67bb23941f78eRahul Ravikumar private static void setExactAlarm( 116d70f977a2a312353a82ffefeeef67bb23941f78eRahul Ravikumar @NonNull Context context, 117d70f977a2a312353a82ffefeeef67bb23941f78eRahul Ravikumar @NonNull String workSpecId, 118d70f977a2a312353a82ffefeeef67bb23941f78eRahul Ravikumar int alarmId, 119d70f977a2a312353a82ffefeeef67bb23941f78eRahul Ravikumar long triggerAtMillis) { 120d70f977a2a312353a82ffefeeef67bb23941f78eRahul Ravikumar 121d70f977a2a312353a82ffefeeef67bb23941f78eRahul Ravikumar AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); 122d70f977a2a312353a82ffefeeef67bb23941f78eRahul Ravikumar Intent delayMet = CommandHandler.createDelayMetIntent(context, workSpecId); 123d70f977a2a312353a82ffefeeef67bb23941f78eRahul Ravikumar PendingIntent pendingIntent = PendingIntent.getService( 124d70f977a2a312353a82ffefeeef67bb23941f78eRahul Ravikumar context, alarmId, delayMet, PendingIntent.FLAG_ONE_SHOT); 125d70f977a2a312353a82ffefeeef67bb23941f78eRahul Ravikumar if (alarmManager != null) { 126d70f977a2a312353a82ffefeeef67bb23941f78eRahul Ravikumar if (Build.VERSION.SDK_INT >= 19) { 127d70f977a2a312353a82ffefeeef67bb23941f78eRahul Ravikumar alarmManager.setExact(RTC_WAKEUP, triggerAtMillis, pendingIntent); 128d70f977a2a312353a82ffefeeef67bb23941f78eRahul Ravikumar } else { 129d70f977a2a312353a82ffefeeef67bb23941f78eRahul Ravikumar alarmManager.set(RTC_WAKEUP, triggerAtMillis, pendingIntent); 130d70f977a2a312353a82ffefeeef67bb23941f78eRahul Ravikumar } 131d70f977a2a312353a82ffefeeef67bb23941f78eRahul Ravikumar } 132d70f977a2a312353a82ffefeeef67bb23941f78eRahul Ravikumar } 133f97ddbc502678a00306afcd73e7a6bb3bcc4c189Sumir Kataria 134f97ddbc502678a00306afcd73e7a6bb3bcc4c189Sumir Kataria private Alarms() { 135f97ddbc502678a00306afcd73e7a6bb3bcc4c189Sumir Kataria } 136d70f977a2a312353a82ffefeeef67bb23941f78eRahul Ravikumar} 137