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

Commit ebfa3e79 authored by Vladimir Komsiyski's avatar Vladimir Komsiyski Committed by Android (Google) Code Review
Browse files

Merge "API for listening for automated apps." into main

parents 943dd43b 3b9de3e2
Loading
Loading
Loading
Loading
+11 −0
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@ import android.companion.virtual.IVirtualDeviceSoundEffectListener;
import android.companion.virtual.VirtualDevice;
import android.companion.virtual.VirtualDeviceParams;
import android.companion.virtual.computercontrol.ComputerControlSessionParams;
import android.companion.virtual.computercontrol.IAutomatedPackageListener;
import android.companion.virtual.computercontrol.IComputerControlSessionCallback;
import android.content.AttributionSource;

@@ -80,6 +81,16 @@ interface IVirtualDeviceManager {
     */
    void unregisterVirtualDeviceListener(in IVirtualDeviceListener listener);

    /**
     * Registers a listener to receive notifications for automated packages.
     */
    void registerAutomatedPackageListener(in IAutomatedPackageListener listener);

    /**
     * Unregisters a previously registered listener.
     */
    void unregisterAutomatedPackageListener(in IAutomatedPackageListener listener);

    /**
     * Returns the ID of the device which owns the display with the given ID.
     */
+91 −0
Original line number Diff line number Diff line
@@ -34,13 +34,16 @@ import android.annotation.SystemService;
import android.annotation.TestApi;
import android.annotation.UserIdInt;
import android.app.PendingIntent;
import android.app.role.RoleManager;
import android.companion.AssociationInfo;
import android.companion.virtual.audio.VirtualAudioDevice;
import android.companion.virtual.audio.VirtualAudioDevice.AudioConfigurationChangeCallback;
import android.companion.virtual.camera.VirtualCamera;
import android.companion.virtual.camera.VirtualCameraConfig;
import android.companion.virtual.computercontrol.AutomatedPackageListener;
import android.companion.virtual.computercontrol.ComputerControlSession;
import android.companion.virtual.computercontrol.ComputerControlSessionParams;
import android.companion.virtual.computercontrol.IAutomatedPackageListener;
import android.companion.virtual.computercontrol.IComputerControlSessionCallback;
import android.companion.virtual.sensor.VirtualSensor;
import android.companion.virtualdevice.flags.Flags;
@@ -186,6 +189,10 @@ public final class VirtualDeviceManager {
    @GuardedBy("mVirtualDeviceListeners")
    private final List<VirtualDeviceListenerDelegate> mVirtualDeviceListeners = new ArrayList<>();

    @GuardedBy("mAutomatedPackageListeners")
    private final List<AutomatedPackageListenerDelegate> mAutomatedPackageListeners =
            new ArrayList<>();

    /** @hide */
    public VirtualDeviceManager(
            @Nullable IVirtualDeviceManager service, @NonNull Context context) {
@@ -365,6 +372,66 @@ public final class VirtualDeviceManager {
        }
    }

    /**
     * Registers a listener to receive notifications when the set of automated apps changes.
     *
     * @param executor The executor where the listener is executed on.
     * @param listener The listener to add.
     * @throws SecurityException if the caller does not hold the {@link RoleManager#ROLE_HOME} role.
     * @see #unregisterAutomatedPackageListener
     * @hide
     */
    public void registerAutomatedPackageListener(
            @NonNull @CallbackExecutor Executor executor,
            @NonNull AutomatedPackageListener listener) {
        if (mService == null) {
            Log.w(TAG, "Failed to register listener; no virtual device manager service.");
            return;
        }
        final AutomatedPackageListenerDelegate delegate =
                new AutomatedPackageListenerDelegate(Objects.requireNonNull(executor),
                        Objects.requireNonNull(listener));
        synchronized (mAutomatedPackageListeners) {
            try {
                mService.registerAutomatedPackageListener(delegate);
            } catch (RemoteException e) {
                throw e.rethrowFromSystemServer();
            }
            mAutomatedPackageListeners.add(delegate);
        }
    }

    /**
     * Unregisters a listener previously registered with {@link #registerAutomatedPackageListener}.
     *
     * @param listener The listener to unregister.
     * @throws SecurityException if the caller does not hold the {@link RoleManager#ROLE_HOME} role.
     * @see #registerAutomatedPackageListener
     * @hide
     */
    public void unregisterAutomatedPackageListener(@NonNull AutomatedPackageListener listener) {
        if (mService == null) {
            Log.w(TAG, "Failed to unregister listener; no virtual device manager service.");
            return;
        }
        Objects.requireNonNull(listener);
        synchronized (mAutomatedPackageListeners) {
            final Iterator<AutomatedPackageListenerDelegate> it =
                    mAutomatedPackageListeners.iterator();
            while (it.hasNext()) {
                final AutomatedPackageListenerDelegate delegate = it.next();
                if (delegate.mListener == listener) {
                    try {
                        mService.unregisterAutomatedPackageListener(delegate);
                    } catch (RemoteException e) {
                        throw e.rethrowFromSystemServer();
                    }
                    it.remove();
                }
            }
        }
    }

    /**
     * Returns the device policy for the given virtual device and policy type.
     *
@@ -1482,4 +1549,28 @@ public final class VirtualDeviceManager {
            }
        }
    }

    /**
     * A wrapper for {@link AutomatedPackageListener} that executes callbacks on the given executor.
     */
    private static class AutomatedPackageListenerDelegate extends IAutomatedPackageListener.Stub {
        private final AutomatedPackageListener mListener;
        private final Executor mExecutor;

        private AutomatedPackageListenerDelegate(
                Executor executor, AutomatedPackageListener listener) {
            mExecutor = executor;
            mListener = listener;
        }

        @Override
        public void onAutomatedPackagesChanged(
                @NonNull String automatingPackage,
                @NonNull List<String> automatedPackages,
                @NonNull UserHandle user) {
            Binder.withCleanCallingIdentity(() ->
                    mExecutor.execute(() -> mListener.onAutomatedPackagesChanged(
                            automatingPackage, automatedPackages, user)));
        }
    }
}
+45 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2025 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.companion.virtual.computercontrol;

import android.annotation.NonNull;
import android.os.UserHandle;

import java.util.List;

/**
 * Listener to get notified when the packages being automated within a
 * {@link ComputerControlSession} changes.
 *
 * @hide
 */
// TODO(b/442624418): Move to LauncherApps.Callback
public interface AutomatedPackageListener {
    /**
     * Called when the set of automated packages for a specific user and session owner has changed.
     *
     * @param automatingPackage The name of the package that owns the {@link ComputerControlSession}
     * @param automatedPackages The names of the packages that are being automated. May be empty,
     *   indicating that automation has stopped for all previously automated packages for this
     *   session owner and user.
     * @param user The UserHandle of the profile of the automated packages.
     */
    void onAutomatedPackagesChanged(
            @NonNull String automatingPackage,
            @NonNull List<String> automatedPackages,
            @NonNull UserHandle user);
}
+33 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2025 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.companion.virtual.computercontrol;

import android.os.UserHandle;

/**
 * Listener to get notified when automated packages change.
 *
 * @hide
 */
oneway interface IAutomatedPackageListener {

    /** Called when the set of automated packages has changed. */
    void onAutomatedPackagesChanged(
            in String automatingPackage,
            in List<String> automatedPackages,
            in UserHandle user);
}
 No newline at end of file
+43 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2025 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.extensions.computercontrol;

import android.os.UserHandle;

import androidx.annotation.NonNull;

import java.util.List;

/**
 * Listener to get notified when the packages being automated within a
 * {@link ComputerControlSession} changes.
 */
public interface AutomatedPackageListener {
    /**
     * Called when the set of automated packages for a specific user and session owner has changed.
     *
     * @param automatingPackage The name of the package that owns the {@link ComputerControlSession}
     * @param automatedPackages The names of the packages that are being automated. May be empty,
     *   indicating that automation has stopped for all previously automated packages for this
     *   session owner and user.
     * @param user The UserHandle of the profile of the automated packages.
     */
    void onAutomatedPackagesChanged(
            @NonNull String automatingPackage,
            @NonNull List<String> automatedPackages,
            @NonNull UserHandle user);
}
Loading