1 /* 2 * Copyright (C) 2015 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 package com.android.messaging.util; 17 18 import android.content.Context; 19 import android.content.res.Resources; 20 import androidx.core.view.accessibility.AccessibilityEventCompat; 21 import androidx.core.view.accessibility.AccessibilityRecordCompat; 22 import android.text.TextUtils; 23 import android.view.View; 24 import android.view.accessibility.AccessibilityEvent; 25 import android.view.accessibility.AccessibilityManager; 26 27 import com.android.messaging.Factory; 28 import com.android.messaging.R; 29 30 import javax.annotation.Nullable; 31 32 public class AccessibilityUtil { 33 public static String sContentDescriptionDivider; 34 isTouchExplorationEnabled(final Context context)35 public static boolean isTouchExplorationEnabled(final Context context) { 36 final AccessibilityManager accessibilityManager = (AccessibilityManager) 37 context.getSystemService(Context.ACCESSIBILITY_SERVICE); 38 return accessibilityManager.isTouchExplorationEnabled(); 39 } 40 appendContentDescription(final Context context, final StringBuilder contentDescription, final String val)41 public static StringBuilder appendContentDescription(final Context context, 42 final StringBuilder contentDescription, final String val) { 43 if (sContentDescriptionDivider == null) { 44 sContentDescriptionDivider = 45 context.getResources().getString(R.string.enumeration_comma); 46 } 47 if (contentDescription.length() != 0) { 48 contentDescription.append(sContentDescriptionDivider); 49 } 50 contentDescription.append(val); 51 return contentDescription; 52 } 53 announceForAccessibilityCompat( final View view, @Nullable final AccessibilityManager accessibilityManager, final int textResourceId)54 public static void announceForAccessibilityCompat( 55 final View view, @Nullable final AccessibilityManager accessibilityManager, 56 final int textResourceId) { 57 final String text = Factory.get().getApplicationContext().getResources().getString( 58 textResourceId); 59 announceForAccessibilityCompat(view, accessibilityManager, text); 60 } 61 announceForAccessibilityCompat( final View view, @Nullable AccessibilityManager accessibilityManager, final CharSequence text)62 public static void announceForAccessibilityCompat( 63 final View view, @Nullable AccessibilityManager accessibilityManager, 64 final CharSequence text) { 65 final Context context = view.getContext().getApplicationContext(); 66 if (accessibilityManager == null) { 67 accessibilityManager = (AccessibilityManager) context.getSystemService( 68 Context.ACCESSIBILITY_SERVICE); 69 } 70 71 if (!accessibilityManager.isEnabled()) { 72 return; 73 } 74 75 // Jelly Bean added support for speaking text verbatim 76 final int eventType = OsUtil.isAtLeastJB() ? AccessibilityEvent.TYPE_ANNOUNCEMENT 77 : AccessibilityEvent.TYPE_VIEW_FOCUSED; 78 79 // Construct an accessibility event with the minimum recommended 80 // attributes. An event without a class name or package may be dropped. 81 final AccessibilityEvent event = AccessibilityEvent.obtain(eventType); 82 event.getText().add(text); 83 event.setEnabled(view.isEnabled()); 84 event.setClassName(view.getClass().getName()); 85 event.setPackageName(context.getPackageName()); 86 87 // JellyBean MR1 requires a source view to set the window ID. 88 final AccessibilityRecordCompat record = AccessibilityEventCompat.asRecord(event); 89 record.setSource(view); 90 91 // Sends the event directly through the accessibility manager. If we only supported SDK 14+ 92 // we could have done: 93 // getParent().requestSendAccessibilityEvent(this, event); 94 accessibilityManager.sendAccessibilityEvent(event); 95 } 96 97 /** 98 * Check to see if the current layout is Right-to-Left. This check is only supported for 99 * API 17+. 100 * For earlier versions, this method will just return false. 101 * @return boolean Boolean indicating whether the currently locale is RTL. 102 */ isLayoutRtl(final View view)103 public static boolean isLayoutRtl(final View view) { 104 if (OsUtil.isAtLeastJB_MR1()) { 105 return View.LAYOUT_DIRECTION_RTL == view.getLayoutDirection(); 106 } else { 107 return false; 108 } 109 } 110 getVocalizedPhoneNumber(final Resources res, final String phoneNumber)111 public static String getVocalizedPhoneNumber(final Resources res, final String phoneNumber) { 112 if (TextUtils.isEmpty(phoneNumber)) { 113 return ""; 114 } 115 final StringBuilder vocalizedPhoneNumber = new StringBuilder(); 116 for (final char c : phoneNumber.toCharArray()) { 117 getVocalizedNumber(res, c, vocalizedPhoneNumber); 118 } 119 return vocalizedPhoneNumber.toString(); 120 } 121 getVocalizedNumber(final Resources res, final char c, final StringBuilder builder)122 public static void getVocalizedNumber(final Resources res, final char c, 123 final StringBuilder builder) { 124 switch (c) { 125 case '0': 126 builder.append(res.getString(R.string.content_description_for_number_zero)); 127 builder.append(" "); 128 return; 129 case '1': 130 builder.append(res.getString(R.string.content_description_for_number_one)); 131 builder.append(" "); 132 return; 133 case '2': 134 builder.append(res.getString(R.string.content_description_for_number_two)); 135 builder.append(" "); 136 return; 137 case '3': 138 builder.append(res.getString(R.string.content_description_for_number_three)); 139 builder.append(" "); 140 return; 141 case '4': 142 builder.append(res.getString(R.string.content_description_for_number_four)); 143 builder.append(" "); 144 return; 145 case '5': 146 builder.append(res.getString(R.string.content_description_for_number_five)); 147 builder.append(" "); 148 return; 149 case '6': 150 builder.append(res.getString(R.string.content_description_for_number_six)); 151 builder.append(" "); 152 return; 153 case '7': 154 builder.append(res.getString(R.string.content_description_for_number_seven)); 155 builder.append(" "); 156 return; 157 case '8': 158 builder.append(res.getString(R.string.content_description_for_number_eight)); 159 builder.append(" "); 160 return; 161 case '9': 162 builder.append(res.getString(R.string.content_description_for_number_nine)); 163 builder.append(" "); 164 return; 165 default: 166 builder.append(c); 167 return; 168 } 169 } 170 } 171