Snap for 10447354 from 4d7b743a91ede9886739f3e902b8405103e58668 to mainline-wifi-release

Change-Id: Icc2bace8513759b290e709bbc7582a3fb74210ec
diff --git a/Android.bp b/Android.bp
index a6e4274..235bad9 100644
--- a/Android.bp
+++ b/Android.bp
@@ -7,7 +7,7 @@
     name: "DeskClock",
     resource_dirs: ["res"],
     sdk_version: "current",
-    target_sdk_version: "24",
+    target_sdk_version: "30",
     overrides: [
         "AlarmClock",
     ],
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 963afe4..04a53e4 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -22,7 +22,7 @@
     <original-package android:name="com.android.alarmclock" />
     <original-package android:name="com.android.deskclock" />
 
-    <uses-sdk android:minSdkVersion="23" android:targetSdkVersion="24" />
+    <uses-sdk android:minSdkVersion="23" android:targetSdkVersion="30" />
 
     <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
     <uses-permission android:name="android.permission.WAKE_LOCK" />
@@ -35,15 +35,6 @@
     <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
     <uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
 
-    <!-- WRITE_SETTINGS is required to record the upcoming alarm prior to L -->
-    <uses-permission
-        android:name="android.permission.WRITE_SETTINGS"
-        android:maxSdkVersion="19" />
-    <!-- READ_PHONE_STATE is required to determine when a phone call exists prior to M -->
-    <uses-permission
-        android:name="android.permission.READ_PHONE_STATE"
-        android:maxSdkVersion="22" />
-
     <application
         android:name=".DeskClockApplication"
         android:allowBackup="false"
diff --git a/OWNERS b/OWNERS
index fe9f33f..6c60e5a 100644
--- a/OWNERS
+++ b/OWNERS
@@ -1,3 +1,5 @@
 # This project has no significant updates recently.
 # Please update this list if you find better candidates.
+iankaz@google.com
+amithds@google.com
 rtenneti@google.com
diff --git a/src/com/android/deskclock/Utils.kt b/src/com/android/deskclock/Utils.kt
index 166803a..3320e20 100644
--- a/src/com/android/deskclock/Utils.kt
+++ b/src/com/android/deskclock/Utils.kt
@@ -315,7 +315,7 @@
     }
 
     @TargetApi(Build.VERSION_CODES.LOLLIPOP)
-    fun updateNextAlarm(am: AlarmManager, info: AlarmClockInfo?, op: PendingIntent?) {
+    fun updateNextAlarm(am: AlarmManager, info: AlarmClockInfo, op: PendingIntent) {
         am.setAlarmClock(info, op)
     }
 
diff --git a/src/com/android/deskclock/alarms/AlarmActivity.kt b/src/com/android/deskclock/alarms/AlarmActivity.kt
index a4caf1a..8d9535d 100644
--- a/src/com/android/deskclock/alarms/AlarmActivity.kt
+++ b/src/com/android/deskclock/alarms/AlarmActivity.kt
@@ -283,6 +283,7 @@
                     }
                     AlarmVolumeButtonBehavior.NOTHING -> {
                     }
+                    null -> { }
                 }
             }
         }
diff --git a/src/com/android/deskclock/alarms/AlarmStateManager.kt b/src/com/android/deskclock/alarms/AlarmStateManager.kt
index 2478ef5..c98380c 100644
--- a/src/com/android/deskclock/alarms/AlarmStateManager.kt
+++ b/src/com/android/deskclock/alarms/AlarmStateManager.kt
@@ -288,7 +288,7 @@
                         PendingIntent.FLAG_UPDATE_CURRENT)
 
                 val info = AlarmClockInfo(alarmTime, viewIntent)
-                Utils.updateNextAlarm(alarmManager, info, operation)
+                Utils.updateNextAlarm(alarmManager, info, operation!!)
             } else if (operation != null) {
                 LogUtils.i("Canceling upcoming AlarmClockInfo")
                 alarmManager.cancel(operation)
diff --git a/src/com/android/deskclock/data/City.kt b/src/com/android/deskclock/data/City.kt
index 4a8abf3..d6e6b04 100644
--- a/src/com/android/deskclock/data/City.kt
+++ b/src/com/android/deskclock/data/City.kt
@@ -54,7 +54,7 @@
     val nameUpperCase: String
         get() {
             if (mNameUpperCase == null) {
-                mNameUpperCase = name.toUpperCase()
+                mNameUpperCase = name.uppercase()
             }
             return mNameUpperCase!!
         }
diff --git a/src/com/android/deskclock/data/SettingsDAO.kt b/src/com/android/deskclock/data/SettingsDAO.kt
index 43e77b5..c399a6c 100644
--- a/src/com/android/deskclock/data/SettingsDAO.kt
+++ b/src/com/android/deskclock/data/SettingsDAO.kt
@@ -342,9 +342,9 @@
     private fun getClockStyle(context: Context, prefs: SharedPreferences, key: String): ClockStyle {
         val defaultStyle: String = context.getString(R.string.default_clock_style)
         val clockStyle: String = prefs.getString(key, defaultStyle)!!
-        // Use hardcoded locale to perform toUpperCase, because in some languages toUpperCase adds
+        // Use hardcoded locale to perform uppercase(), because in some languages uppercase() adds
         // accent to character, which breaks the enum conversion.
-        return ClockStyle.valueOf(clockStyle.toUpperCase(Locale.US))
+        return ClockStyle.valueOf(clockStyle.uppercase(Locale.US))
     }
 
     /**
diff --git a/src/com/android/deskclock/data/TimerModel.kt b/src/com/android/deskclock/data/TimerModel.kt
index 08f6fb1..2b97af7 100644
--- a/src/com/android/deskclock/data/TimerModel.kt
+++ b/src/com/android/deskclock/data/TimerModel.kt
@@ -683,12 +683,6 @@
      * when the application is not open.
      */
     fun updateNotification() {
-        // Notifications should be hidden if the app is open.
-        if (mNotificationModel.isApplicationInForeground) {
-            mNotificationManager.cancel(mNotificationModel.unexpiredTimerNotificationId)
-            return
-        }
-
         // Filter the timers to just include unexpired ones.
         val unexpired: MutableList<Timer> = mutableListOf()
         for (timer in mutableTimers) {
@@ -699,18 +693,33 @@
 
         // If no unexpired timers exist, cancel the notification.
         if (unexpired.isEmpty()) {
-            mNotificationManager.cancel(mNotificationModel.unexpiredTimerNotificationId)
+            if(mNotificationBuilder.isChannelCreated(mNotificationManager)) {
+                LogUtils.i("Cancelling Notifications when list is empty")
+                mNotificationManager.cancel(mNotificationModel.unexpiredTimerNotificationId)
+            }
             return
         }
 
         // Sort the unexpired timers to locate the next one scheduled to expire.
         unexpired.sortWith(Timer.EXPIRY_COMPARATOR)
 
+        //Build and setup a channel for notifications
+        LogUtils.i("Channel being setup!!!!")
         // Otherwise build and post a notification reflecting the latest unexpired timers.
         val notification: Notification =
                 mNotificationBuilder.build(mContext, mNotificationModel, unexpired)
         val notificationId = mNotificationModel.unexpiredTimerNotificationId
         mNotificationBuilder.buildChannel(mContext, mNotificationManager)
+
+        // Notifications should be hidden if the app is open.
+        if (mNotificationModel.isApplicationInForeground) {
+            if(mNotificationBuilder.isChannelCreated(mNotificationManager)) {
+                LogUtils.i("Cancelling notifications when the app is in foreground")
+                mNotificationManager.cancel(mNotificationModel.unexpiredTimerNotificationId)
+            }
+            return
+        }
+
         mNotificationManager.notify(notificationId, notification)
     }
 
@@ -797,7 +806,7 @@
          */
         private val MISSED_THRESHOLD: Long = -MINUTE_IN_MILLIS
 
-        fun schedulePendingIntent(am: AlarmManager, triggerTime: Long, pi: PendingIntent?) {
+        fun schedulePendingIntent(am: AlarmManager, triggerTime: Long, pi: PendingIntent) {
             if (Utils.isMOrLater) {
                 // Ensure the timer fires even if the device is dozing.
                 am.setExactAndAllowWhileIdle(ELAPSED_REALTIME_WAKEUP, triggerTime, pi)
@@ -806,4 +815,4 @@
             }
         }
     }
-}
\ No newline at end of file
+}
diff --git a/src/com/android/deskclock/data/TimerNotificationBuilder.kt b/src/com/android/deskclock/data/TimerNotificationBuilder.kt
index 98e2a92..66601cf 100644
--- a/src/com/android/deskclock/data/TimerNotificationBuilder.kt
+++ b/src/com/android/deskclock/data/TimerNotificationBuilder.kt
@@ -50,6 +50,17 @@
  */
 internal class TimerNotificationBuilder {
 
+    fun isChannelCreated(notificationManager: NotificationManagerCompat): Boolean {
+        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
+            if(notificationManager.getNotificationChannelCompat(TIMER_MODEL_NOTIFICATION_CHANNEL_ID) != null) {
+                return true
+            } else {
+                return false
+            }
+        }
+        return false
+    }
+
     fun buildChannel(context: Context, notificationManager: NotificationManagerCompat) {
         if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
             val channel = NotificationChannel(
@@ -420,4 +431,4 @@
             return SystemClock.elapsedRealtime() + adjustedRemaining
         }
     }
-}
\ No newline at end of file
+}
diff --git a/src/com/android/deskclock/timer/TimerItem.kt b/src/com/android/deskclock/timer/TimerItem.kt
index 9cdcca4..a0573cf 100644
--- a/src/com/android/deskclock/timer/TimerItem.kt
+++ b/src/com/android/deskclock/timer/TimerItem.kt
@@ -138,6 +138,7 @@
                     mTimerText.isActivated = true
                     mTimerText.importantForAccessibility = View.IMPORTANT_FOR_ACCESSIBILITY_NO
                 }
+                null -> { }
             }
         }
     }
diff --git a/src/com/android/deskclock/widget/CircleView.kt b/src/com/android/deskclock/widget/CircleView.kt
index 062a284..e6239fc 100644
--- a/src/com/android/deskclock/widget/CircleView.kt
+++ b/src/com/android/deskclock/widget/CircleView.kt
@@ -132,7 +132,7 @@
             mCirclePaint.color = color
 
             // invalidate the current area
-            invalidate(mCenterX, mCenterY, radius)
+            invalidate()
         }
         return this
     }
@@ -150,8 +150,7 @@
             mCenterX = centerX
 
             // invalidate the old/new areas
-            invalidate(oldCenterX, mCenterY, radius)
-            invalidate(centerX, mCenterY, radius)
+            invalidate()
         }
 
         // clear the horizontal gravity flags
@@ -173,8 +172,7 @@
             mCenterY = centerY
 
             // invalidate the old/new areas
-            invalidate(mCenterX, oldCenterY, radius)
-            invalidate(mCenterX, centerY, radius)
+            invalidate()
         }
 
         // clear the vertical gravity flags
@@ -196,10 +194,7 @@
             this.radius = radius
 
             // invalidate the old/new areas
-            invalidate(mCenterX, mCenterY, oldRadius)
-            if (radius > oldRadius) {
-                invalidate(mCenterX, mCenterY, radius)
-            }
+            invalidate()
         }
 
         // clear the fill gravity flags
@@ -214,15 +209,6 @@
     }
 
     /**
-     * Invalidates the rectangular area that circumscribes the circle defined by `centerX`,
-     * `centerY`, and `radius`.
-     */
-    private fun invalidate(centerX: Float, centerY: Float, radius: Float) {
-        invalidate((centerX - radius - 0.5f).toInt(), (centerY - radius - 0.5f).toInt(),
-                (centerX + radius + 0.5f).toInt(), (centerY + radius + 0.5f).toInt())
-    }
-
-    /**
      * Applies the specified `gravity` and `layoutDirection`, adjusting the alignment
      * and size of the circle depending on the resolved [Gravity] flags. Also invalidates the
      * affected area if necessary.
@@ -257,8 +243,7 @@
         }
 
         if (oldCenterX != mCenterX || oldCenterY != mCenterY || oldRadius != radius) {
-            invalidate(oldCenterX, oldCenterY, oldRadius)
-            invalidate(mCenterX, mCenterY, radius)
+            invalidate()
         }
     }
 
diff --git a/src/com/android/deskclock/worldclock/CitySelectionActivity.kt b/src/com/android/deskclock/worldclock/CitySelectionActivity.kt
index 998faa5..6ec6952 100644
--- a/src/com/android/deskclock/worldclock/CitySelectionActivity.kt
+++ b/src/com/android/deskclock/worldclock/CitySelectionActivity.kt
@@ -459,7 +459,7 @@
          */
         fun filter(queryText: String) {
             mSearchMenuItemController.queryText = queryText
-            val query = City.removeSpecialCharacters(queryText.toUpperCase())
+            val query = City.removeSpecialCharacters(queryText.uppercase())
 
             // Compute the filtered list of cities.
             val filteredCities = if (TextUtils.isEmpty(query)) {