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

Commit 8e4bb10c authored by Tom Chan's avatar Tom Chan Committed by Android (Google) Code Review
Browse files

Merge "Restart WearableSensingService process before sending connection" into main

parents d64d3c6a 1d8b88f0
Loading
Loading
Loading
Loading
+4 −3
Original line number Diff line number Diff line
@@ -206,9 +206,10 @@ public class WearableSensingManager {
     * and kill the WearableSensingService process.
     *
     * <p>Before providing the secureWearableConnection, the system will restart the
     * WearableSensingService process. Other method calls into WearableSensingService may be dropped
     * during the restart. The caller is responsible for ensuring other method calls are queued
     * until a success status is returned from the {@code statusConsumer}.
     * WearableSensingService process if it has not been restarted since the last
     * secureWearableConnection was provided. Other method calls into WearableSensingService may be
     * dropped during the restart. The caller is responsible for ensuring other method calls are
     * queued until a success status is returned from the {@code statusConsumer}.
     *
     * @param wearableConnection The connection to provide
     * @param executor Executor on which to run the consumer callback
+1 −0
Original line number Diff line number Diff line
@@ -37,4 +37,5 @@ oneway interface IWearableSensingService {
            in RemoteCallback detectionResultCallback, in RemoteCallback statusCallback);
    void stopDetection(in String packageName);
    void queryServiceStatus(in int[] eventTypes, in String packageName, in RemoteCallback callback);
    void killProcess();
}
 No newline at end of file
+8 −0
Original line number Diff line number Diff line
@@ -32,6 +32,7 @@ import android.os.Bundle;
import android.os.IBinder;
import android.os.ParcelFileDescriptor;
import android.os.PersistableBundle;
import android.os.Process;
import android.os.RemoteCallback;
import android.os.SharedMemory;
import android.service.ambientcontext.AmbientContextDetectionResult;
@@ -242,6 +243,13 @@ public abstract class WearableSensingService extends Service {
                    WearableSensingService.this.onQueryServiceStatus(
                            new HashSet<>(Arrays.asList(events)), packageName, consumer);
                }

                /** {@inheritDoc} */
                @Override
                public void killProcess() {
                    Slog.d(TAG, "#killProcess");
                    Process.killProcess(Process.myPid());
                }
            };
        }
        Slog.w(TAG, "Incorrect service interface, returning null.");
+102 −11
Original line number Diff line number Diff line
@@ -19,6 +19,8 @@ package com.android.server.wearable;
import static android.content.Context.BIND_FOREGROUND_SERVICE;
import static android.content.Context.BIND_INCLUDE_CAPABILITIES;

import android.app.wearable.Flags;
import android.app.wearable.WearableSensingManager;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
@@ -30,6 +32,7 @@ import android.service.wearable.IWearableSensingService;
import android.service.wearable.WearableSensingService;
import android.util.Slog;

import com.android.internal.annotations.GuardedBy;
import com.android.internal.infra.ServiceConnector;

import java.io.IOException;
@@ -40,6 +43,17 @@ final class RemoteWearableSensingService extends ServiceConnector.Impl<IWearable
            com.android.server.wearable.RemoteWearableSensingService.class.getSimpleName();
    private final static boolean DEBUG = false;

    private final Object mSecureWearableConnectionLock = new Object();

    // mNextSecureWearableConnectionContext will only be non-null when we are waiting for the
    // WearableSensingService process to restart. It will be set to null after it is passed into
    // WearableSensingService.
    @GuardedBy("mSecureWearableConnectionLock")
    private SecureWearableConnectionContext mNextSecureWearableConnectionContext;

    @GuardedBy("mSecureWearableConnectionLock")
    private boolean mSecureWearableConnectionProvided = false;

    RemoteWearableSensingService(Context context, ComponentName serviceName,
            int userId) {
        super(context, new Intent(
@@ -66,11 +80,55 @@ final class RemoteWearableSensingService extends ServiceConnector.Impl<IWearable
    public void provideSecureWearableConnection(
            ParcelFileDescriptor secureWearableConnection, RemoteCallback callback) {
        if (DEBUG) {
            Slog.i(TAG, "Providing secure wearable connection.");
            Slog.i(TAG, "#provideSecureWearableConnection");
        }
        var unused = post(
        if (!Flags.enableRestartWssProcess()) {
            Slog.d(
                    TAG,
                    "FLAG_ENABLE_RESTART_WSS_PROCESS is disabled. Do not attempt to restart the"
                        + " WearableSensingService process");
            provideSecureWearableConnectionInternal(secureWearableConnection, callback);
            return;
        }
        synchronized (mSecureWearableConnectionLock) {
            if (mNextSecureWearableConnectionContext != null) {
                // A process restart is in progress, #binderDied is about to be called. Replace
                // the previous mNextSecureWearableConnectionContext with the current one
                Slog.i(
                        TAG,
                        "A new wearable connection is provided before the process restart triggered"
                            + " by the previous connection is complete. Discarding the previous"
                            + " connection.");
                if (Flags.enableProvideWearableConnectionApi()) {
                    WearableSensingManagerPerUserService.notifyStatusCallback(
                            mNextSecureWearableConnectionContext.mStatusCallback,
                            WearableSensingManager.STATUS_CHANNEL_ERROR);
                }
                mNextSecureWearableConnectionContext =
                        new SecureWearableConnectionContext(secureWearableConnection, callback);
                return;
            }
            if (!mSecureWearableConnectionProvided) {
                // no need to kill the process
                provideSecureWearableConnectionInternal(secureWearableConnection, callback);
                mSecureWearableConnectionProvided = true;
                return;
            }
            mNextSecureWearableConnectionContext =
                    new SecureWearableConnectionContext(secureWearableConnection, callback);
            // Killing the process causes the binder to die. #binderDied will then be triggered
            killWearableSensingServiceProcess();
        }
    }

    private void provideSecureWearableConnectionInternal(
            ParcelFileDescriptor secureWearableConnection, RemoteCallback callback) {
        Slog.d(TAG, "Providing secure wearable connection.");
        var unused =
                post(
                        service -> {
                    service.provideSecureWearableConnection(secureWearableConnection, callback);
                            service.provideSecureWearableConnection(
                                    secureWearableConnection, callback);
                            try {
                                // close the local fd after it has been sent to the WSS process
                                secureWearableConnection.close();
@@ -80,6 +138,28 @@ final class RemoteWearableSensingService extends ServiceConnector.Impl<IWearable
                        });
    }

    @Override
    public void binderDied() {
        super.binderDied();
        synchronized (mSecureWearableConnectionLock) {
            if (mNextSecureWearableConnectionContext != null) {
                // This will call #post, which will recreate the process and bind to it
                provideSecureWearableConnectionInternal(
                        mNextSecureWearableConnectionContext.mSecureWearableConnection,
                        mNextSecureWearableConnectionContext.mStatusCallback);
                mNextSecureWearableConnectionContext = null;
            } else {
                mSecureWearableConnectionProvided = false;
                Slog.w(TAG, "Binder died but there is no secure wearable connection to provide.");
            }
        }
    }

    /** Kills the WearableSensingService process. */
    public void killWearableSensingServiceProcess() {
        var unused = post(service -> service.killProcess());
    }

    /**
     * Provides the implementation a data stream to the wearable.
     *
@@ -176,4 +256,15 @@ final class RemoteWearableSensingService extends ServiceConnector.Impl<IWearable
                                        packageName,
                                        statusCallback));
    }

    private static class SecureWearableConnectionContext {
        final ParcelFileDescriptor mSecureWearableConnection;
        final RemoteCallback mStatusCallback;

        SecureWearableConnectionContext(
                ParcelFileDescriptor secureWearableConnection, RemoteCallback statusCallback) {
            this.mSecureWearableConnection = secureWearableConnection;
            this.mStatusCallback = statusCallback;
        }
    }
}
+16 −5
Original line number Diff line number Diff line
@@ -44,6 +44,7 @@ import com.android.server.infra.AbstractPerUserSystemService;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.concurrent.atomic.AtomicReference;

/**
 * Per-user manager service for managing sensing {@link AmbientContextEvent}s on Wearables.
@@ -68,7 +69,7 @@ final class WearableSensingManagerPerUserService extends
        super(master, lock, userId);
    }

    static void notifyStatusCallback(RemoteCallback statusCallback, int statusCode) {
    public static void notifyStatusCallback(RemoteCallback statusCallback, int statusCode) {
        Bundle bundle = new Bundle();
        bundle.putInt(
                WearableSensingManager.STATUS_RESPONSE_BUNDLE_KEY, statusCode);
@@ -183,11 +184,11 @@ final class WearableSensingManagerPerUserService extends
        }
        synchronized (mSecureChannelLock) {
            if (mSecureChannel != null) {
                // TODO(b/321012559): Kill the WearableSensingService process if it has not been
                // killed from onError
                mSecureChannel.close();
            }
            try {
                final AtomicReference<WearableSensingSecureChannel> currentSecureChannelRef =
                        new AtomicReference<>();
                mSecureChannel =
                        WearableSensingSecureChannel.create(
                                getContext().getSystemService(CompanionDeviceManager.class),
@@ -206,8 +207,17 @@ final class WearableSensingManagerPerUserService extends

                                    @Override
                                    public void onError() {
                                        // TODO(b/321012559): Kill the WearableSensingService
                                        // process if mSecureChannel has not been reassigned
                                        if (Flags.enableRestartWssProcess()) {
                                            synchronized (mSecureChannelLock) {
                                                if (mSecureChannel != null
                                                        && mSecureChannel
                                                                == currentSecureChannelRef.get()) {
                                                    mRemoteService
                                                            .killWearableSensingServiceProcess();
                                                    mSecureChannel = null;
                                                }
                                            }
                                        }
                                        if (Flags.enableProvideWearableConnectionApi()) {
                                            notifyStatusCallback(
                                                    callback,
@@ -215,6 +225,7 @@ final class WearableSensingManagerPerUserService extends
                                        }
                                    }
                                });
                currentSecureChannelRef.set(mSecureChannel);
            } catch (IOException ex) {
                Slog.e(TAG, "Unable to create the secure channel.", ex);
                if (Flags.enableProvideWearableConnectionApi()) {