OSDN Git Service

Disable AR HW when client binder dies.
authordestradaa <destradaa@google.com>
Mon, 24 Aug 2015 17:41:53 +0000 (10:41 -0700)
committerdestradaa <destradaa@google.com>
Mon, 24 Aug 2015 18:02:52 +0000 (11:02 -0700)
Ensure that activities are unregistered from AR HW when the client's
binder dies. This clean up is required to prevent AR HW to keep active
when there are no clients listening for events.

Bug: 19894637
Change-Id: Iccd609cf1d2d4a4453c7a96cb8645b61639c3234

core/java/android/hardware/location/ActivityRecognitionHardware.java
location/lib/java/com/android/location/provider/ActivityRecognitionProvider.java

index 5d3953a..8acd1ff 100644 (file)
@@ -30,20 +30,34 @@ import android.util.Log;
  * @hide
  */
 public class ActivityRecognitionHardware extends IActivityRecognitionHardware.Stub {
-    private static final String TAG = "ActivityRecognitionHardware";
+    private static final String TAG = "ActivityRecognitionHW";
+    private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
 
     private static final String HARDWARE_PERMISSION = Manifest.permission.LOCATION_HARDWARE;
+    private static final String ENFORCE_HW_PERMISSION_MESSAGE = "Permission '"
+            + HARDWARE_PERMISSION + "' not granted to access ActivityRecognitionHardware";
+
     private static final int INVALID_ACTIVITY_TYPE = -1;
     private static final int NATIVE_SUCCESS_RESULT = 0;
+    private static final int EVENT_TYPE_DISABLED = 0;
+    private static final int EVENT_TYPE_ENABLED = 1;
+
+    /**
+     * Contains the number of supported Event Types.
+     *
+     * NOTE: increment this counter every time a new EVENT_TYPE_ is added to
+     *       com.android.location.provider.ActivityRecognitionProvider
+     */
+    private static final int EVENT_TYPE_COUNT = 3;
 
-    private static ActivityRecognitionHardware sSingletonInstance = null;
+    private static ActivityRecognitionHardware sSingletonInstance;
     private static final Object sSingletonInstanceLock = new Object();
 
     private final Context mContext;
+    private final int mSupportedActivitiesCount;
     private final String[] mSupportedActivities;
-
-    private final RemoteCallbackList<IActivityRecognitionHardwareSink> mSinks =
-            new RemoteCallbackList<IActivityRecognitionHardwareSink>();
+    private final int[][] mSupportedActivitiesEnabledEvents;
+    private final SinkList mSinks = new SinkList();
 
     private static class Event {
         public int activity;
@@ -56,6 +70,8 @@ public class ActivityRecognitionHardware extends IActivityRecognitionHardware.St
 
         mContext = context;
         mSupportedActivities = fetchSupportedActivities();
+        mSupportedActivitiesCount = mSupportedActivities.length;
+        mSupportedActivitiesEnabledEvents = new int[mSupportedActivitiesCount][EVENT_TYPE_COUNT];
     }
 
     public static ActivityRecognitionHardware getInstance(Context context) {
@@ -107,7 +123,11 @@ public class ActivityRecognitionHardware extends IActivityRecognitionHardware.St
         }
 
         int result = nativeEnableActivityEvent(activityType, eventType, reportLatencyNs);
-        return result == NATIVE_SUCCESS_RESULT;
+        if (result == NATIVE_SUCCESS_RESULT) {
+            mSupportedActivitiesEnabledEvents[activityType][eventType] = EVENT_TYPE_ENABLED;
+            return true;
+        }
+        return false;
     }
 
     @Override
@@ -120,7 +140,11 @@ public class ActivityRecognitionHardware extends IActivityRecognitionHardware.St
         }
 
         int result = nativeDisableActivityEvent(activityType, eventType);
-        return result == NATIVE_SUCCESS_RESULT;
+        if (result == NATIVE_SUCCESS_RESULT) {
+            mSupportedActivitiesEnabledEvents[activityType][eventType] = EVENT_TYPE_DISABLED;
+            return true;
+        }
+        return false;
     }
 
     @Override
@@ -135,7 +159,7 @@ public class ActivityRecognitionHardware extends IActivityRecognitionHardware.St
      */
     private void onActivityChanged(Event[] events) {
         if (events == null || events.length == 0) {
-            Log.d(TAG, "No events to broadcast for onActivityChanged.");
+            if (DEBUG) Log.d(TAG, "No events to broadcast for onActivityChanged.");
             return;
         }
 
@@ -161,7 +185,6 @@ public class ActivityRecognitionHardware extends IActivityRecognitionHardware.St
             }
         }
         mSinks.finishBroadcast();
-
     }
 
     private String getActivityName(int activityType) {
@@ -193,10 +216,7 @@ public class ActivityRecognitionHardware extends IActivityRecognitionHardware.St
     }
 
     private void checkPermissions() {
-        String message = String.format(
-                "Permission '%s' not granted to access ActivityRecognitionHardware",
-                HARDWARE_PERMISSION);
-        mContext.enforceCallingPermission(HARDWARE_PERMISSION, message);
+        mContext.enforceCallingPermission(HARDWARE_PERMISSION, ENFORCE_HW_PERMISSION_MESSAGE);
     }
 
     private String[] fetchSupportedActivities() {
@@ -208,6 +228,39 @@ public class ActivityRecognitionHardware extends IActivityRecognitionHardware.St
         return new String[0];
     }
 
+    private class SinkList extends RemoteCallbackList<IActivityRecognitionHardwareSink> {
+        @Override
+        public void onCallbackDied(IActivityRecognitionHardwareSink callback) {
+            int callbackCount = mSinks.getRegisteredCallbackCount();
+            if (DEBUG) Log.d(TAG, "RegisteredCallbackCount: " + callbackCount);
+            if (callbackCount != 0) {
+                return;
+            }
+            // currently there is only one client for this, so if all its sinks have died, we clean
+            // up after them, this ensures that the AR HAL is not out of sink
+            for (int activity = 0; activity < mSupportedActivitiesCount; ++activity) {
+                for (int event = 0; event < EVENT_TYPE_COUNT; ++event) {
+                    disableActivityEventIfEnabled(activity, event);
+                }
+            }
+        }
+
+        private void disableActivityEventIfEnabled(int activityType, int eventType) {
+            if (mSupportedActivitiesEnabledEvents[activityType][eventType] != EVENT_TYPE_ENABLED) {
+                return;
+            }
+
+            int result = nativeDisableActivityEvent(activityType, eventType);
+            mSupportedActivitiesEnabledEvents[activityType][eventType] = EVENT_TYPE_DISABLED;
+            String message = String.format(
+                    "DisableActivityEvent: activityType=%d, eventType=%d, result=%d",
+                    activityType,
+                    eventType,
+                    result);
+            Log.e(TAG, message);
+        }
+    }
+
     // native bindings
     static { nativeClassInit(); }
 
index da33464..25f9fa2 100644 (file)
@@ -43,6 +43,8 @@ public final class ActivityRecognitionProvider {
     public static final String ACTIVITY_STILL = "android.activity_recognition.still";
     public static final String ACTIVITY_TILTING = "android.activity_recognition.tilting";
 
+    // NOTE: when adding an additional EVENT_TYPE_, EVENT_TYPE_COUNT needs to be updated in
+    // android.hardware.location.ActivityRecognitionHardware
     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;