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

Commit d91289bd authored by Arthur Ishiguro's avatar Arthur Ishiguro
Browse files

Acquire wakelock on endpoint callbacks

Bug: 383556228
Flag: android.chre.flags.offload_implementation
Test: Confirm desired wakelock behavior through dumpsys power
Change-Id: I9190aa06246a815a9373066277f92abe22c997cb
parent a22a5832
Loading
Loading
Loading
Loading
+22 −1
Original line number Original line Diff line number Diff line
@@ -137,6 +137,8 @@ public class HubEndpoint {
                                                serviceDescriptor,
                                                serviceDescriptor,
                                                mLifecycleCallback.onSessionOpenRequest(
                                                mLifecycleCallback.onSessionOpenRequest(
                                                        initiator, serviceDescriptor)));
                                                        initiator, serviceDescriptor)));
                    } else {
                        invokeCallbackFinished();
                    }
                    }
                }
                }


@@ -163,6 +165,8 @@ public class HubEndpoint {
                                        + result.getReason());
                                        + result.getReason());
                        rejectSession(sessionId);
                        rejectSession(sessionId);
                    }
                    }

                    invokeCallbackFinished();
                }
                }


                private void acceptSession(
                private void acceptSession(
@@ -249,7 +253,12 @@ public class HubEndpoint {
                    activeSession.setOpened();
                    activeSession.setOpened();
                    if (mLifecycleCallback != null) {
                    if (mLifecycleCallback != null) {
                        mLifecycleCallbackExecutor.execute(
                        mLifecycleCallbackExecutor.execute(
                                () -> mLifecycleCallback.onSessionOpened(activeSession));
                                () -> {
                                    mLifecycleCallback.onSessionOpened(activeSession);
                                    invokeCallbackFinished();
                                });
                    } else {
                        invokeCallbackFinished();
                    }
                    }
                }
                }


@@ -278,7 +287,10 @@ public class HubEndpoint {
                                    synchronized (mLock) {
                                    synchronized (mLock) {
                                        mActiveSessions.remove(sessionId);
                                        mActiveSessions.remove(sessionId);
                                    }
                                    }
                                    invokeCallbackFinished();
                                });
                                });
                    } else {
                        invokeCallbackFinished();
                    }
                    }
                }
                }


@@ -323,8 +335,17 @@ public class HubEndpoint {
                                        e.rethrowFromSystemServer();
                                        e.rethrowFromSystemServer();
                                    }
                                    }
                                }
                                }
                                invokeCallbackFinished();
                            });
                            });
                }
                }

                private void invokeCallbackFinished() {
                    try {
                        mServiceToken.onCallbackFinished();
                    } catch (RemoteException e) {
                        e.rethrowFromSystemServer();
                    }
                }
            };
            };


    /** Binder returned from system service, non-null while registered. */
    /** Binder returned from system service, non-null while registered. */
+6 −0
Original line number Original line Diff line number Diff line
@@ -94,4 +94,10 @@ interface IContextHubEndpoint {
     */
     */
    @EnforcePermission("ACCESS_CONTEXT_HUB")
    @EnforcePermission("ACCESS_CONTEXT_HUB")
    void sendMessageDeliveryStatus(int sessionId, int messageSeqNumber, byte errorCode);
    void sendMessageDeliveryStatus(int sessionId, int messageSeqNumber, byte errorCode);

    /**
     * Invoked when a callback from IContextHubEndpointCallback finishes.
     */
    @EnforcePermission("ACCESS_CONTEXT_HUB")
    void onCallbackFinished();
}
}
+89 −32
Original line number Original line Diff line number Diff line
@@ -32,7 +32,10 @@ import android.hardware.location.ContextHubTransaction;
import android.hardware.location.IContextHubTransactionCallback;
import android.hardware.location.IContextHubTransactionCallback;
import android.os.Binder;
import android.os.Binder;
import android.os.IBinder;
import android.os.IBinder;
import android.os.PowerManager;
import android.os.PowerManager.WakeLock;
import android.os.RemoteException;
import android.os.RemoteException;
import android.os.WorkSource;
import android.util.Log;
import android.util.Log;
import android.util.SparseArray;
import android.util.SparseArray;


@@ -54,6 +57,16 @@ public class ContextHubEndpointBroker extends IContextHubEndpoint.Stub
    /** Message used by noteOp when this client receives a message from an endpoint. */
    /** Message used by noteOp when this client receives a message from an endpoint. */
    private static final String RECEIVE_MSG_NOTE = "ContextHubEndpointMessageDelivery";
    private static final String RECEIVE_MSG_NOTE = "ContextHubEndpointMessageDelivery";


    /** The duration of wakelocks acquired during HAL callbacks */
    private static final long WAKELOCK_TIMEOUT_MILLIS = 5 * 1000;

    /*
     * Internal interface used to invoke client callbacks.
     */
    interface CallbackConsumer {
        void accept(IContextHubEndpointCallback callback) throws RemoteException;
    }

    /** The context of the service. */
    /** The context of the service. */
    private final Context mContext;
    private final Context mContext;


@@ -134,6 +147,9 @@ public class ContextHubEndpointBroker extends IContextHubEndpoint.Stub


    private final int mUid;
    private final int mUid;


    /** Wakelock held while nanoapp message are in flight to the client */
    private final WakeLock mWakeLock;

    /* package */ ContextHubEndpointBroker(
    /* package */ ContextHubEndpointBroker(
            Context context,
            Context context,
            IEndpointCommunication hubInterface,
            IEndpointCommunication hubInterface,
@@ -158,6 +174,11 @@ public class ContextHubEndpointBroker extends IContextHubEndpoint.Stub


        mAppOpsManager = context.getSystemService(AppOpsManager.class);
        mAppOpsManager = context.getSystemService(AppOpsManager.class);
        mAppOpsManager.startWatchingMode(AppOpsManager.OP_NONE, mPackageName, this);
        mAppOpsManager.startWatchingMode(AppOpsManager.OP_NONE, mPackageName, this);

        PowerManager powerManager = context.getSystemService(PowerManager.class);
        mWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
        mWakeLock.setWorkSource(new WorkSource(mUid, mPackageName));
        mWakeLock.setReferenceCounted(true);
    }
    }


    @Override
    @Override
@@ -302,6 +323,13 @@ public class ContextHubEndpointBroker extends IContextHubEndpoint.Stub
        }
        }
    }
    }


    @Override
    @android.annotation.EnforcePermission(android.Manifest.permission.ACCESS_CONTEXT_HUB)
    public void onCallbackFinished() {
        super.onCallbackFinished_enforcePermission();
        releaseWakeLock();
    }

    /** Invoked when the underlying binder of this broker has died at the client process. */
    /** Invoked when the underlying binder of this broker has died at the client process. */
    @Override
    @Override
    public void binderDied() {
    public void binderDied() {
@@ -357,15 +385,13 @@ public class ContextHubEndpointBroker extends IContextHubEndpoint.Stub
            mSessionInfoMap.put(sessionId, new SessionInfo(initiator, true));
            mSessionInfoMap.put(sessionId, new SessionInfo(initiator, true));
        }
        }


        if (mContextHubEndpointCallback != null) {
        boolean success =
            try {
                invokeCallback(
                mContextHubEndpointCallback.onSessionOpenRequest(
                        (consumer) ->
                        sessionId, initiator, serviceDescriptor);
                                consumer.onSessionOpenRequest(
            } catch (RemoteException e) {
                                        sessionId, initiator, serviceDescriptor));
                Log.e(TAG, "RemoteException while calling onSessionOpenRequest", e);
        if (!success) {
            cleanupSessionResources(sessionId);
            cleanupSessionResources(sessionId);
                return;
            }
        }
        }
    }
    }


@@ -374,14 +400,11 @@ public class ContextHubEndpointBroker extends IContextHubEndpoint.Stub
            Log.w(TAG, "Unknown session ID in onCloseEndpointSession: id=" + sessionId);
            Log.w(TAG, "Unknown session ID in onCloseEndpointSession: id=" + sessionId);
            return;
            return;
        }
        }
        if (mContextHubEndpointCallback != null) {

            try {
        invokeCallback(
                mContextHubEndpointCallback.onSessionClosed(
                (consumer) ->
                        sessionId, ContextHubServiceUtil.toAppHubEndpointReason(reason));
                        consumer.onSessionClosed(
            } catch (RemoteException e) {
                                sessionId, ContextHubServiceUtil.toAppHubEndpointReason(reason)));
                Log.e(TAG, "RemoteException while calling onSessionClosed", e);
            }
        }
    }
    }


    /* package */ void onEndpointSessionOpenComplete(int sessionId) {
    /* package */ void onEndpointSessionOpenComplete(int sessionId) {
@@ -392,13 +415,8 @@ public class ContextHubEndpointBroker extends IContextHubEndpoint.Stub
            }
            }
            mSessionInfoMap.get(sessionId).setSessionState(SessionInfo.SessionState.ACTIVE);
            mSessionInfoMap.get(sessionId).setSessionState(SessionInfo.SessionState.ACTIVE);
        }
        }
        if (mContextHubEndpointCallback != null) {

            try {
        invokeCallback((consumer) -> consumer.onSessionOpenComplete(sessionId));
                mContextHubEndpointCallback.onSessionOpenComplete(sessionId);
            } catch (RemoteException e) {
                Log.e(TAG, "RemoteException while calling onSessionClosed", e);
            }
        }
    }
    }


    /* package */ void onMessageReceived(int sessionId, HubMessage message) {
    /* package */ void onMessageReceived(int sessionId, HubMessage message) {
@@ -440,16 +458,13 @@ public class ContextHubEndpointBroker extends IContextHubEndpoint.Stub
            return;
            return;
        }
        }


        if (mContextHubEndpointCallback != null) {
        boolean success =
            try {
                invokeCallback((consumer) -> consumer.onMessageReceived(sessionId, message));
                mContextHubEndpointCallback.onMessageReceived(sessionId, message);
        if (!success) {
            } catch (RemoteException e) {
                Log.e(TAG, "RemoteException while calling onMessageReceived", e);
            sendMessageDeliveryStatus(
            sendMessageDeliveryStatus(
                    sessionId, message.getMessageSequenceNumber(), ErrorCode.TRANSIENT_ERROR);
                    sessionId, message.getMessageSequenceNumber(), ErrorCode.TRANSIENT_ERROR);
        }
        }
    }
    }
    }


    /* package */ void onMessageDeliveryStatusReceived(
    /* package */ void onMessageDeliveryStatusReceived(
            int sessionId, int sequenceNumber, byte errorCode) {
            int sessionId, int sequenceNumber, byte errorCode) {
@@ -520,4 +535,46 @@ public class ContextHubEndpointBroker extends IContextHubEndpoint.Stub
        Collection<String> requiredPermissions = targetEndpointInfo.getRequiredPermissions();
        Collection<String> requiredPermissions = targetEndpointInfo.getRequiredPermissions();
        return ContextHubServiceUtil.hasPermissions(mContext, mPid, mUid, requiredPermissions);
        return ContextHubServiceUtil.hasPermissions(mContext, mPid, mUid, requiredPermissions);
    }
    }

    private void acquireWakeLock() {
        Binder.withCleanCallingIdentity(
                () -> {
                    if (mIsRegistered.get()) {
                        mWakeLock.acquire(WAKELOCK_TIMEOUT_MILLIS);
                    }
                });
    }

    private void releaseWakeLock() {
        Binder.withCleanCallingIdentity(
                () -> {
                    if (mWakeLock.isHeld()) {
                        try {
                            mWakeLock.release();
                        } catch (RuntimeException e) {
                            Log.e(TAG, "Releasing the wakelock fails - ", e);
                        }
                    }
                });
    }

    /**
     * Invokes a callback and acquires a wakelock.
     *
     * @param consumer The callback invoke
     * @return false if the callback threw a RemoteException
     */
    private boolean invokeCallback(CallbackConsumer consumer) {
        if (mContextHubEndpointCallback != null) {
            acquireWakeLock();
            try {
                consumer.accept(mContextHubEndpointCallback);
            } catch (RemoteException e) {
                Log.e(TAG, "RemoteException while calling endpoint callback", e);
                releaseWakeLock();
                return false;
            }
        }
        return true;
    }
}
}