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

Commit 89e1907b authored by Caitlin Cassidy's avatar Caitlin Cassidy Committed by Android (Google) Code Review
Browse files

Merge "[Nearby Media Devices] Add a SystemApi to get information about nearby...

Merge "[Nearby Media Devices] Add a SystemApi to get information about nearby media devices from external clients."
parents 24292ef4 ba6b756d
Loading
Loading
Loading
Loading
+22 −0
Original line number Diff line number Diff line
@@ -917,8 +917,10 @@ package android.app {
  public class StatusBarManager {
    method @NonNull @RequiresPermission(android.Manifest.permission.STATUS_BAR) public android.app.StatusBarManager.DisableInfo getDisableInfo();
    method @RequiresPermission(android.Manifest.permission.STATUS_BAR) public int getNavBarModeOverride();
    method @RequiresPermission(android.Manifest.permission.MEDIA_CONTENT_CONTROL) public void registerNearbyMediaDevicesProvider(@NonNull android.media.NearbyMediaDevicesProvider);
    method @RequiresPermission(android.Manifest.permission.STATUS_BAR) public void setDisabledForSetup(boolean);
    method @RequiresPermission(android.Manifest.permission.STATUS_BAR) public void setNavBarModeOverride(int);
    method @RequiresPermission(android.Manifest.permission.MEDIA_CONTENT_CONTROL) public void unregisterNearbyMediaDevicesProvider(@NonNull android.media.NearbyMediaDevicesProvider);
    method @RequiresPermission(android.Manifest.permission.MEDIA_CONTENT_CONTROL) public void updateMediaTapToTransferReceiverDisplay(int, @NonNull android.media.MediaRoute2Info, @Nullable android.graphics.drawable.Icon, @Nullable CharSequence);
    method @RequiresPermission(android.Manifest.permission.MEDIA_CONTENT_CONTROL) public void updateMediaTapToTransferSenderDisplay(int, @NonNull android.media.MediaRoute2Info, @Nullable java.util.concurrent.Executor, @Nullable Runnable);
    field public static final int MEDIA_TRANSFER_RECEIVER_STATE_CLOSE_TO_SENDER = 0; // 0x0
@@ -6257,6 +6259,26 @@ package android.media {
    field public static final int SYNC_EVENT_SHARE_AUDIO_HISTORY = 100; // 0x64
  }
  public final class NearbyDevice implements android.os.Parcelable {
    ctor public NearbyDevice(@NonNull String, int);
    method public int describeContents();
    method @NonNull public String getMediaRoute2Id();
    method public int getRangeZone();
    method @NonNull public static String rangeZoneToString(int);
    method public void writeToParcel(@NonNull android.os.Parcel, int);
    field @NonNull public static final android.os.Parcelable.Creator<android.media.NearbyDevice> CREATOR;
    field public static final int RANGE_CLOSE = 3; // 0x3
    field public static final int RANGE_FAR = 1; // 0x1
    field public static final int RANGE_LONG = 2; // 0x2
    field public static final int RANGE_UNKNOWN = 0; // 0x0
    field public static final int RANGE_WITHIN_REACH = 4; // 0x4
  }
  public interface NearbyMediaDevicesProvider {
    method public void registerNearbyDevicesCallback(@NonNull java.util.function.Consumer<java.util.List<android.media.NearbyDevice>>);
    method public void unregisterNearbyDevicesCallback(@NonNull java.util.function.Consumer<java.util.List<android.media.NearbyDevice>>);
  }
  public class PlayerProxy {
    method public void pause();
    method public void setPan(float);
+122 −0
Original line number Diff line number Diff line
@@ -28,7 +28,11 @@ import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.Context;
import android.graphics.drawable.Icon;
import android.media.INearbyMediaDevicesProvider;
import android.media.INearbyMediaDevicesUpdateCallback;
import android.media.MediaRoute2Info;
import android.media.NearbyDevice;
import android.media.NearbyMediaDevicesProvider;
import android.os.Binder;
import android.os.Build;
import android.os.Bundle;
@@ -46,6 +50,9 @@ import com.android.internal.statusbar.NotificationVisibility;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.Executor;
@@ -503,6 +510,16 @@ public class StatusBarManager {
    @Retention(RetentionPolicy.SOURCE)
    public @interface MediaTransferReceiverState {}

    /**
     * A map from a provider registered in
     * {@link #registerNearbyMediaDevicesProvider(NearbyMediaDevicesProvider)} to the wrapper
     * around the provider that was created internally. We need the wrapper to make the provider
     * binder-compatible, and we need to store a reference to the wrapper so that when the provider
     * is un-registered, we un-register the saved wrapper instance.
     */
    private final Map<NearbyMediaDevicesProvider, NearbyMediaDevicesProviderWrapper>
            nearbyMediaDevicesProviderMap = new HashMap<>();

    @UnsupportedAppUsage
    private Context mContext;
    private IStatusBarService mService;
@@ -1033,6 +1050,67 @@ public class StatusBarManager {
        }
    }

    /**
     * Registers a provider that notifies callbacks about the status of nearby devices that are able
     * to play media.
     * <p>
     * If multiple providers are registered, all the providers will be used for nearby device
     * information.
     * <p>
     * @param provider the nearby device information provider to register
     * <p>
     * @hide
     */
    @SystemApi
    @RequiresPermission(android.Manifest.permission.MEDIA_CONTENT_CONTROL)
    public void registerNearbyMediaDevicesProvider(
            @NonNull NearbyMediaDevicesProvider provider
    ) {
        Objects.requireNonNull(provider);
        if (nearbyMediaDevicesProviderMap.containsKey(provider)) {
            return;
        }
        try {
            final IStatusBarService svc = getService();
            NearbyMediaDevicesProviderWrapper providerWrapper =
                    new NearbyMediaDevicesProviderWrapper(provider);
            nearbyMediaDevicesProviderMap.put(provider, providerWrapper);
            svc.registerNearbyMediaDevicesProvider(providerWrapper);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

   /**
     * Unregisters a provider that gives information about nearby devices that are able to play
     * media.
     * <p>
     * See {@link registerNearbyMediaDevicesProvider}.
     * <p>
     * @param provider the nearby device information provider to unregister
     * <p>
     * @hide
     */
    @SystemApi
    @RequiresPermission(android.Manifest.permission.MEDIA_CONTENT_CONTROL)
    public void unregisterNearbyMediaDevicesProvider(
            @NonNull NearbyMediaDevicesProvider provider
    ) {
        Objects.requireNonNull(provider);
        if (!nearbyMediaDevicesProviderMap.containsKey(provider)) {
            return;
        }
        try {
            final IStatusBarService svc = getService();
            NearbyMediaDevicesProviderWrapper providerWrapper =
                    nearbyMediaDevicesProviderMap.get(provider);
            nearbyMediaDevicesProviderMap.remove(provider);
            svc.unregisterNearbyMediaDevicesProvider(providerWrapper);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /** @hide */
    public static String windowStateToString(int state) {
        if (state == WINDOW_STATE_HIDING) return "WINDOW_STATE_HIDING";
@@ -1340,4 +1418,48 @@ public class StatusBarManager {
            }
        }
    }

    /**
     * @hide
     */
    static final class NearbyMediaDevicesProviderWrapper extends INearbyMediaDevicesProvider.Stub {
        @NonNull
        private final NearbyMediaDevicesProvider mProvider;
        // Because we're wrapping a {@link NearbyMediaDevicesProvider} in a binder-compatible
        // interface, we also need to wrap the callbacks that the provider receives. We use
        // this map to keep track of the original callback and the wrapper callback so that
        // unregistering the callback works correctly.
        @NonNull
        private final Map<INearbyMediaDevicesUpdateCallback, Consumer<List<NearbyDevice>>>
                mRegisteredCallbacks = new HashMap<>();

        NearbyMediaDevicesProviderWrapper(@NonNull NearbyMediaDevicesProvider provider) {
            mProvider = provider;
        }

        @Override
        public void registerNearbyDevicesCallback(
                @NonNull INearbyMediaDevicesUpdateCallback callback) {
            Consumer<List<NearbyDevice>> callbackAsConsumer = nearbyDevices -> {
                try {
                    callback.onDevicesUpdated(nearbyDevices);
                } catch (RemoteException ex) {
                    throw ex.rethrowFromSystemServer();
                }
            };

            mRegisteredCallbacks.put(callback, callbackAsConsumer);
            mProvider.registerNearbyDevicesCallback(callbackAsConsumer);
        }

        @Override
        public void unregisterNearbyDevicesCallback(
                @NonNull INearbyMediaDevicesUpdateCallback callback) {
            if (!mRegisteredCallbacks.containsKey(callback)) {
                return;
            }
            mProvider.unregisterNearbyDevicesCallback(mRegisteredCallbacks.get(callback));
            mRegisteredCallbacks.remove(callback);
        }
    }
}
+55 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2022 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.media;

import android.annotation.NonNull;
import android.annotation.SystemApi;
import android.app.StatusBarManager;

import java.util.List;
import java.util.function.Consumer;

/**
 * An interface that provides information about nearby devices that are able to play media.
 * <p>
 * External clients can implement this interface and pass it to the system via
 * {@link StatusBarManager#registerNearbyMediaDevicesProvider} to inform the system of nearby media
 * devices.
 * <p>
 * @hide
 */
@SystemApi
public interface NearbyMediaDevicesProvider {
    /**
     * Registers a callback that should be notified each time nearby media device(s) change.
     * <p>
     * When a callback is newly registered, it should be immediately notified of the current nearby
     * media devices. Afterwards, the list of devices passed to the callback should always contain
     * the full set of nearby media devices any time you get an update. If a device is no longer
     * valid (went offline, e.g.) then it should be omitted from the list in the next update.
     * <p>
     * @param callback the callback that will consume updates to the nearby media devices.
     */
    void registerNearbyDevicesCallback(@NonNull Consumer<List<NearbyDevice>> callback);

    /**
     * Unregisters a callback. @see #registerNearbyDevicesCallback.
     * <p>
     * @param callback the callback to unregister.
     */
    void unregisterNearbyDevicesCallback(@NonNull Consumer<List<NearbyDevice>> callback);
}
+7 −0
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@ import android.hardware.biometrics.IBiometricContextListener;
import android.hardware.biometrics.IBiometricSysuiReceiver;
import android.hardware.biometrics.PromptInfo;
import android.hardware.fingerprint.IUdfpsHbmListener;
import android.media.INearbyMediaDevicesProvider;
import android.media.MediaRoute2Info;
import android.os.Bundle;
import android.os.ParcelFileDescriptor;
@@ -311,4 +312,10 @@ oneway interface IStatusBar
        in MediaRoute2Info routeInfo,
        in Icon appIcon,
        in CharSequence appName);

    /** Registers a nearby media devices provider. */
    void registerNearbyMediaDevicesProvider(in INearbyMediaDevicesProvider provider);

    /** Unregisters a nearby media devices provider. */
    void unregisterNearbyMediaDevicesProvider(in INearbyMediaDevicesProvider provider);
}
+7 −0
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@ import android.hardware.biometrics.IBiometricContextListener;
import android.hardware.biometrics.IBiometricSysuiReceiver;
import android.hardware.biometrics.PromptInfo;
import android.hardware.fingerprint.IUdfpsHbmListener;
import android.media.INearbyMediaDevicesProvider;
import android.media.MediaRoute2Info;
import android.net.Uri;
import android.os.Bundle;
@@ -211,4 +212,10 @@ interface IStatusBarService
        in MediaRoute2Info routeInfo,
        in Icon appIcon,
        in CharSequence appName);

    /** Registers a nearby media devices provider. */
    void registerNearbyMediaDevicesProvider(in INearbyMediaDevicesProvider provider);

    /** Unregisters a nearby media devices provider. */
    void unregisterNearbyMediaDevicesProvider(in INearbyMediaDevicesProvider provider);
}
Loading