이 페이지에서는 VHAL에서 로터리 입력을 처리하는 방법, 로터리 서비스를 포함하도록 빌드를 구성하는 방법, 모든 앱에서 로터리 환경을 맞춤설정하는 방법을 설명합니다. OEM 제공 런처와 같은 사전 설치된 OEM 앱의 경우 자동차 UI 라이브러리(car-ui-library) 를 참조하세요.
브할
로터리 컨트롤러는 다음 작업을 지원합니다.
- 위, 아래, 왼쪽, 오른쪽으로 조금씩 움직입니다.
- 시계 방향과 시계 반대 방향으로 회전합니다.
- 중앙 버튼을 누르세요.
- 뒤로 버튼을 누르세요.
- 홈 버튼을 누르세요.
- 전화, 미디어 등 다른 버튼을 누릅니다.
시스템 속성 및 해당 int32Values
에 대한 문서는 hardware/interfaces/automotive/vehicle/2.0/types.hal
참조하세요.
VHAL은 다음 작업을 처리해야 합니다.
슬쩍 찌르다
사용자가 회전식 컨트롤러를 오른쪽으로 밀면 VHAL은 다음 int32Values
와 함께 HW_KEY_INPUT
속성을 사용하여 Android에 이벤트를 보내야 합니다.
-
ACTION_DOWN
-
KEYCODE_SYSTEM_NAVIGATION_RIGHT
- 타겟 디스플레이.
사용자가 로터리 컨트롤러를 놓으면 VHAL은 ACTION_UP
과 동일한 속성 및 키코드를 사용해야 합니다. 다른 방향으로의 넛지는 해당 키코드를 사용해야 합니다.
대각선에 대한 키 코드는 없지만 하드웨어가 대각선을 지원하는 경우 VHAL은 수평 및 수직 이벤트를 결합하여 대각선을 생성할 수 있습니다. 예를 들어, 위쪽과 왼쪽으로 조금씩 이동하면 다음이 생성됩니다.
-
HW_KEY_INPUT KEYCODE_SYSTEM_NAVIGATION_LEFT ACTION_DOWN
-
HW_KEY_INPUT KEYCODE_SYSTEM_NAVIGATION_UP ACTION_DOWN
어떤 순서로든(그리고 이후에) 회전 컨트롤러를 놓으면 다음이 생성됩니다.
-
HW_KEY_INPUT KEYCODE_SYSTEM_NAVIGATION_LEFT ACTION_UP
-
HW_KEY_INPUT KEYCODE_SYSTEM_NAVIGATION_UP ACTION_UP
사용자는 회전 컨트롤러를 놓기 전에 수직 방향으로 밀 수 있습니다. 예를 들어 다음 시나리오는 다음과 같습니다.
![수직 방향](https://source.android.google.cn/static/docs/automotive/images/rotary_06.png?authuser=8&hl=ko)
그러면 다음과 같은 일련의 이벤트가 생성됩니다.
-
HW_KEY_INPUT KEYCODE_SYSTEM_NAVIGATION_LEFT ACTION_DOWN
-
HW_KEY_INPUT KEYCODE_SYSTEM_NAVIGATION_UP ACTION_DOWN
-
HW_KEY_INPUT KEYCODE_SYSTEM_NAVIGATION_LEFT ACTION_UP
-
HW_KEY_INPUT KEYCODE_SYSTEM_NAVIGATION_UP ACTION_UP
회전 컨트롤러를 한 방향으로 잡고 있는 동안에는 반복 이벤트가 생성되어서는 안 됩니다.
회전
사용자가 로터리 컨트롤러를 한 멈춤쇠(클릭)만큼 시계 방향으로 회전하면 VHAL은 다음 int32Values
와 함께 HW_ROTARY_INPUT
속성을 사용하여 Android에 이벤트를 전송해야 합니다.
-
ROTARY_INPUT_TYPE_SYSTEM_NAVIGATION
- 1개의 멈춤쇠.
- 타겟 디스플레이.
이벤트의 타임스탬프는 나노초 단위의 경과 시간으로 설정되어야 합니다.
1개의 디텐트 반시계 방향 회전은 동일한 이벤트를 생성해야 하지만 디텐트 수는 -1입니다.
동일한 방향으로 여러 회전 디텐트가 빠르게 연속해서 발생하는 경우 VHAL은 이벤트로 인해 시스템에 과부하가 발생하지 않도록 디텐트를 단일 이벤트로 결합해야 합니다. 이 경우 이벤트의 타임스탬프는 첫 번째 회전 정지가 발생한 시점이어야 합니다. int32Values
에는 연속적인 회전 정지 사이의 나노초 수가 포함되어야 합니다.
예를 들어 다음과 같은 회전 순서가 있습니다.
- 시간 t0에서 사용자는 시계 반대 방향으로 1개의 멈춤쇠를 회전했습니다.
- 시간 t0 + 5ns에서 사용자는 시계 반대 방향으로 1개의 멈춤쇠를 회전했습니다.
- 시간 t0 + 8ns에서 사용자는 시계 반대 방향으로 1개의 멈춤쇠를 회전했습니다.
다음 이벤트를 생성해야 합니다.
- 속성:
HW_ROTARY_INPUT
- 타임스탬프:
t0
-
int32Values
:-
ROTARY_INPUT_TYPE_SYSTEM_NAVIGATION
- -3(시계 반대 방향으로 3개의 멈춤쇠).
- 타겟 디스플레이.
- 첫 번째 멈춤쇠와 두 번째 멈춤쇠 사이는 5ns입니다.
- 두 번째와 세 번째 멈춤쇠 사이는 3ns입니다.
-
가운데 버튼
사용자가 가운데 버튼을 누르면 VHAL은 다음 int32Values
와 함께 HW_KEY_INPUT
속성을 사용하여 Android에 이벤트를 보내야 합니다.
-
ACTION_DOWN
-
KEYCODE_DPAD_CENTER
- 타겟 디스플레이.
사용자가 로터리 컨트롤러를 놓으면 VHAL은 ACTION_UP
과 동일한 속성 및 키코드를 사용해야 합니다.
가운데 버튼을 누른 상태에서는 반복 이벤트를 생성하지 않습니다.
뒤로 버튼
사용자가 뒤로 버튼을 누르면 VHAL은 다음 int32Values
와 함께 HW_KEY_INPUT
속성을 사용하여 Android에 이벤트를 보내야 합니다.
-
ACTION_DOWN
-
KEYCODE_BACK
- 타겟 디스플레이.
사용자가 로터리 컨트롤러를 놓으면 VHAL은 ACTION_UP
과 동일한 속성 및 키코드를 사용해야 합니다.
가운데 버튼을 누르고 있는 동안에는 반복 이벤트가 생성되어서는 안 됩니다.
홈 버튼
뒤로 버튼과 마찬가지로 홈 버튼을 처리하지만 KEYCODE_BACK
대신 KEYCODE_HOME
사용합니다.
기타 버튼
로터리 컨트롤러에 추가 버튼이 포함된 경우 VHAL은 Android의 관점에서 로터리의 일부로 간주되지 않으므로 OEM이 원하는 대로 해당 버튼을 처리할 수 있습니다. 이는 일반적으로 뒤로 및 홈 버튼처럼 처리되지만 키코드는 다릅니다. 예를 들어 KEYCODE_CALL
또는 KEYCODE_MUSIC
.
빌드 구성
로타리 내비게이션은 RotaryService
라는 접근성 서비스를 통해 제공됩니다. 장치의 시스템 이미지에 이 서비스를 포함하려면 makefile에 다음 줄을 추가하세요.
PRODUCT_PACKAGES += CarRotaryController
디버그 빌드에 다음 패키지를 포함할 수도 있습니다.
-
RotaryPlayground
로터리용 참조 앱입니다( RotaryPlayground 참조). -
RotaryIME
데모 로터리 IME( 입력기 편집기 참조). -
CarRotaryImeRRO
RotaryIME
용 오버레이입니다.
로터리 서비스는 장치가 부팅될 때와 사용자 전환이 발생할 때 자동으로 활성화됩니다. 이렇게 하면 사용자가 설정 중에 회전 컨트롤러를 사용할 수 있습니다.
로터리 컨트롤러가 있는 자동차와 없는 자동차에 동일한 빌드를 사용하는 경우 필요한 코드가 빌드에 포함되도록 위에 표시된 대로 CarRotaryController
추가하세요. 회전하지 않는 자동차에서 회전 서비스가 활성화되는 것을 방지하려면 정적 RRO를 생성하여 packages/services/Car/service
의 rotaryService
문자열 리소스를 빈 문자열로 오버레이합니다. 동일한 빌드를 사용하지만 회전식 장치와 비회전식 장치에 대해 별도의 제품 구성을 갖습니다. 후자에만 오버레이가 포함됩니다.
맞춤화
OEM은 다음 위치의 리소스 오버레이를 통해 포커스 찾기 논리, 포커스 강조 표시 및 일부 추가 항목을 사용자 정의할 수 있습니다.
- car-ui-library는
packages/apps/Car/libs/car-ui-lib
에 있습니다. -
RotaryService
는packages/apps/Car/RotaryController
에 있습니다. -
Core
frameworks/base/core
에 있습니다.
넛지 역사
OEM은 두 가지 유형의 넛지 기록을 각각 활성화할지 여부와 활성화할 경우 캐시 크기 및 만료 정책을 구성할 수 있습니다. 이 모든 작업은 다양한 car-ui-library 리소스를 재정의하여 수행됩니다.
포커스 기록 캐시
( 안드로이드 11 QPR3, 안드로이드 11 자동차, 안드로이드 12 )
이 FocusArea
별 캐시는 FocusArea
내에서 가장 최근에 초점이 맞춰진 뷰를 저장하므로 FocusArea
로 다시 이동할 때 초점이 맞춰질 수 있습니다. 이 캐시는 다음 car-ui-library 리소스를 오버레이하여 구성할 수 있습니다.
-
car_ui_focus_history_cache_type
:- 캐시가 비활성화되었습니다.
- 캐시는 일정 시간이 지나면 만료됩니다(아래 참조).
- 캐시는 만료되지 않습니다.
-
car_ui_focus_history_expiration_period_ms
_ms : 캐시 유형이 2로 설정된 경우 캐시가 만료되기까지의 시간(밀리초)입니다(위 참조).
FocusArea 기록 캐시
( 안드로이드 11 QPR3, 안드로이드 11 자동차, 안드로이드 12 )
이 캐시는 반대 방향으로 살짝 움직여 포커스를 동일한 FocusArea
로 되돌릴 수 있도록 살짝 밀기 기록을 저장합니다. 이 캐시는 다음 car-ui-library 리소스를 오버레이하여 구성할 수 있습니다.
-
car_ui_focus_area_history_cache_type
:- 캐시가 비활성화되었습니다.
- 캐시는 일정 시간이 지나면 만료됩니다(아래 참조).
- 캐시는 만료되지 않습니다.
-
car_ui_focus_area_history_expiration_period_ms
_ms : 캐시 유형이 2로 설정된 경우 캐시가 만료되기까지의 시간(밀리초)입니다(위 참조). -
car_ui_clear_focus_area_history_when_rotating
: 사용자가 컨트롤러를 회전할 때 캐시를 무효화할지 여부입니다.
회전
( 안드로이드 11 QPR3, 안드로이드 11 자동차, 안드로이드 12 )
OEM은 RotaryService
에서 두 개의 정수 리소스를 재정의하여 마우스 가속과 같이 회전에 가속이 있는지 여부를 지정할 수 있습니다.
-
rotation_acceleration_3x_ms
: Google이 회전을 멈추기 위해 컨트롤러 회전을 가속해야 하는지 결정하는 데 사용되는 시간 간격(밀리초)입니다. 이 멈춤쇠와 이전 회전 멈춤쇠 사이의 간격이 이 값보다 작으면 3개의 회전 멈춤쇠로 간주됩니다. 3배 가속을 비활성화하려면 이 값을 2147483647로 설정합니다. -
rotation_acceleration_2x_ms
:rotation_acceleration_3x_ms
와 유사합니다. 2배 가속에 사용됩니다. 2배 가속을 비활성화하려면 이 값을2147483647
로 설정합니다.
VHAL에서 요구하는 대로 각 회전 디텐트에 대한 개별 타임스탬프가 있는 경우 가속이 가장 잘 작동합니다. 이를 사용할 수 없는 경우 RotaryService
는 회전 멈춤쇠의 간격이 균일하다고 가정합니다.
/** * Property to feed H/W rotary events to android * * int32Values[0] : RotaryInputType identifying which rotary knob rotated * int32Values[1] : number of detents (clicks), positive for clockwise, * negative for counterclockwise * int32Values[2] : target display defined in VehicleDisplay. Events not * tied to specific display must be sent to * VehicleDisplay#MAIN. * int32values[3 .. 3 + abs(number of detents) - 2]: * nanosecond deltas between pairs of consecutive detents, * if the number of detents is > 1 or < -1 * * VehiclePropValue.timestamp: when the rotation occurred. If the number of * detents is > 1 or < -1, this is when the * first detent of rotation occurred. * * @change_mode VehiclePropertyChangeMode:ON_CHANGE * @data_enum RotaryInputType * @access VehiclePropertyAccess:READ */ HW_ROTARY_INPUT = ( 0x0A20 | VehiclePropertyGroup:SYSTEM | VehiclePropertyType:INT32_VEC | VehicleArea:GLOBAL),
포커스 하이라이트
OEM은 Android 프레임워크의 기본 포커스 하이라이트와 car-ui-library의 여러 포커스 하이라이트 리소스를 재정의할 수 있습니다.
기본 초점 하이라이트
Android 프레임워크는 selectableItemBackground
속성을 통해 기본 포커스 강조 표시를 제공합니다. Theme.DeviceDefault
에서 이 속성은 Core
의 item_background.xml
참조합니다. OEM은 item_background.xml
오버레이하여 기본 초점 강조 표시 드로어블을 변경할 수 있습니다.
이 드로어블은 일반적으로 android:state_focused
및 android:state_pressed
포함하여 다양한 상태 조합을 기반으로 배경을 조정하는 StateListDrawable
이어야 합니다. 사용자가 로터리 컨트롤러를 사용하여 뷰에 초점을 맞추면 android:state_focused
true
되지만 android:state_pressed
는 false
가 됩니다. 그런 다음 사용자가 로터리 컨트롤러의 가운데 버튼을 누르면 사용자가 버튼을 누르고 있는 동안 android:state_focused
및 android:state_pressed
모두 true
됩니다. 사용자가 버튼을 놓으면 android:state_focused
만 true
로 유지됩니다.
car-ui-library는 Theme.DeviceDefault
에서 파생된 테마를 사용합니다. 결과적으로 이 오버레이는 이 라이브러리를 사용하는 앱과 Theme.DeviceDefault
에서 파생된 테마를 사용하는 앱에 영향을 미칩니다. Theme.Material
과 같이 관련 없는 테마를 사용하는 앱에는 영향을 미치지 않습니다.
car-ui-library의 포커스 하이라이트 리소스
OEM은 여러 car-ui-library 리소스를 재정의하여 직사각형이 아닌(예: 원형 또는 알약 모양) 초점 강조 표시가 있는 뷰와 Theme.DeviceDefault
에서 파생되지 않은 테마를 사용하는 앱에서 초점 강조 표시가 어떻게 보이는지 제어할 수 있습니다. Theme.DeviceDefault
. 이러한 리소스는 포커스 하이라이트가 기본 포커스 하이라이트 드로어 블과 일치하도록 오버레이되어야 합니다.
( 안드로이드 11 QPR3, 안드로이드 11 자동차, 안드로이드 12 )
다음 리소스는 뷰에 포커스가 있지만 누르지 않은 경우를 나타내는 데 사용됩니다.
-
car_ui_rotary_focus_fill_color
: 채우기 색상. -
car_ui_rotary_focus_stroke_color
: 윤곽선 색상. -
car_ui_rotary_focus_stroke_width
: 외곽선의 두께입니다.
( 안드로이드 11 QPR3, 안드로이드 11 자동차, 안드로이드 12 )
다음 리소스는 보기에 초점이 맞춰 지고 눌러지는 시기를 나타내는 데 사용됩니다.
-
car_ui_rotary_focus_pressed_fill_color
: 채우기 색상입니다. -
car_ui_rotary_focus_pressed_stroke_color
: 외곽선 색상입니다. -
car_ui_rotary_focus_pressed_stroke_width
: 외곽선의 두께입니다.
표시된 예와 같이 사용자의 주의를 끌기 위해 버튼에 단색 배경색이 지정되는 경우도 있습니다. 이로 인해 초점 하이라이트가 보기 어려울 수 있습니다.
![단색 배경의 버튼](https://source.android.google.cn/static/docs/automotive/images/rotary_05.png?authuser=8&hl=ko)
- ( 안드로이드 11 QPR3, 안드로이드 11 자동차, 안드로이드 12 )
car_ui_rotary_focus_fill_secondary_color
car_ui_rotary_focus_stroke_secondary_color
- ( 안드로이드 12 )
car_ui_rotary_focus_pressed_fill_secondary_color
car_ui_rotary_focus_pressed_stroke_secondary_color
예를 들어 채우기만 원하거나 윤곽선만 원하는 경우 모든 색상이 투명할 수 있으며 치수 중 하나가 0일 수 있습니다.
초점 영역 하이라이트
( 안드로이드 11 QPR3, 안드로이드 11 자동차, 안드로이드 12 )
FocusArea
하위 항목 중 하나에 초점이 맞춰지면 두 가지 유형의 강조 표시를 그릴 수 있습니다. 원하는 경우 두 가지를 함께 사용할 수 있습니다. 이 기능은 AOSP에서 기본적으로 비활성화되어 있지만 car-ui-library 리소스를 재정의하여 활성화할 수 있습니다.
-
car_ui_enable_focus_area_foreground_highlight
:FocusArea
및 그 하위 항목 위에 강조 표시를 그립니다. AOSP에서 이 드로어블은FocusArea
주변의 윤곽선입니다. OEM은car_ui_focus_area_foreground_highlight
드로어블을 재정의할 수 있습니다. -
car_ui_enable_focus_area_background_highlight
:FocusArea
상단, 해당 하위 항목 뒤에 강조 표시를 그립니다. AOSP에서 이 드로어블은 솔리드 채우기입니다. OEM은car_ui_focus_area_background_highlight
드로어블을 재정의할 수 있습니다.
입력기 편집기
IME(입력기)는 입력 방법입니다. 예를 들어 화상 키보드가 있습니다.
( 안드로이드 11 QPR3, 안드로이드 11 자동차, 안드로이드 12 )
OEM은 터치 기반 IME의 ComponentName
지정하기 위해 RotaryService
의 default_touch_input_method
문자열 리소스를 오버레이해야 합니다. 예를 들어 OEM이 Android Automotive와 함께 제공되는 IME를 사용하는 경우 com.google.android.apps.automotive.inputmethod/.InputMethodService
지정해야 합니다.
( 안드로이드 11 QPR3, 안드로이드 11 자동차, 안드로이드 12 )
OEM이 로터리용으로 특별히 IME를 만든 경우 rotary_input_method
리소스에 해당 ComponentName
지정해야 합니다. 이 리소스가 오버레이되면 사용자가 로터리 컨트롤러의 너지, 회전 및 가운데 버튼을 통해 헤드 유닛과 상호 작용할 때마다 지정된 IME가 사용됩니다. 사용자가 화면을 터치하면 이전 IME가 사용됩니다. 뒤로 버튼(및 회전 컨트롤러의 다른 버튼)은 IME 선택에 영향을 주지 않습니다. 이 리소스가 오버레이되지 않으면 IME 전환이 발생하지 않습니다. Carboard는 로터리를 지원하지 않으므로 OEM이 로터리 IME를 제공하지 않은 경우 사용자는 로터리 컨트롤러를 통해 텍스트를 입력할 수 없습니다.
RotaryIME
는 데모 로터리 IME입니다. 기본적이지만 위에서 설명한 자동 IME 전환을 시도해 보는 것만으로도 충분합니다. RotaryIME
의 소스 코드는 packages/apps/Car/tests/RotaryIME/
에서 찾을 수 있습니다.
화면 밖의 넛지
기본적으로 사용자가 화면 가장자리에서 벗어나려고 하면 아무 일도 일어나지 않습니다. OEM은 다음 조합을 지정하여 네 방향 각각에 대해 발생해야 하는 작업을 구성할 수 있습니다.
-
AccessibilityService
에 의해 정의된 전역 작업입니다. 예를 들어GLOBAL_ACTION_BACK
. -
KEYCODE_BACK
과 같은 키 코드입니다. - URL로 표시되는 활동을 시작하려는 의도입니다.
( 안드로이드 11 QPR3, 안드로이드 11 자동차, 안드로이드 12 )
이는 RotaryService
에서 다음 배열 리소스를 오버레이하여 지정됩니다.
-
off_screen_nudge_global_actions
: 사용자가 화면 가장자리에서 위, 아래, 왼쪽 또는 오른쪽으로 움직일 때 수행할 전역 작업 배열입니다. 이 배열의 관련 요소가 -1이면 전역 작업이 수행되지 않습니다. -
off_screen_nudge_key_codes
: 사용자가 화면 가장자리에서 위, 아래, 왼쪽 또는 오른쪽으로 움직일 때 삽입할 클릭 이벤트의 키 코드 배열입니다. 이 배열의 관련 요소가 0(KEYCODE_UNKNOWN
)이면 이벤트가 주입되지 않습니다. -
off_screen_nudge_intents
: 사용자가 화면 가장자리에서 위, 아래, 왼쪽 또는 오른쪽으로 움직일 때 활동을 시작하는 인텐트 배열입니다. 이 배열의 관련 요소가 비어 있으면 활동이 시작되지 않습니다.
기타 구성
다음 RotaryService
리소스를 오버레이해야 합니다:
- ( 안드로이드 11 QPR3, 안드로이드 11 자동차, 안드로이드 12 )
config_showHeadsUpNotificationOnBottom
: 헤드업 알림을 상단이 아닌 하단에 표시해야 하는지 여부를 나타내는 부울 값입니다. 이는frameworks/base/packages/CarSystemUI/res/values/config.xml
의config_showHeadsUpNotificationOnBottom
부울 리소스와 동일한 값을 가져야 합니다. - ( 안드로이드 11 QPR3, 안드로이드 11 자동차, 안드로이드 12 )
notification_headsup_card_margin_horizontal
: 헤드업 알림 창의 왼쪽 및 오른쪽 여백입니다. 이는packages/apps/Car/Notification/res/values/dimens.xml
의notification_headsup_card_margin_horizontal
dimen 리소스와 동일한 값을 가져야 합니다. - ( 안드로이드 12 )
excluded_application_overlay_window_titles
: 오버레이 창으로 간주되어서는 안 되는 창 제목의 배열입니다. 여기에는TaskViews
또는TaskDisplayAreas
나타내는 앱 창의 제목이 포함되어야 합니다. 기본적으로 이 목록에는 '지도'만 포함됩니다.
다음 RotaryService
리소스를 오버레이할 수 있습니다:
- ( 안드로이드 11 QPR3, 안드로이드 11 자동차, 안드로이드 12 )
long_press_ms
: 길게 누르기를 트리거하기 위해 가운데 버튼을 누르고 있어야 하는 시간(밀리초)을 나타내는 정수 값입니다. 0은 시스템 기본 길게 누르기 시간 제한을 사용해야 함을 나타냅니다. 이것이 기본값입니다.