[Reland] GD: Don't always auto select a camera
Original CL was reverted because of a failing test that was not caught by the CQ (since ash_unittests were removed from CQ, see b/333572800). This CL relands the CL with a fix. In Game-Dashboard-initiated sessions, we auto-select the first available camera (if none is currently selected). However, we should stop doing that once a user makes an explicit camera selection. All subsequent sessions should just continue using the system-wide most recent camera selection. Bug: b/324964571 Test: Manually, unit tests. Change-Id: I632288b157b1964704060971e7700bc2062230fa Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5464172 Reviewed-by: Prameet Shah <phshah@chromium.org> Commit-Queue: Ahmed Fakhry <afakhry@chromium.org> Cr-Original-Commit-Position: refs/heads/main@{#1289353} Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5463216 Cr-Commit-Position: refs/heads/main@{#1289727}
This commit is contained in:

committed by
Chromium LUCI CQ

parent
dbcfaa312b
commit
08d35b5993
@ -9,6 +9,7 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "ash/capture_mode/base_capture_mode_session.h"
|
#include "ash/capture_mode/base_capture_mode_session.h"
|
||||||
|
#include "ash/capture_mode/capture_mode_camera_controller.h"
|
||||||
#include "ash/capture_mode/capture_mode_constants.h"
|
#include "ash/capture_mode/capture_mode_constants.h"
|
||||||
#include "ash/capture_mode/capture_mode_controller.h"
|
#include "ash/capture_mode/capture_mode_controller.h"
|
||||||
#include "ash/capture_mode/capture_mode_metrics.h"
|
#include "ash/capture_mode/capture_mode_metrics.h"
|
||||||
@ -230,7 +231,11 @@ class GameDashboardBehavior : public CaptureModeBehavior,
|
|||||||
bool ShouldDemoToolsSettingsBeIncluded() const override { return false; }
|
bool ShouldDemoToolsSettingsBeIncluded() const override { return false; }
|
||||||
bool ShouldGifBeSupported() const override { return false; }
|
bool ShouldGifBeSupported() const override { return false; }
|
||||||
bool ShouldShowUserNudge() const override { return false; }
|
bool ShouldShowUserNudge() const override { return false; }
|
||||||
bool ShouldAutoSelectFirstCamera() const override { return true; }
|
bool ShouldAutoSelectFirstCamera() const override {
|
||||||
|
return !CaptureModeController::Get()
|
||||||
|
->camera_controller()
|
||||||
|
->did_user_ever_change_camera();
|
||||||
|
}
|
||||||
|
|
||||||
std::unique_ptr<CaptureModeBarView> CreateCaptureModeBarView() override {
|
std::unique_ptr<CaptureModeBarView> CreateCaptureModeBarView() override {
|
||||||
return std::make_unique<GameCaptureBarView>();
|
return std::make_unique<GameCaptureBarView>();
|
||||||
|
@ -455,7 +455,8 @@ std::string CaptureModeCameraController::GetDisplayNameOfSelectedCamera()
|
|||||||
return std::string();
|
return std::string();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CaptureModeCameraController::SetSelectedCamera(CameraId camera_id) {
|
void CaptureModeCameraController::SetSelectedCamera(CameraId camera_id,
|
||||||
|
bool by_user) {
|
||||||
// When cameras are disabled by policy, we don't allow any camera selection.
|
// When cameras are disabled by policy, we don't allow any camera selection.
|
||||||
if (IsCameraDisabledByPolicy()) {
|
if (IsCameraDisabledByPolicy()) {
|
||||||
LOG(WARNING) << "Camera is disabled by policy. Selecting camera: "
|
LOG(WARNING) << "Camera is disabled by policy. Selecting camera: "
|
||||||
@ -466,6 +467,13 @@ void CaptureModeCameraController::SetSelectedCamera(CameraId camera_id) {
|
|||||||
if (selected_camera_ == camera_id)
|
if (selected_camera_ == camera_id)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
did_user_ever_change_camera_ |= by_user;
|
||||||
|
|
||||||
|
// If camera auto-selection is on, and a camera change happened (either by
|
||||||
|
// user or due to disconnection), calling `MaybeRevertAutoCameraSelection()`
|
||||||
|
// should be a no-op, and the camera should not be restored to off.
|
||||||
|
did_make_camera_auto_selection_ = false;
|
||||||
|
|
||||||
selected_camera_ = std::move(camera_id);
|
selected_camera_ = std::move(camera_id);
|
||||||
camera_reconnect_timer_.Stop();
|
camera_reconnect_timer_.Stop();
|
||||||
|
|
||||||
|
@ -163,6 +163,9 @@ class ASH_EXPORT CaptureModeCameraController
|
|||||||
bool is_camera_preview_collapsed() const {
|
bool is_camera_preview_collapsed() const {
|
||||||
return is_camera_preview_collapsed_;
|
return is_camera_preview_collapsed_;
|
||||||
}
|
}
|
||||||
|
bool did_user_ever_change_camera() const {
|
||||||
|
return did_user_ever_change_camera_;
|
||||||
|
}
|
||||||
|
|
||||||
void AddObserver(Observer* observer);
|
void AddObserver(Observer* observer);
|
||||||
void RemoveObserver(Observer* observer);
|
void RemoveObserver(Observer* observer);
|
||||||
@ -185,8 +188,9 @@ class ASH_EXPORT CaptureModeCameraController
|
|||||||
|
|
||||||
// Sets the currently selected camera to the whose ID is the given
|
// Sets the currently selected camera to the whose ID is the given
|
||||||
// `camera_id`. If `camera_id` is invalid (see CameraId::is_valid()), this
|
// `camera_id`. If `camera_id` is invalid (see CameraId::is_valid()), this
|
||||||
// clears the selected camera.
|
// clears the selected camera. `by_user` is true if the selection was made
|
||||||
void SetSelectedCamera(CameraId camera_id);
|
// explicitly by the user, false otherwise.
|
||||||
|
void SetSelectedCamera(CameraId camera_id, bool by_user = false);
|
||||||
|
|
||||||
// Sets `should_show_preview_` to the given `value`, and refreshes the state
|
// Sets `should_show_preview_` to the given `value`, and refreshes the state
|
||||||
// of the camera preview.
|
// of the camera preview.
|
||||||
@ -426,6 +430,10 @@ class ASH_EXPORT CaptureModeCameraController
|
|||||||
// selection.
|
// selection.
|
||||||
bool did_make_camera_auto_selection_ = false;
|
bool did_make_camera_auto_selection_ = false;
|
||||||
|
|
||||||
|
// True if the user ever made an explicit camera selection (i.e. from the
|
||||||
|
// capture mode settings menu).
|
||||||
|
bool did_user_ever_change_camera_ = false;
|
||||||
|
|
||||||
base::WeakPtrFactory<CaptureModeCameraController> weak_ptr_factory_{this};
|
base::WeakPtrFactory<CaptureModeCameraController> weak_ptr_factory_{this};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -702,6 +702,11 @@ TEST_F(GameDashboardCaptureModeTest, GameCaptureModeRecordInstantlyTest) {
|
|||||||
? AudioRecordingMode::kSystemAndMicrophone
|
? AudioRecordingMode::kSystemAndMicrophone
|
||||||
: AudioRecordingMode::kMicrophone);
|
: AudioRecordingMode::kMicrophone);
|
||||||
|
|
||||||
|
auto* camera_controller = controller->camera_controller();
|
||||||
|
ASSERT_TRUE(camera_controller->camera_preview_widget());
|
||||||
|
const CameraId camera_id(kDefaultCameraModelId, 1);
|
||||||
|
EXPECT_EQ(camera_id, camera_controller->selected_camera());
|
||||||
|
|
||||||
// Update the audio recording mode and demo tools configs for the
|
// Update the audio recording mode and demo tools configs for the
|
||||||
// game-dashboard initiated capture mode.
|
// game-dashboard initiated capture mode.
|
||||||
controller->SetAudioRecordingMode(AudioRecordingMode::kOff);
|
controller->SetAudioRecordingMode(AudioRecordingMode::kOff);
|
||||||
@ -728,13 +733,110 @@ TEST_F(GameDashboardCaptureModeTest, GameCaptureModeRecordInstantlyTest) {
|
|||||||
|
|
||||||
// Verify that selfie camera is visible and is parented correctly to the game
|
// Verify that selfie camera is visible and is parented correctly to the game
|
||||||
// window.
|
// window.
|
||||||
const auto* camera_controller = controller->camera_controller();
|
|
||||||
const auto* camera_preview_widget =
|
const auto* camera_preview_widget =
|
||||||
camera_controller->camera_preview_widget();
|
camera_controller->camera_preview_widget();
|
||||||
ASSERT_TRUE(camera_preview_widget);
|
ASSERT_TRUE(camera_preview_widget);
|
||||||
EXPECT_EQ(camera_preview_widget->GetNativeWindow()->parent(), game_window());
|
EXPECT_EQ(camera_preview_widget->GetNativeWindow()->parent(), game_window());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(GameDashboardCaptureModeTest, UserTurnsOffCamera) {
|
||||||
|
AddDefaultCamera();
|
||||||
|
|
||||||
|
// By default, the first available camera should be auto selected.
|
||||||
|
auto* controller = StartGameCaptureModeSession();
|
||||||
|
auto* camera_controller = controller->camera_controller();
|
||||||
|
ASSERT_TRUE(camera_controller->camera_preview_widget());
|
||||||
|
const CameraId camera_id(kDefaultCameraModelId, 1);
|
||||||
|
EXPECT_EQ(camera_id, camera_controller->selected_camera());
|
||||||
|
|
||||||
|
// Now, open the settings menu, and select the "camera off" option.
|
||||||
|
LeftClickOn(GetSettingsButton());
|
||||||
|
CaptureModeSettingsTestApi test_api;
|
||||||
|
CaptureModeMenuGroup* camera_menu_group = test_api.GetCameraMenuGroup();
|
||||||
|
ASSERT_TRUE(camera_menu_group);
|
||||||
|
EXPECT_TRUE(camera_menu_group->GetVisible());
|
||||||
|
auto* off_option = test_api.GetCameraOption(kCameraOff);
|
||||||
|
EXPECT_TRUE(off_option);
|
||||||
|
LeftClickOn(off_option);
|
||||||
|
|
||||||
|
// No camera should be selected, and the preview widget should be closed.
|
||||||
|
EXPECT_FALSE(camera_controller->selected_camera().is_valid());
|
||||||
|
EXPECT_FALSE(camera_controller->camera_preview_widget());
|
||||||
|
|
||||||
|
// Close the session and start a new one. No camera should be auto selected.
|
||||||
|
controller->Stop();
|
||||||
|
StartGameCaptureModeSession();
|
||||||
|
EXPECT_FALSE(camera_controller->selected_camera().is_valid());
|
||||||
|
EXPECT_FALSE(camera_controller->camera_preview_widget());
|
||||||
|
controller->Stop();
|
||||||
|
|
||||||
|
// Start a new default session and select a camera, then end the session.
|
||||||
|
StartCaptureSession(CaptureModeSource::kFullscreen, CaptureModeType::kVideo);
|
||||||
|
camera_controller->SetSelectedCamera(camera_id);
|
||||||
|
EXPECT_TRUE(camera_controller->camera_preview_widget());
|
||||||
|
controller->Stop();
|
||||||
|
|
||||||
|
// When we start a new Game Dashboard session next, the camera selected from
|
||||||
|
// the previous default session will remain selected.
|
||||||
|
StartGameCaptureModeSession();
|
||||||
|
EXPECT_EQ(camera_id, camera_controller->selected_camera());
|
||||||
|
EXPECT_TRUE(camera_controller->camera_preview_widget());
|
||||||
|
controller->Stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(GameDashboardCaptureModeTest, StartWithNoCamera) {
|
||||||
|
// Initially there's no camera connected, so the Game Dashboard auto camera
|
||||||
|
// selection won't work.
|
||||||
|
auto* controller = StartGameCaptureModeSession();
|
||||||
|
auto* camera_controller = controller->camera_controller();
|
||||||
|
EXPECT_FALSE(camera_controller->selected_camera().is_valid());
|
||||||
|
EXPECT_FALSE(camera_controller->camera_preview_widget());
|
||||||
|
|
||||||
|
// Now stop the current session, connect a camera, and start a new Game
|
||||||
|
// Dashboard session. This new session should be able to auto-select the
|
||||||
|
// camera.
|
||||||
|
controller->Stop();
|
||||||
|
AddDefaultCamera();
|
||||||
|
StartGameCaptureModeSession();
|
||||||
|
EXPECT_TRUE(camera_controller->camera_preview_widget());
|
||||||
|
const CameraId camera_id(kDefaultCameraModelId, 1);
|
||||||
|
EXPECT_EQ(camera_id, camera_controller->selected_camera());
|
||||||
|
controller->Stop();
|
||||||
|
|
||||||
|
// The next Game Dashboard session should still launch with a camera.
|
||||||
|
StartGameCaptureModeSession();
|
||||||
|
EXPECT_TRUE(camera_controller->camera_preview_widget());
|
||||||
|
EXPECT_EQ(camera_id, camera_controller->selected_camera());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(GameDashboardCaptureModeTest, CameraAutoSelectionDisabledOnChange) {
|
||||||
|
const std::string device_id_1 = "/dev/video0";
|
||||||
|
const std::string display_name_1 = "Integrated Webcam";
|
||||||
|
|
||||||
|
const std::string device_id_2 = "/dev/video1";
|
||||||
|
const std::string display_name_2 = "Integrated Webcam 1";
|
||||||
|
|
||||||
|
AddFakeCamera(device_id_1, display_name_1, display_name_1);
|
||||||
|
AddFakeCamera(device_id_2, display_name_2, display_name_2);
|
||||||
|
|
||||||
|
// The first Game Dashboard session, the first camera will be auto selected.
|
||||||
|
auto* controller = StartGameCaptureModeSession();
|
||||||
|
auto* camera_controller = controller->camera_controller();
|
||||||
|
EXPECT_TRUE(camera_controller->camera_preview_widget());
|
||||||
|
const CameraId camera_id1(display_name_1, 1);
|
||||||
|
EXPECT_EQ(camera_id1, camera_controller->selected_camera());
|
||||||
|
|
||||||
|
// Now, simulate a change by the user to select a different camera while the
|
||||||
|
// session is still running.
|
||||||
|
const CameraId camera_id2(display_name_2, 1);
|
||||||
|
camera_controller->SetSelectedCamera(camera_id2);
|
||||||
|
EXPECT_EQ(camera_id2, camera_controller->selected_camera());
|
||||||
|
|
||||||
|
// Stop the session and expect that the camera remains selected.
|
||||||
|
controller->Stop();
|
||||||
|
EXPECT_EQ(camera_id2, camera_controller->selected_camera());
|
||||||
|
}
|
||||||
|
|
||||||
TEST_F(GameDashboardCaptureModeTest, NoDimmingOfGameDashboardWidgets) {
|
TEST_F(GameDashboardCaptureModeTest, NoDimmingOfGameDashboardWidgets) {
|
||||||
auto* controller = CaptureModeController::Get();
|
auto* controller = CaptureModeController::Get();
|
||||||
controller->StartRecordingInstantlyForGameDashboard(game_window());
|
controller->StartRecordingInstantlyForGameDashboard(game_window());
|
||||||
|
@ -363,14 +363,14 @@ void CaptureModeSettingsView::OnOptionSelected(int option_id) const {
|
|||||||
controller->SetUsesDefaultCaptureFolder(false);
|
controller->SetUsesDefaultCaptureFolder(false);
|
||||||
break;
|
break;
|
||||||
case kCameraOff:
|
case kCameraOff:
|
||||||
camera_controller->SetSelectedCamera(CameraId());
|
camera_controller->SetSelectedCamera(CameraId(), /*by_user=*/true);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
DCHECK(!camera_controller->IsCameraDisabledByPolicy());
|
DCHECK(!camera_controller->IsCameraDisabledByPolicy());
|
||||||
DCHECK_GE(option_id, kCameraDevicesBegin);
|
DCHECK_GE(option_id, kCameraDevicesBegin);
|
||||||
const CameraId* camera_id = FindCameraIdByOptionId(option_id);
|
const CameraId* camera_id = FindCameraIdByOptionId(option_id);
|
||||||
DCHECK(camera_id);
|
DCHECK(camera_id);
|
||||||
camera_controller->SetSelectedCamera(*camera_id);
|
camera_controller->SetSelectedCamera(*camera_id, /*by_user=*/true);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user