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<>(); 35 36 // the following constants must remain in sync with activity_recognition.h 37 38 public static final String ACTIVITY_IN_VEHICLE = "android.activity_recognition.in_vehicle"; 39 public static final String ACTIVITY_ON_BICYCLE = "android.activity_recognition.on_bicycle"; 40 public static final String ACTIVITY_WALKING = "android.activity_recognition.walking"; 41 public static final String ACTIVITY_RUNNING = "android.activity_recognition.running"; 42 public static final String ACTIVITY_STILL = "android.activity_recognition.still"; 43 public static final String ACTIVITY_TILTING = "android.activity_recognition.tilting"; 44 45 // NOTE: when adding an additional EVENT_TYPE_, EVENT_TYPE_COUNT needs to be updated in 46 // android.hardware.location.ActivityRecognitionHardware 47 public static final int EVENT_TYPE_FLUSH_COMPLETE = 0; 48 public static final int EVENT_TYPE_ENTER = 1; 49 public static final int EVENT_TYPE_EXIT = 2; 50 51 // end constants activity_recognition.h 52 53 /** 54 * Used to receive Activity-Recognition events. 55 */ 56 public interface Sink { 57 void onActivityChanged(ActivityChangedEvent event); 58 } 59 60 public ActivityRecognitionProvider(IActivityRecognitionHardware service) 61 throws RemoteException { 62 Preconditions.checkNotNull(service); 63 mService = service; 64 mService.registerSink(new SinkTransport()); 65 } 66 67 public String[] getSupportedActivities() throws RemoteException { 68 return mService.getSupportedActivities(); 69 } 70 71 public boolean isActivitySupported(String activity) throws RemoteException { 72 return mService.isActivitySupported(activity); 73 } 74 75 public void registerSink(Sink sink) { 76 Preconditions.checkNotNull(sink); 77 synchronized (mSinkSet) { 78 mSinkSet.add(sink); 79 } 80 } 81 82 // TODO: if this functionality is exposed to 3rd party developers, handle unregistration (here 83 // and in the service) of all sinks while failing to disable all events 84 public void unregisterSink(Sink sink) { 85 Preconditions.checkNotNull(sink); 86 synchronized (mSinkSet) { 87 mSinkSet.remove(sink); 88 } 89 } 90 91 public boolean enableActivityEvent(String activity, int eventType, long reportLatencyNs) 92 throws RemoteException { 93 return mService.enableActivityEvent(activity, eventType, reportLatencyNs); 94 } 95 96 public boolean disableActivityEvent(String activity, int eventType) throws RemoteException { 97 return mService.disableActivityEvent(activity, eventType); 98 } 99 100 public boolean flush() throws RemoteException { 101 return mService.flush(); 102 } 103 104 private final class SinkTransport extends IActivityRecognitionHardwareSink.Stub { 105 @Override 106 public void onActivityChanged(android.hardware.location.ActivityChangedEvent event) { 107 Collection<Sink> sinks; 108 synchronized (mSinkSet) { 109 if (mSinkSet.isEmpty()) { 110 return; 111 } 112 sinks = new ArrayList<>(mSinkSet); 113 } 114 115 // translate the event from platform internal and GmsCore types 116 ArrayList<ActivityRecognitionEvent> gmsEvents = new ArrayList<>(); 117 for (android.hardware.location.ActivityRecognitionEvent reportingEvent 118 : event.getActivityRecognitionEvents()) { 119 ActivityRecognitionEvent gmsEvent = new ActivityRecognitionEvent( 120 reportingEvent.getActivity(), 121 reportingEvent.getEventType(), 122 reportingEvent.getTimestampNs()); 123 gmsEvents.add(gmsEvent); 124 } 125 ActivityChangedEvent gmsEvent = new ActivityChangedEvent(gmsEvents); 126 127 for (Sink sink : sinks) { 128 sink.onActivityChanged(gmsEvent); 129 } 130 } 131 } 132} 133