Bubble v2 a11y.

- Set checkable for bubble buttons so the check status of non checkable button (back to call, end call) is not read.
- Add support for bottom action buttons.

Test: manual
PiperOrigin-RevId: 183150371
Change-Id: Ifae9c912ec923e8d2cda3146413138bd2eb94b47
diff --git a/java/com/android/incallui/NewReturnToCallController.java b/java/com/android/incallui/NewReturnToCallController.java
index b8798b1..4c3c2a2 100644
--- a/java/com/android/incallui/NewReturnToCallController.java
+++ b/java/com/android/incallui/NewReturnToCallController.java
@@ -238,6 +238,7 @@
             .setIconDrawable(context.getDrawable(R.drawable.quantum_ic_exit_to_app_vd_theme_24))
             .setIntent(fullScreen)
             .setName(context.getText(R.string.bubble_return_to_call))
+            .setCheckable(false)
             .build());
     // Mute/unmute
     actions.add(
@@ -252,6 +253,7 @@
         Action.builder()
             .setIconDrawable(context.getDrawable(speakerButtonInfo.icon))
             .setName(context.getText(speakerButtonInfo.label))
+            .setCheckable(speakerButtonInfo.checkable)
             .setChecked(speakerButtonInfo.isChecked)
             .setIntent(speakerButtonInfo.checkable ? toggleSpeaker : showSpeakerSelect)
             .build());
@@ -261,6 +263,7 @@
             .setIconDrawable(context.getDrawable(R.drawable.quantum_ic_call_end_vd_theme_24))
             .setIntent(endCall)
             .setName(context.getText(R.string.incall_label_end_call))
+            .setCheckable(false)
             .build());
     return actions;
   }
diff --git a/java/com/android/newbubble/BottomActionViewController.java b/java/com/android/newbubble/BottomActionViewController.java
index 04e0e5f..b480ac9 100644
--- a/java/com/android/newbubble/BottomActionViewController.java
+++ b/java/com/android/newbubble/BottomActionViewController.java
@@ -23,6 +23,7 @@
 import android.view.View;
 import android.view.WindowManager;
 import android.view.WindowManager.LayoutParams;
+import android.view.accessibility.AccessibilityEvent;
 import android.view.animation.LinearInterpolator;
 
 /** Controller for showing and hiding bubble bottom action view. */
@@ -157,10 +158,14 @@
 
     // Scale unhighlight target back to 1x
     if (!shouldHighlightDismiss && dismissHighlighted) {
+      // A11y
+      dismissView.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_HOVER_EXIT);
       // Unhighlight dismiss
       dismissView.animate().scaleX(1f).scaleY(1f).setDuration(HIGHLIGHT_TARGET_DURATION).start();
       dismissHighlighted = false;
     } else if (!shouldHighlightEndCall && endCallHighlighted) {
+      // A11y
+      endCallView.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_HOVER_EXIT);
       // Unhighlight end call
       endCallView.animate().scaleX(1f).scaleY(1f).setDuration(HIGHLIGHT_TARGET_DURATION).start();
       endCallHighlighted = false;
@@ -168,6 +173,8 @@
 
     // Scale highlight target larger
     if (shouldHighlightDismiss && !dismissHighlighted) {
+      // A11y
+      dismissView.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_HOVER_ENTER);
       // Highlight dismiss
       dismissView.setPivotY(dismissView.getHeight() / 2 + textOffsetSize);
       dismissView
@@ -184,6 +191,8 @@
           .start();
       dismissHighlighted = true;
     } else if (shouldHighlightEndCall && !endCallHighlighted) {
+      // A11y
+      endCallView.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_HOVER_ENTER);
       // Highlight end call
       endCallView.setPivotY(dismissView.getHeight() / 2 + textOffsetSize);
       endCallView
diff --git a/java/com/android/newbubble/NewBubble.java b/java/com/android/newbubble/NewBubble.java
index 8b188ba..2e98ad1 100644
--- a/java/com/android/newbubble/NewBubble.java
+++ b/java/com/android/newbubble/NewBubble.java
@@ -722,7 +722,7 @@
       button.setCompoundDrawablesWithIntrinsicBounds(action.getIconDrawable(), null, null, null);
     }
     button.setChecked(action.isChecked());
-    button.setEnabled(action.isEnabled());
+    button.setCheckable(action.isCheckable());
     button.setText(action.getName());
     button.setContentDescription(action.getName());
     button.setOnClickListener(v -> doAction(action));
diff --git a/java/com/android/newbubble/NewBubbleInfo.java b/java/com/android/newbubble/NewBubbleInfo.java
index ec26a31..cc7ac7c 100644
--- a/java/com/android/newbubble/NewBubbleInfo.java
+++ b/java/com/android/newbubble/NewBubbleInfo.java
@@ -86,19 +86,19 @@
     @NonNull
     public abstract PendingIntent getIntent();
 
-    public abstract boolean isEnabled();
+    public abstract boolean isCheckable();
 
     public abstract boolean isChecked();
 
     public static Builder builder() {
-      return new AutoValue_NewBubbleInfo_Action.Builder().setEnabled(true).setChecked(false);
+      return new AutoValue_NewBubbleInfo_Action.Builder().setCheckable(true).setChecked(false);
     }
 
     public static Builder from(@NonNull Action action) {
       return builder()
           .setIntent(action.getIntent())
           .setChecked(action.isChecked())
-          .setEnabled(action.isEnabled())
+          .setCheckable(action.isCheckable())
           .setName(action.getName())
           .setIconDrawable(action.getIconDrawable());
     }
@@ -113,7 +113,7 @@
 
       public abstract Builder setIntent(@NonNull PendingIntent intent);
 
-      public abstract Builder setEnabled(boolean enabled);
+      public abstract Builder setCheckable(boolean enabled);
 
       public abstract Builder setChecked(boolean checked);
 
diff --git a/java/com/android/newbubble/NewCheckableButton.java b/java/com/android/newbubble/NewCheckableButton.java
index 15858d3..fda0ddc 100644
--- a/java/com/android/newbubble/NewCheckableButton.java
+++ b/java/com/android/newbubble/NewCheckableButton.java
@@ -45,22 +45,28 @@
 
   public NewCheckableButton(Context context, AttributeSet attrs, int defStyleAttr) {
     super(context, attrs, defStyleAttr);
+  }
 
+  public void setCheckable(boolean checkable) {
     ViewCompat.setAccessibilityDelegate(
         this,
         new AccessibilityDelegateCompat() {
           @Override
           public void onInitializeAccessibilityEvent(View host, AccessibilityEvent event) {
             super.onInitializeAccessibilityEvent(host, event);
-            event.setChecked(isChecked());
+            if (checkable) {
+              event.setChecked(isChecked());
+            }
           }
 
           @Override
           public void onInitializeAccessibilityNodeInfo(
               View host, AccessibilityNodeInfoCompat info) {
             super.onInitializeAccessibilityNodeInfo(host, info);
-            info.setCheckable(true);
-            info.setChecked(isChecked());
+            info.setCheckable(checkable);
+            if (checkable) {
+              info.setChecked(isChecked());
+            }
           }
         });
   }
diff --git a/java/com/android/newbubble/res/layout/bottom_action_base.xml b/java/com/android/newbubble/res/layout/bottom_action_base.xml
index 8f7ba75..b4d7c89 100644
--- a/java/com/android/newbubble/res/layout/bottom_action_base.xml
+++ b/java/com/android/newbubble/res/layout/bottom_action_base.xml
@@ -20,7 +20,8 @@
     android:weightSum="2"
     android:orientation="horizontal"
     android:gravity="center"
-    android:background="@drawable/bottom_action_scrim">
+    android:background="@drawable/bottom_action_scrim"
+    android:contentDescription="@string/a11y_bubble_bottom_action_description">
 
   <!-- Add space to make sure text is not off screen when scaled. (1 - 1/1.3) / 2 ~= 0.11 -->
   <View
@@ -33,7 +34,8 @@
       android:layout_width="0dp"
       android:layout_height="match_parent"
       android:layout_weight="0.78"
-      android:gravity="center">
+      android:gravity="center"
+      android:contentDescription="@string/bubble_bottom_action_hide">
     <TextView
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
@@ -60,7 +62,8 @@
       android:layout_width="0dp"
       android:layout_height="match_parent"
       android:layout_weight="0.78"
-      android:gravity="center">
+      android:gravity="center"
+      android:contentDescription="@string/bubble_bottom_action_end_call">
     <TextView
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
diff --git a/java/com/android/newbubble/res/values/strings.xml b/java/com/android/newbubble/res/values/strings.xml
index 08c685e..7ef61ce 100644
--- a/java/com/android/newbubble/res/values/strings.xml
+++ b/java/com/android/newbubble/res/values/strings.xml
@@ -18,6 +18,8 @@
 <resources>
   <!-- A string for Talkback to read when accessibility user touch bubble. -->
   <string name="a11y_bubble_description">Dialer bubble</string>
+  <!-- A string to describe bubble bottom actions for accessibility user. -->
+  <string name="a11y_bubble_bottom_action_description">Bottom action buttons</string>
   <!-- A string to describe available action for accessibility user. It will be read as "Actions:
     double tap to expand call action menu". -->
   <string name="a11y_bubble_primary_button_expand_action">Expand call action menu</string>