1/* 2 * Copyright (C) 2014 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License 15 */ 16 17package com.android.location.provider; 18 19import com.android.internal.util.Preconditions; 20 21import android.hardware.location.IActivityRecognitionHardware; 22import android.hardware.location.IActivityRecognitionHardwareSink; 23import android.os.RemoteException; 24 25import java.util.ArrayList; 26import java.util.Collection; 27import java.util.HashSet; 28 29/** 30 * A class that exposes {@link IActivityRecognitionHardware} functionality to unbundled services. 31 */ 32public final class ActivityRecognitionProvider { 33 private final IActivityRecognitionHardware mService; 34 private final HashSet<Sink> mSinkSet = new HashSet<Sink>(); 35 private final SinkTransport mSinkTransport = new SinkTransport(); 36 37 // the following constants must remain in sync with activity_recognition.h 38 39 public static final String ACTIVITY_IN_VEHICLE = "android.activity_recognition.in_vehicle"; 40 public static final String ACTIVITY_ON_BICYCLE = "android.activity_recognition.on_bicycle"; 41 public static final String ACTIVITY_WALKING = "android.activity_recognition.walking"; 42 public static final String ACTIVITY_RUNNING = "android.activity_recognition.running"; 43 public static final String ACTIVITY_STILL = "android.activity_recognition.still"; 44 public static final String ACTIVITY_TILTING = "android.activity_recognition.tilting"; 45 46 public static final int EVENT_TYPE_FLUSH_COMPLETE = 0; 47 public static final int EVENT_TYPE_ENTER = 1; 48 public static final int EVENT_TYPE_EXIT = 2; 49 50 // end constants activity_recognition.h 51 52 /** 53 * Used to receive Activity-Recognition events. 54 */ 55 public interface Sink { 56 void onActivityChanged(ActivityChangedEvent event); 57 } 58 59 public ActivityRecognitionProvider(IActivityRecognitionHardware service) 60 throws RemoteException { 61 Preconditions.checkNotNull(service); 62 mService = service; 63 mService.registerSink(mSinkTransport); 64 } 65 66 public String[] getSupportedActivities() throws RemoteException { 67 return mService.getSupportedActivities(); 68 } 69 70 public boolean isActivitySupported(String activity) throws RemoteException { 71 return mService.isActivitySupported(activity); 72 } 73 74 public void registerSink(Sink sink) { 75 Preconditions.checkNotNull(sink); 76 synchronized (mSinkSet) { 77 mSinkSet.add(sink); 78 } 79 } 80 81 // TODO: if this functionality is exposed to 3rd party developers, handle unregistration (here 82 // and in the service) of all sinks while failing to disable all events 83 public void unregisterSink(Sink sink) { 84 Preconditions.checkNotNull(sink); 85 synchronized (mSinkSet) { 86 mSinkSet.remove(sink); 87 } 88 } 89 90 public boolean enableActivityEvent(String activity, int eventType, long reportLatencyNs) 91 throws RemoteException { 92 return mService.enableActivityEvent(activity, eventType, reportLatencyNs); 93 } 94 95 public boolean disableActivityEvent(String activity, int eventType) throws RemoteException { 96 return mService.disableActivityEvent(activity, eventType); 97 } 98 99 public boolean flush() throws RemoteException { 100 return mService.flush(); 101 } 102 103 private final class SinkTransport extends IActivityRecognitionHardwareSink.Stub { 104 @Override 105 public void onActivityChanged( 106 android.hardware.location.ActivityChangedEvent activityChangedEvent) { 107 Collection<Sink> sinks; 108 synchronized (mSinkSet) { 109 if (mSinkSet.isEmpty()) { 110 return; 111 } 112 113 sinks = new ArrayList<Sink>(mSinkSet); 114 } 115 116 // translate the event from platform internal and GmsCore types 117 ArrayList<ActivityRecognitionEvent> gmsEvents = 118 new ArrayList<ActivityRecognitionEvent>(); 119 for (android.hardware.location.ActivityRecognitionEvent event 120 : activityChangedEvent.getActivityRecognitionEvents()) { 121 ActivityRecognitionEvent gmsEvent = new ActivityRecognitionEvent( 122 event.getActivity(), 123 event.getEventType(), 124 event.getTimestampNs()); 125 gmsEvents.add(gmsEvent); 126 } 127 ActivityChangedEvent gmsEvent = new ActivityChangedEvent(gmsEvents); 128 129 for (Sink sink : sinks) { 130 sink.onActivityChanged(gmsEvent); 131 } 132 } 133 } 134} 135