Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 614612ed authored by destradaa's avatar destradaa
Browse files

Disable AR HW when client binder dies.

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
parent 8b86268b
Loading
Loading
Loading
Loading
+66 −13
Original line number Diff line number Diff line
@@ -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(); }

+2 −0
Original line number Diff line number Diff line
@@ -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;