diff options
57 files changed, 1366 insertions, 491 deletions
diff --git a/Android.bp b/Android.bp index c03c9f1cb69b..dd46108b8576 100644 --- a/Android.bp +++ b/Android.bp @@ -53,6 +53,7 @@ filegroup { "core/java/android/view/DisplayAdjustments.java", ], path: "core/java", + visibility: ["//frameworks/base/test-mock"], } filegroup { diff --git a/api/current.txt b/api/current.txt index c399464521de..430e8407a4d8 100644 --- a/api/current.txt +++ b/api/current.txt @@ -26477,6 +26477,7 @@ package android.media { public final class MediaRoute2Info implements android.os.Parcelable { method public int describeContents(); + method @Nullable public String getClientPackageName(); method public int getConnectionState(); method @Nullable public CharSequence getDescription(); method public int getDeviceType(); @@ -26498,6 +26499,9 @@ package android.media { field public static final int DEVICE_TYPE_REMOTE_SPEAKER = 2; // 0x2 field public static final int DEVICE_TYPE_REMOTE_TV = 1; // 0x1 field public static final int DEVICE_TYPE_UNKNOWN = 0; // 0x0 + field public static final String FEATURE_LIVE_AUDIO = "android.media.intent.category.LIVE_AUDIO"; + field public static final String FEATURE_LIVE_VIDEO = "android.media.intent.category.LIVE_VIDEO"; + field public static final String FEATURE_REMOTE_PLAYBACK = "android.media.intent.category.REMOTE_PLAYBACK"; field public static final int PLAYBACK_VOLUME_FIXED = 0; // 0x0 field public static final int PLAYBACK_VOLUME_VARIABLE = 1; // 0x1 } @@ -26522,9 +26526,23 @@ package android.media { public abstract class MediaRoute2ProviderService extends android.app.Service { ctor public MediaRoute2ProviderService(); + method @NonNull public final java.util.List<android.media.RoutingSessionInfo> getAllSessionInfo(); + method @Nullable public final android.media.RoutingSessionInfo getSessionInfo(@NonNull String); method public final void notifyRoutes(@NonNull java.util.Collection<android.media.MediaRoute2Info>); - method @NonNull public android.os.IBinder onBind(@NonNull android.content.Intent); + method public final void notifySessionCreated(@NonNull android.media.RoutingSessionInfo, long); + method public final void notifySessionCreationFailed(long); + method public final void notifySessionReleased(@NonNull String); + method public final void notifySessionUpdated(@NonNull android.media.RoutingSessionInfo); + method @CallSuper @Nullable public android.os.IBinder onBind(@NonNull android.content.Intent); + method public abstract void onCreateSession(@NonNull String, @NonNull String, long, @Nullable android.os.Bundle); + method public abstract void onDeselectRoute(@NonNull String, @NonNull String); method public void onDiscoveryPreferenceChanged(@NonNull android.media.RouteDiscoveryPreference); + method public abstract void onReleaseSession(@NonNull String); + method public abstract void onSelectRoute(@NonNull String, @NonNull String); + method public abstract void onSetVolume(@NonNull String, int); + method public abstract void onTransferToRoute(@NonNull String, @NonNull String); + method public abstract void onUpdateVolume(@NonNull String, int); + field public static final long REQUEST_ID_UNKNOWN = 0L; // 0x0L field public static final String SERVICE_INTERFACE = "android.media.MediaRoute2ProviderService"; } @@ -26652,12 +26670,22 @@ package android.media { } public class MediaRouter2 { + method @NonNull public java.util.List<android.media.MediaRouter2.RoutingController> getControllers(); method @NonNull public static android.media.MediaRouter2 getInstance(@NonNull android.content.Context); method @NonNull public java.util.List<android.media.MediaRoute2Info> getRoutes(); + method @NonNull public android.media.MediaRouter2.RoutingController getSystemController(); + method public void registerControllerCallback(@NonNull java.util.concurrent.Executor, @NonNull android.media.MediaRouter2.RoutingControllerCallback); method public void registerRouteCallback(@NonNull java.util.concurrent.Executor, @NonNull android.media.MediaRouter2.RouteCallback, @NonNull android.media.RouteDiscoveryPreference); + method public void requestCreateController(@NonNull android.media.MediaRoute2Info); + method public void setOnGetControllerHintsListener(@Nullable android.media.MediaRouter2.OnGetControllerHintsListener); + method public void unregisterControllerCallback(@NonNull android.media.MediaRouter2.RoutingControllerCallback); method public void unregisterRouteCallback(@NonNull android.media.MediaRouter2.RouteCallback); } + public static interface MediaRouter2.OnGetControllerHintsListener { + method @Nullable public android.os.Bundle onGetControllerHints(@NonNull android.media.MediaRoute2Info); + } + public static class MediaRouter2.RouteCallback { ctor public MediaRouter2.RouteCallback(); method public void onRoutesAdded(@NonNull java.util.List<android.media.MediaRoute2Info>); @@ -26665,6 +26693,28 @@ package android.media { method public void onRoutesRemoved(@NonNull java.util.List<android.media.MediaRoute2Info>); } + public class MediaRouter2.RoutingController { + method public void deselectRoute(@NonNull android.media.MediaRoute2Info); + method @Nullable public android.os.Bundle getControlHints(); + method @NonNull public java.util.List<android.media.MediaRoute2Info> getDeselectableRoutes(); + method @NonNull public String getId(); + method @NonNull public java.util.List<android.media.MediaRoute2Info> getSelectableRoutes(); + method @NonNull public java.util.List<android.media.MediaRoute2Info> getSelectedRoutes(); + method @NonNull public java.util.List<android.media.MediaRoute2Info> getTransferrableRoutes(); + method public boolean isReleased(); + method public void release(); + method public void selectRoute(@NonNull android.media.MediaRoute2Info); + method public void transferToRoute(@NonNull android.media.MediaRoute2Info); + } + + public static class MediaRouter2.RoutingControllerCallback { + ctor public MediaRouter2.RoutingControllerCallback(); + method public void onControllerCreated(@NonNull android.media.MediaRouter2.RoutingController); + method public void onControllerCreationFailed(@NonNull android.media.MediaRoute2Info); + method public void onControllerReleased(@NonNull android.media.MediaRouter2.RoutingController); + method public void onControllerUpdated(@NonNull android.media.MediaRouter2.RoutingController); + } + public class MediaScannerConnection implements android.content.ServiceConnection { ctor public MediaScannerConnection(android.content.Context, android.media.MediaScannerConnection.MediaScannerConnectionClient); method public void connect(); @@ -27039,6 +27089,38 @@ package android.media { method @NonNull public android.media.RouteDiscoveryPreference.Builder setPreferredFeatures(@NonNull java.util.List<java.lang.String>); } + public final class RoutingSessionInfo implements android.os.Parcelable { + method public int describeContents(); + method @NonNull public String getClientPackageName(); + method @Nullable public android.os.Bundle getControlHints(); + method @NonNull public java.util.List<java.lang.String> getDeselectableRoutes(); + method @NonNull public String getId(); + method @NonNull public java.util.List<java.lang.String> getSelectableRoutes(); + method @NonNull public java.util.List<java.lang.String> getSelectedRoutes(); + method @NonNull public java.util.List<java.lang.String> getTransferrableRoutes(); + method public void writeToParcel(@NonNull android.os.Parcel, int); + field @NonNull public static final android.os.Parcelable.Creator<android.media.RoutingSessionInfo> CREATOR; + } + + public static final class RoutingSessionInfo.Builder { + ctor public RoutingSessionInfo.Builder(@NonNull String, @NonNull String); + ctor public RoutingSessionInfo.Builder(@NonNull android.media.RoutingSessionInfo); + method @NonNull public android.media.RoutingSessionInfo.Builder addDeselectableRoute(@NonNull String); + method @NonNull public android.media.RoutingSessionInfo.Builder addSelectableRoute(@NonNull String); + method @NonNull public android.media.RoutingSessionInfo.Builder addSelectedRoute(@NonNull String); + method @NonNull public android.media.RoutingSessionInfo.Builder addTransferrableRoute(@NonNull String); + method @NonNull public android.media.RoutingSessionInfo build(); + method @NonNull public android.media.RoutingSessionInfo.Builder clearDeselectableRoutes(); + method @NonNull public android.media.RoutingSessionInfo.Builder clearSelectableRoutes(); + method @NonNull public android.media.RoutingSessionInfo.Builder clearSelectedRoutes(); + method @NonNull public android.media.RoutingSessionInfo.Builder clearTransferrableRoutes(); + method @NonNull public android.media.RoutingSessionInfo.Builder removeDeselectableRoute(@NonNull String); + method @NonNull public android.media.RoutingSessionInfo.Builder removeSelectableRoute(@NonNull String); + method @NonNull public android.media.RoutingSessionInfo.Builder removeSelectedRoute(@NonNull String); + method @NonNull public android.media.RoutingSessionInfo.Builder removeTransferrableRoute(@NonNull String); + method @NonNull public android.media.RoutingSessionInfo.Builder setControlHints(@Nullable android.os.Bundle); + } + public final class Session2Command implements android.os.Parcelable { ctor public Session2Command(int); ctor public Session2Command(@NonNull String, @Nullable android.os.Bundle); @@ -30557,7 +30639,9 @@ package android.net.wifi { } public class ScanResult implements android.os.Parcelable { + ctor public ScanResult(@NonNull android.net.wifi.ScanResult); method public int describeContents(); + method @NonNull public java.util.List<android.net.wifi.ScanResult.InformationElement> getInformationElements(); method public int getWifiStandard(); method public boolean is80211mcResponder(); method public boolean isPasspointNetwork(); @@ -30568,6 +30652,7 @@ package android.net.wifi { field public static final int CHANNEL_WIDTH_40MHZ = 1; // 0x1 field public static final int CHANNEL_WIDTH_80MHZ = 2; // 0x2 field public static final int CHANNEL_WIDTH_80MHZ_PLUS_MHZ = 4; // 0x4 + field @NonNull public static final android.os.Parcelable.Creator<android.net.wifi.ScanResult> CREATOR; field public String SSID; field public static final int WIFI_STANDARD_11AC = 5; // 0x5 field public static final int WIFI_STANDARD_11AX = 6; // 0x6 @@ -30585,6 +30670,13 @@ package android.net.wifi { field public CharSequence venueName; } + public static class ScanResult.InformationElement { + ctor public ScanResult.InformationElement(@NonNull android.net.wifi.ScanResult.InformationElement); + method @NonNull public java.nio.ByteBuffer getBytes(); + method public int getId(); + method public int getIdExt(); + } + public final class SoftApConfiguration implements android.os.Parcelable { method public int describeContents(); method @Nullable public android.net.MacAddress getBssid(); @@ -31508,8 +31600,10 @@ package android.net.wifi.p2p { method public int getControlPort(); method public int getDeviceType(); method public int getMaxThroughput(); + method public boolean isContentProtectionSupported(); method public boolean isSessionAvailable(); method public boolean isWfdEnabled(); + method public void setContentProtectionSupported(boolean); method public void setControlPort(int); method public boolean setDeviceType(int); method public void setMaxThroughput(int); diff --git a/api/system-current.txt b/api/system-current.txt index 41533b7cd19d..d1696c8256c4 100755 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -4689,6 +4689,10 @@ package android.media.tv.tuner { method @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER) public int setSatellitePosition(int); method @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER) public int setTone(int); method @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER) public int setVoltage(int); + field public static final int EVENT_TYPE_DISEQC_RX_OVERFLOW = 0; // 0x0 + field public static final int EVENT_TYPE_DISEQC_RX_PARITY_ERROR = 2; // 0x2 + field public static final int EVENT_TYPE_DISEQC_RX_TIMEOUT = 1; // 0x1 + field public static final int EVENT_TYPE_LNB_OVERLOAD = 3; // 0x3 field public static final int POSITION_A = 1; // 0x1 field public static final int POSITION_B = 2; // 0x2 field public static final int POSITION_UNDEFINED = 0; // 0x0 @@ -4705,6 +4709,11 @@ package android.media.tv.tuner { field public static final int VOLTAGE_NONE = 0; // 0x0 } + public interface LnbCallback { + method public void onDiseqcMessage(@NonNull byte[]); + method public void onEvent(int); + } + public final class Tuner implements java.lang.AutoCloseable { ctor public Tuner(@NonNull android.content.Context); method @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER) public void clearOnTuneEventListener(); @@ -4712,6 +4721,9 @@ package android.media.tv.tuner { method @Nullable @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER) public android.media.tv.tuner.dvr.DvrPlayback openDvrPlayback(long, @Nullable java.util.concurrent.Executor, @Nullable android.media.tv.tuner.dvr.OnPlaybackStatusChangedListener); method @Nullable @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER) public android.media.tv.tuner.dvr.DvrRecorder openDvrRecorder(long, @Nullable java.util.concurrent.Executor, @Nullable android.media.tv.tuner.dvr.OnRecordStatusChangedListener); method @Nullable @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER) public android.media.tv.tuner.filter.Filter openFilter(int, int, long, @Nullable java.util.concurrent.Executor, @Nullable android.media.tv.tuner.filter.FilterCallback); + method @Nullable @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER) public android.media.tv.tuner.Lnb openLnb(@Nullable java.util.concurrent.Executor, @Nullable android.media.tv.tuner.LnbCallback); + method @Nullable @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER) public android.media.tv.tuner.Lnb openLnbByName(@Nullable String, @Nullable java.util.concurrent.Executor, @NonNull android.media.tv.tuner.LnbCallback); + method @Nullable public android.media.tv.tuner.filter.TimeFilter openTimeFilter(); method @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER) public void setOnTuneEventListener(@NonNull java.util.concurrent.Executor, @NonNull android.media.tv.tuner.frontend.OnTuneEventListener); method @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER) public int stopTune(); method @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER) public int tune(@NonNull android.media.tv.tuner.frontend.FrontendSettings); @@ -4728,6 +4740,18 @@ package android.media.tv.tuner { field public static final int RESULT_SUCCESS = 0; // 0x0 field public static final int RESULT_UNAVAILABLE = 1; // 0x1 field public static final int RESULT_UNKNOWN_ERROR = 6; // 0x6 + field public static final int SC_HEVC_INDEX_AUD = 2; // 0x2 + field public static final int SC_HEVC_INDEX_SLICE_BLA_N_LP = 16; // 0x10 + field public static final int SC_HEVC_INDEX_SLICE_BLA_W_RADL = 8; // 0x8 + field public static final int SC_HEVC_INDEX_SLICE_CE_BLA_W_LP = 4; // 0x4 + field public static final int SC_HEVC_INDEX_SLICE_IDR_N_LP = 64; // 0x40 + field public static final int SC_HEVC_INDEX_SLICE_IDR_W_RADL = 32; // 0x20 + field public static final int SC_HEVC_INDEX_SLICE_TRAIL_CRA = 128; // 0x80 + field public static final int SC_HEVC_INDEX_SPS = 1; // 0x1 + field public static final int SC_INDEX_B_FRAME = 4; // 0x4 + field public static final int SC_INDEX_I_FRAME = 1; // 0x1 + field public static final int SC_INDEX_P_FRAME = 2; // 0x2 + field public static final int SC_INDEX_SEQUENCE = 8; // 0x8 } } @@ -4797,6 +4821,59 @@ package android.media.tv.tuner.dvr { package android.media.tv.tuner.filter { + public class AlpFilterConfiguration extends android.media.tv.tuner.filter.FilterConfiguration { + method @NonNull @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER) public static android.media.tv.tuner.filter.AlpFilterConfiguration.Builder builder(@NonNull android.content.Context); + method public int getLengthType(); + method public int getPacketType(); + method public int getType(); + field public static final int LENGTH_TYPE_UNDEFINED = 0; // 0x0 + field public static final int LENGTH_TYPE_WITHOUT_ADDITIONAL_HEADER = 1; // 0x1 + field public static final int LENGTH_TYPE_WITH_ADDITIONAL_HEADER = 2; // 0x2 + } + + public static class AlpFilterConfiguration.Builder extends android.media.tv.tuner.filter.FilterConfiguration.Builder<android.media.tv.tuner.filter.AlpFilterConfiguration.Builder> { + method @NonNull public android.media.tv.tuner.filter.AlpFilterConfiguration build(); + method @NonNull public android.media.tv.tuner.filter.AlpFilterConfiguration.Builder setLengthType(int); + method @NonNull public android.media.tv.tuner.filter.AlpFilterConfiguration.Builder setPacketType(int); + } + + public class AudioDescriptor { + method public byte getAdFade(); + method public byte getAdGainCenter(); + method public byte getAdGainFront(); + method public byte getAdGainSurround(); + method public byte getAdPan(); + method public char getAdVersionTextTag(); + } + + public class AvSettings extends android.media.tv.tuner.filter.Settings { + method @NonNull @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER) public static android.media.tv.tuner.filter.AvSettings.Builder builder(@NonNull android.content.Context, int, boolean); + method public boolean isPassthrough(); + } + + public static class AvSettings.Builder extends android.media.tv.tuner.filter.Settings.Builder<android.media.tv.tuner.filter.AvSettings.Builder> { + method @NonNull public android.media.tv.tuner.filter.AvSettings build(); + method @NonNull public android.media.tv.tuner.filter.AvSettings.Builder setPassthrough(boolean); + } + + public class DownloadEvent extends android.media.tv.tuner.filter.FilterEvent { + method public int getDataLength(); + method public int getItemFragmentIndex(); + method public int getItemId(); + method public int getLastItemFragmentIndex(); + method public int getMpuSequenceNumber(); + } + + public class DownloadSettings extends android.media.tv.tuner.filter.Settings { + method @NonNull @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER) public static android.media.tv.tuner.filter.DownloadSettings.Builder builder(@NonNull android.content.Context, int); + method public int getDownloadId(); + } + + public static class DownloadSettings.Builder extends android.media.tv.tuner.filter.Settings.Builder<android.media.tv.tuner.filter.DownloadSettings.Builder> { + method @NonNull public android.media.tv.tuner.filter.DownloadSettings build(); + method @NonNull public android.media.tv.tuner.filter.DownloadSettings.Builder setDownloadId(int); + } + public class Filter implements java.lang.AutoCloseable { method public void close(); method public int configure(@NonNull android.media.tv.tuner.filter.FilterConfiguration); @@ -4840,12 +4917,79 @@ package android.media.tv.tuner.filter { } public abstract class FilterConfiguration { + method @Nullable public android.media.tv.tuner.filter.Settings getSettings(); + method public abstract int getType(); + field public static final int PACKET_TYPE_COMPRESSED = 2; // 0x2 + field public static final int PACKET_TYPE_IPV4 = 0; // 0x0 + field public static final int PACKET_TYPE_SIGNALING = 4; // 0x4 + } + + public abstract static class FilterConfiguration.Builder<T extends android.media.tv.tuner.filter.FilterConfiguration.Builder<T>> { + method @NonNull public T setSettings(@Nullable android.media.tv.tuner.filter.Settings); } public abstract class FilterEvent { ctor public FilterEvent(); } + public class IpFilterConfiguration extends android.media.tv.tuner.filter.FilterConfiguration { + method @NonNull @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER) public static android.media.tv.tuner.filter.IpFilterConfiguration.Builder builder(@NonNull android.content.Context); + method @NonNull @Size(min=4, max=16) public byte[] getDstIpAddress(); + method public int getDstPort(); + method @NonNull @Size(min=4, max=16) public byte[] getSrcIpAddress(); + method public int getSrcPort(); + method public int getType(); + method public boolean isPassthrough(); + } + + public static class IpFilterConfiguration.Builder extends android.media.tv.tuner.filter.FilterConfiguration.Builder<android.media.tv.tuner.filter.IpFilterConfiguration.Builder> { + method @NonNull public android.media.tv.tuner.filter.IpFilterConfiguration build(); + method @NonNull public android.media.tv.tuner.filter.IpFilterConfiguration.Builder setDstIpAddress(@NonNull byte[]); + method @NonNull public android.media.tv.tuner.filter.IpFilterConfiguration.Builder setDstPort(int); + method @NonNull public android.media.tv.tuner.filter.IpFilterConfiguration.Builder setPassthrough(boolean); + method @NonNull public android.media.tv.tuner.filter.IpFilterConfiguration.Builder setSrcIpAddress(@NonNull byte[]); + method @NonNull public android.media.tv.tuner.filter.IpFilterConfiguration.Builder setSrcPort(int); + } + + public class IpPayloadEvent extends android.media.tv.tuner.filter.FilterEvent { + method public int getDataLength(); + } + + public class MediaEvent extends android.media.tv.tuner.filter.FilterEvent { + method public long getAvDataId(); + method public long getDataLength(); + method @Nullable public android.media.tv.tuner.filter.AudioDescriptor getExtraMetaData(); + method public int getMpuSequenceNumber(); + method public long getOffset(); + method public long getPts(); + method public int getStreamId(); + method public boolean isPrivateData(); + method public boolean isPtsPresent(); + method public boolean isSecureMemory(); + } + + public class MmtpFilterConfiguration extends android.media.tv.tuner.filter.FilterConfiguration { + method @NonNull @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER) public static android.media.tv.tuner.filter.MmtpFilterConfiguration.Builder builder(@NonNull android.content.Context); + method public int getMmtpPacketId(); + method public int getType(); + } + + public static class MmtpFilterConfiguration.Builder extends android.media.tv.tuner.filter.FilterConfiguration.Builder<android.media.tv.tuner.filter.MmtpFilterConfiguration.Builder> { + method @NonNull public android.media.tv.tuner.filter.MmtpFilterConfiguration build(); + method @NonNull public android.media.tv.tuner.filter.MmtpFilterConfiguration.Builder setMmtpPacketId(int); + } + + public class MmtpRecordEvent extends android.media.tv.tuner.filter.FilterEvent { + method public long getDataLength(); + method public int getScHevcIndexMask(); + } + + public class PesEvent extends android.media.tv.tuner.filter.FilterEvent { + method public int getDataLength(); + method public int getMpuSequenceNumber(); + method public int getStreamId(); + } + public class PesSettings extends android.media.tv.tuner.filter.Settings { method @NonNull @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER) public static android.media.tv.tuner.filter.PesSettings.Builder builder(@NonNull android.content.Context, int); method public int getStreamId(); @@ -4858,6 +5002,33 @@ package android.media.tv.tuner.filter { method @NonNull public android.media.tv.tuner.filter.PesSettings.Builder setStreamId(int); } + public class RecordSettings extends android.media.tv.tuner.filter.Settings { + method @NonNull @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER) public static android.media.tv.tuner.filter.RecordSettings.Builder builder(@NonNull android.content.Context, int); + method public int getScIndexMask(); + method public int getScIndexType(); + method public int getTsIndexMask(); + field public static final int TS_INDEX_ADAPTATION_EXTENSION_FLAG = 4096; // 0x1000 + field public static final int TS_INDEX_CHANGE_TO_EVEN_SCRAMBLED = 8; // 0x8 + field public static final int TS_INDEX_CHANGE_TO_NOT_SCRAMBLED = 4; // 0x4 + field public static final int TS_INDEX_CHANGE_TO_ODD_SCRAMBLED = 16; // 0x10 + field public static final int TS_INDEX_DISCONTINUITY_INDICATOR = 32; // 0x20 + field public static final int TS_INDEX_FIRST_PACKET = 1; // 0x1 + field public static final int TS_INDEX_OPCR_FLAG = 512; // 0x200 + field public static final int TS_INDEX_PAYLOAD_UNIT_START_INDICATOR = 2; // 0x2 + field public static final int TS_INDEX_PCR_FLAG = 256; // 0x100 + field public static final int TS_INDEX_PRIORITY_INDICATOR = 128; // 0x80 + field public static final int TS_INDEX_PRIVATE_DATA = 2048; // 0x800 + field public static final int TS_INDEX_RANDOM_ACCESS_INDICATOR = 64; // 0x40 + field public static final int TS_INDEX_SPLICING_POINT_FLAG = 1024; // 0x400 + } + + public static class RecordSettings.Builder extends android.media.tv.tuner.filter.Settings.Builder<android.media.tv.tuner.filter.RecordSettings.Builder> { + method @NonNull public android.media.tv.tuner.filter.RecordSettings build(); + method @NonNull public android.media.tv.tuner.filter.RecordSettings.Builder setScIndexMask(int); + method @NonNull public android.media.tv.tuner.filter.RecordSettings.Builder setScIndexType(int); + method @NonNull public android.media.tv.tuner.filter.RecordSettings.Builder setTsIndexMask(int); + } + public class SectionEvent extends android.media.tv.tuner.filter.FilterEvent { method public int getDataLength(); method public int getSectionNumber(); @@ -4865,12 +5036,74 @@ package android.media.tv.tuner.filter { method public int getVersion(); } + public class SectionSettings extends android.media.tv.tuner.filter.Settings { + } + + public class SectionSettingsWithSectionBits extends android.media.tv.tuner.filter.SectionSettings { + method @NonNull @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER) public static android.media.tv.tuner.filter.SectionSettingsWithSectionBits.Builder builder(@NonNull android.content.Context, int); + method @NonNull public byte[] getFilterBytes(); + method @NonNull public byte[] getMask(); + method @NonNull public byte[] getMode(); + } + + public static class SectionSettingsWithSectionBits.Builder extends android.media.tv.tuner.filter.Settings.Builder<android.media.tv.tuner.filter.SectionSettingsWithSectionBits.Builder> { + method @NonNull public android.media.tv.tuner.filter.SectionSettingsWithSectionBits build(); + method @NonNull public android.media.tv.tuner.filter.SectionSettingsWithSectionBits.Builder setFilter(@NonNull byte[]); + method @NonNull public android.media.tv.tuner.filter.SectionSettingsWithSectionBits.Builder setMask(@NonNull byte[]); + method @NonNull public android.media.tv.tuner.filter.SectionSettingsWithSectionBits.Builder setMode(@NonNull byte[]); + } + + public class SectionSettingsWithTableInfo extends android.media.tv.tuner.filter.SectionSettings { + method @NonNull @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER) public static android.media.tv.tuner.filter.SectionSettingsWithTableInfo.Builder builder(@NonNull android.content.Context, int); + method public int getTableId(); + method public int getVersion(); + } + + public static class SectionSettingsWithTableInfo.Builder extends android.media.tv.tuner.filter.Settings.Builder<android.media.tv.tuner.filter.SectionSettingsWithTableInfo.Builder> { + method @NonNull public android.media.tv.tuner.filter.SectionSettingsWithTableInfo build(); + method @NonNull public android.media.tv.tuner.filter.SectionSettingsWithTableInfo.Builder setTableId(int); + method @NonNull public android.media.tv.tuner.filter.SectionSettingsWithTableInfo.Builder setVersion(int); + } + public abstract class Settings { + method public int getType(); + } + + public abstract static class Settings.Builder<T extends android.media.tv.tuner.filter.Settings.Builder<T>> { + } + + public class TemiEvent extends android.media.tv.tuner.filter.FilterEvent { + method @NonNull public byte[] getDescriptorData(); + method public byte getDescriptorTag(); + method public long getPts(); + } + + public class TimeFilter implements java.lang.AutoCloseable { + method public int clearTimestamp(); + method public void close(); + method public long getSourceTime(); + method public long getTimeStamp(); + method public int setCurrentTimestamp(long); + field public static final long TIMESTAMP_UNAVAILABLE = -1L; // 0xffffffffffffffffL + } + + public class TlvFilterConfiguration extends android.media.tv.tuner.filter.FilterConfiguration { + method @NonNull @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER) public static android.media.tv.tuner.filter.TlvFilterConfiguration.Builder builder(@NonNull android.content.Context); + method public int getPacketType(); + method public int getType(); + method public boolean isCompressedIpPacket(); + method public boolean isPassthrough(); + } + + public static class TlvFilterConfiguration.Builder extends android.media.tv.tuner.filter.FilterConfiguration.Builder<android.media.tv.tuner.filter.TlvFilterConfiguration.Builder> { + method @NonNull public android.media.tv.tuner.filter.TlvFilterConfiguration build(); + method @NonNull public android.media.tv.tuner.filter.TlvFilterConfiguration.Builder setIsCompressedIpPacket(boolean); + method @NonNull public android.media.tv.tuner.filter.TlvFilterConfiguration.Builder setPacketType(int); + method @NonNull public android.media.tv.tuner.filter.TlvFilterConfiguration.Builder setPassthrough(boolean); } public class TsFilterConfiguration extends android.media.tv.tuner.filter.FilterConfiguration { method @NonNull @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER) public static android.media.tv.tuner.filter.TsFilterConfiguration.Builder builder(@NonNull android.content.Context); - method @Nullable public android.media.tv.tuner.filter.Settings getSettings(); method public int getTpid(); method public int getType(); } @@ -4881,6 +5114,13 @@ package android.media.tv.tuner.filter { method @NonNull public android.media.tv.tuner.filter.TsFilterConfiguration.Builder setTpid(int); } + public class TsRecordEvent extends android.media.tv.tuner.filter.FilterEvent { + method public long getDataLength(); + method public int getPacketId(); + method public int getScIndexMask(); + method public int getTsIndexMask(); + } + } package android.media.tv.tuner.frontend { @@ -6964,7 +7204,13 @@ package android.net.wifi.wificond { public final class DeviceWiphyCapabilities implements android.os.Parcelable { ctor public DeviceWiphyCapabilities(); method public int describeContents(); + method public int getMaxNumberRxSpatialStreams(); + method public int getMaxNumberTxSpatialStreams(); + method public boolean isChannelWidthSupported(int); method public boolean isWifiStandardSupported(int); + method public void setChannelWidthSupported(int, boolean); + method public void setMaxNumberRxSpatialStreams(int); + method public void setMaxNumberTxSpatialStreams(int); method public void setWifiStandardSupport(int, boolean); method public void writeToParcel(@NonNull android.os.Parcel, int); field @NonNull public static final android.os.Parcelable.Creator<android.net.wifi.wificond.DeviceWiphyCapabilities> CREATOR; diff --git a/core/java/android/content/pm/ActivityInfo.java b/core/java/android/content/pm/ActivityInfo.java index e5daaca4aa52..622588b63fef 100644 --- a/core/java/android/content/pm/ActivityInfo.java +++ b/core/java/android/content/pm/ActivityInfo.java @@ -290,6 +290,15 @@ public class ActivityInfo extends ComponentInfo implements Parcelable { public int colorMode = COLOR_MODE_DEFAULT; /** + * Value for {@link #preferMinimalPostProcessing} indicating that by default + * minimal post processing is not preferred. + * + * @see android.R.attr#preferMinimalPostProcessing + * @hide + */ + public static final boolean MINIMAL_POST_PROCESSING_DEFAULT = false; + + /** * Indicates whether the activity wants the connected display to do minimal post processing on * the produced image or video frames. This will only be requested if this activity's main * window is visible on the screen. @@ -315,7 +324,7 @@ public class ActivityInfo extends ComponentInfo implements Parcelable { * @see android.view.WindowManager.LayoutParams#preferMinimalPostProcessing * @see android.view.Display#isMinimalPostProcessingSupported */ - public boolean preferMinimalPostProcessing = false; + public boolean preferMinimalPostProcessing = MINIMAL_POST_PROCESSING_DEFAULT; /** * Bit in {@link #flags} indicating whether this activity is able to diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java index 87acbc146f49..fd4c26569873 100644 --- a/core/java/android/content/pm/PackageParser.java +++ b/core/java/android/content/pm/PackageParser.java @@ -59,7 +59,6 @@ import android.content.pm.PackageParserCacheHelper.ReadHelper; import android.content.pm.PackageParserCacheHelper.WriteHelper; import android.content.pm.parsing.AndroidPackage; import android.content.pm.parsing.ApkParseUtils; -import android.content.pm.parsing.ComponentParseUtils; import android.content.pm.parsing.PackageImpl; import android.content.pm.parsing.PackageInfoUtils; import android.content.pm.parsing.ParsedPackage; @@ -4350,6 +4349,7 @@ public class PackageParser { a.info.directBootAware = false; a.info.rotationAnimation = ROTATION_ANIMATION_UNSPECIFIED; a.info.colorMode = ActivityInfo.COLOR_MODE_DEFAULT; + a.info.preferMinimalPostProcessing = ActivityInfo.MINIMAL_POST_PROCESSING_DEFAULT; if (hardwareAccelerated) { a.info.flags |= ActivityInfo.FLAG_HARDWARE_ACCELERATED; } @@ -4564,6 +4564,10 @@ public class PackageParser { a.info.colorMode = sa.getInt(R.styleable.AndroidManifestActivity_colorMode, ActivityInfo.COLOR_MODE_DEFAULT); + a.info.preferMinimalPostProcessing = sa.getBoolean( + R.styleable.AndroidManifestActivity_preferMinimalPostProcessing, + ActivityInfo.MINIMAL_POST_PROCESSING_DEFAULT); + if (sa.getBoolean(R.styleable.AndroidManifestActivity_showWhenLocked, false)) { a.info.flags |= ActivityInfo.FLAG_SHOW_WHEN_LOCKED; } diff --git a/core/java/android/content/pm/parsing/ApkParseUtils.java b/core/java/android/content/pm/parsing/ApkParseUtils.java index 38d3137200c6..9b069acd1b06 100644 --- a/core/java/android/content/pm/parsing/ApkParseUtils.java +++ b/core/java/android/content/pm/parsing/ApkParseUtils.java @@ -2640,6 +2640,7 @@ public class ApkParseUtils { activity.directBootAware = false; activity.rotationAnimation = ROTATION_ANIMATION_UNSPECIFIED; activity.colorMode = ActivityInfo.COLOR_MODE_DEFAULT; + activity.preferMinimalPostProcessing = ActivityInfo.MINIMAL_POST_PROCESSING_DEFAULT; if (hardwareAccelerated) { activity.flags |= ActivityInfo.FLAG_HARDWARE_ACCELERATED; } diff --git a/core/java/android/content/pm/parsing/ComponentParseUtils.java b/core/java/android/content/pm/parsing/ComponentParseUtils.java index 56ace5ecfa18..3846202aa04d 100644 --- a/core/java/android/content/pm/parsing/ComponentParseUtils.java +++ b/core/java/android/content/pm/parsing/ComponentParseUtils.java @@ -553,6 +553,7 @@ public class ComponentParseUtils { public String requestedVrComponent; public int rotationAnimation = -1; public int colorMode; + public boolean preferMinimalPostProcessing; public int order; public ActivityInfo.WindowLayout windowLayout; @@ -640,6 +641,7 @@ public class ComponentParseUtils { dest.writeString(this.requestedVrComponent); dest.writeInt(this.rotationAnimation); dest.writeInt(this.colorMode); + dest.writeBoolean(this.preferMinimalPostProcessing); dest.writeInt(this.order); dest.writeBundle(this.metaData); @@ -685,6 +687,7 @@ public class ComponentParseUtils { this.requestedVrComponent = in.readString(); this.rotationAnimation = in.readInt(); this.colorMode = in.readInt(); + this.preferMinimalPostProcessing = in.readByte() != 0; this.order = in.readInt(); this.metaData = in.readBundle(); if (in.readInt() == 1) { @@ -1645,6 +1648,10 @@ public class ComponentParseUtils { result.colorMode = sa.getInt(R.styleable.AndroidManifestActivity_colorMode, ActivityInfo.COLOR_MODE_DEFAULT); + result.preferMinimalPostProcessing = sa.getBoolean( + R.styleable.AndroidManifestActivity_preferMinimalPostProcessing, + ActivityInfo.MINIMAL_POST_PROCESSING_DEFAULT); + if (sa.getBoolean(R.styleable.AndroidManifestActivity_showWhenLocked, false)) { result.flags |= ActivityInfo.FLAG_SHOW_WHEN_LOCKED; } diff --git a/core/java/android/content/pm/parsing/PackageInfoUtils.java b/core/java/android/content/pm/parsing/PackageInfoUtils.java index 73a8d2a7dc0f..e0ba99bb4937 100644 --- a/core/java/android/content/pm/parsing/PackageInfoUtils.java +++ b/core/java/android/content/pm/parsing/PackageInfoUtils.java @@ -345,6 +345,7 @@ public class PackageInfoUtils { ai.requestedVrComponent = a.requestedVrComponent; ai.rotationAnimation = a.rotationAnimation; ai.colorMode = a.colorMode; + ai.preferMinimalPostProcessing = a.preferMinimalPostProcessing; ai.windowLayout = a.windowLayout; ai.metaData = a.metaData; ai.applicationInfo = applicationInfo; diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index b97482a30cc0..eee8fb13d3a6 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -7488,6 +7488,21 @@ public final class Settings { public static final String INCALL_POWER_BUTTON_BEHAVIOR = "incall_power_button_behavior"; /** + * Whether the user allows minimal post processing or not. + * + * <p>Values: + * 0 - Not allowed. Any preferences set through the Window.setPreferMinimalPostProcessing + * API will be ignored. + * 1 - Allowed. Any preferences set through the Window.setPreferMinimalPostProcessing API + * will be respected and the appropriate signals will be sent to display. + * (Default behaviour) + * + * @hide + */ + public static final String MINIMAL_POST_PROCESSING_ALLOWED = + "minimal_post_processing_allowed"; + + /** * INCALL_POWER_BUTTON_BEHAVIOR value for "turn off screen". * @hide */ diff --git a/core/java/android/view/InsetsController.java b/core/java/android/view/InsetsController.java index 9bc8dce71856..e890bda097f1 100644 --- a/core/java/android/view/InsetsController.java +++ b/core/java/android/view/InsetsController.java @@ -28,7 +28,6 @@ import android.annotation.IntDef; import android.annotation.NonNull; import android.graphics.Insets; import android.graphics.Rect; -import android.net.InvalidPacketException.ErrorCode; import android.os.RemoteException; import android.util.ArraySet; import android.util.Log; @@ -148,13 +147,18 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation } } - private class DefaultAnimationControlListener implements WindowInsetsAnimationControlListener { + /** + * The default implementation of listener, to be used by InsetsController and InsetsPolicy to + * animate insets. + */ + public static class InternalAnimationControlListener + implements WindowInsetsAnimationControlListener { private WindowInsetsAnimationController mController; private ObjectAnimator mAnimator; - private boolean mShow; + protected boolean mShow; - DefaultAnimationControlListener(boolean show) { + InternalAnimationControlListener(boolean show) { mShow = show; } @@ -178,9 +182,9 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation onAnimationFinish(); } }); - mStartingAnimation = true; + setStartingAnimation(true); mAnimator.start(); - mStartingAnimation = false; + setStartingAnimation(false); } @Override @@ -191,16 +195,19 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation } } - private void onAnimationFinish() { + protected void setStartingAnimation(boolean startingAnimation) { + } + + protected void onAnimationFinish() { mController.finish(mShow); } - private float getRawProgress() { + protected float getRawProgress() { float fraction = (float) mAnimator.getCurrentPlayTime() / mAnimator.getDuration(); return mShow ? fraction : 1 - fraction; } - private long getDurationMs() { + protected long getDurationMs() { if (mAnimator != null) { return mAnimator.getDuration(); } @@ -222,6 +229,17 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation final @AnimationType int type; } + private class DefaultAnimationControlListener extends InternalAnimationControlListener { + DefaultAnimationControlListener(boolean show) { + super(show); + } + + @Override + protected void setStartingAnimation(boolean startingAnimation) { + mStartingAnimation = startingAnimation; + } + } + private final String TAG = "InsetsControllerImpl"; private final InsetsState mState = new InsetsState(); diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java index b891af52a887..513e72f27901 100644 --- a/core/java/android/widget/Editor.java +++ b/core/java/android/widget/Editor.java @@ -21,6 +21,7 @@ import android.animation.ValueAnimator; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; +import android.app.AppGlobals; import android.app.PendingIntent; import android.app.PendingIntent.CanceledException; import android.app.RemoteAction; @@ -384,6 +385,10 @@ public class Editor { private final SuggestionHelper mSuggestionHelper = new SuggestionHelper(); + // Specifies whether the cursor control feature set is enabled. + // This can only be true if the text view is editable. + private final boolean mCursorControlEnabled; + Editor(TextView textView) { mTextView = textView; // Synchronize the filter list, which places the undo input filter at the end. @@ -397,6 +402,13 @@ public class Editor { Magnifier.createBuilderWithOldMagnifierDefaults(mTextView).build(); mMagnifierAnimator = new MagnifierMotionAnimator(magnifier); } + + mCursorControlEnabled = AppGlobals.getIntCoreSetting( + WidgetFlags.KEY_ENABLE_CURSOR_CONTROL , 0) != 0; + if (TextView.DEBUG_CURSOR) { + logCursor("Editor", "Cursor control is %s.", + mCursorControlEnabled ? "enabled" : "disabled"); + } } ParcelableParcel saveInstanceState() { diff --git a/core/java/android/widget/WidgetFlags.java b/core/java/android/widget/WidgetFlags.java new file mode 100644 index 000000000000..fa1e498d55b6 --- /dev/null +++ b/core/java/android/widget/WidgetFlags.java @@ -0,0 +1,40 @@ +/* + Copyright (C) 2019 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.widget; + +/** + * Keeps the flags related to the Widget namespace in {@link DeviceConfig}. + * + * @hide + */ +public final class WidgetFlags { + + /** + * Whether the cursor control feature set is enabled. + * TODO: Makes this flag key visible to webview/chrome. + */ + public static final String ENABLE_CURSOR_CONTROL = + "CursorControlFeature__enable_cursor_control"; + + /** + * The key name used in app core settings for enable cursor control. + */ + public static final String KEY_ENABLE_CURSOR_CONTROL = "widget__enable_cursor_control"; + + private WidgetFlags() { + } +} diff --git a/media/java/android/media/MediaRoute2Info.java b/media/java/android/media/MediaRoute2Info.java index 239dfed051ee..eae13d0062e8 100644 --- a/media/java/android/media/MediaRoute2Info.java +++ b/media/java/android/media/MediaRoute2Info.java @@ -134,6 +134,59 @@ public final class MediaRoute2Info implements Parcelable { */ public static final int DEVICE_TYPE_BLUETOOTH = 3; + /** + * Media feature: Live audio. + * <p> + * A route that supports live audio routing will allow the media audio stream + * to be sent to supported destinations. This can include internal speakers or + * audio jacks on the device itself, A2DP devices, and more. + * </p><p> + * When a live audio route is selected, audio routing is transparent to the application. + * All audio played on the media stream will be routed to the selected destination. + * </p><p> + * Refer to the class documentation for details about live audio routes. + * </p> + */ + public static final String FEATURE_LIVE_AUDIO = "android.media.intent.category.LIVE_AUDIO"; + + /** + * Media feature: Live video. + * <p> + * A route that supports live video routing will allow a mirrored version + * of the device's primary display or a customized + * {@link android.app.Presentation Presentation} to be sent to supported + * destinations. + * </p><p> + * When a live video route is selected, audio and video routing is transparent + * to the application. By default, audio and video is routed to the selected + * destination. For certain live video routes, the application may also use a + * {@link android.app.Presentation Presentation} to replace the mirrored view + * on the external display with different content. + * </p><p> + * Refer to the class documentation for details about live video routes. + * </p> + * + * @see android.app.Presentation + */ + public static final String FEATURE_LIVE_VIDEO = "android.media.intent.category.LIVE_VIDEO"; + + /** + * Media feature: Remote playback. + * <p> + * A route that supports remote playback routing will allow an application to send + * requests to play content remotely to supported destinations. + * </p><p> + * Remote playback routes destinations operate independently of the local device. + * When a remote playback route is selected, the application can control the content + * playing on the destination using {@link MediaRouter2.RoutingController#getControlHints()}. + * The application may also receive status updates from the route regarding remote playback. + * </p><p> + * Refer to the class documentation for details about remote playback routes. + * </p> + */ + public static final String FEATURE_REMOTE_PLAYBACK = + "android.media.intent.category.REMOTE_PLAYBACK"; + final String mId; final CharSequence mName; final List<String> mFeatures; @@ -260,9 +313,8 @@ public final class MediaRoute2Info implements Parcelable { } /** - * Gets the package name of the client that uses the route. - * Returns null if no clients use this route. - * @hide + * Gets the package name of the app using the route. + * Returns null if no apps are using this route. */ @Nullable public String getClientPackageName() { diff --git a/media/java/android/media/MediaRoute2ProviderService.java b/media/java/android/media/MediaRoute2ProviderService.java index 6bfa851804a1..1e8b18808891 100644 --- a/media/java/android/media/MediaRoute2ProviderService.java +++ b/media/java/android/media/MediaRoute2ProviderService.java @@ -18,6 +18,7 @@ package android.media; import static com.android.internal.util.function.pooled.PooledLambda.obtainMessage; +import android.annotation.CallSuper; import android.annotation.NonNull; import android.annotation.Nullable; import android.app.Service; @@ -64,7 +65,6 @@ public abstract class MediaRoute2ProviderService extends Service { * request. * * @see #notifySessionCreated(RoutingSessionInfo, long) - * @hide */ public static final long REQUEST_ID_UNKNOWN = 0; @@ -82,8 +82,14 @@ public abstract class MediaRoute2ProviderService extends Service { mHandler = new Handler(Looper.getMainLooper()); } + /** + * If overriding this method, call through to the super method for any unknown actions. + * <p> + * {@inheritDoc} + */ + @CallSuper @Override - @NonNull + @Nullable public IBinder onBind(@NonNull Intent intent) { //TODO: Allow binding from media router service only? if (SERVICE_INTERFACE.equals(intent.getAction())) { @@ -110,7 +116,6 @@ public abstract class MediaRoute2ProviderService extends Service { * * @param routeId the id of the route * @param volume the target volume - * @hide */ public abstract void onSetVolume(@NonNull String routeId, int volume); @@ -119,7 +124,6 @@ public abstract class MediaRoute2ProviderService extends Service { * * @param routeId id of the route * @param delta the delta to add to the current volume - * @hide */ public abstract void onUpdateVolume(@NonNull String routeId, int delta); @@ -129,7 +133,6 @@ public abstract class MediaRoute2ProviderService extends Service { * @param sessionId id of the session * @return information of the session with the given id. * null if the session is released or ID is not valid. - * @hide */ @Nullable public final RoutingSessionInfo getSessionInfo(@NonNull String sessionId) { @@ -143,7 +146,6 @@ public abstract class MediaRoute2ProviderService extends Service { /** * Gets the list of {@link RoutingSessionInfo session info} that the provider service maintains. - * @hide */ @NonNull public final List<RoutingSessionInfo> getAllSessionInfo() { @@ -163,7 +165,7 @@ public abstract class MediaRoute2ProviderService extends Service { * @param requestId id of the previous request to create this session provided in * {@link #onCreateSession(String, String, long, Bundle)} * @see #onCreateSession(String, String, long, Bundle) - * @hide + * @see #getSessionInfo(String) */ public final void notifySessionCreated(@NonNull RoutingSessionInfo sessionInfo, long requestId) { @@ -197,7 +199,6 @@ public abstract class MediaRoute2ProviderService extends Service { * @param requestId id of the previous request to create the session provided in * {@link #onCreateSession(String, String, long, Bundle)}. * @see #onCreateSession(String, String, long, Bundle) - * @hide */ public final void notifySessionCreationFailed(long requestId) { if (mClient == null) { @@ -213,8 +214,6 @@ public abstract class MediaRoute2ProviderService extends Service { /** * Notifies the existing session is updated. For example, when * {@link RoutingSessionInfo#getSelectedRoutes() selected routes} are changed. - * - * @hide */ public final void notifySessionUpdated(@NonNull RoutingSessionInfo sessionInfo) { Objects.requireNonNull(sessionInfo, "sessionInfo must not be null"); @@ -244,7 +243,6 @@ public abstract class MediaRoute2ProviderService extends Service { * * @param sessionId id of the released session. * @see #onReleaseSession(String) - * @hide */ public final void notifySessionReleased(@NonNull String sessionId) { if (TextUtils.isEmpty(sessionId)) { @@ -296,7 +294,6 @@ public abstract class MediaRoute2ProviderService extends Service { * @see RoutingSessionInfo.Builder#Builder(String, String) * @see RoutingSessionInfo.Builder#addSelectedRoute(String) * @see RoutingSessionInfo.Builder#setControlHints(Bundle) - * @hide */ public abstract void onCreateSession(@NonNull String packageName, @NonNull String routeId, long requestId, @Nullable Bundle sessionHints); @@ -314,7 +311,6 @@ public abstract class MediaRoute2ProviderService extends Service { * @param sessionId id of the session being released. * @see #notifySessionReleased(String) * @see #getSessionInfo(String) - * @hide */ public abstract void onReleaseSession(@NonNull String sessionId); @@ -326,7 +322,6 @@ public abstract class MediaRoute2ProviderService extends Service { * * @param sessionId id of the session * @param routeId id of the route - * @hide */ public abstract void onSelectRoute(@NonNull String sessionId, @NonNull String routeId); @@ -338,7 +333,6 @@ public abstract class MediaRoute2ProviderService extends Service { * * @param sessionId id of the session * @param routeId id of the route - * @hide */ public abstract void onDeselectRoute(@NonNull String sessionId, @NonNull String routeId); @@ -350,7 +344,6 @@ public abstract class MediaRoute2ProviderService extends Service { * * @param sessionId id of the session * @param routeId id of the route - * @hide */ public abstract void onTransferToRoute(@NonNull String sessionId, @NonNull String routeId); @@ -370,9 +363,8 @@ public abstract class MediaRoute2ProviderService extends Service { * </p> * * @param preference the new discovery preference - * - * TODO: This method needs tests. */ + // TODO: This method needs tests. public void onDiscoveryPreferenceChanged(@NonNull RouteDiscoveryPreference preference) {} /** diff --git a/media/java/android/media/MediaRouter2.java b/media/java/android/media/MediaRouter2.java index a6198842abe8..18670e9a6fe2 100644 --- a/media/java/android/media/MediaRouter2.java +++ b/media/java/android/media/MediaRouter2.java @@ -35,6 +35,7 @@ import android.util.Log; import com.android.internal.annotations.GuardedBy; import java.util.ArrayList; +import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.List; @@ -49,9 +50,9 @@ import java.util.stream.Collectors; * Media Router 2 allows applications to control the routing of media channels * and streams from the current device to remote speakers and devices. * - * TODO: Add method names at the beginning of log messages. (e.g. changeSessionInfoOnHandler) - * Not only MediaRouter2, but also to service / manager / provider. */ +// TODO: Add method names at the beginning of log messages. (e.g. updateControllerOnHandler) +// Not only MediaRouter2, but also to service / manager / provider. public class MediaRouter2 { private static final String TAG = "MR2"; private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); @@ -66,17 +67,17 @@ public class MediaRouter2 { private final CopyOnWriteArrayList<RouteCallbackRecord> mRouteCallbackRecords = new CopyOnWriteArrayList<>(); - private final CopyOnWriteArrayList<SessionCallbackRecord> mSessionCallbackRecords = + private final CopyOnWriteArrayList<ControllerCallbackRecord> mControllerCallbackRecords = new CopyOnWriteArrayList<>(); - private final CopyOnWriteArrayList<SessionCreationRequest> mSessionCreationRequests = + private final CopyOnWriteArrayList<ControllerCreationRequest> mControllerCreationRequests = new CopyOnWriteArrayList<>(); private final String mPackageName; @GuardedBy("sRouterLock") final Map<String, MediaRoute2Info> mRoutes = new HashMap<>(); - final RoutingController mDefaultController; + final RoutingController mSystemController; @GuardedBy("sRouterLock") private RouteDiscoveryPreference mDiscoveryPreference = RouteDiscoveryPreference.EMPTY; @@ -88,13 +89,13 @@ public class MediaRouter2 { @GuardedBy("sRouterLock") private Map<String, RoutingController> mRoutingControllers = new ArrayMap<>(); - private AtomicInteger mSessionCreationRequestCnt = new AtomicInteger(1); + private AtomicInteger mControllerCreationRequestCnt = new AtomicInteger(1); final Handler mHandler; @GuardedBy("sRouterLock") private boolean mShouldUpdateRoutes; private volatile List<MediaRoute2Info> mFilteredRoutes = Collections.emptyList(); - private volatile OnCreateSessionListener mOnCreateSessionListener; + private volatile OnGetControllerHintsListener mOnGetControllerHintsListener; /** * Gets an instance of the media router associated with the context. @@ -137,7 +138,7 @@ public class MediaRouter2 { for (MediaRoute2Info route : currentSystemRoutes) { mRoutes.put(route.getId(), route); } - mDefaultController = new DefaultRoutingController(currentSystemSessionInfo); + mSystemController = new SystemRoutingController(currentSystemSessionInfo); } /** @@ -251,23 +252,22 @@ public class MediaRouter2 { } /** - * Registers a callback to get updates on creations and changes of routing sessions. + * Registers a callback to get updates on creations and changes of + * {@link RoutingController routing controllers}. * If you register the same callback twice or more, it will be ignored. * * @param executor the executor to execute the callback on * @param callback the callback to register - * @see #unregisterSessionCallback - * @hide + * @see #unregisterControllerCallback */ - @NonNull - public void registerSessionCallback(@CallbackExecutor Executor executor, - @NonNull SessionCallback callback) { + public void registerControllerCallback(@NonNull @CallbackExecutor Executor executor, + @NonNull RoutingControllerCallback callback) { Objects.requireNonNull(executor, "executor must not be null"); Objects.requireNonNull(callback, "callback must not be null"); - SessionCallbackRecord record = new SessionCallbackRecord(executor, callback); - if (!mSessionCallbackRecords.addIfAbsent(record)) { - Log.w(TAG, "Ignoring the same session callback"); + ControllerCallbackRecord record = new ControllerCallbackRecord(executor, callback); + if (!mControllerCallbackRecords.addIfAbsent(record)) { + Log.w(TAG, "Ignoring the same controller callback"); return; } } @@ -277,59 +277,54 @@ public class MediaRouter2 { * If the callback has not been added or been removed already, it is ignored. * * @param callback the callback to unregister - * @see #registerSessionCallback - * @hide + * @see #registerControllerCallback */ - @NonNull - public void unregisterSessionCallback(@NonNull SessionCallback callback) { + public void unregisterControllerCallback(@NonNull RoutingControllerCallback callback) { Objects.requireNonNull(callback, "callback must not be null"); - if (!mSessionCallbackRecords.remove(new SessionCallbackRecord(null, callback))) { - Log.w(TAG, "Ignoring unknown session callback"); + if (!mControllerCallbackRecords.remove(new ControllerCallbackRecord(null, callback))) { + Log.w(TAG, "Ignoring unknown controller callback"); return; } } /** - * Sets an {@link OnCreateSessionListener} to send hints when creating a session. - * To send the hints, listener should be set <em>BEFORE</em> calling - * {@link #requestCreateSession(MediaRoute2Info)}. + * Sets an {@link OnGetControllerHintsListener} to send hints when creating a + * {@link RoutingController}. To send the hints, listener should be set <em>BEFORE</em> calling + * {@link #requestCreateController(MediaRoute2Info)}. * - * @param listener A listener to send optional app-specific hints when creating a session. + * @param listener A listener to send optional app-specific hints when creating a controller. * {@code null} for unset. - * @hide */ - public void setOnCreateSessionListener(@Nullable OnCreateSessionListener listener) { - mOnCreateSessionListener = listener; + public void setOnGetControllerHintsListener(@Nullable OnGetControllerHintsListener listener) { + mOnGetControllerHintsListener = listener; } /** - * Requests the media route provider service to create a session with the given route. + * Requests the media route provider service to create a {@link RoutingController} + * with the given route. * - * @param route the route you want to create a session with. + * @param route the route you want to create a controller with. * - * @see SessionCallback#onSessionCreated - * @see SessionCallback#onSessionCreationFailed - * @hide + * @see RoutingControllerCallback#onControllerCreated + * @see RoutingControllerCallback#onControllerCreationFailed */ - @NonNull - public void requestCreateSession(@NonNull MediaRoute2Info route) { + public void requestCreateController(@NonNull MediaRoute2Info route) { Objects.requireNonNull(route, "route must not be null"); // TODO: Check the given route exists final int requestId; - requestId = mSessionCreationRequestCnt.getAndIncrement(); - - SessionCreationRequest request = new SessionCreationRequest(requestId, route); - mSessionCreationRequests.add(request); + requestId = mControllerCreationRequestCnt.getAndIncrement(); + ControllerCreationRequest request = new ControllerCreationRequest(requestId, route); + mControllerCreationRequests.add(request); - OnCreateSessionListener listener = mOnCreateSessionListener; - Bundle sessionHints = null; + OnGetControllerHintsListener listener = mOnGetControllerHintsListener; + Bundle controllerHints = null; if (listener != null) { - sessionHints = listener.onCreateSession(route); - if (sessionHints != null) { - sessionHints = new Bundle(sessionHints); + controllerHints = listener.onGetControllerHints(route); + if (controllerHints != null) { + controllerHints = new Bundle(controllerHints); } } @@ -339,10 +334,9 @@ public class MediaRouter2 { } if (client != null) { try { - mMediaRouterService.requestCreateSession(client, route, requestId, - sessionHints); + mMediaRouterService.requestCreateSession(client, route, requestId, controllerHints); } catch (RemoteException ex) { - Log.e(TAG, "Unable to request to create session.", ex); + Log.e(TAG, "Unable to request to create controller.", ex); mHandler.sendMessage(obtainMessage(MediaRouter2::createControllerOnHandler, MediaRouter2.this, null, requestId)); } @@ -353,16 +347,35 @@ public class MediaRouter2 { * Gets a {@link RoutingController} which can control the routes provided by system. * e.g. Phone speaker, wired headset, Bluetooth, etc. * <p> - * Note: The default controller can't be released. Calling {@link RoutingController#release()} - * will be no-op. + * Note: The system controller can't be released. Calling {@link RoutingController#release()} + * will be ignored. * <p> * This method will always return the same instance. - * - * @hide */ @NonNull - public RoutingController getDefaultController() { - return mDefaultController; + public RoutingController getSystemController() { + return mSystemController; + } + + /** + * Gets the list of currently non-released {@link RoutingController routing controllers}. + * <p> + * Note: The list returned here will never be empty. The first element in the list is + * always the {@link #getSystemController() system controller}. + */ + @NonNull + public List<RoutingController> getControllers() { + List<RoutingController> result = new ArrayList<>(); + result.add(0, mSystemController); + + Collection<RoutingController> controllers; + synchronized (sRouterLock) { + controllers = mRoutingControllers.values(); + if (controllers != null) { + result.addAll(controllers); + } + } + return result; } /** @@ -493,15 +506,15 @@ public class MediaRouter2 { } /** - * Creates a controller and calls the {@link SessionCallback#onSessionCreated}. - * If session creation has failed, then it calls - * {@link SessionCallback#onSessionCreationFailed}. + * Creates a controller and calls the {@link RoutingControllerCallback#onControllerCreated}. + * If the controller creation has failed, then it calls + * {@link RoutingControllerCallback#onControllerCreationFailed}. * <p> * Pass {@code null} to sessionInfo for the failure case. */ void createControllerOnHandler(@Nullable RoutingSessionInfo sessionInfo, int requestId) { - SessionCreationRequest matchingRequest = null; - for (SessionCreationRequest request : mSessionCreationRequests) { + ControllerCreationRequest matchingRequest = null; + for (ControllerCreationRequest request : mControllerCreationRequests) { if (request.mRequestId == requestId) { matchingRequest = request; break; @@ -509,21 +522,21 @@ public class MediaRouter2 { } if (matchingRequest != null) { - mSessionCreationRequests.remove(matchingRequest); + mControllerCreationRequests.remove(matchingRequest); MediaRoute2Info requestedRoute = matchingRequest.mRoute; if (sessionInfo == null) { // TODO: We may need to distinguish between failure and rejection. // One way can be introducing 'reason'. - notifySessionCreationFailed(requestedRoute); + notifyControllerCreationFailed(requestedRoute); return; } else if (!sessionInfo.getSelectedRoutes().contains(requestedRoute.getId())) { Log.w(TAG, "The session does not contain the requested route. " + "(requestedRouteId=" + requestedRoute.getId() + ", actualRoutes=" + sessionInfo.getSelectedRoutes() + ")"); - notifySessionCreationFailed(requestedRoute); + notifyControllerCreationFailed(requestedRoute); return; } else if (!TextUtils.equals(requestedRoute.getProviderId(), sessionInfo.getProviderId())) { @@ -531,7 +544,7 @@ public class MediaRouter2 { + "(requested route's providerId=" + requestedRoute.getProviderId() + ", actual providerId=" + sessionInfo.getProviderId() + ")"); - notifySessionCreationFailed(requestedRoute); + notifyControllerCreationFailed(requestedRoute); return; } } @@ -539,24 +552,23 @@ public class MediaRouter2 { if (sessionInfo != null) { RoutingController controller = new RoutingController(sessionInfo); synchronized (sRouterLock) { - mRoutingControllers.put(controller.getSessionId(), controller); + mRoutingControllers.put(controller.getId(), controller); } - notifySessionCreated(controller); + notifyControllerCreated(controller); } } - void changeSessionInfoOnHandler(RoutingSessionInfo sessionInfo) { + void updateControllerOnHandler(RoutingSessionInfo sessionInfo) { if (sessionInfo == null) { - Log.w(TAG, "changeSessionInfoOnHandler: Ignoring null sessionInfo."); + Log.w(TAG, "updateControllerOnHandler: Ignoring null sessionInfo."); return; } if (sessionInfo.isSystemSession()) { // The session info is sent from SystemMediaRoute2Provider. - RoutingController defaultController = getDefaultController(); - RoutingSessionInfo oldInfo = defaultController.getRoutingSessionInfo(); - defaultController.setRoutingSessionInfo(sessionInfo); - notifySessionInfoChanged(defaultController, oldInfo, sessionInfo); + RoutingController systemController = getSystemController(); + systemController.setRoutingSessionInfo(sessionInfo); + notifyControllerUpdated(systemController); return; } @@ -566,20 +578,20 @@ public class MediaRouter2 { } if (matchingController == null) { - Log.w(TAG, "changeSessionInfoOnHandler: Matching controller not found. uniqueSessionId=" + Log.w(TAG, "updateControllerOnHandler: Matching controller not found. uniqueSessionId=" + sessionInfo.getId()); return; } RoutingSessionInfo oldInfo = matchingController.getRoutingSessionInfo(); if (!TextUtils.equals(oldInfo.getProviderId(), sessionInfo.getProviderId())) { - Log.w(TAG, "changeSessionInfoOnHandler: Provider IDs are not matched. old=" + Log.w(TAG, "updateControllerOnHandler: Provider IDs are not matched. old=" + oldInfo.getProviderId() + ", new=" + sessionInfo.getProviderId()); return; } matchingController.setRoutingSessionInfo(sessionInfo); - notifySessionInfoChanged(matchingController, oldInfo, sessionInfo); + notifyControllerUpdated(matchingController); } void releaseControllerOnHandler(RoutingSessionInfo sessionInfo) { @@ -609,11 +621,15 @@ public class MediaRouter2 { return; } + boolean removed; synchronized (sRouterLock) { - mRoutingControllers.remove(uniqueSessionId, matchingController); + removed = mRoutingControllers.remove(uniqueSessionId, matchingController); + } + + if (removed) { + matchingController.release(); + notifyControllerReleased(matchingController); } - matchingController.release(); - notifyControllerReleased(matchingController); } private List<MediaRoute2Info> filterRoutes(List<MediaRoute2Info> routes, @@ -654,33 +670,31 @@ public class MediaRouter2 { } } - private void notifySessionCreated(RoutingController controller) { - for (SessionCallbackRecord record: mSessionCallbackRecords) { + private void notifyControllerCreated(RoutingController controller) { + for (ControllerCallbackRecord record: mControllerCallbackRecords) { record.mExecutor.execute( - () -> record.mSessionCallback.onSessionCreated(controller)); + () -> record.mControllerCallback.onControllerCreated(controller)); } } - private void notifySessionCreationFailed(MediaRoute2Info route) { - for (SessionCallbackRecord record: mSessionCallbackRecords) { + private void notifyControllerCreationFailed(MediaRoute2Info route) { + for (ControllerCallbackRecord record: mControllerCallbackRecords) { record.mExecutor.execute( - () -> record.mSessionCallback.onSessionCreationFailed(route)); + () -> record.mControllerCallback.onControllerCreationFailed(route)); } } - private void notifySessionInfoChanged(RoutingController controller, - RoutingSessionInfo oldInfo, RoutingSessionInfo newInfo) { - for (SessionCallbackRecord record: mSessionCallbackRecords) { + private void notifyControllerUpdated(RoutingController controller) { + for (ControllerCallbackRecord record: mControllerCallbackRecords) { record.mExecutor.execute( - () -> record.mSessionCallback.onSessionInfoChanged( - controller, oldInfo, newInfo)); + () -> record.mControllerCallback.onControllerUpdated(controller)); } } private void notifyControllerReleased(RoutingController controller) { - for (SessionCallbackRecord record: mSessionCallbackRecords) { + for (ControllerCallbackRecord record: mControllerCallbackRecords) { record.mExecutor.execute( - () -> record.mSessionCallback.onSessionReleased(controller)); + () -> record.mControllerCallback.onControllerReleased(controller)); } } @@ -707,98 +721,84 @@ public class MediaRouter2 { * Called when routes are changed. For example, it is called when the route's name * or volume have been changed. * - * TODO: Write here what the developers should do when this method is called. - * How they can find the exact point how a route is changed? - * It can be a volume, name, client package name, .... - * * @param routes the list of routes that have been changed. It's never empty. */ public void onRoutesChanged(@NonNull List<MediaRoute2Info> routes) {} } /** - * Callback for receiving a result of session creation and session updates. - * @hide + * Callback for receiving a result of {@link RoutingController} creation and updates. */ - public static class SessionCallback { + public static class RoutingControllerCallback { /** - * Called when the routing session is created by the route provider. + * Called when the {@link RoutingController} is created. + * A {@link RoutingController} can be created by calling + * {@link #requestCreateController(MediaRoute2Info)}, or by the system. * - * @param controller the controller to control the created session + * @param controller the controller to control routes */ - public void onSessionCreated(@NonNull RoutingController controller) {} + public void onControllerCreated(@NonNull RoutingController controller) {} /** - * Called when the session creation request failed. + * Called when the controller creation request failed. * - * @param requestedRoute the route info which was used for the request + * @param requestedRoute the route info which was used for the creation request */ - public void onSessionCreationFailed(@NonNull MediaRoute2Info requestedRoute) {} + public void onControllerCreationFailed(@NonNull MediaRoute2Info requestedRoute) {} /** - * Called when the session info has changed. - * - * @param oldInfo the session info before the session changed. - * @prarm newInfo the changed session info + * Called when the controller is updated. * - * TODO: (Discussion) Do we really need newInfo? The controller has the newInfo. - * However. there can be timing issue if there is no newInfo. + * @param controller the updated controller. Can be the system controller. + * @see #getSystemController() */ - public void onSessionInfoChanged(@NonNull RoutingController controller, - @NonNull RoutingSessionInfo oldInfo, - @NonNull RoutingSessionInfo newInfo) {} + public void onControllerUpdated(@NonNull RoutingController controller) {} /** - * Called when the session is released by {@link MediaRoute2ProviderService}. - * Before this method is called, the controller would be released by the system, - * which means the {@link RoutingController#isReleased()} will always return true + * Called when a routing controller is released. It can be released in two cases: + * <ul> + * <li>When {@link RoutingController#release()} is called.</li> + * <li>When the remote session in the provider is destroyed.</li> + * </ul> + * {@link RoutingController#isReleased()} will always return {@code true} * for the {@code controller} here. - * <p> - * Note: Calling {@link RoutingController#release()} will <em>NOT</em> trigger - * this method to be called. - * - * TODO: Add tests for checking whether this method is called. - * TODO: When service process dies, this should be called. * + * @see RoutingController#release() * @see RoutingController#isReleased() */ - public void onSessionReleased(@NonNull RoutingController controller) {} + // TODO: Add tests for checking whether this method is called. + // TODO: When service process dies, this should be called. + public void onControllerReleased(@NonNull RoutingController controller) {} } /** - * A listener interface to send an optional app-specific hints when creating a session. - * - * @hide + * A listener interface to send an optional app-specific hints when creating the + * {@link RoutingController}. */ - public interface OnCreateSessionListener { + public interface OnGetControllerHintsListener { /** * Called when the {@link MediaRouter2} is about to request - * the media route provider service to create a session with the given route. - * The {@link Bundle} returned here will be sent to media route provider service as a hint - * for creating a session. - * <p> - * To send hints when creating the session, set this listener before calling - * {@link #requestCreateSession(MediaRoute2Info)}. + * the media route provider service to create a controller with the given route. + * The {@link Bundle} returned here will be sent to media route provider service as a hint. * <p> - * This will be called on the same thread which calls - * {@link #requestCreateSession(MediaRoute2Info)}. + * To send hints when creating the controller, set the listener before calling + * {@link #requestCreateController(MediaRoute2Info)}. The method will be called + * on the same thread which calls {@link #requestCreateController(MediaRoute2Info)}. * - * @param route The route to create session with + * @param route The route to create controller with * @return An optional bundle of app-specific arguments to send to the provider, * or null if none. The contents of this bundle may affect the result of - * session creation. + * controller creation. * @see MediaRoute2ProviderService#onCreateSession(String, String, long, Bundle) */ @Nullable - Bundle onCreateSession(@NonNull MediaRoute2Info route); + Bundle onGetControllerHints(@NonNull MediaRoute2Info route); } /** * A class to control media routing session in media route provider. * For example, selecting/deselcting/transferring routes to session can be done through this - * class. Instances are created by {@link MediaRouter2}. - * - * @hide + * class. Instances are created by {@link #requestCreateController(MediaRoute2Info)}. */ public class RoutingController { private final Object mControllerLock = new Object(); @@ -814,9 +814,10 @@ public class MediaRouter2 { } /** - * @return the ID of the session + * @return the ID of the controller */ - public String getSessionId() { + @NonNull + public String getId() { synchronized (mControllerLock) { return mSessionInfo.getId(); } @@ -873,7 +874,7 @@ public class MediaRouter2 { } /** - * Returns true if the session is released, false otherwise. + * Returns true if this controller is released, false otherwise. * If it is released, then all other getters from this instance may return invalid values. * Also, any operations to this instance will be ignored once released. * @@ -896,7 +897,7 @@ public class MediaRouter2 { * * @see #getSelectedRoutes() * @see #getSelectableRoutes() - * @see SessionCallback#onSessionInfoChanged + * @see RoutingControllerCallback#onControllerUpdated */ public void selectRoute(@NonNull MediaRoute2Info route) { Objects.requireNonNull(route, "route must not be null"); @@ -925,7 +926,7 @@ public class MediaRouter2 { } if (client != null) { try { - mMediaRouterService.selectRoute(client, getSessionId(), route); + mMediaRouterService.selectRoute(client, getId(), route); } catch (RemoteException ex) { Log.e(TAG, "Unable to select route for session.", ex); } @@ -943,7 +944,7 @@ public class MediaRouter2 { * * @see #getSelectedRoutes() * @see #getDeselectableRoutes() - * @see SessionCallback#onSessionInfoChanged + * @see RoutingControllerCallback#onControllerUpdated */ public void deselectRoute(@NonNull MediaRoute2Info route) { Objects.requireNonNull(route, "route must not be null"); @@ -972,7 +973,7 @@ public class MediaRouter2 { } if (client != null) { try { - mMediaRouterService.deselectRoute(client, getSessionId(), route); + mMediaRouterService.deselectRoute(client, getId(), route); } catch (RemoteException ex) { Log.e(TAG, "Unable to remove route from session.", ex); } @@ -990,7 +991,7 @@ public class MediaRouter2 { * * @see #getSelectedRoutes() * @see #getTransferrableRoutes() - * @see SessionCallback#onSessionInfoChanged + * @see RoutingControllerCallback#onControllerUpdated */ public void transferToRoute(@NonNull MediaRoute2Info route) { Objects.requireNonNull(route, "route must not be null"); @@ -1020,7 +1021,7 @@ public class MediaRouter2 { } if (client != null) { try { - mMediaRouterService.transferToRoute(client, getSessionId(), route); + mMediaRouterService.transferToRoute(client, getId(), route); } catch (RemoteException ex) { Log.e(TAG, "Unable to transfer to route for session.", ex); } @@ -1031,9 +1032,8 @@ public class MediaRouter2 { * Release this controller and corresponding session. * Any operations on this controller after calling this method will be ignored. * The devices that are playing media will stop playing it. - * - * TODO: Add tests using {@link MediaRouter2Manager#getActiveSessions()}. */ + // TODO: Add tests using {@link MediaRouter2Manager#getActiveSessions()}. public void release() { synchronized (mControllerLock) { if (mIsReleased) { @@ -1044,13 +1044,19 @@ public class MediaRouter2 { } Client2 client; + boolean removed; synchronized (sRouterLock) { - mRoutingControllers.remove(getSessionId(), this); + removed = mRoutingControllers.remove(getId(), this); client = mClient; } + + if (removed) { + mHandler.post(() -> notifyControllerReleased(RoutingController.this)); + } + if (client != null) { try { - mMediaRouterService.releaseSession(client, getSessionId()); + mMediaRouterService.releaseSession(client, getId()); } catch (RemoteException ex) { Log.e(TAG, "Unable to notify of controller release", ex); } @@ -1071,7 +1077,7 @@ public class MediaRouter2 { StringBuilder result = new StringBuilder() .append("RoutingController{ ") - .append("sessionId=").append(getSessionId()) + .append("id=").append(getId()) .append(", selectedRoutes={") .append(selectedRoutes) .append("}") @@ -1122,19 +1128,19 @@ public class MediaRouter2 { } } - class DefaultRoutingController extends RoutingController { - DefaultRoutingController(@NonNull RoutingSessionInfo sessionInfo) { + class SystemRoutingController extends RoutingController { + SystemRoutingController(@NonNull RoutingSessionInfo sessionInfo) { super(sessionInfo); } @Override public void release() { - // Do nothing. DefaultRoutingController will never be released + // Do nothing. SystemRoutingController will never be released } @Override public boolean isReleased() { - // DefaultRoutingController will never be released + // SystemRoutingController will never be released return false; } } @@ -1168,13 +1174,13 @@ public class MediaRouter2 { } } - final class SessionCallbackRecord { + final class ControllerCallbackRecord { public final Executor mExecutor; - public final SessionCallback mSessionCallback; + public final RoutingControllerCallback mControllerCallback; - SessionCallbackRecord(@NonNull Executor executor, - @NonNull SessionCallback sessionCallback) { - mSessionCallback = sessionCallback; + ControllerCallbackRecord(@NonNull Executor executor, + @NonNull RoutingControllerCallback controllerCallback) { + mControllerCallback = controllerCallback; mExecutor = executor; } @@ -1183,23 +1189,24 @@ public class MediaRouter2 { if (this == obj) { return true; } - if (!(obj instanceof SessionCallbackRecord)) { + if (!(obj instanceof ControllerCallbackRecord)) { return false; } - return mSessionCallback == ((SessionCallbackRecord) obj).mSessionCallback; + return mControllerCallback + == ((ControllerCallbackRecord) obj).mControllerCallback; } @Override public int hashCode() { - return mSessionCallback.hashCode(); + return mControllerCallback.hashCode(); } } - final class SessionCreationRequest { + final class ControllerCreationRequest { public final MediaRoute2Info mRoute; public final int mRequestId; - SessionCreationRequest(int requestId, @NonNull MediaRoute2Info route) { + ControllerCreationRequest(int requestId, @NonNull MediaRoute2Info route) { mRoute = route; mRequestId = requestId; } @@ -1235,7 +1242,7 @@ public class MediaRouter2 { @Override public void notifySessionInfoChanged(@Nullable RoutingSessionInfo sessionInfo) { - mHandler.sendMessage(obtainMessage(MediaRouter2::changeSessionInfoOnHandler, + mHandler.sendMessage(obtainMessage(MediaRouter2::updateControllerOnHandler, MediaRouter2.this, sessionInfo)); } diff --git a/media/java/android/media/RoutingSessionInfo.java b/media/java/android/media/RoutingSessionInfo.java index cb996f493eb4..5383ea219c57 100644 --- a/media/java/android/media/RoutingSessionInfo.java +++ b/media/java/android/media/RoutingSessionInfo.java @@ -31,7 +31,6 @@ import java.util.Objects; /** * Describes a routing session which is created when a media route is selected. - * @hide */ public final class RoutingSessionInfo implements Parcelable { @NonNull diff --git a/media/java/android/media/tv/tuner/Lnb.java b/media/java/android/media/tv/tuner/Lnb.java index a9a15d97e859..a8d2cba46440 100644 --- a/media/java/android/media/tv/tuner/Lnb.java +++ b/media/java/android/media/tv/tuner/Lnb.java @@ -126,25 +126,21 @@ public class Lnb implements AutoCloseable { /** * Outgoing Diseqc message overflow. - * @hide */ public static final int EVENT_TYPE_DISEQC_RX_OVERFLOW = Constants.LnbEventType.DISEQC_RX_OVERFLOW; /** * Outgoing Diseqc message isn't delivered on time. - * @hide */ public static final int EVENT_TYPE_DISEQC_RX_TIMEOUT = Constants.LnbEventType.DISEQC_RX_TIMEOUT; /** * Incoming Diseqc message has parity error. - * @hide */ public static final int EVENT_TYPE_DISEQC_RX_PARITY_ERROR = Constants.LnbEventType.DISEQC_RX_PARITY_ERROR; /** * LNB is overload. - * @hide */ public static final int EVENT_TYPE_LNB_OVERLOAD = Constants.LnbEventType.LNB_OVERLOAD; @@ -162,8 +158,7 @@ public class Lnb implements AutoCloseable { mId = id; } - /** @hide */ - public void setCallback(@Nullable LnbCallback callback) { + void setCallback(@Nullable LnbCallback callback) { mCallback = callback; if (mCallback == null) { return; diff --git a/media/java/android/media/tv/tuner/LnbCallback.java b/media/java/android/media/tv/tuner/LnbCallback.java index 5155f604b77b..78624701c8e0 100644 --- a/media/java/android/media/tv/tuner/LnbCallback.java +++ b/media/java/android/media/tv/tuner/LnbCallback.java @@ -17,6 +17,8 @@ package android.media.tv.tuner; +import android.annotation.NonNull; +import android.annotation.SystemApi; import android.media.tv.tuner.Lnb.EventType; /** @@ -24,6 +26,7 @@ import android.media.tv.tuner.Lnb.EventType; * * @hide */ +@SystemApi public interface LnbCallback { /** * Invoked when there is a LNB event. @@ -37,5 +40,5 @@ public interface LnbCallback { * Equipment Control) message which is specified by EUTELSAT Bus Functional * Specification Version 4.2. */ - void onDiseqcMessage(byte[] diseqcMessage); + void onDiseqcMessage(@NonNull byte[] diseqcMessage); } diff --git a/media/java/android/media/tv/tuner/Tuner.java b/media/java/android/media/tv/tuner/Tuner.java index f5f288d45d2c..8723fbb6f9fc 100644 --- a/media/java/android/media/tv/tuner/Tuner.java +++ b/media/java/android/media/tv/tuner/Tuner.java @@ -564,12 +564,11 @@ public final class Tuner implements AutoCloseable { * executor is used if it's {@code null}. * @param cb the callback to receive notifications from LNB. * @return the opened LNB object. {@code null} if the operation failed. - * - * @hide */ @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER) @Nullable - public Lnb openLnb(@CallbackExecutor @Nullable Executor executor, LnbCallback cb) { + public Lnb openLnb(@CallbackExecutor @Nullable Executor executor, @Nullable LnbCallback cb) { + TunerUtils.checkTunerPermission(mContext); return openLnbByName(null, executor, cb); } @@ -581,18 +580,26 @@ public final class Tuner implements AutoCloseable { * executor is used if it's {@code null}. * @param cb the callback to receive notifications from LNB. * @return the opened LNB object. {@code null} if the operation failed. - * - * @hide */ @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER) @Nullable public Lnb openLnbByName(@Nullable String name, @CallbackExecutor @Nullable Executor executor, - LnbCallback cb) { + @NonNull LnbCallback cb) { TunerUtils.checkTunerPermission(mContext); // TODO: use resource manager to get LNB ID. return new Lnb(0); } + /** + * Open a time filter object. + * + * @return the opened time filter object. {@code null} if the operation failed. + */ + @Nullable + public TimeFilter openTimeFilter() { + return nativeOpenTimeFilter(); + } + private List<Integer> getLnbIds() { mLnbIds = nativeGetLnbIds(); return mLnbIds; diff --git a/media/java/android/media/tv/tuner/TunerConstants.java b/media/java/android/media/tv/tuner/TunerConstants.java index b76a14d66313..5747c0b265f4 100644 --- a/media/java/android/media/tv/tuner/TunerConstants.java +++ b/media/java/android/media/tv/tuner/TunerConstants.java @@ -70,7 +70,6 @@ public final class TunerConstants { */ public static final int INDEX_TYPE_SC_HEVC = Constants.DemuxRecordScIndexType.SC_HEVC; - /** * Indexes can be tagged by Start Code in PES (Packetized Elementary Stream) * according to ISO/IEC 13818-1. @@ -83,22 +82,18 @@ public final class TunerConstants { /** * SC index for a new I-frame. - * @hide */ public static final int SC_INDEX_I_FRAME = Constants.DemuxScIndex.I_FRAME; /** * SC index for a new P-frame. - * @hide */ public static final int SC_INDEX_P_FRAME = Constants.DemuxScIndex.P_FRAME; /** * SC index for a new B-frame. - * @hide */ public static final int SC_INDEX_B_FRAME = Constants.DemuxScIndex.B_FRAME; /** * SC index for a new sequence. - * @hide */ public static final int SC_INDEX_SEQUENCE = Constants.DemuxScIndex.SEQUENCE; @@ -118,47 +113,39 @@ public final class TunerConstants { /** * SC HEVC index SPS. - * @hide */ public static final int SC_HEVC_INDEX_SPS = Constants.DemuxScHevcIndex.SPS; /** * SC HEVC index AUD. - * @hide */ public static final int SC_HEVC_INDEX_AUD = Constants.DemuxScHevcIndex.AUD; /** * SC HEVC index SLICE_CE_BLA_W_LP. - * @hide */ public static final int SC_HEVC_INDEX_SLICE_CE_BLA_W_LP = Constants.DemuxScHevcIndex.SLICE_CE_BLA_W_LP; /** * SC HEVC index SLICE_BLA_W_RADL. - * @hide */ public static final int SC_HEVC_INDEX_SLICE_BLA_W_RADL = Constants.DemuxScHevcIndex.SLICE_BLA_W_RADL; /** * SC HEVC index SLICE_BLA_N_LP. - * @hide */ public static final int SC_HEVC_INDEX_SLICE_BLA_N_LP = Constants.DemuxScHevcIndex.SLICE_BLA_N_LP; /** * SC HEVC index SLICE_IDR_W_RADL. - * @hide */ public static final int SC_HEVC_INDEX_SLICE_IDR_W_RADL = Constants.DemuxScHevcIndex.SLICE_IDR_W_RADL; /** * SC HEVC index SLICE_IDR_N_LP. - * @hide */ public static final int SC_HEVC_INDEX_SLICE_IDR_N_LP = Constants.DemuxScHevcIndex.SLICE_IDR_N_LP; /** * SC HEVC index SLICE_TRAIL_CRA. - * @hide */ public static final int SC_HEVC_INDEX_SLICE_TRAIL_CRA = Constants.DemuxScHevcIndex.SLICE_TRAIL_CRA; diff --git a/media/java/android/media/tv/tuner/filter/AlpFilterConfiguration.java b/media/java/android/media/tv/tuner/filter/AlpFilterConfiguration.java index 197dd22d3b45..064ab80efb5c 100644 --- a/media/java/android/media/tv/tuner/filter/AlpFilterConfiguration.java +++ b/media/java/android/media/tv/tuner/filter/AlpFilterConfiguration.java @@ -19,6 +19,7 @@ package android.media.tv.tuner.filter; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.RequiresPermission; +import android.annotation.SystemApi; import android.content.Context; import android.hardware.tv.tuner.V1_0.Constants; import android.media.tv.tuner.TunerUtils; @@ -28,8 +29,10 @@ import java.lang.annotation.RetentionPolicy; /** * Filter configuration for a ALP filter. + * * @hide */ +@SystemApi public class AlpFilterConfiguration extends FilterConfiguration { /** @hide */ @Retention(RetentionPolicy.SOURCE) @@ -57,7 +60,7 @@ public class AlpFilterConfiguration extends FilterConfiguration { private final int mPacketType; private final int mLengthType; - public AlpFilterConfiguration(Settings settings, int packetType, int lengthType) { + private AlpFilterConfiguration(Settings settings, int packetType, int lengthType) { super(settings); mPacketType = packetType; mLengthType = lengthType; diff --git a/media/java/android/media/tv/tuner/filter/AudioDescriptor.java b/media/java/android/media/tv/tuner/filter/AudioDescriptor.java index c88c07f8a150..7b1576a9ea26 100644 --- a/media/java/android/media/tv/tuner/filter/AudioDescriptor.java +++ b/media/java/android/media/tv/tuner/filter/AudioDescriptor.java @@ -16,11 +16,14 @@ package android.media.tv.tuner.filter; +import android.annotation.SystemApi; + /** * Meta data from AD (Audio Descriptor) according to ETSI TS 101 154 V2.1.1. * * @hide */ +@SystemApi public class AudioDescriptor { private final byte mAdFade; private final byte mAdPan; @@ -68,7 +71,7 @@ public class AudioDescriptor { * * <p>A single ASCII character version designator (here "1" indicates revision 1). */ - public char getVersionTextTag() { + public char getAdVersionTextTag() { return mVersionTextTag; } diff --git a/media/java/android/media/tv/tuner/filter/AvSettings.java b/media/java/android/media/tv/tuner/filter/AvSettings.java index 93eaaa47d186..bf11893e4bb3 100644 --- a/media/java/android/media/tv/tuner/filter/AvSettings.java +++ b/media/java/android/media/tv/tuner/filter/AvSettings.java @@ -18,6 +18,7 @@ package android.media.tv.tuner.filter; import android.annotation.NonNull; import android.annotation.RequiresPermission; +import android.annotation.SystemApi; import android.content.Context; import android.media.tv.tuner.TunerUtils; @@ -26,6 +27,7 @@ import android.media.tv.tuner.TunerUtils; * * @hide */ +@SystemApi public class AvSettings extends Settings { private final boolean mIsPassthrough; diff --git a/media/java/android/media/tv/tuner/filter/DownloadEvent.java b/media/java/android/media/tv/tuner/filter/DownloadEvent.java index 44c8447514d5..9f97b6141de0 100644 --- a/media/java/android/media/tv/tuner/filter/DownloadEvent.java +++ b/media/java/android/media/tv/tuner/filter/DownloadEvent.java @@ -16,11 +16,14 @@ package android.media.tv.tuner.filter; +import android.annotation.SystemApi; + /** * Filter event sent from {@link Filter} objects with download type. * * @hide */ +@SystemApi public class DownloadEvent extends FilterEvent { private final int mItemId; private final int mMpuSequenceNumber; diff --git a/media/java/android/media/tv/tuner/filter/DownloadSettings.java b/media/java/android/media/tv/tuner/filter/DownloadSettings.java index fa7744a00e4f..915ad79ffd5a 100644 --- a/media/java/android/media/tv/tuner/filter/DownloadSettings.java +++ b/media/java/android/media/tv/tuner/filter/DownloadSettings.java @@ -18,13 +18,16 @@ package android.media.tv.tuner.filter; import android.annotation.NonNull; import android.annotation.RequiresPermission; +import android.annotation.SystemApi; import android.content.Context; import android.media.tv.tuner.TunerUtils; /** * Filter Settings for a Download. + * * @hide */ +@SystemApi public class DownloadSettings extends Settings { private final int mDownloadId; diff --git a/media/java/android/media/tv/tuner/filter/FilterConfiguration.java b/media/java/android/media/tv/tuner/filter/FilterConfiguration.java index 33c9b4184283..c1d2275d3bdb 100644 --- a/media/java/android/media/tv/tuner/filter/FilterConfiguration.java +++ b/media/java/android/media/tv/tuner/filter/FilterConfiguration.java @@ -17,6 +17,7 @@ package android.media.tv.tuner.filter; import android.annotation.IntDef; +import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SystemApi; @@ -39,17 +40,14 @@ public abstract class FilterConfiguration { /** * IP v4 packet type. - * @hide */ public static final int PACKET_TYPE_IPV4 = 0; /** * Compressed packet type. - * @hide */ public static final int PACKET_TYPE_COMPRESSED = 2; /** * Signaling packet type. - * @hide */ public static final int PACKET_TYPE_SIGNALING = 4; @@ -63,12 +61,13 @@ public abstract class FilterConfiguration { /** * Gets filter configuration type. - * @hide */ @Filter.Type public abstract int getType(); - /** @hide */ + /** + * Gets filter Settings. + */ @Nullable public Settings getSettings() { return mSettings; @@ -78,7 +77,6 @@ public abstract class FilterConfiguration { * Builder for {@link FilterConfiguration}. * * @param <T> The subclass to be built. - * @hide */ public abstract static class Builder<T extends Builder<T>> { /* package */ Settings mSettings; @@ -89,8 +87,8 @@ public abstract class FilterConfiguration { /** * Sets filter settings. */ - @Nullable - public T setFrequency(Settings settings) { + @NonNull + public T setSettings(@Nullable Settings settings) { mSettings = settings; return self(); } diff --git a/media/java/android/media/tv/tuner/filter/IpFilterConfiguration.java b/media/java/android/media/tv/tuner/filter/IpFilterConfiguration.java index e16bac8f3dc8..bf5aaeda4742 100644 --- a/media/java/android/media/tv/tuner/filter/IpFilterConfiguration.java +++ b/media/java/android/media/tv/tuner/filter/IpFilterConfiguration.java @@ -19,13 +19,16 @@ package android.media.tv.tuner.filter; import android.annotation.NonNull; import android.annotation.RequiresPermission; import android.annotation.Size; +import android.annotation.SystemApi; import android.content.Context; import android.media.tv.tuner.TunerUtils; /** * Filter configuration for a IP filter. + * * @hide */ +@SystemApi public class IpFilterConfiguration extends FilterConfiguration { private final byte[] mSrcIpAddress; private final byte[] mDstIpAddress; @@ -33,7 +36,7 @@ public class IpFilterConfiguration extends FilterConfiguration { private final int mDstPort; private final boolean mPassthrough; - public IpFilterConfiguration(Settings settings, byte[] srcAddr, byte[] dstAddr, int srcPort, + private IpFilterConfiguration(Settings settings, byte[] srcAddr, byte[] dstAddr, int srcPort, int dstPort, boolean passthrough) { super(settings); mSrcIpAddress = srcAddr; @@ -52,6 +55,7 @@ public class IpFilterConfiguration extends FilterConfiguration { * Gets source IP address. */ @Size(min = 4, max = 16) + @NonNull public byte[] getSrcIpAddress() { return mSrcIpAddress; } @@ -59,6 +63,7 @@ public class IpFilterConfiguration extends FilterConfiguration { * Gets destination IP address. */ @Size(min = 4, max = 16) + @NonNull public byte[] getDstIpAddress() { return mDstIpAddress; } @@ -113,7 +118,7 @@ public class IpFilterConfiguration extends FilterConfiguration { * Sets source IP address. */ @NonNull - public Builder setSrcIpAddress(byte[] srcIpAddress) { + public Builder setSrcIpAddress(@NonNull byte[] srcIpAddress) { mSrcIpAddress = srcIpAddress; return this; } @@ -121,7 +126,7 @@ public class IpFilterConfiguration extends FilterConfiguration { * Sets destination IP address. */ @NonNull - public Builder setDstIpAddress(byte[] dstIpAddress) { + public Builder setDstIpAddress(@NonNull byte[] dstIpAddress) { mDstIpAddress = dstIpAddress; return this; } diff --git a/media/java/android/media/tv/tuner/filter/IpPayloadEvent.java b/media/java/android/media/tv/tuner/filter/IpPayloadEvent.java index 7d8f0ce4d2bb..42a124f5a673 100644 --- a/media/java/android/media/tv/tuner/filter/IpPayloadEvent.java +++ b/media/java/android/media/tv/tuner/filter/IpPayloadEvent.java @@ -16,11 +16,14 @@ package android.media.tv.tuner.filter; +import android.annotation.SystemApi; + /** * Filter event sent from {@link Filter} objects with IP payload type. * * @hide */ +@SystemApi public class IpPayloadEvent extends FilterEvent { private final int mDataLength; diff --git a/media/java/android/media/tv/tuner/filter/MediaEvent.java b/media/java/android/media/tv/tuner/filter/MediaEvent.java index 6b69aca0e414..eb2f4a9533ad 100644 --- a/media/java/android/media/tv/tuner/filter/MediaEvent.java +++ b/media/java/android/media/tv/tuner/filter/MediaEvent.java @@ -18,12 +18,14 @@ package android.media.tv.tuner.filter; import android.annotation.BytesLong; import android.annotation.Nullable; +import android.annotation.SystemApi; /** * Filter event sent from {@link Filter} objects with media type. * * @hide */ +@SystemApi public class MediaEvent extends FilterEvent{ private final int mStreamId; private final boolean mIsPtsPresent; @@ -62,11 +64,11 @@ public class MediaEvent extends FilterEvent{ } /** - * Returns whether PTS is present. + * Returns whether PTS (Presentation Time Stamp) is present. * * @return {@code true} if PTS is present in PES header; {@code false} otherwise. */ - public boolean getIsPtsPresent() { + public boolean isPtsPresent() { return mIsPtsPresent; } @@ -109,7 +111,7 @@ public class MediaEvent extends FilterEvent{ * @return {@code true} if the data is in secure area, and isn't mappable; * {@code false} otherwise. */ - public boolean getIsSecureMemory() { + public boolean isSecureMemory() { return mIsSecureMemory; } @@ -134,7 +136,7 @@ public class MediaEvent extends FilterEvent{ * * @return {@code true} if the data is in private; {@code false} otherwise. */ - public boolean getIsPrivateData() { + public boolean isPrivateData() { return mIsPrivateData; } diff --git a/media/java/android/media/tv/tuner/filter/MmtpFilterConfiguration.java b/media/java/android/media/tv/tuner/filter/MmtpFilterConfiguration.java index dfca949b1905..060182985dd0 100644 --- a/media/java/android/media/tv/tuner/filter/MmtpFilterConfiguration.java +++ b/media/java/android/media/tv/tuner/filter/MmtpFilterConfiguration.java @@ -18,17 +18,20 @@ package android.media.tv.tuner.filter; import android.annotation.NonNull; import android.annotation.RequiresPermission; +import android.annotation.SystemApi; import android.content.Context; import android.media.tv.tuner.TunerUtils; /** * Filter configuration for a MMTP filter. + * * @hide */ +@SystemApi public class MmtpFilterConfiguration extends FilterConfiguration { private final int mMmtpPid; - public MmtpFilterConfiguration(Settings settings, int mmtpPid) { + private MmtpFilterConfiguration(Settings settings, int mmtpPid) { super(settings); mMmtpPid = mmtpPid; } @@ -39,11 +42,11 @@ public class MmtpFilterConfiguration extends FilterConfiguration { } /** - * Gets MMTP PID. + * Gets MMTP Packet ID. * * <p>Packet ID is used to specify packets in MMTP. */ - public int getMmtpPid() { + public int getMmtpPacketId() { return mMmtpPid; } @@ -69,10 +72,10 @@ public class MmtpFilterConfiguration extends FilterConfiguration { } /** - * Sets MMTP PID. + * Sets MMTP Packet ID. */ @NonNull - public Builder setMmtpPid(int mmtpPid) { + public Builder setMmtpPacketId(int mmtpPid) { mMmtpPid = mmtpPid; return this; } diff --git a/media/java/android/media/tv/tuner/filter/MmtpRecordEvent.java b/media/java/android/media/tv/tuner/filter/MmtpRecordEvent.java index f4cf83336137..093dc6ff7d64 100644 --- a/media/java/android/media/tv/tuner/filter/MmtpRecordEvent.java +++ b/media/java/android/media/tv/tuner/filter/MmtpRecordEvent.java @@ -16,19 +16,23 @@ package android.media.tv.tuner.filter; +import android.annotation.BytesLong; +import android.annotation.SystemApi; + /** * Filter event sent from {@link Filter} objects with MMTP type. * * @hide */ +@SystemApi public class MmtpRecordEvent extends FilterEvent { private final int mScHevcIndexMask; - private final long mByteNumber; + private final long mDataLength; // This constructor is used by JNI code only - private MmtpRecordEvent(int scHevcIndexMask, long byteNumber) { + private MmtpRecordEvent(int scHevcIndexMask, long dataLength) { mScHevcIndexMask = scHevcIndexMask; - mByteNumber = byteNumber; + mDataLength = dataLength; } /** @@ -39,9 +43,10 @@ public class MmtpRecordEvent extends FilterEvent { } /** - * Gets the byte number from beginning of the filter's output. + * Gets data size in bytes of filtered data. */ - public long getByteNumber() { - return mByteNumber; + @BytesLong + public long getDataLength() { + return mDataLength; } } diff --git a/media/java/android/media/tv/tuner/filter/PesEvent.java b/media/java/android/media/tv/tuner/filter/PesEvent.java index 081b7661c433..695e596c98b7 100644 --- a/media/java/android/media/tv/tuner/filter/PesEvent.java +++ b/media/java/android/media/tv/tuner/filter/PesEvent.java @@ -16,11 +16,14 @@ package android.media.tv.tuner.filter; +import android.annotation.SystemApi; + /** * Filter event sent from {@link Filter} objects with PES type. * * @hide */ +@SystemApi public class PesEvent extends FilterEvent { private final int mStreamId; private final int mDataLength; diff --git a/media/java/android/media/tv/tuner/filter/RecordSettings.java b/media/java/android/media/tv/tuner/filter/RecordSettings.java index 4e9d67f60db4..209ed67f23ff 100644 --- a/media/java/android/media/tv/tuner/filter/RecordSettings.java +++ b/media/java/android/media/tv/tuner/filter/RecordSettings.java @@ -19,6 +19,7 @@ package android.media.tv.tuner.filter; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.RequiresPermission; +import android.annotation.SystemApi; import android.content.Context; import android.hardware.tv.tuner.V1_0.Constants; import android.media.tv.tuner.TunerConstants; @@ -30,8 +31,10 @@ import java.lang.annotation.RetentionPolicy; /** * The Settings for the record in DVR. + * * @hide */ +@SystemApi public class RecordSettings extends Settings { /** * Indexes can be tagged through TS (Transport Stream) header. @@ -51,74 +54,61 @@ public class RecordSettings extends Settings { /** * TS index FIRST_PACKET. - * @hide */ public static final int TS_INDEX_FIRST_PACKET = Constants.DemuxTsIndex.FIRST_PACKET; /** * TS index PAYLOAD_UNIT_START_INDICATOR. - * @hide */ public static final int TS_INDEX_PAYLOAD_UNIT_START_INDICATOR = Constants.DemuxTsIndex.PAYLOAD_UNIT_START_INDICATOR; /** * TS index CHANGE_TO_NOT_SCRAMBLED. - * @hide */ public static final int TS_INDEX_CHANGE_TO_NOT_SCRAMBLED = Constants.DemuxTsIndex.CHANGE_TO_NOT_SCRAMBLED; /** * TS index CHANGE_TO_EVEN_SCRAMBLED. - * @hide */ public static final int TS_INDEX_CHANGE_TO_EVEN_SCRAMBLED = Constants.DemuxTsIndex.CHANGE_TO_EVEN_SCRAMBLED; /** * TS index CHANGE_TO_ODD_SCRAMBLED. - * @hide */ public static final int TS_INDEX_CHANGE_TO_ODD_SCRAMBLED = Constants.DemuxTsIndex.CHANGE_TO_ODD_SCRAMBLED; /** * TS index DISCONTINUITY_INDICATOR. - * @hide */ public static final int TS_INDEX_DISCONTINUITY_INDICATOR = Constants.DemuxTsIndex.DISCONTINUITY_INDICATOR; /** * TS index RANDOM_ACCESS_INDICATOR. - * @hide */ public static final int TS_INDEX_RANDOM_ACCESS_INDICATOR = Constants.DemuxTsIndex.RANDOM_ACCESS_INDICATOR; /** * TS index PRIORITY_INDICATOR. - * @hide */ public static final int TS_INDEX_PRIORITY_INDICATOR = Constants.DemuxTsIndex.PRIORITY_INDICATOR; /** * TS index PCR_FLAG. - * @hide */ public static final int TS_INDEX_PCR_FLAG = Constants.DemuxTsIndex.PCR_FLAG; /** * TS index OPCR_FLAG. - * @hide */ public static final int TS_INDEX_OPCR_FLAG = Constants.DemuxTsIndex.OPCR_FLAG; /** * TS index SPLICING_POINT_FLAG. - * @hide */ public static final int TS_INDEX_SPLICING_POINT_FLAG = Constants.DemuxTsIndex.SPLICING_POINT_FLAG; /** * TS index PRIVATE_DATA. - * @hide */ public static final int TS_INDEX_PRIVATE_DATA = Constants.DemuxTsIndex.PRIVATE_DATA; /** * TS index ADAPTATION_EXTENSION_FLAG. - * @hide */ public static final int TS_INDEX_ADAPTATION_EXTENSION_FLAG = Constants.DemuxTsIndex.ADAPTATION_EXTENSION_FLAG; diff --git a/media/java/android/media/tv/tuner/filter/SectionSettings.java b/media/java/android/media/tv/tuner/filter/SectionSettings.java index b8d0fad5e06c..70788a7515ca 100644 --- a/media/java/android/media/tv/tuner/filter/SectionSettings.java +++ b/media/java/android/media/tv/tuner/filter/SectionSettings.java @@ -16,12 +16,15 @@ package android.media.tv.tuner.filter; +import android.annotation.SystemApi; import android.media.tv.tuner.TunerUtils; /** * Filter Settings for Section data according to ISO/IEC 13818-1. + * * @hide */ +@SystemApi public class SectionSettings extends Settings { SectionSettings(int mainType) { diff --git a/media/java/android/media/tv/tuner/filter/SectionSettingsWithSectionBits.java b/media/java/android/media/tv/tuner/filter/SectionSettingsWithSectionBits.java index a2d42d8cfe50..eeeabdfecc01 100644 --- a/media/java/android/media/tv/tuner/filter/SectionSettingsWithSectionBits.java +++ b/media/java/android/media/tv/tuner/filter/SectionSettingsWithSectionBits.java @@ -18,13 +18,16 @@ package android.media.tv.tuner.filter; import android.annotation.NonNull; import android.annotation.RequiresPermission; +import android.annotation.SystemApi; import android.content.Context; import android.media.tv.tuner.TunerUtils; /** * Bits Settings for Section Filters. + * * @hide */ +@SystemApi public class SectionSettingsWithSectionBits extends SectionSettings { private final byte[] mFilter; private final byte[] mMask; @@ -41,6 +44,7 @@ public class SectionSettingsWithSectionBits extends SectionSettings { /** * Gets the bytes configured for Section Filter */ + @NonNull public byte[] getFilterBytes() { return mFilter; } @@ -49,6 +53,7 @@ public class SectionSettingsWithSectionBits extends SectionSettings { * * <p>The bits in the bytes are used for filtering. */ + @NonNull public byte[] getMask() { return mMask; } @@ -60,6 +65,7 @@ public class SectionSettingsWithSectionBits extends SectionSettings { * <p>Do negative match at the bit position of the configured bytes when the bit at same * position of the mode is 1. */ + @NonNull public byte[] getMode() { return mMode; } @@ -93,7 +99,7 @@ public class SectionSettingsWithSectionBits extends SectionSettings { * Sets filter bytes. */ @NonNull - public Builder setFilter(byte[] filter) { + public Builder setFilter(@NonNull byte[] filter) { mFilter = filter; return this; } @@ -101,7 +107,7 @@ public class SectionSettingsWithSectionBits extends SectionSettings { * Sets bit mask. */ @NonNull - public Builder setMask(byte[] mask) { + public Builder setMask(@NonNull byte[] mask) { mMask = mask; return this; } @@ -109,7 +115,7 @@ public class SectionSettingsWithSectionBits extends SectionSettings { * Sets mode. */ @NonNull - public Builder setMode(byte[] mode) { + public Builder setMode(@NonNull byte[] mode) { mMode = mode; return this; } diff --git a/media/java/android/media/tv/tuner/filter/SectionSettingsWithTableInfo.java b/media/java/android/media/tv/tuner/filter/SectionSettingsWithTableInfo.java index 0c9cd2bc9e56..c5ff45cfa7de 100644 --- a/media/java/android/media/tv/tuner/filter/SectionSettingsWithTableInfo.java +++ b/media/java/android/media/tv/tuner/filter/SectionSettingsWithTableInfo.java @@ -18,13 +18,16 @@ package android.media.tv.tuner.filter; import android.annotation.NonNull; import android.annotation.RequiresPermission; +import android.annotation.SystemApi; import android.content.Context; import android.media.tv.tuner.TunerUtils; /** * Table information for Section Filter. + * * @hide */ +@SystemApi public class SectionSettingsWithTableInfo extends SectionSettings { private final int mTableId; private final int mVersion; diff --git a/media/java/android/media/tv/tuner/filter/Settings.java b/media/java/android/media/tv/tuner/filter/Settings.java index d697280a4106..fee7f66c1231 100644 --- a/media/java/android/media/tv/tuner/filter/Settings.java +++ b/media/java/android/media/tv/tuner/filter/Settings.java @@ -33,8 +33,6 @@ public abstract class Settings { /** * Gets filter settings type. - * - * @hide */ public int getType() { return mType; @@ -45,7 +43,6 @@ public abstract class Settings { * Builder for {@link Settings}. * * @param <T> The subclass to be built. - * @hide */ public abstract static class Builder<T extends Builder<T>> { /* package */ final int mMainType; diff --git a/media/java/android/media/tv/tuner/filter/TemiEvent.java b/media/java/android/media/tv/tuner/filter/TemiEvent.java index b5bd49920715..9bee9280a8ac 100644 --- a/media/java/android/media/tv/tuner/filter/TemiEvent.java +++ b/media/java/android/media/tv/tuner/filter/TemiEvent.java @@ -17,12 +17,14 @@ package android.media.tv.tuner.filter; import android.annotation.NonNull; +import android.annotation.SystemApi; /** * Filter event sent from {@link Filter} objects for Timed External Media Information (TEMI) data. * * @hide */ +@SystemApi public class TemiEvent extends FilterEvent { private final long mPts; private final byte mDescrTag; @@ -44,14 +46,14 @@ public class TemiEvent extends FilterEvent { } /** - * Gets TEMI descriptor tag. + * Gets TEMI (Timed External Media Information) descriptor tag. */ public byte getDescriptorTag() { return mDescrTag; } /** - * Gets TEMI descriptor. + * Gets TEMI (Timed External Media Information) descriptor. */ @NonNull public byte[] getDescriptorData() { diff --git a/media/java/android/media/tv/tuner/filter/TimeFilter.java b/media/java/android/media/tv/tuner/filter/TimeFilter.java index c9750040c605..a926d59cdd03 100644 --- a/media/java/android/media/tv/tuner/filter/TimeFilter.java +++ b/media/java/android/media/tv/tuner/filter/TimeFilter.java @@ -16,7 +16,7 @@ package android.media.tv.tuner.filter; -import android.annotation.Nullable; +import android.annotation.SystemApi; import android.media.tv.tuner.TunerConstants.Result; /** @@ -30,7 +30,21 @@ import android.media.tv.tuner.TunerConstants.Result; * * @hide */ +@SystemApi public class TimeFilter implements AutoCloseable { + + /** + * Timestamp is unavailable. + * + * <p>Returned by {@link #getSourceTime()} or {@link #getTimeStamp()} when the requested + * timestamp is not available. + * + * @see #getSourceTime() + * @see #getTimeStamp() + */ + public static final long TIMESTAMP_UNAVAILABLE = -1L; + + private native int nativeSetTimestamp(long timestamp); private native int nativeClearTimestamp(); private native Long nativeGetTimestamp(); @@ -39,6 +53,10 @@ public class TimeFilter implements AutoCloseable { private boolean mEnable = false; + // Called by JNI code + private TimeFilter() { + } + /** * Set timestamp for time based filter. * @@ -86,13 +104,12 @@ public class TimeFilter implements AutoCloseable { * * @return current timestamp in the time filter. It's based on the 90KHz counter, and it's * the same format as PTS (Presentation Time Stamp) defined in ISO/IEC 13818-1:2019. The - * timestamps may or may not be related to PTS or DTS. {@code null} if the timestamp is - * never set. + * timestamps may or may not be related to PTS or DTS. Returns {@link #TIMESTAMP_UNAVAILABLE} + * if the timestamp is never set. */ - @Nullable - public Long getTimeStamp() { + public long getTimeStamp() { if (!mEnable) { - return null; + return TIMESTAMP_UNAVAILABLE; } return nativeGetTimestamp(); } @@ -104,12 +121,12 @@ public class TimeFilter implements AutoCloseable { * * @return first timestamp of incoming data stream. It's based on the 90KHz counter, and * it's the same format as PTS (Presentation Time Stamp) defined in ISO/IEC 13818-1:2019. - * The timestamps may or may not be related to PTS or DTS. + * The timestamps may or may not be related to PTS or DTS. Returns + * {@link #TIMESTAMP_UNAVAILABLE} if the timestamp is not available. */ - @Nullable - public Long getSourceTime() { + public long getSourceTime() { if (!mEnable) { - return null; + return TIMESTAMP_UNAVAILABLE; } return nativeGetSourceTime(); } diff --git a/media/java/android/media/tv/tuner/filter/TlvFilterConfiguration.java b/media/java/android/media/tv/tuner/filter/TlvFilterConfiguration.java index 0a0e1a8540ec..b6878e6a13a8 100644 --- a/media/java/android/media/tv/tuner/filter/TlvFilterConfiguration.java +++ b/media/java/android/media/tv/tuner/filter/TlvFilterConfiguration.java @@ -18,19 +18,22 @@ package android.media.tv.tuner.filter; import android.annotation.NonNull; import android.annotation.RequiresPermission; +import android.annotation.SystemApi; import android.content.Context; import android.media.tv.tuner.TunerUtils; /** * Filter configuration for a TLV filter. + * * @hide */ +@SystemApi public class TlvFilterConfiguration extends FilterConfiguration { private final int mPacketType; private final boolean mIsCompressedIpPacket; private final boolean mPassthrough; - public TlvFilterConfiguration(Settings settings, int packetType, boolean isCompressed, + private TlvFilterConfiguration(Settings settings, int packetType, boolean isCompressed, boolean passthrough) { super(settings); mPacketType = packetType; diff --git a/media/java/android/media/tv/tuner/filter/TsRecordEvent.java b/media/java/android/media/tv/tuner/filter/TsRecordEvent.java index 4dd843274227..7a14bb863700 100644 --- a/media/java/android/media/tv/tuner/filter/TsRecordEvent.java +++ b/media/java/android/media/tv/tuner/filter/TsRecordEvent.java @@ -16,43 +16,47 @@ package android.media.tv.tuner.filter; +import android.annotation.BytesLong; +import android.annotation.SystemApi; + /** * Filter event sent from {@link Filter} objects for TS record data. * * @hide */ +@SystemApi public class TsRecordEvent extends FilterEvent { private final int mPid; private final int mTsIndexMask; private final int mScIndexMask; - private final long mByteNumber; + private final long mDataLength; // This constructor is used by JNI code only - private TsRecordEvent(int pid, int tsIndexMask, int scIndexMask, long byteNumber) { + private TsRecordEvent(int pid, int tsIndexMask, int scIndexMask, long dataLength) { mPid = pid; mTsIndexMask = tsIndexMask; mScIndexMask = scIndexMask; - mByteNumber = byteNumber; + mDataLength = dataLength; } /** * Gets packet ID. */ - public int getTpid() { + public int getPacketId() { return mPid; } /** - * Gets TS index mask. + * Gets TS (transport stream) index mask. */ @RecordSettings.TsIndexMask public int getTsIndexMask() { return mTsIndexMask; } /** - * Gets SC index mask. + * Gets SC (Start Code) index mask. * * <p>The index type is SC or SC-HEVC, and is set when configuring the filter. */ @@ -62,9 +66,10 @@ public class TsRecordEvent extends FilterEvent { } /** - * Gets the byte number from beginning of the filter's output. + * Gets data size in bytes of filtered data. */ - public long getByteNumber() { - return mByteNumber; + @BytesLong + public long getDataLength() { + return mDataLength; } } diff --git a/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouter2Test.java b/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouter2Test.java index a9fcf7703cfc..daaa8688e203 100644 --- a/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouter2Test.java +++ b/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouter2Test.java @@ -43,12 +43,11 @@ import android.annotation.NonNull; import android.content.Context; import android.media.MediaRoute2Info; import android.media.MediaRouter2; -import android.media.MediaRouter2.OnCreateSessionListener; +import android.media.MediaRouter2.OnGetControllerHintsListener; import android.media.MediaRouter2.RouteCallback; import android.media.MediaRouter2.RoutingController; -import android.media.MediaRouter2.SessionCallback; +import android.media.MediaRouter2.RoutingControllerCallback; import android.media.RouteDiscoveryPreference; -import android.media.RoutingSessionInfo; import android.net.Uri; import android.os.Bundle; import android.os.Parcel; @@ -156,33 +155,34 @@ public class MediaRouter2Test { } @Test - public void testRegisterSessionCallbackWithInvalidArguments() { + public void testRegisterControllerCallbackWithInvalidArguments() { Executor executor = mExecutor; - SessionCallback callback = new SessionCallback(); + RoutingControllerCallback callback = new RoutingControllerCallback(); // Tests null executor assertThrows(NullPointerException.class, - () -> mRouter2.registerSessionCallback(null, callback)); + () -> mRouter2.registerControllerCallback(null, callback)); // Tests null callback assertThrows(NullPointerException.class, - () -> mRouter2.registerSessionCallback(executor, null)); + () -> mRouter2.registerControllerCallback(executor, null)); } @Test - public void testUnregisterSessionCallbackWithNullCallback() { + public void testUnregisterControllerCallbackWithNullCallback() { // Tests null callback assertThrows(NullPointerException.class, - () -> mRouter2.unregisterSessionCallback(null)); + () -> mRouter2.unregisterControllerCallback(null)); } @Test - public void testRequestCreateSessionWithNullRoute() { - assertThrows(NullPointerException.class, () -> mRouter2.requestCreateSession(null)); + public void testRequestCreateControllerWithNullRoute() { + assertThrows(NullPointerException.class, + () -> mRouter2.requestCreateController(null)); } @Test - public void testRequestCreateSessionSuccess() throws Exception { + public void testRequestCreateControllerSuccess() throws Exception { final List<String> sampleRouteFeature = new ArrayList<>(); sampleRouteFeature.add(FEATURE_SAMPLE); @@ -195,9 +195,9 @@ public class MediaRouter2Test { final List<RoutingController> controllers = new ArrayList<>(); // Create session with this route - SessionCallback sessionCallback = new SessionCallback() { + RoutingControllerCallback controllerCallback = new RoutingControllerCallback() { @Override - public void onSessionCreated(RoutingController controller) { + public void onControllerCreated(RoutingController controller) { assertNotNull(controller); assertTrue(createRouteMap(controller.getSelectedRoutes()).containsKey(ROUTE_ID1)); controllers.add(controller); @@ -205,7 +205,7 @@ public class MediaRouter2Test { } @Override - public void onSessionCreationFailed(MediaRoute2Info requestedRoute) { + public void onControllerCreationFailed(MediaRoute2Info requestedRoute) { failureLatch.countDown(); } }; @@ -215,8 +215,8 @@ public class MediaRouter2Test { mRouter2.registerRouteCallback(mExecutor, routeCallback, RouteDiscoveryPreference.EMPTY); try { - mRouter2.registerSessionCallback(mExecutor, sessionCallback); - mRouter2.requestCreateSession(route); + mRouter2.registerControllerCallback(mExecutor, controllerCallback); + mRouter2.requestCreateController(route); assertTrue(successLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS)); // onSessionCreationFailed should not be called. @@ -224,12 +224,12 @@ public class MediaRouter2Test { } finally { releaseControllers(controllers); mRouter2.unregisterRouteCallback(routeCallback); - mRouter2.unregisterSessionCallback(sessionCallback); + mRouter2.unregisterControllerCallback(controllerCallback); } } @Test - public void testRequestCreateSessionFailure() throws Exception { + public void testRequestCreateControllerFailure() throws Exception { final List<String> sampleRouteType = new ArrayList<>(); sampleRouteType.add(FEATURE_SAMPLE); @@ -242,15 +242,15 @@ public class MediaRouter2Test { final List<RoutingController> controllers = new ArrayList<>(); // Create session with this route - SessionCallback sessionCallback = new SessionCallback() { + RoutingControllerCallback controllerCallback = new RoutingControllerCallback() { @Override - public void onSessionCreated(RoutingController controller) { + public void onControllerCreated(RoutingController controller) { controllers.add(controller); successLatch.countDown(); } @Override - public void onSessionCreationFailed(MediaRoute2Info requestedRoute) { + public void onControllerCreationFailed(MediaRoute2Info requestedRoute) { assertEquals(route, requestedRoute); failureLatch.countDown(); } @@ -261,8 +261,8 @@ public class MediaRouter2Test { mRouter2.registerRouteCallback(mExecutor, routeCallback, RouteDiscoveryPreference.EMPTY); try { - mRouter2.registerSessionCallback(mExecutor, sessionCallback); - mRouter2.requestCreateSession(route); + mRouter2.registerControllerCallback(mExecutor, controllerCallback); + mRouter2.requestCreateController(route); assertTrue(failureLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS)); // onSessionCreated should not be called. @@ -270,12 +270,12 @@ public class MediaRouter2Test { } finally { releaseControllers(controllers); mRouter2.unregisterRouteCallback(routeCallback); - mRouter2.unregisterSessionCallback(sessionCallback); + mRouter2.unregisterControllerCallback(controllerCallback); } } @Test - public void testRequestCreateSessionMultipleSessions() throws Exception { + public void testRequestCreateControllerMultipleSessions() throws Exception { final List<String> sampleRouteType = new ArrayList<>(); sampleRouteType.add(FEATURE_SAMPLE); @@ -284,15 +284,15 @@ public class MediaRouter2Test { final List<RoutingController> createdControllers = new ArrayList<>(); // Create session with this route - SessionCallback sessionCallback = new SessionCallback() { + RoutingControllerCallback controllerCallback = new RoutingControllerCallback() { @Override - public void onSessionCreated(RoutingController controller) { + public void onControllerCreated(RoutingController controller) { createdControllers.add(controller); successLatch.countDown(); } @Override - public void onSessionCreationFailed(MediaRoute2Info requestedRoute) { + public void onControllerCreationFailed(MediaRoute2Info requestedRoute) { failureLatch.countDown(); } }; @@ -308,9 +308,9 @@ public class MediaRouter2Test { mRouter2.registerRouteCallback(mExecutor, routeCallback, RouteDiscoveryPreference.EMPTY); try { - mRouter2.registerSessionCallback(mExecutor, sessionCallback); - mRouter2.requestCreateSession(route1); - mRouter2.requestCreateSession(route2); + mRouter2.registerControllerCallback(mExecutor, controllerCallback); + mRouter2.requestCreateController(route1); + mRouter2.requestCreateController(route2); assertTrue(successLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS)); // onSessionCreationFailed should not be called. @@ -321,19 +321,19 @@ public class MediaRouter2Test { RoutingController controller1 = createdControllers.get(0); RoutingController controller2 = createdControllers.get(1); - assertNotEquals(controller1.getSessionId(), controller2.getSessionId()); + assertNotEquals(controller1.getId(), controller2.getId()); assertTrue(createRouteMap(controller1.getSelectedRoutes()).containsKey(ROUTE_ID1)); assertTrue(createRouteMap(controller2.getSelectedRoutes()).containsKey(ROUTE_ID2)); } finally { releaseControllers(createdControllers); mRouter2.unregisterRouteCallback(routeCallback); - mRouter2.unregisterSessionCallback(sessionCallback); + mRouter2.unregisterControllerCallback(controllerCallback); } } @Test - public void testSetOnCreateSessionListener() throws Exception { + public void testSetOnGetControllerHintsListener() throws Exception { final List<String> sampleRouteFeature = new ArrayList<>(); sampleRouteFeature.add(FEATURE_SAMPLE); @@ -343,9 +343,9 @@ public class MediaRouter2Test { final Bundle createSessionHints = new Bundle(); createSessionHints.putString(TEST_KEY, TEST_VALUE); - final OnCreateSessionListener listener = new OnCreateSessionListener() { + final OnGetControllerHintsListener listener = new OnGetControllerHintsListener() { @Override - public Bundle onCreateSession(MediaRoute2Info route) { + public Bundle onGetControllerHints(MediaRoute2Info route) { return createSessionHints; } }; @@ -355,9 +355,9 @@ public class MediaRouter2Test { final List<RoutingController> controllers = new ArrayList<>(); // Create session with this route - SessionCallback sessionCallback = new SessionCallback() { + RoutingControllerCallback controllerCallback = new RoutingControllerCallback() { @Override - public void onSessionCreated(RoutingController controller) { + public void onControllerCreated(RoutingController controller) { assertNotNull(controller); assertTrue(createRouteMap(controller.getSelectedRoutes()).containsKey(ROUTE_ID1)); @@ -373,7 +373,7 @@ public class MediaRouter2Test { } @Override - public void onSessionCreationFailed(MediaRoute2Info requestedRoute) { + public void onControllerCreationFailed(MediaRoute2Info requestedRoute) { failureLatch.countDown(); } }; @@ -383,12 +383,12 @@ public class MediaRouter2Test { mRouter2.registerRouteCallback(mExecutor, routeCallback, RouteDiscoveryPreference.EMPTY); try { - mRouter2.registerSessionCallback(mExecutor, sessionCallback); + mRouter2.registerControllerCallback(mExecutor, controllerCallback); // The SampleMediaRoute2ProviderService supposed to set control hints // with the given creationSessionHints. - mRouter2.setOnCreateSessionListener(listener); - mRouter2.requestCreateSession(route); + mRouter2.setOnGetControllerHintsListener(listener); + mRouter2.requestCreateController(route); assertTrue(successLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS)); // onSessionCreationFailed should not be called. @@ -396,12 +396,12 @@ public class MediaRouter2Test { } finally { releaseControllers(controllers); mRouter2.unregisterRouteCallback(routeCallback); - mRouter2.unregisterSessionCallback(sessionCallback); + mRouter2.unregisterControllerCallback(controllerCallback); } } @Test - public void testSessionCallbackIsNotCalledAfterUnregistered() throws Exception { + public void testRoutingControllerCallbackIsNotCalledAfterUnregistered() throws Exception { final List<String> sampleRouteType = new ArrayList<>(); sampleRouteType.add(FEATURE_SAMPLE); @@ -414,15 +414,15 @@ public class MediaRouter2Test { final List<RoutingController> controllers = new ArrayList<>(); // Create session with this route - SessionCallback sessionCallback = new SessionCallback() { + RoutingControllerCallback controllerCallback = new RoutingControllerCallback() { @Override - public void onSessionCreated(RoutingController controller) { + public void onControllerCreated(RoutingController controller) { controllers.add(controller); successLatch.countDown(); } @Override - public void onSessionCreationFailed(MediaRoute2Info requestedRoute) { + public void onControllerCreationFailed(MediaRoute2Info requestedRoute) { failureLatch.countDown(); } }; @@ -432,11 +432,11 @@ public class MediaRouter2Test { mRouter2.registerRouteCallback(mExecutor, routeCallback, RouteDiscoveryPreference.EMPTY); try { - mRouter2.registerSessionCallback(mExecutor, sessionCallback); - mRouter2.requestCreateSession(route); + mRouter2.registerControllerCallback(mExecutor, controllerCallback); + mRouter2.requestCreateController(route); // Unregisters session callback - mRouter2.unregisterSessionCallback(sessionCallback); + mRouter2.unregisterControllerCallback(controllerCallback); // No session callback methods should be called. assertFalse(successLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS)); @@ -444,7 +444,7 @@ public class MediaRouter2Test { } finally { releaseControllers(controllers); mRouter2.unregisterRouteCallback(routeCallback); - mRouter2.unregisterSessionCallback(sessionCallback); + mRouter2.unregisterControllerCallback(controllerCallback); } } @@ -458,59 +458,49 @@ public class MediaRouter2Test { MediaRoute2Info routeToCreateSessionWith = routes.get(ROUTE_ID1); assertNotNull(routeToCreateSessionWith); - final CountDownLatch onSessionCreatedLatch = new CountDownLatch(1); - final CountDownLatch onSessionInfoChangedLatchForSelect = new CountDownLatch(1); - final CountDownLatch onSessionInfoChangedLatchForDeselect = new CountDownLatch(1); + final CountDownLatch onControllerCreatedLatch = new CountDownLatch(1); + final CountDownLatch onControllerUpdatedLatchForSelect = new CountDownLatch(1); + final CountDownLatch onControllerUpdatedLatchForDeselect = new CountDownLatch(1); final List<RoutingController> controllers = new ArrayList<>(); // Create session with ROUTE_ID1 - SessionCallback sessionCallback = new SessionCallback() { + RoutingControllerCallback controllerCallback = new RoutingControllerCallback() { @Override - public void onSessionCreated(RoutingController controller) { + public void onControllerCreated(RoutingController controller) { assertNotNull(controller); assertTrue(getRouteIds(controller.getSelectedRoutes()).contains(ROUTE_ID1)); controllers.add(controller); - onSessionCreatedLatch.countDown(); + onControllerCreatedLatch.countDown(); } @Override - public void onSessionInfoChanged(RoutingController controller, - RoutingSessionInfo oldInfo, RoutingSessionInfo newInfo) { - if (onSessionCreatedLatch.getCount() != 0 + public void onControllerUpdated(RoutingController controller) { + if (onControllerCreatedLatch.getCount() != 0 || !TextUtils.equals( - controllers.get(0).getSessionId(), controller.getSessionId())) { + controllers.get(0).getId(), controller.getId())) { return; } - if (onSessionInfoChangedLatchForSelect.getCount() != 0) { - // Check oldInfo - assertEquals(controller.getSessionId(), oldInfo.getId()); - assertEquals(1, oldInfo.getSelectedRoutes().size()); - assertTrue(oldInfo.getSelectedRoutes().contains(ROUTE_ID1)); - assertTrue(oldInfo.getSelectableRoutes().contains( - ROUTE_ID4_TO_SELECT_AND_DESELECT)); - - // Check newInfo - assertEquals(controller.getSessionId(), newInfo.getId()); - assertEquals(2, newInfo.getSelectedRoutes().size()); - assertTrue(newInfo.getSelectedRoutes().contains(ROUTE_ID1)); - assertTrue(newInfo.getSelectedRoutes().contains( - ROUTE_ID4_TO_SELECT_AND_DESELECT)); - assertFalse(newInfo.getSelectableRoutes().contains( - ROUTE_ID4_TO_SELECT_AND_DESELECT)); - - onSessionInfoChangedLatchForSelect.countDown(); + if (onControllerUpdatedLatchForSelect.getCount() != 0) { + assertEquals(2, controller.getSelectedRoutes().size()); + assertTrue(getRouteIds(controller.getSelectedRoutes()) + .contains(ROUTE_ID1)); + assertTrue(getRouteIds(controller.getSelectedRoutes()) + .contains(ROUTE_ID4_TO_SELECT_AND_DESELECT)); + assertFalse(getRouteIds(controller.getSelectableRoutes()) + .contains(ROUTE_ID4_TO_SELECT_AND_DESELECT)); + + onControllerUpdatedLatchForSelect.countDown(); } else { - // Check newInfo - assertEquals(controller.getSessionId(), newInfo.getId()); - assertEquals(1, newInfo.getSelectedRoutes().size()); - assertTrue(newInfo.getSelectedRoutes().contains(ROUTE_ID1)); - assertFalse(newInfo.getSelectedRoutes().contains( - ROUTE_ID4_TO_SELECT_AND_DESELECT)); - assertTrue(newInfo.getSelectableRoutes().contains( - ROUTE_ID4_TO_SELECT_AND_DESELECT)); - - onSessionInfoChangedLatchForDeselect.countDown(); + assertEquals(1, controller.getSelectedRoutes().size()); + assertTrue(getRouteIds(controller.getSelectedRoutes()) + .contains(ROUTE_ID1)); + assertFalse(getRouteIds(controller.getSelectedRoutes()) + .contains(ROUTE_ID4_TO_SELECT_AND_DESELECT)); + assertTrue(getRouteIds(controller.getSelectableRoutes()) + .contains(ROUTE_ID4_TO_SELECT_AND_DESELECT)); + + onControllerUpdatedLatchForDeselect.countDown(); } } }; @@ -520,9 +510,9 @@ public class MediaRouter2Test { mRouter2.registerRouteCallback(mExecutor, routeCallback, RouteDiscoveryPreference.EMPTY); try { - mRouter2.registerSessionCallback(mExecutor, sessionCallback); - mRouter2.requestCreateSession(routeToCreateSessionWith); - assertTrue(onSessionCreatedLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS)); + mRouter2.registerControllerCallback(mExecutor, controllerCallback); + mRouter2.requestCreateController(routeToCreateSessionWith); + assertTrue(onControllerCreatedLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS)); assertEquals(1, controllers.size()); RoutingController controller = controllers.get(0); @@ -535,15 +525,15 @@ public class MediaRouter2Test { assertNotNull(routeToSelectAndDeselect); controller.selectRoute(routeToSelectAndDeselect); - assertTrue(onSessionInfoChangedLatchForSelect.await(TIMEOUT_MS, TimeUnit.MILLISECONDS)); + assertTrue(onControllerUpdatedLatchForSelect.await(TIMEOUT_MS, TimeUnit.MILLISECONDS)); controller.deselectRoute(routeToSelectAndDeselect); - assertTrue(onSessionInfoChangedLatchForDeselect.await( + assertTrue(onControllerUpdatedLatchForDeselect.await( TIMEOUT_MS, TimeUnit.MILLISECONDS)); } finally { releaseControllers(controllers); mRouter2.unregisterRouteCallback(routeCallback); - mRouter2.unregisterSessionCallback(sessionCallback); + mRouter2.unregisterControllerCallback(controllerCallback); } } @@ -556,43 +546,35 @@ public class MediaRouter2Test { MediaRoute2Info routeToCreateSessionWith = routes.get(ROUTE_ID1); assertNotNull(routeToCreateSessionWith); - final CountDownLatch onSessionCreatedLatch = new CountDownLatch(1); - final CountDownLatch onSessionInfoChangedLatch = new CountDownLatch(1); + final CountDownLatch onControllerCreatedLatch = new CountDownLatch(1); + final CountDownLatch onControllerUpdatedLatch = new CountDownLatch(1); final List<RoutingController> controllers = new ArrayList<>(); // Create session with ROUTE_ID1 - SessionCallback sessionCallback = new SessionCallback() { + RoutingControllerCallback controllerCallback = new RoutingControllerCallback() { @Override - public void onSessionCreated(RoutingController controller) { + public void onControllerCreated(RoutingController controller) { assertNotNull(controller); assertTrue(getRouteIds(controller.getSelectedRoutes()).contains(ROUTE_ID1)); controllers.add(controller); - onSessionCreatedLatch.countDown(); + onControllerCreatedLatch.countDown(); } @Override - public void onSessionInfoChanged(RoutingController controller, - RoutingSessionInfo oldInfo, RoutingSessionInfo newInfo) { - if (onSessionCreatedLatch.getCount() != 0 + public void onControllerUpdated(RoutingController controller) { + if (onControllerCreatedLatch.getCount() != 0 || !TextUtils.equals( - controllers.get(0).getSessionId(), controller.getSessionId())) { + controllers.get(0).getId(), controller.getId())) { return; } - - // Check oldInfo - assertEquals(controller.getSessionId(), oldInfo.getId()); - assertEquals(1, oldInfo.getSelectedRoutes().size()); - assertTrue(oldInfo.getSelectedRoutes().contains(ROUTE_ID1)); - assertTrue(oldInfo.getTransferrableRoutes().contains(ROUTE_ID5_TO_TRANSFER_TO)); - - // Check newInfo - assertEquals(controller.getSessionId(), newInfo.getId()); - assertEquals(1, newInfo.getSelectedRoutes().size()); - assertFalse(newInfo.getSelectedRoutes().contains(ROUTE_ID1)); - assertTrue(newInfo.getSelectedRoutes().contains(ROUTE_ID5_TO_TRANSFER_TO)); - assertFalse(newInfo.getTransferrableRoutes().contains(ROUTE_ID5_TO_TRANSFER_TO)); - - onSessionInfoChangedLatch.countDown(); + assertEquals(1, controller.getSelectedRoutes().size()); + assertFalse(getRouteIds(controller.getSelectedRoutes()).contains(ROUTE_ID1)); + assertTrue(getRouteIds(controller.getSelectedRoutes()) + .contains(ROUTE_ID5_TO_TRANSFER_TO)); + assertFalse(getRouteIds(controller.getTransferrableRoutes()) + .contains(ROUTE_ID5_TO_TRANSFER_TO)); + + onControllerUpdatedLatch.countDown(); } }; @@ -601,9 +583,9 @@ public class MediaRouter2Test { mRouter2.registerRouteCallback(mExecutor, routeCallback, RouteDiscoveryPreference.EMPTY); try { - mRouter2.registerSessionCallback(mExecutor, sessionCallback); - mRouter2.requestCreateSession(routeToCreateSessionWith); - assertTrue(onSessionCreatedLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS)); + mRouter2.registerControllerCallback(mExecutor, controllerCallback); + mRouter2.requestCreateController(routeToCreateSessionWith); + assertTrue(onControllerCreatedLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS)); assertEquals(1, controllers.size()); RoutingController controller = controllers.get(0); @@ -615,18 +597,18 @@ public class MediaRouter2Test { assertNotNull(routeToTransferTo); controller.transferToRoute(routeToTransferTo); - assertTrue(onSessionInfoChangedLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS)); + assertTrue(onControllerUpdatedLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS)); } finally { releaseControllers(controllers); mRouter2.unregisterRouteCallback(routeCallback); - mRouter2.unregisterSessionCallback(sessionCallback); + mRouter2.unregisterControllerCallback(controllerCallback); } } - // TODO: Add tests for onSessionReleased() call. + // TODO: Add tests for onSessionReleased() when provider releases the session. @Test - public void testRoutingControllerReleaseShouldIgnoreTransferTo() throws Exception { + public void testRoutingControllerRelease() throws Exception { final List<String> sampleRouteType = new ArrayList<>(); sampleRouteType.add(FEATURE_SAMPLE); @@ -634,29 +616,37 @@ public class MediaRouter2Test { MediaRoute2Info routeToCreateSessionWith = routes.get(ROUTE_ID1); assertNotNull(routeToCreateSessionWith); - final CountDownLatch onSessionCreatedLatch = new CountDownLatch(1); - final CountDownLatch onSessionInfoChangedLatch = new CountDownLatch(1); + final CountDownLatch onControllerCreatedLatch = new CountDownLatch(1); + final CountDownLatch onControllerUpdatedLatch = new CountDownLatch(1); + final CountDownLatch onControllerReleasedLatch = new CountDownLatch(1); final List<RoutingController> controllers = new ArrayList<>(); // Create session with ROUTE_ID1 - SessionCallback sessionCallback = new SessionCallback() { + RoutingControllerCallback controllerCallback = new RoutingControllerCallback() { @Override - public void onSessionCreated(RoutingController controller) { + public void onControllerCreated(RoutingController controller) { assertNotNull(controller); assertTrue(getRouteIds(controller.getSelectedRoutes()).contains(ROUTE_ID1)); controllers.add(controller); - onSessionCreatedLatch.countDown(); + onControllerCreatedLatch.countDown(); } @Override - public void onSessionInfoChanged(RoutingController controller, - RoutingSessionInfo oldInfo, RoutingSessionInfo newInfo) { - if (onSessionCreatedLatch.getCount() != 0 - || !TextUtils.equals( - controllers.get(0).getSessionId(), controller.getSessionId())) { + public void onControllerUpdated(RoutingController controller) { + if (onControllerCreatedLatch.getCount() != 0 + || !TextUtils.equals(controllers.get(0).getId(), controller.getId())) { return; } - onSessionInfoChangedLatch.countDown(); + onControllerUpdatedLatch.countDown(); + } + + @Override + public void onControllerReleased(RoutingController controller) { + if (onControllerCreatedLatch.getCount() != 0 + || !TextUtils.equals(controllers.get(0).getId(), controller.getId())) { + return; + } + onControllerReleasedLatch.countDown(); } }; @@ -665,9 +655,9 @@ public class MediaRouter2Test { mRouter2.registerRouteCallback(mExecutor, routeCallback, RouteDiscoveryPreference.EMPTY); try { - mRouter2.registerSessionCallback(mExecutor, sessionCallback); - mRouter2.requestCreateSession(routeToCreateSessionWith); - assertTrue(onSessionCreatedLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS)); + mRouter2.registerControllerCallback(mExecutor, controllerCallback); + mRouter2.requestCreateController(routeToCreateSessionWith); + assertTrue(onControllerCreatedLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS)); assertEquals(1, controllers.size()); RoutingController controller = controllers.get(0); @@ -684,20 +674,23 @@ public class MediaRouter2Test { // This call should be ignored. // The onSessionInfoChanged() shouldn't be called. controller.transferToRoute(routeToTransferTo); - assertFalse(onSessionInfoChangedLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS)); + assertFalse(onControllerUpdatedLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS)); + + // onControllerReleased should be called. + assertTrue(onControllerReleasedLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS)); } finally { releaseControllers(controllers); mRouter2.unregisterRouteCallback(routeCallback); - mRouter2.unregisterSessionCallback(sessionCallback); + mRouter2.unregisterControllerCallback(controllerCallback); } } // TODO: Consider adding tests with bluetooth connection/disconnection. @Test - public void testGetDefaultController() { - final RoutingController defaultController = mRouter2.getDefaultController(); - assertNotNull(defaultController); - assertFalse(defaultController.isReleased()); + public void testGetSystemController() { + final RoutingController systemController = mRouter2.getSystemController(); + assertNotNull(systemController); + assertFalse(systemController.isReleased()); } // Helper for getting routes easily diff --git a/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouterManagerTest.java b/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouterManagerTest.java index 39313eec6bf8..7726e90674f2 100644 --- a/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouterManagerTest.java +++ b/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouterManagerTest.java @@ -28,7 +28,7 @@ import android.content.Intent; import android.media.MediaRoute2Info; import android.media.MediaRouter2; import android.media.MediaRouter2.RouteCallback; -import android.media.MediaRouter2.SessionCallback; +import android.media.MediaRouter2.RoutingControllerCallback; import android.media.MediaRouter2Manager; import android.media.RouteDiscoveryPreference; import android.media.RoutingSessionInfo; @@ -110,7 +110,7 @@ public class MediaRouterManagerTest { private final List<MediaRouter2Manager.Callback> mManagerCallbacks = new ArrayList<>(); private final List<RouteCallback> mRouteCallbacks = new ArrayList<>(); - private final List<SessionCallback> mSessionCallbacks = new ArrayList<>(); + private final List<RoutingControllerCallback> mControllerCallbacks = new ArrayList<>(); public static final List<String> FEATURES_ALL = new ArrayList(); public static final List<String> FEATURES_SPECIAL = new ArrayList(); @@ -213,9 +213,9 @@ public class MediaRouterManagerTest { addManagerCallback(new MediaRouter2Manager.Callback()); //TODO: remove this when it's not necessary. addRouterCallback(new MediaRouter2.RouteCallback()); - addSessionCallback(new SessionCallback() { + addSessionCallback(new RoutingControllerCallback() { @Override - public void onSessionCreated(MediaRouter2.RoutingController controller) { + public void onControllerCreated(MediaRouter2.RoutingController controller) { if (createRouteMap(controller.getSelectedRoutes()).containsKey(ROUTE_ID1)) { latch.countDown(); } @@ -414,9 +414,9 @@ public class MediaRouterManagerTest { mRouter2.registerRouteCallback(mExecutor, routeCallback, RouteDiscoveryPreference.EMPTY); } - private void addSessionCallback(SessionCallback sessionCallback) { - mSessionCallbacks.add(sessionCallback); - mRouter2.registerSessionCallback(mExecutor, sessionCallback); + private void addSessionCallback(RoutingControllerCallback controllerCallback) { + mControllerCallbacks.add(controllerCallback); + mRouter2.registerControllerCallback(mExecutor, controllerCallback); } private void clearCallbacks() { @@ -430,10 +430,10 @@ public class MediaRouterManagerTest { } mRouteCallbacks.clear(); - for (SessionCallback sessionCallback : mSessionCallbacks) { - mRouter2.unregisterSessionCallback(sessionCallback); + for (RoutingControllerCallback controllerCallback : mControllerCallbacks) { + mRouter2.unregisterControllerCallback(controllerCallback); } - mSessionCallbacks.clear(); + mControllerCallbacks.clear(); } private void releaseAllSessions() { diff --git a/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java b/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java index 5636cc8a3ca3..de4817cc4c49 100644 --- a/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java +++ b/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java @@ -85,6 +85,7 @@ public class SecureSettings { Settings.Secure.TTY_MODE_ENABLED, Settings.Secure.RTT_CALLING_MODE, Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR, + Settings.Secure.MINIMAL_POST_PROCESSING_ALLOWED, Settings.Secure.NIGHT_DISPLAY_CUSTOM_START_TIME, Settings.Secure.NIGHT_DISPLAY_CUSTOM_END_TIME, Settings.Secure.NIGHT_DISPLAY_COLOR_TEMPERATURE, diff --git a/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java b/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java index ed06fa71cff1..849f22f7e0a2 100644 --- a/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java +++ b/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java @@ -131,6 +131,7 @@ public class SecureSettingsValidators { VALIDATORS.put( Secure.INCALL_POWER_BUTTON_BEHAVIOR, new DiscreteValueValidator(new String[] {"1", "2"})); + VALIDATORS.put(Secure.MINIMAL_POST_PROCESSING_ALLOWED, BOOLEAN_VALIDATOR); VALIDATORS.put(Secure.NIGHT_DISPLAY_CUSTOM_START_TIME, NON_NEGATIVE_INTEGER_VALIDATOR); VALIDATORS.put(Secure.NIGHT_DISPLAY_CUSTOM_END_TIME, NON_NEGATIVE_INTEGER_VALIDATOR); VALIDATORS.put(Secure.NIGHT_DISPLAY_COLOR_TEMPERATURE, NON_NEGATIVE_INTEGER_VALIDATOR); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowController.java index d346d395e444..fe4879b0b071 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowController.java @@ -256,7 +256,12 @@ public class NotificationShadeWindowController implements Callback, Dumpable, mLpChanged.flags &= ~LayoutParams.FLAG_ALT_FOCUSABLE_IM; } else if (state.isKeyguardShowingAndNotOccluded() || panelFocusable) { mLpChanged.flags &= ~LayoutParams.FLAG_NOT_FOCUSABLE; - mLpChanged.flags |= LayoutParams.FLAG_ALT_FOCUSABLE_IM; + // Make sure to remove FLAG_ALT_FOCUSABLE_IM when keyguard needs input. + if (state.mKeyguardNeedsInput) { + mLpChanged.flags &= ~LayoutParams.FLAG_ALT_FOCUSABLE_IM; + } else { + mLpChanged.flags |= LayoutParams.FLAG_ALT_FOCUSABLE_IM; + } } else { mLpChanged.flags |= LayoutParams.FLAG_NOT_FOCUSABLE; mLpChanged.flags &= ~LayoutParams.FLAG_ALT_FOCUSABLE_IM; diff --git a/services/core/java/com/android/server/am/CoreSettingsObserver.java b/services/core/java/com/android/server/am/CoreSettingsObserver.java index aa8bc04f0f7c..fa55701cd882 100644 --- a/services/core/java/com/android/server/am/CoreSettingsObserver.java +++ b/services/core/java/com/android/server/am/CoreSettingsObserver.java @@ -16,15 +16,21 @@ package com.android.server.am; +import android.app.ActivityThread; import android.content.Context; import android.database.ContentObserver; import android.net.Uri; import android.os.Bundle; +import android.provider.DeviceConfig; import android.provider.Settings; +import android.widget.WidgetFlags; import com.android.internal.annotations.VisibleForTesting; +import java.util.ArrayList; import java.util.HashMap; +import java.util.HashSet; +import java.util.List; import java.util.Map; /** @@ -36,6 +42,19 @@ import java.util.Map; final class CoreSettingsObserver extends ContentObserver { private static final String LOG_TAG = CoreSettingsObserver.class.getSimpleName(); + private static class DeviceConfigEntry { + String namespace; + String flag; + String coreSettingKey; + Class<?> type; + DeviceConfigEntry(String namespace, String flag, String coreSettingKey, Class<?> type) { + this.namespace = namespace; + this.flag = flag; + this.coreSettingKey = coreSettingKey; + this.type = type; + } + } + // mapping form property name to its type @VisibleForTesting static final Map<String, Class<?>> sSecureSettingToTypeMap = new HashMap< @@ -46,6 +65,7 @@ final class CoreSettingsObserver extends ContentObserver { @VisibleForTesting static final Map<String, Class<?>> sGlobalSettingToTypeMap = new HashMap< String, Class<?>>(); + static final List<DeviceConfigEntry> sDeviceConfigEntries = new ArrayList<DeviceConfigEntry>(); static { sSecureSettingToTypeMap.put(Settings.Secure.LONG_PRESS_TIMEOUT, int.class); sSecureSettingToTypeMap.put(Settings.Secure.MULTI_PRESS_TIMEOUT, int.class); @@ -84,6 +104,11 @@ final class CoreSettingsObserver extends ContentObserver { sGlobalSettingToTypeMap.put(Settings.Global.GAME_DRIVER_BLACKLISTS, String.class); sGlobalSettingToTypeMap.put(Settings.Global.GAME_DRIVER_SPHAL_LIBRARIES, String.class); // add other global settings here... + + sDeviceConfigEntries.add(new DeviceConfigEntry( + DeviceConfig.NAMESPACE_WIDGET, WidgetFlags.ENABLE_CURSOR_CONTROL, + WidgetFlags.KEY_ENABLE_CURSOR_CONTROL, boolean.class)); + // add other device configs here... } private final Bundle mCoreSettings = new Bundle(); @@ -112,6 +137,7 @@ final class CoreSettingsObserver extends ContentObserver { populateSettings(mCoreSettings, sSecureSettingToTypeMap); populateSettings(mCoreSettings, sSystemSettingToTypeMap); populateSettings(mCoreSettings, sGlobalSettingToTypeMap); + populateSettingsFromDeviceConfig(); mActivityManagerService.onCoreSettingsChange(mCoreSettings); } @@ -133,6 +159,16 @@ final class CoreSettingsObserver extends ContentObserver { mActivityManagerService.mContext.getContentResolver().registerContentObserver( uri, false, this); } + + HashSet<String> deviceConfigNamespaces = new HashSet<>(); + for (DeviceConfigEntry entry : sDeviceConfigEntries) { + if (!deviceConfigNamespaces.contains(entry.namespace)) { + DeviceConfig.addOnPropertiesChangedListener( + entry.namespace, ActivityThread.currentApplication().getMainExecutor(), + (DeviceConfig.Properties prop) -> onChange(false)); + deviceConfigNamespaces.add(entry.namespace); + } + } } @VisibleForTesting @@ -164,4 +200,25 @@ final class CoreSettingsObserver extends ContentObserver { } } } + + private void populateSettingsFromDeviceConfig() { + for (DeviceConfigEntry entry : sDeviceConfigEntries) { + if (entry.type == String.class) { + mCoreSettings.putString(entry.coreSettingKey, + DeviceConfig.getString(entry.namespace, entry.flag, "")); + } else if (entry.type == int.class) { + mCoreSettings.putInt(entry.coreSettingKey, + DeviceConfig.getInt(entry.namespace, entry.flag, 0)); + } else if (entry.type == float.class) { + mCoreSettings.putFloat(entry.coreSettingKey, + DeviceConfig.getFloat(entry.namespace, entry.flag, 0)); + } else if (entry.type == long.class) { + mCoreSettings.putLong(entry.coreSettingKey, + DeviceConfig.getLong(entry.namespace, entry.flag, 0)); + } else if (entry.type == boolean.class) { + mCoreSettings.putInt(entry.coreSettingKey, + DeviceConfig.getBoolean(entry.namespace, entry.flag, false) ? 1 : 0); + } + } + } } diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java index 58e519d1f595..d27b245d77ba 100644 --- a/services/core/java/com/android/server/display/DisplayManagerService.java +++ b/services/core/java/com/android/server/display/DisplayManagerService.java @@ -39,6 +39,7 @@ import android.content.pm.PackageManager; import android.content.pm.ParceledListSlice; import android.content.res.Resources; import android.content.res.TypedArray; +import android.database.ContentObserver; import android.graphics.ColorSpace; import android.graphics.Point; import android.graphics.Rect; @@ -60,6 +61,7 @@ import android.hardware.display.WifiDisplayStatus; import android.hardware.input.InputManagerInternal; import android.media.projection.IMediaProjection; import android.media.projection.IMediaProjectionManager; +import android.net.Uri; import android.os.Binder; import android.os.Handler; import android.os.IBinder; @@ -77,6 +79,7 @@ import android.os.SystemProperties; import android.os.Trace; import android.os.UserHandle; import android.os.UserManager; +import android.provider.Settings; import android.text.TextUtils; import android.util.IntArray; import android.util.Pair; @@ -304,6 +307,13 @@ public final class DisplayManagerService extends SystemService { private SensorManager mSensorManager; + // Whether minimal post processing is allowed by the user. + @GuardedBy("mSyncRoot") + private boolean mMinimalPostProcessingAllowed; + + // Receives notifications about changes to Settings. + private SettingsObserver mSettingsObserver; + public DisplayManagerService(Context context) { this(context, new Injector()); } @@ -403,6 +413,7 @@ public final class DisplayManagerService extends SystemService { BrightnessConfiguration config = mPersistentDataStore.getBrightnessConfiguration(userSerial); mDisplayPowerController.setBrightnessConfiguration(config); + handleSettingsChange(); } mDisplayPowerController.onSwitchUser(newUserId); } @@ -428,6 +439,8 @@ public final class DisplayManagerService extends SystemService { // Just in case the top inset changed before the system was ready. At this point, any // relevant configuration should be in place. recordTopInsetLocked(mLogicalDisplays.get(Display.DEFAULT_DISPLAY)); + + updateSettingsLocked(); } mDisplayModeDirector.setDesiredDisplayModeSpecsListener( @@ -435,6 +448,8 @@ public final class DisplayManagerService extends SystemService { mDisplayModeDirector.start(mSensorManager); mHandler.sendEmptyMessage(MSG_REGISTER_ADDITIONAL_DISPLAY_ADAPTERS); + + mSettingsObserver = new SettingsObserver(); } @VisibleForTesting @@ -569,6 +584,33 @@ public final class DisplayManagerService extends SystemService { } } + private class SettingsObserver extends ContentObserver { + SettingsObserver() { + super(mHandler); + + mContext.getContentResolver().registerContentObserver( + Settings.Secure.getUriFor( + Settings.Secure.MINIMAL_POST_PROCESSING_ALLOWED), false, this); + } + + @Override + public void onChange(boolean selfChange, Uri uri) { + handleSettingsChange(); + } + } + + private void handleSettingsChange() { + synchronized (mSyncRoot) { + updateSettingsLocked(); + scheduleTraversalLocked(false); + } + } + + private void updateSettingsLocked() { + mMinimalPostProcessingAllowed = Settings.Secure.getIntForUser(mContext.getContentResolver(), + Settings.Secure.MINIMAL_POST_PROCESSING_ALLOWED, 1, UserHandle.USER_CURRENT) != 0; + } + private DisplayInfo getDisplayInfoInternal(int displayId, int callingUid) { synchronized (mSyncRoot) { LogicalDisplay display = mLogicalDisplays.get(displayId); @@ -1192,7 +1234,7 @@ public final class DisplayManagerService extends SystemService { } private void setDisplayPropertiesInternal(int displayId, boolean hasContent, - float requestedRefreshRate, int requestedModeId, boolean requestedMinimalPostProcessing, + float requestedRefreshRate, int requestedModeId, boolean preferMinimalPostProcessing, boolean inTraversal) { synchronized (mSyncRoot) { LogicalDisplay display = mLogicalDisplays.get(displayId); @@ -1220,14 +1262,13 @@ public final class DisplayManagerService extends SystemService { mDisplayModeDirector.getAppRequestObserver().setAppRequestedMode( displayId, requestedModeId); + if (display.getDisplayInfoLocked().minimalPostProcessingSupported) { + boolean mppRequest = mMinimalPostProcessingAllowed && preferMinimalPostProcessing; - if (display.getDisplayInfoLocked().minimalPostProcessingSupported - && (display.getRequestedMinimalPostProcessingLocked() - != requestedMinimalPostProcessing)) { - - display.setRequestedMinimalPostProcessingLocked(requestedMinimalPostProcessing); - - shouldScheduleTraversal = true; + if (display.getRequestedMinimalPostProcessingLocked() != mppRequest) { + display.setRequestedMinimalPostProcessingLocked(mppRequest); + shouldScheduleTraversal = true; + } } if (shouldScheduleTraversal) { diff --git a/services/core/java/com/android/server/media/BluetoothRouteProvider.java b/services/core/java/com/android/server/media/BluetoothRouteProvider.java index 9f42c3625a51..837c489c0cac 100644 --- a/services/core/java/com/android/server/media/BluetoothRouteProvider.java +++ b/services/core/java/com/android/server/media/BluetoothRouteProvider.java @@ -145,7 +145,7 @@ class BluetoothRouteProvider { BluetoothRouteInfo newBtRoute = new BluetoothRouteInfo(); newBtRoute.btDevice = device; newBtRoute.route = new MediaRoute2Info.Builder(device.getAddress(), device.getName()) - .addFeature(SystemMediaRoute2Provider.TYPE_LIVE_AUDIO) + .addFeature(MediaRoute2Info.FEATURE_LIVE_AUDIO) .setConnectionState(MediaRoute2Info.CONNECTION_STATE_DISCONNECTED) .setDescription(mContext.getResources().getText( R.string.bluetooth_a2dp_audio_route_name).toString()) diff --git a/services/core/java/com/android/server/media/SystemMediaRoute2Provider.java b/services/core/java/com/android/server/media/SystemMediaRoute2Provider.java index ebea6c3dc558..6f6d8a1e8df4 100644 --- a/services/core/java/com/android/server/media/SystemMediaRoute2Provider.java +++ b/services/core/java/com/android/server/media/SystemMediaRoute2Provider.java @@ -16,6 +16,9 @@ package com.android.server.media; +import static android.media.MediaRoute2Info.FEATURE_LIVE_AUDIO; +import static android.media.MediaRoute2Info.FEATURE_LIVE_VIDEO; + import android.annotation.NonNull; import android.content.ComponentName; import android.content.Context; @@ -51,10 +54,6 @@ class SystemMediaRoute2Provider extends MediaRoute2Provider { static final String DEFAULT_ROUTE_ID = "DEFAULT_ROUTE"; static final String SYSTEM_SESSION_ID = "SYSTEM_SESSION"; - // TODO: Move these to a proper place - public static final String TYPE_LIVE_AUDIO = "android.media.intent.route.TYPE_LIVE_AUDIO"; - public static final String TYPE_LIVE_VIDEO = "android.media.intent.route.TYPE_LIVE_VIDEO"; - private final AudioManager mAudioManager; private final IAudioService mAudioService; private final Handler mHandler; @@ -158,8 +157,8 @@ class SystemMediaRoute2Provider extends MediaRoute2Provider { : MediaRoute2Info.PLAYBACK_VOLUME_VARIABLE) .setVolumeMax(mAudioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC)) .setVolume(mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC)) - .addFeature(TYPE_LIVE_AUDIO) - .addFeature(TYPE_LIVE_VIDEO) + .addFeature(FEATURE_LIVE_AUDIO) + .addFeature(FEATURE_LIVE_VIDEO) .build(); AudioRoutesInfo newAudioRoutes = null; @@ -209,8 +208,8 @@ class SystemMediaRoute2Provider extends MediaRoute2Provider { : MediaRoute2Info.PLAYBACK_VOLUME_VARIABLE) .setVolumeMax(mAudioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC)) .setVolume(mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC)) - .addFeature(TYPE_LIVE_AUDIO) - .addFeature(TYPE_LIVE_VIDEO) + .addFeature(FEATURE_LIVE_AUDIO) + .addFeature(FEATURE_LIVE_VIDEO) .build(); publishRoutes(); diff --git a/wifi/java/android/net/wifi/ScanResult.aidl b/wifi/java/android/net/wifi/ScanResult.aidl index bb66722e4a13..b30689ca5d16 100644 --- a/wifi/java/android/net/wifi/ScanResult.aidl +++ b/wifi/java/android/net/wifi/ScanResult.aidl @@ -16,4 +16,4 @@ package android.net.wifi; -parcelable ScanResult; +@JavaOnlyStableParcelable parcelable ScanResult; diff --git a/wifi/java/android/net/wifi/ScanResult.java b/wifi/java/android/net/wifi/ScanResult.java index 341330587614..3fda6cda92f5 100644 --- a/wifi/java/android/net/wifi/ScanResult.java +++ b/wifi/java/android/net/wifi/ScanResult.java @@ -17,6 +17,7 @@ package android.net.wifi; import android.annotation.IntDef; +import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SystemApi; import android.compat.annotation.UnsupportedAppUsage; @@ -27,8 +28,10 @@ import com.android.internal.annotations.VisibleForTesting; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; +import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.List; import java.util.Objects; @@ -576,67 +579,120 @@ public class ScanResult implements Parcelable { @UnsupportedAppUsage public List<String> anqpLines; - /** information elements from beacon - * @hide + /** + * information elements from beacon. */ public static class InformationElement { + /** @hide */ @UnsupportedAppUsage public static final int EID_SSID = 0; + /** @hide */ @UnsupportedAppUsage public static final int EID_SUPPORTED_RATES = 1; + /** @hide */ @UnsupportedAppUsage public static final int EID_TIM = 5; + /** @hide */ @UnsupportedAppUsage public static final int EID_BSS_LOAD = 11; + /** @hide */ @UnsupportedAppUsage public static final int EID_ERP = 42; + /** @hide */ public static final int EID_HT_CAPABILITIES = 45; + /** @hide */ @UnsupportedAppUsage public static final int EID_RSN = 48; + /** @hide */ @UnsupportedAppUsage public static final int EID_EXTENDED_SUPPORTED_RATES = 50; + /** @hide */ @UnsupportedAppUsage public static final int EID_HT_OPERATION = 61; + /** @hide */ @UnsupportedAppUsage public static final int EID_INTERWORKING = 107; + /** @hide */ @UnsupportedAppUsage public static final int EID_ROAMING_CONSORTIUM = 111; + /** @hide */ @UnsupportedAppUsage public static final int EID_EXTENDED_CAPS = 127; + /** @hide */ public static final int EID_VHT_CAPABILITIES = 191; + /** @hide */ @UnsupportedAppUsage public static final int EID_VHT_OPERATION = 192; + /** @hide */ @UnsupportedAppUsage public static final int EID_VSA = 221; + /** @hide */ public static final int EID_EXTENSION_PRESENT = 255; - /** - * Extension IDs - */ + // Extension IDs + /** @hide */ public static final int EID_EXT_HE_CAPABILITIES = 35; + /** @hide */ public static final int EID_EXT_HE_OPERATION = 36; + /** @hide */ @UnsupportedAppUsage public int id; + /** @hide */ public int idExt; + + /** @hide */ @UnsupportedAppUsage public byte[] bytes; + /** @hide */ public InformationElement() { } - public InformationElement(InformationElement rhs) { + public InformationElement(@NonNull InformationElement rhs) { this.id = rhs.id; this.idExt = rhs.idExt; this.bytes = rhs.bytes.clone(); } + + /** + * The element ID of the information element. Defined in the IEEE 802.11-2016 spec + * Table 9-77. + */ + public int getId() { + return id; + } + + /** + * The element ID Extension of the information element. Defined in the IEEE 802.11-2016 spec + * Table 9-77. + */ + public int getIdExt() { + return idExt; + } + + /** + * Get the specific content of the information element. + */ + @NonNull + public ByteBuffer getBytes() { + return ByteBuffer.wrap(bytes).asReadOnlyBuffer(); + } } - /** information elements found in the beacon + /** + * information elements found in the beacon. * @hide */ @UnsupportedAppUsage public InformationElement[] informationElements; + /** + * Get all information elements found in the beacon. + */ + @NonNull + public List<InformationElement> getInformationElements() { + return Collections.unmodifiableList(Arrays.asList(informationElements)); + } /** ANQP response elements. * @hide @@ -762,8 +818,8 @@ public class ScanResult implements Parcelable { this.wifiSsid = wifiSsid; } - /** copy constructor {@hide} */ - public ScanResult(ScanResult source) { + /** copy constructor */ + public ScanResult(@NonNull ScanResult source) { if (source != null) { wifiSsid = source.wifiSsid; SSID = source.SSID; @@ -929,9 +985,8 @@ public class ScanResult implements Parcelable { } } - /** Implement the Parcelable interface {@hide} */ - @UnsupportedAppUsage - public static final @android.annotation.NonNull Creator<ScanResult> CREATOR = + /** Implement the Parcelable interface */ + public static final @NonNull Creator<ScanResult> CREATOR = new Creator<ScanResult>() { public ScanResult createFromParcel(Parcel in) { WifiSsid wifiSsid = null; diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pWfdInfo.java b/wifi/java/android/net/wifi/p2p/WifiP2pWfdInfo.java index a4115027b6c1..5484d248429f 100644 --- a/wifi/java/android/net/wifi/p2p/WifiP2pWfdInfo.java +++ b/wifi/java/android/net/wifi/p2p/WifiP2pWfdInfo.java @@ -61,6 +61,9 @@ public final class WifiP2pWfdInfo implements Parcelable { * {@link #mDeviceInfo} & {@link #DEVICE_TYPE} is one of {@link #DEVICE_TYPE_WFD_SOURCE}, * {@link #DEVICE_TYPE_PRIMARY_SINK}, {@link #DEVICE_TYPE_SECONDARY_SINK} or * {@link #DEVICE_TYPE_SOURCE_OR_PRIMARY_SINK}. + * + * The bit definition is listed in 5.1.2 WFD Device Information Subelement in + * Wi-Fi Display Technical Specification. */ private static final int DEVICE_TYPE = 1 << 1 | 1 << 0; private static final int COUPLED_SINK_SUPPORT_AT_SOURCE = 1 << 2; @@ -69,6 +72,8 @@ public final class WifiP2pWfdInfo implements Parcelable { private static final int SESSION_AVAILABLE_BIT2 = 1 << 5; private static final int SESSION_AVAILABLE = SESSION_AVAILABLE_BIT2 | SESSION_AVAILABLE_BIT1; + /* The support of Content Protection using the HDCP system 2.0/2.1. */ + private static final int CONTENT_PROTECTION_SUPPORT = 1 << 8; private int mCtrlPort; @@ -146,6 +151,26 @@ public final class WifiP2pWfdInfo implements Parcelable { } } + /** + * @return true if Content Protection using the HDCP system 2.0/2.1 is supported. + */ + public boolean isContentProtectionSupported() { + return (mDeviceInfo & CONTENT_PROTECTION_SUPPORT) != 0; + } + + /** + * Sets whether Content Protection using the HDCP system 2.0/2.1 is supported. + * + * @param enabled true to indicate that Content Protection is supported, false otherwise. + */ + public void setContentProtectionSupported(boolean enabled) { + if (enabled) { + mDeviceInfo |= CONTENT_PROTECTION_SUPPORT; + } else { + mDeviceInfo &= ~CONTENT_PROTECTION_SUPPORT; + } + } + /** Returns the TCP port at which the WFD Device listens for RTSP messages. */ public int getControlPort() { return mCtrlPort; diff --git a/wifi/java/android/net/wifi/wificond/DeviceWiphyCapabilities.java b/wifi/java/android/net/wifi/wificond/DeviceWiphyCapabilities.java index de1c7600f8ef..13ae3b322841 100644 --- a/wifi/java/android/net/wifi/wificond/DeviceWiphyCapabilities.java +++ b/wifi/java/android/net/wifi/wificond/DeviceWiphyCapabilities.java @@ -37,12 +37,21 @@ public final class DeviceWiphyCapabilities implements Parcelable { private boolean m80211nSupported; private boolean m80211acSupported; private boolean m80211axSupported; + private boolean mChannelWidth160MhzSupported; + private boolean mChannelWidth80p80MhzSupported; + private int mMaxNumberTxSpatialStreams; + private int mMaxNumberRxSpatialStreams; + /** public constructor */ public DeviceWiphyCapabilities() { m80211nSupported = false; m80211acSupported = false; m80211axSupported = false; + mChannelWidth160MhzSupported = false; + mChannelWidth80p80MhzSupported = false; + mMaxNumberTxSpatialStreams = 1; + mMaxNumberRxSpatialStreams = 1; } /** @@ -91,6 +100,88 @@ public final class DeviceWiphyCapabilities implements Parcelable { } } + /** + * Get the support for channel bandwidth + * + * @param chWidth valid values from {@link ScanResult}'s {@code CHANNEL_WIDTH_} + * + * @return {@code true} if supported, {@code false} otherwise. + */ + public boolean isChannelWidthSupported(int chWidth) { + switch (chWidth) { + case ScanResult.CHANNEL_WIDTH_20MHZ: + return true; + case ScanResult.CHANNEL_WIDTH_40MHZ: + return (m80211nSupported || m80211acSupported || m80211axSupported); + case ScanResult.CHANNEL_WIDTH_80MHZ: + return (m80211acSupported || m80211axSupported); + case ScanResult.CHANNEL_WIDTH_160MHZ: + return mChannelWidth160MhzSupported; + case ScanResult.CHANNEL_WIDTH_80MHZ_PLUS_MHZ: + return mChannelWidth80p80MhzSupported; + default: + Log.e(TAG, "isChannelWidthSupported called with invalid channel width: " + chWidth); + } + return false; + } + + /** + * Set support for channel bandwidth + * + * @param chWidth valid values are {@link ScanResult#CHANNEL_WIDTH_160MHZ} and + * {@link ScanResult#CHANNEL_WIDTH_80MHZ_PLUS_MHZ} + * @param support {@code true} if supported, {@code false} otherwise. + */ + public void setChannelWidthSupported(int chWidth, boolean support) { + switch (chWidth) { + case ScanResult.CHANNEL_WIDTH_160MHZ: + mChannelWidth160MhzSupported = support; + break; + case ScanResult.CHANNEL_WIDTH_80MHZ_PLUS_MHZ: + mChannelWidth80p80MhzSupported = support; + break; + default: + Log.e(TAG, "setChannelWidthSupported called with Invalid channel width: " + + chWidth); + } + } + + /** + * Get maximum number of transmit spatial streams + * + * @return number of spatial streams + */ + public int getMaxNumberTxSpatialStreams() { + return mMaxNumberTxSpatialStreams; + } + + /** + * Set maximum number of transmit spatial streams + * + * @param streams number of spatial streams + */ + public void setMaxNumberTxSpatialStreams(int streams) { + mMaxNumberTxSpatialStreams = streams; + } + + /** + * Get maximum number of receive spatial streams + * + * @return number of streams + */ + public int getMaxNumberRxSpatialStreams() { + return mMaxNumberRxSpatialStreams; + } + + /** + * Set maximum number of receive spatial streams + * + * @param streams number of streams + */ + public void setMaxNumberRxSpatialStreams(int streams) { + mMaxNumberRxSpatialStreams = streams; + } + /** override comparator */ @Override public boolean equals(Object rhs) { @@ -102,13 +193,19 @@ public final class DeviceWiphyCapabilities implements Parcelable { return m80211nSupported == capa.m80211nSupported && m80211acSupported == capa.m80211acSupported - && m80211axSupported == capa.m80211axSupported; + && m80211axSupported == capa.m80211axSupported + && mChannelWidth160MhzSupported == capa.mChannelWidth160MhzSupported + && mChannelWidth80p80MhzSupported == capa.mChannelWidth80p80MhzSupported + && mMaxNumberTxSpatialStreams == capa.mMaxNumberTxSpatialStreams + && mMaxNumberRxSpatialStreams == capa.mMaxNumberRxSpatialStreams; } /** override hash code */ @Override public int hashCode() { - return Objects.hash(m80211nSupported, m80211acSupported, m80211axSupported); + return Objects.hash(m80211nSupported, m80211acSupported, m80211axSupported, + mChannelWidth160MhzSupported, mChannelWidth80p80MhzSupported, + mMaxNumberTxSpatialStreams, mMaxNumberRxSpatialStreams); } /** implement Parcelable interface */ @@ -126,6 +223,10 @@ public final class DeviceWiphyCapabilities implements Parcelable { out.writeBoolean(m80211nSupported); out.writeBoolean(m80211acSupported); out.writeBoolean(m80211axSupported); + out.writeBoolean(mChannelWidth160MhzSupported); + out.writeBoolean(mChannelWidth80p80MhzSupported); + out.writeInt(mMaxNumberTxSpatialStreams); + out.writeInt(mMaxNumberRxSpatialStreams); } @Override @@ -134,6 +235,13 @@ public final class DeviceWiphyCapabilities implements Parcelable { sb.append("m80211nSupported:").append(m80211nSupported ? "Yes" : "No"); sb.append("m80211acSupported:").append(m80211acSupported ? "Yes" : "No"); sb.append("m80211axSupported:").append(m80211axSupported ? "Yes" : "No"); + sb.append("mChannelWidth160MhzSupported: ") + .append(mChannelWidth160MhzSupported ? "Yes" : "No"); + sb.append("mChannelWidth80p80MhzSupported: ") + .append(mChannelWidth80p80MhzSupported ? "Yes" : "No"); + sb.append("mMaxNumberTxSpatialStreams: ").append(mMaxNumberTxSpatialStreams); + sb.append("mMaxNumberRxSpatialStreams: ").append(mMaxNumberRxSpatialStreams); + return sb.toString(); } @@ -149,6 +257,10 @@ public final class DeviceWiphyCapabilities implements Parcelable { capabilities.m80211nSupported = in.readBoolean(); capabilities.m80211acSupported = in.readBoolean(); capabilities.m80211axSupported = in.readBoolean(); + capabilities.mChannelWidth160MhzSupported = in.readBoolean(); + capabilities.mChannelWidth80p80MhzSupported = in.readBoolean(); + capabilities.mMaxNumberTxSpatialStreams = in.readInt(); + capabilities.mMaxNumberRxSpatialStreams = in.readInt(); return capabilities; } diff --git a/wifi/tests/src/android/net/wifi/p2p/WifiP2pWfdInfoTest.java b/wifi/tests/src/android/net/wifi/p2p/WifiP2pWfdInfoTest.java index cea73efc88d0..15a0aacf6e5b 100644 --- a/wifi/tests/src/android/net/wifi/p2p/WifiP2pWfdInfoTest.java +++ b/wifi/tests/src/android/net/wifi/p2p/WifiP2pWfdInfoTest.java @@ -45,6 +45,7 @@ public class WifiP2pWfdInfoTest { // initialize device info flags. mSourceInfo.setDeviceType(WifiP2pWfdInfo.DEVICE_TYPE_WFD_SOURCE); mSourceInfo.setSessionAvailable(true); + mSourceInfo.setContentProtectionSupported(true); } /** @@ -63,13 +64,16 @@ public class WifiP2pWfdInfoTest { info.setSessionAvailable(true); assertTrue(info.isSessionAvailable()); + info.setContentProtectionSupported(true); + assertTrue(info.isContentProtectionSupported()); + info.setControlPort(TEST_CTRL_PORT); assertEquals(TEST_CTRL_PORT, info.getControlPort()); info.setMaxThroughput(TEST_MAX_TPUT); assertEquals(TEST_MAX_TPUT, info.getMaxThroughput()); - assertEquals("0010270f0400", info.getDeviceInfoHex()); + assertEquals("0110270f0400", info.getDeviceInfoHex()); } /** diff --git a/wifi/tests/src/android/net/wifi/wificond/DeviceWiphyCapabilitiesTest.java b/wifi/tests/src/android/net/wifi/wificond/DeviceWiphyCapabilitiesTest.java index 1479acfe8e20..8e3627acd4ed 100644 --- a/wifi/tests/src/android/net/wifi/wificond/DeviceWiphyCapabilitiesTest.java +++ b/wifi/tests/src/android/net/wifi/wificond/DeviceWiphyCapabilitiesTest.java @@ -45,6 +45,10 @@ public class DeviceWiphyCapabilitiesTest { capa.setWifiStandardSupport(ScanResult.WIFI_STANDARD_11N, true); capa.setWifiStandardSupport(ScanResult.WIFI_STANDARD_11AC, true); capa.setWifiStandardSupport(ScanResult.WIFI_STANDARD_11AX, false); + capa.setChannelWidthSupported(ScanResult.CHANNEL_WIDTH_160MHZ, true); + capa.setChannelWidthSupported(ScanResult.CHANNEL_WIDTH_80MHZ_PLUS_MHZ, false); + capa.setMaxNumberTxSpatialStreams(2); + capa.setMaxNumberRxSpatialStreams(1); Parcel parcel = Parcel.obtain(); capa.writeToParcel(parcel, 0); @@ -56,4 +60,29 @@ public class DeviceWiphyCapabilitiesTest { assertEquals(capa, capaDeserialized); assertEquals(capa.hashCode(), capaDeserialized.hashCode()); } + + /** + * Test mapping wifi standard support into channel width support + */ + @Test + public void testMappingWifiStandardIntoChannelWidthSupport() { + DeviceWiphyCapabilities capa = new DeviceWiphyCapabilities(); + + capa.setWifiStandardSupport(ScanResult.WIFI_STANDARD_11N, false); + capa.setWifiStandardSupport(ScanResult.WIFI_STANDARD_11AC, false); + capa.setWifiStandardSupport(ScanResult.WIFI_STANDARD_11AX, false); + assertEquals(true, capa.isChannelWidthSupported(ScanResult.CHANNEL_WIDTH_20MHZ)); + assertEquals(false, capa.isChannelWidthSupported(ScanResult.CHANNEL_WIDTH_40MHZ)); + assertEquals(false, capa.isChannelWidthSupported(ScanResult.CHANNEL_WIDTH_80MHZ)); + + capa.setWifiStandardSupport(ScanResult.WIFI_STANDARD_11N, true); + assertEquals(true, capa.isChannelWidthSupported(ScanResult.CHANNEL_WIDTH_20MHZ)); + assertEquals(true, capa.isChannelWidthSupported(ScanResult.CHANNEL_WIDTH_40MHZ)); + assertEquals(false, capa.isChannelWidthSupported(ScanResult.CHANNEL_WIDTH_80MHZ)); + + capa.setWifiStandardSupport(ScanResult.WIFI_STANDARD_11AC, true); + assertEquals(true, capa.isChannelWidthSupported(ScanResult.CHANNEL_WIDTH_20MHZ)); + assertEquals(true, capa.isChannelWidthSupported(ScanResult.CHANNEL_WIDTH_40MHZ)); + assertEquals(true, capa.isChannelWidthSupported(ScanResult.CHANNEL_WIDTH_80MHZ)); + } } diff --git a/wifi/tests/src/android/net/wifi/wificond/WifiCondManagerTest.java b/wifi/tests/src/android/net/wifi/wificond/WifiCondManagerTest.java index 619c95efb173..f262268d7179 100644 --- a/wifi/tests/src/android/net/wifi/wificond/WifiCondManagerTest.java +++ b/wifi/tests/src/android/net/wifi/wificond/WifiCondManagerTest.java @@ -1046,6 +1046,10 @@ public class WifiCondManagerTest { capaExpected.setWifiStandardSupport(ScanResult.WIFI_STANDARD_11N, true); capaExpected.setWifiStandardSupport(ScanResult.WIFI_STANDARD_11AC, true); capaExpected.setWifiStandardSupport(ScanResult.WIFI_STANDARD_11AX, false); + capaExpected.setChannelWidthSupported(ScanResult.CHANNEL_WIDTH_160MHZ, true); + capaExpected.setChannelWidthSupported(ScanResult.CHANNEL_WIDTH_80MHZ_PLUS_MHZ, false); + capaExpected.setMaxNumberTxSpatialStreams(2); + capaExpected.setMaxNumberRxSpatialStreams(1); when(mWificond.getDeviceWiphyCapabilities(TEST_INTERFACE_NAME)) .thenReturn(capaExpected); |