1 /* 2 * Copyright (C) 2020 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.deskclock.controller 18 19 import android.annotation.TargetApi 20 import android.content.ComponentName 21 import android.content.Context 22 import android.content.Intent 23 import android.content.pm.ShortcutInfo 24 import android.content.pm.ShortcutManager 25 import android.graphics.drawable.Icon 26 import android.os.Build 27 import android.os.UserManager 28 import android.provider.AlarmClock 29 import androidx.annotation.StringRes 30 31 import com.android.deskclock.DeskClock 32 import com.android.deskclock.HandleApiCalls 33 import com.android.deskclock.HandleShortcuts 34 import com.android.deskclock.LogUtils 35 import com.android.deskclock.R 36 import com.android.deskclock.ScreensaverActivity 37 import com.android.deskclock.data.DataModel 38 import com.android.deskclock.data.Lap 39 import com.android.deskclock.data.Stopwatch 40 import com.android.deskclock.data.StopwatchListener 41 import com.android.deskclock.events.Events 42 import com.android.deskclock.events.ShortcutEventTracker 43 import com.android.deskclock.stopwatch.StopwatchService 44 import com.android.deskclock.uidata.UiDataModel 45 46 @TargetApi(Build.VERSION_CODES.N_MR1) 47 internal class ShortcutController(val context: Context) { 48 private val mComponentName = ComponentName(context, DeskClock::class.java) 49 private val mShortcutManager = context.getSystemService(ShortcutManager::class.java) 50 private val mUserManager = context.getSystemService(Context.USER_SERVICE) as UserManager 51 52 init { 53 Controller.getController().addEventTracker(ShortcutEventTracker(context)) 54 DataModel.dataModel.addStopwatchListener(StopwatchWatcher()) 55 } 56 57 fun updateShortcuts() { 58 if (!mUserManager.isUserUnlocked()) { 59 LogUtils.i("Skipping shortcut update because user is locked.") 60 return 61 } 62 try { 63 val alarm: ShortcutInfo = createNewAlarmShortcut() 64 val timer: ShortcutInfo = createNewTimerShortcut() 65 val stopwatch: ShortcutInfo = createStopwatchShortcut() 66 val screensaver: ShortcutInfo = createScreensaverShortcut() 67 mShortcutManager.setDynamicShortcuts(listOf(alarm, timer, stopwatch, screensaver)) 68 } catch (e: IllegalStateException) { 69 LogUtils.wtf(e) 70 } 71 } 72 73 private fun createNewAlarmShortcut(): ShortcutInfo { 74 val intent: Intent = Intent(AlarmClock.ACTION_SET_ALARM) 75 .setClass(context, HandleApiCalls::class.java) 76 .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) 77 .putExtra(Events.EXTRA_EVENT_LABEL, R.string.label_shortcut) 78 val setAlarmShortcut = UiDataModel.uiDataModel 79 .getShortcutId(R.string.category_alarm, R.string.action_create) 80 return ShortcutInfo.Builder(context, setAlarmShortcut) 81 .setIcon(Icon.createWithResource(context, R.drawable.shortcut_new_alarm)) 82 .setActivity(mComponentName) 83 .setShortLabel(context.getString(R.string.shortcut_new_alarm_short)) 84 .setLongLabel(context.getString(R.string.shortcut_new_alarm_long)) 85 .setIntent(intent) 86 .setRank(0) 87 .build() 88 } 89 90 private fun createNewTimerShortcut(): ShortcutInfo { 91 val intent: Intent = Intent(AlarmClock.ACTION_SET_TIMER) 92 .setClass(context, HandleApiCalls::class.java) 93 .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) 94 .putExtra(Events.EXTRA_EVENT_LABEL, R.string.label_shortcut) 95 val setTimerShortcut = UiDataModel.uiDataModel 96 .getShortcutId(R.string.category_timer, R.string.action_create) 97 return ShortcutInfo.Builder(context, setTimerShortcut) 98 .setIcon(Icon.createWithResource(context, R.drawable.shortcut_new_timer)) 99 .setActivity(mComponentName) 100 .setShortLabel(context.getString(R.string.shortcut_new_timer_short)) 101 .setLongLabel(context.getString(R.string.shortcut_new_timer_long)) 102 .setIntent(intent) 103 .setRank(1) 104 .build() 105 } 106 107 private fun createStopwatchShortcut(): ShortcutInfo { 108 @StringRes val action: Int = if (DataModel.dataModel.stopwatch.isRunning) { 109 R.string.action_pause 110 } else { 111 R.string.action_start 112 } 113 val shortcutId = UiDataModel.uiDataModel 114 .getShortcutId(R.string.category_stopwatch, action) 115 val shortcut: ShortcutInfo.Builder = ShortcutInfo.Builder(context, shortcutId) 116 .setIcon(Icon.createWithResource(context, R.drawable.shortcut_stopwatch)) 117 .setActivity(mComponentName) 118 .setRank(2) 119 val intent: Intent 120 if (DataModel.dataModel.stopwatch.isRunning) { 121 intent = Intent(StopwatchService.ACTION_PAUSE_STOPWATCH) 122 .putExtra(Events.EXTRA_EVENT_LABEL, R.string.label_shortcut) 123 shortcut.setShortLabel(context.getString(R.string.shortcut_pause_stopwatch_short)) 124 .setLongLabel(context.getString(R.string.shortcut_pause_stopwatch_long)) 125 } else { 126 intent = Intent(StopwatchService.ACTION_START_STOPWATCH) 127 .putExtra(Events.EXTRA_EVENT_LABEL, R.string.label_shortcut) 128 shortcut.setShortLabel(context.getString(R.string.shortcut_start_stopwatch_short)) 129 .setLongLabel(context.getString(R.string.shortcut_start_stopwatch_long)) 130 } 131 intent.setClass(context, HandleShortcuts::class.java) 132 .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) 133 return shortcut 134 .setIntent(intent) 135 .build() 136 } 137 138 private fun createScreensaverShortcut(): ShortcutInfo { 139 val intent: Intent = Intent(Intent.ACTION_MAIN) 140 .setClass(context, ScreensaverActivity::class.java) 141 .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) 142 .putExtra(Events.EXTRA_EVENT_LABEL, R.string.label_shortcut) 143 val screensaverShortcut = UiDataModel.uiDataModel 144 .getShortcutId(R.string.category_screensaver, R.string.action_show) 145 return ShortcutInfo.Builder(context, screensaverShortcut) 146 .setIcon(Icon.createWithResource(context, R.drawable.shortcut_screensaver)) 147 .setActivity(mComponentName) 148 .setShortLabel(context.getString(R.string.shortcut_start_screensaver_short)) 149 .setLongLabel(context.getString(R.string.shortcut_start_screensaver_long)) 150 .setIntent(intent) 151 .setRank(3) 152 .build() 153 } 154 155 private inner class StopwatchWatcher : StopwatchListener { 156 157 override fun stopwatchUpdated(before: Stopwatch, after: Stopwatch) { 158 if (!mUserManager.isUserUnlocked()) { 159 LogUtils.i("Skipping stopwatch shortcut update because user is locked.") 160 return 161 } 162 try { 163 mShortcutManager.updateShortcuts(listOf(createStopwatchShortcut())) 164 } catch (e: IllegalStateException) { 165 LogUtils.wtf(e) 166 } 167 } 168 169 override fun lapAdded(lap: Lap) {} 170 } 171 }