/*
* 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);
}
}
}
}