Merge "Change saveOnAllViewsInsible from boolean to flags" into oc-dev
diff --git a/api/current.txt b/api/current.txt
index 1df3840..8a25ab4 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -12599,7 +12599,6 @@
public class BitmapShader extends android.graphics.Shader {
ctor public BitmapShader(android.graphics.Bitmap, android.graphics.Shader.TileMode, android.graphics.Shader.TileMode);
- method public void set(android.graphics.Bitmap, android.graphics.Shader.TileMode, android.graphics.Shader.TileMode);
}
public class BlurMaskFilter extends android.graphics.MaskFilter {
@@ -12852,8 +12851,6 @@
ctor public ColorMatrixColorFilter(android.graphics.ColorMatrix);
ctor public ColorMatrixColorFilter(float[]);
method public void getColorMatrix(android.graphics.ColorMatrix);
- method public void setColorMatrix(android.graphics.ColorMatrix);
- method public void setColorMatrixArray(float[]);
}
public abstract class ColorSpace {
@@ -12994,8 +12991,6 @@
public class ComposeShader extends android.graphics.Shader {
ctor public ComposeShader(android.graphics.Shader, android.graphics.Shader, android.graphics.Xfermode);
ctor public ComposeShader(android.graphics.Shader, android.graphics.Shader, android.graphics.PorterDuff.Mode);
- method public void set(android.graphics.Shader, android.graphics.Shader, android.graphics.Xfermode);
- method public void set(android.graphics.Shader, android.graphics.Shader, android.graphics.PorterDuff.Mode);
}
public class CornerPathEffect extends android.graphics.PathEffect {
@@ -13068,15 +13063,11 @@
ctor public LightingColorFilter(int, int);
method public int getColorAdd();
method public int getColorMultiply();
- method public void setColorAdd(int);
- method public void setColorMultiply(int);
}
public class LinearGradient extends android.graphics.Shader {
ctor public LinearGradient(float, float, float, float, int[], float[], android.graphics.Shader.TileMode);
ctor public LinearGradient(float, float, float, float, int, int, android.graphics.Shader.TileMode);
- method public void set(float, float, float, float, int[], float[], android.graphics.Shader.TileMode);
- method public void set(float, float, float, float, int, int, android.graphics.Shader.TileMode);
}
public class MaskFilter {
@@ -13586,10 +13577,6 @@
public class PorterDuffColorFilter extends android.graphics.ColorFilter {
ctor public PorterDuffColorFilter(int, android.graphics.PorterDuff.Mode);
- method public int getColor();
- method public android.graphics.PorterDuff.Mode getMode();
- method public void setColor(int);
- method public void setMode(android.graphics.PorterDuff.Mode);
}
public class PorterDuffXfermode extends android.graphics.Xfermode {
@@ -13599,8 +13586,6 @@
public class RadialGradient extends android.graphics.Shader {
ctor public RadialGradient(float, float, float, int[], float[], android.graphics.Shader.TileMode);
ctor public RadialGradient(float, float, float, int, int, android.graphics.Shader.TileMode);
- method public void set(float, float, float, int[], float[], android.graphics.Shader.TileMode);
- method public void set(float, float, float, int, int, android.graphics.Shader.TileMode);
}
public final class Rect implements android.os.Parcelable {
@@ -13785,8 +13770,6 @@
public class SweepGradient extends android.graphics.Shader {
ctor public SweepGradient(float, float, int[], float[]);
ctor public SweepGradient(float, float, int, int);
- method public void set(float, float, int[], float[]);
- method public void set(float, float, int, int);
}
public class Typeface {
@@ -22774,7 +22757,7 @@
method public android.media.MediaPlayer.DrmInfo getDrmInfo();
method public java.lang.String getDrmPropertyString(java.lang.String) throws android.media.MediaPlayer.NoDrmSchemeException;
method public int getDuration();
- method public android.media.MediaDrm.KeyRequest getKeyRequest(byte[], java.lang.String, int, java.util.Map<java.lang.String, java.lang.String>) throws android.media.MediaPlayer.NoDrmSchemeException;
+ method public android.media.MediaDrm.KeyRequest getKeyRequest(byte[], byte[], java.lang.String, int, java.util.Map<java.lang.String, java.lang.String>) throws android.media.MediaPlayer.NoDrmSchemeException;
method public android.os.PersistableBundle getMetrics();
method public android.media.PlaybackParams getPlaybackParams();
method public int getSelectedTrack(int) throws java.lang.IllegalStateException;
@@ -22788,7 +22771,7 @@
method public void pause() throws java.lang.IllegalStateException;
method public void prepare() throws java.io.IOException, java.lang.IllegalStateException;
method public void prepareAsync() throws java.lang.IllegalStateException;
- method public void prepareDrm(java.util.UUID) throws android.media.MediaPlayer.ProvisioningErrorException, android.media.ResourceBusyException, android.media.UnsupportedSchemeException;
+ method public void prepareDrm(java.util.UUID) throws android.media.MediaPlayer.ProvisioningNetworkErrorException, android.media.MediaPlayer.ProvisioningServerErrorException, android.media.ResourceBusyException, android.media.UnsupportedSchemeException;
method public byte[] provideKeyResponse(byte[], byte[]) throws android.media.DeniedByServerException, android.media.MediaPlayer.NoDrmSchemeException;
method public void release();
method public void releaseDrm() throws android.media.MediaPlayer.NoDrmSchemeException;
@@ -22815,7 +22798,7 @@
method public void setNextMediaPlayer(android.media.MediaPlayer);
method public void setOnBufferingUpdateListener(android.media.MediaPlayer.OnBufferingUpdateListener);
method public void setOnCompletionListener(android.media.MediaPlayer.OnCompletionListener);
- method public void setOnDrmConfigListener(android.media.MediaPlayer.OnDrmConfigListener);
+ method public void setOnDrmConfigHelper(android.media.MediaPlayer.OnDrmConfigHelper);
method public void setOnDrmInfoListener(android.media.MediaPlayer.OnDrmInfoListener);
method public void setOnDrmInfoListener(android.media.MediaPlayer.OnDrmInfoListener, android.os.Handler);
method public void setOnDrmPreparedListener(android.media.MediaPlayer.OnDrmPreparedListener);
@@ -22856,6 +22839,10 @@
field public static final int MEDIA_INFO_VIDEO_RENDERING_START = 3; // 0x3
field public static final int MEDIA_INFO_VIDEO_TRACK_LAGGING = 700; // 0x2bc
field public static final java.lang.String MEDIA_MIMETYPE_TEXT_SUBRIP = "application/x-subrip";
+ field public static final int PREPARE_DRM_STATUS_PREPARATION_ERROR = 3; // 0x3
+ field public static final int PREPARE_DRM_STATUS_PROVISIONING_NETWORK_ERROR = 1; // 0x1
+ field public static final int PREPARE_DRM_STATUS_PROVISIONING_SERVER_ERROR = 2; // 0x2
+ field public static final int PREPARE_DRM_STATUS_SUCCESS = 0; // 0x0
field public static final int SEEK_CLOSEST = 3; // 0x3
field public static final int SEEK_CLOSEST_SYNC = 2; // 0x2
field public static final int SEEK_NEXT_SYNC = 1; // 0x1
@@ -22865,7 +22852,6 @@
}
public static final class MediaPlayer.DrmInfo {
- method public java.lang.String[] getMimes();
method public java.util.Map<java.util.UUID, byte[]> getPssh();
method public java.util.UUID[] getSupportedSchemes();
}
@@ -22897,7 +22883,7 @@
method public abstract void onCompletion(android.media.MediaPlayer);
}
- public static abstract interface MediaPlayer.OnDrmConfigListener {
+ public static abstract interface MediaPlayer.OnDrmConfigHelper {
method public abstract void onDrmConfig(android.media.MediaPlayer);
}
@@ -22906,7 +22892,7 @@
}
public static abstract interface MediaPlayer.OnDrmPreparedListener {
- method public abstract void onDrmPrepared(android.media.MediaPlayer, boolean);
+ method public abstract void onDrmPrepared(android.media.MediaPlayer, int);
}
public static abstract interface MediaPlayer.OnErrorListener {
@@ -22937,8 +22923,12 @@
method public abstract void onVideoSizeChanged(android.media.MediaPlayer, int, int);
}
- public static final class MediaPlayer.ProvisioningErrorException extends android.media.MediaDrmException {
- ctor public MediaPlayer.ProvisioningErrorException(java.lang.String);
+ public static final class MediaPlayer.ProvisioningNetworkErrorException extends android.media.MediaDrmException {
+ ctor public MediaPlayer.ProvisioningNetworkErrorException(java.lang.String);
+ }
+
+ public static final class MediaPlayer.ProvisioningServerErrorException extends android.media.MediaDrmException {
+ ctor public MediaPlayer.ProvisioningServerErrorException(java.lang.String);
}
public static class MediaPlayer.TrackInfo implements android.os.Parcelable {
@@ -26751,8 +26741,8 @@
}
public class DiscoverySession {
- method public java.lang.String createNetworkSpecifierOpen(android.net.wifi.aware.PeerHandle);
- method public java.lang.String createNetworkSpecifierPassphrase(android.net.wifi.aware.PeerHandle, java.lang.String);
+ method public android.net.NetworkSpecifier createNetworkSpecifierOpen(android.net.wifi.aware.PeerHandle);
+ method public android.net.NetworkSpecifier createNetworkSpecifierPassphrase(android.net.wifi.aware.PeerHandle, java.lang.String);
method public void destroy();
method public void sendMessage(android.net.wifi.aware.PeerHandle, int, byte[]);
}
@@ -26838,8 +26828,8 @@
}
public class WifiAwareSession {
- method public java.lang.String createNetworkSpecifierOpen(int, byte[]);
- method public java.lang.String createNetworkSpecifierPassphrase(int, byte[], java.lang.String);
+ method public android.net.NetworkSpecifier createNetworkSpecifierOpen(int, byte[]);
+ method public android.net.NetworkSpecifier createNetworkSpecifierPassphrase(int, byte[], java.lang.String);
method public void destroy();
method public void publish(android.net.wifi.aware.PublishConfig, android.net.wifi.aware.DiscoverySessionCallback, android.os.Handler);
method public void subscribe(android.net.wifi.aware.SubscribeConfig, android.net.wifi.aware.DiscoverySessionCallback, android.os.Handler);
diff --git a/api/system-current.txt b/api/system-current.txt
index d98f38c..8749179 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -13373,7 +13373,6 @@
public class BitmapShader extends android.graphics.Shader {
ctor public BitmapShader(android.graphics.Bitmap, android.graphics.Shader.TileMode, android.graphics.Shader.TileMode);
- method public void set(android.graphics.Bitmap, android.graphics.Shader.TileMode, android.graphics.Shader.TileMode);
}
public class BlurMaskFilter extends android.graphics.MaskFilter {
@@ -13626,8 +13625,6 @@
ctor public ColorMatrixColorFilter(android.graphics.ColorMatrix);
ctor public ColorMatrixColorFilter(float[]);
method public void getColorMatrix(android.graphics.ColorMatrix);
- method public void setColorMatrix(android.graphics.ColorMatrix);
- method public void setColorMatrixArray(float[]);
}
public abstract class ColorSpace {
@@ -13768,8 +13765,6 @@
public class ComposeShader extends android.graphics.Shader {
ctor public ComposeShader(android.graphics.Shader, android.graphics.Shader, android.graphics.Xfermode);
ctor public ComposeShader(android.graphics.Shader, android.graphics.Shader, android.graphics.PorterDuff.Mode);
- method public void set(android.graphics.Shader, android.graphics.Shader, android.graphics.Xfermode);
- method public void set(android.graphics.Shader, android.graphics.Shader, android.graphics.PorterDuff.Mode);
}
public class CornerPathEffect extends android.graphics.PathEffect {
@@ -13842,15 +13837,11 @@
ctor public LightingColorFilter(int, int);
method public int getColorAdd();
method public int getColorMultiply();
- method public void setColorAdd(int);
- method public void setColorMultiply(int);
}
public class LinearGradient extends android.graphics.Shader {
ctor public LinearGradient(float, float, float, float, int[], float[], android.graphics.Shader.TileMode);
ctor public LinearGradient(float, float, float, float, int, int, android.graphics.Shader.TileMode);
- method public void set(float, float, float, float, int[], float[], android.graphics.Shader.TileMode);
- method public void set(float, float, float, float, int, int, android.graphics.Shader.TileMode);
}
public class MaskFilter {
@@ -14360,10 +14351,6 @@
public class PorterDuffColorFilter extends android.graphics.ColorFilter {
ctor public PorterDuffColorFilter(int, android.graphics.PorterDuff.Mode);
- method public int getColor();
- method public android.graphics.PorterDuff.Mode getMode();
- method public void setColor(int);
- method public void setMode(android.graphics.PorterDuff.Mode);
}
public class PorterDuffXfermode extends android.graphics.Xfermode {
@@ -14373,8 +14360,6 @@
public class RadialGradient extends android.graphics.Shader {
ctor public RadialGradient(float, float, float, int[], float[], android.graphics.Shader.TileMode);
ctor public RadialGradient(float, float, float, int, int, android.graphics.Shader.TileMode);
- method public void set(float, float, float, int[], float[], android.graphics.Shader.TileMode);
- method public void set(float, float, float, int, int, android.graphics.Shader.TileMode);
}
public final class Rect implements android.os.Parcelable {
@@ -14559,8 +14544,6 @@
public class SweepGradient extends android.graphics.Shader {
ctor public SweepGradient(float, float, int[], float[]);
ctor public SweepGradient(float, float, int, int);
- method public void set(float, float, int[], float[]);
- method public void set(float, float, int, int);
}
public class Typeface {
@@ -24610,7 +24593,7 @@
method public android.media.MediaPlayer.DrmInfo getDrmInfo();
method public java.lang.String getDrmPropertyString(java.lang.String) throws android.media.MediaPlayer.NoDrmSchemeException;
method public int getDuration();
- method public android.media.MediaDrm.KeyRequest getKeyRequest(byte[], java.lang.String, int, java.util.Map<java.lang.String, java.lang.String>) throws android.media.MediaPlayer.NoDrmSchemeException;
+ method public android.media.MediaDrm.KeyRequest getKeyRequest(byte[], byte[], java.lang.String, int, java.util.Map<java.lang.String, java.lang.String>) throws android.media.MediaPlayer.NoDrmSchemeException;
method public android.os.PersistableBundle getMetrics();
method public android.media.PlaybackParams getPlaybackParams();
method public int getSelectedTrack(int) throws java.lang.IllegalStateException;
@@ -24624,7 +24607,7 @@
method public void pause() throws java.lang.IllegalStateException;
method public void prepare() throws java.io.IOException, java.lang.IllegalStateException;
method public void prepareAsync() throws java.lang.IllegalStateException;
- method public void prepareDrm(java.util.UUID) throws android.media.MediaPlayer.ProvisioningErrorException, android.media.ResourceBusyException, android.media.UnsupportedSchemeException;
+ method public void prepareDrm(java.util.UUID) throws android.media.MediaPlayer.ProvisioningNetworkErrorException, android.media.MediaPlayer.ProvisioningServerErrorException, android.media.ResourceBusyException, android.media.UnsupportedSchemeException;
method public byte[] provideKeyResponse(byte[], byte[]) throws android.media.DeniedByServerException, android.media.MediaPlayer.NoDrmSchemeException;
method public void release();
method public void releaseDrm() throws android.media.MediaPlayer.NoDrmSchemeException;
@@ -24651,7 +24634,7 @@
method public void setNextMediaPlayer(android.media.MediaPlayer);
method public void setOnBufferingUpdateListener(android.media.MediaPlayer.OnBufferingUpdateListener);
method public void setOnCompletionListener(android.media.MediaPlayer.OnCompletionListener);
- method public void setOnDrmConfigListener(android.media.MediaPlayer.OnDrmConfigListener);
+ method public void setOnDrmConfigHelper(android.media.MediaPlayer.OnDrmConfigHelper);
method public void setOnDrmInfoListener(android.media.MediaPlayer.OnDrmInfoListener);
method public void setOnDrmInfoListener(android.media.MediaPlayer.OnDrmInfoListener, android.os.Handler);
method public void setOnDrmPreparedListener(android.media.MediaPlayer.OnDrmPreparedListener);
@@ -24692,6 +24675,10 @@
field public static final int MEDIA_INFO_VIDEO_RENDERING_START = 3; // 0x3
field public static final int MEDIA_INFO_VIDEO_TRACK_LAGGING = 700; // 0x2bc
field public static final java.lang.String MEDIA_MIMETYPE_TEXT_SUBRIP = "application/x-subrip";
+ field public static final int PREPARE_DRM_STATUS_PREPARATION_ERROR = 3; // 0x3
+ field public static final int PREPARE_DRM_STATUS_PROVISIONING_NETWORK_ERROR = 1; // 0x1
+ field public static final int PREPARE_DRM_STATUS_PROVISIONING_SERVER_ERROR = 2; // 0x2
+ field public static final int PREPARE_DRM_STATUS_SUCCESS = 0; // 0x0
field public static final int SEEK_CLOSEST = 3; // 0x3
field public static final int SEEK_CLOSEST_SYNC = 2; // 0x2
field public static final int SEEK_NEXT_SYNC = 1; // 0x1
@@ -24701,7 +24688,6 @@
}
public static final class MediaPlayer.DrmInfo {
- method public java.lang.String[] getMimes();
method public java.util.Map<java.util.UUID, byte[]> getPssh();
method public java.util.UUID[] getSupportedSchemes();
}
@@ -24733,7 +24719,7 @@
method public abstract void onCompletion(android.media.MediaPlayer);
}
- public static abstract interface MediaPlayer.OnDrmConfigListener {
+ public static abstract interface MediaPlayer.OnDrmConfigHelper {
method public abstract void onDrmConfig(android.media.MediaPlayer);
}
@@ -24742,7 +24728,7 @@
}
public static abstract interface MediaPlayer.OnDrmPreparedListener {
- method public abstract void onDrmPrepared(android.media.MediaPlayer, boolean);
+ method public abstract void onDrmPrepared(android.media.MediaPlayer, int);
}
public static abstract interface MediaPlayer.OnErrorListener {
@@ -24773,8 +24759,12 @@
method public abstract void onVideoSizeChanged(android.media.MediaPlayer, int, int);
}
- public static final class MediaPlayer.ProvisioningErrorException extends android.media.MediaDrmException {
- ctor public MediaPlayer.ProvisioningErrorException(java.lang.String);
+ public static final class MediaPlayer.ProvisioningNetworkErrorException extends android.media.MediaDrmException {
+ ctor public MediaPlayer.ProvisioningNetworkErrorException(java.lang.String);
+ }
+
+ public static final class MediaPlayer.ProvisioningServerErrorException extends android.media.MediaDrmException {
+ ctor public MediaPlayer.ProvisioningServerErrorException(java.lang.String);
}
public static class MediaPlayer.TrackInfo implements android.os.Parcelable {
@@ -29494,9 +29484,9 @@
}
public class DiscoverySession {
- method public java.lang.String createNetworkSpecifierOpen(android.net.wifi.aware.PeerHandle);
- method public java.lang.String createNetworkSpecifierPassphrase(android.net.wifi.aware.PeerHandle, java.lang.String);
- method public java.lang.String createNetworkSpecifierPmk(android.net.wifi.aware.PeerHandle, byte[]);
+ method public android.net.NetworkSpecifier createNetworkSpecifierOpen(android.net.wifi.aware.PeerHandle);
+ method public android.net.NetworkSpecifier createNetworkSpecifierPassphrase(android.net.wifi.aware.PeerHandle, java.lang.String);
+ method public android.net.NetworkSpecifier createNetworkSpecifierPmk(android.net.wifi.aware.PeerHandle, byte[]);
method public void destroy();
method public void sendMessage(android.net.wifi.aware.PeerHandle, int, byte[]);
}
@@ -29582,9 +29572,9 @@
}
public class WifiAwareSession {
- method public java.lang.String createNetworkSpecifierOpen(int, byte[]);
- method public java.lang.String createNetworkSpecifierPassphrase(int, byte[], java.lang.String);
- method public java.lang.String createNetworkSpecifierPmk(int, byte[], byte[]);
+ method public android.net.NetworkSpecifier createNetworkSpecifierOpen(int, byte[]);
+ method public android.net.NetworkSpecifier createNetworkSpecifierPassphrase(int, byte[], java.lang.String);
+ method public android.net.NetworkSpecifier createNetworkSpecifierPmk(int, byte[], byte[]);
method public void destroy();
method public void publish(android.net.wifi.aware.PublishConfig, android.net.wifi.aware.DiscoverySessionCallback, android.os.Handler);
method public void subscribe(android.net.wifi.aware.SubscribeConfig, android.net.wifi.aware.DiscoverySessionCallback, android.os.Handler);
diff --git a/api/test-current.txt b/api/test-current.txt
index 958c620..7a73d4b 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -12641,7 +12641,6 @@
public class BitmapShader extends android.graphics.Shader {
ctor public BitmapShader(android.graphics.Bitmap, android.graphics.Shader.TileMode, android.graphics.Shader.TileMode);
- method public void set(android.graphics.Bitmap, android.graphics.Shader.TileMode, android.graphics.Shader.TileMode);
}
public class BlurMaskFilter extends android.graphics.MaskFilter {
@@ -12894,8 +12893,6 @@
ctor public ColorMatrixColorFilter(android.graphics.ColorMatrix);
ctor public ColorMatrixColorFilter(float[]);
method public void getColorMatrix(android.graphics.ColorMatrix);
- method public void setColorMatrix(android.graphics.ColorMatrix);
- method public void setColorMatrixArray(float[]);
}
public abstract class ColorSpace {
@@ -13036,8 +13033,6 @@
public class ComposeShader extends android.graphics.Shader {
ctor public ComposeShader(android.graphics.Shader, android.graphics.Shader, android.graphics.Xfermode);
ctor public ComposeShader(android.graphics.Shader, android.graphics.Shader, android.graphics.PorterDuff.Mode);
- method public void set(android.graphics.Shader, android.graphics.Shader, android.graphics.Xfermode);
- method public void set(android.graphics.Shader, android.graphics.Shader, android.graphics.PorterDuff.Mode);
}
public class CornerPathEffect extends android.graphics.PathEffect {
@@ -13110,15 +13105,11 @@
ctor public LightingColorFilter(int, int);
method public int getColorAdd();
method public int getColorMultiply();
- method public void setColorAdd(int);
- method public void setColorMultiply(int);
}
public class LinearGradient extends android.graphics.Shader {
ctor public LinearGradient(float, float, float, float, int[], float[], android.graphics.Shader.TileMode);
ctor public LinearGradient(float, float, float, float, int, int, android.graphics.Shader.TileMode);
- method public void set(float, float, float, float, int[], float[], android.graphics.Shader.TileMode);
- method public void set(float, float, float, float, int, int, android.graphics.Shader.TileMode);
}
public class MaskFilter {
@@ -13628,10 +13619,6 @@
public class PorterDuffColorFilter extends android.graphics.ColorFilter {
ctor public PorterDuffColorFilter(int, android.graphics.PorterDuff.Mode);
- method public int getColor();
- method public android.graphics.PorterDuff.Mode getMode();
- method public void setColor(int);
- method public void setMode(android.graphics.PorterDuff.Mode);
}
public class PorterDuffXfermode extends android.graphics.Xfermode {
@@ -13641,8 +13628,6 @@
public class RadialGradient extends android.graphics.Shader {
ctor public RadialGradient(float, float, float, int[], float[], android.graphics.Shader.TileMode);
ctor public RadialGradient(float, float, float, int, int, android.graphics.Shader.TileMode);
- method public void set(float, float, float, int[], float[], android.graphics.Shader.TileMode);
- method public void set(float, float, float, int, int, android.graphics.Shader.TileMode);
}
public final class Rect implements android.os.Parcelable {
@@ -13827,8 +13812,6 @@
public class SweepGradient extends android.graphics.Shader {
ctor public SweepGradient(float, float, int[], float[]);
ctor public SweepGradient(float, float, int, int);
- method public void set(float, float, int[], float[]);
- method public void set(float, float, int, int);
}
public class Typeface {
@@ -22881,7 +22864,7 @@
method public android.media.MediaPlayer.DrmInfo getDrmInfo();
method public java.lang.String getDrmPropertyString(java.lang.String) throws android.media.MediaPlayer.NoDrmSchemeException;
method public int getDuration();
- method public android.media.MediaDrm.KeyRequest getKeyRequest(byte[], java.lang.String, int, java.util.Map<java.lang.String, java.lang.String>) throws android.media.MediaPlayer.NoDrmSchemeException;
+ method public android.media.MediaDrm.KeyRequest getKeyRequest(byte[], byte[], java.lang.String, int, java.util.Map<java.lang.String, java.lang.String>) throws android.media.MediaPlayer.NoDrmSchemeException;
method public android.os.PersistableBundle getMetrics();
method public android.media.PlaybackParams getPlaybackParams();
method public int getSelectedTrack(int) throws java.lang.IllegalStateException;
@@ -22895,7 +22878,7 @@
method public void pause() throws java.lang.IllegalStateException;
method public void prepare() throws java.io.IOException, java.lang.IllegalStateException;
method public void prepareAsync() throws java.lang.IllegalStateException;
- method public void prepareDrm(java.util.UUID) throws android.media.MediaPlayer.ProvisioningErrorException, android.media.ResourceBusyException, android.media.UnsupportedSchemeException;
+ method public void prepareDrm(java.util.UUID) throws android.media.MediaPlayer.ProvisioningNetworkErrorException, android.media.MediaPlayer.ProvisioningServerErrorException, android.media.ResourceBusyException, android.media.UnsupportedSchemeException;
method public byte[] provideKeyResponse(byte[], byte[]) throws android.media.DeniedByServerException, android.media.MediaPlayer.NoDrmSchemeException;
method public void release();
method public void releaseDrm() throws android.media.MediaPlayer.NoDrmSchemeException;
@@ -22922,7 +22905,7 @@
method public void setNextMediaPlayer(android.media.MediaPlayer);
method public void setOnBufferingUpdateListener(android.media.MediaPlayer.OnBufferingUpdateListener);
method public void setOnCompletionListener(android.media.MediaPlayer.OnCompletionListener);
- method public void setOnDrmConfigListener(android.media.MediaPlayer.OnDrmConfigListener);
+ method public void setOnDrmConfigHelper(android.media.MediaPlayer.OnDrmConfigHelper);
method public void setOnDrmInfoListener(android.media.MediaPlayer.OnDrmInfoListener);
method public void setOnDrmInfoListener(android.media.MediaPlayer.OnDrmInfoListener, android.os.Handler);
method public void setOnDrmPreparedListener(android.media.MediaPlayer.OnDrmPreparedListener);
@@ -22963,6 +22946,10 @@
field public static final int MEDIA_INFO_VIDEO_RENDERING_START = 3; // 0x3
field public static final int MEDIA_INFO_VIDEO_TRACK_LAGGING = 700; // 0x2bc
field public static final java.lang.String MEDIA_MIMETYPE_TEXT_SUBRIP = "application/x-subrip";
+ field public static final int PREPARE_DRM_STATUS_PREPARATION_ERROR = 3; // 0x3
+ field public static final int PREPARE_DRM_STATUS_PROVISIONING_NETWORK_ERROR = 1; // 0x1
+ field public static final int PREPARE_DRM_STATUS_PROVISIONING_SERVER_ERROR = 2; // 0x2
+ field public static final int PREPARE_DRM_STATUS_SUCCESS = 0; // 0x0
field public static final int SEEK_CLOSEST = 3; // 0x3
field public static final int SEEK_CLOSEST_SYNC = 2; // 0x2
field public static final int SEEK_NEXT_SYNC = 1; // 0x1
@@ -22972,7 +22959,6 @@
}
public static final class MediaPlayer.DrmInfo {
- method public java.lang.String[] getMimes();
method public java.util.Map<java.util.UUID, byte[]> getPssh();
method public java.util.UUID[] getSupportedSchemes();
}
@@ -23004,7 +22990,7 @@
method public abstract void onCompletion(android.media.MediaPlayer);
}
- public static abstract interface MediaPlayer.OnDrmConfigListener {
+ public static abstract interface MediaPlayer.OnDrmConfigHelper {
method public abstract void onDrmConfig(android.media.MediaPlayer);
}
@@ -23013,7 +22999,7 @@
}
public static abstract interface MediaPlayer.OnDrmPreparedListener {
- method public abstract void onDrmPrepared(android.media.MediaPlayer, boolean);
+ method public abstract void onDrmPrepared(android.media.MediaPlayer, int);
}
public static abstract interface MediaPlayer.OnErrorListener {
@@ -23044,8 +23030,12 @@
method public abstract void onVideoSizeChanged(android.media.MediaPlayer, int, int);
}
- public static final class MediaPlayer.ProvisioningErrorException extends android.media.MediaDrmException {
- ctor public MediaPlayer.ProvisioningErrorException(java.lang.String);
+ public static final class MediaPlayer.ProvisioningNetworkErrorException extends android.media.MediaDrmException {
+ ctor public MediaPlayer.ProvisioningNetworkErrorException(java.lang.String);
+ }
+
+ public static final class MediaPlayer.ProvisioningServerErrorException extends android.media.MediaDrmException {
+ ctor public MediaPlayer.ProvisioningServerErrorException(java.lang.String);
}
public static class MediaPlayer.TrackInfo implements android.os.Parcelable {
@@ -26858,8 +26848,8 @@
}
public class DiscoverySession {
- method public java.lang.String createNetworkSpecifierOpen(android.net.wifi.aware.PeerHandle);
- method public java.lang.String createNetworkSpecifierPassphrase(android.net.wifi.aware.PeerHandle, java.lang.String);
+ method public android.net.NetworkSpecifier createNetworkSpecifierOpen(android.net.wifi.aware.PeerHandle);
+ method public android.net.NetworkSpecifier createNetworkSpecifierPassphrase(android.net.wifi.aware.PeerHandle, java.lang.String);
method public void destroy();
method public void sendMessage(android.net.wifi.aware.PeerHandle, int, byte[]);
}
@@ -26945,8 +26935,8 @@
}
public class WifiAwareSession {
- method public java.lang.String createNetworkSpecifierOpen(int, byte[]);
- method public java.lang.String createNetworkSpecifierPassphrase(int, byte[], java.lang.String);
+ method public android.net.NetworkSpecifier createNetworkSpecifierOpen(int, byte[]);
+ method public android.net.NetworkSpecifier createNetworkSpecifierPassphrase(int, byte[], java.lang.String);
method public void destroy();
method public void publish(android.net.wifi.aware.PublishConfig, android.net.wifi.aware.DiscoverySessionCallback, android.os.Handler);
method public void subscribe(android.net.wifi.aware.SubscribeConfig, android.net.wifi.aware.DiscoverySessionCallback, android.os.Handler);
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 09906be..178b967 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -54,6 +54,7 @@
import android.os.UserManager;
import android.os.storage.StorageManager;
import android.os.storage.VolumeInfo;
+import android.provider.Settings;
import android.util.AndroidException;
import android.util.Log;
@@ -3983,6 +3984,8 @@
* <p>If no packages have been changed, returns <code>null</code>.
* <p>The sequence number starts at <code>0</code> and is
* reset every boot.
+ * @param sequenceNumber The first sequence number for which to retrieve package changes.
+ * @see Settings.Global#BOOT_COUNT
*/
public abstract @Nullable ChangedPackages getChangedPackages(
@IntRange(from=0) int sequenceNumber);
@@ -6256,18 +6259,18 @@
/**
* Checks whether the calling package is allowed to request package installs through package
- * installer. Apps are encouraged to call this api before launching the package installer via
+ * installer. Apps are encouraged to call this API before launching the package installer via
* intent {@link android.content.Intent#ACTION_INSTALL_PACKAGE}. Starting from Android O, the
* user can explicitly choose what external sources they trust to install apps on the device.
- * If this api returns false, the install request will be blocked by the package installer and
+ * If this API returns false, the install request will be blocked by the package installer and
* a dialog will be shown to the user with an option to launch settings to change their
* preference. An application must target Android O or higher and declare permission
- * {@link android.Manifest.permission#REQUEST_INSTALL_PACKAGES} in order to use this api.
+ * {@link android.Manifest.permission#REQUEST_INSTALL_PACKAGES} in order to use this API.
*
* @return true if the calling package is trusted by the user to request install packages on
* the device, false otherwise.
- * @see {@link android.content.Intent#ACTION_INSTALL_PACKAGE}
- * @see {@link android.provider.Settings#ACTION_MANAGE_UNKNOWN_APP_SOURCES}
+ * @see android.content.Intent#ACTION_INSTALL_PACKAGE
+ * @see android.provider.Settings#ACTION_MANAGE_UNKNOWN_APP_SOURCES
*/
public abstract boolean canRequestPackageInstalls();
diff --git a/core/java/android/preference/Preference.java b/core/java/android/preference/Preference.java
index d3adce7..7496cb2 100644
--- a/core/java/android/preference/Preference.java
+++ b/core/java/android/preference/Preference.java
@@ -135,6 +135,7 @@
private boolean mDependencyMet = true;
private boolean mParentDependencyMet = true;
private boolean mRecycleEnabled = true;
+ private boolean mHasSingleLineTitleAttr;
private boolean mSingleLineTitle = true;
private boolean mIconSpaceReserved;
@@ -303,6 +304,7 @@
case com.android.internal.R.styleable.Preference_singleLineTitle:
mSingleLineTitle = a.getBoolean(attr, mSingleLineTitle);
+ mHasSingleLineTitleAttr = true;
break;
case com.android.internal.R.styleable.Preference_iconSpaceReserved:
@@ -609,7 +611,9 @@
if (!TextUtils.isEmpty(title)) {
titleView.setText(title);
titleView.setVisibility(View.VISIBLE);
- titleView.setSingleLine(mSingleLineTitle);
+ if (mHasSingleLineTitleAttr) {
+ titleView.setSingleLine(mSingleLineTitle);
+ }
} else {
titleView.setVisibility(View.GONE);
}
diff --git a/core/java/com/android/internal/app/AccessibilityButtonChooserActivity.java b/core/java/com/android/internal/app/AccessibilityButtonChooserActivity.java
index 032c775..b9ed963 100644
--- a/core/java/com/android/internal/app/AccessibilityButtonChooserActivity.java
+++ b/core/java/com/android/internal/app/AccessibilityButtonChooserActivity.java
@@ -34,6 +34,7 @@
import android.widget.TextView;
import com.android.internal.R;
+import com.android.internal.widget.ResolverDrawerLayout;
import java.util.ArrayList;
import java.util.Collections;
@@ -56,6 +57,11 @@
super.onCreate(savedInstanceState);
setContentView(R.layout.accessibility_button_chooser);
+ final ResolverDrawerLayout rdl = findViewById(R.id.contentPanel);
+ if (rdl != null) {
+ rdl.setOnDismissedListener(this::finish);
+ }
+
String component = Settings.Secure.getString(getContentResolver(),
Settings.Secure.ACCESSIBILITY_BUTTON_TARGET_COMPONENT);
if (TextUtils.isEmpty(component)) {
diff --git a/core/res/res/layout/accessibility_button_chooser.xml b/core/res/res/layout/accessibility_button_chooser.xml
index 0ef785f..480defb 100644
--- a/core/res/res/layout/accessibility_button_chooser.xml
+++ b/core/res/res/layout/accessibility_button_chooser.xml
@@ -19,7 +19,7 @@
<com.android.internal.widget.ResolverDrawerLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
- android:layout_height="match_parent"
+ android:layout_height="wrap_content"
android:maxWidth="@dimen/resolver_max_width"
android:maxCollapsedHeight="256dp"
android:maxCollapsedHeightSmall="56dp"
@@ -27,11 +27,14 @@
<LinearLayout
android:layout_width="match_parent"
- android:layout_height="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_alwaysShow="true"
android:orientation="vertical"
android:background="?attr/colorBackground"
android:paddingTop="8dp"
- android:paddingBottom="8dp">
+ android:paddingBottom="8dp"
+ android:paddingStart="?attr/dialogPreferredPadding"
+ android:paddingEnd="?attr/dialogPreferredPadding">
<TextView
android:layout_width="match_parent"
@@ -41,8 +44,6 @@
android:text="@string/accessibility_button_prompt_text"
android:gravity="start|center_vertical"
android:layout_alignParentStart="true"
- android:paddingStart="?attr/dialogPreferredPadding"
- android:paddingEnd="?attr/dialogPreferredPadding"
android:paddingTop="8dp"
android:paddingBottom="8dp"/>
@@ -55,20 +56,15 @@
android:verticalSpacing="10dp"
android:horizontalSpacing="10dp"
android:stretchMode="columnWidth"
- android:paddingStart="?attr/dialogPreferredPadding"
- android:paddingEnd="?attr/dialogPreferredPadding"
android:gravity="center"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/accessibility_button_prompt"
- android:layout_alwaysShow="true"
android:textAppearance="?attr/textAppearanceMedium"
android:text="@string/accessibility_button_instructional_text"
android:gravity="start|center_vertical"
- android:paddingStart="?attr/dialogPreferredPadding"
- android:paddingEnd="?attr/dialogPreferredPadding"
android:paddingTop="8dp"
android:paddingBottom="8dp"
android:visibility="gone"/>
diff --git a/core/tests/coretests/src/android/view/textclassifier/TextClassificationManagerTest.java b/core/tests/coretests/src/android/view/textclassifier/TextClassificationManagerTest.java
new file mode 100644
index 0000000..0acff9b
--- /dev/null
+++ b/core/tests/coretests/src/android/view/textclassifier/TextClassificationManagerTest.java
@@ -0,0 +1,212 @@
+/*
+ * Copyright (C) 2017 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.view.textclassifier;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThat;
+import static org.mockito.Mockito.mock;
+
+import android.os.LocaleList;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+import android.view.textclassifier.TextClassificationManager;
+import android.view.textclassifier.TextClassificationResult;
+import android.view.textclassifier.TextClassifier;
+import android.view.textclassifier.TextLanguage;
+import android.view.textclassifier.TextSelection;
+
+import org.hamcrest.BaseMatcher;
+import org.hamcrest.Description;
+import org.hamcrest.Matcher;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.List;
+import java.util.Locale;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class TextClassificationManagerTest {
+
+ private static final LocaleList LOCALES = LocaleList.forLanguageTags("en");
+
+ private TextClassificationManager mTcm;
+ private TextClassifier mClassifier;
+
+ @Before
+ public void setup() {
+ mTcm = InstrumentationRegistry.getTargetContext()
+ .getSystemService(TextClassificationManager.class);
+ mTcm.setTextClassifier(null);
+ mClassifier = mTcm.getTextClassifier();
+ }
+
+ @Test
+ public void testSmartSelection() {
+ if (isTextClassifierDisabled()) return;
+
+ String text = "Contact me at droid@android.com";
+ String selected = "droid";
+ String suggested = "droid@android.com";
+ int startIndex = text.indexOf(selected);
+ int endIndex = startIndex + selected.length();
+ int smartStartIndex = text.indexOf(suggested);
+ int smartEndIndex = smartStartIndex + suggested.length();
+
+ assertThat(mClassifier.suggestSelection(text, startIndex, endIndex, LOCALES),
+ isTextSelection(smartStartIndex, smartEndIndex, TextClassifier.TYPE_EMAIL));
+ }
+
+ @Test
+ public void testSmartSelection_url() {
+ if (isTextClassifierDisabled()) return;
+
+ String text = "Visit http://www.android.com for more information";
+ String selected = "http";
+ String suggested = "http://www.android.com";
+ int startIndex = text.indexOf(selected);
+ int endIndex = startIndex + selected.length();
+ int smartStartIndex = text.indexOf(suggested);
+ int smartEndIndex = smartStartIndex + suggested.length();
+
+ assertThat(mClassifier.suggestSelection(text, startIndex, endIndex, LOCALES),
+ isTextSelection(smartStartIndex, smartEndIndex, TextClassifier.TYPE_URL));
+ }
+
+ @Test
+ public void testTextClassificationResult() {
+ if (isTextClassifierDisabled()) return;
+
+ String text = "Contact me at droid@android.com";
+ String classifiedText = "droid@android.com";
+ int startIndex = text.indexOf(classifiedText);
+ int endIndex = startIndex + classifiedText.length();
+ assertThat(mClassifier.getTextClassificationResult(text, startIndex, endIndex, LOCALES),
+ isTextClassificationResult(classifiedText, TextClassifier.TYPE_EMAIL));
+ }
+
+ @Test
+ public void testTextClassificationResult_url() {
+ if (isTextClassifierDisabled()) return;
+
+ String text = "Visit http://www.android.com for more information";
+ String classifiedText = "http://www.android.com";
+ int startIndex = text.indexOf(classifiedText);
+ int endIndex = startIndex + classifiedText.length();
+ assertThat(mClassifier.getTextClassificationResult(text, startIndex, endIndex, LOCALES),
+ isTextClassificationResult(classifiedText, TextClassifier.TYPE_URL));
+ }
+
+ @Test
+ public void testLanguageDetection() {
+ if (isTextClassifierDisabled()) return;
+
+ String text = "This is a piece of English text";
+ assertThat(mTcm.detectLanguages(text), isDetectedLanguage("en"));
+
+ text = "Das ist ein deutscher Text";
+ assertThat(mTcm.detectLanguages(text), isDetectedLanguage("de"));
+
+ text = "これは日本語のテキストです";
+ assertThat(mTcm.detectLanguages(text), isDetectedLanguage("ja"));
+ }
+
+ @Test
+ public void testSetTextClassifier() {
+ TextClassifier classifier = mock(TextClassifier.class);
+ mTcm.setTextClassifier(classifier);
+ assertEquals(classifier, mTcm.getTextClassifier());
+ }
+
+ private boolean isTextClassifierDisabled() {
+ return mClassifier == TextClassifier.NO_OP;
+ }
+
+ private static Matcher<TextSelection> isTextSelection(
+ final int startIndex, final int endIndex, final String type) {
+ return new BaseMatcher<TextSelection>() {
+ @Override
+ public boolean matches(Object o) {
+ if (o instanceof TextSelection) {
+ TextSelection selection = (TextSelection) o;
+ return startIndex == selection.getSelectionStartIndex()
+ && endIndex == selection.getSelectionEndIndex()
+ && selection.getEntityCount() > 0
+ && type.equals(selection.getEntity(0));
+ }
+ return false;
+ }
+
+ @Override
+ public void describeTo(Description description) {
+ description.appendValue(
+ String.format("%d, %d, %s", startIndex, endIndex, type));
+ }
+ };
+ }
+
+ private static Matcher<TextClassificationResult> isTextClassificationResult(
+ final String text, final String type) {
+ return new BaseMatcher<TextClassificationResult>() {
+ @Override
+ public boolean matches(Object o) {
+ if (o instanceof TextClassificationResult) {
+ TextClassificationResult result = (TextClassificationResult) o;
+ return text.equals(result.getText())
+ && result.getEntityCount() > 0
+ && type.equals(result.getEntity(0));
+ // TODO: Include other properties.
+ }
+ return false;
+ }
+
+ @Override
+ public void describeTo(Description description) {
+ description.appendText("text=").appendValue(text)
+ .appendText(", type=").appendValue(type);
+ }
+ };
+ }
+
+ private static Matcher<List<TextLanguage>> isDetectedLanguage(final String language) {
+ return new BaseMatcher<List<TextLanguage>>() {
+ @Override
+ public boolean matches(Object o) {
+ if (o instanceof List) {
+ List languages = (List) o;
+ if (!languages.isEmpty()) {
+ Object o1 = languages.get(0);
+ if (o1 instanceof TextLanguage) {
+ TextLanguage lang = (TextLanguage) o1;
+ return lang.getLanguageCount() > 0
+ && new Locale(language).getLanguage()
+ .equals(lang.getLanguage(0).getLanguage());
+ }
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public void describeTo(Description description) {
+ description.appendValue(String.format("%s", language));
+ }
+ };
+ }
+}
diff --git a/graphics/java/android/graphics/BitmapShader.java b/graphics/java/android/graphics/BitmapShader.java
index 7e6756e..5577f53 100644
--- a/graphics/java/android/graphics/BitmapShader.java
+++ b/graphics/java/android/graphics/BitmapShader.java
@@ -41,35 +41,16 @@
* @param tileY The tiling mode for y to draw the bitmap in.
*/
public BitmapShader(@NonNull Bitmap bitmap, @NonNull TileMode tileX, @NonNull TileMode tileY) {
- set(bitmap, tileX, tileY);
+ this(bitmap, tileX.nativeInt, tileY.nativeInt);
}
private BitmapShader(Bitmap bitmap, int tileX, int tileY) {
- setInternal(bitmap, tileX, tileY);
- }
-
- /**
- * Reinitialize the BitmapShader's Bitmap and tile modes.
- *
- * @param bitmap The bitmap to use inside the shader
- * @param tileX The tiling mode for x to draw the bitmap in.
- * @param tileY The tiling mode for y to draw the bitmap in.
- */
- public void set(@NonNull Bitmap bitmap, @NonNull TileMode tileX, @NonNull TileMode tileY) {
- if (tileX == null || tileY == null) {
- throw new IllegalArgumentException();
- }
- setInternal(bitmap, tileX.nativeInt, tileY.nativeInt);
- }
-
- private void setInternal(Bitmap bitmap, int tileX, int tileY) {
if (bitmap == null) {
throw new IllegalArgumentException("Bitmap must be non-null");
}
if (bitmap == mBitmap && tileX == mTileX && tileY == mTileY) {
return;
}
- discardNativeInstance();
mBitmap = bitmap;
mTileX = tileX;
mTileY = tileY;
diff --git a/graphics/java/android/graphics/ColorMatrixColorFilter.java b/graphics/java/android/graphics/ColorMatrixColorFilter.java
index 61f6cc5..9201a2e 100644
--- a/graphics/java/android/graphics/ColorMatrixColorFilter.java
+++ b/graphics/java/android/graphics/ColorMatrixColorFilter.java
@@ -73,6 +73,8 @@
* @see #getColorMatrix(ColorMatrix)
* @see #setColorMatrixArray(float[])
* @see ColorMatrix#reset()
+ *
+ * @hide
*/
public void setColorMatrix(@Nullable ColorMatrix matrix) {
discardNativeInstance();
@@ -99,6 +101,8 @@
*
* @throws ArrayIndexOutOfBoundsException if the specified array's
* length is < 20
+ *
+ * @hide
*/
public void setColorMatrixArray(@Nullable float[] array) {
// called '...Array' so that passing null isn't ambiguous
diff --git a/graphics/java/android/graphics/ComposeShader.java b/graphics/java/android/graphics/ComposeShader.java
index 8438bf2..e107ea7 100644
--- a/graphics/java/android/graphics/ComposeShader.java
+++ b/graphics/java/android/graphics/ComposeShader.java
@@ -59,43 +59,10 @@
}
private ComposeShader(Shader shaderA, Shader shaderB, int nativeMode) {
- setInternal(shaderA, shaderB, nativeMode);
- }
-
- /**
- * Reinitialize the ComposeShader's component Shaders and blend mode.
- *
- * @param shaderA The colors from this shader are seen as the "dst" by the mode
- * @param shaderB The colors from this shader are seen as the "src" by the mode
- * @param mode The PorterDuff mode that combines the colors from the two shaders.
- */
- public void set(@NonNull Shader shaderA, @NonNull Shader shaderB, @NonNull Xfermode mode) {
- setInternal(shaderA, shaderB, mode.porterDuffMode);
- }
-
- /**
- * Reinitialize the ComposeShader's component Shaders and blend mode.
- *
- * @param shaderA The colors from this shader are seen as the "dst" by the mode
- * @param shaderB The colors from this shader are seen as the "src" by the mode
- * @param mode The PorterDuff mode that combines the colors from the two shaders.
- */
- public void set(@NonNull Shader shaderA, @NonNull Shader shaderB,
- @NonNull PorterDuff.Mode mode) {
- setInternal(shaderA, shaderB, mode.nativeInt);
- }
-
- private void setInternal(Shader shaderA, Shader shaderB, int nativeMode) {
if (shaderA == null || shaderB == null) {
throw new IllegalArgumentException("Shader parameters must not be null");
}
- if (shaderA == mShaderA && shaderB == mShaderB && mPorterDuffMode == nativeMode) {
- // no work to do...
- return;
- }
-
- discardNativeInstance();
mShaderA = shaderA;
mShaderB = shaderB;
mPorterDuffMode = nativeMode;
@@ -109,16 +76,6 @@
mShaderA.getNativeInstance(), mShaderB.getNativeInstance(), mPorterDuffMode);
}
- @Override
- void verifyNativeInstance() {
- if (mShaderA.getNativeInstance() != mNativeInstanceShaderA
- || mShaderB.getNativeInstance() != mNativeInstanceShaderB) {
- // Child shader native instance has been updated,
- // so our cached native instance is no longer valid - discard it
- discardNativeInstance();
- }
- }
-
/**
* @hide
*/
diff --git a/graphics/java/android/graphics/LightingColorFilter.java b/graphics/java/android/graphics/LightingColorFilter.java
index b0c145b..1578ffb 100644
--- a/graphics/java/android/graphics/LightingColorFilter.java
+++ b/graphics/java/android/graphics/LightingColorFilter.java
@@ -57,8 +57,6 @@
/**
* Returns the RGB color used to multiply the source color when the
* color filter is applied.
- *
- * @see #setColorMultiply(int)
*/
@ColorInt
public int getColorMultiply() {
@@ -71,6 +69,8 @@
* The alpha channel of this color is ignored.
*
* @see #getColorMultiply()
+ *
+ * @hide
*/
public void setColorMultiply(@ColorInt int mul) {
if (mMul != mul) {
@@ -82,8 +82,6 @@
/**
* Returns the RGB color that will be added to the source color
* when the color filter is applied.
- *
- * @see #setColorAdd(int)
*/
@ColorInt
public int getColorAdd() {
@@ -96,6 +94,8 @@
* The alpha channel of this color is ignored.
*
* @see #getColorAdd()
+ *
+ * @hide
*/
public void setColorAdd(@ColorInt int add) {
if (mAdd != add) {
diff --git a/graphics/java/android/graphics/LinearGradient.java b/graphics/java/android/graphics/LinearGradient.java
index 0e4cd0a..7139efe 100644
--- a/graphics/java/android/graphics/LinearGradient.java
+++ b/graphics/java/android/graphics/LinearGradient.java
@@ -57,7 +57,20 @@
*/
public LinearGradient(float x0, float y0, float x1, float y1, @NonNull @ColorInt int colors[],
@Nullable float positions[], @NonNull TileMode tile) {
- set(x0, y0, x1, y1, colors, positions, tile);
+ if (colors.length < 2) {
+ throw new IllegalArgumentException("needs >= 2 number of colors");
+ }
+ if (positions != null && colors.length != positions.length) {
+ throw new IllegalArgumentException("color and position arrays must be of equal length");
+ }
+ mType = TYPE_COLORS_AND_POSITIONS;
+ mX0 = x0;
+ mY0 = y0;
+ mX1 = x1;
+ mY1 = y1;
+ mColors = colors.clone();
+ mPositions = positions != null ? positions.clone() : null;
+ mTileMode = tile;
}
/**
@@ -74,56 +87,6 @@
public LinearGradient(float x0, float y0, float x1, float y1,
@ColorInt int color0, @ColorInt int color1,
@NonNull TileMode tile) {
- set(x0, y0, x1, y1, color0, color1, tile);
- }
-
- /**
- * Reinitialize the shader.
- *
- * @param x0 The x-coordinate for the start of the gradient line
- * @param y0 The y-coordinate for the start of the gradient line
- * @param x1 The x-coordinate for the end of the gradient line
- * @param y1 The y-coordinate for the end of the gradient line
- * @param colors The colors to be distributed along the gradient line
- * @param positions May be null. The relative positions [0..1] of
- * each corresponding color in the colors array. If this is null,
- * the the colors are distributed evenly along the gradient line.
- * @param tile The Shader tiling mode
- */
- public void set(float x0, float y0, float x1, float y1, @NonNull @ColorInt int colors[],
- @Nullable float positions[], @NonNull TileMode tile) {
- if (colors.length < 2) {
- throw new IllegalArgumentException("needs >= 2 number of colors");
- }
- if (positions != null && colors.length != positions.length) {
- throw new IllegalArgumentException("color and position arrays must be of equal length");
- }
- discardNativeInstance();
- mType = TYPE_COLORS_AND_POSITIONS;
- mX0 = x0;
- mY0 = y0;
- mX1 = x1;
- mY1 = y1;
- mColors = colors.clone();
- mPositions = positions != null ? positions.clone() : null;
- mTileMode = tile;
- }
-
- /**
- * Reinitialize the shader.
- *
- * @param x0 The x-coordinate for the start of the gradient line
- * @param y0 The y-coordinate for the start of the gradient line
- * @param x1 The x-coordinate for the end of the gradient line
- * @param y1 The y-coordinate for the end of the gradient line
- * @param color0 The color at the start of the gradient line.
- * @param color1 The color at the end of the gradient line.
- * @param tile The Shader tiling mode
- */
- public void set(float x0, float y0, float x1, float y1,
- @ColorInt int color0, @ColorInt int color1,
- @NonNull TileMode tile) {
- discardNativeInstance();
mType = TYPE_COLOR_START_AND_COLOR_END;
mX0 = x0;
mY0 = y0;
diff --git a/graphics/java/android/graphics/PorterDuffColorFilter.java b/graphics/java/android/graphics/PorterDuffColorFilter.java
index ccc6ead..01d5825 100644
--- a/graphics/java/android/graphics/PorterDuffColorFilter.java
+++ b/graphics/java/android/graphics/PorterDuffColorFilter.java
@@ -49,6 +49,8 @@
*
* @see Color
* @see #setColor(int)
+ *
+ * @hide
*/
@ColorInt
public int getColor() {
@@ -64,6 +66,8 @@
* @see Color
* @see #getColor()
* @see #getMode()
+ *
+ * @hide
*/
public void setColor(@ColorInt int color) {
if (mColor != color) {
@@ -78,6 +82,8 @@
*
* @see PorterDuff
* @see #setMode(android.graphics.PorterDuff.Mode)
+ *
+ * @hide
*/
public PorterDuff.Mode getMode() {
return mMode;
@@ -90,6 +96,8 @@
* @see PorterDuff
* @see #getMode()
* @see #getColor()
+ *
+ * @hide
*/
public void setMode(@NonNull PorterDuff.Mode mode) {
if (mode == null) {
diff --git a/graphics/java/android/graphics/RadialGradient.java b/graphics/java/android/graphics/RadialGradient.java
index ae8f7da..f4b1191 100644
--- a/graphics/java/android/graphics/RadialGradient.java
+++ b/graphics/java/android/graphics/RadialGradient.java
@@ -57,7 +57,22 @@
public RadialGradient(float centerX, float centerY, float radius,
@NonNull @ColorInt int colors[], @Nullable float stops[],
@NonNull TileMode tileMode) {
- set(centerX, centerY, radius, colors, stops, tileMode);
+ if (radius <= 0) {
+ throw new IllegalArgumentException("radius must be > 0");
+ }
+ if (colors.length < 2) {
+ throw new IllegalArgumentException("needs >= 2 number of colors");
+ }
+ if (stops != null && colors.length != stops.length) {
+ throw new IllegalArgumentException("color and position arrays must be of equal length");
+ }
+ mType = TYPE_COLORS_AND_POSITIONS;
+ mX = centerX;
+ mY = centerY;
+ mRadius = radius;
+ mColors = colors.clone();
+ mPositions = stops != null ? stops.clone() : null;
+ mTileMode = tileMode;
}
/**
@@ -72,59 +87,9 @@
*/
public RadialGradient(float centerX, float centerY, float radius,
@ColorInt int centerColor, @ColorInt int edgeColor, @NonNull TileMode tileMode) {
- set(centerX, centerY, radius, centerColor, edgeColor, tileMode);
- }
-
- /**
- * Reinitialize the shader.
- *
- * @param centerX The x-coordinate of the center of the radius
- * @param centerY The y-coordinate of the center of the radius
- * @param radius Must be positive. The radius of the circle for this gradient.
- * @param colors The colors to be distributed between the center and edge of the circle
- * @param stops May be <code>null</code>. Valid values are between <code>0.0f</code> and
- * <code>1.0f</code>. The relative position of each corresponding color in
- * the colors array. If <code>null</code>, colors are distributed evenly
- * between the center and edge of the circle.
- * @param tileMode The Shader tiling mode
- */
- public void set(float centerX, float centerY, float radius,
- @NonNull @ColorInt int colors[], @Nullable float stops[], @NonNull TileMode tileMode) {
if (radius <= 0) {
throw new IllegalArgumentException("radius must be > 0");
}
- if (colors.length < 2) {
- throw new IllegalArgumentException("needs >= 2 number of colors");
- }
- if (stops != null && colors.length != stops.length) {
- throw new IllegalArgumentException("color and position arrays must be of equal length");
- }
- discardNativeInstance();
- mType = TYPE_COLORS_AND_POSITIONS;
- mX = centerX;
- mY = centerY;
- mRadius = radius;
- mColors = colors.clone();
- mPositions = stops != null ? stops.clone() : null;
- mTileMode = tileMode;
- }
-
- /**
- * Reinitialize the shader.
- *
- * @param centerX The x-coordinate of the center of the radius
- * @param centerY The y-coordinate of the center of the radius
- * @param radius Must be positive. The radius of the circle for this gradient
- * @param centerColor The color at the center of the circle.
- * @param edgeColor The color at the edge of the circle.
- * @param tileMode The Shader tiling mode
- */
- public void set(float centerX, float centerY, float radius,
- @ColorInt int centerColor, @ColorInt int edgeColor, @NonNull TileMode tileMode) {
- if (radius <= 0) {
- throw new IllegalArgumentException("radius must be > 0");
- }
- discardNativeInstance();
mType = TYPE_COLOR_CENTER_AND_COLOR_EDGE;
mX = centerX;
mY = centerY;
diff --git a/graphics/java/android/graphics/Shader.java b/graphics/java/android/graphics/Shader.java
index 8410ab2..c744757 100644
--- a/graphics/java/android/graphics/Shader.java
+++ b/graphics/java/android/graphics/Shader.java
@@ -105,20 +105,13 @@
return 0;
}
- void discardNativeInstance() {
+ private void discardNativeInstance() {
if (mNativeInstance != 0) {
nativeSafeUnref(mNativeInstance);
mNativeInstance = 0;
}
}
- /**
- * Callback for subclasses to call {@link #discardNativeInstance()} if the most recently
- * constructed native instance is no longer valid.
- */
- void verifyNativeInstance() {
- }
-
@Override
protected void finalize() throws Throwable {
try {
@@ -155,9 +148,6 @@
throw new IllegalStateException("attempting to use a finalized Shader");
}
- // verify mNativeInstance is valid
- verifyNativeInstance();
-
if (mNativeInstance == 0) {
mNativeInstance = createNativeInstance(mLocalMatrix == null
? 0 : mLocalMatrix.native_instance);
diff --git a/graphics/java/android/graphics/SweepGradient.java b/graphics/java/android/graphics/SweepGradient.java
index 0a1aef6..b6b80b4 100644
--- a/graphics/java/android/graphics/SweepGradient.java
+++ b/graphics/java/android/graphics/SweepGradient.java
@@ -54,7 +54,18 @@
*/
public SweepGradient(float cx, float cy,
@NonNull @ColorInt int colors[], @Nullable float positions[]) {
- set(cx, cy, colors, positions);
+ if (colors.length < 2) {
+ throw new IllegalArgumentException("needs >= 2 number of colors");
+ }
+ if (positions != null && colors.length != positions.length) {
+ throw new IllegalArgumentException(
+ "color and position arrays must be of equal length");
+ }
+ mType = TYPE_COLORS_AND_POSITIONS;
+ mCx = cx;
+ mCy = cy;
+ mColors = colors.clone();
+ mPositions = positions != null ? positions.clone() : null;
}
/**
@@ -66,50 +77,6 @@
* @param color1 The color to use at the end of the sweep
*/
public SweepGradient(float cx, float cy, @ColorInt int color0, @ColorInt int color1) {
- set(cx, cy, color0, color1);
- }
-
- /**
- * Reinitialize the shader.
- *
- * @param cx The x-coordinate of the center
- * @param cy The y-coordinate of the center
- * @param colors The colors to be distributed between around the center.
- * There must be at least 2 colors in the array.
- * @param positions May be NULL. The relative position of
- * each corresponding color in the colors array, beginning
- * with 0 and ending with 1.0. If the values are not
- * monotonic, the drawing may produce unexpected results.
- * If positions is NULL, then the colors are automatically
- * spaced evenly.
- */
- public void set(float cx, float cy,
- @NonNull @ColorInt int colors[], @Nullable float positions[]) {
- if (colors.length < 2) {
- throw new IllegalArgumentException("needs >= 2 number of colors");
- }
- if (positions != null && colors.length != positions.length) {
- throw new IllegalArgumentException(
- "color and position arrays must be of equal length");
- }
- discardNativeInstance();
- mType = TYPE_COLORS_AND_POSITIONS;
- mCx = cx;
- mCy = cy;
- mColors = colors.clone();
- mPositions = positions != null ? positions.clone() : null;
- }
-
- /**
- * Reinitialize the shader.
- *
- * @param cx The x-coordinate of the center
- * @param cy The y-coordinate of the center
- * @param color0 The color to use at the start of the sweep
- * @param color1 The color to use at the end of the sweep
- */
- public void set(float cx, float cy, @ColorInt int color0, @ColorInt int color1) {
- discardNativeInstance();
mType = TYPE_COLOR_START_AND_COLOR_END;
mCx = cx;
mCy = cy;
diff --git a/media/java/android/media/MediaPlayer.java b/media/java/android/media/MediaPlayer.java
index 9386246..d5efc97 100644
--- a/media/java/android/media/MediaPlayer.java
+++ b/media/java/android/media/MediaPlayer.java
@@ -1007,13 +1007,14 @@
* @param context the Context to use when resolving the Uri
* @param uri the Content URI of the data you want to play
* @param headers the headers to be sent together with the request for the data
- * Note that the cross domain redirection is allowed by default, but that can be
- * changed with key/value pairs through the headers parameter with
- * "android-allow-cross-domain-redirect" as the key and "0" or "1" as the value
- * to disallow or allow cross domain redirection.
* The headers must not include cookies. Instead, use the cookies param.
* @param cookies the cookies to be sent together with the request
* @throws IllegalStateException if it is called in an invalid state
+ *
+ * <p><strong>Note</strong> that the cross domain redirection is allowed by default,
+ * but that can be changed with key/value pairs through the headers parameter with
+ * "android-allow-cross-domain-redirect" as the key and "0" or "1" as the value to
+ * disallow or allow cross domain redirection.
*/
public void setDataSource(@NonNull Context context, @NonNull Uri uri,
@Nullable Map<String, String> headers, @Nullable List<HttpCookie> cookies)
@@ -1056,11 +1057,12 @@
* @param context the Context to use when resolving the Uri
* @param uri the Content URI of the data you want to play
* @param headers the headers to be sent together with the request for the data
- * Note that the cross domain redirection is allowed by default, but that can be
- * changed with key/value pairs through the headers parameter with
- * "android-allow-cross-domain-redirect" as the key and "0" or "1" as the value
- * to disallow or allow cross domain redirection.
* @throws IllegalStateException if it is called in an invalid state
+ *
+ * <p><strong>Note</strong> that the cross domain redirection is allowed by default,
+ * but that can be changed with key/value pairs through the headers parameter with
+ * "android-allow-cross-domain-redirect" as the key and "0" or "1" as the value to
+ * disallow or allow cross domain redirection.
*/
public void setDataSource(@NonNull Context context, @NonNull Uri uri,
@Nullable Map<String, String> headers)
@@ -1981,7 +1983,7 @@
mOnSubtitleDataListener = null;
// Modular DRM clean up
- mOnDrmConfigListener = null;
+ mOnDrmConfigHelper = null;
mOnDrmInfoHandlerDelegate = null;
mOnDrmPreparedHandlerDelegate = null;
resetDrmState();
@@ -3905,11 +3907,11 @@
* 'securityLevel', which has to be set after DRM scheme creation but
* before the DRM session is opened.
*
- * The only allowed DRM calls in this listener are getDrmPropertyString
- * and setDrmPropertyString.
+ * The only allowed DRM calls in this listener are {@code getDrmPropertyString}
+ * and {@code setDrmPropertyString}.
*
*/
- public interface OnDrmConfigListener
+ public interface OnDrmConfigHelper
{
/**
* Called to give the app the opportunity to configure DRM before the session is created
@@ -3922,19 +3924,19 @@
/**
* Register a callback to be invoked for configuration of the DRM object before
* the session is created.
- * The callback will be invoked synchronously half-way into the execution
+ * The callback will be invoked synchronously during the execution
* of {@link #prepareDrm(UUID uuid)}.
*
* @param listener the callback that will be run
*/
- public void setOnDrmConfigListener(OnDrmConfigListener listener)
+ public void setOnDrmConfigHelper(OnDrmConfigHelper listener)
{
synchronized (mDrmLock) {
- mOnDrmConfigListener = listener;
+ mOnDrmConfigHelper = listener;
} // synchronized
}
- private OnDrmConfigListener mOnDrmConfigListener;
+ private OnDrmConfigHelper mOnDrmConfigHelper;
/**
* Interface definition of a callback to be invoked when the
@@ -3946,7 +3948,7 @@
* Called to indicate DRM info is available
*
* @param mp the {@code MediaPlayer} associated with this callback
- * @param drmInfo DRM info of the source including PSSH, mimes, and subset
+ * @param drmInfo DRM info of the source including PSSH, and subset
* of crypto schemes supported by this device
*/
public void onDrmInfo(MediaPlayer mp, DrmInfo drmInfo);
@@ -3982,6 +3984,41 @@
private OnDrmInfoHandlerDelegate mOnDrmInfoHandlerDelegate;
+
+ /**
+ * The status codes for {@link OnDrmPreparedListener#onDrmPrepared} listener.
+ * <p>
+ *
+ * DRM preparation has succeeded.
+ */
+ public static final int PREPARE_DRM_STATUS_SUCCESS = 0;
+
+ /**
+ * The device required DRM provisioning but couldn't reach the provisioning server.
+ */
+ public static final int PREPARE_DRM_STATUS_PROVISIONING_NETWORK_ERROR = 1;
+
+ /**
+ * The device required DRM provisioning but the provisioning server denied the request.
+ */
+ public static final int PREPARE_DRM_STATUS_PROVISIONING_SERVER_ERROR = 2;
+
+ /**
+ * The DRM preparation has failed .
+ */
+ public static final int PREPARE_DRM_STATUS_PREPARATION_ERROR = 3;
+
+
+ /** @hide */
+ @IntDef({
+ PREPARE_DRM_STATUS_SUCCESS,
+ PREPARE_DRM_STATUS_PROVISIONING_NETWORK_ERROR,
+ PREPARE_DRM_STATUS_PROVISIONING_SERVER_ERROR,
+ PREPARE_DRM_STATUS_PREPARATION_ERROR,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface PrepareDrmStatusCode {}
+
/**
* Interface definition of a callback to notify the app when the
* DRM is ready for key request/response
@@ -3992,9 +4029,13 @@
* Called to notify the app that prepareDrm is finished and ready for key request/response
*
* @param mp the {@code MediaPlayer} associated with this callback
- * @param success the result of DRM preparation
+ * @param status the result of DRM preparation which can be
+ * {@link #PREPARE_DRM_STATUS_SUCCESS},
+ * {@link #PREPARE_DRM_STATUS_PROVISIONING_NETWORK_ERROR},
+ * {@link #PREPARE_DRM_STATUS_PROVISIONING_SERVER_ERROR}, or
+ * {@link #PREPARE_DRM_STATUS_PREPARATION_ERROR}.
*/
- public void onDrmPrepared(MediaPlayer mp, boolean success);
+ public void onDrmPrepared(MediaPlayer mp, @PrepareDrmStatusCode int status);
}
/**
@@ -4038,30 +4079,28 @@
mOnDrmInfoListener = listener;
// find the looper for our new event handler
- Looper looper = null;
if (handler != null) {
- looper = handler.getLooper();
- }
-
- // construct the event handler with this looper
- if (looper != null) {
- // implement the event handler delegate
- mHandler = new Handler(looper) {
- public void handleMessage(Message msg) {
- DrmInfo drmInfo = (DrmInfo)msg.obj;
- mOnDrmInfoListener.onDrmInfo(mMediaPlayer, drmInfo);
- }
- };
+ mHandler = handler;
+ } else {
+ // handler == null
+ // Will let OnDrmInfoListener be called in mEventHandler similar to other
+ // legacy notifications. This is because MEDIA_DRM_INFO's notification has to be
+ // sent before MEDIA_PREPARED's (i.e., in the same order they are issued by
+ // mediaserver). As a result, the callback has to be called directly by
+ // EventHandler.handleMessage similar to onPrepared.
}
}
void notifyClient(DrmInfo drmInfo) {
- if ( mHandler != null ) {
- Message msg = new Message(); // no message type needed
- msg.obj = drmInfo;
- mHandler.sendMessage(msg);
+ if (mHandler != null) {
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ mOnDrmInfoListener.onDrmInfo(mMediaPlayer, drmInfo);
+ }
+ });
}
- else { // no handler: direct call
+ else { // no handler: direct call by mEventHandler
mOnDrmInfoListener.onDrmInfo(mMediaPlayer, drmInfo);
}
}
@@ -4078,31 +4117,26 @@
mOnDrmPreparedListener = listener;
// find the looper for our new event handler
- Looper looper = null;
if (handler != null) {
- looper = handler.getLooper();
- }
-
- // construct the event handler with this looper
- if (looper != null) {
- // implement the event handler delegate
- mHandler = new Handler(looper) {
- public void handleMessage(Message msg) {
- boolean success = (msg.arg1 == 0) ? false : true;
- mOnDrmPreparedListener.onDrmPrepared(mMediaPlayer, success);
- }
- };
+ mHandler = handler;
+ } else if (mEventHandler != null) {
+ // Otherwise, use mEventHandler
+ mHandler = mEventHandler;
+ } else {
+ Log.e(TAG, "OnDrmPreparedHandlerDelegate: Unexpected null mEventHandler");
}
}
- void notifyClient(boolean success) {
- if ( mHandler != null ) {
- Message msg = new Message(); // no message type needed
- msg.arg1 = success ? 1 : 0;
- mHandler.sendMessage(msg);
- }
- else { // no handler: direct call
- mOnDrmPreparedListener.onDrmPrepared(mMediaPlayer, success);
+ void notifyClient(int status) {
+ if (mHandler != null) {
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ mOnDrmPreparedListener.onDrmPrepared(mMediaPlayer, status);
+ }
+ });
+ } else {
+ Log.e(TAG, "OnDrmPreparedHandlerDelegate:notifyClient: Unexpected null mHandler");
}
}
}
@@ -4137,7 +4171,7 @@
/**
* Prepares the DRM for the current source
* <p>
- * If {@code OnDrmConfigListener} is registered, it will be called half-way into
+ * If {@code OnDrmConfigHelper} is registered, it will be called during
* preparation to allow configuration of the DRM properties before opening the
* DRM session. Note that the callback is called synchronously in the thread that called
* {@code prepareDrm}. It should be used only for a series of {@code getDrmPropertyString}
@@ -4148,9 +4182,9 @@
* complete depending on the network connectivity.
* If {@code OnDrmPreparedListener} is registered, prepareDrm() runs in non-blocking
* mode by launching the provisioning in the background and returning. The listener
- * will be called when provisioning and preperation has finished. If a
+ * will be called when provisioning and preparation has finished. If a
* {@code OnDrmPreparedListener} is not registered, prepareDrm() waits till provisioning
- * and preperation has finished, i.e., runs in blocking mode.
+ * and preparation has finished, i.e., runs in blocking mode.
* <p>
* If {@code OnDrmPreparedListener} is registered, it is called to indicate the DRM
* session being ready. The application should not make any assumption about its call
@@ -4158,18 +4192,23 @@
* execute the listener (unless the listener is registered with a handler thread).
* <p>
*
- * @param uuid The UUID of the crypto scheme.
+ * @param uuid The UUID of the crypto scheme. If not known beforehand, it can be retrieved
+ * from the source through {@code getDrmInfo} or registering a {@code onDrmInfoListener}.
*
- * @throws IllegalStateException if called before prepare(), or there exists a Drm already
- * @throws UnsupportedSchemeException if the crypto scheme is not supported
- * @throws ResourceBusyException if required DRM resources are in use
- * @throws ProvisioningErrorException if provisioning is required but an attempt failed
+ * @throws IllegalStateException if called before prepare(), or the DRM was
+ * prepared already
+ * @throws UnsupportedSchemeException if the crypto scheme is not supported
+ * @throws ResourceBusyException if required DRM resources are in use
+ * @throws ProvisioningNetworkErrorException if provisioning is required but failed due to a
+ * network error
+ * @throws ProvisioningServerErrorException if provisioning is required but failed due to
+ * the request denied by the provisioning server
*/
public void prepareDrm(@NonNull UUID uuid)
- throws UnsupportedSchemeException,
- ResourceBusyException, ProvisioningErrorException
+ throws UnsupportedSchemeException, ResourceBusyException,
+ ProvisioningNetworkErrorException, ProvisioningServerErrorException
{
- Log.v(TAG, "prepareDrm: uuid: " + uuid + " mOnDrmConfigListener: " + mOnDrmConfigListener);
+ Log.v(TAG, "prepareDrm: uuid: " + uuid + " mOnDrmConfigHelper: " + mOnDrmConfigHelper);
boolean allDoneWithoutProvisioning = false;
// get a snapshot as we'll use them outside the lock
@@ -4177,7 +4216,7 @@
synchronized (mDrmLock) {
- // only allowing if tied to a protected source; might releax for releasing offline keys
+ // only allowing if tied to a protected source; might relax for releasing offline keys
if (mDrmInfo == null) {
final String msg = "prepareDrm(): Wrong usage: The player must be prepared and " +
"DRM info be retrieved before this call.";
@@ -4226,8 +4265,8 @@
// call the callback outside the lock
- if (mOnDrmConfigListener != null) {
- mOnDrmConfigListener.onDrmConfig(this);
+ if (mOnDrmConfigHelper != null) {
+ mOnDrmConfigHelper.onDrmConfig(this);
}
synchronized (mDrmLock) {
@@ -4251,15 +4290,33 @@
Log.w(TAG, "prepareDrm: NotProvisionedException");
// handle provisioning internally; it'll reset mPrepareDrmInProgress
- boolean result = HandleProvisioninig(uuid);
+ int result = HandleProvisioninig(uuid);
// if blocking mode, we're already done;
// if non-blocking mode, we attempted to launch background provisioning
- if (result == false) {
- final String msg = "prepareDrm: Provisioning was required but failed.";
- Log.e(TAG, msg);
+ if (result != PREPARE_DRM_STATUS_SUCCESS) {
earlyExit = true;
- throw new ProvisioningErrorException(msg);
+ String msg;
+
+ switch (result) {
+ case PREPARE_DRM_STATUS_PROVISIONING_NETWORK_ERROR:
+ msg = "prepareDrm: Provisioning was required but failed " +
+ "due to a network error.";
+ Log.e(TAG, msg);
+ throw new ProvisioningNetworkErrorException(msg);
+
+ case PREPARE_DRM_STATUS_PROVISIONING_SERVER_ERROR:
+ msg = "prepareDrm: Provisioning was required but the request " +
+ "was denied by the server.";
+ Log.e(TAG, msg);
+ throw new ProvisioningServerErrorException(msg);
+
+ case PREPARE_DRM_STATUS_PREPARATION_ERROR:
+ default: // default for safeguard
+ msg = "prepareDrm: Post-provisioning preparation failed.";
+ Log.e(TAG, msg);
+ throw new IllegalStateException(msg);
+ }
}
// nothing else to do;
// if blocking or non-blocking, HandleProvisioninig does the re-attempt & cleanup
@@ -4281,7 +4338,7 @@
// if finished successfully without provisioning, call the callback outside the lock
if (allDoneWithoutProvisioning) {
if (onDrmPreparedHandlerDelegate != null)
- onDrmPreparedHandlerDelegate.notifyClient(true /*success*/);
+ onDrmPreparedHandlerDelegate.notifyClient(PREPARE_DRM_STATUS_SUCCESS);
}
}
@@ -4291,6 +4348,10 @@
/**
* Releases the DRM session
+ * <p>
+ * The player has to have an active DRM session and be in stopped, or prepared
+ * state before this call is made.
+ * A {@code reset()} call will release the DRM session implicitly.
*
* @throws NoDrmSchemeException if there is no active DRM session to release
*/
@@ -4307,7 +4368,7 @@
try {
// we don't have the player's state in this layer. The below call raises
- // exception if we're in a non-stopped/idle state.
+ // exception if we're in a non-stopped/prepared state.
// for cleaning native/mediaserver crypto object
_releaseDrm();
@@ -4316,9 +4377,11 @@
cleanDrmObj();
mActiveDrmScheme = false;
- } catch (Exception e) {
+ } catch (IllegalStateException e) {
Log.w(TAG, "releaseDrm: Exception ", e);
- throw e;
+ throw new IllegalStateException("releaseDrm: The player is not in a valid state.");
+ } catch (Exception e) {
+ Log.e(TAG, "releaseDrm: Exception ", e);
}
} // synchronized
}
@@ -4337,21 +4400,23 @@
* it should deliver to the response to the DRM engine plugin using the method
* {@link #provideKeyResponse}.
*
- * @param scope may be a container-specific initialization data or a keySetId,
- * depending on the specified keyType.
- * When the keyType is KEY_TYPE_STREAMING or KEY_TYPE_OFFLINE, scope should be set to
- * the container-specific initialization data. Its meaning is interpreted based on the
- * mime type provided in the mimeType parameter. It could contain, for example,
- * the content ID, key ID or other data obtained from the content metadata that is
- * required in generating the key request.
- * When the keyType is KEY_TYPE_RELEASE, scope should be set to the keySetId of
- * the keys being released.
+ * @param keySetId is the key-set identifier of the offline keys being released when keyType is
+ * {@link MediaDrm#KEY_TYPE_RELEASE}. It should be set to null for other key requests, when
+ * keyType is {@link MediaDrm#KEY_TYPE_STREAMING} or {@link MediaDrm#KEY_TYPE_OFFLINE}.
+ *
+ * @param initData is the container-specific initialization data when the keyType is
+ * {@link MediaDrm#KEY_TYPE_STREAMING} or {@link MediaDrm#KEY_TYPE_OFFLINE}. Its meaning is
+ * interpreted based on the mime type provided in the mimeType parameter. It could
+ * contain, for example, the content ID, key ID or other data obtained from the content
+ * metadata that is required in generating the key request.
+ * When the keyType is {@link MediaDrm#KEY_TYPE_RELEASE}, it should be set to null.
*
* @param mimeType identifies the mime type of the content
*
- * @param keyType specifes the type of the request. The request may be to acquire
- * keys for streaming or offline content, or to release previously acquired
- * keys, which are identified by a keySetId.
+ * @param keyType specifies the type of the request. The request may be to acquire
+ * keys for streaming, {@link MediaDrm#KEY_TYPE_STREAMING}, or for offline content
+ * {@link MediaDrm#KEY_TYPE_OFFLINE}, or to release previously acquired
+ * keys ({@link MediaDrm#KEY_TYPE_RELEASE}), which are identified by a keySetId.
*
* @param optionalParameters are included in the key request message to
* allow a client application to provide additional message parameters to the server.
@@ -4360,12 +4425,13 @@
* @throws NoDrmSchemeException if there is no active DRM session
*/
@NonNull
- public MediaDrm.KeyRequest getKeyRequest(@NonNull byte[] scope, @Nullable String mimeType,
- @MediaDrm.KeyType int keyType, @Nullable Map<String, String> optionalParameters)
+ public MediaDrm.KeyRequest getKeyRequest(@Nullable byte[] keySetId, @Nullable byte[] initData,
+ @Nullable String mimeType, @MediaDrm.KeyType int keyType,
+ @Nullable Map<String, String> optionalParameters)
throws NoDrmSchemeException
{
Log.v(TAG, "getKeyRequest: " +
- " scope: " + scope + " mimeType: " + mimeType +
+ " keySetId: " + keySetId + " initData:" + initData + " mimeType: " + mimeType +
" keyType: " + keyType + " optionalParameters: " + optionalParameters);
synchronized (mDrmLock) {
@@ -4375,20 +4441,16 @@
}
try {
- byte[] scopeOut = (keyType != MediaDrm.KEY_TYPE_RELEASE) ?
- mDrmSessionId : // sessionId for KEY_TYPE_STREAMING/OFFLINE
- scope; // keySetId for KEY_TYPE_RELEASE
-
- byte[] initData = (keyType != MediaDrm.KEY_TYPE_RELEASE) ?
- scope : // initData for KEY_TYPE_STREAMING/OFFLINE
- null; // not used for KEY_TYPE_RELEASE
+ byte[] scope = (keyType != MediaDrm.KEY_TYPE_RELEASE) ?
+ mDrmSessionId : // sessionId for KEY_TYPE_STREAMING/OFFLINE
+ keySetId; // keySetId for KEY_TYPE_RELEASE
HashMap<String, String> hmapOptionalParameters =
(optionalParameters != null) ?
new HashMap<String, String>(optionalParameters) :
null;
- MediaDrm.KeyRequest request = mDrmObj.getKeyRequest(scopeOut, initData, mimeType,
+ MediaDrm.KeyRequest request = mDrmObj.getKeyRequest(scope, initData, mimeType,
keyType, hmapOptionalParameters);
Log.v(TAG, "getKeyRequest: --> request: " + request);
@@ -4499,8 +4561,8 @@
* @param propertyName the property name
*
* Standard fields names are:
- * {link #PROPERTY_VENDOR}, {link #PROPERTY_VERSION},
- * {link #PROPERTY_DESCRIPTION}, {link #PROPERTY_ALGORITHMS}
+ * {@link MediaDrm#PROPERTY_VENDOR}, {@link MediaDrm#PROPERTY_VERSION},
+ * {@link MediaDrm#PROPERTY_DESCRIPTION}, {@link MediaDrm#PROPERTY_ALGORITHMS}
*/
@NonNull
public String getDrmPropertyString(@NonNull @MediaDrm.StringProperty String propertyName)
@@ -4537,8 +4599,8 @@
* @param value the property value
*
* Standard fields names are:
- * {link #PROPERTY_VENDOR}, {link #PROPERTY_VERSION},
- * {link #PROPERTY_DESCRIPTION}, {link #PROPERTY_ALGORITHMS}
+ * {@link MediaDrm#PROPERTY_VENDOR}, {@link MediaDrm#PROPERTY_VERSION},
+ * {@link MediaDrm#PROPERTY_DESCRIPTION}, {@link MediaDrm#PROPERTY_ALGORITHMS}
*/
public void setDrmPropertyString(@NonNull @MediaDrm.StringProperty String propertyName,
@NonNull String value)
@@ -4565,8 +4627,6 @@
public static final class DrmInfo {
private Map<UUID, byte[]> mapPssh;
private UUID[] supportedSchemes;
- // TODO: Won't need this in final release. Only keeping it for the existing test app.
- private String[] mimes;
public Map<UUID, byte[]> getPssh() {
return mapPssh;
@@ -4574,15 +4634,10 @@
public UUID[] getSupportedSchemes() {
return supportedSchemes;
}
- // TODO: Won't need this in final release. Only keeping it for the existing test app.
- public String[] getMimes() {
- return mimes;
- }
- private DrmInfo(Map<UUID, byte[]> Pssh, UUID[] SupportedSchemes, String[] Mimes) {
+ private DrmInfo(Map<UUID, byte[]> Pssh, UUID[] SupportedSchemes) {
mapPssh = Pssh;
supportedSchemes = SupportedSchemes;
- mimes = Mimes;
}
private DrmInfo(Parcel parcel) {
@@ -4608,18 +4663,12 @@
supportedSchemes[i]);
}
- // TODO: Won't need this in final release. Only keeping it for the test app.
- mimes = parcel.readStringArray();
- int mimeCount = mimes.length;
- Log.v(TAG, "DrmInfo() mime: " + Arrays.toString(mimes));
-
Log.v(TAG, "DrmInfo() Parcel psshsize: " + psshsize +
- " supportedDRMsCount: " + supportedDRMsCount +
- " mimeCount: " + mimeCount);
+ " supportedDRMsCount: " + supportedDRMsCount);
}
private DrmInfo makeCopy() {
- return new DrmInfo(this.mapPssh, this.supportedSchemes, this.mimes);
+ return new DrmInfo(this.mapPssh, this.supportedSchemes);
}
private String arrToHex(byte[] bytes) {
@@ -4714,11 +4763,22 @@
/**
* Thrown when the device requires DRM provisioning but the provisioning attempt has
- * failed (for example: network timeout, provisioning server error).
+ * failed due to a network error (Internet reachability, timeout, etc.).
* Extends MediaDrm.MediaDrmException
*/
- public static final class ProvisioningErrorException extends MediaDrmException {
- public ProvisioningErrorException(String detailMessage) {
+ public static final class ProvisioningNetworkErrorException extends MediaDrmException {
+ public ProvisioningNetworkErrorException(String detailMessage) {
+ super(detailMessage);
+ }
+ }
+
+ /**
+ * Thrown when the device requires DRM provisioning but the provisioning attempt has
+ * failed due to the provisioning server denying the request.
+ * Extends MediaDrm.MediaDrmException
+ */
+ public static final class ProvisioningServerErrorException extends MediaDrmException {
+ public ProvisioningServerErrorException(String detailMessage) {
super(detailMessage);
}
}
@@ -4770,14 +4830,13 @@
private UUID uuid;
private String urlStr;
- private byte[] response;
private Object drmLock;
private OnDrmPreparedHandlerDelegate onDrmPreparedHandlerDelegate;
private MediaPlayer mediaPlayer;
- private boolean succeeded;
+ private int status;
private boolean finished;
- public boolean succeeded() {
- return succeeded;
+ public int status() {
+ return status;
}
public ProvisioningThread initialize(MediaDrm.ProvisionRequest request,
@@ -4790,12 +4849,15 @@
urlStr = request.getDefaultUrl() + "&signedRequest=" + new String(request.getData());
this.uuid = uuid;
+ status = PREPARE_DRM_STATUS_PREPARATION_ERROR;
+
Log.v(TAG, "HandleProvisioninig: Thread is initialised url: " + urlStr);
return this;
}
public void run() {
+ byte[] response = null;
boolean provisioningSucceeded = false;
try {
URL url = new URL(urlStr);
@@ -4813,11 +4875,13 @@
Log.v(TAG, "HandleProvisioninig: Thread run: response " +
response.length + " " + response);
} catch (Exception e) {
+ status = PREPARE_DRM_STATUS_PROVISIONING_NETWORK_ERROR;
Log.w(TAG, "HandleProvisioninig: Thread run: connect " + e + " url: " + url);
} finally {
connection.disconnect();
}
} catch (Exception e) {
+ status = PREPARE_DRM_STATUS_PROVISIONING_NETWORK_ERROR;
Log.w(TAG, "HandleProvisioninig: Thread run: openConnection " + e);
}
@@ -4828,12 +4892,15 @@
"provideProvisionResponse SUCCEEDED!");
provisioningSucceeded = true;
- } catch (Exception e) {
+ } catch (Exception e) {
+ status = PREPARE_DRM_STATUS_PROVISIONING_SERVER_ERROR;
Log.w(TAG, "HandleProvisioninig: Thread run: " +
"provideProvisionResponse " + e);
}
}
+ boolean succeeded = false;
+
// non-blocking mode needs the lock
if (onDrmPreparedHandlerDelegate != null) {
@@ -4841,6 +4908,9 @@
// continuing with prepareDrm
if (provisioningSucceeded) {
succeeded = mediaPlayer.resumePrepareDrm(uuid);
+ status = (succeeded) ?
+ PREPARE_DRM_STATUS_SUCCESS :
+ PREPARE_DRM_STATUS_PREPARATION_ERROR;
}
mediaPlayer.mDrmProvisioningInProgress = false;
mediaPlayer.mPrepareDrmInProgress = false;
@@ -4850,12 +4920,15 @@
} // synchronized
// calling the callback outside the lock
- onDrmPreparedHandlerDelegate.notifyClient(succeeded);
+ onDrmPreparedHandlerDelegate.notifyClient(status);
} else { // blocking mode already has the lock
// continuing with prepareDrm
if (provisioningSucceeded) {
succeeded = mediaPlayer.resumePrepareDrm(uuid);
+ status = (succeeded) ?
+ PREPARE_DRM_STATUS_SUCCESS :
+ PREPARE_DRM_STATUS_PREPARATION_ERROR;
}
mediaPlayer.mDrmProvisioningInProgress = false;
mediaPlayer.mPrepareDrmInProgress = false;
@@ -4869,19 +4942,19 @@
} // ProvisioningThread
- private boolean HandleProvisioninig(UUID uuid)
+ private int HandleProvisioninig(UUID uuid)
{
// the lock is already held by the caller
if (mDrmProvisioningInProgress) {
Log.e(TAG, "HandleProvisioninig: Unexpected mDrmProvisioningInProgress");
- return false;
+ return PREPARE_DRM_STATUS_PREPARATION_ERROR;
}
MediaDrm.ProvisionRequest provReq = mDrmObj.getProvisionRequest();
if (provReq == null) {
Log.e(TAG, "HandleProvisioninig: getProvisionRequest returned null.");
- return false;
+ return PREPARE_DRM_STATUS_PREPARATION_ERROR;
}
Log.v(TAG, "HandleProvisioninig provReq " +
@@ -4893,11 +4966,11 @@
mDrmProvisioningThread = new ProvisioningThread().initialize(provReq, uuid, this);
mDrmProvisioningThread.start();
- boolean result = false;
+ int result;
- // non-blocking
+ // non-blocking: this is not the final result
if (mOnDrmPreparedHandlerDelegate != null) {
- result = true;
+ result = PREPARE_DRM_STATUS_SUCCESS;
} else {
// if blocking mode, wait till provisioning is done
try {
@@ -4905,7 +4978,7 @@
} catch (Exception e) {
Log.w(TAG, "HandleProvisioninig: Thread.join Exception " + e);
}
- result = mDrmProvisioningThread.succeeded();
+ result = mDrmProvisioningThread.status();
// no longer need the thread
mDrmProvisioningThread = null;
}
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipDismissViewController.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipDismissViewController.java
index 86bb0de..4b3cdfb 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipDismissViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipDismissViewController.java
@@ -39,7 +39,8 @@
// This delay controls how long to wait before we show the target when the user first moves
// the PIP, to prevent the target from animating if the user just wants to fling the PIP
private static final int SHOW_TARGET_DELAY = 100;
- private static final int SHOW_TARGET_DURATION = 200;
+ private static final int SHOW_TARGET_DURATION = 350;
+ private static final int HIDE_TARGET_DURATION = 225;
private Context mContext;
private WindowManager mWindowManager;
@@ -96,7 +97,7 @@
public void showDismissTarget() {
mDismissView.animate()
.alpha(1f)
- .setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN)
+ .setInterpolator(Interpolators.LINEAR)
.setStartDelay(SHOW_TARGET_DELAY)
.setDuration(SHOW_TARGET_DURATION)
.start();
@@ -109,9 +110,9 @@
if (mDismissView != null) {
mDismissView.animate()
.alpha(0f)
- .setInterpolator(Interpolators.FAST_OUT_LINEAR_IN)
+ .setInterpolator(Interpolators.LINEAR)
.setStartDelay(0)
- .setDuration(SHOW_TARGET_DURATION)
+ .setDuration(HIDE_TARGET_DURATION)
.withEndAction(new Runnable() {
@Override
public void run() {
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java
index fbf7ff2..3223f9f 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java
@@ -63,7 +63,7 @@
private static final int METRIC_VALUE_DISMISSED_BY_TAP = 0;
private static final int METRIC_VALUE_DISMISSED_BY_DRAG = 1;
- private static final int SHOW_DISMISS_AFFORDANCE_DELAY = 200;
+ private static final int SHOW_DISMISS_AFFORDANCE_DELAY = 225;
// Allow dragging the PIP to a location to close it
private static final boolean ENABLE_DISMISS_DRAG_TO_EDGE = true;
diff --git a/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java
index 6b3203c..c92c52f 100644
--- a/services/autofill/java/com/android/server/autofill/Session.java
+++ b/services/autofill/java/com/android/server/autofill/Session.java
@@ -442,7 +442,7 @@
*/
public boolean showSaveLocked() {
if (mStructure == null) {
- Slog.wtf(TAG, "showSaveLocked(): no mStructure");
+ Slog.d(TAG, "showSaveLocked(): no mStructure");
return true;
}
if (mResponses == null) {
diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java
index 17c7dde..7cdddc0 100644
--- a/services/core/java/com/android/server/am/ActivityRecord.java
+++ b/services/core/java/com/android/server/am/ActivityRecord.java
@@ -1178,6 +1178,10 @@
* the activity is not currently visible and {@param noThrow} is not set.
*/
boolean checkEnterPictureInPictureState(String caller, boolean noThrow, boolean beforeStopping) {
+ if (!supportsPictureInPicture()) {
+ return false;
+ }
+
// Check app-ops and see if PiP is supported for this package
if (!checkEnterPictureInPictureAppOpsState()) {
return false;
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index 825e8ac..85c5c64 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -65,6 +65,8 @@
import static com.android.server.am.ActivityRecord.APPLICATION_ACTIVITY_TYPE;
import static com.android.server.am.ActivityRecord.ASSISTANT_ACTIVITY_TYPE;
import static com.android.server.am.ActivityRecord.HOME_ACTIVITY_TYPE;
+import static com.android.server.am.ActivityStack.ActivityState.STOPPED;
+import static com.android.server.am.ActivityStack.ActivityState.STOPPING;
import static com.android.server.am.ActivityStackSupervisor.FindTaskResult;
import static com.android.server.am.ActivityStackSupervisor.ON_TOP;
import static com.android.server.am.ActivityStackSupervisor.PAUSE_IMMEDIATELY;
@@ -1179,7 +1181,7 @@
final ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities;
for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
final ActivityRecord r = activities.get(activityNdx);
- if (r.state == ActivityState.STOPPING || r.state == ActivityState.STOPPED
+ if (r.state == STOPPING || r.state == STOPPED
|| r.state == ActivityState.PAUSED || r.state == ActivityState.PAUSING) {
r.setSleeping(true);
}
@@ -1362,7 +1364,7 @@
if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Complete pause: " + prev);
if (prev != null) {
- final boolean wasStopping = prev.state == ActivityState.STOPPING;
+ final boolean wasStopping = prev.state == STOPPING;
prev.state = ActivityState.PAUSED;
if (prev.finishing) {
if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Executing finish of activity: " + prev);
@@ -1383,7 +1385,7 @@
// We are also stopping, the stop request must have gone soon after the pause.
// We can't clobber it, because the stop confirmation will not be handled.
// We don't need to schedule another stop, we only need to let it happen.
- prev.state = ActivityState.STOPPING;
+ prev.state = STOPPING;
} else if ((!prev.visible && !hasVisibleBehindActivity())
|| mService.isSleepingOrShuttingDownLocked()) {
// If we were visible then resumeTopActivities will release resources before
@@ -2002,10 +2004,17 @@
// keeping the screen frozen.
if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "Making invisible: " + r + " " + r.state);
try {
+ final boolean canEnterPictureInPicture = r.checkEnterPictureInPictureState(
+ "makeInvisible", true /* noThrow */, true /* beforeStopping */);
+ // We don't want to call setVisible(false) to avoid notifying the client of this
+ // intermittent invisible state if it can enter Pip and isn't stopped or stopping.
+ if (!canEnterPictureInPicture || r.state == STOPPING || r.state == STOPPED) {
+ r.setVisible(false);
+ }
+
switch (r.state) {
case STOPPING:
case STOPPED:
- r.setVisible(false);
if (r.app != null && r.app.thread != null) {
if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY,
"Scheduling invisibility: " + r);
@@ -2024,25 +2033,16 @@
// This case created for transitioning activities from
// translucent to opaque {@link Activity#convertToOpaque}.
if (visibleBehind == r) {
- r.setVisible(false);
releaseBackgroundResources(r);
} else {
// If this activity is in a state where it can currently enter
// picture-in-picture, then don't immediately schedule the idle now in case
// the activity tries to enterPictureInPictureMode() later. Otherwise,
// we will try and stop the activity next time idle is processed.
- final boolean canEnterPictureInPicture = r.checkEnterPictureInPictureState(
- "makeInvisible", true /* noThrow */, true /* beforeStopping */);
if (canEnterPictureInPicture) {
- // We set r.visible=false so that Stop will later
- // call setVisible for us. In this case
- // we don't want to call setVisible(false) to avoid
- // notifying the client of this intermittent invisible
- // state.
+ // We set r.visible=false so that Stop will later call setVisible for us
r.visible = false;
- } else {
- r.setVisible(false);
}
addToStopping(r, true /* scheduleIdle */,
canEnterPictureInPicture /* idleDelayed */);
@@ -2318,9 +2318,20 @@
mStackSupervisor.setLaunchSource(next.info.applicationInfo.uid);
+ final boolean prevCanPip = prev != null && prev.checkEnterPictureInPictureState(
+ "resumeTopActivity", true /* noThrow */, userLeaving /* beforeStopping */);
// If the flag RESUME_WHILE_PAUSING is set, then continue to schedule the previous activity
- // to be paused, while at the same time resuming the new resume activity
+ // to be paused, while at the same time resuming the new resume activity only if the
+ // previous activity can't go into Pip since we want to give Pip activities a chance to
+ // enter Pip before resuming the next activity.
final boolean resumeWhilePausing = (next.info.flags & FLAG_RESUME_WHILE_PAUSING) != 0;
+ // TODO: This would be go to have however, the various call points that pass in
+ // prev need to be corrected first. In some cases the prev is equal to the next e.g. launch
+ // an app from home. And, is come other cases it is null e.g. press home button after
+ // launching an app. The doc on the method says prev. is null expect for the case we are
+ // coming from pause. We need to see if that is a valid thing and also if all the code in
+ // this method using prev. are setup to function like that.
+ //&& !prevCanPip;
boolean pausing = mStackSupervisor.pauseBackStacks(userLeaving, next, false);
if (mResumedActivity != null) {
if (DEBUG_STATES) Slog.d(TAG_STATES,
@@ -3360,11 +3371,11 @@
r.stopped = false;
if (DEBUG_STATES) Slog.v(TAG_STATES,
"Moving to STOPPING: " + r + " (stop requested)");
- r.state = ActivityState.STOPPING;
+ r.state = STOPPING;
if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY,
"Stopping visible=" + r.visible + " for " + r);
if (!r.visible) {
- r.setVisibility(false);
+ r.setVisible(false);
}
EventLogTags.writeAmStopActivity(
r.userId, System.identityHashCode(r), r.shortComponentName);
@@ -3382,7 +3393,7 @@
// Just in case, assume it to be stopped.
r.stopped = true;
if (DEBUG_STATES) Slog.v(TAG_STATES, "Stop failed; moving to STOPPED: " + r);
- r.state = ActivityState.STOPPED;
+ r.state = STOPPED;
if (r.deferRelaunchUntilPaused) {
destroyActivityLocked(r, true, "stop-except");
}
@@ -3687,7 +3698,7 @@
}
if (DEBUG_STATES) Slog.v(TAG_STATES,
"Moving to STOPPING: "+ r + " (finish requested)");
- r.state = ActivityState.STOPPING;
+ r.state = STOPPING;
if (oomAdj) {
mService.updateOomAdjLocked();
}
@@ -3712,8 +3723,8 @@
|| (prevState == ActivityState.PAUSED
&& (mode == FINISH_AFTER_PAUSE || mStackId == PINNED_STACK_ID))
|| finishingActivityInNonFocusedStack
- || prevState == ActivityState.STOPPING
- || prevState == ActivityState.STOPPED
+ || prevState == STOPPING
+ || prevState == STOPPED
|| prevState == ActivityState.INITIALIZING) {
r.makeFinishingLocked();
boolean activityRemoved = destroyActivityLocked(r, true, "finish-imm");
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index 43ae4b2..152d5f4 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -2878,6 +2878,10 @@
mWindowManager.deferSurfaceLayout();
+ // This will clear the pinned stack by moving an existing task to the full screen stack,
+ // ensuring only one task is present.
+ moveTasksToFullscreenStackLocked(PINNED_STACK_ID, !ON_TOP);
+
// Need to make sure the pinned stack exist so we can resize it below...
final PinnedActivityStack stack = getStack(PINNED_STACK_ID, CREATE_IF_NEEDED, ON_TOP);
diff --git a/services/core/java/com/android/server/am/TaskRecord.java b/services/core/java/com/android/server/am/TaskRecord.java
index f8a4d4b..d42b6a7 100644
--- a/services/core/java/com/android/server/am/TaskRecord.java
+++ b/services/core/java/com/android/server/am/TaskRecord.java
@@ -48,6 +48,7 @@
import android.util.DisplayMetrics;
import android.util.Slog;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.app.IVoiceInteractor;
import com.android.internal.util.XmlUtils;
@@ -445,10 +446,23 @@
final Rect bounds = updateOverrideConfigurationFromLaunchBounds();
final Configuration overrideConfig = getOverrideConfiguration();
- mWindowContainerController = new TaskWindowContainerController(taskId, this,
+ setWindowContainerController(new TaskWindowContainerController(taskId, this,
getStack().getWindowContainerController(), userId, bounds, overrideConfig,
mResizeMode, mSupportsPictureInPicture, isHomeTask(), onTop, showForAllUsers,
- lastTaskDescription);
+ lastTaskDescription));
+ }
+
+ /**
+ * Should only be invoked from {@link #createWindowContainer(boolean, boolean)}.
+ */
+ @VisibleForTesting
+ protected void setWindowContainerController(TaskWindowContainerController controller) {
+ if (mWindowContainerController != null) {
+ throw new IllegalArgumentException("Window container=" + mWindowContainerController
+ + " already created for task=" + this);
+ }
+
+ mWindowContainerController = controller;
}
void removeWindowContainer() {
diff --git a/services/core/java/com/android/server/notification/GlobalSortKeyComparator.java b/services/core/java/com/android/server/notification/GlobalSortKeyComparator.java
index ce976d2..acedafc 100644
--- a/services/core/java/com/android/server/notification/GlobalSortKeyComparator.java
+++ b/services/core/java/com/android/server/notification/GlobalSortKeyComparator.java
@@ -15,19 +15,25 @@
*/
package com.android.server.notification;
+import android.util.Slog;
+
import java.util.Comparator;
/**
* Sorts notifications by their global sort key.
*/
public class GlobalSortKeyComparator implements Comparator<NotificationRecord> {
+ private final static String TAG = "GlobalSortComp";
+
@Override
public int compare(NotificationRecord left, NotificationRecord right) {
if (left.getGlobalSortKey() == null) {
- throw new IllegalStateException("Missing left global sort key: " + left);
+ Slog.wtf(TAG, "Missing left global sort key: " + left);
+ return 1;
}
if (right.getGlobalSortKey() == null) {
- throw new IllegalStateException("Missing right global sort key: " + right);
+ Slog.wtf(TAG, "Missing right global sort key: " + right);
+ return -1;
}
return left.getGlobalSortKey().compareTo(right.getGlobalSortKey());
}
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index cc3948e..8a6a940 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -1874,10 +1874,9 @@
int userId = ActivityManager.handleIncomingUser(Binder.getCallingPid(),
Binder.getCallingUid(), incomingUserId, true, false,
"getAppActiveNotifications", pkg);
- final ArrayMap<String, StatusBarNotification> map
- = new ArrayMap<>(mNotificationList.size() + mEnqueuedNotifications.size());
-
synchronized (mNotificationLock) {
+ final ArrayMap<String, StatusBarNotification> map
+ = new ArrayMap<>(mNotificationList.size() + mEnqueuedNotifications.size());
final int N = mNotificationList.size();
for (int i = 0; i < N; i++) {
StatusBarNotification sbn = sanitizeSbn(pkg, userId,
@@ -1900,11 +1899,10 @@
map.put(sbn.getKey(), sbn); // pending update overwrites existing post here
}
}
+ final ArrayList<StatusBarNotification> list = new ArrayList<>(map.size());
+ list.addAll(map.values());
+ return new ParceledListSlice<StatusBarNotification>(list);
}
-
- final ArrayList<StatusBarNotification> list = new ArrayList<>(map.size());
- list.addAll(map.values());
- return new ParceledListSlice<StatusBarNotification>(list);
}
private StatusBarNotification sanitizeSbn(String pkg, int userId,
@@ -2036,8 +2034,10 @@
long identity = Binder.clearCallingIdentity();
try {
// allow bound services to disable themselves
- final ManagedServiceInfo info = mListeners.checkServiceTokenLocked(token);
- info.getOwner().setComponentState(info.component, false);
+ synchronized (mNotificationLock) {
+ final ManagedServiceInfo info = mListeners.checkServiceTokenLocked(token);
+ info.getOwner().setComponentState(info.component, false);
+ }
} finally {
Binder.restoreCallingIdentity(identity);
}
@@ -2101,8 +2101,10 @@
String key, String snoozeCriterionId) {
long identity = Binder.clearCallingIdentity();
try {
- final ManagedServiceInfo info = mListeners.checkServiceTokenLocked(token);
- snoozeNotificationInt(key, SNOOZE_UNTIL_UNSPECIFIED, snoozeCriterionId, info);
+ synchronized (mNotificationLock) {
+ final ManagedServiceInfo info = mListeners.checkServiceTokenLocked(token);
+ snoozeNotificationInt(key, SNOOZE_UNTIL_UNSPECIFIED, snoozeCriterionId, info);
+ }
} finally {
Binder.restoreCallingIdentity(identity);
}
@@ -2118,8 +2120,10 @@
long duration) {
long identity = Binder.clearCallingIdentity();
try {
- final ManagedServiceInfo info = mListeners.checkServiceTokenLocked(token);
- snoozeNotificationInt(key, duration, null, info);
+ synchronized (mNotificationLock) {
+ final ManagedServiceInfo info = mListeners.checkServiceTokenLocked(token);
+ snoozeNotificationInt(key, duration, null, info);
+ }
} finally {
Binder.restoreCallingIdentity(identity);
}
@@ -2134,9 +2138,11 @@
public void unsnoozeNotificationFromAssistant(INotificationListener token, String key) {
long identity = Binder.clearCallingIdentity();
try {
- final ManagedServiceInfo info =
- mNotificationAssistants.checkServiceTokenLocked(token);
- unsnoozeNotificationInt(key, info);
+ synchronized (mNotificationLock) {
+ final ManagedServiceInfo info =
+ mNotificationAssistants.checkServiceTokenLocked(token);
+ unsnoozeNotificationInt(key, info);
+ }
} finally {
Binder.restoreCallingIdentity(identity);
}
@@ -2734,7 +2740,10 @@
}
private void verifyPrivilegedListener(INotificationListener token, UserHandle user) {
- ManagedServiceInfo info = mListeners.checkServiceTokenLocked(token);
+ ManagedServiceInfo info;
+ synchronized (mNotificationLock) {
+ info = mListeners.checkServiceTokenLocked(token);
+ }
if (!hasCompanionDevice(info)) {
throw new SecurityException(info + " does not have access");
}
@@ -3099,8 +3108,10 @@
@Override
public void run() {
synchronized (mNotificationLock) {
- removeForegroundServiceFlagByListLocked(mEnqueuedNotifications, pkg, notificationId, userId);
- removeForegroundServiceFlagByListLocked(mNotificationList, pkg, notificationId, userId);
+ removeForegroundServiceFlagByListLocked(
+ mEnqueuedNotifications, pkg, notificationId, userId);
+ removeForegroundServiceFlagByListLocked(
+ mNotificationList, pkg, notificationId, userId);
}
}
});
@@ -3229,8 +3240,12 @@
private void doDebugOnlyToast(CharSequence toastText) {
if (Build.IS_DEBUGGABLE) {
- Toast toast = Toast.makeText(getContext(), toastText, Toast.LENGTH_LONG);
- toast.show();
+ try {
+ Toast toast = Toast.makeText(getContext(), toastText, Toast.LENGTH_LONG);
+ toast.show();
+ } catch (RuntimeException e) {
+ Slog.w(TAG, "Unable to toast with text: " + toastText, e);
+ }
}
}
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index bfa1b99..e82ba9c 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -742,8 +742,8 @@
boolean forceEphemeralUsers = false; // Can only be set by a device owner.
boolean isNetworkLoggingEnabled = false; // Can only be set by a device owner.
- // one notification after enabling + 3 more after reboots
- static final int DEF_MAXIMUM_NETWORK_LOGGING_NOTIFICATIONS_SHOWN = 4;
+ // one notification after enabling + one more after reboots
+ static final int DEF_MAXIMUM_NETWORK_LOGGING_NOTIFICATIONS_SHOWN = 2;
int numNetworkLoggingNotifications = 0;
long lastNetworkLoggingNotificationTimeMs = 0; // Time in milliseconds since epoch
diff --git a/services/tests/notification/src/com/android/server/notification/GlobalSortKeyComparatorTest.java b/services/tests/notification/src/com/android/server/notification/GlobalSortKeyComparatorTest.java
new file mode 100644
index 0000000..24cb72e
--- /dev/null
+++ b/services/tests/notification/src/com/android/server/notification/GlobalSortKeyComparatorTest.java
@@ -0,0 +1,153 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.server.notification;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Matchers.eq;
+
+import android.app.Notification;
+import android.app.NotificationChannel;
+import android.app.NotificationManager;
+import android.os.UserHandle;
+import android.service.notification.StatusBarNotification;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.runner.AndroidJUnit4;
+import android.test.suitebuilder.annotation.SmallTest;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class GlobalSortKeyComparatorTest {
+
+ private final String PKG = "PKG";
+ private final int UID = 1111111;
+ private static final String TEST_CHANNEL_ID = "test_channel_id";
+
+ @Test
+ public void testComparator() throws Exception {
+ Notification n = new Notification.Builder(
+ InstrumentationRegistry.getContext(), TEST_CHANNEL_ID)
+ .build();
+ NotificationRecord left = new NotificationRecord(InstrumentationRegistry.getContext(),
+ new StatusBarNotification(PKG,
+ PKG, 1, "media", UID, UID, n,
+ new UserHandle(UserHandle.myUserId()),
+ "", 1499), getDefaultChannel());
+ left.setGlobalSortKey("first");
+
+ NotificationRecord right = new NotificationRecord(InstrumentationRegistry.getContext(),
+ new StatusBarNotification(PKG,
+ PKG, 1, "media", UID, UID, n,
+ new UserHandle(UserHandle.myUserId()),
+ "", 1499), getDefaultChannel());
+ right.setGlobalSortKey("second");
+
+ NotificationRecord last = new NotificationRecord(InstrumentationRegistry.getContext(),
+ new StatusBarNotification(PKG,
+ PKG, 1, "media", UID, UID, n,
+ new UserHandle(UserHandle.myUserId()),
+ "", 1499), getDefaultChannel());
+
+
+ final List<NotificationRecord> expected = new ArrayList<>();
+ expected.add(left);
+ expected.add(right);
+ expected.add(last);
+
+ List<NotificationRecord> actual = new ArrayList<>();
+ actual.addAll(expected);
+ Collections.shuffle(actual);
+
+ Collections.sort(actual, new GlobalSortKeyComparator());
+
+ assertEquals(expected, actual);
+ }
+
+ @Test
+ public void testNoCrash_leftNull() throws Exception {
+ Notification n = new Notification.Builder(
+ InstrumentationRegistry.getContext(), TEST_CHANNEL_ID)
+ .build();
+ NotificationRecord left = new NotificationRecord(InstrumentationRegistry.getContext(),
+ new StatusBarNotification(PKG,
+ PKG, 1, "media", UID, UID, n,
+ new UserHandle(UserHandle.myUserId()),
+ "", 1499), getDefaultChannel());
+
+ NotificationRecord right = new NotificationRecord(InstrumentationRegistry.getContext(),
+ new StatusBarNotification(PKG,
+ PKG, 1, "media", UID, UID, n,
+ new UserHandle(UserHandle.myUserId()),
+ "", 1499), getDefaultChannel());
+ right.setGlobalSortKey("not null");
+
+ final List<NotificationRecord> expected = new ArrayList<>();
+ expected.add(right);
+ expected.add(left);
+
+ List<NotificationRecord> actual = new ArrayList<>();
+ actual.addAll(expected);
+ Collections.shuffle(actual);
+
+ Collections.sort(actual, new GlobalSortKeyComparator());
+
+ assertEquals(expected, actual);
+ }
+
+ @Test
+ public void testNoCrash_rightNull() throws Exception {
+ Notification n = new Notification.Builder(
+ InstrumentationRegistry.getContext(), TEST_CHANNEL_ID)
+ .build();
+ NotificationRecord left = new NotificationRecord(InstrumentationRegistry.getContext(),
+ new StatusBarNotification(PKG,
+ PKG, 1, "media", UID, UID, n,
+ new UserHandle(UserHandle.myUserId()),
+ "", 1499), getDefaultChannel());
+ left.setGlobalSortKey("not null");
+
+ NotificationRecord right = new NotificationRecord(InstrumentationRegistry.getContext(),
+ new StatusBarNotification(PKG,
+ PKG, 1, "media", UID, UID, n,
+ new UserHandle(UserHandle.myUserId()),
+ "", 1499), getDefaultChannel());
+
+ final List<NotificationRecord> expected = new ArrayList<>();
+ expected.add(left);
+ expected.add(right);
+
+ List<NotificationRecord> actual = new ArrayList<>();
+ actual.addAll(expected);
+ Collections.shuffle(actual);
+
+ Collections.sort(actual, new GlobalSortKeyComparator());
+
+ assertEquals(expected, actual);
+ }
+
+ private NotificationChannel getDefaultChannel() {
+ return new NotificationChannel(NotificationChannel.DEFAULT_CHANNEL_ID, "name",
+ NotificationManager.IMPORTANCE_LOW);
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityRecordTests.java b/services/tests/servicestests/src/com/android/server/am/ActivityRecordTests.java
index 54ecab3..f75d49c 100644
--- a/services/tests/servicestests/src/com/android/server/am/ActivityRecordTests.java
+++ b/services/tests/servicestests/src/com/android/server/am/ActivityRecordTests.java
@@ -16,7 +16,8 @@
package com.android.server.am;
-import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
import android.content.ComponentName;
import android.platform.test.annotations.Presubmit;
@@ -36,50 +37,61 @@
@Presubmit
@RunWith(AndroidJUnit4.class)
public class ActivityRecordTests extends ActivityTestsBase {
+ private static final int TEST_STACK_ID = 100;
+
private final ComponentName testActivityComponent =
ComponentName.unflattenFromString("com.foo/.BarActivity");
@Test
public void testStackCleanupOnClearingTask() throws Exception {
final ActivityManagerService service = createActivityManagerService();
- final TestActivityStack testStack = new ActivityStackBuilder(service).build();
- final TaskRecord task = createTask(service, testActivityComponent, testStack);
+ final TaskRecord task = createTask(service, testActivityComponent, TEST_STACK_ID);
final ActivityRecord record = createActivity(service, testActivityComponent, task);
record.setTask(null);
- assertTrue(testStack.onActivityRemovedFromStackInvocationCount() == 1);
+ assertEquals(getActivityRemovedFromStackCount(service, TEST_STACK_ID), 1);
}
@Test
public void testStackCleanupOnActivityRemoval() throws Exception {
final ActivityManagerService service = createActivityManagerService();
- final TestActivityStack testStack = new ActivityStackBuilder(service).build();
- final TaskRecord task = createTask(service, testActivityComponent, testStack);
+ final TaskRecord task = createTask(service, testActivityComponent, TEST_STACK_ID);
final ActivityRecord record = createActivity(service, testActivityComponent, task);
task.removeActivity(record);
- assertTrue(testStack.onActivityRemovedFromStackInvocationCount() == 1);
+ assertEquals(getActivityRemovedFromStackCount(service, TEST_STACK_ID), 1);
}
@Test
public void testStackCleanupOnTaskRemoval() throws Exception {
final ActivityManagerService service = createActivityManagerService();
- final TestActivityStack testStack = new ActivityStackBuilder(service).build();
- final TaskRecord task = createTask(service, testActivityComponent, testStack);
+ final TaskRecord task = createTask(service, testActivityComponent, TEST_STACK_ID);
final ActivityRecord record = createActivity(service, testActivityComponent, task);
- testStack.removeTask(task, null /*reason*/, ActivityStack.REMOVE_TASK_MODE_MOVING);
- assertTrue(testStack.onActivityRemovedFromStackInvocationCount() == 1);
+ service.mStackSupervisor.getStack(TEST_STACK_ID)
+ .removeTask(task, null /*reason*/, ActivityStack.REMOVE_TASK_MODE_MOVING);
+
+ // Stack should be gone on task removal.
+ assertNull(service.mStackSupervisor.getStack(TEST_STACK_ID));
}
@Test
public void testNoCleanupMovingActivityInSameStack() throws Exception {
final ActivityManagerService service = createActivityManagerService();
- final TestActivityStack testStack = new ActivityStackBuilder(service).build();
- final TaskRecord oldTask = createTask(service, testActivityComponent, testStack);
+ final TaskRecord oldTask = createTask(service, testActivityComponent, TEST_STACK_ID);
final ActivityRecord record = createActivity(service, testActivityComponent, oldTask);
- final TaskRecord newTask = createTask(service, testActivityComponent, testStack);
+ final TaskRecord newTask = createTask(service, testActivityComponent, TEST_STACK_ID);
record.reparent(newTask, 0, null /*reason*/);
- assertTrue(testStack.onActivityRemovedFromStackInvocationCount() == 0);
+ assertEquals(getActivityRemovedFromStackCount(service, TEST_STACK_ID), 0);
+ }
+
+ private static int getActivityRemovedFromStackCount(ActivityManagerService service,
+ int stackId) {
+ final ActivityStack stack = service.mStackSupervisor.getStack(stackId);
+ if (stack instanceof ActivityStackReporter) {
+ return ((ActivityStackReporter) stack).onActivityRemovedFromStackInvocationCount();
+ }
+
+ return -1;
}
}
diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityStackSupervisorTests.java b/services/tests/servicestests/src/com/android/server/am/ActivityStackSupervisorTests.java
index 8423aff..fc9ab96 100644
--- a/services/tests/servicestests/src/com/android/server/am/ActivityStackSupervisorTests.java
+++ b/services/tests/servicestests/src/com/android/server/am/ActivityStackSupervisorTests.java
@@ -16,8 +16,14 @@
package com.android.server.am;
+import static android.app.ActivityManager.StackId.FULLSCREEN_WORKSPACE_STACK_ID;
+import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
+import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import android.content.ComponentName;
+import android.graphics.Rect;
import android.platform.test.annotations.Presubmit;
import android.support.test.filters.MediumTest;
import android.support.test.runner.AndroidJUnit4;
@@ -25,6 +31,10 @@
import org.junit.runner.RunWith;
import org.junit.Test;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
import static com.android.server.am.ActivityStackSupervisor.MATCH_TASK_IN_STACKS_OR_RECENT_TASKS_AND_RESTORE;
/**
@@ -37,6 +47,9 @@
@Presubmit
@RunWith(AndroidJUnit4.class)
public class ActivityStackSupervisorTests extends ActivityTestsBase {
+ private final ComponentName testActivityComponent =
+ ComponentName.unflattenFromString("com.foo/.BarActivity");
+
/**
* This test ensures that we do not try to restore a task based off an invalid task id. The
* stack supervisor is a test version so there will be no tasks present. We should expect
@@ -49,4 +62,59 @@
MATCH_TASK_IN_STACKS_OR_RECENT_TASKS_AND_RESTORE, 0 /*stackId*/);
assertNull(task);
}
+
+ /**
+ * This test ensures that an existing task in the pinned stack is moved to the fullscreen
+ * activity stack when a new task is added.
+ */
+ @Test
+ public void testReplacingTaskInPinnedStack() throws Exception {
+ final ActivityManagerService service = createActivityManagerService();
+ final TaskRecord firstTask = createTask(service, testActivityComponent,
+ FULLSCREEN_WORKSPACE_STACK_ID);
+ final ActivityRecord firstActivity = createActivity(service, testActivityComponent,
+ firstTask);
+ // Create a new task on the full screen stack
+ final TaskRecord secondTask = createTask(service, testActivityComponent,
+ FULLSCREEN_WORKSPACE_STACK_ID);
+ final ActivityRecord secondActivity = createActivity(service, testActivityComponent,
+ secondTask);
+ service.mStackSupervisor.setFocusStackUnchecked("testReplacingTaskInPinnedStack",
+ service.mStackSupervisor.getStack(FULLSCREEN_WORKSPACE_STACK_ID));
+
+ // Ensure full screen stack has both tasks.
+ ensureStackPlacement(service.mStackSupervisor, FULLSCREEN_WORKSPACE_STACK_ID, firstTask,
+ secondTask);
+
+ // Move first activity to pinned stack.
+ service.mStackSupervisor.moveActivityToPinnedStackLocked(firstActivity,
+ new Rect() /*sourceBounds*/, 0f /*aspectRatio*/, false, "initialMove");
+
+ // Ensure a task has moved over.
+ ensureStackPlacement(service.mStackSupervisor, PINNED_STACK_ID, firstTask);
+ ensureStackPlacement(service.mStackSupervisor, FULLSCREEN_WORKSPACE_STACK_ID, secondTask);
+
+ // Move second activity to pinned stack.
+ service.mStackSupervisor.moveActivityToPinnedStackLocked(secondActivity,
+ new Rect() /*sourceBounds*/, 0f /*aspectRatio*/ /*destBounds*/, false, "secondMove");
+
+ // Ensure stacks have swapped tasks.
+ ensureStackPlacement(service.mStackSupervisor, PINNED_STACK_ID, secondTask);
+ ensureStackPlacement(service.mStackSupervisor, FULLSCREEN_WORKSPACE_STACK_ID, firstTask);
+ }
+
+ private static void ensureStackPlacement(ActivityStackSupervisor supervisor, int stackId,
+ TaskRecord... tasks) {
+ final ActivityStack stack = supervisor.getStack(stackId);
+ final ArrayList<TaskRecord> stackTasks = stack.getAllTasks();
+ assertEquals(stackTasks.size(), tasks != null ? tasks.length : 0);
+
+ if (tasks == null) {
+ return;
+ }
+
+ for (TaskRecord task : tasks) {
+ assertTrue(stackTasks.contains(task));
+ }
+ }
}
diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityStackTests.java b/services/tests/servicestests/src/com/android/server/am/ActivityStackTests.java
index 1d80b33..f42abf1 100644
--- a/services/tests/servicestests/src/com/android/server/am/ActivityStackTests.java
+++ b/services/tests/servicestests/src/com/android/server/am/ActivityStackTests.java
@@ -37,28 +37,27 @@
@Presubmit
@RunWith(AndroidJUnit4.class)
public class ActivityStackTests extends ActivityTestsBase {
- private final ComponentName testActivityComponent =
+ private static final int TEST_STACK_ID = 100;
+ private static final ComponentName testActivityComponent =
ComponentName.unflattenFromString("com.foo/.BarActivity");
@Test
public void testEmptyTaskCleanupOnRemove() throws Exception {
final ActivityManagerService service = createActivityManagerService();
- final TestActivityStack testStack = new ActivityStackBuilder(service).build();
- final TaskRecord task = createTask(service, testActivityComponent, testStack);
+ final TaskRecord task = createTask(service, testActivityComponent, TEST_STACK_ID);
assertNotNull(task.getWindowContainerController());
- testStack.removeTask(task, "testEmptyTaskCleanupOnRemove",
- ActivityStack.REMOVE_TASK_MODE_DESTROYING);
+ service.mStackSupervisor.getStack(TEST_STACK_ID).removeTask(task,
+ "testEmptyTaskCleanupOnRemove", ActivityStack.REMOVE_TASK_MODE_DESTROYING);
assertNull(task.getWindowContainerController());
}
@Test
public void testOccupiedTaskCleanupOnRemove() throws Exception {
final ActivityManagerService service = createActivityManagerService();
- final TestActivityStack testStack = new ActivityStackBuilder(service).build();
- final TaskRecord task = createTask(service, testActivityComponent, testStack);
+ final TaskRecord task = createTask(service, testActivityComponent, TEST_STACK_ID);
final ActivityRecord activityRecord = createActivity(service, testActivityComponent, task);
assertNotNull(task.getWindowContainerController());
- testStack.removeTask(task, "testOccupiedTaskCleanupOnRemove",
- ActivityStack.REMOVE_TASK_MODE_DESTROYING);
+ service.mStackSupervisor.getStack(TEST_STACK_ID).removeTask(task,
+ "testOccupiedTaskCleanupOnRemove", ActivityStack.REMOVE_TASK_MODE_DESTROYING);
assertNotNull(task.getWindowContainerController());
}
}
diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java b/services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java
index 3bf0e5f..0827084 100644
--- a/services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java
+++ b/services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java
@@ -17,6 +17,11 @@
package com.android.server.am;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.doAnswer;
+
+import org.mockito.invocation.InvocationOnMock;
import android.app.ActivityManager;
import android.content.ComponentName;
@@ -33,6 +38,7 @@
import com.android.server.wm.AppWindowContainerController;
import com.android.server.wm.StackWindowController;
+import com.android.server.wm.TaskWindowContainerController;
import com.android.server.wm.WindowManagerService;
import com.android.server.wm.WindowTestUtils;
import org.junit.After;
@@ -64,16 +70,15 @@
protected ActivityManagerService createActivityManagerService() {
final ActivityManagerService service = new TestActivityManagerService(mContext);
- service.mWindowManager = WindowTestUtils.getWindowManagerService(mContext);
+ service.mWindowManager = WindowTestUtils.getMockWindowManagerService();
return service;
}
- protected static TestActivityStack createActivityStack(ActivityManagerService service,
+ protected static ActivityStack createActivityStack(ActivityManagerService service,
int stackId, int displayId, boolean onTop) {
if (service.mStackSupervisor instanceof TestActivityStackSupervisor) {
- final TestActivityStack stack = ((TestActivityStackSupervisor) service.mStackSupervisor)
+ return ((TestActivityStackSupervisor) service.mStackSupervisor)
.createTestStack(service, stackId, onTop);
- return stack;
}
return null;
@@ -103,7 +108,7 @@
}
protected static TaskRecord createTask(ActivityManagerService service,
- ComponentName component, ActivityStack stack) {
+ ComponentName component, int stackId) {
final ActivityInfo aInfo = new ActivityInfo();
aInfo.applicationInfo = new ApplicationInfo();
aInfo.applicationInfo.packageName = component.getPackageName();
@@ -113,13 +118,16 @@
final TaskRecord task = new TaskRecord(service, 0, aInfo, intent /*intent*/,
null /*_taskDescription*/, new ActivityManager.TaskThumbnailInfo());
+ final ActivityStack stack = service.mStackSupervisor.getStack(stackId,
+ true /*createStaticStackIfNeeded*/, true /*onTop*/);
stack.addTask(task, true, "creating test task");
task.setStack(stack);
- task.createWindowContainer(true, true);
+ task.setWindowContainerController(mock(TaskWindowContainerController.class));
return task;
}
+
/**
* An {@link ActivityManagerService} subclass which provides a test
* {@link ActivityStackSupervisor}.
@@ -127,6 +135,9 @@
protected static class TestActivityManagerService extends ActivityManagerService {
public TestActivityManagerService(Context context) {
super(context);
+ mSupportsMultiWindow = true;
+ mSupportsMultiDisplay = true;
+ mWindowManager = WindowTestUtils.getWindowManagerService(context);
}
@Override
@@ -142,6 +153,12 @@
protected static class TestActivityStackSupervisor extends ActivityStackSupervisor {
public TestActivityStackSupervisor(ActivityManagerService service, Looper looper) {
super(service, looper);
+ mWindowManager = prepareMockWindowManager();
+ }
+
+ // No home stack is set.
+ @Override
+ void moveHomeStackToFront(String reason) {
}
// Invoked during {@link ActivityStack} creation.
@@ -149,18 +166,45 @@
void updateUIDsPresentOnDisplay() {
}
- public TestActivityStack createTestStack(ActivityManagerService service, int stackId,
- boolean onTop) {
+ // Just return the current front task.
+ @Override
+ ActivityStack getNextFocusableStackLocked(ActivityStack currentFocus) {
+ return mFocusedStack;
+ }
+
+ // Called when moving activity to pinned stack.
+ @Override
+ void ensureActivitiesVisibleLocked(ActivityRecord starting, int configChanges,
+ boolean preserveWindows) {
+ }
+
+ public <T extends ActivityStack> T createTestStack(ActivityManagerService service,
+ int stackId, boolean onTop) {
final ActivityDisplay display = new ActivityDisplay();
final TestActivityContainer container =
new TestActivityContainer(service, stackId, display, onTop);
- return container.getStack();
+ mActivityContainers.put(stackId, container);
+ return (T) container.getStack();
+ }
+
+ @Override
+ protected <T extends ActivityStack> T getStack(int stackId,
+ boolean createStaticStackIfNeeded, boolean createOnTop) {
+ final T stack = super.getStack(stackId, createStaticStackIfNeeded, createOnTop);
+
+ if (stack != null || !createStaticStackIfNeeded) {
+ return stack;
+ }
+
+ return createTestStack(mService, stackId, createOnTop);
}
private class TestActivityContainer extends ActivityContainer {
- private ActivityManagerService mService;
- private TestActivityStack mStack;
+ private final ActivityManagerService mService;
+
private boolean mOnTop;
+ private int mStackId;
+ private ActivityStack mStack;
TestActivityContainer(ActivityManagerService service, int stackId,
ActivityDisplay activityDisplay, boolean onTop) {
@@ -174,12 +218,16 @@
// we cannot set {@link mService} by the time the super constructor calling this
// method is invoked.
mOnTop = onTop;
+ mStackId = stackId;
}
- public TestActivityStack getStack() {
+ public ActivityStack getStack() {
if (mStack == null) {
- mStack = new TestActivityStack(this,
- new RecentTasks(mService, mService.mStackSupervisor), mOnTop);
+ final RecentTasks recents =
+ new RecentTasks(mService, mService.mStackSupervisor);
+ mStack = mStackId == ActivityManager.StackId.PINNED_STACK_ID
+ ? new PinnedActivityStack(this, recents, mOnTop)
+ : new TestActivityStack(this, recents, mOnTop);
}
return mStack;
@@ -187,13 +235,31 @@
}
}
+ private static WindowManagerService prepareMockWindowManager() {
+ final WindowManagerService service = mock(WindowManagerService.class);
+
+ doAnswer((InvocationOnMock invocationOnMock) -> {
+ final Runnable runnable = invocationOnMock.<Runnable>getArgument(0);
+ if (runnable != null) {
+ runnable.run();
+ }
+ return null;
+ }).when(service).inSurfaceTransaction(any());
+
+ return service;
+ }
+
+ protected interface ActivityStackReporter {
+ int onActivityRemovedFromStackInvocationCount();
+ }
+
/**
* Override of {@link ActivityStack} that tracks test metrics, such as the number of times a
* method is called. Note that its functionality depends on the implementations of the
* construction arguments.
*/
protected static class TestActivityStack<T extends StackWindowController>
- extends ActivityStack<T> {
+ extends ActivityStack<T> implements ActivityStackReporter {
private int mOnActivityRemovedFromStackCount = 0;
private T mContainerController;
TestActivityStack(ActivityStackSupervisor.ActivityContainer activityContainer,
@@ -208,6 +274,7 @@
}
// Returns the number of times {@link #onActivityRemovedFromStack} has been called
+ @Override
public int onActivityRemovedFromStackInvocationCount() {
return mOnActivityRemovedFromStackCount;
}
@@ -225,6 +292,7 @@
}
}
+
protected static class ActivityStackBuilder {
private boolean mOnTop = true;
private int mStackId = 0;
@@ -251,7 +319,7 @@
return this;
}
- public TestActivityStack build() {
+ public ActivityStack build() {
return createActivityStack(mService, mStackId, mDisplayId, mOnTop);
}
}
diff --git a/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java b/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java
index fbeda0a..9392e8e 100644
--- a/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java
+++ b/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java
@@ -90,6 +90,7 @@
return null;
}).when(am).notifyKeyguardFlagsChanged(any());
}
+
sWm = WindowManagerService.main(context, mock(InputManagerService.class), true, false,
false, new TestWindowManagerPolicy());
}
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowTestUtils.java b/services/tests/servicestests/src/com/android/server/wm/WindowTestUtils.java
index 3a44357..ae3eb52 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowTestUtils.java
+++ b/services/tests/servicestests/src/com/android/server/wm/WindowTestUtils.java
@@ -48,6 +48,13 @@
}
/**
+ * Retrieves an instance of a mock {@link WindowManagerService}.
+ */
+ public static WindowManagerService getMockWindowManagerService() {
+ return mock(WindowManagerService.class);
+ }
+
+ /**
* Creates a mock instance of {@link StackWindowController}.
*/
public static StackWindowController createMockStackWindowContainerController() {
diff --git a/wifi/java/android/net/wifi/aware/DiscoverySession.java b/wifi/java/android/net/wifi/aware/DiscoverySession.java
index 82b3792..bf5c42b 100644
--- a/wifi/java/android/net/wifi/aware/DiscoverySession.java
+++ b/wifi/java/android/net/wifi/aware/DiscoverySession.java
@@ -19,6 +19,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
+import android.net.NetworkSpecifier;
import android.net.wifi.RttManager;
import android.util.Log;
@@ -250,8 +251,8 @@
}
/**
- * Create a {@link android.net.NetworkRequest.Builder#setNetworkSpecifier(String)} for an
- * unencrypted WiFi Aware connection (link) to the specified peer. The
+ * Create a {@link android.net.NetworkRequest.Builder#setNetworkSpecifier(NetworkSpecifier)} for
+ * an unencrypted WiFi Aware connection (link) to the specified peer. The
* {@link android.net.NetworkRequest.Builder#addTransportType(int)} should be set to
* {@link android.net.NetworkCapabilities#TRANSPORT_WIFI_AWARE}.
* <p>
@@ -276,13 +277,13 @@
* request from only that peer. A RESPONDER may specify a {@code null} -
* indicating that it will accept connection requests from any device.
*
- * @return A string to be used to construct
- * {@link android.net.NetworkRequest.Builder#setNetworkSpecifier(String)} to pass to
+ * @return A {@link NetworkSpecifier} to be used to construct
+ * {@link android.net.NetworkRequest.Builder#setNetworkSpecifier(NetworkSpecifier)} to pass to
* {@link android.net.ConnectivityManager#requestNetwork(android.net.NetworkRequest,
* android.net.ConnectivityManager.NetworkCallback)}
* [or other varieties of that API].
*/
- public String createNetworkSpecifierOpen(@Nullable PeerHandle peerHandle) {
+ public NetworkSpecifier createNetworkSpecifierOpen(@Nullable PeerHandle peerHandle) {
if (mTerminated) {
Log.w(TAG, "createNetworkSpecifierOpen: called on terminated session");
return null;
@@ -302,8 +303,8 @@
}
/**
- * Create a {@link android.net.NetworkRequest.Builder#setNetworkSpecifier(String)} for an
- * encrypted WiFi Aware connection (link) to the specified peer. The
+ * Create a {@link android.net.NetworkRequest.Builder#setNetworkSpecifier(NetworkSpecifier)} for
+ * an encrypted WiFi Aware connection (link) to the specified peer. The
* {@link android.net.NetworkRequest.Builder#addTransportType(int)} should be set to
* {@link android.net.NetworkCapabilities#TRANSPORT_WIFI_AWARE}.
* <p>
@@ -329,14 +330,14 @@
* {@link #createNetworkSpecifierOpen(PeerHandle)} API to
* specify an open (unencrypted) link.
*
- * @return A string to be used to construct
- * {@link android.net.NetworkRequest.Builder#setNetworkSpecifier(String)} to pass to
+ * @return A {@link NetworkSpecifier} to be used to construct
+ * {@link android.net.NetworkRequest.Builder#setNetworkSpecifier(NetworkSpecifier)} to pass to
* {@link android.net.ConnectivityManager#requestNetwork(android.net.NetworkRequest,
* android.net.ConnectivityManager.NetworkCallback)}
* [or other varieties of that API].
*/
- public String createNetworkSpecifierPassphrase(@Nullable PeerHandle peerHandle,
- @NonNull String passphrase) {
+ public NetworkSpecifier createNetworkSpecifierPassphrase(
+ @Nullable PeerHandle peerHandle, @NonNull String passphrase) {
if (passphrase == null || passphrase.length() == 0) {
throw new IllegalArgumentException("Passphrase must not be null or empty");
}
@@ -361,8 +362,8 @@
}
/**
- * Create a {@link android.net.NetworkRequest.Builder#setNetworkSpecifier(String)} for an
- * encrypted WiFi Aware connection (link) to the specified peer. The
+ * Create a {@link android.net.NetworkRequest.Builder#setNetworkSpecifier(NetworkSpecifier)} for
+ * an encrypted WiFi Aware connection (link) to the specified peer. The
* {@link android.net.NetworkRequest.Builder#addTransportType(int)} should be set to
* {@link android.net.NetworkCapabilities#TRANSPORT_WIFI_AWARE}.
* <p>
@@ -389,8 +390,8 @@
* Passphrase or {@link #createNetworkSpecifierOpen(PeerHandle)} to specify an
* open (unencrypted) link.
*
- * @return A string to be used to construct
- * {@link android.net.NetworkRequest.Builder#setNetworkSpecifier(String)} to pass to
+ * @return A {@link NetworkSpecifier} to be used to construct
+ * {@link android.net.NetworkRequest.Builder#setNetworkSpecifier(NetworkSpecifier)} to pass to
* {@link android.net.ConnectivityManager#requestNetwork(android.net.NetworkRequest,
* android.net.ConnectivityManager.NetworkCallback)}
* [or other varieties of that API].
@@ -398,7 +399,7 @@
* @hide
*/
@SystemApi
- public String createNetworkSpecifierPmk(@Nullable PeerHandle peerHandle,
+ public NetworkSpecifier createNetworkSpecifierPmk(@Nullable PeerHandle peerHandle,
@NonNull byte[] pmk) {
if (pmk == null || pmk.length == 0) {
throw new IllegalArgumentException("PMK must not be null or empty");
diff --git a/wifi/java/android/net/wifi/aware/WifiAwareManager.java b/wifi/java/android/net/wifi/aware/WifiAwareManager.java
index 4d3957a..3fcbd4b 100644
--- a/wifi/java/android/net/wifi/aware/WifiAwareManager.java
+++ b/wifi/java/android/net/wifi/aware/WifiAwareManager.java
@@ -24,6 +24,7 @@
import android.content.Context;
import android.net.ConnectivityManager;
import android.net.NetworkRequest;
+import android.net.NetworkSpecifier;
import android.net.wifi.RttManager;
import android.os.Binder;
import android.os.Bundle;
@@ -31,7 +32,6 @@
import android.os.Looper;
import android.os.Message;
import android.os.RemoteException;
-import android.util.Base64;
import android.util.Log;
import android.util.SparseArray;
@@ -39,9 +39,6 @@
import libcore.util.HexEncoding;
-import org.json.JSONException;
-import org.json.JSONObject;
-
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.ref.WeakReference;
@@ -129,65 +126,6 @@
private static final boolean VDBG = false; // STOPSHIP if true
/**
- * Keys used to generate a Network Specifier for the Aware network request. The network
- * specifier is formatted as a JSON string.
- */
-
- /**
- * TYPE: in band, specific peer: role, client_id, session_id, peer_id, pmk/passphrase optional
- * @hide
- */
- public static final int NETWORK_SPECIFIER_TYPE_IB = 0;
-
- /**
- * TYPE: in band, any peer: role, client_id, session_id, pmk/passphrase optional
- * [only permitted for RESPONDER]
- * @hide
- */
- public static final int NETWORK_SPECIFIER_TYPE_IB_ANY_PEER = 1;
-
- /**
- * TYPE: out-of-band: role, client_id, peer_mac, pmk/passphrase optional
- * @hide
- */
- public static final int NETWORK_SPECIFIER_TYPE_OOB = 2;
-
- /**
- * TYPE: out-of-band, any peer: role, client_id, pmk/passphrase optional
- * [only permitted for RESPONDER]
- * @hide
- */
- public static final int NETWORK_SPECIFIER_TYPE_OOB_ANY_PEER = 3;
-
-
- /** @hide */
- public static final int NETWORK_SPECIFIER_TYPE_MAX_VALID = NETWORK_SPECIFIER_TYPE_OOB_ANY_PEER;
-
- /** @hide */
- public static final String NETWORK_SPECIFIER_KEY_TYPE = "type";
-
- /** @hide */
- public static final String NETWORK_SPECIFIER_KEY_ROLE = "role";
-
- /** @hide */
- public static final String NETWORK_SPECIFIER_KEY_CLIENT_ID = "client_id";
-
- /** @hide */
- public static final String NETWORK_SPECIFIER_KEY_SESSION_ID = "session_id";
-
- /** @hide */
- public static final String NETWORK_SPECIFIER_KEY_PEER_ID = "peer_id";
-
- /** @hide */
- public static final String NETWORK_SPECIFIER_KEY_PEER_MAC = "peer_mac";
-
- /** @hide */
- public static final String NETWORK_SPECIFIER_KEY_PMK = "pmk";
-
- /** @hide */
- public static final String NETWORK_SPECIFIER_KEY_PASSPHRASE = "passphrase";
-
- /**
* Broadcast intent action to indicate that the state of Wi-Fi Aware availability has changed.
* Use the {@link #isAvailable()} to query the current status.
* This broadcast is <b>not</b> sticky, use the {@link #isAvailable()} API after registering
@@ -483,7 +421,7 @@
}
/** @hide */
- public String createNetworkSpecifier(int clientId, int role, int sessionId,
+ public NetworkSpecifier createNetworkSpecifier(int clientId, int role, int sessionId,
PeerHandle peerHandle, @Nullable byte[] pmk, @Nullable String passphrase) {
if (VDBG) {
Log.v(TAG, "createNetworkSpecifier: role=" + role + ", sessionId=" + sessionId
@@ -492,9 +430,6 @@
+ ", passphrase=" + ((passphrase == null) ? "null" : "non-null"));
}
- int type = (peerHandle == null) ? NETWORK_SPECIFIER_TYPE_IB_ANY_PEER
- : NETWORK_SPECIFIER_TYPE_IB;
-
if (role != WIFI_AWARE_DATA_PATH_ROLE_INITIATOR
&& role != WIFI_AWARE_DATA_PATH_ROLE_RESPONDER) {
throw new IllegalArgumentException(
@@ -509,35 +444,20 @@
}
}
- JSONObject json;
- try {
- json = new JSONObject();
- json.put(NETWORK_SPECIFIER_KEY_TYPE, type);
- json.put(NETWORK_SPECIFIER_KEY_ROLE, role);
- json.put(NETWORK_SPECIFIER_KEY_CLIENT_ID, clientId);
- json.put(NETWORK_SPECIFIER_KEY_SESSION_ID, sessionId);
- if (peerHandle != null) {
- json.put(NETWORK_SPECIFIER_KEY_PEER_ID, peerHandle.peerId);
- }
- if (pmk == null) {
- pmk = new byte[0];
- }
- json.put(NETWORK_SPECIFIER_KEY_PMK,
- Base64.encodeToString(pmk, 0, pmk.length, Base64.DEFAULT));
- if (passphrase == null) {
- passphrase = new String();
- }
- json.put(NETWORK_SPECIFIER_KEY_PASSPHRASE, passphrase);
-
- } catch (JSONException e) {
- return "";
- }
-
- return json.toString();
+ return new WifiAwareNetworkSpecifier(
+ (peerHandle == null) ? WifiAwareNetworkSpecifier.NETWORK_SPECIFIER_TYPE_IB_ANY_PEER
+ : WifiAwareNetworkSpecifier.NETWORK_SPECIFIER_TYPE_IB,
+ role,
+ clientId,
+ sessionId,
+ peerHandle != null ? peerHandle.peerId : 0, // 0 is an invalid peer ID
+ null, // peerMac (not used in this method)
+ pmk,
+ passphrase);
}
/** @hide */
- public String createNetworkSpecifier(int clientId, @DataPathRole int role,
+ public NetworkSpecifier createNetworkSpecifier(int clientId, @DataPathRole int role,
@Nullable byte[] peer, @Nullable byte[] pmk, @Nullable String passphrase) {
if (VDBG) {
Log.v(TAG, "createNetworkSpecifier: role=" + role
@@ -545,9 +465,6 @@
+ ", passphrase=" + ((passphrase == null) ? "null" : "non-null"));
}
- int type = (peer == null) ?
- NETWORK_SPECIFIER_TYPE_OOB_ANY_PEER : NETWORK_SPECIFIER_TYPE_OOB;
-
if (role != WIFI_AWARE_DATA_PATH_ROLE_INITIATOR
&& role != WIFI_AWARE_DATA_PATH_ROLE_RESPONDER) {
throw new IllegalArgumentException(
@@ -564,29 +481,16 @@
throw new IllegalArgumentException("createNetworkSpecifier: Invalid peer MAC address");
}
- JSONObject json;
- try {
- json = new JSONObject();
- json.put(NETWORK_SPECIFIER_KEY_TYPE, type);
- json.put(NETWORK_SPECIFIER_KEY_ROLE, role);
- json.put(NETWORK_SPECIFIER_KEY_CLIENT_ID, clientId);
- if (peer != null) {
- json.put(NETWORK_SPECIFIER_KEY_PEER_MAC, new String(HexEncoding.encode(peer)));
- }
- if (pmk == null) {
- pmk = new byte[0];
- }
- json.put(NETWORK_SPECIFIER_KEY_PMK,
- Base64.encodeToString(pmk, 0, pmk.length, Base64.DEFAULT));
- if (passphrase == null) {
- passphrase = new String();
- }
- json.put(NETWORK_SPECIFIER_KEY_PASSPHRASE, passphrase);
- } catch (JSONException e) {
- return "";
- }
-
- return json.toString();
+ return new WifiAwareNetworkSpecifier(
+ (peer == null) ? WifiAwareNetworkSpecifier.NETWORK_SPECIFIER_TYPE_OOB_ANY_PEER
+ : WifiAwareNetworkSpecifier.NETWORK_SPECIFIER_TYPE_OOB,
+ role,
+ clientId,
+ 0, // 0 is an invalid session ID
+ 0, // 0 is an invalid peer ID
+ peer,
+ pmk,
+ passphrase);
}
private static class WifiAwareEventCallbackProxy extends IWifiAwareEventCallback.Stub {
diff --git a/wifi/java/android/net/wifi/aware/WifiAwareNetworkSpecifier.java b/wifi/java/android/net/wifi/aware/WifiAwareNetworkSpecifier.java
new file mode 100644
index 0000000..5993480
--- /dev/null
+++ b/wifi/java/android/net/wifi/aware/WifiAwareNetworkSpecifier.java
@@ -0,0 +1,234 @@
+/*
+ * Copyright (C) 2017 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.net.wifi.aware;
+
+import android.net.NetworkSpecifier;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.util.Arrays;
+import java.util.Objects;
+
+/**
+ * Network specifier object used to request a Wi-Fi Aware network. Apps do not create these objects
+ * directly but obtain them using
+ * {@link WifiAwareSession#createNetworkSpecifierOpen(int, byte[])} or
+ * {@link DiscoverySession#createNetworkSpecifierOpen(PeerHandle)} or their secure (Passphrase)
+ * versions.
+ *
+ * @hide
+ */
+public final class WifiAwareNetworkSpecifier extends NetworkSpecifier implements Parcelable {
+ /**
+ * TYPE: in band, specific peer: role, client_id, session_id, peer_id, pmk/passphrase optional
+ * @hide
+ */
+ public static final int NETWORK_SPECIFIER_TYPE_IB = 0;
+
+ /**
+ * TYPE: in band, any peer: role, client_id, session_id, pmk/passphrase optional
+ * [only permitted for RESPONDER]
+ * @hide
+ */
+ public static final int NETWORK_SPECIFIER_TYPE_IB_ANY_PEER = 1;
+
+ /**
+ * TYPE: out-of-band: role, client_id, peer_mac, pmk/passphrase optional
+ * @hide
+ */
+ public static final int NETWORK_SPECIFIER_TYPE_OOB = 2;
+
+ /**
+ * TYPE: out-of-band, any peer: role, client_id, pmk/passphrase optional
+ * [only permitted for RESPONDER]
+ * @hide
+ */
+ public static final int NETWORK_SPECIFIER_TYPE_OOB_ANY_PEER = 3;
+
+ /** @hide */
+ public static final int NETWORK_SPECIFIER_TYPE_MAX_VALID = NETWORK_SPECIFIER_TYPE_OOB_ANY_PEER;
+
+ /**
+ * One of the NETWORK_SPECIFIER_TYPE_* constants. The type of the network specifier object.
+ * @hide
+ */
+ public final int type;
+
+ /**
+ * The role of the device: WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_INITIATOR or
+ * WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_RESPONDER.
+ * @hide
+ */
+ public final int role;
+
+ /**
+ * The client ID of the device.
+ * @hide
+ */
+ public final int clientId;
+
+ /**
+ * The session ID in which context to request a data-path. Only relevant for IB requests.
+ * @hide
+ */
+ public final int sessionId;
+
+ /**
+ * The peer ID of the device which the data-path should be connected to. Only relevant for
+ * IB requests (i.e. not IB_ANY_PEER or OOB*).
+ * @hide
+ */
+ public final int peerId;
+
+ /**
+ * The peer MAC address of the device which the data-path should be connected to. Only relevant
+ * for OB requests (i.e. not OOB_ANY_PEER or IB*).
+ * @hide
+ */
+ public final byte[] peerMac;
+
+ /**
+ * The PMK of the requested data-path. Can be null. Only one or none of pmk or passphrase should
+ * be specified.
+ * @hide
+ */
+ public final byte[] pmk;
+
+ /**
+ * The Passphrase of the requested data-path. Can be null. Only one or none of the pmk or
+ * passphrase should be specified.
+ * @hide
+ */
+ public final String passphrase;
+
+ /** @hide */
+ public WifiAwareNetworkSpecifier(int type, int role, int clientId, int sessionId, int peerId,
+ byte[] peerMac, byte[] pmk, String passphrase) {
+ this.type = type;
+ this.role = role;
+ this.clientId = clientId;
+ this.sessionId = sessionId;
+ this.peerId = peerId;
+ this.peerMac = peerMac;
+ this.pmk = pmk;
+ this.passphrase = passphrase;
+ }
+
+ public static final Creator<WifiAwareNetworkSpecifier> CREATOR =
+ new Creator<WifiAwareNetworkSpecifier>() {
+ @Override
+ public WifiAwareNetworkSpecifier createFromParcel(Parcel in) {
+ return new WifiAwareNetworkSpecifier(
+ in.readInt(), // type
+ in.readInt(), // role
+ in.readInt(), // clientId
+ in.readInt(), // sessionId
+ in.readInt(), // peerId
+ in.createByteArray(), // peerMac
+ in.createByteArray(), // pmk
+ in.readString()); // passphrase
+ }
+
+ @Override
+ public WifiAwareNetworkSpecifier[] newArray(int size) {
+ return new WifiAwareNetworkSpecifier[size];
+ }
+ };
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeInt(type);
+ dest.writeInt(role);
+ dest.writeInt(clientId);
+ dest.writeInt(sessionId);
+ dest.writeInt(peerId);
+ dest.writeByteArray(peerMac);
+ dest.writeByteArray(pmk);
+ dest.writeString(passphrase);
+ }
+
+ /** @hide */
+ @Override
+ public boolean satisfiedBy(NetworkSpecifier other) {
+ // MatchAllNetworkSpecifier is taken care in NetworkCapabilities#satisfiedBySpecifier.
+ return equals(other);
+ }
+
+ /** @hide */
+ @Override
+ public int hashCode() {
+ int result = 17;
+
+ result = 31 * result + type;
+ result = 31 * result + role;
+ result = 31 * result + clientId;
+ result = 31 * result + sessionId;
+ result = 31 * result + peerId;
+ result = 31 * result + Arrays.hashCode(peerMac);
+ result = 31 * result + Arrays.hashCode(pmk);
+ result = 31 * result + Objects.hashCode(passphrase);
+
+ return result;
+ }
+
+ /** @hide */
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+
+ if (!(obj instanceof WifiAwareNetworkSpecifier)) {
+ return false;
+ }
+
+ WifiAwareNetworkSpecifier lhs = (WifiAwareNetworkSpecifier) obj;
+
+ return type == lhs.type
+ && role == lhs.role
+ && clientId == lhs.clientId
+ && sessionId == lhs.sessionId
+ && peerId == lhs.peerId
+ && Arrays.equals(peerMac, lhs.peerMac)
+ && Arrays.equals(pmk, lhs.pmk)
+ && Objects.equals(passphrase, lhs.passphrase);
+ }
+
+ /** @hide */
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder("WifiAwareNetworkSpecifier [");
+ sb.append("type=").append(type)
+ .append(", role=").append(role)
+ .append(", clientId=").append(clientId)
+ .append(", sessionId=").append(sessionId)
+ .append(", peerId=").append(peerId)
+ // masking potential PII (although low impact information)
+ .append(", peerMac=").append((peerMac == null) ? "<null>" : "<non-null>")
+ // masking PII
+ .append(", pmk=").append((pmk == null) ? "<null>" : "<non-null>")
+ // masking PII
+ .append(", passphrase=").append((passphrase == null) ? "<null>" : "<non-null>")
+ .append("]");
+ return sb.toString();
+ }
+}
diff --git a/wifi/java/android/net/wifi/aware/WifiAwareSession.java b/wifi/java/android/net/wifi/aware/WifiAwareSession.java
index 895defb..ac3a6bb 100644
--- a/wifi/java/android/net/wifi/aware/WifiAwareSession.java
+++ b/wifi/java/android/net/wifi/aware/WifiAwareSession.java
@@ -19,6 +19,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
+import android.net.NetworkSpecifier;
import android.os.Binder;
import android.os.Handler;
import android.os.Looper;
@@ -184,8 +185,8 @@
}
/**
- * Create a {@link android.net.NetworkRequest.Builder#setNetworkSpecifier(String)} for an
- * unencrypted WiFi Aware connection (link) to the specified peer. The
+ * Create a {@link android.net.NetworkRequest.Builder#setNetworkSpecifier(NetworkSpecifier)} for
+ * an unencrypted WiFi Aware connection (link) to the specified peer. The
* {@link android.net.NetworkRequest.Builder#addTransportType(int)} should be set to
* {@link android.net.NetworkCapabilities#TRANSPORT_WIFI_AWARE}.
* <p>
@@ -205,29 +206,29 @@
* peer. A RESPONDER may specify a {@code null} - indicating that it will accept
* connection requests from any device.
*
- * @return A string to be used to construct
- * {@link android.net.NetworkRequest.Builder#setNetworkSpecifier(String)} to pass to
+ * @return A {@link NetworkSpecifier} to be used to construct
+ * {@link android.net.NetworkRequest.Builder#setNetworkSpecifier(NetworkSpecifier)} to pass to
* {@link android.net.ConnectivityManager#requestNetwork(android.net.NetworkRequest,
* android.net.ConnectivityManager.NetworkCallback)}
* [or other varieties of that API].
*/
- public String createNetworkSpecifierOpen(@WifiAwareManager.DataPathRole int role,
- @Nullable byte[] peer) {
+ public NetworkSpecifier createNetworkSpecifierOpen(
+ @WifiAwareManager.DataPathRole int role, @Nullable byte[] peer) {
WifiAwareManager mgr = mMgr.get();
if (mgr == null) {
Log.e(TAG, "createNetworkSpecifierOpen: called post GC on WifiAwareManager");
- return "";
+ return null;
}
if (mTerminated) {
Log.e(TAG, "createNetworkSpecifierOpen: called after termination");
- return "";
+ return null;
}
return mgr.createNetworkSpecifier(mClientId, role, peer, null, null);
}
/**
- * Create a {@link android.net.NetworkRequest.Builder#setNetworkSpecifier(String)} for an
- * encrypted WiFi Aware connection (link) to the specified peer. The
+ * Create a {@link android.net.NetworkRequest.Builder#setNetworkSpecifier(NetworkSpecifier)} for
+ * an encrypted WiFi Aware connection (link) to the specified peer. The
* {@link android.net.NetworkRequest.Builder#addTransportType(int)} should be set to
* {@link android.net.NetworkCapabilities#TRANSPORT_WIFI_AWARE}.
* <p>
@@ -247,22 +248,23 @@
* the passphrase. Use {@link #createNetworkSpecifierOpen(int, byte[])} to
* specify an open (unencrypted) link.
*
- * @return A string to be used to construct
- * {@link android.net.NetworkRequest.Builder#setNetworkSpecifier(String)} to pass to
+ * @return A {@link NetworkSpecifier} to be used to construct
+ * {@link android.net.NetworkRequest.Builder#setNetworkSpecifier(NetworkSpecifier)} to pass to
* {@link android.net.ConnectivityManager#requestNetwork(android.net.NetworkRequest,
* android.net.ConnectivityManager.NetworkCallback)}
* [or other varieties of that API].
*/
- public String createNetworkSpecifierPassphrase(@WifiAwareManager.DataPathRole int role,
- @Nullable byte[] peer, @NonNull String passphrase) {
+ public NetworkSpecifier createNetworkSpecifierPassphrase(
+ @WifiAwareManager.DataPathRole int role, @Nullable byte[] peer,
+ @NonNull String passphrase) {
WifiAwareManager mgr = mMgr.get();
if (mgr == null) {
Log.e(TAG, "createNetworkSpecifierPassphrase: called post GC on WifiAwareManager");
- return "";
+ return null;
}
if (mTerminated) {
Log.e(TAG, "createNetworkSpecifierPassphrase: called after termination");
- return "";
+ return null;
}
if (passphrase == null || passphrase.length() == 0) {
throw new IllegalArgumentException("Passphrase must not be null or empty");
@@ -271,8 +273,8 @@
}
/**
- * Create a {@link android.net.NetworkRequest.Builder#setNetworkSpecifier(String)} for an
- * encrypted WiFi Aware connection (link) to the specified peer. The
+ * Create a {@link android.net.NetworkRequest.Builder#setNetworkSpecifier(NetworkSpecifier)} for
+ * an encrypted WiFi Aware connection (link) to the specified peer. The
* {@link android.net.NetworkRequest.Builder#addTransportType(int)} should be set to
* {@link android.net.NetworkCapabilities#TRANSPORT_WIFI_AWARE}.
* <p>
@@ -294,8 +296,8 @@
* Passphrase or {@link #createNetworkSpecifierOpen(int, byte[])} to specify an
* open (unencrypted) link.
*
- * @return A string to be used to construct
- * {@link android.net.NetworkRequest.Builder#setNetworkSpecifier(String)} to pass to
+ * @return A {@link NetworkSpecifier} to be used to construct
+ * {@link android.net.NetworkRequest.Builder#setNetworkSpecifier(NetworkSpecifier)} to pass to
* {@link android.net.ConnectivityManager#requestNetwork(android.net.NetworkRequest,
* android.net.ConnectivityManager.NetworkCallback)}
* [or other varieties of that API].
@@ -303,16 +305,16 @@
* @hide
*/
@SystemApi
- public String createNetworkSpecifierPmk(@WifiAwareManager.DataPathRole int role,
- @Nullable byte[] peer, @NonNull byte[] pmk) {
+ public NetworkSpecifier createNetworkSpecifierPmk(
+ @WifiAwareManager.DataPathRole int role, @Nullable byte[] peer, @NonNull byte[] pmk) {
WifiAwareManager mgr = mMgr.get();
if (mgr == null) {
Log.e(TAG, "createNetworkSpecifierPmk: called post GC on WifiAwareManager");
- return "";
+ return null;
}
if (mTerminated) {
Log.e(TAG, "createNetworkSpecifierPmk: called after termination");
- return "";
+ return null;
}
if (pmk == null || pmk.length == 0) {
throw new IllegalArgumentException("PMK must not be null or empty");
diff --git a/wifi/tests/src/android/net/wifi/aware/WifiAwareManagerTest.java b/wifi/tests/src/android/net/wifi/aware/WifiAwareManagerTest.java
index 830db22..72a6a7a 100644
--- a/wifi/tests/src/android/net/wifi/aware/WifiAwareManagerTest.java
+++ b/wifi/tests/src/android/net/wifi/aware/WifiAwareManagerTest.java
@@ -34,11 +34,9 @@
import android.os.Parcel;
import android.os.test.TestLooper;
import android.test.suitebuilder.annotation.SmallTest;
-import android.util.Base64;
import libcore.util.HexEncoding;
-import org.json.JSONObject;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
@@ -959,8 +957,6 @@
final ConfigRequest configRequest = new ConfigRequest.Builder().build();
final PublishConfig publishConfig = new PublishConfig.Builder().build();
- String pmkB64 = Base64.encodeToString(pmk, Base64.DEFAULT);
-
ArgumentCaptor<WifiAwareSession> sessionCaptor = ArgumentCaptor.forClass(
WifiAwareSession.class);
ArgumentCaptor<IWifiAwareEventCallback> clientProxyCallback = ArgumentCaptor
@@ -991,51 +987,37 @@
inOrder.verify(mockSessionCallback).onPublishStarted(publishSession.capture());
// (3) request an open (unencrypted) network specifier from the session
- String networkSpecifier = publishSession.getValue().createNetworkSpecifierOpen(peerHandle);
+ WifiAwareNetworkSpecifier ns =
+ (WifiAwareNetworkSpecifier) publishSession.getValue().createNetworkSpecifierOpen(
+ peerHandle);
// validate format
- JSONObject jsonObject = new JSONObject(networkSpecifier);
- collector.checkThat("role", role,
- equalTo(jsonObject.getInt(WifiAwareManager.NETWORK_SPECIFIER_KEY_ROLE)));
- collector.checkThat("client_id", clientId,
- equalTo(jsonObject.getInt(WifiAwareManager.NETWORK_SPECIFIER_KEY_CLIENT_ID)));
- collector.checkThat("session_id", sessionId,
- equalTo(jsonObject.getInt(WifiAwareManager.NETWORK_SPECIFIER_KEY_SESSION_ID)));
- collector.checkThat("peer_id", peerHandle.peerId,
- equalTo(jsonObject.getInt(WifiAwareManager.NETWORK_SPECIFIER_KEY_PEER_ID)));
+ collector.checkThat("role", role, equalTo(ns.role));
+ collector.checkThat("client_id", clientId, equalTo(ns.clientId));
+ collector.checkThat("session_id", sessionId, equalTo(ns.sessionId));
+ collector.checkThat("peer_id", peerHandle.peerId, equalTo(ns.peerId));
// (4) request an encrypted (PMK) network specifier from the session
- networkSpecifier = publishSession.getValue().createNetworkSpecifierPmk(peerHandle, pmk);
+ ns = (WifiAwareNetworkSpecifier) publishSession.getValue().createNetworkSpecifierPmk(
+ peerHandle, pmk);
// validate format
- jsonObject = new JSONObject(networkSpecifier);
- collector.checkThat("role", role,
- equalTo(jsonObject.getInt(WifiAwareManager.NETWORK_SPECIFIER_KEY_ROLE)));
- collector.checkThat("client_id", clientId,
- equalTo(jsonObject.getInt(WifiAwareManager.NETWORK_SPECIFIER_KEY_CLIENT_ID)));
- collector.checkThat("session_id", sessionId,
- equalTo(jsonObject.getInt(WifiAwareManager.NETWORK_SPECIFIER_KEY_SESSION_ID)));
- collector.checkThat("peer_id", peerHandle.peerId,
- equalTo(jsonObject.getInt(WifiAwareManager.NETWORK_SPECIFIER_KEY_PEER_ID)));
- collector.checkThat("pmk", pmkB64 ,
- equalTo(jsonObject.getString(WifiAwareManager.NETWORK_SPECIFIER_KEY_PMK)));
+ collector.checkThat("role", role, equalTo(ns.role));
+ collector.checkThat("client_id", clientId, equalTo(ns.clientId));
+ collector.checkThat("session_id", sessionId, equalTo(ns.sessionId));
+ collector.checkThat("peer_id", peerHandle.peerId, equalTo(ns.peerId));
+ collector.checkThat("pmk", pmk , equalTo(ns.pmk));
// (5) request an encrypted (Passphrase) network specifier from the session
- networkSpecifier = publishSession.getValue().createNetworkSpecifierPassphrase(peerHandle,
- passphrase);
+ ns = (WifiAwareNetworkSpecifier) publishSession.getValue().createNetworkSpecifierPassphrase(
+ peerHandle, passphrase);
// validate format
- jsonObject = new JSONObject(networkSpecifier);
- collector.checkThat("role", role,
- equalTo(jsonObject.getInt(WifiAwareManager.NETWORK_SPECIFIER_KEY_ROLE)));
- collector.checkThat("client_id", clientId,
- equalTo(jsonObject.getInt(WifiAwareManager.NETWORK_SPECIFIER_KEY_CLIENT_ID)));
- collector.checkThat("session_id", sessionId,
- equalTo(jsonObject.getInt(WifiAwareManager.NETWORK_SPECIFIER_KEY_SESSION_ID)));
- collector.checkThat("peer_id", peerHandle.peerId,
- equalTo(jsonObject.getInt(WifiAwareManager.NETWORK_SPECIFIER_KEY_PEER_ID)));
- collector.checkThat("passphrase", passphrase,
- equalTo(jsonObject.getString(WifiAwareManager.NETWORK_SPECIFIER_KEY_PASSPHRASE)));
+ collector.checkThat("role", role, equalTo(ns.role));
+ collector.checkThat("client_id", clientId, equalTo(ns.clientId));
+ collector.checkThat("session_id", sessionId, equalTo(ns.sessionId));
+ collector.checkThat("peer_id", peerHandle.peerId, equalTo(ns.peerId));
+ collector.checkThat("passphrase", passphrase, equalTo(ns.passphrase));
verifyNoMoreInteractions(mockCallback, mockSessionCallback, mockAwareService,
mockPublishSession, mockRttListener);
@@ -1054,8 +1036,6 @@
final byte[] pmk = "Some arbitrary pmk data".getBytes();
final String passphrase = "A really bad password";
- String pmkB64 = Base64.encodeToString(pmk, Base64.DEFAULT);
-
ArgumentCaptor<WifiAwareSession> sessionCaptor = ArgumentCaptor.forClass(
WifiAwareSession.class);
ArgumentCaptor<IWifiAwareEventCallback> clientProxyCallback = ArgumentCaptor
@@ -1074,47 +1054,32 @@
WifiAwareSession session = sessionCaptor.getValue();
// (2) request an open (unencrypted) direct network specifier
- String networkSpecifier = session.createNetworkSpecifierOpen(role, someMac);
+ WifiAwareNetworkSpecifier ns =
+ (WifiAwareNetworkSpecifier) session.createNetworkSpecifierOpen(role, someMac);
// validate format
- JSONObject jsonObject = new JSONObject(networkSpecifier);
- collector.checkThat("role", role,
- equalTo(jsonObject.getInt(WifiAwareManager.NETWORK_SPECIFIER_KEY_ROLE)));
- collector.checkThat("client_id", clientId,
- equalTo(jsonObject.getInt(WifiAwareManager.NETWORK_SPECIFIER_KEY_CLIENT_ID)));
- collector.checkThat("peer_mac", someMac, equalTo(HexEncoding.decode(
- jsonObject.getString(WifiAwareManager.NETWORK_SPECIFIER_KEY_PEER_MAC).toCharArray(),
- false)));
+ collector.checkThat("role", role, equalTo(ns.role));
+ collector.checkThat("client_id", clientId, equalTo(ns.clientId));
+ collector.checkThat("peer_mac", someMac, equalTo(ns.peerMac));
// (3) request an encrypted (PMK) direct network specifier
- networkSpecifier = session.createNetworkSpecifierPmk(role, someMac, pmk);
+ ns = (WifiAwareNetworkSpecifier) session.createNetworkSpecifierPmk(role, someMac, pmk);
// validate format
- jsonObject = new JSONObject(networkSpecifier);
- collector.checkThat("role", role,
- equalTo(jsonObject.getInt(WifiAwareManager.NETWORK_SPECIFIER_KEY_ROLE)));
- collector.checkThat("client_id", clientId,
- equalTo(jsonObject.getInt(WifiAwareManager.NETWORK_SPECIFIER_KEY_CLIENT_ID)));
- collector.checkThat("peer_mac", someMac, equalTo(HexEncoding.decode(
- jsonObject.getString(WifiAwareManager.NETWORK_SPECIFIER_KEY_PEER_MAC).toCharArray(),
- false)));
- collector.checkThat("pmk", pmkB64,
- equalTo(jsonObject.getString(WifiAwareManager.NETWORK_SPECIFIER_KEY_PMK)));
+ collector.checkThat("role", role, equalTo(ns.role));
+ collector.checkThat("client_id", clientId, equalTo(ns.clientId));
+ collector.checkThat("peer_mac", someMac, equalTo(ns.peerMac));
+ collector.checkThat("pmk", pmk, equalTo(ns.pmk));
// (4) request an encrypted (Passphrase) direct network specifier
- networkSpecifier = session.createNetworkSpecifierPassphrase(role, someMac, passphrase);
+ ns = (WifiAwareNetworkSpecifier) session.createNetworkSpecifierPassphrase(role, someMac,
+ passphrase);
// validate format
- jsonObject = new JSONObject(networkSpecifier);
- collector.checkThat("role", role,
- equalTo(jsonObject.getInt(WifiAwareManager.NETWORK_SPECIFIER_KEY_ROLE)));
- collector.checkThat("client_id", clientId,
- equalTo(jsonObject.getInt(WifiAwareManager.NETWORK_SPECIFIER_KEY_CLIENT_ID)));
- collector.checkThat("peer_mac", someMac, equalTo(HexEncoding.decode(
- jsonObject.getString(WifiAwareManager.NETWORK_SPECIFIER_KEY_PEER_MAC).toCharArray(),
- false)));
- collector.checkThat("passphrase", passphrase,
- equalTo(jsonObject.getString(WifiAwareManager.NETWORK_SPECIFIER_KEY_PASSPHRASE)));
+ collector.checkThat("role", role, equalTo(ns.role));
+ collector.checkThat("client_id", clientId, equalTo(ns.clientId));
+ collector.checkThat("peer_mac", someMac, equalTo(ns.peerMac));
+ collector.checkThat("passphrase", passphrase, equalTo(ns.passphrase));
verifyNoMoreInteractions(mockCallback, mockSessionCallback, mockAwareService,
mockPublishSession, mockRttListener);