Merge "Add ReadViewCameraViewController/Mediator."
This commit is contained in:
@@ -23,6 +23,8 @@
|
||||
<uses-permission android:name="android.car.permission.CAR_POWER" />
|
||||
<!-- This permission is required to get the trusted device list of a user. -->
|
||||
<uses-permission android:name="android.car.permission.CAR_ENROLL_TRUST"/>
|
||||
<!-- This permission is required to monitor gear state. -->
|
||||
<uses-permission android:name="android.car.permission.CAR_POWERTRAIN" />
|
||||
<!-- This permission is required to get bluetooth broadcast. -->
|
||||
<uses-permission android:name="android.permission.BLUETOOTH" />
|
||||
<!-- These permissions are required to implement icons based on role holders. -->
|
||||
|
||||
31
packages/CarSystemUI/res/layout/rear_view_camera.xml
Normal file
31
packages/CarSystemUI/res/layout/rear_view_camera.xml
Normal file
@@ -0,0 +1,31 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
~ Copyright (C) 2020 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.
|
||||
-->
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/rear_view_camera_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@android:color/transparent"
|
||||
android:orientation="vertical">
|
||||
<Button
|
||||
android:id="@+id/close_button"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@color/rear_view_camera_button_background"
|
||||
android:text="@string/rear_view_camera_close_button_text"
|
||||
android:textAppearance="?android:attr/textAppearanceLarge"/>
|
||||
</LinearLayout>
|
||||
@@ -42,4 +42,10 @@
|
||||
android:layout_height="match_parent"
|
||||
android:layout="@layout/car_user_switching_dialog"/>
|
||||
|
||||
</FrameLayout>
|
||||
<!-- Should be at bottom to get the highest Z-order. -->
|
||||
<ViewStub android:id="@+id/rear_view_camera_stub"
|
||||
android:layout_width="@dimen/rear_view_camera_width"
|
||||
android:layout_height="@dimen/rear_view_camera_height"
|
||||
android:layout_gravity="center"
|
||||
android:layout="@layout/rear_view_camera"/>
|
||||
</FrameLayout>
|
||||
|
||||
@@ -66,4 +66,6 @@
|
||||
|
||||
<color name="car_user_switching_dialog_background_color">@android:color/black</color>
|
||||
<color name="car_user_switching_dialog_loading_text_color">@*android:color/car_body1</color>
|
||||
|
||||
<color name="rear_view_camera_button_background">@*android:color/car_card_dark</color>
|
||||
</resources>
|
||||
|
||||
@@ -108,6 +108,7 @@
|
||||
<item>com.android.systemui.car.keyguard.CarKeyguardViewMediator</item>
|
||||
<item>com.android.systemui.car.userswitcher.FullscreenUserSwitcherViewMediator</item>
|
||||
<item>com.android.systemui.car.userswitcher.UserSwitchTransitionViewMediator</item>
|
||||
<item>com.android.systemui.car.rvc.RearViewCameraViewMediator</item>
|
||||
</string-array>
|
||||
|
||||
<!--
|
||||
@@ -150,4 +151,7 @@
|
||||
|
||||
<!-- How many milliseconds to wait before force hiding the UserSwitchTransitionView -->
|
||||
<integer name="config_userSwitchTransitionViewShownTimeoutMs" translatable="false">5000</integer>
|
||||
|
||||
<!-- The Activity name for the Rear View Camera, if empty, the feature will be disabled. -->
|
||||
<string name="config_rearViewCameraActivity" translatable="false"></string>
|
||||
</resources>
|
||||
|
||||
@@ -227,4 +227,8 @@
|
||||
<dimen name="car_fullscreen_user_pod_image_avatar_height">96dp</dimen>
|
||||
<dimen name="car_user_switching_dialog_loading_text_margin_top">@*android:dimen/car_padding_4</dimen>
|
||||
<dimen name="car_user_switching_dialog_loading_text_font_size">@*android:dimen/car_body1_size</dimen>
|
||||
|
||||
<!-- dimensions for rear view camera -->
|
||||
<dimen name="rear_view_camera_width">600dp</dimen>
|
||||
<dimen name="rear_view_camera_height">500dp</dimen>
|
||||
</resources>
|
||||
|
||||
@@ -42,4 +42,6 @@
|
||||
<string name="car_loading_profile">Loading</string>
|
||||
<!-- Message to inform user that the new user profile is loading with additional information on the previous and the next user. [CHAR LIMIT=100] -->
|
||||
<string name="car_loading_profile_developer_message">Loading user (from <xliff:g id="from_user" example="10">%1$d</xliff:g> to <xliff:g id="to_user" example="12">%2$d</xliff:g>)</string>
|
||||
<!-- Text for the close button in Rear View Camera [CHAR LIMIT=30] -->
|
||||
<string name="rear_view_camera_close_button_text">Close</string>
|
||||
</resources>
|
||||
|
||||
@@ -0,0 +1,141 @@
|
||||
/*
|
||||
* Copyright (C) 2020 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.
|
||||
*/
|
||||
|
||||
package com.android.systemui.car.rvc;
|
||||
|
||||
import android.app.ActivityView;
|
||||
import android.app.ActivityView.StateCallback;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Intent;
|
||||
import android.content.res.Resources;
|
||||
import android.util.Slog;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.LinearLayout.LayoutParams;
|
||||
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.systemui.R;
|
||||
import com.android.systemui.car.window.OverlayViewController;
|
||||
import com.android.systemui.car.window.OverlayViewGlobalStateController;
|
||||
import com.android.systemui.dagger.SysUISingleton;
|
||||
import com.android.systemui.dagger.qualifiers.Main;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
/** View controller for the rear view camera. */
|
||||
@SysUISingleton
|
||||
public class RearViewCameraViewController extends OverlayViewController {
|
||||
private static final String TAG = "RearViewCameraView";
|
||||
private static final boolean DBG = false;
|
||||
|
||||
private final ComponentName mRearViewCameraActivity;
|
||||
private ViewGroup mRvcView;
|
||||
private final LayoutParams mRvcViewLayoutParams = new LayoutParams(
|
||||
LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT, /* weight= */ 1.0f);
|
||||
@VisibleForTesting
|
||||
ActivityView mActivityView;
|
||||
@VisibleForTesting
|
||||
final StateCallback mActivityViewCallback = new StateCallback() {
|
||||
@Override
|
||||
public void onActivityViewReady(ActivityView view) {
|
||||
Intent intent = new Intent(Intent.ACTION_MAIN)
|
||||
.setComponent(mRearViewCameraActivity)
|
||||
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||
.addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT)
|
||||
.addFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
|
||||
// TODO(b/170899079): Migrate this to FixedActivityService.
|
||||
view.startActivity(intent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityViewDestroyed(ActivityView view) {}
|
||||
};
|
||||
|
||||
@Inject
|
||||
public RearViewCameraViewController(
|
||||
@Main Resources resources,
|
||||
OverlayViewGlobalStateController overlayViewGlobalStateController) {
|
||||
super(R.id.rear_view_camera_stub, overlayViewGlobalStateController);
|
||||
String rearViewCameraActivityName = resources.getString(
|
||||
R.string.config_rearViewCameraActivity);
|
||||
if (!rearViewCameraActivityName.isEmpty()) {
|
||||
mRearViewCameraActivity = ComponentName.unflattenFromString(rearViewCameraActivityName);
|
||||
if (DBG) Slog.d(TAG, "mRearViewCameraActivity=" + mRearViewCameraActivity);
|
||||
} else {
|
||||
mRearViewCameraActivity = null;
|
||||
Slog.e(TAG, "RearViewCameraViewController is disabled, since no Activity is defined");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onFinishInflate() {
|
||||
mRvcView = (ViewGroup) getLayout().findViewById(R.id.rear_view_camera_container);
|
||||
getLayout().findViewById(R.id.close_button).setOnClickListener(v -> {
|
||||
stop();
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void hideInternal() {
|
||||
super.hideInternal();
|
||||
if (DBG) Slog.d(TAG, "hideInternal: mActivityView=" + mActivityView);
|
||||
if (mActivityView == null) return;
|
||||
mRvcView.removeView(mActivityView);
|
||||
// Release ActivityView since the Activity on ActivityView (with showWhenLocked flag) keeps
|
||||
// running even if ActivityView is hidden.
|
||||
mActivityView.release();
|
||||
mActivityView = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void showInternal() {
|
||||
super.showInternal();
|
||||
if (DBG) Slog.d(TAG, "showInternal: mActivityView=" + mActivityView);
|
||||
if (mActivityView != null) return;
|
||||
mActivityView = new ActivityView(mRvcView.getContext());
|
||||
mActivityView.setCallback(mActivityViewCallback);
|
||||
mActivityView.setLayoutParams(mRvcViewLayoutParams);
|
||||
mRvcView.addView(mActivityView, /* index= */ 0);
|
||||
}
|
||||
|
||||
boolean isShown() {
|
||||
return mActivityView != null;
|
||||
}
|
||||
|
||||
boolean isEnabled() {
|
||||
return mRearViewCameraActivity != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean shouldShowHUN() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean shouldShowWhenOccluded() {
|
||||
// Returns true to show it on top of Keylock.
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean shouldShowNavigationBarInsets() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean shouldShowStatusBarInsets() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,121 @@
|
||||
/*
|
||||
* Copyright (C) 2020 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.
|
||||
*/
|
||||
|
||||
package com.android.systemui.car.rvc;
|
||||
|
||||
import android.car.Car;
|
||||
import android.car.VehicleGear;
|
||||
import android.car.VehiclePropertyIds;
|
||||
import android.car.hardware.CarPropertyValue;
|
||||
import android.car.hardware.property.CarPropertyManager;
|
||||
import android.car.hardware.property.CarPropertyManager.CarPropertyEventCallback;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.os.UserHandle;
|
||||
import android.util.Slog;
|
||||
|
||||
import com.android.systemui.broadcast.BroadcastDispatcher;
|
||||
import com.android.systemui.car.CarServiceProvider;
|
||||
import com.android.systemui.car.window.OverlayViewMediator;
|
||||
import com.android.systemui.dagger.SysUISingleton;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
/**
|
||||
* View mediator for the rear view camera (RVC), which monitors the gear changes and shows
|
||||
* the RVC when the gear position is R and otherwise it hides the RVC.
|
||||
*/
|
||||
@SysUISingleton
|
||||
public class RearViewCameraViewMediator implements OverlayViewMediator {
|
||||
private static final String TAG = "RearViewCameraView";
|
||||
private static final boolean DBG = false;
|
||||
|
||||
private final RearViewCameraViewController mRearViewCameraViewController;
|
||||
private final CarServiceProvider mCarServiceProvider;
|
||||
private final BroadcastDispatcher mBroadcastDispatcher;
|
||||
|
||||
private CarPropertyManager mCarPropertyManager;
|
||||
// TODO(b/170792252): Replace the following with the callback from CarEvsManager if it's ready.
|
||||
private final CarPropertyEventCallback mPropertyEventCallback = new CarPropertyEventCallback() {
|
||||
@Override
|
||||
public void onChangeEvent(CarPropertyValue value) {
|
||||
if (DBG) Slog.d(TAG, "onChangeEvent value=" + value);
|
||||
if (value.getPropertyId() != VehiclePropertyIds.GEAR_SELECTION) {
|
||||
Slog.w(TAG, "Got the event for non-registered property: " + value.getPropertyId());
|
||||
return;
|
||||
}
|
||||
if ((Integer) value.getValue() == VehicleGear.GEAR_REVERSE) {
|
||||
mRearViewCameraViewController.start();
|
||||
} else {
|
||||
mRearViewCameraViewController.stop();
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void onErrorEvent(int propId, int zone) {
|
||||
Slog.e(TAG, "onErrorEvent propId=" + propId + ", zone=" + zone);
|
||||
}
|
||||
};
|
||||
|
||||
private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
if (DBG) Slog.d(TAG, "onReceive: " + intent);
|
||||
if (Intent.ACTION_CLOSE_SYSTEM_DIALOGS.equals(intent.getAction())
|
||||
&& mRearViewCameraViewController.isShown()) {
|
||||
mRearViewCameraViewController.stop();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@Inject
|
||||
public RearViewCameraViewMediator(
|
||||
RearViewCameraViewController rearViewCameraViewController,
|
||||
CarServiceProvider carServiceProvider,
|
||||
BroadcastDispatcher broadcastDispatcher) {
|
||||
if (DBG) Slog.d(TAG, "RearViewCameraViewMediator:init");
|
||||
mRearViewCameraViewController = rearViewCameraViewController;
|
||||
mCarServiceProvider = carServiceProvider;
|
||||
mBroadcastDispatcher = broadcastDispatcher;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerListeners() {
|
||||
if (DBG) Slog.d(TAG, "RearViewCameraViewMediator:registerListeners");
|
||||
if (!mRearViewCameraViewController.isEnabled()) {
|
||||
Slog.i(TAG, "RearViewCameraViewController isn't enabled");
|
||||
return;
|
||||
}
|
||||
|
||||
mCarServiceProvider.addListener(car -> {
|
||||
mCarPropertyManager = (CarPropertyManager) car.getCarManager(Car.PROPERTY_SERVICE);
|
||||
if (mCarPropertyManager == null) {
|
||||
Slog.e(TAG, "Unable to get CarPropertyManager");
|
||||
return;
|
||||
}
|
||||
if (DBG) Slog.d(TAG, "Registering mPropertyEventCallback.");
|
||||
mCarPropertyManager.registerCallback(mPropertyEventCallback,
|
||||
VehiclePropertyIds.GEAR_SELECTION, CarPropertyManager.SENSOR_RATE_UI);
|
||||
});
|
||||
mBroadcastDispatcher.registerReceiver(mBroadcastReceiver,
|
||||
new IntentFilter(Intent.ACTION_CLOSE_SYSTEM_DIALOGS), /* executor= */ null,
|
||||
UserHandle.ALL);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setupOverlayContentViewControllers() {}
|
||||
}
|
||||
@@ -20,6 +20,7 @@ import com.android.systemui.car.keyguard.CarKeyguardViewMediator;
|
||||
import com.android.systemui.car.notification.BottomNotificationPanelViewMediator;
|
||||
import com.android.systemui.car.notification.NotificationPanelViewMediator;
|
||||
import com.android.systemui.car.notification.TopNotificationPanelViewMediator;
|
||||
import com.android.systemui.car.rvc.RearViewCameraViewMediator;
|
||||
import com.android.systemui.car.userswitcher.FullscreenUserSwitcherViewMediator;
|
||||
import com.android.systemui.car.userswitcher.UserSwitchTransitionViewMediator;
|
||||
|
||||
@@ -75,4 +76,11 @@ public abstract class OverlayWindowModule {
|
||||
@ClassKey(UserSwitchTransitionViewMediator.class)
|
||||
public abstract OverlayViewMediator bindUserSwitchTransitionViewMediator(
|
||||
UserSwitchTransitionViewMediator userSwitchTransitionViewMediator);
|
||||
|
||||
/** Injects RearViewCameraViewMediator. */
|
||||
@Binds
|
||||
@IntoMap
|
||||
@ClassKey(RearViewCameraViewMediator.class)
|
||||
public abstract OverlayViewMediator bindRearViewCameraViewMediator(
|
||||
RearViewCameraViewMediator overlayViewsMediator);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,117 @@
|
||||
/*
|
||||
* Copyright (C) 2020 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.
|
||||
*/
|
||||
|
||||
package com.android.systemui.car.rvc;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
import android.app.ActivityView;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Intent;
|
||||
import android.testing.TestableLooper;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import androidx.test.filters.SmallTest;
|
||||
|
||||
import com.android.systemui.R;
|
||||
import com.android.systemui.SysuiTestCase;
|
||||
import com.android.systemui.car.CarSystemUiTest;
|
||||
import com.android.systemui.car.window.OverlayViewGlobalStateController;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.Captor;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
@CarSystemUiTest
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
@TestableLooper.RunWithLooper
|
||||
@SmallTest
|
||||
public class RearViewCameraViewControllerTest extends SysuiTestCase {
|
||||
private static final String TEST_ACTIVITY_NAME = "testPackage/testActivity";
|
||||
private RearViewCameraViewController mRearViewCameraViewController;
|
||||
|
||||
@Mock
|
||||
private OverlayViewGlobalStateController mOverlayViewGlobalStateController;
|
||||
@Mock
|
||||
private ActivityView mMockActivityView;
|
||||
@Captor
|
||||
private ArgumentCaptor<Intent> mIntentCaptor;
|
||||
|
||||
private void setUpRearViewCameraViewController(String testActivityName) {
|
||||
mContext.getOrCreateTestableResources().addOverride(
|
||||
R.string.config_rearViewCameraActivity, testActivityName);
|
||||
mRearViewCameraViewController = new RearViewCameraViewController(
|
||||
mContext.getOrCreateTestableResources().getResources(),
|
||||
mOverlayViewGlobalStateController);
|
||||
mRearViewCameraViewController.inflate((ViewGroup) LayoutInflater.from(mContext).inflate(
|
||||
R.layout.sysui_overlay_window, /* root= */ null));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEmptyResourceDisablesController() {
|
||||
setUpRearViewCameraViewController("");
|
||||
|
||||
assertThat(mRearViewCameraViewController.isEnabled()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNonEmptyResourceEnablesController() {
|
||||
setUpRearViewCameraViewController(TEST_ACTIVITY_NAME);
|
||||
|
||||
assertThat(mRearViewCameraViewController.isEnabled()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testShowInternal() {
|
||||
setUpRearViewCameraViewController(TEST_ACTIVITY_NAME);
|
||||
assertThat(mRearViewCameraViewController.isShown()).isFalse();
|
||||
assertThat(mRearViewCameraViewController.mActivityView).isNull();
|
||||
|
||||
mRearViewCameraViewController.showInternal();
|
||||
|
||||
assertThat(mRearViewCameraViewController.isShown()).isTrue();
|
||||
assertThat(mRearViewCameraViewController.mActivityView).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHideInternal() {
|
||||
setUpRearViewCameraViewController(TEST_ACTIVITY_NAME);
|
||||
assertThat(mRearViewCameraViewController.isShown()).isFalse();
|
||||
mRearViewCameraViewController.showInternal();
|
||||
assertThat(mRearViewCameraViewController.isShown()).isTrue();
|
||||
|
||||
mRearViewCameraViewController.hideInternal();
|
||||
|
||||
assertThat(mRearViewCameraViewController.isShown()).isFalse();
|
||||
assertThat(mRearViewCameraViewController.mActivityView).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOnActivityViewReady_fireIntent() {
|
||||
setUpRearViewCameraViewController(TEST_ACTIVITY_NAME);
|
||||
mRearViewCameraViewController.mActivityViewCallback.onActivityViewReady(mMockActivityView);
|
||||
|
||||
verify(mMockActivityView).startActivity(mIntentCaptor.capture());
|
||||
ComponentName expectedComponent = ComponentName.unflattenFromString(TEST_ACTIVITY_NAME);
|
||||
assertThat(mIntentCaptor.getValue().getComponent()).isEqualTo(expectedComponent);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,169 @@
|
||||
/*
|
||||
* Copyright (C) 2020 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.
|
||||
*/
|
||||
|
||||
package com.android.systemui.car.rvc;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyFloat;
|
||||
import static org.mockito.ArgumentMatchers.anyInt;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.doAnswer;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.car.Car;
|
||||
import android.car.VehicleAreaType;
|
||||
import android.car.VehicleGear;
|
||||
import android.car.VehiclePropertyIds;
|
||||
import android.car.hardware.CarPropertyValue;
|
||||
import android.car.hardware.property.CarPropertyManager;
|
||||
import android.car.hardware.property.CarPropertyManager.CarPropertyEventCallback;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.testing.TestableLooper;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.test.filters.SmallTest;
|
||||
|
||||
import com.android.systemui.SysuiTestCase;
|
||||
import com.android.systemui.broadcast.BroadcastDispatcher;
|
||||
import com.android.systemui.car.CarServiceProvider;
|
||||
import com.android.systemui.car.CarServiceProvider.CarServiceOnConnectedListener;
|
||||
import com.android.systemui.car.CarSystemUiTest;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.Captor;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
@CarSystemUiTest
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
@TestableLooper.RunWithLooper
|
||||
@SmallTest
|
||||
public class RearViewCameraViewMediatorTest extends SysuiTestCase {
|
||||
private static final String TAG = RearViewCameraViewMediatorTest.class.getSimpleName();
|
||||
|
||||
private RearViewCameraViewMediator mRearViewCameraViewMediator;
|
||||
|
||||
@Mock
|
||||
private CarServiceProvider mCarServiceProvider;
|
||||
@Mock
|
||||
private Car mCar;
|
||||
@Mock
|
||||
private CarPropertyManager mCarPropertyManager;
|
||||
@Captor
|
||||
private ArgumentCaptor<CarPropertyEventCallback> mCarPropertyEventCallbackCaptor;
|
||||
|
||||
@Mock
|
||||
private BroadcastDispatcher mBroadcastDispatcher;
|
||||
@Captor
|
||||
private ArgumentCaptor<BroadcastReceiver> mBroadcastReceiverCaptor;
|
||||
@Captor
|
||||
private ArgumentCaptor<IntentFilter> mIntentFilterCaptor;
|
||||
|
||||
@Mock
|
||||
private RearViewCameraViewController mRearViewCameraViewController;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
mRearViewCameraViewMediator = new RearViewCameraViewMediator(
|
||||
mRearViewCameraViewController, mCarServiceProvider, mBroadcastDispatcher);
|
||||
}
|
||||
|
||||
public void setUpListener() {
|
||||
doAnswer(invocation -> {
|
||||
CarServiceOnConnectedListener listener = invocation.getArgument(0);
|
||||
listener.onConnected(mCar);
|
||||
return null;
|
||||
}).when(mCarServiceProvider).addListener(any(CarServiceOnConnectedListener.class));
|
||||
when(mCar.getCarManager(Car.PROPERTY_SERVICE)).thenReturn(mCarPropertyManager);
|
||||
when(mRearViewCameraViewController.isEnabled()).thenReturn(true);
|
||||
|
||||
mRearViewCameraViewMediator.registerListeners();
|
||||
|
||||
verify(mCarPropertyManager).registerCallback(mCarPropertyEventCallbackCaptor.capture(),
|
||||
eq(VehiclePropertyIds.GEAR_SELECTION), anyFloat());
|
||||
verify(mBroadcastDispatcher).registerReceiver(mBroadcastReceiverCaptor.capture(),
|
||||
mIntentFilterCaptor.capture(), any(), any());
|
||||
assertThat(mIntentFilterCaptor.getValue().getAction(0)).isEqualTo(
|
||||
Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDoesnNotRegisterListenersWhenRearViewCameraViewControllerIsDisabled() {
|
||||
when(mRearViewCameraViewController.isEnabled()).thenReturn(false);
|
||||
|
||||
mRearViewCameraViewMediator.registerListeners();
|
||||
|
||||
verify(mCarPropertyManager, never()).registerCallback(any(), anyInt(), anyFloat());
|
||||
verify(mBroadcastDispatcher, never()).registerReceiver(any(), any(), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGearReverseStartsRearViewCamera() {
|
||||
setUpListener();
|
||||
|
||||
CarPropertyValue<Integer> gearReverse = new CarPropertyValue(
|
||||
VehiclePropertyIds.GEAR_SELECTION, VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL,
|
||||
VehicleGear.GEAR_REVERSE);
|
||||
mCarPropertyEventCallbackCaptor.getValue().onChangeEvent(gearReverse);
|
||||
|
||||
verify(mRearViewCameraViewController, times(1)).start();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGearNonReverseStopsRearViewCamera() {
|
||||
setUpListener();
|
||||
|
||||
int[] nonReverseVehicleGears = new int[]{
|
||||
VehicleGear.GEAR_NEUTRAL, VehicleGear.GEAR_PARK, VehicleGear.GEAR_DRIVE,
|
||||
VehicleGear.GEAR_FIRST
|
||||
};
|
||||
for (int i = 0; i < nonReverseVehicleGears.length; ++i) {
|
||||
Log.i(TAG, "testGearNonReverseStopsRearViewCamera: gear=" + nonReverseVehicleGears[i]);
|
||||
CarPropertyValue<Integer> propertyGear = new CarPropertyValue(
|
||||
VehiclePropertyIds.GEAR_SELECTION, VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL,
|
||||
nonReverseVehicleGears[i]);
|
||||
mCarPropertyEventCallbackCaptor.getValue().onChangeEvent(propertyGear);
|
||||
|
||||
verify(mRearViewCameraViewController, times(i + 1)).stop();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBroadcastIntentStopsRearViewCamera() {
|
||||
setUpListener();
|
||||
when(mRearViewCameraViewController.isShown()).thenReturn(true);
|
||||
|
||||
Intent randomIntent = new Intent(Intent.ACTION_MAIN);
|
||||
mBroadcastReceiverCaptor.getValue().onReceive(mContext, randomIntent);
|
||||
|
||||
verify(mRearViewCameraViewController, never()).stop();
|
||||
|
||||
Intent actionCloseSystemDialogs = new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
|
||||
mBroadcastReceiverCaptor.getValue().onReceive(mContext, actionCloseSystemDialogs);
|
||||
|
||||
verify(mRearViewCameraViewController, times(1)).stop();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user