From bdf7d6f56d2017efbcf082e95773fcddce7736f0 Mon Sep 17 00:00:00 2001
From: Yohei Yukawa <yukawa@google.com>
Date: Tue, 5 Feb 2019 22:46:42 -0800
Subject: [PATCH] Support testing Direct Reply with EditTextVariations on API
 24/25

This is a follow up CL to my previous CL [1], which enabled us to test
Direct-Reply with EditTextVariations.

What this CL does are:

 * Specyfing min_sdk_version to avoid INSTALL_FAILED_OLDER_SDK error
   when installing on older devices.
 * Avoiding NoSuchMethodError on pre-O devices where
   Notification.Builder does not have a constructor that takes
   notification channel.
 * Fixing a race condition where notification can be sent before
   notification channel is created.

 [1]: Iafffcc7d138b0f502116a5e557f0c3f17e9d0b73
      da2486fd63d7d46e982d0e2fb2eba3dac07aff32

Bug: 122957841
Test: Made sure that we can install EditTextVariations on N devices
      and "Direct-Reply" on EditTextVariations works there.
Change-Id: Ib4fbd447608b111e763fde4287226cf7e206e65e
---
 tools/EditTextVariations/Android.bp           |  1 +
 .../edittextvariations/NotificationUtils.java | 39 ++++++++++---------
 2 files changed, 22 insertions(+), 18 deletions(-)

diff --git a/tools/EditTextVariations/Android.bp b/tools/EditTextVariations/Android.bp
index 36296a58bd..94b4951a7c 100644
--- a/tools/EditTextVariations/Android.bp
+++ b/tools/EditTextVariations/Android.bp
@@ -18,4 +18,5 @@ android_test {
     srcs: ["src/**/*.java"],
 
     sdk_version: "current",
+    min_sdk_version: "11",
 }
diff --git a/tools/EditTextVariations/src/com/android/inputmethod/tools/edittextvariations/NotificationUtils.java b/tools/EditTextVariations/src/com/android/inputmethod/tools/edittextvariations/NotificationUtils.java
index 64480bbf0a..a9b7132eb2 100644
--- a/tools/EditTextVariations/src/com/android/inputmethod/tools/edittextvariations/NotificationUtils.java
+++ b/tools/EditTextVariations/src/com/android/inputmethod/tools/edittextvariations/NotificationUtils.java
@@ -38,28 +38,33 @@ final class NotificationUtils {
     private static final String CHANNEL_NAME = "Channel Name";
     private static final String CHANNEL_DESCRIPTION = "Channel Description";
     private static final String CHANNEL_ID = "Channel ID";
-    private static final AtomicBoolean sNotificationChannelInitialized = new AtomicBoolean();
     private static final AtomicInteger sNextNotificationId = new AtomicInteger(1);
 
+    private static final Object sLock = new Object();
+    private static boolean sNotificationChannelInitialized = false;
+
+    static final boolean NOTIFICATION_CHANNEL_REQUIRED =
+            Build.VERSION.SDK_INT >= Build.VERSION_CODES.O;
     static final boolean DIRECT_REPLY_SUPPORTED = Build.VERSION.SDK_INT >= Build.VERSION_CODES.N;
 
-    static void ensureNotificationChannel(Context context) {
-        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
+    private static Notification.Builder createNotificationBuilder(Context context) {
+        if (!NOTIFICATION_CHANNEL_REQUIRED) {
             // NotificationChannel is not implemented.  No need to set up notification channel.
-            return;
-        }
-        if (!sNotificationChannelInitialized.compareAndSet(false, true)) {
-            // Already initialized.
-            return;
+            return new Notification.Builder(context);
         }
 
-        // Create the NotificationChannel
-        final NotificationChannel channel = new NotificationChannel(CHANNEL_ID, CHANNEL_NAME,
-                NotificationManager.IMPORTANCE_DEFAULT);
-        channel.setDescription(CHANNEL_DESCRIPTION);
-        // Register the channel with the system; you can't change the importance
-        // or other notification behaviors after this
-        context.getSystemService(NotificationManager.class).createNotificationChannel(channel);
+        // Make sure that a notification channel is created *before* we send a notification.
+        synchronized (sLock) {
+            if (!sNotificationChannelInitialized) {
+                final NotificationChannel channel = new NotificationChannel(CHANNEL_ID,
+                        CHANNEL_NAME, NotificationManager.IMPORTANCE_DEFAULT);
+                channel.setDescription(CHANNEL_DESCRIPTION);
+                context.getSystemService(NotificationManager.class)
+                        .createNotificationChannel(channel);
+                sNotificationChannelInitialized = true;
+            }
+        }
+        return new Notification.Builder(context, CHANNEL_ID);
     }
 
     static void sendDirectReplyNotification(Context context) {
@@ -68,8 +73,6 @@ final class NotificationUtils {
             return;
         }
 
-        ensureNotificationChannel(context);
-
         RemoteInput remoteInput = new RemoteInput.Builder(KEY_REPLY)
                 .setLabel("Reply Label")
                 .build();
@@ -80,7 +83,7 @@ final class NotificationUtils {
                 new Notification.Action.Builder(null, "Direct Reply Test", pendingIntent)
                         .addRemoteInput(remoteInput)
                         .build();
-        final Notification notification = new Notification.Builder(context, CHANNEL_ID)
+        final Notification notification = createNotificationBuilder(context)
                 .setContentText("Content Title")
                 .setSmallIcon(R.drawable.ic_launcher)
                 .setContentText("Message from " + UserHandle.getUserHandleForUid(Process.myUid()))
-- 
GitLab