diff options
author | Xin Li <delphij@google.com> | 2021-10-06 22:53:39 +0000 |
---|---|---|
committer | Xin Li <delphij@google.com> | 2021-10-06 22:53:39 +0000 |
commit | 43c68b1644978fd1c5a35a22eddaaabc7a01be55 (patch) | |
tree | 8dc469e64364fb85fbfbfebe72e96676963beb43 | |
parent | 7407162d0d804905a546bd4a4c52699518c58795 (diff) | |
parent | 3adc0a1fb0fe384cfebef4255689531a63b28f1d (diff) | |
download | tvsystem-43c68b1644978fd1c5a35a22eddaaabc7a01be55.tar.gz |
Merge Android 12android-s-v2-preview-2android-s-v2-preview-1android-s-v2-beta-2android-s-v2-preview-1
Bug: 202323961
Merged-In: I98a36fd3519bb6b7507ed0384c4c58ba220ae456
Change-Id: I2afc409dfdb86ae263711c074ec3a9844c909f34
-rw-r--r-- | Android.bp | 2 | ||||
-rw-r--r-- | OWNERS | 9 | ||||
-rw-r--r-- | api/current.txt | 9 | ||||
-rw-r--r-- | api/system-current.txt | 20 | ||||
-rw-r--r-- | java/com/android/libraries/tv/tvsystem/display/DeviceProductInfo.java | 73 | ||||
-rw-r--r-- | java/com/android/libraries/tv/tvsystem/display/DisplayCompatUtil.java | 2 | ||||
-rw-r--r-- | java/com/android/libraries/tv/tvsystem/media/AudioDeviceAttributes.java | 179 | ||||
-rw-r--r-- | java/com/android/libraries/tv/tvsystem/media/TvAudioManager.java | 76 |
8 files changed, 359 insertions, 11 deletions
@@ -22,6 +22,7 @@ java_sdk_library { api_packages: [ "com.android.libraries.tv.tvsystem", "com.android.libraries.tv.tvsystem.display", + "com.android.libraries.tv.tvsystem.media", "com.android.libraries.tv.tvsystem.pm", "com.android.libraries.tv.tvsystem.user", "com.android.libraries.tv.tvsystem.wifi" @@ -29,6 +30,7 @@ java_sdk_library { dex_preopt: { enabled: false, }, + system_ext_specific: true, no_dist: true, unsafe_ignore_missing_latest_api: true } @@ -0,0 +1,9 @@ +# Primary maintainer +robhor@google.com + +# Additional maintainers +galinap@google.com +philipjunker@google.com +rgl@google.com +sergeynv@google.com +valiiftime@google.com diff --git a/api/current.txt b/api/current.txt index 09cb6e8..fde8b7f 100644 --- a/api/current.txt +++ b/api/current.txt @@ -2,13 +2,18 @@ package com.android.libraries.tv.tvsystem.display { public final class DeviceProductInfo { - ctor public DeviceProductInfo(String, String, String, Integer, com.android.libraries.tv.tvsystem.display.DeviceProductInfo.ManufactureDate, int[]); + ctor @Deprecated public DeviceProductInfo(String, String, String, Integer, com.android.libraries.tv.tvsystem.display.DeviceProductInfo.ManufactureDate, int[]); + method public int getConnectionToSinkType(); method public com.android.libraries.tv.tvsystem.display.DeviceProductInfo.ManufactureDate getManufactureDate(); method public String getManufacturerPnpId(); method public Integer getModelYear(); method public String getName(); method public String getProductId(); - method public int[] getRelativeAddress(); + method @Deprecated public int[] getRelativeAddress(); + field public static final int CONNECTION_TO_SINK_BUILT_IN = 1; // 0x1 + field public static final int CONNECTION_TO_SINK_DIRECT = 2; // 0x2 + field public static final int CONNECTION_TO_SINK_TRANSITIVE = 3; // 0x3 + field public static final int CONNECTION_TO_SINK_UNKNOWN = 0; // 0x0 } public static class DeviceProductInfo.ManufactureDate { diff --git a/api/system-current.txt b/api/system-current.txt index aa0d1db..dbd0cc2 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -1,4 +1,24 @@ // Signature format: 2.0 +package com.android.libraries.tv.tvsystem.media { + + public final class AudioDeviceAttributes { + ctor public AudioDeviceAttributes(@NonNull android.media.AudioDeviceInfo); + ctor public AudioDeviceAttributes(int, int, @NonNull String); + method @NonNull public String getAddress(); + method public int getRole(); + method public int getType(); + field public static final int ROLE_INPUT = 1; // 0x1 + field public static final int ROLE_OUTPUT = 2; // 0x2 + } + + public final class TvAudioManager { + ctor public TvAudioManager(@NonNull android.content.Context); + method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public int getDeviceVolumeBehavior(@NonNull com.android.libraries.tv.tvsystem.media.AudioDeviceAttributes); + method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public void setDeviceVolumeBehavior(@NonNull com.android.libraries.tv.tvsystem.media.AudioDeviceAttributes, int); + } + +} + package com.android.libraries.tv.tvsystem.wifi { public final class SoftApConfiguration implements android.os.Parcelable { diff --git a/java/com/android/libraries/tv/tvsystem/display/DeviceProductInfo.java b/java/com/android/libraries/tv/tvsystem/display/DeviceProductInfo.java index 6e78253..fb0bf71 100644 --- a/java/com/android/libraries/tv/tvsystem/display/DeviceProductInfo.java +++ b/java/com/android/libraries/tv/tvsystem/display/DeviceProductInfo.java @@ -16,7 +16,10 @@ package com.android.libraries.tv.tvsystem.display; -import java.util.Arrays; +import android.annotation.IntDef; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; import java.util.Objects; /** @@ -25,13 +28,39 @@ import java.util.Objects; * product information about the intermediate device. */ public final class DeviceProductInfo { + /** @hide */ + @IntDef(prefix = {"CONNECTION_TO_SINK_"}, value = { + CONNECTION_TO_SINK_UNKNOWN, + CONNECTION_TO_SINK_BUILT_IN, + CONNECTION_TO_SINK_DIRECT, + CONNECTION_TO_SINK_TRANSITIVE + }) + @Retention(RetentionPolicy.SOURCE) + public @interface ConnectionToSinkType { } + + /** The device connection to the display sink is unknown. */ + public static final int CONNECTION_TO_SINK_UNKNOWN = 0; + + /** The display sink is built-in to the device */ + public static final int CONNECTION_TO_SINK_BUILT_IN = 1; + + /** The device is directly connected to the display sink. */ + public static final int CONNECTION_TO_SINK_DIRECT = 2; + + /** The device is transitively connected to the display sink. */ + public static final int CONNECTION_TO_SINK_TRANSITIVE = 3; + private final String mName; private final String mManufacturerPnpId; private final String mProductId; private final Integer mModelYear; private final ManufactureDate mManufactureDate; - private final int[] mRelativeAddress; + private final @ConnectionToSinkType int mConnectionToSinkType; + /** @deprecated use + * {@link #DeviceProductInfo(String, String, String, Integer, ManufactureDate, int)} ()} + * instead.*/ + @Deprecated public DeviceProductInfo( String name, String manufacturerPnpId, @@ -44,7 +73,23 @@ public final class DeviceProductInfo { this.mProductId = productId; this.mModelYear = modelYear; this.mManufactureDate = manufactureDate; - this.mRelativeAddress = relativeAddress; + this.mConnectionToSinkType = CONNECTION_TO_SINK_UNKNOWN; + } + + /** @hide */ + public DeviceProductInfo( + String name, + String manufacturerPnpId, + String productId, + Integer modelYear, + ManufactureDate manufactureDate, + int connectionToSinkType) { + this.mName = name; + this.mManufacturerPnpId = manufacturerPnpId; + this.mProductId = productId; + this.mModelYear = modelYear; + this.mManufactureDate = manufactureDate; + this.mConnectionToSinkType = connectionToSinkType; } /** @@ -87,9 +132,21 @@ public final class DeviceProductInfo { /** * @return Relative address in the display network. For example, for HDMI connected devices this * can be its physical address. Each component of the address is in the range [0, 255]. + * + * @deprecated use {@link #getConnectionToSinkType()} instead. */ + @Deprecated public int[] getRelativeAddress() { - return mRelativeAddress; + return null; + } + + /** + * @return How the current device is connected to the display sink. For example, the display + * can be connected immediately to the device or there can be a receiver in between. + */ + @ConnectionToSinkType + public int getConnectionToSinkType() { + return mConnectionToSinkType; } @Override @@ -105,8 +162,8 @@ public final class DeviceProductInfo { + mModelYear + ", manufactureDate=" + mManufactureDate - + ", relativeAddress=" - + Arrays.toString(mRelativeAddress) + + ", connectionToSinkType=" + + mConnectionToSinkType + '}'; } @@ -120,13 +177,13 @@ public final class DeviceProductInfo { && Objects.equals(mProductId, that.mProductId) && Objects.equals(mModelYear, that.mModelYear) && Objects.equals(mManufactureDate, that.mManufactureDate) - && Arrays.equals(mRelativeAddress, that.mRelativeAddress); + && mConnectionToSinkType == that.mConnectionToSinkType; } @Override public int hashCode() { return Objects.hash(mName, mManufacturerPnpId, mProductId, mModelYear, mManufactureDate, - mRelativeAddress); + mConnectionToSinkType); } /** diff --git a/java/com/android/libraries/tv/tvsystem/display/DisplayCompatUtil.java b/java/com/android/libraries/tv/tvsystem/display/DisplayCompatUtil.java index fb19f98..746f90b 100644 --- a/java/com/android/libraries/tv/tvsystem/display/DisplayCompatUtil.java +++ b/java/com/android/libraries/tv/tvsystem/display/DisplayCompatUtil.java @@ -64,7 +64,7 @@ public final class DisplayCompatUtil { } return new DeviceProductInfo(info.getName(), info.getManufacturerPnpId(), info.getProductId(), info.getModelYear(), manufactureDate, - info.getRelativeAddress()); + info.getConnectionToSinkType()); } private DisplayCompatUtil() {} diff --git a/java/com/android/libraries/tv/tvsystem/media/AudioDeviceAttributes.java b/java/com/android/libraries/tv/tvsystem/media/AudioDeviceAttributes.java new file mode 100644 index 0000000..581d189 --- /dev/null +++ b/java/com/android/libraries/tv/tvsystem/media/AudioDeviceAttributes.java @@ -0,0 +1,179 @@ +/* + * Copyright (C) 2020 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.libraries.tv.tvsystem.media; + +import android.annotation.IntDef; +import android.annotation.NonNull; +import android.annotation.SystemApi; +import android.media.AudioDeviceInfo; +import android.media.AudioPort; +import android.media.AudioSystem; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.util.Objects; + +/** + * @hide + * Class to represent the attributes of an audio device: its type (speaker, headset...), address + * (if known) and role (input, output). + * <p>Unlike {@link AudioDeviceInfo}, the device + * doesn't need to be connected to be uniquely identified, it can + * for instance represent a specific A2DP headset even after a + * disconnection, whereas the corresponding <code>AudioDeviceInfo</code> + * would then be invalid. + * <p>While creating / obtaining an instance is not protected by a + * permission, APIs using one rely on MODIFY_AUDIO_ROUTING. + */ +@SystemApi +public final class AudioDeviceAttributes { + + /** + * A role identifying input devices, such as microphones. + */ + public static final int ROLE_INPUT = AudioPort.ROLE_SOURCE; + /** + * A role identifying output devices, such as speakers or headphones. + */ + public static final int ROLE_OUTPUT = AudioPort.ROLE_SINK; + + /** @hide */ + @IntDef(flag = false, prefix = "ROLE_", value = { + ROLE_INPUT, ROLE_OUTPUT } + ) + @Retention(RetentionPolicy.SOURCE) + public @interface Role {} + + /** + * The audio device type, as defined in {@link AudioDeviceInfo} + */ + private final @AudioDeviceInfo.AudioDeviceType int mType; + /** + * The unique address of the device. Some devices don't have addresses, only an empty string. + */ + private final @NonNull String mAddress; + + /** + * Is input or output device + */ + private final @AudioDeviceAttributes.Role + int mRole; + + /** + * @hide + * Constructor from a valid {@link AudioDeviceInfo} + * @param deviceInfo the connected audio device from which to obtain the device-identifying + * type and address. + */ + @SystemApi + public AudioDeviceAttributes(@NonNull AudioDeviceInfo deviceInfo) { + Objects.requireNonNull(deviceInfo); + mRole = deviceInfo.isSink() ? ROLE_OUTPUT : ROLE_INPUT; + mType = deviceInfo.getType(); + mAddress = deviceInfo.getAddress(); + } + + /** + * @hide + * Constructor from role, device type and address + * @param role indicates input or output role + * @param type the device type, as defined in {@link AudioDeviceInfo} + * @param address the address of the device, or an empty string for devices without one + */ + @SystemApi + public AudioDeviceAttributes(@AudioDeviceAttributes.Role int role, + @AudioDeviceInfo.AudioDeviceType int type, + @NonNull String address) { + Objects.requireNonNull(address); + if (role != ROLE_OUTPUT && role != ROLE_INPUT) { + throw new IllegalArgumentException("Invalid role " + role); + } + + mRole = role; + mType = type; + mAddress = address; + } + + /*package*/ AudioDeviceAttributes(int nativeType, @NonNull String address) { + mRole = (nativeType & AudioSystem.DEVICE_BIT_IN) != 0 ? ROLE_INPUT : ROLE_OUTPUT; + mType = AudioDeviceInfo.convertInternalDeviceToDeviceType(nativeType); + mAddress = address; + } + + /** + * @hide + * Returns the role of a device + * @return the role + */ + @SystemApi + public @AudioDeviceAttributes.Role + int getRole() { + return mRole; + } + + /** + * @hide + * Returns the audio device type of a device + * @return the type, as defined in {@link AudioDeviceInfo} + */ + @SystemApi + public @AudioDeviceInfo.AudioDeviceType int getType() { + return mType; + } + + /** + * @hide + * Returns the address of the audio device, or an empty string for devices without one + * @return the device address + */ + @SystemApi + public @NonNull String getAddress() { + return mAddress; + } + + @Override + public int hashCode() { + return Objects.hash(mRole, mType, mAddress); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + AudioDeviceAttributes that = (AudioDeviceAttributes) o; + return ((mRole == that.mRole) + && (mType == that.mType) + && mAddress.equals(that.mAddress)); + } + + /** @hide */ + public static String roleToString(@AudioDeviceAttributes.Role int role) { + return (role == ROLE_OUTPUT ? "output" : "input"); + } + + @Override + public String toString() { + return new String("AudioDeviceAttributes:" + + " role:" + roleToString(mRole) + + " type:" + (mRole == ROLE_OUTPUT ? AudioSystem.getOutputDeviceName( + AudioDeviceInfo.convertDeviceTypeToInternalDevice(mType)) + : AudioSystem.getInputDeviceName( + AudioDeviceInfo.convertDeviceTypeToInternalDevice(mType))) + + " addr:" + mAddress); + } +} diff --git a/java/com/android/libraries/tv/tvsystem/media/TvAudioManager.java b/java/com/android/libraries/tv/tvsystem/media/TvAudioManager.java new file mode 100644 index 0000000..7b18200 --- /dev/null +++ b/java/com/android/libraries/tv/tvsystem/media/TvAudioManager.java @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2020 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.libraries.tv.tvsystem.media; + + +import android.annotation.NonNull; +import android.annotation.RequiresPermission; +import android.annotation.SystemApi; +import android.content.Context; +import android.media.AudioManager; + +/** + * Provides access to APIs in {@link AudioManager} that are otherwise @hidden. + * + * @hide + */ +@SystemApi +public final class TvAudioManager { + + private final AudioManager mAudioManager; + + public TvAudioManager(@NonNull Context context) { + mAudioManager = context.getSystemService(AudioManager.class); + } + + /** + * @hide + * Sets the volume behavior for an audio output device. + * @see AudioManager#DEVICE_VOLUME_BEHAVIOR_VARIABLE + * @see AudioManager#DEVICE_VOLUME_BEHAVIOR_FULL + * @see AudioManager#DEVICE_VOLUME_BEHAVIOR_FIXED + * @see AudioManager#DEVICE_VOLUME_BEHAVIOR_ABSOLUTE + * @see AudioManager#DEVICE_VOLUME_BEHAVIOR_ABSOLUTE_MULTI_MODE + * @param device the device to be affected + * @param deviceVolumeBehavior one of the device behaviors + */ + @SystemApi + @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) + public void setDeviceVolumeBehavior(@NonNull AudioDeviceAttributes device, + @AudioManager.DeviceVolumeBehavior int deviceVolumeBehavior) { + android.media.AudioDeviceAttributes audioDeviceAttributes = + new android.media.AudioDeviceAttributes(device.getRole(), device.getType(), + device.getAddress()); + mAudioManager.setDeviceVolumeBehavior(audioDeviceAttributes, deviceVolumeBehavior); + } + + /** + * @hide + * Returns the volume device behavior for the given audio device + * @param device the audio device + * @return the volume behavior for the device + */ + @SystemApi + @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) + public @AudioManager.DeviceVolumeBehavior + int getDeviceVolumeBehavior(@NonNull AudioDeviceAttributes device) { + android.media.AudioDeviceAttributes audioDeviceAttributes = + new android.media.AudioDeviceAttributes(device.getRole(), device.getType(), + device.getAddress()); + return mAudioManager.getDeviceVolumeBehavior(audioDeviceAttributes); + } +} |