
本記事では、Android Automotive OS (AAOS)において車が走行中であるかの判定方法や、走行中にUXを制限する方法についてAndroid Open Source Project (AOSP)のコードを確認しながら説明していきます。
また、どのようにUxRestrictionsのルールを組み込むか、それをどのように利用するかも確認します。
※本記事で参照しているのはAOSPのコードであり、具体的な製品の仕様とは異なる可能性がありますのでご承知おきください。
車両向けアプリを開発するにあたって必要となる考え方についてここで説明します。
Driver Distractionとは
車載向けアプリ(特にAAOS向け)の開発において考慮しなければならない特徴的な要件の一つがDriver Distractionです。
Driver Distractionとは、ドライバーの運転に対する注意が散漫になることです。
運転は人命に関わる重大なタスクであるため、アプリはドライバーの集中を妨げないようにする必要があります。そのために車載アプリのUI/UXで守るべきルールが存在します。
ここでHondaのDriver Distractionに対応するためのルールを述べることはできませんが、Googleの以下のドキュメントに基本的な考え方が書かれています。
アプリのコンテンツと操作は、ドライバーの注意散漫を最小限に抑えながら、運転中の操作を補完するものである必要があります。ドライバーが道路から目を離さず、ハンドルを握ったまま操作できるように、UI を簡素化する必要があります。
さらに、操作の原則、ビジュアルの原則、記述の原則ではより具体的に原則について説明しており、参考になります。
Driver Distractionに対応するUI/UX
Driver Distractionを最小化するために、アプリのUI/UXを制限することがあります。
特に走行中については厳しい制限が適用されます。
UI/UXの制限の例としては以下のようなものが挙げられます。
- 操作の制限
- スクロール操作の制限
- キーボード入力など複雑な操作の禁止
- アプリの階層遷移の制限
- ビジュアルの制限
- 画面に表示する要素の数
- 文字サイズやボタンサイズの制限(一定以上の大きさ)
- 注意を引く動画やアニメーションの再生禁止
- テキストの長さの制限
走行中の利用も想定する車載向けアプリを開発する場合にはこれらをはじめ、ドライバーの状況を想定してUI/UXを作り込んでいかなければなりません。
AAOSではどのようにUI/UX制限(UX Restriction)のルールを定義し、Androidアプリ側にどのように提供しているかを見ていきます。
テンプレートによるUI/UX制限の実現
車載向けアプリに対するノウハウがないアプリ提供者にとって、Driver Distractionに対応したUIを考えることは困難です。一方で、ナビやメディアなど運転中に利用できることでユーザーの利便性を上げられるアプリもあります。
そこでGoogleは車載向けにリリースできるアプリのタイプを定め、同時にAndroid Autoアプリ向けにUIのテンプレートを用意しています。
これらのテンプレートはAAOSを開発している自動車メーカーによって、車載アプリとして適したUIにカスタマイズされています。また、走行中かどうかを判定してUIを切り替えるものもあります。
そのためテンプレートを使用することで、アプリ提供者は少ない労力で車載利用に最適化された方法でUIを実現できます。
Android Automotive OSのDriver Distraction(UX Restriction)
AAOSでは車両が走行中かどうか判定し、状況に応じてUI/UXを制限する仕組みがあります。
ここではそのルールの定義、走行状態の判定、利用方法を見ていきます。
Googleが定義してくれているテンプレートを利用する場合はここまで意識することはないと思いますが、どのような仕組みになっているか見てみるのは面白いと思います。
UxRestrictionsのルールの定義
Android Automotive OSを開発する自動車メーカーは、packages/services/Car/service/res/xml/car_ux_restrictions_map.xml
を使用してUX制限のルールを記載します(リンクはAOSPのデフォルトのファイルです)。
例えば以下の例では、movingの状態で5.0m/s以上の速度が出ている場合にUX制限を適用しています。
state="moving" minSpeed="5.0">
requiresDistractionOptimization="true" uxr="no_dialpad|no_filtering|limit_string_length|no_keyboard|no_video|limit_content|no_setup|no_text_message"/>
UX制限の種別はCarUxRestrictionsに定義があります。
例えば、no_video
=UX_RESTRICTIONS_NO_VIDEO
の場合は動画を制限することを意図します。
limit_content
=UX_RESTRICTIONS_LIMIT_CONTENT
は画面に含まれるコンテンツの数を制限します。getMaxCumulativeContentItems()
やgetMaxContentDepth()
で取得できる値によって、アプリ側でUIが制限するものですが、この値は同じくpackages/services/Car/service/res/xml/car_ux_restrictions_map.xml内のRestrictionParameters
に定義します。
maxLength="120"/>
maxCumulativeItems="21" maxDepth="3"/>
DrivingStateの判定処理
DrivingStateは下記の通りです。
- parked: ギアがパーキングに入っている
- idling: ギアがパーキングに入っておらず、速度がゼロ
- moving: ギアがパーキングに入っておらず、速度がゼロではない
以下はその判定ロジックの抜粋です:
/**
* Infers the current driving state of the car from the other Car Sensor properties like
* Current Gear, Speed etc.
*
* @return Current driving state
*/
@GuardedBy("mLock")
@CarDrivingState
private int inferDrivingStateLocked() {
updateVehiclePropertiesIfNeededLocked();
if (DBG) {
Slogf.d(TAG,
"inferDrivingStateLocked mLastGear: " + mLastGear + "mLastSpeed: " + mLastSpeed
+ "mLastIgnitionState: " + mLastIgnitionState);
}
/*
Logic to start off deriving driving state:
1. If gear == parked, then Driving State is parked.
2. If gear != parked,
2a. if parking brake is applied, then Driving state is parked.
2b. if parking brake is not applied or unknown/unavailable, then driving state
is still unknown.
3. If driving state is unknown at the end of step 2,
3a. if speed == 0, then driving state is idling
3b. if speed != 0, then driving state is moving
3c. if speed is unavailable,
3ca. If ignition state is supported and ignition state == lock or acc or
off, then driving state is parked
3cb. else driving state is unknown
*/
if (isVehicleKnownToBeParkedLocked()) {
return CarDrivingStateEvent.DRIVING_STATE_PARKED;
}
// We don't know if the vehicle is parked, let's look at the speed.
if (!isPropertyStatusAvailable(mLastSpeed)) {
if (isOptionalPropertySupportedLocked(VehicleProperty.IGNITION_STATE)
&& isVehicleKnownToBeInLockOrAccOrOffIgnitionStateLocked()) {
return CarDrivingStateEvent.DRIVING_STATE_PARKED;
}
return CarDrivingStateEvent.DRIVING_STATE_UNKNOWN;
} else if (mLastSpeed.getValue().equals(0f)) {
return CarDrivingStateEvent.DRIVING_STATE_IDLING;
} else {
return CarDrivingStateEvent.DRIVING_STATE_MOVING;
}
}
それぞれの状態でどのようなUX制限(Restrictions)のルールを適用するかをcar_ux_restrictions_map.xmlに記載します。
DrivingStateの定義はCarDrivingStateEventにあります。
CarDrivingStateServiceがギア、パーキングブレーキ、速度、イグニッションなどの状態を持っており、CarDrivingStateServiceのinferDrivingStateLockedの中でDrivingStateを判定しています。
UxRestrictionの判定処理
car_ux_restrictions_map.xmlで定義した内容が読み込まれ保持されており、CarUxRestrictionsConfigurationのgetUxRestrictionsでDrivingStateと速度に対応するUxRestrictionsを判定します。
CarUxRestrictionManagerServiceで車両情報(速度)とDrivingStateを監視し、登録されたCarUxRestrictionsChangeListenerのonUxRestrictionsChangedを呼び出しています。
利用側では、運転状態と UX 制限の利用にあるとおり、CarUxRestrictionManager.OnUxRestrictionsChangedListener
を実装してregisterListener
することで、現在のCarUxRestrictionsを受け取って制限に応じた処理を行うことができます。
@Nullable private CarUxRestrictionsManager mCarUxRestrictionsManager;
private CarUxRestrictions mCurrentUxRestrictions;
/* Implement the onUxRestrictionsChangedListener interface */
private CarUxRestrictionsManager.OnUxRestrictionsChangedListener mUxrChangeListener =
new CarUxRestrictionsManager.OnUxRestrictionsChangedListener()
{
@Override
public void onUxRestrictionsChanged(CarUxRestrictions carUxRestrictions) {
mCurrentUxRestrictions = carUxRestrictions;
/* Handle the new restrictions */
handleUxRestrictionsChanged(carUxRestrictions);
}
};
本記事ではcar_ux_restrictions_map.xml
でのUxRestrictionsの定義から、それがアプリでのonUxRestrictionsChanged
呼び出しまでつながってくる流れをかいつまんで確認しました。
AAOSやAAOS向けのアプリ開発では、一般のAndroidアプリ開発とは異なる車両特有の考慮が必要です。
車両の状態に応じてUIを適切に制限することで、安全性を確保しながらもユーザーに価値を提供するアプリを開発することができます。
これは自動車メーカーならではの知識と技術が活かせる領域であり、車載ソフトウェアの開発の醍醐味と言えます。
※この記事は、本田技研工業のデジタルサービス ソフトウェア内製化チームによる寄稿です。
他の記事はこちらからご覧いただけます。
Views: 0