Add support in the platform for Activity Recognition Hardware.
Change-Id: I7c4fff3526583475a5edf1f4ba8fede4e9419ead
This commit is contained in:
@@ -156,6 +156,9 @@ LOCAL_SRC_FILES += \
|
||||
core/java/android/hardware/hdmi/IHdmiVendorCommandListener.aidl \
|
||||
core/java/android/hardware/input/IInputManager.aidl \
|
||||
core/java/android/hardware/input/IInputDevicesChangedListener.aidl \
|
||||
core/java/android/hardware/location/IActivityRecognitionHardware.aidl \
|
||||
core/java/android/hardware/location/IActivityRecognitionHardwareSink.aidl \
|
||||
core/java/android/hardware/location/IActivityRecognitionHardwareWatcher.aidl \
|
||||
core/java/android/hardware/location/IFusedLocationHardware.aidl \
|
||||
core/java/android/hardware/location/IFusedLocationHardwareSink.aidl \
|
||||
core/java/android/hardware/location/IGeofenceHardware.aidl \
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* Copyright (C) 2014 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 android.hardware.location;
|
||||
|
||||
parcelable ActivityChangedEvent;
|
||||
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* Copyright (C) 2014 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 android.hardware.location;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
import java.security.InvalidParameterException;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* A class representing an event for Activity changes.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public class ActivityChangedEvent implements Parcelable {
|
||||
private final List<ActivityRecognitionEvent> mActivityRecognitionEvents;
|
||||
|
||||
public ActivityChangedEvent(ActivityRecognitionEvent[] activityRecognitionEvents) {
|
||||
if (activityRecognitionEvents == null) {
|
||||
throw new InvalidParameterException(
|
||||
"Parameter 'activityRecognitionEvents' must not be null.");
|
||||
}
|
||||
|
||||
mActivityRecognitionEvents = Arrays.asList(activityRecognitionEvents);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public Iterable<ActivityRecognitionEvent> getActivityRecognitionEvents() {
|
||||
return mActivityRecognitionEvents;
|
||||
}
|
||||
|
||||
public static final Creator<ActivityChangedEvent> CREATOR =
|
||||
new Creator<ActivityChangedEvent>() {
|
||||
@Override
|
||||
public ActivityChangedEvent createFromParcel(Parcel source) {
|
||||
int activityRecognitionEventsLength = source.readInt();
|
||||
ActivityRecognitionEvent[] activityRecognitionEvents =
|
||||
new ActivityRecognitionEvent[activityRecognitionEventsLength];
|
||||
source.readTypedArray(activityRecognitionEvents, ActivityRecognitionEvent.CREATOR);
|
||||
|
||||
return new ActivityChangedEvent(activityRecognitionEvents);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ActivityChangedEvent[] newArray(int size) {
|
||||
return new ActivityChangedEvent[size];
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel parcel, int flags) {
|
||||
ActivityRecognitionEvent[] activityRecognitionEventArray =
|
||||
mActivityRecognitionEvents.toArray(new ActivityRecognitionEvent[0]);
|
||||
parcel.writeInt(activityRecognitionEventArray.length);
|
||||
parcel.writeTypedArray(activityRecognitionEventArray, flags);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* Copyright (C) 2014 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 android.hardware.location;
|
||||
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
/**
|
||||
* A class that represents an Activity Recognition Event.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public class ActivityRecognitionEvent implements Parcelable {
|
||||
private final String mActivity;
|
||||
private final int mEventType;
|
||||
private final long mTimestampNs;
|
||||
|
||||
public ActivityRecognitionEvent(String activity, int eventType, long timestampNs) {
|
||||
mActivity = activity;
|
||||
mEventType = eventType;
|
||||
mTimestampNs = timestampNs;
|
||||
}
|
||||
|
||||
public String getActivity() {
|
||||
return mActivity;
|
||||
}
|
||||
|
||||
public int getEventType() {
|
||||
return mEventType;
|
||||
}
|
||||
|
||||
public long getTimestampNs() {
|
||||
return mTimestampNs;
|
||||
}
|
||||
|
||||
public static final Creator<ActivityRecognitionEvent> CREATOR =
|
||||
new Creator<ActivityRecognitionEvent>() {
|
||||
@Override
|
||||
public ActivityRecognitionEvent createFromParcel(Parcel source) {
|
||||
String activity = source.readString();
|
||||
int eventType = source.readInt();
|
||||
long timestampNs = source.readLong();
|
||||
|
||||
return new ActivityRecognitionEvent(activity, eventType, timestampNs);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ActivityRecognitionEvent[] newArray(int size) {
|
||||
return new ActivityRecognitionEvent[size];
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel parcel, int flags) {
|
||||
parcel.writeString(mActivity);
|
||||
parcel.writeInt(mEventType);
|
||||
parcel.writeLong(mTimestampNs);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,224 @@
|
||||
/*
|
||||
* Copyright (C) 2014 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 android.hardware.location;
|
||||
|
||||
import android.Manifest;
|
||||
import android.content.Context;
|
||||
import android.os.RemoteCallbackList;
|
||||
import android.os.RemoteException;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
|
||||
/**
|
||||
* A class that implements an {@link IActivityRecognitionHardware} backed up by the Activity
|
||||
* Recognition HAL.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public class ActivityRecognitionHardware extends IActivityRecognitionHardware.Stub {
|
||||
private static final String TAG = "ActivityRecognitionHardware";
|
||||
|
||||
private static final String HARDWARE_PERMISSION = Manifest.permission.LOCATION_HARDWARE;
|
||||
private static final int INVALID_ACTIVITY_TYPE = -1;
|
||||
private static final int NATIVE_SUCCESS_RESULT = 0;
|
||||
|
||||
private static ActivityRecognitionHardware sSingletonInstance = null;
|
||||
private static final Object sSingletonInstanceLock = new Object();
|
||||
|
||||
private final Context mContext;
|
||||
private final String[] mSupportedActivities;
|
||||
|
||||
private final RemoteCallbackList<IActivityRecognitionHardwareSink> mSinks =
|
||||
new RemoteCallbackList<IActivityRecognitionHardwareSink>();
|
||||
|
||||
private static class Event {
|
||||
public int activity;
|
||||
public int type;
|
||||
public long timestamp;
|
||||
}
|
||||
|
||||
private ActivityRecognitionHardware(Context context) {
|
||||
nativeInitialize();
|
||||
|
||||
mContext = context;
|
||||
mSupportedActivities = fetchSupportedActivities();
|
||||
}
|
||||
|
||||
public static ActivityRecognitionHardware getInstance(Context context) {
|
||||
synchronized (sSingletonInstanceLock) {
|
||||
if (sSingletonInstance == null) {
|
||||
sSingletonInstance = new ActivityRecognitionHardware(context);
|
||||
}
|
||||
|
||||
return sSingletonInstance;
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isSupported() {
|
||||
return nativeIsSupported();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getSupportedActivities() {
|
||||
checkPermissions();
|
||||
return mSupportedActivities;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isActivitySupported(String activity) {
|
||||
checkPermissions();
|
||||
int activityType = getActivityType(activity);
|
||||
return activityType != INVALID_ACTIVITY_TYPE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean registerSink(IActivityRecognitionHardwareSink sink) {
|
||||
checkPermissions();
|
||||
return mSinks.register(sink);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean unregisterSink(IActivityRecognitionHardwareSink sink) {
|
||||
checkPermissions();
|
||||
return mSinks.unregister(sink);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean enableActivityEvent(String activity, int eventType, long reportLatencyNs) {
|
||||
checkPermissions();
|
||||
|
||||
int activityType = getActivityType(activity);
|
||||
if (activityType == INVALID_ACTIVITY_TYPE) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int result = nativeEnableActivityEvent(activityType, eventType, reportLatencyNs);
|
||||
return result == NATIVE_SUCCESS_RESULT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean disableActivityEvent(String activity, int eventType) {
|
||||
checkPermissions();
|
||||
|
||||
int activityType = getActivityType(activity);
|
||||
if (activityType == INVALID_ACTIVITY_TYPE) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int result = nativeDisableActivityEvent(activityType, eventType);
|
||||
return result == NATIVE_SUCCESS_RESULT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean flush() {
|
||||
checkPermissions();
|
||||
int result = nativeFlush();
|
||||
return result == NATIVE_SUCCESS_RESULT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by the Activity-Recognition HAL.
|
||||
*/
|
||||
private void onActivityChanged(Event[] events) {
|
||||
int size = mSinks.beginBroadcast();
|
||||
if (size == 0 || events == null || events.length == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
int eventsLength = events.length;
|
||||
ActivityRecognitionEvent activityRecognitionEventArray[] =
|
||||
new ActivityRecognitionEvent[eventsLength];
|
||||
for (int i = 0; i < eventsLength; ++i) {
|
||||
Event event = events[i];
|
||||
String activityName = getActivityName(event.activity);
|
||||
activityRecognitionEventArray[i] =
|
||||
new ActivityRecognitionEvent(activityName, event.type, event.timestamp);
|
||||
}
|
||||
ActivityChangedEvent activityChangedEvent =
|
||||
new ActivityChangedEvent(activityRecognitionEventArray);
|
||||
|
||||
for (int i = 0; i < size; ++i) {
|
||||
IActivityRecognitionHardwareSink sink = mSinks.getBroadcastItem(i);
|
||||
try {
|
||||
sink.onActivityChanged(activityChangedEvent);
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Error delivering activity changed event.", e);
|
||||
}
|
||||
}
|
||||
mSinks.finishBroadcast();
|
||||
|
||||
}
|
||||
|
||||
private String getActivityName(int activityType) {
|
||||
if (activityType < 0 || activityType >= mSupportedActivities.length) {
|
||||
String message = String.format(
|
||||
"Invalid ActivityType: %d, SupportedActivities: %d",
|
||||
activityType,
|
||||
mSupportedActivities.length);
|
||||
Log.e(TAG, message);
|
||||
return null;
|
||||
}
|
||||
|
||||
return mSupportedActivities[activityType];
|
||||
}
|
||||
|
||||
private int getActivityType(String activity) {
|
||||
if (TextUtils.isEmpty(activity)) {
|
||||
return INVALID_ACTIVITY_TYPE;
|
||||
}
|
||||
|
||||
int supporteActivitiesLength = mSupportedActivities.length;
|
||||
for (int i = 0; i < supporteActivitiesLength; ++i) {
|
||||
if (activity.equals(mSupportedActivities[i])) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return INVALID_ACTIVITY_TYPE;
|
||||
}
|
||||
|
||||
private void checkPermissions() {
|
||||
String message = String.format(
|
||||
"Permission '%s' not granted to access ActivityRecognitionHardware",
|
||||
HARDWARE_PERMISSION);
|
||||
mContext.enforceCallingPermission(HARDWARE_PERMISSION, message);
|
||||
}
|
||||
|
||||
private static String[] fetchSupportedActivities() {
|
||||
String[] supportedActivities = nativeGetSupportedActivities();
|
||||
if (supportedActivities != null) {
|
||||
return supportedActivities;
|
||||
}
|
||||
|
||||
return new String[0];
|
||||
}
|
||||
|
||||
// native bindings
|
||||
static { nativeClassInit(); }
|
||||
|
||||
private static native void nativeClassInit();
|
||||
private static native void nativeInitialize();
|
||||
private static native void nativeRelease();
|
||||
private static native boolean nativeIsSupported();
|
||||
private static native String[] nativeGetSupportedActivities();
|
||||
private static native int nativeEnableActivityEvent(
|
||||
int activityType,
|
||||
int eventType,
|
||||
long reportLatenceNs);
|
||||
private static native int nativeDisableActivityEvent(int activityType, int eventType);
|
||||
private static native int nativeFlush();
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Copyright (C) 2014, 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/license/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 android.hardware.location;
|
||||
|
||||
import android.hardware.location.IActivityRecognitionHardwareSink;
|
||||
|
||||
/**
|
||||
* Activity Recognition Hardware provider interface.
|
||||
* This interface can be used to implement hardware based activity recognition.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
interface IActivityRecognitionHardware {
|
||||
/**
|
||||
* Gets an array of supported activities by hardware.
|
||||
*/
|
||||
String[] getSupportedActivities();
|
||||
|
||||
/**
|
||||
* Returns true if the given activity is supported, false otherwise.
|
||||
*/
|
||||
boolean isActivitySupported(in String activityType);
|
||||
|
||||
/**
|
||||
* Registers a sink with Hardware Activity-Recognition.
|
||||
*/
|
||||
boolean registerSink(in IActivityRecognitionHardwareSink sink);
|
||||
|
||||
/**
|
||||
* Unregisters a sink with Hardware Activity-Recognition.
|
||||
*/
|
||||
boolean unregisterSink(in IActivityRecognitionHardwareSink sink);
|
||||
|
||||
/**
|
||||
* Enables tracking of a given activity/event type, if the activity is supported.
|
||||
*/
|
||||
boolean enableActivityEvent(in String activityType, int eventType, long reportLatencyNs);
|
||||
|
||||
/**
|
||||
* Disables tracking of a given activity/eventy type.
|
||||
*/
|
||||
boolean disableActivityEvent(in String activityType, int eventType);
|
||||
|
||||
/**
|
||||
* Requests hardware for all the activity events detected up to the given point in time.
|
||||
*/
|
||||
boolean flush();
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright (C) 2014, 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/license/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 android.hardware.location;
|
||||
|
||||
import android.hardware.location.ActivityChangedEvent;
|
||||
|
||||
/**
|
||||
* Activity Recognition Hardware provider Sink interface.
|
||||
* This interface can be used to implement sinks to receive activity notifications.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
interface IActivityRecognitionHardwareSink {
|
||||
/**
|
||||
* Activity changed event.
|
||||
*/
|
||||
void onActivityChanged(in ActivityChangedEvent event);
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright (C) 2014, 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/license/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 android.hardware.location;
|
||||
|
||||
import android.hardware.location.IActivityRecognitionHardware;
|
||||
|
||||
/**
|
||||
* Activity Recognition Hardware watcher. This interface can be used to receive interfaces to
|
||||
* implementations of {@link IActivityRecognitionHardware}.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
interface IActivityRecognitionHardwareWatcher {
|
||||
/**
|
||||
* Hardware Activity-Recognition availability event.
|
||||
*/
|
||||
void onInstanceChanged(in IActivityRecognitionHardware instance);
|
||||
}
|
||||
@@ -147,6 +147,7 @@ LOCAL_SRC_FILES:= \
|
||||
android_hardware_UsbDevice.cpp \
|
||||
android_hardware_UsbDeviceConnection.cpp \
|
||||
android_hardware_UsbRequest.cpp \
|
||||
android_hardware_location_ActivityRecognitionHardware.cpp \
|
||||
android_util_FileObserver.cpp \
|
||||
android/opengl/poly_clip.cpp.arm \
|
||||
android/opengl/util.cpp.arm \
|
||||
|
||||
@@ -87,6 +87,7 @@ extern int register_android_hardware_SoundTrigger(JNIEnv *env);
|
||||
extern int register_android_hardware_UsbDevice(JNIEnv *env);
|
||||
extern int register_android_hardware_UsbDeviceConnection(JNIEnv *env);
|
||||
extern int register_android_hardware_UsbRequest(JNIEnv *env);
|
||||
extern int register_android_hardware_location_ActivityRecognitionHardware(JNIEnv* env);
|
||||
|
||||
extern int register_android_media_AudioRecord(JNIEnv *env);
|
||||
extern int register_android_media_AudioSystem(JNIEnv *env);
|
||||
@@ -1323,6 +1324,7 @@ static const RegJNIRec gRegJNI[] = {
|
||||
REG_JNI(register_android_hardware_UsbDevice),
|
||||
REG_JNI(register_android_hardware_UsbDeviceConnection),
|
||||
REG_JNI(register_android_hardware_UsbRequest),
|
||||
REG_JNI(register_android_hardware_location_ActivityRecognitionHardware),
|
||||
REG_JNI(register_android_media_AudioRecord),
|
||||
REG_JNI(register_android_media_AudioSystem),
|
||||
REG_JNI(register_android_media_AudioTrack),
|
||||
|
||||
@@ -0,0 +1,304 @@
|
||||
/*
|
||||
* Copyright 2014, 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.
|
||||
*/
|
||||
|
||||
#define LOG_TAG "ActivityRecognitionHardware"
|
||||
|
||||
#include <jni.h>
|
||||
#include <JNIHelp.h>
|
||||
|
||||
#include <android_runtime/AndroidRuntime.h>
|
||||
#include <android_runtime/Log.h>
|
||||
|
||||
#include "activity_recognition.h"
|
||||
|
||||
|
||||
// keep base connection data from the HAL
|
||||
static activity_recognition_module_t* sModule = NULL;
|
||||
static activity_recognition_device_t* sDevice = NULL;
|
||||
|
||||
static jobject sCallbacksObject = NULL;
|
||||
static jmethodID sOnActivityChanged = NULL;
|
||||
|
||||
|
||||
static void check_and_clear_exceptions(JNIEnv* env, const char* method_name) {
|
||||
if (!env->ExceptionCheck()) {
|
||||
return;
|
||||
}
|
||||
|
||||
ALOGE("An exception was thrown by '%s'.", method_name);
|
||||
LOGE_EX(env);
|
||||
env->ExceptionClear();
|
||||
}
|
||||
|
||||
static jint attach_thread(JNIEnv** env) {
|
||||
JavaVM* java_vm = android::AndroidRuntime::getJavaVM();
|
||||
assert(java_vm != NULL);
|
||||
|
||||
JavaVMAttachArgs args = {
|
||||
JNI_VERSION_1_6,
|
||||
"ActivityRecognition HAL callback.",
|
||||
NULL /* group */
|
||||
};
|
||||
|
||||
jint result = java_vm->AttachCurrentThread(env, &args);
|
||||
if (result != JNI_OK) {
|
||||
ALOGE("Attach to callback thread failed: %d", result);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static jint detach_thread() {
|
||||
JavaVM* java_vm = android::AndroidRuntime::getJavaVM();
|
||||
assert(java_vm != NULL);
|
||||
|
||||
jint result = java_vm->DetachCurrentThread();
|
||||
if (result != JNI_OK) {
|
||||
ALOGE("Detach of callback thread failed: %d", result);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Handle activity recognition events from HAL.
|
||||
*/
|
||||
static void activity_callback(
|
||||
const activity_recognition_callback_procs_t* procs,
|
||||
const activity_event_t* events,
|
||||
int count) {
|
||||
if (sOnActivityChanged == NULL) {
|
||||
ALOGE("Dropping activity_callback because onActivityChanged handler is null.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (events == NULL || count <= 0) {
|
||||
ALOGE("Invalid activity_callback. Count: %d, Events: %p", count, events);
|
||||
return;
|
||||
}
|
||||
|
||||
JNIEnv* env = NULL;
|
||||
int result = attach_thread(&env);
|
||||
if (result != JNI_OK) {
|
||||
return;
|
||||
}
|
||||
|
||||
jclass event_class =
|
||||
env->FindClass("android/hardware/location/ActivityRecognitionHardware$Event");
|
||||
jmethodID event_ctor = env->GetMethodID(event_class, "<init>", "()V");
|
||||
jfieldID activity_field = env->GetFieldID(event_class, "activity", "I");
|
||||
jfieldID type_field = env->GetFieldID(event_class, "type", "I");
|
||||
jfieldID timestamp_field = env->GetFieldID(event_class, "timestamp", "J");
|
||||
|
||||
jobjectArray events_array = env->NewObjectArray(count, event_class, NULL);
|
||||
for (int i = 0; i < count; ++i) {
|
||||
const activity_event_t* event = &events[i];
|
||||
jobject event_object = env->NewObject(event_class, event_ctor);
|
||||
env->SetIntField(event_object, activity_field, event->activity);
|
||||
env->SetIntField(event_object, type_field, event->event_type);
|
||||
env->SetLongField(event_object, timestamp_field, event->timestamp);
|
||||
env->SetObjectArrayElement(events_array, i, event_object);
|
||||
env->DeleteLocalRef(event_object);
|
||||
}
|
||||
|
||||
env->CallVoidMethod(sCallbacksObject, sOnActivityChanged, events_array);
|
||||
check_and_clear_exceptions(env, __FUNCTION__);
|
||||
|
||||
// TODO: ideally we'd let the HAL register the callback thread only once
|
||||
detach_thread();
|
||||
}
|
||||
|
||||
activity_recognition_callback_procs_t sCallbacks {
|
||||
activity_callback,
|
||||
};
|
||||
|
||||
/**
|
||||
* Initializes the ActivityRecognitionHardware class from the native side.
|
||||
*/
|
||||
static void class_init(JNIEnv* env, jclass clazz) {
|
||||
// open the hardware module
|
||||
int error = hw_get_module(
|
||||
ACTIVITY_RECOGNITION_HARDWARE_MODULE_ID,
|
||||
(const hw_module_t**) &sModule);
|
||||
if (error != 0) {
|
||||
ALOGE("Error hw_get_module: %d", error);
|
||||
return;
|
||||
}
|
||||
|
||||
error = activity_recognition_open(&sModule->common, &sDevice);
|
||||
if (error != 0) {
|
||||
ALOGE("Error opening device: %d", error);
|
||||
return;
|
||||
}
|
||||
|
||||
// get references to the Java provided methods
|
||||
sOnActivityChanged = env->GetMethodID(
|
||||
clazz,
|
||||
"onActivityChanged",
|
||||
"([Landroid/hardware/location/ActivityRecognitionHardware$Event;)V");
|
||||
if (sOnActivityChanged == NULL) {
|
||||
ALOGE("Error obtaining ActivityChanged callback.");
|
||||
return;
|
||||
}
|
||||
|
||||
// register callbacks
|
||||
sDevice->register_activity_callback(sDevice, &sCallbacks);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes and connect the callbacks handlers in the HAL.
|
||||
*/
|
||||
static void initialize(JNIEnv* env, jobject obj) {
|
||||
if (sCallbacksObject == NULL) {
|
||||
sCallbacksObject = env->NewGlobalRef(obj);
|
||||
} else {
|
||||
ALOGD("Callbacks Object was already initialized.");
|
||||
}
|
||||
|
||||
if (sDevice != NULL) {
|
||||
sDevice->register_activity_callback(sDevice, &sCallbacks);
|
||||
} else {
|
||||
ALOGD("ActivityRecognition device not found during initialization.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* De-initializes the ActivityRecognitionHardware from the native side.
|
||||
*/
|
||||
static void release(JNIEnv* env, jobject obj) {
|
||||
if (sDevice == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
int error = activity_recognition_close(sDevice);
|
||||
if (error != 0) {
|
||||
ALOGE("Error closing device: %d", error);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if ActivityRecognition HAL is supported, false otherwise.
|
||||
*/
|
||||
static jboolean is_supported(JNIEnv* env, jclass clazz) {
|
||||
if (sModule != NULL && sDevice != NULL ) {
|
||||
return JNI_TRUE;
|
||||
}
|
||||
return JNI_FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an array representing the supported activities.
|
||||
*/
|
||||
static jobjectArray get_supported_activities(JNIEnv* env, jobject obj) {
|
||||
if (sModule == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char const* const* list = NULL;
|
||||
int list_size = sModule->get_supported_activities_list(sModule, &list);
|
||||
if (list_size <= 0 || list == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
jclass string_class = env->FindClass("java/lang/String;");
|
||||
if (string_class == NULL) {
|
||||
ALOGE("Unable to find String class for supported activities.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
jobjectArray string_array = env->NewObjectArray(list_size, string_class, NULL);
|
||||
if (string_array == NULL) {
|
||||
ALOGE("Unable to create string array for supported activities.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (int i = 0; i < list_size; ++i) {
|
||||
const char* string_ptr = const_cast<const char*>(list[i]);
|
||||
jsize string_length = strlen(string_ptr);
|
||||
jstring string = env->NewString((const jchar*) string_ptr, string_length);
|
||||
env->SetObjectArrayElement(string_array, i, string);
|
||||
|
||||
// log debugging information in case we need to try to trace issues with the strings
|
||||
if (string_length) {
|
||||
ALOGD("Invalid activity (index=%d) name size: %d", i, string_length);
|
||||
}
|
||||
}
|
||||
|
||||
return string_array;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables a given activity event to be actively monitored.
|
||||
*/
|
||||
static int enable_activity_event(
|
||||
JNIEnv* env,
|
||||
jobject obj,
|
||||
jint activity_handle,
|
||||
jint event_type,
|
||||
jlong report_latency_ns) {
|
||||
return sDevice->enable_activity_event(
|
||||
sDevice,
|
||||
(uint32_t) activity_handle,
|
||||
(uint32_t) event_type,
|
||||
report_latency_ns);
|
||||
}
|
||||
|
||||
/**
|
||||
* Disables a given activity event from being actively monitored.
|
||||
*/
|
||||
static int disable_activity_event(
|
||||
JNIEnv* env,
|
||||
jobject obj,
|
||||
jint activity_handle,
|
||||
jint event_type) {
|
||||
return sDevice->disable_activity_event(
|
||||
sDevice,
|
||||
(uint32_t) activity_handle,
|
||||
(uint32_t) event_type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Request flush for al batch buffers.
|
||||
*/
|
||||
static int flush(JNIEnv* env, jobject obj) {
|
||||
return sDevice->flush(sDevice);
|
||||
}
|
||||
|
||||
|
||||
static JNINativeMethod sMethods[] = {
|
||||
// {"name", "signature", (void*) functionPointer },
|
||||
{ "nativeClassInit", "()V", (void*) class_init },
|
||||
{ "nativeInitialize", "()V", (void*) initialize },
|
||||
{ "nativeRelease", "()V", (void*) release },
|
||||
{ "nativeIsSupported", "()Z", (void*) is_supported },
|
||||
{ "nativeGetSupportedActivities", "()[Ljava/lang/String;", (void*) get_supported_activities },
|
||||
{ "nativeEnableActivityEvent", "(IIJ)I", (void*) enable_activity_event },
|
||||
{ "nativeDisableActivityEvent", "(II)I", (void*) disable_activity_event },
|
||||
{ "nativeFlush", "()I", (void*) flush },
|
||||
};
|
||||
|
||||
/**
|
||||
* Registration method invoked in JNI load.
|
||||
*/
|
||||
int register_android_hardware_location_ActivityRecognitionHardware(JNIEnv* env) {
|
||||
return jniRegisterNativeMethods(
|
||||
env,
|
||||
"android/hardware/location/ActivityRecognitionHardware",
|
||||
sMethods,
|
||||
NELEM(sMethods));
|
||||
}
|
||||
@@ -835,6 +835,19 @@
|
||||
config_enableGeofenceOverlay is false. -->
|
||||
<string name="config_geofenceProviderPackageName" translatable="false">@null</string>
|
||||
|
||||
<!-- Whether to enable Hardware Activity-Recognition overlay which allows Hardware
|
||||
Activity-Recognition to be replaced by an app at run-time. When disabled, only the
|
||||
config_activityRecognitionHardwarePackageName package will be searched for
|
||||
its implementation, otherwise packages whose signature matches the
|
||||
signatures of config_locationProviderPackageNames will be searched, and
|
||||
the service with the highest version number will be picked. Anyone who
|
||||
wants to disable the overlay mechanism can set it to false.
|
||||
-->
|
||||
<bool name="config_enableActivityRecognitionHardwareOverlay" translatable="false">true</bool>
|
||||
<!-- Package name providing Hardware Activity-Recognition API support. Used only when
|
||||
config_enableActivityRecognitionHardwareOverlay is false. -->
|
||||
<string name="config_activityRecognitionHardwarePackageName" translatable="false">@null</string>
|
||||
|
||||
<!-- Package name(s) containing location provider support.
|
||||
These packages can contain services implementing location providers,
|
||||
such as the Geocode Provider, Network Location Provider, and
|
||||
|
||||
@@ -1478,6 +1478,7 @@
|
||||
<java-symbol type="bool" name="config_useAttentionLight" />
|
||||
<java-symbol type="bool" name="config_animateScreenLights" />
|
||||
<java-symbol type="bool" name="config_automatic_brightness_available" />
|
||||
<java-symbol type="bool" name="config_enableActivityRecognitionHardwareOverlay" />
|
||||
<java-symbol type="bool" name="config_enableFusedLocationOverlay" />
|
||||
<java-symbol type="bool" name="config_enableHardwareFlpOverlay" />
|
||||
<java-symbol type="bool" name="config_enableGeocoderOverlay" />
|
||||
@@ -1570,6 +1571,7 @@
|
||||
<java-symbol type="string" name="car_mode_disable_notification_title" />
|
||||
<java-symbol type="string" name="chooser_wallpaper" />
|
||||
<java-symbol type="string" name="config_datause_iface" />
|
||||
<java-symbol type="string" name="config_activityRecognitionHardwarePackageName" />
|
||||
<java-symbol type="string" name="config_fusedLocationProviderPackageName" />
|
||||
<java-symbol type="string" name="config_hardwareFlpPackageName" />
|
||||
<java-symbol type="string" name="config_geocoderProviderPackageName" />
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright (C) 2014 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.location.provider;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
|
||||
import java.security.InvalidParameterException;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* A class representing an event for Activity changes.
|
||||
*/
|
||||
public class ActivityChangedEvent {
|
||||
private final List<ActivityRecognitionEvent> mActivityRecognitionEvents;
|
||||
|
||||
public ActivityChangedEvent(List<ActivityRecognitionEvent> activityRecognitionEvents) {
|
||||
if (activityRecognitionEvents == null) {
|
||||
throw new InvalidParameterException(
|
||||
"Parameter 'activityRecognitionEvents' must not be null.");
|
||||
}
|
||||
|
||||
mActivityRecognitionEvents = activityRecognitionEvents;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public Iterable<ActivityRecognitionEvent> getActivityRecognitionEvents() {
|
||||
return mActivityRecognitionEvents;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright (C) 2014 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.location.provider;
|
||||
|
||||
/**
|
||||
* A class that represents an Activity Recognition Event.
|
||||
*/
|
||||
public class ActivityRecognitionEvent {
|
||||
private final String mActivity;
|
||||
private final int mEventType;
|
||||
private final long mTimestampNs;
|
||||
|
||||
public ActivityRecognitionEvent(String activity, int eventType, long timestampNs) {
|
||||
mActivity = activity;
|
||||
mEventType = eventType;
|
||||
mTimestampNs = timestampNs;
|
||||
}
|
||||
|
||||
public String getActivity() {
|
||||
return mActivity;
|
||||
}
|
||||
|
||||
public int getEventType() {
|
||||
return mEventType;
|
||||
}
|
||||
|
||||
public long getTimestampNs() {
|
||||
return mTimestampNs;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,134 @@
|
||||
/*
|
||||
* Copyright (C) 2014 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.location.provider;
|
||||
|
||||
import com.android.internal.util.Preconditions;
|
||||
|
||||
import android.hardware.location.IActivityRecognitionHardware;
|
||||
import android.hardware.location.IActivityRecognitionHardwareSink;
|
||||
import android.os.RemoteException;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
|
||||
/**
|
||||
* A class that exposes {@link IActivityRecognitionHardware} functionality to unbundled services.
|
||||
*/
|
||||
public final class ActivityRecognitionProvider {
|
||||
private final IActivityRecognitionHardware mService;
|
||||
private final HashSet<Sink> mSinkSet = new HashSet<Sink>();
|
||||
private final SinkTransport mSinkTransport = new SinkTransport();
|
||||
|
||||
// the following constants must remain in sync with activity_recognition.h
|
||||
|
||||
public static final String ACTIVITY_IN_VEHICLE = "android.activity_recognition.in_vehicle";
|
||||
public static final String ACTIVITY_ON_BICYCLE = "android.activity_recognition.on_bicycle";
|
||||
public static final String ACTIVITY_WALKING = "android.activity_recognition.walking";
|
||||
public static final String ACTIVITY_RUNNING = "android.activity_recognition.running";
|
||||
public static final String ACTIVITY_STILL = "android.activity_recognition.still";
|
||||
public static final String ACTIVITY_TILTING = "android.activity_recognition.tilting";
|
||||
|
||||
public static final int EVENT_TYPE_FLUSH_COMPLETE = 0;
|
||||
public static final int EVENT_TYPE_ENTER = 1;
|
||||
public static final int EVENT_TYPE_EXIT = 2;
|
||||
|
||||
// end constants activity_recognition.h
|
||||
|
||||
/**
|
||||
* Used to receive Activity-Recognition events.
|
||||
*/
|
||||
public interface Sink {
|
||||
void onActivityChanged(ActivityChangedEvent event);
|
||||
}
|
||||
|
||||
public ActivityRecognitionProvider(IActivityRecognitionHardware service)
|
||||
throws RemoteException {
|
||||
Preconditions.checkNotNull(service);
|
||||
mService = service;
|
||||
mService.registerSink(mSinkTransport);
|
||||
}
|
||||
|
||||
public String[] getSupportedActivities() throws RemoteException {
|
||||
return mService.getSupportedActivities();
|
||||
}
|
||||
|
||||
public boolean isActivitySupported(String activity) throws RemoteException {
|
||||
return mService.isActivitySupported(activity);
|
||||
}
|
||||
|
||||
public void registerSink(Sink sink) {
|
||||
Preconditions.checkNotNull(sink);
|
||||
synchronized (mSinkSet) {
|
||||
mSinkSet.add(sink);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: if this functionality is exposed to 3rd party developers, handle unregistration (here
|
||||
// and in the service) of all sinks while failing to disable all events
|
||||
public void unregisterSink(Sink sink) {
|
||||
Preconditions.checkNotNull(sink);
|
||||
synchronized (mSinkSet) {
|
||||
mSinkSet.remove(sink);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean enableActivityEvent(String activity, int eventType, long reportLatencyNs)
|
||||
throws RemoteException {
|
||||
return mService.enableActivityEvent(activity, eventType, reportLatencyNs);
|
||||
}
|
||||
|
||||
public boolean disableActivityEvent(String activity, int eventType) throws RemoteException {
|
||||
return mService.disableActivityEvent(activity, eventType);
|
||||
}
|
||||
|
||||
public boolean flush() throws RemoteException {
|
||||
return mService.flush();
|
||||
}
|
||||
|
||||
private final class SinkTransport extends IActivityRecognitionHardwareSink.Stub {
|
||||
@Override
|
||||
public void onActivityChanged(
|
||||
android.hardware.location.ActivityChangedEvent activityChangedEvent) {
|
||||
Collection<Sink> sinks;
|
||||
synchronized (mSinkSet) {
|
||||
if (mSinkSet.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
sinks = new ArrayList<Sink>(mSinkSet);
|
||||
}
|
||||
|
||||
// translate the event from platform internal and GmsCore types
|
||||
ArrayList<ActivityRecognitionEvent> gmsEvents =
|
||||
new ArrayList<ActivityRecognitionEvent>();
|
||||
for (android.hardware.location.ActivityRecognitionEvent event
|
||||
: activityChangedEvent.getActivityRecognitionEvents()) {
|
||||
ActivityRecognitionEvent gmsEvent = new ActivityRecognitionEvent(
|
||||
event.getActivity(),
|
||||
event.getEventType(),
|
||||
event.getTimestampNs());
|
||||
gmsEvents.add(gmsEvent);
|
||||
}
|
||||
ActivityChangedEvent gmsEvent = new ActivityChangedEvent(gmsEvents);
|
||||
|
||||
for (Sink sink : sinks) {
|
||||
sink.onActivityChanged(gmsEvent);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
* Copyright (C) 2014 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.location.provider;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.hardware.location.IActivityRecognitionHardware;
|
||||
import android.hardware.location.IActivityRecognitionHardwareWatcher;
|
||||
import android.os.Binder;
|
||||
import android.os.IBinder;
|
||||
import android.os.Process;
|
||||
import android.os.RemoteException;
|
||||
import android.util.Log;
|
||||
|
||||
/**
|
||||
* A watcher class for Activity-Recognition instances.
|
||||
*/
|
||||
public class ActivityRecognitionProviderWatcher {
|
||||
private static final String TAG = "ActivityRecognitionProviderWatcher";
|
||||
|
||||
private static ActivityRecognitionProviderWatcher sWatcher;
|
||||
private static final Object sWatcherLock = new Object();
|
||||
|
||||
private ActivityRecognitionProvider mActivityRecognitionProvider;
|
||||
|
||||
private ActivityRecognitionProviderWatcher() {}
|
||||
|
||||
public static ActivityRecognitionProviderWatcher getInstance() {
|
||||
synchronized (sWatcherLock) {
|
||||
if (sWatcher == null) {
|
||||
sWatcher = new ActivityRecognitionProviderWatcher();
|
||||
}
|
||||
return sWatcher;
|
||||
}
|
||||
}
|
||||
|
||||
private IActivityRecognitionHardwareWatcher.Stub mWatcherStub =
|
||||
new IActivityRecognitionHardwareWatcher.Stub() {
|
||||
@Override
|
||||
public void onInstanceChanged(IActivityRecognitionHardware instance) {
|
||||
int callingUid = Binder.getCallingUid();
|
||||
if (callingUid != Process.SYSTEM_UID) {
|
||||
Log.d(TAG, "Ignoring calls from non-system server. Uid: " + callingUid);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
mActivityRecognitionProvider = new ActivityRecognitionProvider(instance);
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Error creating Hardware Activity-Recognition", e);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Gets the binder needed to interact with proxy provider in the platform.
|
||||
*/
|
||||
@NonNull
|
||||
public IBinder getBinder() {
|
||||
return mWatcherStub;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an object that supports the functionality of {@link ActivityRecognitionProvider}.
|
||||
*
|
||||
* @return Non-null value if the functionality is supported by the platform, false otherwise.
|
||||
*/
|
||||
@Nullable
|
||||
public ActivityRecognitionProvider getActivityRecognitionProvider() {
|
||||
return mActivityRecognitionProvider;
|
||||
}
|
||||
}
|
||||
@@ -20,6 +20,7 @@ import com.android.internal.content.PackageMonitor;
|
||||
import com.android.internal.location.ProviderProperties;
|
||||
import com.android.internal.location.ProviderRequest;
|
||||
import com.android.internal.os.BackgroundThread;
|
||||
import com.android.server.location.ActivityRecognitionProxy;
|
||||
import com.android.server.location.FlpHardwareProvider;
|
||||
import com.android.server.location.FusedProxy;
|
||||
import com.android.server.location.GeocoderProxy;
|
||||
@@ -53,6 +54,7 @@ import android.content.pm.Signature;
|
||||
import android.content.pm.UserInfo;
|
||||
import android.content.res.Resources;
|
||||
import android.database.ContentObserver;
|
||||
import android.hardware.location.ActivityRecognitionHardware;
|
||||
import android.location.Address;
|
||||
import android.location.Criteria;
|
||||
import android.location.GeocoderParams;
|
||||
@@ -475,7 +477,7 @@ public class LocationManagerService extends ILocationManager.Stub {
|
||||
Slog.e(TAG, "no geocoder provider found");
|
||||
}
|
||||
|
||||
// bind to fused provider if supported
|
||||
// bind to fused hardware provider if supported
|
||||
if (FlpHardwareProvider.isSupported()) {
|
||||
FlpHardwareProvider flpHardwareProvider =
|
||||
FlpHardwareProvider.getInstance(mContext);
|
||||
@@ -505,6 +507,23 @@ public class LocationManagerService extends ILocationManager.Stub {
|
||||
Slog.e(TAG, "FLP HAL not supported.");
|
||||
}
|
||||
|
||||
// bind to the hardware activity recognition if supported
|
||||
if (ActivityRecognitionHardware.isSupported()) {
|
||||
ActivityRecognitionProxy proxy = ActivityRecognitionProxy.createAndBind(
|
||||
mContext,
|
||||
mLocationHandler,
|
||||
ActivityRecognitionHardware.getInstance(mContext),
|
||||
com.android.internal.R.bool.config_enableActivityRecognitionHardwareOverlay,
|
||||
com.android.internal.R.string.config_activityRecognitionHardwarePackageName,
|
||||
com.android.internal.R.array.config_locationProviderPackageNames);
|
||||
|
||||
if (proxy == null) {
|
||||
Slog.e(TAG, "Unable to bind ActivityRecognitionProxy.");
|
||||
}
|
||||
} else {
|
||||
Slog.e(TAG, "Hardware Activity-Recognition not supported.");
|
||||
}
|
||||
|
||||
String[] testProviderStrings = resources.getStringArray(
|
||||
com.android.internal.R.array.config_testLocationProviders);
|
||||
for (String testProviderString : testProviderStrings) {
|
||||
|
||||
@@ -0,0 +1,111 @@
|
||||
/*
|
||||
* Copyright (C) 2014 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.server.location;
|
||||
|
||||
import com.android.server.ServiceWatcher;
|
||||
|
||||
import android.content.Context;
|
||||
import android.hardware.location.ActivityRecognitionHardware;
|
||||
import android.hardware.location.IActivityRecognitionHardwareWatcher;
|
||||
import android.os.Handler;
|
||||
import android.os.RemoteException;
|
||||
import android.util.Log;
|
||||
|
||||
/**
|
||||
* Proxy class to bind GmsCore to the ActivityRecognitionHardware.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public class ActivityRecognitionProxy {
|
||||
private final String TAG = "ActivityRecognitionProxy";
|
||||
private final ServiceWatcher mServiceWatcher;
|
||||
private final ActivityRecognitionHardware mActivityRecognitionHardware;
|
||||
|
||||
private ActivityRecognitionProxy(
|
||||
Context context,
|
||||
Handler handler,
|
||||
ActivityRecognitionHardware activityRecognitionHardware,
|
||||
int overlaySwitchResId,
|
||||
int defaultServicePackageNameResId,
|
||||
int initialPackageNameResId) {
|
||||
mActivityRecognitionHardware = activityRecognitionHardware;
|
||||
|
||||
Runnable newServiceWork = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
bindProvider(mActivityRecognitionHardware);
|
||||
}
|
||||
};
|
||||
|
||||
// prepare the connection to the provider
|
||||
mServiceWatcher = new ServiceWatcher(
|
||||
context,
|
||||
TAG,
|
||||
"com.android.location.service.ActivityRecognitionProvider",
|
||||
overlaySwitchResId,
|
||||
defaultServicePackageNameResId,
|
||||
initialPackageNameResId,
|
||||
newServiceWork,
|
||||
handler);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an instance of the proxy and binds it to the appropriate FusedProvider.
|
||||
*
|
||||
* @return An instance of the proxy if it could be bound, null otherwise.
|
||||
*/
|
||||
public static ActivityRecognitionProxy createAndBind(
|
||||
Context context,
|
||||
Handler handler,
|
||||
ActivityRecognitionHardware activityRecognitionHardware,
|
||||
int overlaySwitchResId,
|
||||
int defaultServicePackageNameResId,
|
||||
int initialPackageNameResId) {
|
||||
ActivityRecognitionProxy activityRecognitionProxy = new ActivityRecognitionProxy(
|
||||
context,
|
||||
handler,
|
||||
activityRecognitionHardware,
|
||||
overlaySwitchResId,
|
||||
defaultServicePackageNameResId,
|
||||
initialPackageNameResId);
|
||||
|
||||
// try to bind the provider
|
||||
if (!activityRecognitionProxy.mServiceWatcher.start()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return activityRecognitionProxy;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to bind the FusedLocationHardware to the appropriate FusedProvider instance.
|
||||
*/
|
||||
private void bindProvider(ActivityRecognitionHardware activityRecognitionHardware) {
|
||||
IActivityRecognitionHardwareWatcher watcher =
|
||||
IActivityRecognitionHardwareWatcher.Stub.asInterface(mServiceWatcher.getBinder());
|
||||
if (watcher == null) {
|
||||
Log.e(TAG, "No provider instance found on connection.");
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
watcher.onInstanceChanged(mActivityRecognitionHardware);
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Error delivering hardware interface.", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user