Commit ed72cf43 authored by Kuo Jen Wei's avatar Kuo Jen Wei Committed by Commit Bot

[CCA] Press volume button to start shutter.

Set CCA window can consume volume button. Add new mojo API monitoring tablet
mode state. Trigger camera shutter when CCA window receive volume button event
in tablet mode.

Design doc: go/cros-camera:dd:cca-volume-button-shutter

Bug: 1024118
Test: Manually test shutter triggered after clicking volume button in
tablet/non-tablet mode

Change-Id: I8b6730773abae7741e90e676abc1a196f6289668
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2089111Reviewed-by: default avatarScott Violet <sky@chromium.org>
Reviewed-by: default avatarWei Lee <wtlee@chromium.org>
Reviewed-by: default avatarMitsuru Oshima <oshima@chromium.org>
Reviewed-by: default avatarDominick Ng <dominickn@chromium.org>
Commit-Queue: Kuo Jen Wei <inker@chromium.org>
Cr-Commit-Position: refs/heads/master@{#760369}
parent 1e7636e6
...@@ -30,6 +30,7 @@ ...@@ -30,6 +30,7 @@
#include "media/capture/video/chromeos/mojom/camera_app.mojom.h" #include "media/capture/video/chromeos/mojom/camera_app.mojom.h"
#include "mojo/public/cpp/bindings/pending_receiver.h" #include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/self_owned_receiver.h" #include "mojo/public/cpp/bindings/self_owned_receiver.h"
#include "ui/aura/window.h"
#if BUILDFLAG(GOOGLE_CHROME_BRANDING) #if BUILDFLAG(GOOGLE_CHROME_BRANDING)
#include "chromeos/services/ime/public/mojom/input_engine.mojom.h" #include "chromeos/services/ime/public/mojom/input_engine.mojom.h"
...@@ -119,9 +120,10 @@ void ConnectToCameraAppHelper( ...@@ -119,9 +120,10 @@ void ConnectToCameraAppHelper(
mojo::PendingReceiver<chromeos_camera::mojom::CameraAppHelper> receiver) { mojo::PendingReceiver<chromeos_camera::mojom::CameraAppHelper> receiver) {
auto handle_result_callback = base::BindRepeating( auto handle_result_callback = base::BindRepeating(
&HandleCameraResult, source->GetProcess()->GetBrowserContext()); &HandleCameraResult, source->GetProcess()->GetBrowserContext());
auto* window = source->GetNativeView()->GetToplevelWindow();
auto camera_app_helper = auto camera_app_helper =
std::make_unique<chromeos_camera::CameraAppHelperImpl>( std::make_unique<chromeos_camera::CameraAppHelperImpl>(
std::move(handle_result_callback)); std::move(handle_result_callback), window);
mojo::MakeSelfOwnedReceiver(std::move(camera_app_helper), mojo::MakeSelfOwnedReceiver(std::move(camera_app_helper),
std::move(receiver)); std::move(receiver));
} }
......
...@@ -174,6 +174,7 @@ export class App { ...@@ -174,6 +174,7 @@ export class App {
* @return {!Promise} * @return {!Promise}
*/ */
async start() { async start() {
await this.cameraView_.initialize();
let ackMigrate = false; let ackMigrate = false;
filesystem filesystem
.initialize(() => { .initialize(() => {
......
...@@ -2,6 +2,8 @@ ...@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
import {assertBoolean} from '../chrome_util.js';
/** /**
* The singleton instance of ChromeHelper. Initialized by the first * The singleton instance of ChromeHelper. Initialized by the first
* invocation of getInstance(). * invocation of getInstance().
...@@ -22,16 +24,37 @@ export class ChromeHelper { ...@@ -22,16 +24,37 @@ export class ChromeHelper {
* @type {!chromeosCamera.mojom.CameraAppHelperRemote} * @type {!chromeosCamera.mojom.CameraAppHelperRemote}
*/ */
this.remote_ = chromeosCamera.mojom.CameraAppHelper.getRemote(); this.remote_ = chromeosCamera.mojom.CameraAppHelper.getRemote();
/**
* Whether device is in tablet mode.
* @type {?boolean}
*/
this.isTabletMode_ = null;
} }
/** /**
* Checks if the device is under tablet mode currently. * Starts tablet mode monitor monitoring tablet mode state of device.
* @return {!Promise<boolean>} * @return {!Promise}
*/ */
async isTabletMode() { async initTabletModeMonitor() {
return await this.remote_.isTabletMode().then(({isTabletMode}) => { const monitorCallbackRouter =
return isTabletMode; new chromeosCamera.mojom.TabletModeMonitorCallbackRouter();
monitorCallbackRouter.update.addListener((tableMode) => {
this.isTabletMode_ = tableMode;
}); });
this.isTabletMode_ =
(await this.remote_.setTabletMonitor(
monitorCallbackRouter.$.bindNewPipeAndPassRemote()))
.isTabletMode;
}
/**
* Checks if the device is under tablet mode currently.
* @return {boolean}
*/
isTabletMode() {
return assertBoolean(this.isTabletMode_);
} }
/** /**
......
...@@ -210,10 +210,9 @@ export class Camera extends View { ...@@ -210,10 +210,9 @@ export class Camera extends View {
}); });
chrome.app.window.current().onMinimized.addListener(() => this.start()); chrome.app.window.current().onMinimized.addListener(() => this.start());
document.addEventListener('visibilitychange', async () => { document.addEventListener('visibilitychange', () => {
const isTabletBackground = await this.isTabletBackground_();
const recording = state.get(state.State.TAKING) && state.get(Mode.VIDEO); const recording = state.get(state.State.TAKING) && state.get(Mode.VIDEO);
if (isTabletBackground && !recording) { if (this.isTabletBackground_() && !recording) {
this.start(); this.start();
} }
}); });
...@@ -221,6 +220,14 @@ export class Camera extends View { ...@@ -221,6 +220,14 @@ export class Camera extends View {
this.configuring_ = null; this.configuring_ = null;
} }
/**
* Initializes camera view.
* @return {!Promise}
*/
async initialize() {
await ChromeHelper.getInstance().initTabletModeMonitor();
}
/** /**
* @return {boolean} Returns if window is fully overlapped by other window in * @return {boolean} Returns if window is fully overlapped by other window in
* both window mode or tablet mode. * both window mode or tablet mode.
...@@ -231,22 +238,20 @@ export class Camera extends View { ...@@ -231,22 +238,20 @@ export class Camera extends View {
} }
/** /**
* @return {!Promise<boolean>} Resolved to boolean value indicating whether * @return {boolean} Whether window is put to background in tablet mode.
* window is put to background in tablet mode.
* @private * @private
*/ */
async isTabletBackground_() { isTabletBackground_() {
const isTabletMode = await ChromeHelper.getInstance().isTabletMode(); return ChromeHelper.getInstance().isTabletMode() && !this.isVisible_;
return isTabletMode && !this.isVisible_;
} }
/** /**
* Whether app window is suspended. * Whether app window is suspended.
* @return {!Promise<boolean>} * @return {boolean}
*/ */
async isSuspended() { isSuspended() {
return this.locked_ || chrome.app.window.current().isMinimized() || return this.locked_ || chrome.app.window.current().isMinimized() ||
state.get(state.State.SUSPEND) || await this.isTabletBackground_(); state.get(state.State.SUSPEND) || this.isTabletBackground_();
} }
/** /**
...@@ -356,6 +361,16 @@ export class Camera extends View { ...@@ -356,6 +361,16 @@ export class Camera extends View {
toast.show(this.preview_.toString()); toast.show(this.preview_.toString());
return true; return true;
} }
if ((key === 'AudioVolumeUp' || key === 'AudioVolumeDown') &&
ChromeHelper.getInstance().isTabletMode() &&
state.get(state.State.STREAMING)) {
if (state.get(state.State.TAKING)) {
this.endTake_();
} else {
this.beginTake_();
}
return true;
}
return false; return false;
} }
...@@ -414,7 +429,7 @@ export class Camera extends View { ...@@ -414,7 +429,7 @@ export class Camera extends View {
} }
for (const {resolution: captureR, previewCandidates} of resolCandidates) { for (const {resolution: captureR, previewCandidates} of resolCandidates) {
for (const constraints of previewCandidates) { for (const constraints of previewCandidates) {
if (await this.isSuspended()) { if (this.isSuspended()) {
throw new CameraSuspendedError(); throw new CameraSuspendedError();
} }
try { try {
...@@ -469,7 +484,7 @@ export class Camera extends View { ...@@ -469,7 +484,7 @@ export class Camera extends View {
async start_() { async start_() {
try { try {
await this.infoUpdater_.lockDeviceInfo(async () => { await this.infoUpdater_.lockDeviceInfo(async () => {
if (!await this.isSuspended()) { if (!this.isSuspended()) {
for (const id of await this.options_.videoDeviceIds()) { for (const id of await this.options_.videoDeviceIds()) {
if (await this.startWithDevice_(id)) { if (await this.startWithDevice_(id)) {
// Make the different active camera announced by screen reader. // Make the different active camera announced by screen reader.
......
...@@ -198,6 +198,7 @@ source_set("camera_app_helper") { ...@@ -198,6 +198,7 @@ source_set("camera_app_helper") {
deps = [ deps = [
"common:camera_app_helper", "common:camera_app_helper",
"//ash/public/cpp", "//ash/public/cpp",
"//ui/aura",
] ]
} }
......
...@@ -3,5 +3,6 @@ include_rules = [ ...@@ -3,5 +3,6 @@ include_rules = [
"+media", "+media",
"+mojo", "+mojo",
"+third_party/libyuv", "+third_party/libyuv",
"+ui/aura",
"+ui/gfx", "+ui/gfx",
] ]
\ No newline at end of file
...@@ -4,16 +4,27 @@ ...@@ -4,16 +4,27 @@
#include "components/chromeos_camera/camera_app_helper_impl.h" #include "components/chromeos_camera/camera_app_helper_impl.h"
#include <utility>
#include "ash/public/cpp/tablet_mode.h" #include "ash/public/cpp/tablet_mode.h"
#include "ash/public/cpp/window_properties.h"
#include "base/trace_event/trace_event.h" #include "base/trace_event/trace_event.h"
#include "ui/aura/window.h"
namespace chromeos_camera { namespace chromeos_camera {
CameraAppHelperImpl::CameraAppHelperImpl( CameraAppHelperImpl::CameraAppHelperImpl(
CameraResultCallback camera_result_callback) CameraResultCallback camera_result_callback,
: camera_result_callback_(std::move(camera_result_callback)) {} aura::Window* window)
: camera_result_callback_(std::move(camera_result_callback)) {
DCHECK(window);
window->SetProperty(ash::kCanConsumeSystemKeysKey, true);
ash::TabletMode::Get()->AddObserver(this);
}
CameraAppHelperImpl::~CameraAppHelperImpl() = default; CameraAppHelperImpl::~CameraAppHelperImpl() {
ash::TabletMode::Get()->RemoveObserver(this);
}
void CameraAppHelperImpl::HandleCameraResult( void CameraAppHelperImpl::HandleCameraResult(
uint32_t intent_id, uint32_t intent_id,
...@@ -35,4 +46,21 @@ void CameraAppHelperImpl::StopPerfEventTrace(const std::string& event) { ...@@ -35,4 +46,21 @@ void CameraAppHelperImpl::StopPerfEventTrace(const std::string& event) {
TRACE_EVENT_END0("camera", event.c_str()); TRACE_EVENT_END0("camera", event.c_str());
} }
void CameraAppHelperImpl::SetTabletMonitor(
mojo::PendingRemote<TabletModeMonitor> monitor,
SetTabletMonitorCallback callback) {
monitor_ = mojo::Remote<TabletModeMonitor>(std::move(monitor));
std::move(callback).Run(ash::TabletMode::Get()->InTabletMode());
}
void CameraAppHelperImpl::OnTabletModeStarted() {
if (monitor_.is_bound())
monitor_->Update(true);
}
void CameraAppHelperImpl::OnTabletModeEnded() {
if (monitor_.is_bound())
monitor_->Update(false);
}
} // namespace chromeos_camera } // namespace chromeos_camera
...@@ -7,22 +7,32 @@ ...@@ -7,22 +7,32 @@
#include <vector> #include <vector>
#include "ash/public/cpp/tablet_mode_observer.h"
#include "base/macros.h"
#include "components/chromeos_camera/common/camera_app_helper.mojom.h" #include "components/chromeos_camera/common/camera_app_helper.mojom.h"
#include "mojo/public/cpp/bindings/remote.h"
namespace aura {
class Window;
} // namespace aura
namespace chromeos_camera { namespace chromeos_camera {
class CameraAppHelperImpl : public chromeos_camera::mojom::CameraAppHelper { class CameraAppHelperImpl : public ash::TabletModeObserver,
public mojom::CameraAppHelper {
public: public:
using CameraResultCallback = using CameraResultCallback =
base::RepeatingCallback<void(uint32_t, base::RepeatingCallback<void(uint32_t,
arc::mojom::CameraIntentAction, arc::mojom::CameraIntentAction,
const std::vector<uint8_t>&, const std::vector<uint8_t>&,
HandleCameraResultCallback)>; HandleCameraResultCallback)>;
using TabletModeMonitor = mojom::TabletModeMonitor;
explicit CameraAppHelperImpl(CameraResultCallback camera_result_callback); CameraAppHelperImpl(CameraResultCallback camera_result_callback,
aura::Window* window);
~CameraAppHelperImpl() override; ~CameraAppHelperImpl() override;
// chromeos_camera::mojom::CameraAppHelper implementations. // mojom::CameraAppHelper implementations.
void HandleCameraResult(uint32_t intent_id, void HandleCameraResult(uint32_t intent_id,
arc::mojom::CameraIntentAction action, arc::mojom::CameraIntentAction action,
const std::vector<uint8_t>& data, const std::vector<uint8_t>& data,
...@@ -30,10 +40,18 @@ class CameraAppHelperImpl : public chromeos_camera::mojom::CameraAppHelper { ...@@ -30,10 +40,18 @@ class CameraAppHelperImpl : public chromeos_camera::mojom::CameraAppHelper {
void IsTabletMode(IsTabletModeCallback callback) override; void IsTabletMode(IsTabletModeCallback callback) override;
void StartPerfEventTrace(const std::string& event) override; void StartPerfEventTrace(const std::string& event) override;
void StopPerfEventTrace(const std::string& event) override; void StopPerfEventTrace(const std::string& event) override;
void SetTabletMonitor(mojo::PendingRemote<TabletModeMonitor> monitor,
SetTabletMonitorCallback callback) override;
private: private:
// ash::TabletModeObserver overrides;
void OnTabletModeStarted() override;
void OnTabletModeEnded() override;
CameraResultCallback camera_result_callback_; CameraResultCallback camera_result_callback_;
mojo::Remote<TabletModeMonitor> monitor_;
DISALLOW_COPY_AND_ASSIGN(CameraAppHelperImpl); DISALLOW_COPY_AND_ASSIGN(CameraAppHelperImpl);
}; };
......
...@@ -6,6 +6,14 @@ module chromeos_camera.mojom; ...@@ -6,6 +6,14 @@ module chromeos_camera.mojom;
import "components/arc/mojom/camera_intent.mojom"; import "components/arc/mojom/camera_intent.mojom";
// Interface for monitoring tablet mode state of device. The state is detected
// from Chrome browser process and is notified to Chrome Camera App in renderer
// process.
interface TabletModeMonitor {
// Updates with the latest changed tablet mode state.
Update(bool is_tablet_mode);
};
// Interface for communication between Chrome Camera App (Remote) and Chrome // Interface for communication between Chrome Camera App (Remote) and Chrome
// (Receiver). // (Receiver).
interface CameraAppHelper { interface CameraAppHelper {
...@@ -26,4 +34,10 @@ interface CameraAppHelper { ...@@ -26,4 +34,10 @@ interface CameraAppHelper {
// Triggers the end of event tracing for given |event|. // Triggers the end of event tracing for given |event|.
StopPerfEventTrace(string event); StopPerfEventTrace(string event);
// Registers an TabletModeMonitor instance and returns the tablet mode
// initial state. Calling the Update() whenever the tablet mode state
// changes.
SetTabletMonitor(pending_remote<TabletModeMonitor> monitor)
=> (bool is_tablet_mode);
}; };
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment