diff options
3 files changed, 173 insertions, 0 deletions
diff --git a/core/proto/android/input/keyboard_configured.proto b/core/proto/android/input/keyboard_configured.proto new file mode 100644 index 000000000000..16990087b319 --- /dev/null +++ b/core/proto/android/input/keyboard_configured.proto @@ -0,0 +1,50 @@ +/* + * Copyright 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +syntax = "proto2"; + +package com.android.internal.os; + +option java_outer_classname = "KeyboardConfiguredProto"; + +/** + * RepeatedKeyboardLayout proto from input_extension_atoms.proto, + * duplicated here so that it's accessible in the build. + * Must be kept in sync with the version in input_extension_atoms.proto. + */ + +// Message containing the repeated field for KeyboardLayoutConfig +message RepeatedKeyboardLayoutConfig { + repeated KeyboardLayoutConfig keyboard_layout_config = 1; +} + +// Keyboard layout configured when the device is connected +// used in KeyboardConfigured atom +message KeyboardLayoutConfig { + // Keyboard configuration details + // Layout type mappings found at: + // frameworks/base/core/res/res/values/attrs.xml + optional int32 keyboard_layout_type = 1; + // PK language language tag (e.g. en-US, ru-Cyrl, etc). This will follow + // BCP-47 language tag standards. + optional string keyboard_language_tag = 2; + // Selected keyboard layout name (e.g. English(US), English(Dvorak), etc.) + optional string keyboard_layout_name = 3; + // Criteria for layout selection (such as user, device, virtual keyboard based) + // IntDef annotation at: + // services/core/java/com/android/server/input/KeyboardMetricsCollector.java + optional int32 layout_selection_criteria = 4; +} diff --git a/services/core/java/com/android/server/input/KeyboardLayoutManager.java b/services/core/java/com/android/server/input/KeyboardLayoutManager.java index 6ec4022fe15a..611a61a2e272 100644 --- a/services/core/java/com/android/server/input/KeyboardLayoutManager.java +++ b/services/core/java/com/android/server/input/KeyboardLayoutManager.java @@ -252,6 +252,8 @@ final class KeyboardLayoutManager implements InputManager.InputDeviceListener { if (needToShowNotification) { maybeUpdateNotification(); } + // TODO (b/280421650): Implement logging statements using KeyboardMetricsCollector + // for KeyboardConfigured atom } private String getDefaultKeyboardLayout(final InputDevice inputDevice) { diff --git a/services/core/java/com/android/server/input/KeyboardMetricsCollector.java b/services/core/java/com/android/server/input/KeyboardMetricsCollector.java index a9ae3121ce9f..b8f57f555c0e 100644 --- a/services/core/java/com/android/server/input/KeyboardMetricsCollector.java +++ b/services/core/java/com/android/server/input/KeyboardMetricsCollector.java @@ -16,10 +16,20 @@ package com.android.server.input; +import static java.lang.annotation.RetentionPolicy.SOURCE; + +import android.annotation.IntDef; +import android.hardware.input.KeyboardLayout; +import android.util.proto.ProtoOutputStream; import android.view.InputDevice; +import com.android.internal.os.KeyboardConfiguredProto.KeyboardLayoutConfig; +import com.android.internal.os.KeyboardConfiguredProto.RepeatedKeyboardLayoutConfig; import com.android.internal.util.FrameworkStatsLog; +import java.lang.annotation.Retention; +import java.util.List; + /** * Collect Keyboard metrics */ @@ -38,4 +48,115 @@ public final class KeyboardMetricsCollector { FrameworkStatsLog.write(FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED, vendor_id, product_id, keyboardSystemEvent, keyCode, modifierState); } + + /** + * Function to log the KeyboardConfigured + * {@link com.android.os.input.KeyboardConfigured} atom + * + * @param inputDevice Input device + * @param keyboardLayoutConfigurations List of keyboard configurations + * @param isFirstTimeConfiguration Whether keyboard is configured for the first time + */ + public static void logKeyboardConfiguredAtom(InputDevice inputDevice, + List<KeyboardLayoutConfiguration> keyboardLayoutConfigurations, + boolean isFirstTimeConfiguration) { + int vendor_id = inputDevice.getVendorId(); + int product_id = inputDevice.getProductId(); + + // Creating proto to log nested field KeyboardLayoutConfig in atom + ProtoOutputStream proto = new ProtoOutputStream(); + + for (KeyboardLayoutConfiguration keyboardLayoutConfiguration : + keyboardLayoutConfigurations) { + addKeyboardLayoutConfigurationToProto(proto, keyboardLayoutConfiguration); + } + // Push the atom to Statsd + FrameworkStatsLog.write(FrameworkStatsLog.KEYBOARD_CONFIGURED, + isFirstTimeConfiguration, vendor_id, product_id, proto.getBytes()); + } + + /** + * Populate the KeyboardLayoutConfig proto which is a repeated proto + * in the RepeatedKeyboardLayoutConfig proto with values from the + * {@link KeyboardLayoutConfiguration} class + * The proto definitions can be found at: + * "frameworks/proto_logging/stats/atoms/input/input_extension_atoms.proto" + * + * @param proto Representing the nested proto RepeatedKeyboardLayoutConfig + * @param keyboardLayoutConfiguration Class containing the fields for populating the + * KeyboardLayoutConfig proto + */ + private static void addKeyboardLayoutConfigurationToProto(ProtoOutputStream proto, + KeyboardLayoutConfiguration keyboardLayoutConfiguration) { + // Start a new KeyboardLayoutConfig proto. + long keyboardLayoutConfigToken = proto.start( + RepeatedKeyboardLayoutConfig.KEYBOARD_LAYOUT_CONFIG); + proto.write(KeyboardLayoutConfig.KEYBOARD_LANGUAGE_TAG, + keyboardLayoutConfiguration.getKeyboardLanguageTag()); + proto.write(KeyboardLayoutConfig.KEYBOARD_LAYOUT_TYPE, + keyboardLayoutConfiguration.getKeyboardLayoutType()); + proto.write(KeyboardLayoutConfig.KEYBOARD_LAYOUT_NAME, + keyboardLayoutConfiguration.getKeyboardLayoutName()); + proto.write(KeyboardLayoutConfig.LAYOUT_SELECTION_CRITERIA, + keyboardLayoutConfiguration.getLayoutSelectionCriteria()); + proto.end(keyboardLayoutConfigToken); + } + + /** + * Java class representing the proto KeyboardLayoutConfig defined in + * "frameworks/proto_logging/stats/atoms/input/input_extension_atoms.proto" + * + * @see com.android.os.input.KeyboardConfigured + */ + public static class KeyboardLayoutConfiguration { + // KeyboardLayoutType in "frameworks/base/core/res/res/values/attrs.xml" + // contains mapping for enums to int + int mKeyboardLayoutType; + String mKeyboardLanguageTag; + KeyboardLayout mKeyboardLayout; + @LayoutSelectionCriteria int mLayoutSelectionCriteria; + + @Retention(SOURCE) + @IntDef(prefix = { "LAYOUT_SELECTION_CRITERIA_" }, value = { + LAYOUT_SELECTION_CRITERIA_USER, + LAYOUT_SELECTION_CRITERIA_DEVICE, + LAYOUT_SELECTION_CRITERIA_VIRTUAL_KEYBOARD + }) + public @interface LayoutSelectionCriteria {} + + /** Manual selection by user */ + public static final int LAYOUT_SELECTION_CRITERIA_USER = 0; + + /** Auto-detection based on device provided language tag and layout type */ + public static final int LAYOUT_SELECTION_CRITERIA_DEVICE = 1; + + /** Auto-detection based on IME provided language tag and layout type */ + public static final int LAYOUT_SELECTION_CRITERIA_VIRTUAL_KEYBOARD = 2; + + KeyboardLayoutConfiguration(int keyboardLayoutType, + String keyboardLanguageTag, + KeyboardLayout keyboardLayout, + @LayoutSelectionCriteria int layoutSelectionCriteria) { + mKeyboardLayoutType = keyboardLayoutType; + mKeyboardLanguageTag = keyboardLanguageTag; + mKeyboardLayout = keyboardLayout; + mLayoutSelectionCriteria = layoutSelectionCriteria; + } + int getKeyboardLayoutType() { + return mKeyboardLayoutType; + } + + String getKeyboardLanguageTag() { + return mKeyboardLanguageTag; + } + + String getKeyboardLayoutName() { + return mKeyboardLayout.getLabel(); + } + + @LayoutSelectionCriteria int getLayoutSelectionCriteria() { + return mLayoutSelectionCriteria; + } + } } + |