// Copyright 2018 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "content/browser/accessibility/browser_accessibility_state_impl_android.h"
#include <memory>
#include "base/containers/contains.h"
#include "base/metrics/histogram_functions.h"
#include "base/metrics/histogram_macros.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/public/browser/browser_thread.h"
#include "ui/accessibility/android/accessibility_state.h"
#include "ui/gfx/animation/animation.h"
namespace content {
namespace {
// These are hashes of different accessibility services which are generally used
// as part of an assistive technology.
const uint32_t kAssistiveTechPackageHashes[] = {
0x349d4b1a, // Android Accessibility Suite
0xa5a469fc, // Sound Amplifier
0xb13e6179, // Action Blocks Accessibility
0xb38ef877, // Voice Access
0xbc2897b4, // BrailleBack
};
// These are hashes of different "accessibility" services that enable
// accessibility but are only using it in the context of password management.
const uint32_t kPasswordPackageHashes[] = {
0x013b76f2, 0x31cd47e3, 0x353cf6c5, 0x48723526, 0x4a8cfa8a,
0x7e0ad835, 0x7e3515d0, 0x8e4c009f, 0x920ad3bd, 0xca841f39,
};
// IMPORTANT!
// These values are written to logs. Do not renumber or delete
// existing items; add new entries to the end of the list.
//
// Note: The string names for these enums must correspond with the names of
// constants from AccessibilityEvent and AccessibilityServiceInfo, defined
// below. For example, UMA_EVENT_ANNOUNCEMENT corresponds to
// ACCESSIBILITYEVENT_TYPE_ANNOUNCEMENT via the macro
// EVENT_TYPE_HISTOGRAM(event_type_mask, ANNOUNCEMENT).
//
// LINT.IfChange
enum {
UMA_CAPABILITY_CAN_CONTROL_MAGNIFICATION = 0,
UMA_CAPABILITY_CAN_PERFORM_GESTURES = 1,
UMA_CAPABILITY_CAN_REQUEST_ENHANCED_WEB_ACCESSIBILITY = 2,
UMA_CAPABILITY_CAN_REQUEST_FILTER_KEY_EVENTS = 3,
UMA_CAPABILITY_CAN_REQUEST_TOUCH_EXPLORATION = 4,
UMA_CAPABILITY_CAN_RETRIEVE_WINDOW_CONTENT = 5,
UMA_EVENT_ANNOUNCEMENT = 6,
UMA_EVENT_ASSIST_READING_CONTEXT = 7,
UMA_EVENT_GESTURE_DETECTION_END = 8,
UMA_EVENT_GESTURE_DETECTION_START = 9,
UMA_EVENT_NOTIFICATION_STATE_CHANGED = 10,
UMA_EVENT_TOUCH_EXPLORATION_GESTURE_END = 11,
UMA_EVENT_TOUCH_EXPLORATION_GESTURE_START = 12,
UMA_EVENT_TOUCH_INTERACTION_END = 13,
UMA_EVENT_TOUCH_INTERACTION_START = 14,
UMA_EVENT_VIEW_ACCESSIBILITY_FOCUSED = 15,
UMA_EVENT_VIEW_ACCESSIBILITY_FOCUS_CLEARED = 16,
UMA_EVENT_VIEW_CLICKED = 17,
UMA_EVENT_VIEW_CONTEXT_CLICKED = 18,
UMA_EVENT_VIEW_FOCUSED = 19,
UMA_EVENT_VIEW_HOVER_ENTER = 20,
UMA_EVENT_VIEW_HOVER_EXIT = 21,
UMA_EVENT_VIEW_LONG_CLICKED = 22,
UMA_EVENT_VIEW_SCROLLED = 23,
UMA_EVENT_VIEW_SELECTED = 24,
UMA_EVENT_VIEW_TEXT_CHANGED = 25,
UMA_EVENT_VIEW_TEXT_SELECTION_CHANGED = 26,
UMA_EVENT_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY = 27,
UMA_EVENT_WINDOWS_CHANGED = 28,
UMA_EVENT_WINDOW_CONTENT_CHANGED = 29,
UMA_EVENT_WINDOW_STATE_CHANGED = 30,
UMA_FEEDBACK_AUDIBLE = 31,
UMA_FEEDBACK_BRAILLE = 32,
UMA_FEEDBACK_GENERIC = 33,
UMA_FEEDBACK_HAPTIC = 34,
UMA_FEEDBACK_SPOKEN = 35,
UMA_FEEDBACK_VISUAL = 36,
UMA_FLAG_FORCE_DIRECT_BOOT_AWARE = 37,
UMA_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS = 38,
UMA_FLAG_REPORT_VIEW_IDS = 39,
UMA_FLAG_REQUEST_ENHANCED_WEB_ACCESSIBILITY = 40,
UMA_FLAG_REQUEST_FILTER_KEY_EVENTS = 41,
UMA_FLAG_REQUEST_TOUCH_EXPLORATION_MODE = 42,
UMA_FLAG_RETRIEVE_INTERACTIVE_WINDOWS = 43,
UMA_SERVICE_TYPE_UNKNOWN = 44,
UMA_SERVICE_TYPE_PASSWORD_MANAGER = 45,
UMA_SERVICE_TYPE_ASSISTIVE_TECH = 46,
UMA_CAPABILITY_CAN_REQUEST_FINGERPRINT_GESTURES = 47,
UMA_CAPABILITY_CAN_TAKE_SCREENSHOT = 48,
UMA_FLAG_ENABLE_ACCESSIBILITY_VOLUME = 49,
UMA_FLAG_REQUEST_ACCESSIBILITY_BUTTON = 50,
UMA_FLAG_REQUEST_FINGERPRINT_GESTURES = 51,
UMA_FLAG_REQUEST_MULTI_FINGER_GESTURES = 52,
UMA_FLAG_REQUEST_SHORTCUT_WARNING_DIALOG_SPOKEN_FEEDBACK = 53,
UMA_FLAG_SERVICE_HANDLES_DOUBLE_TAP = 54,
UMA_SERVICE_TYPE_ASSISTIVE_TECH_WITH_PASSWORD_MANAGER = 55,
UMA_SERVICE_TYPE_ASSISTIVE_TECH_WITH_UNKNOWN = 56,
UMA_SERVICE_TYPE_PASSWORD_MANAGER_WITH_UNKNOWN = 57,
UMA_SERVICE_TYPE_ALL_VARIANTS = 58,
UMA_EVENT_SPEECH_STATE_CHANGE = 59,
UMA_FEEDBACK_ALL_MASK = 60,
UMA_FLAG_REQUEST_2_FINGER_PASSTHROUGH = 61,
UMA_FLAG_SEND_MOTION_EVENTS = 62,
UMA_FLAG_INPUT_METHOD_EDITOR = 63,
// This must always be the last enum. It's okay for its value to
// increase, but none of the other enum values may change.
UMA_ACCESSIBILITYSERVICEINFO_MAX
};
// LINT.ThenChange(/tools/metrics/histograms/metadata/accessibility/enums.xml:AccessibilityAndroidServiceInfoEnum)
// These are constants from
// android.view.accessibility.AccessibilityEvent in Java.
//
// If you add a new constant, add a new UMA enum above and add a line
// to RecordAccessibilityServiceStatsHistogram(), below.
enum {
ACCESSIBILITYEVENT_TYPE_VIEW_CLICKED = 0x00000001,
ACCESSIBILITYEVENT_TYPE_VIEW_LONG_CLICKED = 0x00000002,
ACCESSIBILITYEVENT_TYPE_VIEW_SELECTED = 0x00000004,
ACCESSIBILITYEVENT_TYPE_VIEW_FOCUSED = 0x00000008,
ACCESSIBILITYEVENT_TYPE_VIEW_TEXT_CHANGED = 0x00000010,
ACCESSIBILITYEVENT_TYPE_WINDOW_STATE_CHANGED = 0x00000020,
ACCESSIBILITYEVENT_TYPE_NOTIFICATION_STATE_CHANGED = 0x00000040,
ACCESSIBILITYEVENT_TYPE_VIEW_HOVER_ENTER = 0x00000080,
ACCESSIBILITYEVENT_TYPE_VIEW_HOVER_EXIT = 0x00000100,
ACCESSIBILITYEVENT_TYPE_TOUCH_EXPLORATION_GESTURE_START = 0x00000200,
ACCESSIBILITYEVENT_TYPE_TOUCH_EXPLORATION_GESTURE_END = 0x00000400,
ACCESSIBILITYEVENT_TYPE_WINDOW_CONTENT_CHANGED = 0x00000800,
ACCESSIBILITYEVENT_TYPE_VIEW_SCROLLED = 0x00001000,
ACCESSIBILITYEVENT_TYPE_VIEW_TEXT_SELECTION_CHANGED = 0x00002000,
ACCESSIBILITYEVENT_TYPE_ANNOUNCEMENT = 0x00004000,
ACCESSIBILITYEVENT_TYPE_VIEW_ACCESSIBILITY_FOCUSED = 0x00008000,
ACCESSIBILITYEVENT_TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED = 0x00010000,
ACCESSIBILITYEVENT_TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY =
0x00020000,
ACCESSIBILITYEVENT_TYPE_GESTURE_DETECTION_START = 0x00040000,
ACCESSIBILITYEVENT_TYPE_GESTURE_DETECTION_END = 0x00080000,
ACCESSIBILITYEVENT_TYPE_TOUCH_INTERACTION_START = 0x00100000,
ACCESSIBILITYEVENT_TYPE_TOUCH_INTERACTION_END = 0x00200000,
ACCESSIBILITYEVENT_TYPE_WINDOWS_CHANGED = 0x00400000,
ACCESSIBILITYEVENT_TYPE_VIEW_CONTEXT_CLICKED = 0x00800000,
ACCESSIBILITYEVENT_TYPE_ASSIST_READING_CONTEXT = 0x01000000,
ACCESSIBILITYEVENT_TYPE_SPEECH_STATE_CHANGE = 0x02000000,
};
// These are constants from
// android.accessibilityservice.AccessibilityServiceInfo in Java:
//
// If you add a new constant, add a new UMA enum above and add a line
// to RecordAccessibilityServiceStatsHistogram(), below.
enum {
ACCESSIBILITYSERVICEINFO_CAPABILITY_CAN_RETRIEVE_WINDOW_CONTENT = 0x00000001,
ACCESSIBILITYSERVICEINFO_CAPABILITY_CAN_REQUEST_TOUCH_EXPLORATION =
0x00000002,
ACCESSIBILITYSERVICEINFO_CAPABILITY_CAN_REQUEST_ENHANCED_WEB_ACCESSIBILITY =
0x00000004,
ACCESSIBILITYSERVICEINFO_CAPABILITY_CAN_REQUEST_FILTER_KEY_EVENTS =
0x00000008,
ACCESSIBILITYSERVICEINFO_CAPABILITY_CAN_CONTROL_MAGNIFICATION = 0x00000010,
ACCESSIBILITYSERVICEINFO_CAPABILITY_CAN_PERFORM_GESTURES = 0x00000020,
ACCESSIBILITYSERVICEINFO_CAPABILITY_CAN_REQUEST_FINGERPRINT_GESTURES =
0x00000040,
ACCESSIBILITYSERVICEINFO_CAPABILITY_CAN_TAKE_SCREENSHOT = 0x00000080,
ACCESSIBILITYSERVICEINFO_FEEDBACK_SPOKEN = 0x0000001,
ACCESSIBILITYSERVICEINFO_FEEDBACK_HAPTIC = 0x0000002,
ACCESSIBILITYSERVICEINFO_FEEDBACK_AUDIBLE = 0x0000004,
ACCESSIBILITYSERVICEINFO_FEEDBACK_VISUAL = 0x0000008,
ACCESSIBILITYSERVICEINFO_FEEDBACK_GENERIC = 0x0000010,
ACCESSIBILITYSERVICEINFO_FEEDBACK_BRAILLE = 0x0000020,
ACCESSIBILITYSERVICEINFO_FEEDBACK_ALL_MASK = 0xFFFFFFFF,
ACCESSIBILITYSERVICEINFO_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS = 0x0000002,
ACCESSIBILITYSERVICEINFO_FLAG_REQUEST_TOUCH_EXPLORATION_MODE = 0x0000004,
ACCESSIBILITYSERVICEINFO_FLAG_REQUEST_ENHANCED_WEB_ACCESSIBILITY = 0x00000008,
ACCESSIBILITYSERVICEINFO_FLAG_REPORT_VIEW_IDS = 0x00000010,
ACCESSIBILITYSERVICEINFO_FLAG_REQUEST_FILTER_KEY_EVENTS = 0x00000020,
ACCESSIBILITYSERVICEINFO_FLAG_RETRIEVE_INTERACTIVE_WINDOWS = 0x00000040,
ACCESSIBILITYSERVICEINFO_FLAG_ENABLE_ACCESSIBILITY_VOLUME = 0x00000080,
ACCESSIBILITYSERVICEINFO_FLAG_REQUEST_ACCESSIBILITY_BUTTON = 0x00000100,
ACCESSIBILITYSERVICEINFO_FLAG_REQUEST_FINGERPRINT_GESTURES = 0x00000200,
ACCESSIBILITYSERVICEINFO_FLAG_REQUEST_SHORTCUT_WARNING_DIALOG_SPOKEN_FEEDBACK =
0x00000400,
ACCESSIBILITYSERVICEINFO_FLAG_SERVICE_HANDLES_DOUBLE_TAP = 0x00000800,
ACCESSIBILITYSERVICEINFO_FLAG_REQUEST_MULTI_FINGER_GESTURES = 0x00001000,
ACCESSIBILITYSERVICEINFO_FLAG_REQUEST_2_FINGER_PASSTHROUGH = 0x0002000,
ACCESSIBILITYSERVICEINFO_FLAG_SEND_MOTION_EVENTS = 0x0004000,
ACCESSIBILITYSERVICEINFO_FLAG_INPUT_METHOD_EDITOR = 0x0008000,
ACCESSIBILITYSERVICEINFO_FLAG_FORCE_DIRECT_BOOT_AWARE = 0x00010000,
};
// These macros simplify recording a histogram based on information we get
// from an AccessibilityService. There are four bitmasks of information
// we get from each AccessibilityService, and for each possible bit mask
// corresponding to one flag, we want to check if that flag is set, and if
// so, record the corresponding histogram.
//
// Doing this with macros reduces the chance for human error by
// recording the wrong histogram for the wrong flag.
//
// These macros are used by RecordAccessibilityServiceStatsHistogram(), below.
#define EVENT_TYPE_HISTOGRAM(event_type_mask, event_type, histogram) \
if (event_type_mask & ACCESSIBILITYEVENT_TYPE_##event_type) \
base::UmaHistogramEnumeration(histogram, UMA_EVENT_##event_type, \
UMA_ACCESSIBILITYSERVICEINFO_MAX)
#define FLAGS_HISTOGRAM(flags_mask, flag, histogram) \
if (flags_mask & ACCESSIBILITYSERVICEINFO_FLAG_##flag) \
base::UmaHistogramEnumeration(histogram, UMA_FLAG_##flag, \
UMA_ACCESSIBILITYSERVICEINFO_MAX)
#define FEEDBACK_TYPE_HISTOGRAM(feedback_type_mask, feedback_type, histogram) \
if (feedback_type_mask & ACCESSIBILITYSERVICEINFO_FEEDBACK_##feedback_type) \
base::UmaHistogramEnumeration(histogram, UMA_FEEDBACK_##feedback_type, \
UMA_ACCESSIBILITYSERVICEINFO_MAX)
#define CAPABILITY_TYPE_HISTOGRAM(capability_type_mask, capability_type, \
histogram) \
if (capability_type_mask & \
ACCESSIBILITYSERVICEINFO_CAPABILITY_##capability_type) \
base::UmaHistogramEnumeration(histogram, UMA_CAPABILITY_##capability_type, \
UMA_ACCESSIBILITYSERVICEINFO_MAX)
#define SERVICE_TYPE_HISTOGRAM(service_type, histogram) \
base::UmaHistogramEnumeration(histogram, service_type, \
UMA_ACCESSIBILITYSERVICEINFO_MAX);
// This macro simplifies the recording of the aggregate accessibility
// information in the CollectAccessibilityServiceStats() method, below.
//
// There are 7 possible variants of the "Accessibility.AndroidServiceInfo.{}"
// histogram. We consider users that have: assistive tech, password managers, or
// an unknown service enabled. We track the 7 possible subsets of these (the
// empty set of nothing enabled is implicitly tracked by whichever users do not
// belong to one of the other groups). Requested event, feedback, flag, and
// capabilities are recorded per subset.
#define RECORD_ALL_HISTOGRAMS(event, feedback, flag, capability, \
service_type_variant) \
RecordAccessibilityServiceStatsHistogram( \
event, feedback, flag, capability, \
"Accessibility.AndroidServiceInfo." #service_type_variant); \
SERVICE_TYPE_HISTOGRAM( \
UMA_SERVICE_TYPE_##service_type_variant, \
"Accessibility.AndroidServiceInfo." #service_type_variant)
} // namespace
BrowserAccessibilityStateImplAndroid::BrowserAccessibilityStateImplAndroid() {
ui::AccessibilityState::RegisterAccessibilityStateDelegate(this);
}
BrowserAccessibilityStateImplAndroid::~BrowserAccessibilityStateImplAndroid() {
ui::AccessibilityState::UnregisterAccessibilityStateDelegate(this);
}
void BrowserAccessibilityStateImplAndroid::
RecordAccessibilityServiceInfoHistograms() {
int event_type_mask =
ui::AccessibilityState::GetAccessibilityServiceEventTypeMask();
int feedback_type_mask =
ui::AccessibilityState::GetAccessibilityServiceFeedbackTypeMask();
int flags_mask = ui::AccessibilityState::GetAccessibilityServiceFlagsMask();
int capabilities_mask =
ui::AccessibilityState::GetAccessibilityServiceCapabilitiesMask();
std::vector<std::string> service_ids =
ui::AccessibilityState::GetAccessibilityServiceIds();
int len = service_ids.size();
bool has_assistive_tech = false;
bool has_password_manager = false;
bool has_unknown = false;
for (int i = 0; i < len; ++i) {
std::string service_id = service_ids[i];
std::string service_package = service_id.erase(service_id.find("/"));
uint32_t service_hash = base::PersistentHash(service_package);
if (base::Contains(kAssistiveTechPackageHashes, service_hash)) {
has_assistive_tech = true;
} else if (base::Contains(kPasswordPackageHashes, service_hash)) {
has_password_manager = true;
} else {
has_unknown = true;
}
}
if (has_assistive_tech && has_password_manager && has_unknown) {
RECORD_ALL_HISTOGRAMS(event_type_mask, feedback_type_mask, flags_mask,
capabilities_mask, ALL_VARIANTS);
} else if (has_assistive_tech && has_password_manager) {
RECORD_ALL_HISTOGRAMS(event_type_mask, feedback_type_mask, flags_mask,
capabilities_mask,
ASSISTIVE_TECH_WITH_PASSWORD_MANAGER);
} else if (has_assistive_tech && has_unknown) {
RECORD_ALL_HISTOGRAMS(event_type_mask, feedback_type_mask, flags_mask,
capabilities_mask, ASSISTIVE_TECH_WITH_UNKNOWN);
} else if (has_password_manager && has_unknown) {
RECORD_ALL_HISTOGRAMS(event_type_mask, feedback_type_mask, flags_mask,
capabilities_mask, PASSWORD_MANAGER_WITH_UNKNOWN);
} else if (has_assistive_tech) {
RECORD_ALL_HISTOGRAMS(event_type_mask, feedback_type_mask, flags_mask,
capabilities_mask, ASSISTIVE_TECH);
} else if (has_password_manager) {
RECORD_ALL_HISTOGRAMS(event_type_mask, feedback_type_mask, flags_mask,
capabilities_mask, PASSWORD_MANAGER);
} else if (has_unknown) {
RECORD_ALL_HISTOGRAMS(event_type_mask, feedback_type_mask, flags_mask,
capabilities_mask, UNKNOWN);
}
}
void BrowserAccessibilityStateImplAndroid::
RecordAccessibilityServiceStatsHistogram(int event_type_mask,
int feedback_type_mask,
int flags_mask,
int capabilities_mask,
std::string histogram) {
EVENT_TYPE_HISTOGRAM(event_type_mask, ANNOUNCEMENT, histogram);
EVENT_TYPE_HISTOGRAM(event_type_mask, ASSIST_READING_CONTEXT, histogram);
EVENT_TYPE_HISTOGRAM(event_type_mask, GESTURE_DETECTION_END, histogram);
EVENT_TYPE_HISTOGRAM(event_type_mask, GESTURE_DETECTION_START, histogram);
EVENT_TYPE_HISTOGRAM(event_type_mask, NOTIFICATION_STATE_CHANGED, histogram);
EVENT_TYPE_HISTOGRAM(event_type_mask, TOUCH_EXPLORATION_GESTURE_END,
histogram);
EVENT_TYPE_HISTOGRAM(event_type_mask, TOUCH_EXPLORATION_GESTURE_START,
histogram);
EVENT_TYPE_HISTOGRAM(event_type_mask, TOUCH_INTERACTION_END, histogram);
EVENT_TYPE_HISTOGRAM(event_type_mask, TOUCH_INTERACTION_START, histogram);
EVENT_TYPE_HISTOGRAM(event_type_mask, VIEW_ACCESSIBILITY_FOCUSED, histogram);
EVENT_TYPE_HISTOGRAM(event_type_mask, VIEW_ACCESSIBILITY_FOCUS_CLEARED,
histogram);
EVENT_TYPE_HISTOGRAM(event_type_mask, VIEW_CLICKED, histogram);
EVENT_TYPE_HISTOGRAM(event_type_mask, VIEW_CONTEXT_CLICKED, histogram);
EVENT_TYPE_HISTOGRAM(event_type_mask, VIEW_FOCUSED, histogram);
EVENT_TYPE_HISTOGRAM(event_type_mask, VIEW_HOVER_ENTER, histogram);
EVENT_TYPE_HISTOGRAM(event_type_mask, VIEW_HOVER_EXIT, histogram);
EVENT_TYPE_HISTOGRAM(event_type_mask, VIEW_LONG_CLICKED, histogram);
EVENT_TYPE_HISTOGRAM(event_type_mask, VIEW_SCROLLED, histogram);
EVENT_TYPE_HISTOGRAM(event_type_mask, VIEW_SELECTED, histogram);
EVENT_TYPE_HISTOGRAM(event_type_mask, VIEW_TEXT_CHANGED, histogram);
EVENT_TYPE_HISTOGRAM(event_type_mask, VIEW_TEXT_SELECTION_CHANGED, histogram);
EVENT_TYPE_HISTOGRAM(event_type_mask,
VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY, histogram);
EVENT_TYPE_HISTOGRAM(event_type_mask, WINDOWS_CHANGED, histogram);
EVENT_TYPE_HISTOGRAM(event_type_mask, WINDOW_CONTENT_CHANGED, histogram);
EVENT_TYPE_HISTOGRAM(event_type_mask, WINDOW_STATE_CHANGED, histogram);
EVENT_TYPE_HISTOGRAM(event_type_mask, SPEECH_STATE_CHANGE, histogram);
FEEDBACK_TYPE_HISTOGRAM(feedback_type_mask, SPOKEN, histogram);
FEEDBACK_TYPE_HISTOGRAM(feedback_type_mask, HAPTIC, histogram);
FEEDBACK_TYPE_HISTOGRAM(feedback_type_mask, AUDIBLE, histogram);
FEEDBACK_TYPE_HISTOGRAM(feedback_type_mask, VISUAL, histogram);
FEEDBACK_TYPE_HISTOGRAM(feedback_type_mask, GENERIC, histogram);
FEEDBACK_TYPE_HISTOGRAM(feedback_type_mask, BRAILLE, histogram);
FEEDBACK_TYPE_HISTOGRAM(feedback_type_mask, ALL_MASK, histogram);
FLAGS_HISTOGRAM(flags_mask, INCLUDE_NOT_IMPORTANT_VIEWS, histogram);
FLAGS_HISTOGRAM(flags_mask, REQUEST_TOUCH_EXPLORATION_MODE, histogram);
FLAGS_HISTOGRAM(flags_mask, REQUEST_ENHANCED_WEB_ACCESSIBILITY, histogram);
FLAGS_HISTOGRAM(flags_mask, REPORT_VIEW_IDS, histogram);
FLAGS_HISTOGRAM(flags_mask, REQUEST_FILTER_KEY_EVENTS, histogram);
FLAGS_HISTOGRAM(flags_mask, RETRIEVE_INTERACTIVE_WINDOWS, histogram);
FLAGS_HISTOGRAM(flags_mask, FORCE_DIRECT_BOOT_AWARE, histogram);
FLAGS_HISTOGRAM(flags_mask, ENABLE_ACCESSIBILITY_VOLUME, histogram);
FLAGS_HISTOGRAM(flags_mask, REQUEST_ACCESSIBILITY_BUTTON, histogram);
FLAGS_HISTOGRAM(flags_mask, REQUEST_FINGERPRINT_GESTURES, histogram);
FLAGS_HISTOGRAM(flags_mask, REQUEST_MULTI_FINGER_GESTURES, histogram);
FLAGS_HISTOGRAM(flags_mask, REQUEST_SHORTCUT_WARNING_DIALOG_SPOKEN_FEEDBACK,
histogram);
FLAGS_HISTOGRAM(flags_mask, SERVICE_HANDLES_DOUBLE_TAP, histogram);
FLAGS_HISTOGRAM(flags_mask, REQUEST_2_FINGER_PASSTHROUGH, histogram);
FLAGS_HISTOGRAM(flags_mask, SEND_MOTION_EVENTS, histogram);
FLAGS_HISTOGRAM(flags_mask, INPUT_METHOD_EDITOR, histogram);
CAPABILITY_TYPE_HISTOGRAM(capabilities_mask, CAN_RETRIEVE_WINDOW_CONTENT,
histogram);
CAPABILITY_TYPE_HISTOGRAM(capabilities_mask, CAN_REQUEST_TOUCH_EXPLORATION,
histogram);
CAPABILITY_TYPE_HISTOGRAM(capabilities_mask,
CAN_REQUEST_ENHANCED_WEB_ACCESSIBILITY, histogram);
CAPABILITY_TYPE_HISTOGRAM(capabilities_mask, CAN_REQUEST_FILTER_KEY_EVENTS,
histogram);
CAPABILITY_TYPE_HISTOGRAM(capabilities_mask, CAN_CONTROL_MAGNIFICATION,
histogram);
CAPABILITY_TYPE_HISTOGRAM(capabilities_mask, CAN_PERFORM_GESTURES, histogram);
CAPABILITY_TYPE_HISTOGRAM(capabilities_mask, CAN_REQUEST_FINGERPRINT_GESTURES,
histogram);
CAPABILITY_TYPE_HISTOGRAM(capabilities_mask, CAN_TAKE_SCREENSHOT, histogram);
}
void BrowserAccessibilityStateImplAndroid::OnAnimatorDurationScaleChanged() {
// We need to call into gfx::Animation and WebContentsImpl on the UI thread,
// so ensure that we setup the notification on the correct thread.
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
gfx::Animation::UpdatePrefersReducedMotion();
for (content::WebContentsImpl* wc :
content::WebContentsImpl::GetAllWebContents()) {
wc->OnWebPreferencesChanged();
}
}
void BrowserAccessibilityStateImplAndroid::OnDisplayInversionEnabledChanged(
bool enabled) {
// We need to call into GetInstanceForWeb on the UI thread,
// so ensure that we setup the notification on the correct thread.
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
ui::NativeTheme* native_theme = ui::NativeTheme::GetInstanceForWeb();
native_theme->set_inverted_colors(enabled);
native_theme->NotifyOnNativeThemeUpdated();
}
void BrowserAccessibilityStateImplAndroid::OnContrastLevelChanged(
bool highContrastEnabled) {
// We need to call into GetInstanceForWeb on the UI thread,
// so ensure that we setup the notification on the correct thread.
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
ui::NativeTheme* native_theme = ui::NativeTheme::GetInstanceForWeb();
native_theme->SetPreferredContrast(
highContrastEnabled ? ui::NativeTheme::PreferredContrast::kMore
: ui::NativeTheme::PreferredContrast::kNoPreference);
native_theme->set_prefers_reduced_transparency(highContrastEnabled);
native_theme->NotifyOnNativeThemeUpdated();
}
void BrowserAccessibilityStateImplAndroid::UpdateHistogramsOnOtherThread() {
BrowserAccessibilityStateImpl::UpdateHistogramsOnOtherThread();
// NOTE: this method is run from another thread to reduce jank, since
// there's no guarantee these system calls will return quickly. Be careful
// not to add any code that isn't safe to run from a non-main thread!
DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::UI));
// Screen reader metric.
ui::AXMode mode =
BrowserAccessibilityStateImpl::GetInstance()->GetAccessibilityMode();
UMA_HISTOGRAM_BOOLEAN("Accessibility.Android.ScreenReader",
mode.has_mode(ui::AXMode::kScreenReader));
}
void BrowserAccessibilityStateImplAndroid::UpdateUniqueUserHistograms() {
BrowserAccessibilityStateImpl::UpdateUniqueUserHistograms();
ui::AXMode mode = GetAccessibilityMode();
UMA_HISTOGRAM_BOOLEAN("Accessibility.Android.ScreenReader.EveryReport",
mode.has_mode(ui::AXMode::kScreenReader));
}
// static
std::unique_ptr<BrowserAccessibilityStateImpl>
BrowserAccessibilityStateImpl::Create() {
return std::make_unique<BrowserAccessibilityStateImplAndroid>();
}
} // namespace content