提交 e8b988e2 编写于 作者: A Adam Barth

Expose Android sensors to via Mojo services

This CL adds a sensor_service to sky/services and wires it into SkyShell
The plan is to eventually use this data to implement shake-to-refresh.

R=eseidel@chromium.org

Review URL: https://codereview.chromium.org/962043002
上级 ef1b30fa
......@@ -8,6 +8,7 @@
<uses-sdk android:minSdkVersion="14" android:targetSdkVersion="21" />
<uses-permission android:name="android.permission.INTERNET"/>
<uses-feature android:name="android.hardware.sensor.accelerometer" android:required="true" />
<application android:name="org.domokit.sky.shell.SkyApplication" android:label="Sky">
<activity android:name="SkyDemoActivity"
......
......@@ -154,7 +154,6 @@ void DartController::ExecuteLibraryInModule(AbstractModule* module,
}
static void UnhandledExceptionCallback(Dart_Handle error) {
DCHECK(!Dart_IsError(error));
LOG(ERROR) << Dart_GetError(error);
}
......
<script>
import '/sky/framework/shell.dart' as shell;
import 'dart:sky';
import 'package:sky/services/sensors/sensors.mojom.dart';
class MyListener extends SensorListener {
int count = 0;
void onAccuracyChanged(int accuracy) {
print("onAccuracyChanged $accuracy");
}
void onSensorChanged(SensorData data) {
double value = data.values[0] + data.values[1] + data.values[2];
if (value > 40.0) {
document.querySelector('div').textContent =
"Shake count " + (count++).toString();
}
}
MyListener.unbound() {
stub = new SensorListenerStub.unbound()
..delegate = this;
}
SensorListenerStub stub;
}
void main() {
var sensorService = new SensorServiceProxy.unbound();
shell.requestService(sensorService);
var listener = new MyListener.unbound();
sensorService.ptr.addListener(SensorType_ACCELEROMETER, listener.stub);
listener.stub.listen();
}
</script>
<div>Shake me.</div>
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import "/mojo/public/dart/application.dart";
import "dart:sky.internals" as internals;
import "mojo:core" as core;
import "package:mojo/public/interfaces/application/service_provider.mojom.dart";
ApplicationConnection _initConnection() {
int rawHandle = internals.takeServicesProvidedByEmbedder();
core.MojoHandle proxyHandle = new core.MojoHandle(rawHandle);
ServiceProviderProxy serviceProvider = null;
if (proxyHandle.isValid)
serviceProvider = new ServiceProviderProxy.fromHandle(proxyHandle);
return new ApplicationConnection(null, serviceProvider);
}
final ApplicationConnection _connection = _initConnection();
void requestService(Object proxy) {
_connection.requestService(proxy);
}
......@@ -4,11 +4,14 @@
package org.domokit.oknet;
import android.content.Context;
import com.squareup.okhttp.OkHttpClient;
import org.chromium.mojo.bindings.InterfaceRequest;
import org.chromium.mojo.system.Core;
import org.chromium.mojo.system.DataPipe;
import org.chromium.mojo.system.MessagePipeHandle;
import org.chromium.mojo.system.MojoException;
import org.chromium.mojom.mojo.CookieStore;
import org.chromium.mojom.mojo.NetAddress;
......@@ -26,10 +29,12 @@ public class NetworkServiceImpl implements NetworkService {
private OkHttpClient mClient;
private Core mCore;
public NetworkServiceImpl(Core core) {
public NetworkServiceImpl(Context context, Core core, MessagePipeHandle pipe) {
assert core != null;
mCore = core;
mClient = new OkHttpClient();
NetworkService.MANAGER.bind(this, pipe);
}
@Override
......
# Copyright 2015 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import("//build/config/android/config.gni")
import("//build/config/android/rules.gni")
import("//mojo/public/tools/bindings/mojom.gni")
android_library("sensors") {
java_files = [
"org/domokit/sensors/SensorForwarder.java",
"org/domokit/sensors/SensorServiceImpl.java",
]
deps = [
"//mojo/public/java:bindings",
"//mojo/public/java:system",
":interfaces_java",
]
}
mojom("interfaces") {
sources = [
"sensors.mojom",
]
}
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package org.domokit.sensors;
import android.content.Context;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.util.Log;
import org.chromium.mojo.bindings.ConnectionErrorHandler;
import org.chromium.mojo.system.MojoException;
import org.chromium.mojom.sensors.SensorData;
import org.chromium.mojom.sensors.SensorListener;
import org.chromium.mojom.sensors.SensorType;
/**
* A class to forward sensor data to a SensorListener.
*/
public class SensorForwarder implements ConnectionErrorHandler, SensorEventListener {
private static final String TAG = "SensorForwarder";
private SensorListener.Proxy mListener;
private SensorManager mManager;
private Sensor mSensor;
private static int getAndroidTypeForSensor(int sensorType) {
switch (sensorType) {
case SensorType.ACCELEROMETER:
return Sensor.TYPE_ACCELEROMETER;
case SensorType.AMBIENT_TEMPERATURE:
return Sensor.TYPE_AMBIENT_TEMPERATURE;
case SensorType.GAME_ROTATION_VECTOR:
return Sensor.TYPE_GAME_ROTATION_VECTOR;
case SensorType.GEOMAGNETIC_ROTATION_VECTOR:
return Sensor.TYPE_GEOMAGNETIC_ROTATION_VECTOR;
case SensorType.GRAVITY:
return Sensor.TYPE_GRAVITY;
case SensorType.GYROSCOPE:
return Sensor.TYPE_GYROSCOPE;
case SensorType.GYROSCOPE_UNCALIBRATED:
return Sensor.TYPE_GYROSCOPE_UNCALIBRATED;
case SensorType.HEART_RATE:
return Sensor.TYPE_HEART_RATE;
case SensorType.LIGHT:
return Sensor.TYPE_LIGHT;
case SensorType.LINEAR_ACCELERATION:
return Sensor.TYPE_LINEAR_ACCELERATION;
case SensorType.MAGNETIC_FIELD:
return Sensor.TYPE_MAGNETIC_FIELD;
case SensorType.MAGNETIC_FIELD_UNCALIBRATED:
return Sensor.TYPE_MAGNETIC_FIELD_UNCALIBRATED;
case SensorType.PRESSURE:
return Sensor.TYPE_PRESSURE;
case SensorType.PROXIMITY:
return Sensor.TYPE_PROXIMITY;
case SensorType.RELATIVE_HUMIDITY:
return Sensor.TYPE_RELATIVE_HUMIDITY;
case SensorType.ROTATION_VECTOR:
return Sensor.TYPE_ROTATION_VECTOR;
case SensorType.SIGNIFICANT_MOTION:
return Sensor.TYPE_SIGNIFICANT_MOTION;
case SensorType.STEP_COUNTER:
return Sensor.TYPE_STEP_COUNTER;
case SensorType.STEP_DETECTOR:
return Sensor.TYPE_STEP_DETECTOR;
default:
return -1;
}
}
public SensorForwarder(Context context, int mojoSensorType, SensorListener.Proxy listener) {
int androidSensorType = getAndroidTypeForSensor(mojoSensorType);
mListener = listener;
mManager = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE);
mSensor = mManager.getDefaultSensor(androidSensorType);
if (mSensor == null) {
Log.e(TAG, "No default sensor for sensor type " + mojoSensorType);
mListener.close();
return;
}
// TODO(abarth): We should expose a way for clients to request different
// update rates.
mManager.registerListener(this, mSensor, SensorManager.SENSOR_DELAY_NORMAL);
mListener.setErrorHandler(this);
}
@Override
public void onConnectionError(MojoException e) {
mManager.unregisterListener(this);
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
mListener.onAccuracyChanged(accuracy);
}
@Override
public void onSensorChanged(SensorEvent event) {
SensorData data = new SensorData();
data.accuracy = event.accuracy;
data.timeStamp = event.timestamp;
data.values = event.values;
mListener.onSensorChanged(data);
}
}
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package org.domokit.sensors;
import android.content.Context;
import org.chromium.mojo.system.Core;
import org.chromium.mojo.system.MessagePipeHandle;
import org.chromium.mojo.system.MojoException;
import org.chromium.mojom.sensors.SensorListener;
import org.chromium.mojom.sensors.SensorService;
/**
* Android implementation of Senors.
*/
public class SensorServiceImpl implements SensorService {
private Context mContext;
public SensorServiceImpl(Context context, Core core, MessagePipeHandle pipe) {
mContext = context;
SensorService.MANAGER.bind(this, pipe);
}
@Override
public void close() {}
@Override
public void onConnectionError(MojoException e) {}
@Override
public void addListener(int sensorType, SensorListener listener) {
new SensorForwarder(mContext, sensorType, (SensorListener.Proxy) listener);
}
}
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
module sensors;
enum SensorType {
ACCELEROMETER,
AMBIENT_TEMPERATURE,
GAME_ROTATION_VECTOR,
GEOMAGNETIC_ROTATION_VECTOR,
GRAVITY,
GYROSCOPE,
GYROSCOPE_UNCALIBRATED,
HEART_RATE,
LIGHT,
LINEAR_ACCELERATION,
MAGNETIC_FIELD,
MAGNETIC_FIELD_UNCALIBRATED,
PRESSURE,
PROXIMITY,
RELATIVE_HUMIDITY,
ROTATION_VECTOR,
SIGNIFICANT_MOTION,
STEP_COUNTER,
STEP_DETECTOR,
};
struct SensorData {
int32 accuracy;
int64 time_stamp;
array<float> values;
};
interface SensorListener {
OnAccuracyChanged(int32 accuracy);
OnSensorChanged(SensorData data);
};
interface SensorService {
AddListener(SensorType type, SensorListener listener);
};
......@@ -41,6 +41,8 @@ shared_library("sky_shell") {
"ui/engine.h",
"ui/input_event_converter.cc",
"ui/input_event_converter.h",
"ui/internals.cc",
"ui/internals.h",
"ui_delegate.cc",
"ui_delegate.h",
]
......@@ -49,6 +51,7 @@ shared_library("sky_shell") {
"//base",
"//base:i18n",
"//build/config/sanitizers:deps",
"//dart/runtime/bin:libdart_withcore",
"//mojo/android:libsystem_java",
"//mojo/common",
"//mojo/edk/system",
......@@ -58,6 +61,7 @@ shared_library("sky_shell") {
"//mojo/services/network/public/interfaces",
"//skia",
"//sky/engine",
"//sky/engine/tonic",
"//sky/services/platform",
"//sky/services/viewport",
"//ui/gfx/geometry",
......@@ -83,6 +87,8 @@ android_library("java") {
"//mojo/public/java:system",
"//mojo/services/network/public/interfaces:interfaces_java",
"//sky/services/oknet",
"//sky/services/sensors",
"//sky/services/sensors:interfaces_java",
"//sky/services/viewport:viewport_java",
]
}
......
......@@ -4,6 +4,7 @@
#include "sky/shell/java_service_provider.h"
#include "base/android/jni_android.h"
#include "jni/JavaServiceProvider_jni.h"
namespace sky {
......@@ -16,7 +17,8 @@ bool RegisterJavaServiceProvider(JNIEnv* env) {
mojo::ScopedMessagePipeHandle CreateJavaServiceProvider() {
JNIEnv* env = base::android::AttachCurrentThread();
return mojo::ScopedMessagePipeHandle(
mojo::MessagePipeHandle(Java_JavaServiceProvider_create(env)));
mojo::MessagePipeHandle(Java_JavaServiceProvider_create(
env, base::android::GetApplicationContext())));
}
} // namespace shell
......
......@@ -4,6 +4,8 @@
package org.domokit.sky.shell;
import android.content.Context;
import org.chromium.base.CalledByNative;
import org.chromium.base.JNINamespace;
import org.chromium.mojo.system.Core;
......@@ -13,7 +15,9 @@ import org.chromium.mojo.system.Pair;
import org.chromium.mojo.system.impl.CoreImpl;
import org.chromium.mojom.mojo.NetworkService;
import org.chromium.mojom.mojo.ServiceProvider;
import org.chromium.mojom.sensors.SensorService;
import org.domokit.oknet.NetworkServiceImpl;
import org.domokit.sensors.SensorServiceImpl;
/**
* A class to intialize the network.
......@@ -21,19 +25,22 @@ import org.domokit.oknet.NetworkServiceImpl;
@JNINamespace("sky::shell")
public class JavaServiceProvider implements ServiceProvider {
private Core mCore;
private Context mContext;
@SuppressWarnings("unused")
@CalledByNative
public static int create() {
public static int create(Context context) {
Core core = CoreImpl.getInstance();
Pair<MessagePipeHandle, MessagePipeHandle> messagePipe = core.createMessagePipe(null);
ServiceProvider.MANAGER.bind(new JavaServiceProvider(core), messagePipe.first);
ServiceProvider.MANAGER.bind(new JavaServiceProvider(core, context), messagePipe.first);
return messagePipe.second.releaseNativeHandle();
}
public JavaServiceProvider(Core core) {
public JavaServiceProvider(Core core, Context context) {
assert core != null;
assert context != null;
mCore = core;
mContext = context;
}
@Override
......@@ -45,7 +52,10 @@ public class JavaServiceProvider implements ServiceProvider {
@Override
public void connectToService(String interfaceName, MessagePipeHandle pipe) {
if (interfaceName.equals(NetworkService.MANAGER.getName())) {
NetworkService.MANAGER.bind(new NetworkServiceImpl(mCore), pipe);
new NetworkServiceImpl(mContext, mCore, pipe);
return;
} else if (interfaceName.equals(SensorService.MANAGER.getName())) {
new SensorServiceImpl(mContext, mCore, pipe);
return;
}
pipe.close();
......
......@@ -18,7 +18,7 @@ import org.chromium.base.library_loader.ProcessInitException;
* state and initializations.
*/
public class SkyApplication extends BaseChromiumApplication {
private static final String TAG = "SkyShellApplication";
private static final String TAG = "SkyApplication";
private static final String PRIVATE_DATA_DIRECTORY_SUFFIX = "sky_shell";
private static final String[] SKY_MANDATORY_PAKS = {
"icudtl.dat",
......
......@@ -14,6 +14,7 @@
#include "sky/services/platform/platform_impl.h"
#include "sky/shell/ui/animator.h"
#include "sky/shell/ui/input_event_converter.h"
#include "sky/shell/ui/internals.h"
#include "third_party/skia/include/core/SkCanvas.h"
#include "third_party/skia/include/core/SkPictureRecorder.h"
......@@ -48,10 +49,10 @@ base::WeakPtr<Engine> Engine::GetWeakPtr() {
}
void Engine::Init(mojo::ScopedMessagePipeHandle service_provider_handle) {
mojo::ServiceProviderPtr service_provider =
service_provider_ =
mojo::MakeProxy<mojo::ServiceProvider>(service_provider_handle.Pass());
mojo::NetworkServicePtr network_service;
mojo::ConnectToService(service_provider.get(), &network_service);
mojo::ConnectToService(service_provider_.get(), &network_service);
platform_impl_.reset(new PlatformImpl(network_service.Pass()));
blink::initialize(platform_impl_.get());
......@@ -141,6 +142,11 @@ void Engine::scheduleVisualUpdate() {
animator_->RequestFrame();
}
void Engine::didCreateIsolate(blink::WebLocalFrame* frame,
Dart_Isolate isolate) {
Internals::Create(isolate, service_provider_.Pass());
}
blink::ServiceProvider* Engine::services() {
return this;
}
......
......@@ -11,6 +11,7 @@
#include "base/single_thread_task_runner.h"
#include "mojo/public/cpp/bindings/binding.h"
#include "mojo/public/cpp/system/core.h"
#include "mojo/public/interfaces/application/service_provider.mojom.h"
#include "mojo/services/navigation/public/interfaces/navigation.mojom.h"
#include "skia/ext/refptr.h"
#include "sky/engine/public/platform/ServiceProvider.h"
......@@ -65,6 +66,8 @@ class Engine : public UIDelegate,
void scheduleVisualUpdate() override;
blink::WebScreenInfo screenInfo() override;
blink::ServiceProvider* services() override;
void didCreateIsolate(blink::WebLocalFrame* frame,
Dart_Isolate isolate) override;
// Services methods:
mojo::NavigatorHost* NavigatorHost() override;
......@@ -77,6 +80,7 @@ class Engine : public UIDelegate,
void UpdateWebViewSize();
mojo::ServiceProviderPtr service_provider_;
scoped_ptr<PlatformImpl> platform_impl_;
scoped_ptr<Animator> animator_;
blink::WebView* web_view_;
......
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "sky/engine/config.h"
#include "sky/shell/ui/internals.h"
#include "mojo/public/cpp/application/connect.h"
#include "mojo/public/cpp/bindings/array.h"
#include "sky/engine/tonic/dart_builtin.h"
#include "sky/engine/tonic/dart_converter.h"
#include "sky/engine/tonic/dart_error.h"
#include "sky/engine/tonic/dart_state.h"
using namespace blink;
namespace sky {
namespace shell {
namespace {
int kInternalsKey = 0;
Internals* GetInternals() {
DartState* state = DartState::Current();
return static_cast<Internals*>(state->GetUserData(&kInternalsKey));
}
void TakeServicesProvidedByEmbedder(Dart_NativeArguments args) {
Dart_SetIntegerReturnValue(
args, GetInternals()->TakeServicesProvidedByEmbedder().value());
}
const DartBuiltin::Natives kNativeFunctions[] = {
{"takeServicesProvidedByEmbedder", TakeServicesProvidedByEmbedder, 0},
};
const DartBuiltin& GetBuiltin() {
static DartBuiltin& builtin = *new DartBuiltin(kNativeFunctions,
arraysize(kNativeFunctions));
return builtin;
}
Dart_NativeFunction Resolver(Dart_Handle name,
int argument_count,
bool* auto_setup_scope) {
return GetBuiltin().Resolver(name, argument_count, auto_setup_scope);
}
const uint8_t* Symbolizer(Dart_NativeFunction native_function) {
return GetBuiltin().Symbolizer(native_function);
}
const char kLibraryName[] = "dart:sky.internals";
const char kLibrarySource[] = R"DART(
int takeServicesProvidedByEmbedder() native "takeServicesProvidedByEmbedder";
)DART";
} // namespace
void Internals::Create(Dart_Isolate isolate,
mojo::ServiceProviderPtr service_provider) {
DartState* state = DartState::From(isolate);
state->SetUserData(&kInternalsKey, new Internals(service_provider.Pass()));
Dart_Handle library =
Dart_LoadLibrary(Dart_NewStringFromCString(kLibraryName),
Dart_NewStringFromCString(kLibrarySource), 0, 0);
CHECK(!LogIfError(library));
CHECK(!LogIfError(Dart_FinalizeLoading(true)));
CHECK(!LogIfError(Dart_SetNativeResolver(library, Resolver, Symbolizer)));
}
Internals::Internals(mojo::ServiceProviderPtr service_provider)
: service_provider_(service_provider.Pass()) {
}
Internals::~Internals() {
}
mojo::Handle Internals::TakeServicesProvidedByEmbedder() {
return service_provider_.PassMessagePipe().release();
}
} // namespace shell
} // namespace sky
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef SKY_SHELL_UI_INTERNALS_H_
#define SKY_SHELL_UI_INTERNALS_H_
#include "base/supports_user_data.h"
#include "dart/runtime/include/dart_api.h"
#include "mojo/public/interfaces/application/service_provider.mojom.h"
namespace sky {
namespace shell {
class Internals : public base::SupportsUserData::Data {
public:
virtual ~Internals();
static void Create(Dart_Isolate isolate,
mojo::ServiceProviderPtr service_provider);
mojo::Handle TakeServicesProvidedByEmbedder();
private:
explicit Internals(mojo::ServiceProviderPtr service_provider);
mojo::ServiceProviderPtr service_provider_;
MOJO_DISALLOW_COPY_AND_ASSIGN(Internals);
};
} // namespace shell
} // namespace sky
#endif // SKY_SHELL_UI_INTERNALS_H_
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册