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 @@
#include "media/capture/video/chromeos/mojom/camera_app.mojom.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/self_owned_receiver.h"
#include "ui/aura/window.h"
#if BUILDFLAG(GOOGLE_CHROME_BRANDING)
#include "chromeos/services/ime/public/mojom/input_engine.mojom.h"
......@@ -119,9 +120,10 @@ void ConnectToCameraAppHelper(
mojo::PendingReceiver<chromeos_camera::mojom::CameraAppHelper> receiver) {
auto handle_result_callback = base::BindRepeating(
&HandleCameraResult, source->GetProcess()->GetBrowserContext());
auto* window = source->GetNativeView()->GetToplevelWindow();
auto camera_app_helper =
std::make_unique<chromeos_camera::CameraAppHelperImpl>(
std::move(handle_result_callback));
std::move(handle_result_callback), window);
mojo::MakeSelfOwnedReceiver(std::move(camera_app_helper),
std::move(receiver));
}
......
......@@ -174,6 +174,7 @@ export class App {
* @return {!Promise}
*/
async start() {
await this.cameraView_.initialize();
let ackMigrate = false;
filesystem
.initialize(() => {
......
......@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import {assertBoolean} from '../chrome_util.js';
/**
* The singleton instance of ChromeHelper. Initialized by the first
* invocation of getInstance().
......@@ -22,16 +24,37 @@ export class ChromeHelper {
* @type {!chromeosCamera.mojom.CameraAppHelperRemote}
*/
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.
* @return {!Promise<boolean>}
* Starts tablet mode monitor monitoring tablet mode state of device.
* @return {!Promise}
*/
async isTabletMode() {
return await this.remote_.isTabletMode().then(({isTabletMode}) => {
return isTabletMode;
async initTabletModeMonitor() {
const monitorCallbackRouter =
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 {
});
chrome.app.window.current().onMinimized.addListener(() => this.start());
document.addEventListener('visibilitychange', async () => {
const isTabletBackground = await this.isTabletBackground_();
document.addEventListener('visibilitychange', () => {
const recording = state.get(state.State.TAKING) && state.get(Mode.VIDEO);
if (isTabletBackground && !recording) {
if (this.isTabletBackground_() && !recording) {
this.start();
}
});
......@@ -221,6 +220,14 @@ export class Camera extends View {
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
* both window mode or tablet mode.
......@@ -231,22 +238,20 @@ export class Camera extends View {
}
/**
* @return {!Promise<boolean>} Resolved to boolean value indicating whether
* window is put to background in tablet mode.
* @return {boolean} Whether window is put to background in tablet mode.
* @private
*/
async isTabletBackground_() {
const isTabletMode = await ChromeHelper.getInstance().isTabletMode();
return isTabletMode && !this.isVisible_;
isTabletBackground_() {
return ChromeHelper.getInstance().isTabletMode() && !this.isVisible_;
}
/**
* Whether app window is suspended.
* @return {!Promise<boolean>}
* @return {boolean}
*/
async isSuspended() {
isSuspended() {
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 {
toast.show(this.preview_.toString());
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;
}
......@@ -414,7 +429,7 @@ export class Camera extends View {
}
for (const {resolution: captureR, previewCandidates} of resolCandidates) {
for (const constraints of previewCandidates) {
if (await this.isSuspended()) {
if (this.isSuspended()) {
throw new CameraSuspendedError();
}
try {
......@@ -469,7 +484,7 @@ export class Camera extends View {
async start_() {
try {
await this.infoUpdater_.lockDeviceInfo(async () => {
if (!await this.isSuspended()) {
if (!this.isSuspended()) {
for (const id of await this.options_.videoDeviceIds()) {
if (await this.startWithDevice_(id)) {
// Make the different active camera announced by screen reader.
......
......@@ -198,6 +198,7 @@ source_set("camera_app_helper") {
deps = [
"common:camera_app_helper",
"//ash/public/cpp",
"//ui/aura",
]
}
......
......@@ -3,5 +3,6 @@ include_rules = [
"+media",
"+mojo",
"+third_party/libyuv",
"+ui/aura",
"+ui/gfx",
]
\ No newline at end of file
......@@ -4,16 +4,27 @@
#include "components/chromeos_camera/camera_app_helper_impl.h"
#include <utility>
#include "ash/public/cpp/tablet_mode.h"
#include "ash/public/cpp/window_properties.h"
#include "base/trace_event/trace_event.h"
#include "ui/aura/window.h"
namespace chromeos_camera {
CameraAppHelperImpl::CameraAppHelperImpl(
CameraResultCallback camera_result_callback)
: camera_result_callback_(std::move(camera_result_callback)) {}
CameraResultCallback 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(
uint32_t intent_id,
......@@ -35,4 +46,21 @@ void CameraAppHelperImpl::StopPerfEventTrace(const std::string& event) {
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
......@@ -7,22 +7,32 @@
#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 "mojo/public/cpp/bindings/remote.h"
namespace aura {
class Window;
} // namespace aura
namespace chromeos_camera {
class CameraAppHelperImpl : public chromeos_camera::mojom::CameraAppHelper {
class CameraAppHelperImpl : public ash::TabletModeObserver,
public mojom::CameraAppHelper {
public:
using CameraResultCallback =
base::RepeatingCallback<void(uint32_t,
arc::mojom::CameraIntentAction,
const std::vector<uint8_t>&,
HandleCameraResultCallback)>;
using TabletModeMonitor = mojom::TabletModeMonitor;
explicit CameraAppHelperImpl(CameraResultCallback camera_result_callback);
CameraAppHelperImpl(CameraResultCallback camera_result_callback,
aura::Window* window);
~CameraAppHelperImpl() override;
// chromeos_camera::mojom::CameraAppHelper implementations.
// mojom::CameraAppHelper implementations.
void HandleCameraResult(uint32_t intent_id,
arc::mojom::CameraIntentAction action,
const std::vector<uint8_t>& data,
......@@ -30,10 +40,18 @@ class CameraAppHelperImpl : public chromeos_camera::mojom::CameraAppHelper {
void IsTabletMode(IsTabletModeCallback callback) override;
void StartPerfEventTrace(const std::string& event) override;
void StopPerfEventTrace(const std::string& event) override;
void SetTabletMonitor(mojo::PendingRemote<TabletModeMonitor> monitor,
SetTabletMonitorCallback callback) override;
private:
// ash::TabletModeObserver overrides;
void OnTabletModeStarted() override;
void OnTabletModeEnded() override;
CameraResultCallback camera_result_callback_;
mojo::Remote<TabletModeMonitor> monitor_;
DISALLOW_COPY_AND_ASSIGN(CameraAppHelperImpl);
};
......
......@@ -6,6 +6,14 @@ module chromeos_camera.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
// (Receiver).
interface CameraAppHelper {
......@@ -26,4 +34,10 @@ interface CameraAppHelper {
// Triggers the end of event tracing for given |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