Merge "IMS: UT ServiceClass" into lmp-mr1-wfc-dev
automerge: d3b6cbe
* commit 'd3b6cbe172f429038894b1fae09fb72e8a646519':
IMS: UT ServiceClass
diff --git a/Android.mk b/Android.mk
index 3b1991c..81113f7 100644
--- a/Android.mk
+++ b/Android.mk
@@ -386,6 +386,7 @@
wifi/java/android/net/wifi/p2p/IWifiP2pManager.aidl \
wifi/java/android/net/wifi/IWifiScanner.aidl \
wifi/java/android/net/wifi/IRttManager.aidl \
+ wifi/java/android/net/wifi/passpoint/IWifiPasspointManager.aidl \
packages/services/PacProcessor/com/android/net/IProxyService.aidl \
packages/services/Proxy/com/android/net/IProxyCallback.aidl \
packages/services/Proxy/com/android/net/IProxyPortListener.aidl \
diff --git a/api/current.txt b/api/current.txt
index 35423fd..98b15c7 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -6662,6 +6662,7 @@
field public static final int SCAN_MODE_BALANCED = 1; // 0x1
field public static final int SCAN_MODE_LOW_LATENCY = 2; // 0x2
field public static final int SCAN_MODE_LOW_POWER = 0; // 0x0
+ field public static final int SCAN_MODE_OPPORTUNISTIC = -1; // 0xffffffff
}
public static final class ScanSettings.Builder {
@@ -10785,6 +10786,8 @@
public class ImageFormat {
ctor public ImageFormat();
method public static int getBitsPerPixel(int);
+ field public static final int DEPTH16 = 1144402265; // 0x44363159
+ field public static final int DEPTH_POINT_CLOUD = 257; // 0x101
field public static final int JPEG = 256; // 0x100
field public static final int NV16 = 16; // 0x10
field public static final int NV21 = 17; // 0x11
@@ -12558,6 +12561,8 @@
field public static final int CAMERA_DISABLED = 1; // 0x1
field public static final int CAMERA_DISCONNECTED = 2; // 0x2
field public static final int CAMERA_ERROR = 3; // 0x3
+ field public static final int CAMERA_IN_USE = 4; // 0x4
+ field public static final int MAX_CAMERAS_IN_USE = 5; // 0x5
}
public abstract class CameraCaptureSession implements java.lang.AutoCloseable {
@@ -12601,11 +12606,14 @@
field public static final android.hardware.camera2.CameraCharacteristics.Key<android.util.Range<java.lang.Integer>[]> CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES;
field public static final android.hardware.camera2.CameraCharacteristics.Key<android.util.Range<java.lang.Integer>> CONTROL_AE_COMPENSATION_RANGE;
field public static final android.hardware.camera2.CameraCharacteristics.Key<android.util.Rational> CONTROL_AE_COMPENSATION_STEP;
+ field public static final android.hardware.camera2.CameraCharacteristics.Key<java.lang.Boolean> CONTROL_AE_LOCK_AVAILABLE;
field public static final android.hardware.camera2.CameraCharacteristics.Key<int[]> CONTROL_AF_AVAILABLE_MODES;
field public static final android.hardware.camera2.CameraCharacteristics.Key<int[]> CONTROL_AVAILABLE_EFFECTS;
+ field public static final android.hardware.camera2.CameraCharacteristics.Key<int[]> CONTROL_AVAILABLE_MODES;
field public static final android.hardware.camera2.CameraCharacteristics.Key<int[]> CONTROL_AVAILABLE_SCENE_MODES;
field public static final android.hardware.camera2.CameraCharacteristics.Key<int[]> CONTROL_AVAILABLE_VIDEO_STABILIZATION_MODES;
field public static final android.hardware.camera2.CameraCharacteristics.Key<int[]> CONTROL_AWB_AVAILABLE_MODES;
+ field public static final android.hardware.camera2.CameraCharacteristics.Key<java.lang.Boolean> CONTROL_AWB_LOCK_AVAILABLE;
field public static final android.hardware.camera2.CameraCharacteristics.Key<java.lang.Integer> CONTROL_MAX_REGIONS_AE;
field public static final android.hardware.camera2.CameraCharacteristics.Key<java.lang.Integer> CONTROL_MAX_REGIONS_AF;
field public static final android.hardware.camera2.CameraCharacteristics.Key<java.lang.Integer> CONTROL_MAX_REGIONS_AWB;
@@ -12622,8 +12630,13 @@
field public static final android.hardware.camera2.CameraCharacteristics.Key<java.lang.Integer> LENS_INFO_FOCUS_DISTANCE_CALIBRATION;
field public static final android.hardware.camera2.CameraCharacteristics.Key<java.lang.Float> LENS_INFO_HYPERFOCAL_DISTANCE;
field public static final android.hardware.camera2.CameraCharacteristics.Key<java.lang.Float> LENS_INFO_MINIMUM_FOCUS_DISTANCE;
+ field public static final android.hardware.camera2.CameraCharacteristics.Key<float[]> LENS_INTRINSIC_CALIBRATION;
+ field public static final android.hardware.camera2.CameraCharacteristics.Key<float[]> LENS_POSE_ROTATION;
+ field public static final android.hardware.camera2.CameraCharacteristics.Key<float[]> LENS_POSE_TRANSLATION;
+ field public static final android.hardware.camera2.CameraCharacteristics.Key<float[]> LENS_RADIAL_DISTORTION;
field public static final android.hardware.camera2.CameraCharacteristics.Key<int[]> NOISE_REDUCTION_AVAILABLE_NOISE_REDUCTION_MODES;
field public static final android.hardware.camera2.CameraCharacteristics.Key<int[]> REQUEST_AVAILABLE_CAPABILITIES;
+ field public static final android.hardware.camera2.CameraCharacteristics.Key<java.lang.Integer> REQUEST_MAX_NUM_INPUT_STREAMS;
field public static final android.hardware.camera2.CameraCharacteristics.Key<java.lang.Integer> REQUEST_MAX_NUM_OUTPUT_PROC;
field public static final android.hardware.camera2.CameraCharacteristics.Key<java.lang.Integer> REQUEST_MAX_NUM_OUTPUT_PROC_STALLING;
field public static final android.hardware.camera2.CameraCharacteristics.Key<java.lang.Integer> REQUEST_MAX_NUM_OUTPUT_RAW;
@@ -12643,6 +12656,7 @@
field public static final android.hardware.camera2.CameraCharacteristics.Key<android.graphics.Rect> SENSOR_INFO_ACTIVE_ARRAY_SIZE;
field public static final android.hardware.camera2.CameraCharacteristics.Key<java.lang.Integer> SENSOR_INFO_COLOR_FILTER_ARRANGEMENT;
field public static final android.hardware.camera2.CameraCharacteristics.Key<android.util.Range<java.lang.Long>> SENSOR_INFO_EXPOSURE_TIME_RANGE;
+ field public static final android.hardware.camera2.CameraCharacteristics.Key<java.lang.Boolean> SENSOR_INFO_LENS_SHADING_APPLIED;
field public static final android.hardware.camera2.CameraCharacteristics.Key<java.lang.Long> SENSOR_INFO_MAX_FRAME_DURATION;
field public static final android.hardware.camera2.CameraCharacteristics.Key<android.util.SizeF> SENSOR_INFO_PHYSICAL_SIZE;
field public static final android.hardware.camera2.CameraCharacteristics.Key<android.util.Size> SENSOR_INFO_PIXEL_ARRAY_SIZE;
@@ -12653,8 +12667,10 @@
field public static final android.hardware.camera2.CameraCharacteristics.Key<java.lang.Integer> SENSOR_ORIENTATION;
field public static final android.hardware.camera2.CameraCharacteristics.Key<java.lang.Integer> SENSOR_REFERENCE_ILLUMINANT1;
field public static final android.hardware.camera2.CameraCharacteristics.Key<java.lang.Byte> SENSOR_REFERENCE_ILLUMINANT2;
+ field public static final android.hardware.camera2.CameraCharacteristics.Key<int[]> SHADING_AVAILABLE_MODES;
field public static final android.hardware.camera2.CameraCharacteristics.Key<int[]> STATISTICS_INFO_AVAILABLE_FACE_DETECT_MODES;
field public static final android.hardware.camera2.CameraCharacteristics.Key<boolean[]> STATISTICS_INFO_AVAILABLE_HOT_PIXEL_MAP_MODES;
+ field public static final android.hardware.camera2.CameraCharacteristics.Key<byte[]> STATISTICS_INFO_AVAILABLE_LENS_SHADING_MAP_MODES;
field public static final android.hardware.camera2.CameraCharacteristics.Key<java.lang.Integer> STATISTICS_INFO_MAX_FACE_COUNT;
field public static final android.hardware.camera2.CameraCharacteristics.Key<java.lang.Integer> SYNC_MAX_LATENCY;
field public static final android.hardware.camera2.CameraCharacteristics.Key<int[]> TONEMAP_AVAILABLE_TONE_MAP_MODES;
@@ -12698,7 +12714,10 @@
method public java.lang.String[] getCameraIdList() throws android.hardware.camera2.CameraAccessException;
method public void openCamera(java.lang.String, android.hardware.camera2.CameraDevice.StateCallback, android.os.Handler) throws android.hardware.camera2.CameraAccessException;
method public void registerAvailabilityCallback(android.hardware.camera2.CameraManager.AvailabilityCallback, android.os.Handler);
+ method public void registerTorchCallback(android.hardware.camera2.CameraManager.TorchCallback, android.os.Handler);
+ method public void setTorchMode(java.lang.String, boolean) throws android.hardware.camera2.CameraAccessException;
method public void unregisterAvailabilityCallback(android.hardware.camera2.CameraManager.AvailabilityCallback);
+ method public void unregisterTorchCallback(android.hardware.camera2.CameraManager.TorchCallback);
}
public static abstract class CameraManager.AvailabilityCallback {
@@ -12707,6 +12726,12 @@
method public void onCameraUnavailable(java.lang.String);
}
+ public static abstract class CameraManager.TorchCallback {
+ ctor public CameraManager.TorchCallback();
+ method public void onTorchModeChanged(java.lang.String, boolean);
+ method public void onTorchModeUnavailable(java.lang.String);
+ }
+
public abstract class CameraMetadata {
method public java.util.List<TKey> getKeys();
field public static final int COLOR_CORRECTION_ABERRATION_MODE_FAST = 1; // 0x1
@@ -12724,6 +12749,7 @@
field public static final int CONTROL_AE_MODE_ON_ALWAYS_FLASH = 3; // 0x3
field public static final int CONTROL_AE_MODE_ON_AUTO_FLASH = 2; // 0x2
field public static final int CONTROL_AE_MODE_ON_AUTO_FLASH_REDEYE = 4; // 0x4
+ field public static final int CONTROL_AE_PRECAPTURE_TRIGGER_CANCEL = 2; // 0x2
field public static final int CONTROL_AE_PRECAPTURE_TRIGGER_IDLE = 0; // 0x0
field public static final int CONTROL_AE_PRECAPTURE_TRIGGER_START = 1; // 0x1
field public static final int CONTROL_AE_STATE_CONVERGED = 2; // 0x2
@@ -12820,6 +12846,7 @@
field public static final int INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY = 2; // 0x2
field public static final int INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED = 0; // 0x0
field public static final int LENS_FACING_BACK = 1; // 0x1
+ field public static final int LENS_FACING_EXTERNAL = 2; // 0x2
field public static final int LENS_FACING_FRONT = 0; // 0x0
field public static final int LENS_INFO_FOCUS_DISTANCE_CALIBRATION_APPROXIMATE = 1; // 0x1
field public static final int LENS_INFO_FOCUS_DISTANCE_CALIBRATION_CALIBRATED = 2; // 0x2
@@ -12830,13 +12857,16 @@
field public static final int LENS_STATE_STATIONARY = 0; // 0x0
field public static final int NOISE_REDUCTION_MODE_FAST = 1; // 0x1
field public static final int NOISE_REDUCTION_MODE_HIGH_QUALITY = 2; // 0x2
+ field public static final int NOISE_REDUCTION_MODE_MINIMAL = 3; // 0x3
field public static final int NOISE_REDUCTION_MODE_OFF = 0; // 0x0
field public static final int REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE = 0; // 0x0
field public static final int REQUEST_AVAILABLE_CAPABILITIES_BURST_CAPTURE = 6; // 0x6
field public static final int REQUEST_AVAILABLE_CAPABILITIES_MANUAL_POST_PROCESSING = 2; // 0x2
field public static final int REQUEST_AVAILABLE_CAPABILITIES_MANUAL_SENSOR = 1; // 0x1
+ field public static final int REQUEST_AVAILABLE_CAPABILITIES_OPAQUE_REPROCESSING = 4; // 0x4
field public static final int REQUEST_AVAILABLE_CAPABILITIES_RAW = 3; // 0x3
field public static final int REQUEST_AVAILABLE_CAPABILITIES_READ_SENSOR_SETTINGS = 5; // 0x5
+ field public static final int REQUEST_AVAILABLE_CAPABILITIES_YUV_REPROCESSING = 7; // 0x7
field public static final int SCALER_CROPPING_TYPE_CENTER_ONLY = 0; // 0x0
field public static final int SCALER_CROPPING_TYPE_FREEFORM = 1; // 0x1
field public static final int SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_BGGR = 3; // 0x3
@@ -12886,7 +12916,11 @@
field public static final int SYNC_MAX_LATENCY_UNKNOWN = -1; // 0xffffffff
field public static final int TONEMAP_MODE_CONTRAST_CURVE = 0; // 0x0
field public static final int TONEMAP_MODE_FAST = 1; // 0x1
+ field public static final int TONEMAP_MODE_GAMMA_VALUE = 3; // 0x3
field public static final int TONEMAP_MODE_HIGH_QUALITY = 2; // 0x2
+ field public static final int TONEMAP_MODE_PRESET_CURVE = 4; // 0x4
+ field public static final int TONEMAP_PRESET_CURVE_REC709 = 1; // 0x1
+ field public static final int TONEMAP_PRESET_CURVE_SRGB = 0; // 0x0
}
public class CaptureFailure {
@@ -12942,6 +12976,7 @@
field public static final android.hardware.camera2.CaptureRequest.Key<java.lang.Float> LENS_FOCUS_DISTANCE;
field public static final android.hardware.camera2.CaptureRequest.Key<java.lang.Integer> LENS_OPTICAL_STABILIZATION_MODE;
field public static final android.hardware.camera2.CaptureRequest.Key<java.lang.Integer> NOISE_REDUCTION_MODE;
+ field public static final android.hardware.camera2.CaptureRequest.Key<java.lang.Float> REPROCESS_EFFECTIVE_EXPOSURE_FACTOR;
field public static final android.hardware.camera2.CaptureRequest.Key<android.graphics.Rect> SCALER_CROP_REGION;
field public static final android.hardware.camera2.CaptureRequest.Key<java.lang.Long> SENSOR_EXPOSURE_TIME;
field public static final android.hardware.camera2.CaptureRequest.Key<java.lang.Long> SENSOR_FRAME_DURATION;
@@ -12953,7 +12988,9 @@
field public static final android.hardware.camera2.CaptureRequest.Key<java.lang.Boolean> STATISTICS_HOT_PIXEL_MAP_MODE;
field public static final android.hardware.camera2.CaptureRequest.Key<java.lang.Integer> STATISTICS_LENS_SHADING_MAP_MODE;
field public static final android.hardware.camera2.CaptureRequest.Key<android.hardware.camera2.params.TonemapCurve> TONEMAP_CURVE;
+ field public static final android.hardware.camera2.CaptureRequest.Key<java.lang.Float> TONEMAP_GAMMA;
field public static final android.hardware.camera2.CaptureRequest.Key<java.lang.Integer> TONEMAP_MODE;
+ field public static final android.hardware.camera2.CaptureRequest.Key<java.lang.Integer> TONEMAP_PRESET_CURVE;
}
public static final class CaptureRequest.Builder {
@@ -13016,9 +13053,14 @@
field public static final android.hardware.camera2.CaptureResult.Key<java.lang.Float> LENS_FOCAL_LENGTH;
field public static final android.hardware.camera2.CaptureResult.Key<java.lang.Float> LENS_FOCUS_DISTANCE;
field public static final android.hardware.camera2.CaptureResult.Key<android.util.Pair<java.lang.Float, java.lang.Float>> LENS_FOCUS_RANGE;
+ field public static final android.hardware.camera2.CaptureResult.Key<float[]> LENS_INTRINSIC_CALIBRATION;
field public static final android.hardware.camera2.CaptureResult.Key<java.lang.Integer> LENS_OPTICAL_STABILIZATION_MODE;
+ field public static final android.hardware.camera2.CaptureResult.Key<float[]> LENS_POSE_ROTATION;
+ field public static final android.hardware.camera2.CaptureResult.Key<float[]> LENS_POSE_TRANSLATION;
+ field public static final android.hardware.camera2.CaptureResult.Key<float[]> LENS_RADIAL_DISTORTION;
field public static final android.hardware.camera2.CaptureResult.Key<java.lang.Integer> LENS_STATE;
field public static final android.hardware.camera2.CaptureResult.Key<java.lang.Integer> NOISE_REDUCTION_MODE;
+ field public static final android.hardware.camera2.CaptureResult.Key<java.lang.Float> REPROCESS_EFFECTIVE_EXPOSURE_FACTOR;
field public static final android.hardware.camera2.CaptureResult.Key<java.lang.Byte> REQUEST_PIPELINE_DEPTH;
field public static final android.hardware.camera2.CaptureResult.Key<android.graphics.Rect> SCALER_CROP_REGION;
field public static final android.hardware.camera2.CaptureResult.Key<java.lang.Long> SENSOR_EXPOSURE_TIME;
@@ -13040,7 +13082,9 @@
field public static final android.hardware.camera2.CaptureResult.Key<java.lang.Integer> STATISTICS_LENS_SHADING_MAP_MODE;
field public static final android.hardware.camera2.CaptureResult.Key<java.lang.Integer> STATISTICS_SCENE_FLICKER;
field public static final android.hardware.camera2.CaptureResult.Key<android.hardware.camera2.params.TonemapCurve> TONEMAP_CURVE;
+ field public static final android.hardware.camera2.CaptureResult.Key<java.lang.Float> TONEMAP_GAMMA;
field public static final android.hardware.camera2.CaptureResult.Key<java.lang.Integer> TONEMAP_MODE;
+ field public static final android.hardware.camera2.CaptureResult.Key<java.lang.Integer> TONEMAP_PRESET_CURVE;
}
public static final class CaptureResult.Key {
@@ -17867,11 +17911,23 @@
method public int describeContents();
method public void writeToParcel(android.os.Parcel, int);
field public java.lang.String BSSID;
+ field public static final int CHANNEL_WIDTH_160MHZ = 3; // 0x3
+ field public static final int CHANNEL_WIDTH_20MHZ = 0; // 0x0
+ field public static final int CHANNEL_WIDTH_40MHZ = 1; // 0x1
+ field public static final int CHANNEL_WIDTH_80MHZ = 2; // 0x2
+ field public static final int CHANNEL_WIDTH_80MHZ_PLUS_MHZ = 4; // 0x4
field public java.lang.String SSID;
field public java.lang.String capabilities;
+ field public int centerFreq0;
+ field public int centerFreq1;
+ field public int channelWidth;
field public int frequency;
+ field public boolean is80211McRTTResponder;
field public int level;
+ field public java.lang.String operatorFriendlyName;
+ field public boolean passpointNetwork;
field public long timestamp;
+ field public java.lang.String venueName;
}
public final class SupplicantState extends java.lang.Enum implements android.os.Parcelable {
@@ -17898,6 +17954,7 @@
public class WifiConfiguration implements android.os.Parcelable {
ctor public WifiConfiguration();
method public int describeContents();
+ method public boolean isPasspoint();
method public void writeToParcel(android.os.Parcel, int);
field public java.lang.String BSSID;
field public java.lang.String FQDN;
@@ -17907,11 +17964,15 @@
field public java.util.BitSet allowedKeyManagement;
field public java.util.BitSet allowedPairwiseCiphers;
field public java.util.BitSet allowedProtocols;
+ field public int apBand;
+ field public int apChannel;
field public android.net.wifi.WifiEnterpriseConfig enterpriseConfig;
field public boolean hiddenSSID;
field public int networkId;
field public java.lang.String preSharedKey;
field public int priority;
+ field public java.lang.String providerFriendlyName;
+ field public java.util.HashSet<java.lang.Long> roamingConsortiumIds;
field public int status;
field public java.lang.String[] wepKeys;
field public int wepTxKeyIndex;
@@ -17969,6 +18030,7 @@
ctor public WifiEnterpriseConfig();
ctor public WifiEnterpriseConfig(android.net.wifi.WifiEnterpriseConfig);
method public int describeContents();
+ method public java.lang.String getAltSubjectMatch();
method public java.lang.String getAnonymousIdentity();
method public java.security.cert.X509Certificate getCaCertificate();
method public java.security.cert.X509Certificate getClientCertificate();
@@ -17976,7 +18038,10 @@
method public java.lang.String getIdentity();
method public java.lang.String getPassword();
method public int getPhase2Method();
- method public java.lang.String getSubjectMatch();
+ method public java.lang.String getPlmn();
+ method public java.lang.String getRealm();
+ method public deprecated java.lang.String getSubjectMatch();
+ method public void setAltSubjectMatch(java.lang.String);
method public void setAnonymousIdentity(java.lang.String);
method public void setCaCertificate(java.security.cert.X509Certificate);
method public void setClientKeyEntry(java.security.PrivateKey, java.security.cert.X509Certificate);
@@ -17984,13 +18049,16 @@
method public void setIdentity(java.lang.String);
method public void setPassword(java.lang.String);
method public void setPhase2Method(int);
- method public void setSubjectMatch(java.lang.String);
+ method public void setPlmn(java.lang.String);
+ method public void setRealm(java.lang.String);
+ method public deprecated void setSubjectMatch(java.lang.String);
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.net.wifi.WifiEnterpriseConfig> CREATOR;
}
public static final class WifiEnterpriseConfig.Eap {
field public static final int AKA = 5; // 0x5
+ field public static final int AKA_PRIME = 6; // 0x6
field public static final int NONE = -1; // 0xffffffff
field public static final int PEAP = 0; // 0x0
field public static final int PWD = 3; // 0x3
@@ -25862,6 +25930,7 @@
public static final class VoicemailContract.Status implements android.provider.BaseColumns {
method public static android.net.Uri buildSourceUri(java.lang.String);
+ method public static void setStatus(android.content.Context, android.telecom.PhoneAccountHandle, int, int, int);
field public static final java.lang.String CONFIGURATION_STATE = "configuration_state";
field public static final int CONFIGURATION_STATE_CAN_BE_CONFIGURED = 2; // 0x2
field public static final int CONFIGURATION_STATE_NOT_CONFIGURED = 1; // 0x1
@@ -25876,6 +25945,8 @@
field public static final int NOTIFICATION_CHANNEL_STATE_MESSAGE_WAITING = 2; // 0x2
field public static final int NOTIFICATION_CHANNEL_STATE_NO_CONNECTION = 1; // 0x1
field public static final int NOTIFICATION_CHANNEL_STATE_OK = 0; // 0x0
+ field public static final java.lang.String PHONE_ACCOUNT_COMPONENT_NAME = "phone_account_component_name";
+ field public static final java.lang.String PHONE_ACCOUNT_ID = "phone_account_id";
field public static final java.lang.String SETTINGS_URI = "settings_uri";
field public static final java.lang.String SOURCE_PACKAGE = "source_package";
field public static final java.lang.String VOICEMAIL_ACCESS_URI = "voicemail_access_uri";
@@ -25883,8 +25954,13 @@
public static final class VoicemailContract.Voicemails implements android.provider.BaseColumns android.provider.OpenableColumns {
method public static android.net.Uri buildSourceUri(java.lang.String);
+ method public static int deleteAll(android.content.Context);
+ method public static android.net.Uri insert(android.content.Context, android.telecom.Voicemail);
+ method public static int insert(android.content.Context, java.util.List<android.telecom.Voicemail>);
field public static final android.net.Uri CONTENT_URI;
field public static final java.lang.String DATE = "date";
+ field public static final java.lang.String DELETED = "deleted";
+ field public static final java.lang.String DIRTY = "dirty";
field public static final java.lang.String DIR_TYPE = "vnd.android.cursor.dir/voicemails";
field public static final java.lang.String DURATION = "duration";
field public static final java.lang.String HAS_CONTENT = "has_content";
@@ -25892,6 +25968,8 @@
field public static final java.lang.String ITEM_TYPE = "vnd.android.cursor.item/voicemail";
field public static final java.lang.String MIME_TYPE = "mime_type";
field public static final java.lang.String NUMBER = "number";
+ field public static final java.lang.String PHONE_ACCOUNT_COMPONENT_NAME = "subscription_component_name";
+ field public static final java.lang.String PHONE_ACCOUNT_ID = "subscription_id";
field public static final java.lang.String SOURCE_DATA = "source_data";
field public static final java.lang.String SOURCE_PACKAGE = "source_package";
field public static final java.lang.String TRANSCRIPTION = "transcription";
@@ -28166,8 +28244,81 @@
package android.telecom {
+ public class AuthenticatorService extends android.app.Service {
+ ctor public AuthenticatorService();
+ method public android.os.IBinder onBind(android.content.Intent);
+ }
+
+ public class AuthenticatorService.Authenticator extends android.accounts.AbstractAccountAuthenticator {
+ ctor public AuthenticatorService.Authenticator(android.content.Context);
+ method public android.os.Bundle addAccount(android.accounts.AccountAuthenticatorResponse, java.lang.String, java.lang.String, java.lang.String[], android.os.Bundle) throws android.accounts.NetworkErrorException;
+ method public android.os.Bundle confirmCredentials(android.accounts.AccountAuthenticatorResponse, android.accounts.Account, android.os.Bundle) throws android.accounts.NetworkErrorException;
+ method public android.os.Bundle editProperties(android.accounts.AccountAuthenticatorResponse, java.lang.String);
+ method public android.os.Bundle getAuthToken(android.accounts.AccountAuthenticatorResponse, android.accounts.Account, java.lang.String, android.os.Bundle) throws android.accounts.NetworkErrorException;
+ method public java.lang.String getAuthTokenLabel(java.lang.String);
+ method public android.os.Bundle hasFeatures(android.accounts.AccountAuthenticatorResponse, android.accounts.Account, java.lang.String[]) throws android.accounts.NetworkErrorException;
+ method public android.os.Bundle updateCredentials(android.accounts.AccountAuthenticatorResponse, android.accounts.Account, java.lang.String, android.os.Bundle) throws android.accounts.NetworkErrorException;
+ }
+
+ public class PhoneAccount implements android.os.Parcelable {
+ method public static android.telecom.PhoneAccount.Builder builder(android.telecom.PhoneAccountHandle, java.lang.CharSequence);
+ method public android.graphics.drawable.Drawable createIconDrawable(android.content.Context);
+ method public int describeContents();
+ method public android.telecom.PhoneAccountHandle getAccountHandle();
+ method public android.net.Uri getAddress();
+ method public int getCapabilities();
+ method public int getHighlightColor();
+ method public android.graphics.Bitmap getIconBitmap();
+ method public java.lang.String getIconPackageName();
+ method public int getIconResId();
+ method public int getIconTint();
+ method public java.lang.CharSequence getLabel();
+ method public java.lang.CharSequence getShortDescription();
+ method public android.net.Uri getSubscriptionAddress();
+ method public java.util.List<java.lang.String> getSupportedUriSchemes();
+ method public boolean hasCapabilities(int);
+ method public boolean supportsUriScheme(java.lang.String);
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final int CAPABILITY_PLACE_EMERGENCY_CALLS = 16; // 0x10
+ field public static final int CAPABILITY_SIM_SUBSCRIPTION = 4; // 0x4
+ field public static final android.os.Parcelable.Creator<android.telecom.PhoneAccount> CREATOR;
+ field public static final int NO_HIGHLIGHT_COLOR = 0; // 0x0
+ field public static final int NO_ICON_TINT = 0; // 0x0
+ field public static final int NO_RESOURCE_ID = -1; // 0xffffffff
+ field public static final java.lang.String SCHEME_SIP = "sip";
+ field public static final java.lang.String SCHEME_TEL = "tel";
+ field public static final java.lang.String SCHEME_VOICEMAIL = "voicemail";
+ }
+
+ public static class PhoneAccount.Builder {
+ ctor public PhoneAccount.Builder(android.telecom.PhoneAccountHandle, java.lang.CharSequence);
+ ctor public PhoneAccount.Builder(android.telecom.PhoneAccount);
+ method public android.telecom.PhoneAccount build();
+ method public android.telecom.PhoneAccount.Builder setAddress(android.net.Uri);
+ method public android.telecom.PhoneAccount.Builder setCapabilities(int);
+ method public android.telecom.PhoneAccount.Builder setHighlightColor(int);
+ method public android.telecom.PhoneAccount.Builder setIcon(android.content.Context, int);
+ method public android.telecom.PhoneAccount.Builder setIcon(java.lang.String, int);
+ method public android.telecom.PhoneAccount.Builder setIcon(android.content.Context, int, int);
+ method public android.telecom.PhoneAccount.Builder setIcon(java.lang.String, int, int);
+ method public android.telecom.PhoneAccount.Builder setIcon(android.graphics.Bitmap);
+ method public android.telecom.PhoneAccount.Builder setShortDescription(java.lang.CharSequence);
+ method public android.telecom.PhoneAccount.Builder setSubscriptionAddress(android.net.Uri);
+ method public android.telecom.PhoneAccount.Builder setSupportedUriSchemes(java.util.List<java.lang.String>);
+ }
+
+ public class PhoneAccountHandle implements android.os.Parcelable {
+ ctor public PhoneAccountHandle(android.content.ComponentName, java.lang.String);
+ method public int describeContents();
+ method public android.content.ComponentName getComponentName();
+ method public java.lang.String getId();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.telecom.PhoneAccountHandle> CREATOR;
+ }
+
public class TelecomManager {
method public void cancelMissedCallsNotification();
+ method public android.telecom.PhoneAccount getPhoneAccount(android.telecom.PhoneAccountHandle);
method public boolean handleMmi(java.lang.String);
method public boolean isInCall();
method public void showInCallScreen(boolean);
@@ -28176,7 +28327,10 @@
field public static final char DTMF_CHARACTER_WAIT = 59; // 0x003b ';'
field public static final java.lang.String EXTRA_CALL_DISCONNECT_CAUSE = "android.telecom.extra.CALL_DISCONNECT_CAUSE";
field public static final java.lang.String EXTRA_CALL_DISCONNECT_MESSAGE = "android.telecom.extra.CALL_DISCONNECT_MESSAGE";
+ field public static final java.lang.String EXTRA_OUTGOING_CALL_EXTRAS = "android.telecom.extra.OUTGOING_CALL_EXTRAS";
+ field public static final java.lang.String EXTRA_PHONE_ACCOUNT_HANDLE = "android.telecom.extra.PHONE_ACCOUNT_HANDLE";
field public static final java.lang.String EXTRA_START_CALL_WITH_SPEAKERPHONE = "android.telecom.extra.START_CALL_WITH_SPEAKERPHONE";
+ field public static final java.lang.String EXTRA_START_CALL_WITH_VIDEO_STATE = "android.telecom.extra.START_CALL_WITH_VIDEO_STATE";
field public static final java.lang.String GATEWAY_ORIGINAL_ADDRESS = "android.telecom.extra.GATEWAY_ORIGINAL_ADDRESS";
field public static final java.lang.String GATEWAY_PROVIDER_PACKAGE = "android.telecom.extra.GATEWAY_PROVIDER_PACKAGE";
field public static final int PRESENTATION_ALLOWED = 1; // 0x1
@@ -28185,6 +28339,63 @@
field public static final int PRESENTATION_UNKNOWN = 3; // 0x3
}
+ public class VideoProfile implements android.os.Parcelable {
+ ctor public VideoProfile(int);
+ ctor public VideoProfile(int, int);
+ method public int describeContents();
+ method public int getQuality();
+ method public int getVideoState();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.telecom.VideoProfile> CREATOR;
+ field public static final int QUALITY_DEFAULT = 4; // 0x4
+ field public static final int QUALITY_HIGH = 1; // 0x1
+ field public static final int QUALITY_LOW = 3; // 0x3
+ field public static final int QUALITY_MEDIUM = 2; // 0x2
+ }
+
+ public static class VideoProfile.VideoState {
+ ctor public VideoProfile.VideoState();
+ method public static boolean isAudioOnly(int);
+ method public static boolean isBidirectional(int);
+ method public static boolean isPaused(int);
+ method public static boolean isReceptionEnabled(int);
+ method public static boolean isTransmissionEnabled(int);
+ field public static final int AUDIO_ONLY = 0; // 0x0
+ field public static final int BIDIRECTIONAL = 3; // 0x3
+ field public static final int PAUSED = 4; // 0x4
+ field public static final int RX_ENABLED = 2; // 0x2
+ field public static final int TX_ENABLED = 1; // 0x1
+ }
+
+ public class Voicemail implements android.os.Parcelable {
+ method public static android.telecom.Voicemail.Builder createForInsertion(long, java.lang.String);
+ method public int describeContents();
+ method public long getDuration();
+ method public long getId();
+ method public java.lang.String getNumber();
+ method public java.lang.String getSourceData();
+ method public java.lang.String getSourcePackage();
+ method public long getTimestampMillis();
+ method public android.net.Uri getUri();
+ method public boolean hasContent();
+ method public boolean isRead();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.telecom.Voicemail> CREATOR;
+ }
+
+ public static class Voicemail.Builder {
+ method public android.telecom.Voicemail build();
+ method public android.telecom.Voicemail.Builder setDuration(long);
+ method public android.telecom.Voicemail.Builder setHasContent(boolean);
+ method public android.telecom.Voicemail.Builder setId(long);
+ method public android.telecom.Voicemail.Builder setIsRead(boolean);
+ method public android.telecom.Voicemail.Builder setNumber(java.lang.String);
+ method public android.telecom.Voicemail.Builder setSourceData(java.lang.String);
+ method public android.telecom.Voicemail.Builder setSourcePackage(java.lang.String);
+ method public android.telecom.Voicemail.Builder setTimestamp(long);
+ method public android.telecom.Voicemail.Builder setUri(android.net.Uri);
+ }
+
}
package android.telephony {
@@ -28378,6 +28589,7 @@
public class PhoneNumberUtils {
ctor public PhoneNumberUtils();
+ method public static void addPhoneTtsSpan(android.text.Spannable, int, int);
method public static java.lang.String calledPartyBCDFragmentToString(byte[], int, int);
method public static java.lang.String calledPartyBCDToString(byte[], int, int);
method public static boolean compare(java.lang.String, java.lang.String);
@@ -28394,6 +28606,8 @@
method public static java.lang.String formatNumberToE164(java.lang.String, java.lang.String);
method public static deprecated int getFormatTypeForLocale(java.util.Locale);
method public static java.lang.String getNumberFromIntent(android.content.Intent, android.content.Context);
+ method public static android.text.style.TtsSpan getPhoneTtsSpan(java.lang.String);
+ method public static java.lang.CharSequence getPhoneTtsSpannable(java.lang.CharSequence);
method public static java.lang.String getStrippedReversed(java.lang.String);
method public static final boolean is12Key(char);
method public static final boolean isDialable(char);
diff --git a/api/system-current.txt b/api/system-current.txt
index 729f656..6838ec1 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -6889,6 +6889,7 @@
field public static final int SCAN_MODE_BALANCED = 1; // 0x1
field public static final int SCAN_MODE_LOW_LATENCY = 2; // 0x2
field public static final int SCAN_MODE_LOW_POWER = 0; // 0x0
+ field public static final int SCAN_MODE_OPPORTUNISTIC = -1; // 0xffffffff
field public static final int SCAN_RESULT_TYPE_ABBREVIATED = 1; // 0x1
field public static final int SCAN_RESULT_TYPE_FULL = 0; // 0x0
}
@@ -11091,6 +11092,8 @@
public class ImageFormat {
ctor public ImageFormat();
method public static int getBitsPerPixel(int);
+ field public static final int DEPTH16 = 1144402265; // 0x44363159
+ field public static final int DEPTH_POINT_CLOUD = 257; // 0x101
field public static final int JPEG = 256; // 0x100
field public static final int NV16 = 16; // 0x10
field public static final int NV21 = 17; // 0x11
@@ -12864,6 +12867,8 @@
field public static final int CAMERA_DISABLED = 1; // 0x1
field public static final int CAMERA_DISCONNECTED = 2; // 0x2
field public static final int CAMERA_ERROR = 3; // 0x3
+ field public static final int CAMERA_IN_USE = 4; // 0x4
+ field public static final int MAX_CAMERAS_IN_USE = 5; // 0x5
}
public abstract class CameraCaptureSession implements java.lang.AutoCloseable {
@@ -12907,11 +12912,14 @@
field public static final android.hardware.camera2.CameraCharacteristics.Key<android.util.Range<java.lang.Integer>[]> CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES;
field public static final android.hardware.camera2.CameraCharacteristics.Key<android.util.Range<java.lang.Integer>> CONTROL_AE_COMPENSATION_RANGE;
field public static final android.hardware.camera2.CameraCharacteristics.Key<android.util.Rational> CONTROL_AE_COMPENSATION_STEP;
+ field public static final android.hardware.camera2.CameraCharacteristics.Key<java.lang.Boolean> CONTROL_AE_LOCK_AVAILABLE;
field public static final android.hardware.camera2.CameraCharacteristics.Key<int[]> CONTROL_AF_AVAILABLE_MODES;
field public static final android.hardware.camera2.CameraCharacteristics.Key<int[]> CONTROL_AVAILABLE_EFFECTS;
+ field public static final android.hardware.camera2.CameraCharacteristics.Key<int[]> CONTROL_AVAILABLE_MODES;
field public static final android.hardware.camera2.CameraCharacteristics.Key<int[]> CONTROL_AVAILABLE_SCENE_MODES;
field public static final android.hardware.camera2.CameraCharacteristics.Key<int[]> CONTROL_AVAILABLE_VIDEO_STABILIZATION_MODES;
field public static final android.hardware.camera2.CameraCharacteristics.Key<int[]> CONTROL_AWB_AVAILABLE_MODES;
+ field public static final android.hardware.camera2.CameraCharacteristics.Key<java.lang.Boolean> CONTROL_AWB_LOCK_AVAILABLE;
field public static final android.hardware.camera2.CameraCharacteristics.Key<java.lang.Integer> CONTROL_MAX_REGIONS_AE;
field public static final android.hardware.camera2.CameraCharacteristics.Key<java.lang.Integer> CONTROL_MAX_REGIONS_AF;
field public static final android.hardware.camera2.CameraCharacteristics.Key<java.lang.Integer> CONTROL_MAX_REGIONS_AWB;
@@ -12928,8 +12936,13 @@
field public static final android.hardware.camera2.CameraCharacteristics.Key<java.lang.Integer> LENS_INFO_FOCUS_DISTANCE_CALIBRATION;
field public static final android.hardware.camera2.CameraCharacteristics.Key<java.lang.Float> LENS_INFO_HYPERFOCAL_DISTANCE;
field public static final android.hardware.camera2.CameraCharacteristics.Key<java.lang.Float> LENS_INFO_MINIMUM_FOCUS_DISTANCE;
+ field public static final android.hardware.camera2.CameraCharacteristics.Key<float[]> LENS_INTRINSIC_CALIBRATION;
+ field public static final android.hardware.camera2.CameraCharacteristics.Key<float[]> LENS_POSE_ROTATION;
+ field public static final android.hardware.camera2.CameraCharacteristics.Key<float[]> LENS_POSE_TRANSLATION;
+ field public static final android.hardware.camera2.CameraCharacteristics.Key<float[]> LENS_RADIAL_DISTORTION;
field public static final android.hardware.camera2.CameraCharacteristics.Key<int[]> NOISE_REDUCTION_AVAILABLE_NOISE_REDUCTION_MODES;
field public static final android.hardware.camera2.CameraCharacteristics.Key<int[]> REQUEST_AVAILABLE_CAPABILITIES;
+ field public static final android.hardware.camera2.CameraCharacteristics.Key<java.lang.Integer> REQUEST_MAX_NUM_INPUT_STREAMS;
field public static final android.hardware.camera2.CameraCharacteristics.Key<java.lang.Integer> REQUEST_MAX_NUM_OUTPUT_PROC;
field public static final android.hardware.camera2.CameraCharacteristics.Key<java.lang.Integer> REQUEST_MAX_NUM_OUTPUT_PROC_STALLING;
field public static final android.hardware.camera2.CameraCharacteristics.Key<java.lang.Integer> REQUEST_MAX_NUM_OUTPUT_RAW;
@@ -12949,6 +12962,7 @@
field public static final android.hardware.camera2.CameraCharacteristics.Key<android.graphics.Rect> SENSOR_INFO_ACTIVE_ARRAY_SIZE;
field public static final android.hardware.camera2.CameraCharacteristics.Key<java.lang.Integer> SENSOR_INFO_COLOR_FILTER_ARRANGEMENT;
field public static final android.hardware.camera2.CameraCharacteristics.Key<android.util.Range<java.lang.Long>> SENSOR_INFO_EXPOSURE_TIME_RANGE;
+ field public static final android.hardware.camera2.CameraCharacteristics.Key<java.lang.Boolean> SENSOR_INFO_LENS_SHADING_APPLIED;
field public static final android.hardware.camera2.CameraCharacteristics.Key<java.lang.Long> SENSOR_INFO_MAX_FRAME_DURATION;
field public static final android.hardware.camera2.CameraCharacteristics.Key<android.util.SizeF> SENSOR_INFO_PHYSICAL_SIZE;
field public static final android.hardware.camera2.CameraCharacteristics.Key<android.util.Size> SENSOR_INFO_PIXEL_ARRAY_SIZE;
@@ -12959,8 +12973,10 @@
field public static final android.hardware.camera2.CameraCharacteristics.Key<java.lang.Integer> SENSOR_ORIENTATION;
field public static final android.hardware.camera2.CameraCharacteristics.Key<java.lang.Integer> SENSOR_REFERENCE_ILLUMINANT1;
field public static final android.hardware.camera2.CameraCharacteristics.Key<java.lang.Byte> SENSOR_REFERENCE_ILLUMINANT2;
+ field public static final android.hardware.camera2.CameraCharacteristics.Key<int[]> SHADING_AVAILABLE_MODES;
field public static final android.hardware.camera2.CameraCharacteristics.Key<int[]> STATISTICS_INFO_AVAILABLE_FACE_DETECT_MODES;
field public static final android.hardware.camera2.CameraCharacteristics.Key<boolean[]> STATISTICS_INFO_AVAILABLE_HOT_PIXEL_MAP_MODES;
+ field public static final android.hardware.camera2.CameraCharacteristics.Key<byte[]> STATISTICS_INFO_AVAILABLE_LENS_SHADING_MAP_MODES;
field public static final android.hardware.camera2.CameraCharacteristics.Key<java.lang.Integer> STATISTICS_INFO_MAX_FACE_COUNT;
field public static final android.hardware.camera2.CameraCharacteristics.Key<java.lang.Integer> SYNC_MAX_LATENCY;
field public static final android.hardware.camera2.CameraCharacteristics.Key<int[]> TONEMAP_AVAILABLE_TONE_MAP_MODES;
@@ -13004,7 +13020,10 @@
method public java.lang.String[] getCameraIdList() throws android.hardware.camera2.CameraAccessException;
method public void openCamera(java.lang.String, android.hardware.camera2.CameraDevice.StateCallback, android.os.Handler) throws android.hardware.camera2.CameraAccessException;
method public void registerAvailabilityCallback(android.hardware.camera2.CameraManager.AvailabilityCallback, android.os.Handler);
+ method public void registerTorchCallback(android.hardware.camera2.CameraManager.TorchCallback, android.os.Handler);
+ method public void setTorchMode(java.lang.String, boolean) throws android.hardware.camera2.CameraAccessException;
method public void unregisterAvailabilityCallback(android.hardware.camera2.CameraManager.AvailabilityCallback);
+ method public void unregisterTorchCallback(android.hardware.camera2.CameraManager.TorchCallback);
}
public static abstract class CameraManager.AvailabilityCallback {
@@ -13013,6 +13032,12 @@
method public void onCameraUnavailable(java.lang.String);
}
+ public static abstract class CameraManager.TorchCallback {
+ ctor public CameraManager.TorchCallback();
+ method public void onTorchModeChanged(java.lang.String, boolean);
+ method public void onTorchModeUnavailable(java.lang.String);
+ }
+
public abstract class CameraMetadata {
method public java.util.List<TKey> getKeys();
field public static final int COLOR_CORRECTION_ABERRATION_MODE_FAST = 1; // 0x1
@@ -13030,6 +13055,7 @@
field public static final int CONTROL_AE_MODE_ON_ALWAYS_FLASH = 3; // 0x3
field public static final int CONTROL_AE_MODE_ON_AUTO_FLASH = 2; // 0x2
field public static final int CONTROL_AE_MODE_ON_AUTO_FLASH_REDEYE = 4; // 0x4
+ field public static final int CONTROL_AE_PRECAPTURE_TRIGGER_CANCEL = 2; // 0x2
field public static final int CONTROL_AE_PRECAPTURE_TRIGGER_IDLE = 0; // 0x0
field public static final int CONTROL_AE_PRECAPTURE_TRIGGER_START = 1; // 0x1
field public static final int CONTROL_AE_STATE_CONVERGED = 2; // 0x2
@@ -13126,6 +13152,7 @@
field public static final int INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY = 2; // 0x2
field public static final int INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED = 0; // 0x0
field public static final int LENS_FACING_BACK = 1; // 0x1
+ field public static final int LENS_FACING_EXTERNAL = 2; // 0x2
field public static final int LENS_FACING_FRONT = 0; // 0x0
field public static final int LENS_INFO_FOCUS_DISTANCE_CALIBRATION_APPROXIMATE = 1; // 0x1
field public static final int LENS_INFO_FOCUS_DISTANCE_CALIBRATION_CALIBRATED = 2; // 0x2
@@ -13136,13 +13163,16 @@
field public static final int LENS_STATE_STATIONARY = 0; // 0x0
field public static final int NOISE_REDUCTION_MODE_FAST = 1; // 0x1
field public static final int NOISE_REDUCTION_MODE_HIGH_QUALITY = 2; // 0x2
+ field public static final int NOISE_REDUCTION_MODE_MINIMAL = 3; // 0x3
field public static final int NOISE_REDUCTION_MODE_OFF = 0; // 0x0
field public static final int REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE = 0; // 0x0
field public static final int REQUEST_AVAILABLE_CAPABILITIES_BURST_CAPTURE = 6; // 0x6
field public static final int REQUEST_AVAILABLE_CAPABILITIES_MANUAL_POST_PROCESSING = 2; // 0x2
field public static final int REQUEST_AVAILABLE_CAPABILITIES_MANUAL_SENSOR = 1; // 0x1
+ field public static final int REQUEST_AVAILABLE_CAPABILITIES_OPAQUE_REPROCESSING = 4; // 0x4
field public static final int REQUEST_AVAILABLE_CAPABILITIES_RAW = 3; // 0x3
field public static final int REQUEST_AVAILABLE_CAPABILITIES_READ_SENSOR_SETTINGS = 5; // 0x5
+ field public static final int REQUEST_AVAILABLE_CAPABILITIES_YUV_REPROCESSING = 7; // 0x7
field public static final int SCALER_CROPPING_TYPE_CENTER_ONLY = 0; // 0x0
field public static final int SCALER_CROPPING_TYPE_FREEFORM = 1; // 0x1
field public static final int SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_BGGR = 3; // 0x3
@@ -13192,7 +13222,11 @@
field public static final int SYNC_MAX_LATENCY_UNKNOWN = -1; // 0xffffffff
field public static final int TONEMAP_MODE_CONTRAST_CURVE = 0; // 0x0
field public static final int TONEMAP_MODE_FAST = 1; // 0x1
+ field public static final int TONEMAP_MODE_GAMMA_VALUE = 3; // 0x3
field public static final int TONEMAP_MODE_HIGH_QUALITY = 2; // 0x2
+ field public static final int TONEMAP_MODE_PRESET_CURVE = 4; // 0x4
+ field public static final int TONEMAP_PRESET_CURVE_REC709 = 1; // 0x1
+ field public static final int TONEMAP_PRESET_CURVE_SRGB = 0; // 0x0
}
public class CaptureFailure {
@@ -13248,6 +13282,7 @@
field public static final android.hardware.camera2.CaptureRequest.Key<java.lang.Float> LENS_FOCUS_DISTANCE;
field public static final android.hardware.camera2.CaptureRequest.Key<java.lang.Integer> LENS_OPTICAL_STABILIZATION_MODE;
field public static final android.hardware.camera2.CaptureRequest.Key<java.lang.Integer> NOISE_REDUCTION_MODE;
+ field public static final android.hardware.camera2.CaptureRequest.Key<java.lang.Float> REPROCESS_EFFECTIVE_EXPOSURE_FACTOR;
field public static final android.hardware.camera2.CaptureRequest.Key<android.graphics.Rect> SCALER_CROP_REGION;
field public static final android.hardware.camera2.CaptureRequest.Key<java.lang.Long> SENSOR_EXPOSURE_TIME;
field public static final android.hardware.camera2.CaptureRequest.Key<java.lang.Long> SENSOR_FRAME_DURATION;
@@ -13259,7 +13294,9 @@
field public static final android.hardware.camera2.CaptureRequest.Key<java.lang.Boolean> STATISTICS_HOT_PIXEL_MAP_MODE;
field public static final android.hardware.camera2.CaptureRequest.Key<java.lang.Integer> STATISTICS_LENS_SHADING_MAP_MODE;
field public static final android.hardware.camera2.CaptureRequest.Key<android.hardware.camera2.params.TonemapCurve> TONEMAP_CURVE;
+ field public static final android.hardware.camera2.CaptureRequest.Key<java.lang.Float> TONEMAP_GAMMA;
field public static final android.hardware.camera2.CaptureRequest.Key<java.lang.Integer> TONEMAP_MODE;
+ field public static final android.hardware.camera2.CaptureRequest.Key<java.lang.Integer> TONEMAP_PRESET_CURVE;
}
public static final class CaptureRequest.Builder {
@@ -13322,9 +13359,14 @@
field public static final android.hardware.camera2.CaptureResult.Key<java.lang.Float> LENS_FOCAL_LENGTH;
field public static final android.hardware.camera2.CaptureResult.Key<java.lang.Float> LENS_FOCUS_DISTANCE;
field public static final android.hardware.camera2.CaptureResult.Key<android.util.Pair<java.lang.Float, java.lang.Float>> LENS_FOCUS_RANGE;
+ field public static final android.hardware.camera2.CaptureResult.Key<float[]> LENS_INTRINSIC_CALIBRATION;
field public static final android.hardware.camera2.CaptureResult.Key<java.lang.Integer> LENS_OPTICAL_STABILIZATION_MODE;
+ field public static final android.hardware.camera2.CaptureResult.Key<float[]> LENS_POSE_ROTATION;
+ field public static final android.hardware.camera2.CaptureResult.Key<float[]> LENS_POSE_TRANSLATION;
+ field public static final android.hardware.camera2.CaptureResult.Key<float[]> LENS_RADIAL_DISTORTION;
field public static final android.hardware.camera2.CaptureResult.Key<java.lang.Integer> LENS_STATE;
field public static final android.hardware.camera2.CaptureResult.Key<java.lang.Integer> NOISE_REDUCTION_MODE;
+ field public static final android.hardware.camera2.CaptureResult.Key<java.lang.Float> REPROCESS_EFFECTIVE_EXPOSURE_FACTOR;
field public static final android.hardware.camera2.CaptureResult.Key<java.lang.Byte> REQUEST_PIPELINE_DEPTH;
field public static final android.hardware.camera2.CaptureResult.Key<android.graphics.Rect> SCALER_CROP_REGION;
field public static final android.hardware.camera2.CaptureResult.Key<java.lang.Long> SENSOR_EXPOSURE_TIME;
@@ -13346,7 +13388,9 @@
field public static final android.hardware.camera2.CaptureResult.Key<java.lang.Integer> STATISTICS_LENS_SHADING_MAP_MODE;
field public static final android.hardware.camera2.CaptureResult.Key<java.lang.Integer> STATISTICS_SCENE_FLICKER;
field public static final android.hardware.camera2.CaptureResult.Key<android.hardware.camera2.params.TonemapCurve> TONEMAP_CURVE;
+ field public static final android.hardware.camera2.CaptureResult.Key<java.lang.Float> TONEMAP_GAMMA;
field public static final android.hardware.camera2.CaptureResult.Key<java.lang.Integer> TONEMAP_MODE;
+ field public static final android.hardware.camera2.CaptureResult.Key<java.lang.Integer> TONEMAP_PRESET_CURVE;
}
public static final class CaptureResult.Key {
@@ -19197,7 +19241,8 @@
}
public class RttManager {
- method public android.net.wifi.RttManager.Capabilities getCapabilities();
+ method public deprecated android.net.wifi.RttManager.Capabilities getCapabilities();
+ method public android.net.wifi.RttManager.RttCapabilities getRttCapabilities();
method public void startRanging(android.net.wifi.RttManager.RttParams[], android.net.wifi.RttManager.RttListener);
method public void stopRanging(android.net.wifi.RttManager.RttListener);
field public static final int BASE = 160256; // 0x27200
@@ -19207,10 +19252,19 @@
field public static final int CMD_OP_STOP_RANGING = 160257; // 0x27201
field public static final int CMD_OP_SUCCEEDED = 160259; // 0x27203
field public static final java.lang.String DESCRIPTION_KEY = "android.net.wifi.RttManager.Description";
+ field public static final int PREAMBLE_HT = 2; // 0x2
+ field public static final int PREAMBLE_LEGACY = 1; // 0x1
+ field public static final int PREAMBLE_VHT = 4; // 0x4
field public static final int REASON_INVALID_LISTENER = -3; // 0xfffffffd
field public static final int REASON_INVALID_REQUEST = -4; // 0xfffffffc
field public static final int REASON_NOT_AVAILABLE = -2; // 0xfffffffe
field public static final int REASON_UNSPECIFIED = -1; // 0xffffffff
+ field public static final int RTT_BW_10_SUPPORT = 2; // 0x2
+ field public static final int RTT_BW_160_SUPPORT = 32; // 0x20
+ field public static final int RTT_BW_20_SUPPORT = 4; // 0x4
+ field public static final int RTT_BW_40_SUPPORT = 8; // 0x8
+ field public static final int RTT_BW_5_SUPPORT = 1; // 0x1
+ field public static final int RTT_BW_80_SUPPORT = 16; // 0x10
field public static final int RTT_CHANNEL_WIDTH_10 = 6; // 0x6
field public static final int RTT_CHANNEL_WIDTH_160 = 3; // 0x3
field public static final int RTT_CHANNEL_WIDTH_20 = 0; // 0x0
@@ -19218,26 +19272,31 @@
field public static final int RTT_CHANNEL_WIDTH_5 = 5; // 0x5
field public static final int RTT_CHANNEL_WIDTH_80 = 2; // 0x2
field public static final int RTT_CHANNEL_WIDTH_80P80 = 4; // 0x4
- field public static final int RTT_CHANNEL_WIDTH_UNSPECIFIED = -1; // 0xffffffff
+ field public static final deprecated int RTT_CHANNEL_WIDTH_UNSPECIFIED = -1; // 0xffffffff
field public static final int RTT_PEER_TYPE_AP = 1; // 0x1
field public static final int RTT_PEER_TYPE_STA = 2; // 0x2
field public static final int RTT_PEER_TYPE_UNSPECIFIED = 0; // 0x0
field public static final int RTT_STATUS_ABORTED = 8; // 0x8
field public static final int RTT_STATUS_FAILURE = 1; // 0x1
field public static final int RTT_STATUS_FAIL_AP_ON_DIFF_CHANNEL = 6; // 0x6
+ field public static final int RTT_STATUS_FAIL_BUSY_TRY_LATER = 12; // 0xc
+ field public static final int RTT_STATUS_FAIL_INVALID_TS = 9; // 0x9
field public static final int RTT_STATUS_FAIL_NOT_SCHEDULED_YET = 4; // 0x4
field public static final int RTT_STATUS_FAIL_NO_CAPABILITY = 7; // 0x7
field public static final int RTT_STATUS_FAIL_NO_RSP = 2; // 0x2
+ field public static final int RTT_STATUS_FAIL_PROTOCOL = 10; // 0xa
field public static final int RTT_STATUS_FAIL_REJECTED = 3; // 0x3
+ field public static final int RTT_STATUS_FAIL_SCHEDULE = 11; // 0xb
field public static final int RTT_STATUS_FAIL_TM_TIMEOUT = 5; // 0x5
field public static final int RTT_STATUS_SUCCESS = 0; // 0x0
- field public static final int RTT_TYPE_11_MC = 4; // 0x4
- field public static final int RTT_TYPE_11_V = 2; // 0x2
+ field public static final deprecated int RTT_TYPE_11_MC = 4; // 0x4
+ field public static final deprecated int RTT_TYPE_11_V = 2; // 0x2
field public static final int RTT_TYPE_ONE_SIDED = 1; // 0x1
- field public static final int RTT_TYPE_UNSPECIFIED = 0; // 0x0
+ field public static final int RTT_TYPE_TWO_SIDED = 4; // 0x4
+ field public static final deprecated int RTT_TYPE_UNSPECIFIED = 0; // 0x0
}
- public class RttManager.Capabilities {
+ public deprecated class RttManager.Capabilities {
ctor public RttManager.Capabilities();
field public int supportedPeerType;
field public int supportedType;
@@ -19256,6 +19315,20 @@
field public android.net.wifi.RttManager.RttResult[] mResults;
}
+ public static class RttManager.RttCapabilities implements android.os.Parcelable {
+ ctor public RttManager.RttCapabilities();
+ method public int describeContents();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public int bwSupported;
+ field public boolean lciSupported;
+ field public boolean lcrSupported;
+ field public boolean oneSidedRttSupported;
+ field public int preambleSupported;
+ field public deprecated boolean supportedPeerType;
+ field public deprecated boolean supportedType;
+ field public boolean twoSided11McRttSupported;
+ }
+
public static abstract interface RttManager.RttListener {
method public abstract void onAborted();
method public abstract void onFailure(int, java.lang.String);
@@ -19264,41 +19337,87 @@
public static class RttManager.RttParams {
ctor public RttManager.RttParams();
+ field public boolean LCIRequest;
+ field public boolean LCRRequest;
+ field public int bandwidth;
field public java.lang.String bssid;
+ field public int burstTimeout;
+ field public int centerFreq0;
+ field public int centerFreq1;
field public int channelWidth;
field public int deviceType;
field public int frequency;
- field public int num_retries;
- field public int num_samples;
+ field public int interval;
+ field public int numRetriesPerFTMR;
+ field public int numRetriesPerMeasurementFrame;
+ field public int numSamplesPerBurst;
+ field public deprecated int num_retries;
+ field public deprecated int num_samples;
+ field public int numberBurst;
+ field public int preamble;
field public int requestType;
}
public static class RttManager.RttResult {
ctor public RttManager.RttResult();
field public java.lang.String bssid;
- field public int distance_cm;
- field public int distance_sd_cm;
- field public int distance_spread_cm;
- field public int requestType;
+ field public int burstDuration;
+ field public int burstNumber;
+ field public int distance;
+ field public int distanceSpread;
+ field public int distanceStandardDeviation;
+ field public deprecated int distance_cm;
+ field public deprecated int distance_sd_cm;
+ field public deprecated int distance_spread_cm;
+ field public int frameNumberPerBurstPeer;
+ field public int measurementFrameNumber;
+ field public int measurementType;
+ field public deprecated int requestType;
+ field public int retryAfterDuration;
field public int rssi;
- field public int rssi_spread;
- field public long rtt_ns;
- field public long rtt_sd_ns;
- field public long rtt_spread_ns;
+ field public int rssiSpread;
+ field public deprecated int rssi_spread;
+ field public long rtt;
+ field public long rttSpread;
+ field public long rttStandardDeviation;
+ field public deprecated long rtt_ns;
+ field public deprecated long rtt_sd_ns;
+ field public deprecated long rtt_spread_ns;
+ field public int rxRate;
field public int status;
+ field public int successMeasurementFrameNumber;
field public long ts;
- field public int tx_rate;
+ field public int txRate;
+ field public deprecated int tx_rate;
+ }
+
+ public class RttManager.wifiInformationElement {
+ ctor public RttManager.wifiInformationElement();
+ field public java.lang.String data;
+ field public int id;
}
public class ScanResult implements android.os.Parcelable {
method public int describeContents();
method public void writeToParcel(android.os.Parcel, int);
field public java.lang.String BSSID;
+ field public static final int CHANNEL_WIDTH_160MHZ = 3; // 0x3
+ field public static final int CHANNEL_WIDTH_20MHZ = 0; // 0x0
+ field public static final int CHANNEL_WIDTH_40MHZ = 1; // 0x1
+ field public static final int CHANNEL_WIDTH_80MHZ = 2; // 0x2
+ field public static final int CHANNEL_WIDTH_80MHZ_PLUS_MHZ = 4; // 0x4
field public java.lang.String SSID;
field public java.lang.String capabilities;
+ field public int centerFreq0;
+ field public int centerFreq1;
+ field public int channelWidth;
field public int frequency;
+ field public boolean is80211McRTTResponder;
field public int level;
+ field public java.lang.String operatorFriendlyName;
+ field public boolean passpointNetwork;
field public long timestamp;
+ field public java.lang.String venueName;
}
public final class SupplicantState extends java.lang.Enum implements android.os.Parcelable {
@@ -19325,6 +19444,7 @@
public class WifiConfiguration implements android.os.Parcelable {
ctor public WifiConfiguration();
method public int describeContents();
+ method public boolean isPasspoint();
method public void writeToParcel(android.os.Parcel, int);
field public java.lang.String BSSID;
field public java.lang.String FQDN;
@@ -19334,6 +19454,8 @@
field public java.util.BitSet allowedKeyManagement;
field public java.util.BitSet allowedPairwiseCiphers;
field public java.util.BitSet allowedProtocols;
+ field public int apBand;
+ field public int apChannel;
field public int creatorUid;
field public android.net.wifi.WifiEnterpriseConfig enterpriseConfig;
field public boolean hiddenSSID;
@@ -19344,6 +19466,8 @@
field public int numScorerOverrideAndSwitchedNetwork;
field public java.lang.String preSharedKey;
field public int priority;
+ field public java.lang.String providerFriendlyName;
+ field public java.util.HashSet<java.lang.Long> roamingConsortiumIds;
field public int status;
field public java.lang.String[] wepKeys;
field public int wepTxKeyIndex;
@@ -19416,6 +19540,7 @@
ctor public WifiEnterpriseConfig();
ctor public WifiEnterpriseConfig(android.net.wifi.WifiEnterpriseConfig);
method public int describeContents();
+ method public java.lang.String getAltSubjectMatch();
method public java.lang.String getAnonymousIdentity();
method public java.security.cert.X509Certificate getCaCertificate();
method public java.security.cert.X509Certificate getClientCertificate();
@@ -19423,7 +19548,10 @@
method public java.lang.String getIdentity();
method public java.lang.String getPassword();
method public int getPhase2Method();
- method public java.lang.String getSubjectMatch();
+ method public java.lang.String getPlmn();
+ method public java.lang.String getRealm();
+ method public deprecated java.lang.String getSubjectMatch();
+ method public void setAltSubjectMatch(java.lang.String);
method public void setAnonymousIdentity(java.lang.String);
method public void setCaCertificate(java.security.cert.X509Certificate);
method public void setClientKeyEntry(java.security.PrivateKey, java.security.cert.X509Certificate);
@@ -19431,13 +19559,16 @@
method public void setIdentity(java.lang.String);
method public void setPassword(java.lang.String);
method public void setPhase2Method(int);
- method public void setSubjectMatch(java.lang.String);
+ method public void setPlmn(java.lang.String);
+ method public void setRealm(java.lang.String);
+ method public deprecated void setSubjectMatch(java.lang.String);
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.net.wifi.WifiEnterpriseConfig> CREATOR;
}
public static final class WifiEnterpriseConfig.Eap {
field public static final int AKA = 5; // 0x5
+ field public static final int AKA_PRIME = 6; // 0x6
field public static final int NONE = -1; // 0xffffffff
field public static final int PEAP = 0; // 0x0
field public static final int PWD = 3; // 0x3
@@ -19595,9 +19726,11 @@
method public void configureWifiChange(android.net.wifi.WifiScanner.WifiChangeSettings);
method public android.net.wifi.ScanResult[] getScanResults();
method public void startBackgroundScan(android.net.wifi.WifiScanner.ScanSettings, android.net.wifi.WifiScanner.ScanListener);
+ method public void startScan(android.net.wifi.WifiScanner.ScanSettings, android.net.wifi.WifiScanner.ScanListener);
method public void startTrackingBssids(android.net.wifi.WifiScanner.BssidInfo[], int, android.net.wifi.WifiScanner.BssidListener);
method public void startTrackingWifiChange(android.net.wifi.WifiScanner.WifiChangeListener);
method public void stopBackgroundScan(android.net.wifi.WifiScanner.ScanListener);
+ method public void stopScan(android.net.wifi.WifiScanner.ScanListener);
method public void stopTrackingBssids(android.net.wifi.WifiScanner.BssidListener);
method public void stopTrackingWifiChange(android.net.wifi.WifiScanner.WifiChangeListener);
field public static final int MAX_SCAN_PERIOD_MS = 1024000; // 0xfa000
@@ -19634,6 +19767,7 @@
public static abstract interface WifiScanner.BssidListener implements android.net.wifi.WifiScanner.ActionListener {
method public abstract void onFound(android.net.wifi.ScanResult[]);
+ method public abstract void onLost(android.net.wifi.ScanResult[]);
}
public static class WifiScanner.ChannelSpec {
@@ -19649,10 +19783,37 @@
field public android.net.wifi.WifiScanner.BssidInfo[] bssidInfos;
}
+ public static class WifiScanner.ParcelableScanData implements android.os.Parcelable {
+ ctor public WifiScanner.ParcelableScanData(android.net.wifi.WifiScanner.ScanData[]);
+ method public int describeContents();
+ method public android.net.wifi.WifiScanner.ScanData[] getResults();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public android.net.wifi.WifiScanner.ScanData[] mResults;
+ }
+
+ public static class WifiScanner.ParcelableScanResults implements android.os.Parcelable {
+ ctor public WifiScanner.ParcelableScanResults(android.net.wifi.ScanResult[]);
+ method public int describeContents();
+ method public android.net.wifi.ScanResult[] getResults();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public android.net.wifi.ScanResult[] mResults;
+ }
+
+ public static class WifiScanner.ScanData implements android.os.Parcelable {
+ ctor public WifiScanner.ScanData(int, int, android.net.wifi.ScanResult[]);
+ ctor public WifiScanner.ScanData(android.net.wifi.WifiScanner.ScanData);
+ method public int describeContents();
+ method public int getFlags();
+ method public int getId();
+ method public android.net.wifi.ScanResult[] getResults();
+ method public void writeToParcel(android.os.Parcel, int);
+ }
+
public static abstract interface WifiScanner.ScanListener implements android.net.wifi.WifiScanner.ActionListener {
method public abstract void onFullResult(android.net.wifi.ScanResult);
method public abstract void onPeriodChanged(int);
- method public abstract void onResults(android.net.wifi.ScanResult[]);
+ method public abstract deprecated void onResults(android.net.wifi.ScanResult[]);
+ method public abstract void onResults(android.net.wifi.WifiScanner.ScanData[]);
}
public static class WifiScanner.ScanSettings implements android.os.Parcelable {
@@ -19661,6 +19822,7 @@
method public void writeToParcel(android.os.Parcel, int);
field public int band;
field public android.net.wifi.WifiScanner.ChannelSpec[] channels;
+ field public int maxScansToCache;
field public int numBssidsPerScan;
field public int periodInMs;
field public int reportEvents;
@@ -27454,6 +27616,7 @@
public static final class VoicemailContract.Status implements android.provider.BaseColumns {
method public static android.net.Uri buildSourceUri(java.lang.String);
+ method public static void setStatus(android.content.Context, android.telecom.PhoneAccountHandle, int, int, int);
field public static final java.lang.String CONFIGURATION_STATE = "configuration_state";
field public static final int CONFIGURATION_STATE_CAN_BE_CONFIGURED = 2; // 0x2
field public static final int CONFIGURATION_STATE_NOT_CONFIGURED = 1; // 0x1
@@ -27468,6 +27631,8 @@
field public static final int NOTIFICATION_CHANNEL_STATE_MESSAGE_WAITING = 2; // 0x2
field public static final int NOTIFICATION_CHANNEL_STATE_NO_CONNECTION = 1; // 0x1
field public static final int NOTIFICATION_CHANNEL_STATE_OK = 0; // 0x0
+ field public static final java.lang.String PHONE_ACCOUNT_COMPONENT_NAME = "phone_account_component_name";
+ field public static final java.lang.String PHONE_ACCOUNT_ID = "phone_account_id";
field public static final java.lang.String SETTINGS_URI = "settings_uri";
field public static final java.lang.String SOURCE_PACKAGE = "source_package";
field public static final java.lang.String VOICEMAIL_ACCESS_URI = "voicemail_access_uri";
@@ -27475,8 +27640,13 @@
public static final class VoicemailContract.Voicemails implements android.provider.BaseColumns android.provider.OpenableColumns {
method public static android.net.Uri buildSourceUri(java.lang.String);
+ method public static int deleteAll(android.content.Context);
+ method public static android.net.Uri insert(android.content.Context, android.telecom.Voicemail);
+ method public static int insert(android.content.Context, java.util.List<android.telecom.Voicemail>);
field public static final android.net.Uri CONTENT_URI;
field public static final java.lang.String DATE = "date";
+ field public static final java.lang.String DELETED = "deleted";
+ field public static final java.lang.String DIRTY = "dirty";
field public static final java.lang.String DIR_TYPE = "vnd.android.cursor.dir/voicemails";
field public static final java.lang.String DURATION = "duration";
field public static final java.lang.String HAS_CONTENT = "has_content";
@@ -27484,6 +27654,8 @@
field public static final java.lang.String ITEM_TYPE = "vnd.android.cursor.item/voicemail";
field public static final java.lang.String MIME_TYPE = "mime_type";
field public static final java.lang.String NUMBER = "number";
+ field public static final java.lang.String PHONE_ACCOUNT_COMPONENT_NAME = "subscription_component_name";
+ field public static final java.lang.String PHONE_ACCOUNT_ID = "subscription_id";
field public static final java.lang.String SOURCE_DATA = "source_data";
field public static final java.lang.String SOURCE_PACKAGE = "source_package";
field public static final java.lang.String TRANSCRIPTION = "transcription";
@@ -29896,6 +30068,22 @@
field public final int supportedRouteMask;
}
+ public class AuthenticatorService extends android.app.Service {
+ ctor public AuthenticatorService();
+ method public android.os.IBinder onBind(android.content.Intent);
+ }
+
+ public class AuthenticatorService.Authenticator extends android.accounts.AbstractAccountAuthenticator {
+ ctor public AuthenticatorService.Authenticator(android.content.Context);
+ method public android.os.Bundle addAccount(android.accounts.AccountAuthenticatorResponse, java.lang.String, java.lang.String, java.lang.String[], android.os.Bundle) throws android.accounts.NetworkErrorException;
+ method public android.os.Bundle confirmCredentials(android.accounts.AccountAuthenticatorResponse, android.accounts.Account, android.os.Bundle) throws android.accounts.NetworkErrorException;
+ method public android.os.Bundle editProperties(android.accounts.AccountAuthenticatorResponse, java.lang.String);
+ method public android.os.Bundle getAuthToken(android.accounts.AccountAuthenticatorResponse, android.accounts.Account, java.lang.String, android.os.Bundle) throws android.accounts.NetworkErrorException;
+ method public java.lang.String getAuthTokenLabel(java.lang.String);
+ method public android.os.Bundle hasFeatures(android.accounts.AccountAuthenticatorResponse, android.accounts.Account, java.lang.String[]) throws android.accounts.NetworkErrorException;
+ method public android.os.Bundle updateCredentials(android.accounts.AccountAuthenticatorResponse, android.accounts.Account, java.lang.String, android.os.Bundle) throws android.accounts.NetworkErrorException;
+ }
+
public final class Call {
method public void addListener(android.telecom.Call.Listener);
method public void answer(int);
@@ -30202,10 +30390,14 @@
method public java.util.List<java.lang.String> getSupportedUriSchemes();
method public boolean hasCapabilities(int);
method public boolean supportsUriScheme(java.lang.String);
+ method public android.telecom.PhoneAccount.Builder toBuilder();
method public void writeToParcel(android.os.Parcel, int);
+ field public static final int CAPABILITY_CALL_PROVIDER = 2; // 0x2
field public static final int CAPABILITY_CONNECTION_MANAGER = 1; // 0x1
+ field public static final int CAPABILITY_MULTI_USER = 32; // 0x20
field public static final int CAPABILITY_PLACE_EMERGENCY_CALLS = 16; // 0x10
field public static final int CAPABILITY_SIM_SUBSCRIPTION = 4; // 0x4
+ field public static final int CAPABILITY_VIDEO_CALLING = 8; // 0x8
field public static final android.os.Parcelable.Creator<android.telecom.PhoneAccount> CREATOR;
field public static final int NO_HIGHLIGHT_COLOR = 0; // 0x0
field public static final int NO_ICON_TINT = 0; // 0x0
@@ -30218,7 +30410,9 @@
public static class PhoneAccount.Builder {
ctor public PhoneAccount.Builder(android.telecom.PhoneAccountHandle, java.lang.CharSequence);
ctor public PhoneAccount.Builder(android.telecom.PhoneAccount);
+ method public android.telecom.PhoneAccount.Builder addSupportedUriScheme(java.lang.String);
method public android.telecom.PhoneAccount build();
+ method public android.telecom.PhoneAccount.Builder setAccountHandle(android.telecom.PhoneAccountHandle);
method public android.telecom.PhoneAccount.Builder setAddress(android.net.Uri);
method public android.telecom.PhoneAccount.Builder setCapabilities(int);
method public android.telecom.PhoneAccount.Builder setHighlightColor(int);
@@ -30234,9 +30428,11 @@
public class PhoneAccountHandle implements android.os.Parcelable {
ctor public PhoneAccountHandle(android.content.ComponentName, java.lang.String);
+ ctor public PhoneAccountHandle(android.content.ComponentName, java.lang.String, android.os.UserHandle);
method public int describeContents();
method public android.content.ComponentName getComponentName();
method public java.lang.String getId();
+ method public android.os.UserHandle getUserHandle();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.telecom.PhoneAccountHandle> CREATOR;
}
@@ -30361,6 +30557,7 @@
method public void unregisterPhoneAccount(android.telecom.PhoneAccountHandle);
field public static final java.lang.String ACTION_CHANGE_PHONE_ACCOUNTS = "android.telecom.action.CHANGE_PHONE_ACCOUNTS";
field public static final java.lang.String ACTION_CONNECTION_SERVICE_CONFIGURE = "android.telecom.action.CONNECTION_SERVICE_CONFIGURE";
+ field public static final java.lang.String ACTION_PHONE_ACCOUNT_REGISTERED = "android.telecom.action.PHONE_ACCOUNT_REGISTERED";
field public static final java.lang.String ACTION_SHOW_CALL_SETTINGS = "android.telecom.action.SHOW_CALL_SETTINGS";
field public static final char DTMF_CHARACTER_PAUSE = 44; // 0x002c ','
field public static final char DTMF_CHARACTER_WAIT = 59; // 0x003b ';'
@@ -30372,6 +30569,7 @@
field public static final java.lang.String EXTRA_OUTGOING_CALL_EXTRAS = "android.telecom.extra.OUTGOING_CALL_EXTRAS";
field public static final java.lang.String EXTRA_PHONE_ACCOUNT_HANDLE = "android.telecom.extra.PHONE_ACCOUNT_HANDLE";
field public static final java.lang.String EXTRA_START_CALL_WITH_SPEAKERPHONE = "android.telecom.extra.START_CALL_WITH_SPEAKERPHONE";
+ field public static final java.lang.String EXTRA_START_CALL_WITH_VIDEO_STATE = "android.telecom.extra.START_CALL_WITH_VIDEO_STATE";
field public static final java.lang.String GATEWAY_ORIGINAL_ADDRESS = "android.telecom.extra.GATEWAY_ORIGINAL_ADDRESS";
field public static final java.lang.String GATEWAY_PROVIDER_PACKAGE = "android.telecom.extra.GATEWAY_PROVIDER_PACKAGE";
field public static final int PRESENTATION_ALLOWED = 1; // 0x1
@@ -30380,6 +30578,63 @@
field public static final int PRESENTATION_UNKNOWN = 3; // 0x3
}
+ public class VideoProfile implements android.os.Parcelable {
+ ctor public VideoProfile(int);
+ ctor public VideoProfile(int, int);
+ method public int describeContents();
+ method public int getQuality();
+ method public int getVideoState();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.telecom.VideoProfile> CREATOR;
+ field public static final int QUALITY_DEFAULT = 4; // 0x4
+ field public static final int QUALITY_HIGH = 1; // 0x1
+ field public static final int QUALITY_LOW = 3; // 0x3
+ field public static final int QUALITY_MEDIUM = 2; // 0x2
+ }
+
+ public static class VideoProfile.VideoState {
+ ctor public VideoProfile.VideoState();
+ method public static boolean isAudioOnly(int);
+ method public static boolean isBidirectional(int);
+ method public static boolean isPaused(int);
+ method public static boolean isReceptionEnabled(int);
+ method public static boolean isTransmissionEnabled(int);
+ field public static final int AUDIO_ONLY = 0; // 0x0
+ field public static final int BIDIRECTIONAL = 3; // 0x3
+ field public static final int PAUSED = 4; // 0x4
+ field public static final int RX_ENABLED = 2; // 0x2
+ field public static final int TX_ENABLED = 1; // 0x1
+ }
+
+ public class Voicemail implements android.os.Parcelable {
+ method public static android.telecom.Voicemail.Builder createForInsertion(long, java.lang.String);
+ method public int describeContents();
+ method public long getDuration();
+ method public long getId();
+ method public java.lang.String getNumber();
+ method public java.lang.String getSourceData();
+ method public java.lang.String getSourcePackage();
+ method public long getTimestampMillis();
+ method public android.net.Uri getUri();
+ method public boolean hasContent();
+ method public boolean isRead();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.telecom.Voicemail> CREATOR;
+ }
+
+ public static class Voicemail.Builder {
+ method public android.telecom.Voicemail build();
+ method public android.telecom.Voicemail.Builder setDuration(long);
+ method public android.telecom.Voicemail.Builder setHasContent(boolean);
+ method public android.telecom.Voicemail.Builder setId(long);
+ method public android.telecom.Voicemail.Builder setIsRead(boolean);
+ method public android.telecom.Voicemail.Builder setNumber(java.lang.String);
+ method public android.telecom.Voicemail.Builder setSourceData(java.lang.String);
+ method public android.telecom.Voicemail.Builder setSourcePackage(java.lang.String);
+ method public android.telecom.Voicemail.Builder setTimestamp(long);
+ method public android.telecom.Voicemail.Builder setUri(android.net.Uri);
+ }
+
}
package android.telephony {
@@ -30573,6 +30828,7 @@
public class PhoneNumberUtils {
ctor public PhoneNumberUtils();
+ method public static void addPhoneTtsSpan(android.text.Spannable, int, int);
method public static java.lang.String calledPartyBCDFragmentToString(byte[], int, int);
method public static java.lang.String calledPartyBCDToString(byte[], int, int);
method public static boolean compare(java.lang.String, java.lang.String);
@@ -30589,6 +30845,8 @@
method public static java.lang.String formatNumberToE164(java.lang.String, java.lang.String);
method public static deprecated int getFormatTypeForLocale(java.util.Locale);
method public static java.lang.String getNumberFromIntent(android.content.Intent, android.content.Context);
+ method public static android.text.style.TtsSpan getPhoneTtsSpan(java.lang.String);
+ method public static java.lang.CharSequence getPhoneTtsSpannable(java.lang.CharSequence);
method public static java.lang.String getStrippedReversed(java.lang.String);
method public static final boolean is12Key(char);
method public static final boolean isDialable(char);
diff --git a/core/java/android/bluetooth/le/ScanSettings.java b/core/java/android/bluetooth/le/ScanSettings.java
index 7eae439..0106686 100644
--- a/core/java/android/bluetooth/le/ScanSettings.java
+++ b/core/java/android/bluetooth/le/ScanSettings.java
@@ -25,6 +25,13 @@
* parameters for the scan.
*/
public final class ScanSettings implements Parcelable {
+
+ /**
+ * A special Bluetooth LE scan mode. Applications using this scan mode will passively listen for
+ * other scan results without starting BLE scans themselves.
+ */
+ public static final int SCAN_MODE_OPPORTUNISTIC = -1;
+
/**
* Perform Bluetooth LE scan in low power mode. This is the default scan mode as it consumes the
* least power.
@@ -177,7 +184,7 @@
* @throws IllegalArgumentException If the {@code scanMode} is invalid.
*/
public Builder setScanMode(int scanMode) {
- if (scanMode < SCAN_MODE_LOW_POWER || scanMode > SCAN_MODE_LOW_LATENCY) {
+ if (scanMode < SCAN_MODE_OPPORTUNISTIC || scanMode > SCAN_MODE_LOW_LATENCY) {
throw new IllegalArgumentException("invalid scan mode " + scanMode);
}
mScanMode = scanMode;
diff --git a/core/java/android/hardware/ICameraService.aidl b/core/java/android/hardware/ICameraService.aidl
index 2bc3dd4..9aede01 100644
--- a/core/java/android/hardware/ICameraService.aidl
+++ b/core/java/android/hardware/ICameraService.aidl
@@ -81,4 +81,6 @@
int clientUid,
// Container for an ICamera object
out BinderHolder device);
+
+ int setTorchMode(String CameraId, boolean enabled, IBinder clientBinder);
}
diff --git a/core/java/android/hardware/ICameraServiceListener.aidl b/core/java/android/hardware/ICameraServiceListener.aidl
index c5484965..49278b6 100644
--- a/core/java/android/hardware/ICameraServiceListener.aidl
+++ b/core/java/android/hardware/ICameraServiceListener.aidl
@@ -23,4 +23,6 @@
* Keep up-to-date with frameworks/av/include/camera/ICameraServiceListener.h
*/
void onStatusChanged(int status, int cameraId);
+
+ void onTorchStatusChanged(int status, String cameraId);
}
diff --git a/core/java/android/hardware/camera2/CameraAccessException.java b/core/java/android/hardware/camera2/CameraAccessException.java
index 91ef6ca..84e9912 100644
--- a/core/java/android/hardware/camera2/CameraAccessException.java
+++ b/core/java/android/hardware/camera2/CameraAccessException.java
@@ -28,16 +28,14 @@
*/
public class CameraAccessException extends AndroidException {
/**
- * The camera device is in use already
- * @hide
+ * The camera device is in use already.
*/
public static final int CAMERA_IN_USE = 4;
/**
- * The system-wide limit for number of open cameras has been reached,
- * and more camera devices cannot be opened until previous instances are
- * closed.
- * @hide
+ * The system-wide limit for number of open cameras or camera resources has
+ * been reached, and more camera devices cannot be opened or torch mode
+ * cannot be turned on until previous instances are closed.
*/
public static final int MAX_CAMERAS_IN_USE = 5;
diff --git a/core/java/android/hardware/camera2/CameraCharacteristics.java b/core/java/android/hardware/camera2/CameraCharacteristics.java
index 7cf8fb0..9a29897 100644
--- a/core/java/android/hardware/camera2/CameraCharacteristics.java
+++ b/core/java/android/hardware/camera2/CameraCharacteristics.java
@@ -638,6 +638,44 @@
new Key<android.hardware.camera2.params.HighSpeedVideoConfiguration[]>("android.control.availableHighSpeedVideoConfigurations", android.hardware.camera2.params.HighSpeedVideoConfiguration[].class);
/**
+ * <p>Whether the camera device supports {@link CaptureRequest#CONTROL_AE_LOCK android.control.aeLock}</p>
+ * <p>LIMITED or FULL devices will always list <code>true</code></p>
+ * <p>This key is available on all devices.</p>
+ *
+ * @see CaptureRequest#CONTROL_AE_LOCK
+ */
+ @PublicKey
+ public static final Key<Boolean> CONTROL_AE_LOCK_AVAILABLE =
+ new Key<Boolean>("android.control.aeLockAvailable", boolean.class);
+
+ /**
+ * <p>Whether the camera device supports {@link CaptureRequest#CONTROL_AWB_LOCK android.control.awbLock}</p>
+ * <p>LIMITED or FULL devices will always list <code>true</code></p>
+ * <p>This key is available on all devices.</p>
+ *
+ * @see CaptureRequest#CONTROL_AWB_LOCK
+ */
+ @PublicKey
+ public static final Key<Boolean> CONTROL_AWB_LOCK_AVAILABLE =
+ new Key<Boolean>("android.control.awbLockAvailable", boolean.class);
+
+ /**
+ * <p>List of control modes for {@link CaptureRequest#CONTROL_MODE android.control.mode} that are supported by this camera
+ * device.</p>
+ * <p>This list contains control modes that can be set for the camera device.
+ * LEGACY mode devices will always support AUTO mode. LIMITED and FULL
+ * devices will always support OFF, AUTO modes.</p>
+ * <p><b>Range of valid values:</b><br>
+ * Any value listed in {@link CaptureRequest#CONTROL_MODE android.control.mode}</p>
+ * <p>This key is available on all devices.</p>
+ *
+ * @see CaptureRequest#CONTROL_MODE
+ */
+ @PublicKey
+ public static final Key<int[]> CONTROL_AVAILABLE_MODES =
+ new Key<int[]>("android.control.availableModes", int[].class);
+
+ /**
* <p>List of edge enhancement modes for {@link CaptureRequest#EDGE_MODE android.edge.mode} that are supported by this camera
* device.</p>
* <p>Full-capability camera devices must always support OFF; all devices will list FAST.</p>
@@ -889,16 +927,141 @@
* <ul>
* <li>{@link #LENS_FACING_FRONT FRONT}</li>
* <li>{@link #LENS_FACING_BACK BACK}</li>
+ * <li>{@link #LENS_FACING_EXTERNAL EXTERNAL}</li>
* </ul></p>
* <p>This key is available on all devices.</p>
* @see #LENS_FACING_FRONT
* @see #LENS_FACING_BACK
+ * @see #LENS_FACING_EXTERNAL
*/
@PublicKey
public static final Key<Integer> LENS_FACING =
new Key<Integer>("android.lens.facing", int.class);
/**
+ * <p>The orientation of the camera relative to the sensor
+ * coordinate system.</p>
+ * <p>The four coefficients that describe the quarternion
+ * rotation from the Android sensor coordinate system to a
+ * camera-aligned coordinate system where the X-axis is
+ * aligned with the long side of the image sensor, the Y-axis
+ * is aligned with the short side of the image sensor, and
+ * the Z-axis is aligned with the optical axis of the sensor.</p>
+ * <p>To convert from the quarternion coefficients <code>(x,y,z,w)</code>
+ * to the axis of rotation <code>(a_x, a_y, a_z)</code> and rotation
+ * amount <code>theta</code>, the following formulas can be used:</p>
+ * <pre><code> theta = 2 * acos(w)
+ * a_x = x / sin(theta/2)
+ * a_y = y / sin(theta/2)
+ * a_z = z / sin(theta/2)
+ * </code></pre>
+ * <p>To create a 3x3 rotation matrix that applies the rotation
+ * defined by this quarternion, the following matrix can be
+ * used:</p>
+ * <pre><code>R = [ 1 - 2y^2 - 2z^2, 2xy - 2zw, 2xz + 2yw,
+ * 2xy + 2zw, 1 - 2x^2 - 2z^2, 2yz - 2xw,
+ * 2xz - 2yw, 2yz + 2xw, 1 - 2x^2 - 2y^2 ]
+ * </code></pre>
+ * <p>This matrix can then be used to apply the rotation to a
+ * column vector point with</p>
+ * <p><code>p' = Rp</code></p>
+ * <p>where <code>p</code> is in the device sensor coordinate system, and
+ * <code>p'</code> is in the camera-oriented coordinate system.</p>
+ * <p><b>Units</b>:
+ * Quarternion coefficients</p>
+ * <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
+ */
+ @PublicKey
+ public static final Key<float[]> LENS_POSE_ROTATION =
+ new Key<float[]>("android.lens.poseRotation", float[].class);
+
+ /**
+ * <p>Position of the camera optical center.</p>
+ * <p>As measured in the device sensor coordinate system, the
+ * position of the camera device's optical center, as a
+ * three-dimensional vector <code>(x,y,z)</code>.</p>
+ * <p>To transform a world position to a camera-device centered
+ * coordinate system, the position must be translated by this
+ * vector and then rotated by {@link CameraCharacteristics#LENS_POSE_ROTATION android.lens.poseRotation}.</p>
+ * <p><b>Units</b>: Meters</p>
+ * <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
+ *
+ * @see CameraCharacteristics#LENS_POSE_ROTATION
+ */
+ @PublicKey
+ public static final Key<float[]> LENS_POSE_TRANSLATION =
+ new Key<float[]>("android.lens.poseTranslation", float[].class);
+
+ /**
+ * <p>The parameters for this camera device's intrinsic
+ * calibration.</p>
+ * <p>The five calibration parameters that describe the
+ * transform from camera-centric 3D coordinates to sensor
+ * pixel coordinates:</p>
+ * <pre><code>[f_x, f_y, c_x, c_y, s]
+ * </code></pre>
+ * <p>Where <code>f_x</code> and <code>f_y</code> are the horizontal and vertical
+ * focal lengths, <code>[c_x, c_y]</code> is the position of the optical
+ * axis, and <code>s</code> is a skew parameter for the sensor plane not
+ * being aligned with the lens plane.</p>
+ * <p>These are typically used within a transformation matrix K:</p>
+ * <pre><code>K = [ f_x, s, c_x,
+ * 0, f_y, c_y,
+ * 0 0, 1 ]
+ * </code></pre>
+ * <p>which can then be combined with the camera pose rotation
+ * <code>R</code> and translation <code>t</code> ({@link CameraCharacteristics#LENS_POSE_ROTATION android.lens.poseRotation} and
+ * {@link CameraCharacteristics#LENS_POSE_TRANSLATION android.lens.poseTranslation}, respective) to calculate the
+ * complete transform from world coordinates to pixel
+ * coordinates:</p>
+ * <pre><code>P = [ K 0 * [ R t
+ * 0 1 ] 0 1 ]
+ * </code></pre>
+ * <p>and with <code>p_w</code> being a point in the world coordinate system
+ * and <code>p_s</code> being a point in the camera active pixel array
+ * coordinate system, and with the mapping including the
+ * homogeneous division by z:</p>
+ * <pre><code> p_h = (x_h, y_h, z_h) = P p_w
+ * p_s = p_h / z_h
+ * </code></pre>
+ * <p>so <code>[x_s, y_s]</code> is the pixel coordinates of the world
+ * point, <code>z_s = 1</code>, and <code>w_s</code> is a measurement of disparity
+ * (depth) in pixel coordinates.</p>
+ * <p><b>Units</b>:
+ * Pixels in the android.sensor.activeArraySize coordinate
+ * system.</p>
+ * <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
+ *
+ * @see CameraCharacteristics#LENS_POSE_ROTATION
+ * @see CameraCharacteristics#LENS_POSE_TRANSLATION
+ */
+ @PublicKey
+ public static final Key<float[]> LENS_INTRINSIC_CALIBRATION =
+ new Key<float[]>("android.lens.intrinsicCalibration", float[].class);
+
+ /**
+ * <p>The correction coefficients to correct for this camera device's
+ * radial lens distortion.</p>
+ * <p>Three cofficients <code>[kappa_1, kappa_2, kappa_3]</code> that
+ * can be used to correct the lens's radial geometric
+ * distortion with the mapping equations:</p>
+ * <pre><code> x_c = x_i * ( 1 + kappa_1 * r^2 + kappa_2 * r^4 + kappa_3 * r^6 )
+ * y_c = y_i * ( 1 + kappa_1 * r^2 + kappa_2 * r^4 + kappa_3 * r^6 )
+ * </code></pre>
+ * <p>where <code>[x_i, y_i]</code> are normalized coordinates with <code>(0,0)</code>
+ * at the lens optical center, and <code>[-1, 1]</code> are the edges of
+ * the active pixel array; and where <code>[x_c, y_c]</code> are the
+ * corrected normalized coordinates with radial distortion
+ * removed; and <code>r^2 = x_i^2 + y_i^2</code>.</p>
+ * <p><b>Units</b>:
+ * Coefficients for a 6th-degree even radial polynomial.</p>
+ * <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
+ */
+ @PublicKey
+ public static final Key<float[]> LENS_RADIAL_DISTORTION =
+ new Key<float[]>("android.lens.radialDistortion", float[].class);
+
+ /**
* <p>List of noise reduction modes for {@link CaptureRequest#NOISE_REDUCTION_MODE android.noiseReduction.mode} that are supported
* by this camera device.</p>
* <p>Full-capability camera devices will always support OFF and FAST.</p>
@@ -1069,8 +1232,11 @@
* android.scaler.availableInputOutputFormatsMap. When using an
* input stream, there must be at least one output stream
* configured to to receive the reprocessed images.</p>
+ * <p>When an input stream and some output streams are used in a reprocessing request,
+ * only the input buffer will be used to produce these output stream buffers, and a
+ * new sensor image will not be captured.</p>
* <p>For example, for Zero Shutter Lag (ZSL) still capture use case, the input
- * stream image format will be RAW_OPAQUE, the associated output stream image format
+ * stream image format will be OPAQUE, the associated output stream image format
* should be JPEG.</p>
* <p><b>Range of valid values:</b><br></p>
* <p>0 or 1.</p>
@@ -1080,8 +1246,8 @@
* {@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL android.info.supportedHardwareLevel} key</p>
*
* @see CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL
- * @hide
*/
+ @PublicKey
public static final Key<Integer> REQUEST_MAX_NUM_INPUT_STREAMS =
new Key<Integer>("android.request.maxNumInputStreams", int.class);
@@ -1157,8 +1323,10 @@
* <li>{@link #REQUEST_AVAILABLE_CAPABILITIES_MANUAL_SENSOR MANUAL_SENSOR}</li>
* <li>{@link #REQUEST_AVAILABLE_CAPABILITIES_MANUAL_POST_PROCESSING MANUAL_POST_PROCESSING}</li>
* <li>{@link #REQUEST_AVAILABLE_CAPABILITIES_RAW RAW}</li>
+ * <li>{@link #REQUEST_AVAILABLE_CAPABILITIES_OPAQUE_REPROCESSING OPAQUE_REPROCESSING}</li>
* <li>{@link #REQUEST_AVAILABLE_CAPABILITIES_READ_SENSOR_SETTINGS READ_SENSOR_SETTINGS}</li>
* <li>{@link #REQUEST_AVAILABLE_CAPABILITIES_BURST_CAPTURE BURST_CAPTURE}</li>
+ * <li>{@link #REQUEST_AVAILABLE_CAPABILITIES_YUV_REPROCESSING YUV_REPROCESSING}</li>
* </ul></p>
* <p>This key is available on all devices.</p>
*
@@ -1167,8 +1335,10 @@
* @see #REQUEST_AVAILABLE_CAPABILITIES_MANUAL_SENSOR
* @see #REQUEST_AVAILABLE_CAPABILITIES_MANUAL_POST_PROCESSING
* @see #REQUEST_AVAILABLE_CAPABILITIES_RAW
+ * @see #REQUEST_AVAILABLE_CAPABILITIES_OPAQUE_REPROCESSING
* @see #REQUEST_AVAILABLE_CAPABILITIES_READ_SENSOR_SETTINGS
* @see #REQUEST_AVAILABLE_CAPABILITIES_BURST_CAPTURE
+ * @see #REQUEST_AVAILABLE_CAPABILITIES_YUV_REPROCESSING
*/
@PublicKey
public static final Key<int[]> REQUEST_AVAILABLE_CAPABILITIES =
@@ -1345,10 +1515,10 @@
* <p>The mapping of image formats that are supported by this
* camera device for input streams, to their corresponding output formats.</p>
* <p>All camera devices with at least 1
- * android.request.maxNumInputStreams will have at least one
+ * {@link CameraCharacteristics#REQUEST_MAX_NUM_INPUT_STREAMS android.request.maxNumInputStreams} will have at least one
* available input format.</p>
* <p>The camera device will support the following map of formats,
- * if its dependent capability is supported:</p>
+ * if its dependent capability ({@link CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES android.request.availableCapabilities}) is supported:</p>
* <table>
* <thead>
* <tr>
@@ -1359,45 +1529,42 @@
* </thead>
* <tbody>
* <tr>
- * <td align="left">RAW_OPAQUE</td>
+ * <td align="left">OPAQUE</td>
* <td align="left">JPEG</td>
- * <td align="left">ZSL</td>
+ * <td align="left">OPAQUE_REPROCESSING</td>
* </tr>
* <tr>
- * <td align="left">RAW_OPAQUE</td>
+ * <td align="left">OPAQUE</td>
* <td align="left">YUV_420_888</td>
- * <td align="left">ZSL</td>
+ * <td align="left">OPAQUE_REPROCESSING</td>
* </tr>
* <tr>
- * <td align="left">RAW_OPAQUE</td>
- * <td align="left">RAW16</td>
- * <td align="left">RAW</td>
- * </tr>
- * <tr>
- * <td align="left">RAW16</td>
* <td align="left">YUV_420_888</td>
- * <td align="left">RAW</td>
- * </tr>
- * <tr>
- * <td align="left">RAW16</td>
* <td align="left">JPEG</td>
- * <td align="left">RAW</td>
+ * <td align="left">YUV_REPROCESSING</td>
+ * </tr>
+ * <tr>
+ * <td align="left">YUV_420_888</td>
+ * <td align="left">YUV_420_888</td>
+ * <td align="left">YUV_REPROCESSING</td>
* </tr>
* </tbody>
* </table>
- * <p>For ZSL-capable camera devices, using the RAW_OPAQUE format
+ * <p>OPAQUE refers to a device-internal format that is not directly application-visible.
+ * An OPAQUE input or output surface can be acquired by
+ * OpaqueImageRingBufferQueue#getInputSurface() or
+ * OpaqueImageRingBufferQueue#getOutputSurface().
+ * For a OPAQUE_REPROCESSING-capable camera device, using the OPAQUE format
* as either input or output will never hurt maximum frame rate (i.e.
- * StreamConfigurationMap#getOutputStallDuration(int,Size)
- * for a <code>format =</code> RAW_OPAQUE is always 0).</p>
+ * StreamConfigurationMap#getOutputStallDuration(klass,Size) is always 0),
+ * where klass is android.media.OpaqueImageRingBufferQueue.class.</p>
* <p>Attempting to configure an input stream with output streams not
* listed as available in this map is not valid.</p>
* <p>TODO: typedef to ReprocessFormatMap</p>
* <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
- * <p><b>Full capability</b> -
- * Present on all camera devices that report being {@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL_FULL HARDWARE_LEVEL_FULL} devices in the
- * {@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL android.info.supportedHardwareLevel} key</p>
*
- * @see CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL
+ * @see CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES
+ * @see CameraCharacteristics#REQUEST_MAX_NUM_INPUT_STREAMS
* @hide
*/
public static final Key<int[]> SCALER_AVAILABLE_INPUT_OUTPUT_FORMATS_MAP =
@@ -1899,6 +2066,23 @@
new Key<Integer>("android.sensor.info.timestampSource", int.class);
/**
+ * <p>Whether the RAW images output from this camera device are subject to
+ * lens shading correction.</p>
+ * <p>If TRUE, all images produced by the camera device in the RAW image formats will
+ * have lens shading correction already applied to it. If FALSE, the images will
+ * not be adjusted for lens shading correction.
+ * See {@link CameraCharacteristics#REQUEST_MAX_NUM_OUTPUT_RAW android.request.maxNumOutputRaw} for a list of RAW image formats.</p>
+ * <p>This key will be <code>null</code> for all devices do not report this information.
+ * Devices with RAW capability will always report this information in this key.</p>
+ * <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
+ *
+ * @see CameraCharacteristics#REQUEST_MAX_NUM_OUTPUT_RAW
+ */
+ @PublicKey
+ public static final Key<Boolean> SENSOR_INFO_LENS_SHADING_APPLIED =
+ new Key<Boolean>("android.sensor.info.lensShadingApplied", boolean.class);
+
+ /**
* <p>The standard reference illuminant used as the scene light source when
* calculating the {@link CameraCharacteristics#SENSOR_COLOR_TRANSFORM1 android.sensor.colorTransform1},
* {@link CameraCharacteristics#SENSOR_CALIBRATION_TRANSFORM1 android.sensor.calibrationTransform1}, and
@@ -2189,6 +2373,22 @@
new Key<int[]>("android.sensor.availableTestPatternModes", int[].class);
/**
+ * <p>List of lens shading modes for {@link CaptureRequest#SHADING_MODE android.shading.mode} that are supported by this camera device.</p>
+ * <p>This list contains lens shading modes that can be set for the camera device.
+ * Camera devices that support the MANUAL_POST_PROCESSING capability will always
+ * list OFF and FAST mode. This includes all FULL level devices.
+ * LEGACY devices will always only support FAST mode.</p>
+ * <p><b>Range of valid values:</b><br>
+ * Any value listed in {@link CaptureRequest#SHADING_MODE android.shading.mode}</p>
+ * <p>This key is available on all devices.</p>
+ *
+ * @see CaptureRequest#SHADING_MODE
+ */
+ @PublicKey
+ public static final Key<int[]> SHADING_AVAILABLE_MODES =
+ new Key<int[]>("android.shading.availableModes", int[].class);
+
+ /**
* <p>List of face detection modes for {@link CaptureRequest#STATISTICS_FACE_DETECT_MODE android.statistics.faceDetectMode} that are
* supported by this camera device.</p>
* <p>OFF is always supported.</p>
@@ -2232,6 +2432,23 @@
new Key<boolean[]>("android.statistics.info.availableHotPixelMapModes", boolean[].class);
/**
+ * <p>List of lens shading map output modes for {@link CaptureRequest#STATISTICS_LENS_SHADING_MAP_MODE android.statistics.lensShadingMapMode} that
+ * are supported by this camera device.</p>
+ * <p>If no lens shading map output is available for this camera device, this key will
+ * contain only OFF.</p>
+ * <p>ON is always supported on devices with the RAW capability.
+ * LEGACY mode devices will always only support OFF.</p>
+ * <p><b>Range of valid values:</b><br>
+ * Any value listed in {@link CaptureRequest#STATISTICS_LENS_SHADING_MAP_MODE android.statistics.lensShadingMapMode}</p>
+ * <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
+ *
+ * @see CaptureRequest#STATISTICS_LENS_SHADING_MAP_MODE
+ */
+ @PublicKey
+ public static final Key<byte[]> STATISTICS_INFO_AVAILABLE_LENS_SHADING_MAP_MODES =
+ new Key<byte[]>("android.statistics.info.availableLensShadingMapModes", byte[].class);
+
+ /**
* <p>Maximum number of supported points in the
* tonemap curve that can be used for {@link CaptureRequest#TONEMAP_CURVE android.tonemap.curve}.</p>
* <p>If the actual number of points provided by the application (in {@link CaptureRequest#TONEMAP_CURVE android.tonemap.curve}*) is
@@ -2255,8 +2472,13 @@
/**
* <p>List of tonemapping modes for {@link CaptureRequest#TONEMAP_MODE android.tonemap.mode} that are supported by this camera
* device.</p>
- * <p>Camera devices that support the MANUAL_POST_PROCESSING capability will always list
- * CONTRAST_CURVE and FAST. This includes all FULL level devices.</p>
+ * <p>Camera devices that support the MANUAL_POST_PROCESSING capability will always contain
+ * at least one of below mode combinations:</p>
+ * <ul>
+ * <li>CONTRAST_CURVE and FAST</li>
+ * <li>GAMMA_VALUE, PRESET_CURVE, and FAST</li>
+ * </ul>
+ * <p>This includes all FULL level devices.</p>
* <p><b>Range of valid values:</b><br>
* Any value listed in {@link CaptureRequest#TONEMAP_MODE android.tonemap.mode}</p>
* <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
@@ -2394,6 +2616,83 @@
public static final Key<Integer> SYNC_MAX_LATENCY =
new Key<Integer>("android.sync.maxLatency", int.class);
+ /**
+ * <p>The available depth dataspace stream
+ * configurations that this camera device supports
+ * (i.e. format, width, height, output/input stream).</p>
+ * <p>These are output stream configurations for use with
+ * dataSpace HAL_DATASPACE_DEPTH. The configurations are
+ * listed as <code>(format, width, height, input?)</code> tuples.</p>
+ * <p>Only devices that support depth output for at least
+ * the HAL_PIXEL_FORMAT_Y16 dense depth map may include
+ * this entry.</p>
+ * <p>A device that also supports the HAL_PIXEL_FORMAT_BLOB
+ * sparse depth point cloud must report a single entry for
+ * the format in this list as <code>(HAL_PIXEL_FORMAT_BLOB,
+ * android.depth.maxDepthSamples, 1, OUTPUT)</code> in addition to
+ * the entries for HAL_PIXEL_FORMAT_Y16.</p>
+ * <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
+ * <p><b>Limited capability</b> -
+ * Present on all camera devices that report being at least {@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED HARDWARE_LEVEL_LIMITED} devices in the
+ * {@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL android.info.supportedHardwareLevel} key</p>
+ *
+ * @see CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL
+ * @hide
+ */
+ public static final Key<android.hardware.camera2.params.StreamConfiguration[]> DEPTH_AVAILABLE_DEPTH_STREAM_CONFIGURATIONS =
+ new Key<android.hardware.camera2.params.StreamConfiguration[]>("android.depth.availableDepthStreamConfigurations", android.hardware.camera2.params.StreamConfiguration[].class);
+
+ /**
+ * <p>This lists the minimum frame duration for each
+ * format/size combination for depth output formats.</p>
+ * <p>This should correspond to the frame duration when only that
+ * stream is active, with all processing (typically in android.*.mode)
+ * set to either OFF or FAST.</p>
+ * <p>When multiple streams are used in a request, the minimum frame
+ * duration will be max(individual stream min durations).</p>
+ * <p>The minimum frame duration of a stream (of a particular format, size)
+ * is the same regardless of whether the stream is input or output.</p>
+ * <p>See {@link CaptureRequest#SENSOR_FRAME_DURATION android.sensor.frameDuration} and
+ * android.scaler.availableStallDurations for more details about
+ * calculating the max frame rate.</p>
+ * <p>(Keep in sync with
+ * StreamConfigurationMap#getOutputMinFrameDuration)</p>
+ * <p><b>Units</b>: (format, width, height, ns) x n</p>
+ * <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
+ * <p><b>Limited capability</b> -
+ * Present on all camera devices that report being at least {@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED HARDWARE_LEVEL_LIMITED} devices in the
+ * {@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL android.info.supportedHardwareLevel} key</p>
+ *
+ * @see CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL
+ * @see CaptureRequest#SENSOR_FRAME_DURATION
+ * @hide
+ */
+ public static final Key<android.hardware.camera2.params.StreamConfigurationDuration[]> DEPTH_AVAILABLE_DEPTH_MIN_FRAME_DURATIONS =
+ new Key<android.hardware.camera2.params.StreamConfigurationDuration[]>("android.depth.availableDepthMinFrameDurations", android.hardware.camera2.params.StreamConfigurationDuration[].class);
+
+ /**
+ * <p>This lists the maximum stall duration for each
+ * format/size combination for depth streams.</p>
+ * <p>A stall duration is how much extra time would get added
+ * to the normal minimum frame duration for a repeating request
+ * that has streams with non-zero stall.</p>
+ * <p>This functions similarly to
+ * android.scaler.availableStallDurations for depth
+ * streams.</p>
+ * <p>All depth output stream formats may have a nonzero stall
+ * duration.</p>
+ * <p><b>Units</b>: (format, width, height, ns) x n</p>
+ * <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
+ * <p><b>Limited capability</b> -
+ * Present on all camera devices that report being at least {@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED HARDWARE_LEVEL_LIMITED} devices in the
+ * {@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL android.info.supportedHardwareLevel} key</p>
+ *
+ * @see CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL
+ * @hide
+ */
+ public static final Key<android.hardware.camera2.params.StreamConfigurationDuration[]> DEPTH_AVAILABLE_DEPTH_STALL_DURATIONS =
+ new Key<android.hardware.camera2.params.StreamConfigurationDuration[]>("android.depth.availableDepthStallDurations", android.hardware.camera2.params.StreamConfigurationDuration[].class);
+
/*~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~
* End generated code
*~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~O@*/
diff --git a/core/java/android/hardware/camera2/CameraDevice.java b/core/java/android/hardware/camera2/CameraDevice.java
index 482b1f0..444419d 100644
--- a/core/java/android/hardware/camera2/CameraDevice.java
+++ b/core/java/android/hardware/camera2/CameraDevice.java
@@ -18,6 +18,7 @@
import android.hardware.camera2.params.StreamConfigurationMap;
import android.graphics.ImageFormat;
+import android.hardware.camera2.params.OutputConfiguration;
import android.os.Handler;
import android.view.Surface;
@@ -183,7 +184,7 @@
* Then obtain the Surface with
* {@link android.renderscript.Allocation#getSurface}.</li>
*
- * <li>For access to raw, uncompressed JPEG data in the application: Create an
+ * <li>For access to RAW, uncompressed YUV, or compressed JPEG data in the application: Create an
* {@link android.media.ImageReader} object with one of the supported output formats given by
* {@link StreamConfigurationMap#getOutputFormats()}, setting its size to one of the
* corresponding supported sizes by passing the chosen output format into
@@ -381,6 +382,20 @@
throws CameraAccessException;
/**
+ * <p>Create a new camera capture session by providing the target output set of Surfaces and
+ * its corresponding surface configuration to the camera device.</p>
+ *
+ * @see #createCaptureSession
+ * @see OutputConfiguration
+ *
+ * @hide
+ */
+ public abstract void createCaptureSessionByOutputConfiguration(
+ List<OutputConfiguration> outputConfigurations,
+ CameraCaptureSession.StateCallback callback, Handler handler)
+ throws CameraAccessException;
+
+ /**
* <p>Create a {@link CaptureRequest.Builder} for new capture requests,
* initialized with template for a target use case. The settings are chosen
* to be the best options for the specific camera device, so it is not
diff --git a/core/java/android/hardware/camera2/CameraManager.java b/core/java/android/hardware/camera2/CameraManager.java
index b6bb33b..faa782a 100644
--- a/core/java/android/hardware/camera2/CameraManager.java
+++ b/core/java/android/hardware/camera2/CameraManager.java
@@ -27,6 +27,7 @@
import android.hardware.camera2.utils.CameraRuntimeException;
import android.hardware.camera2.utils.BinderHolder;
import android.os.IBinder;
+import android.os.Binder;
import android.os.Handler;
import android.os.Looper;
import android.os.RemoteException;
@@ -109,8 +110,11 @@
* of the state of individual CameraManager instances.</p>
*
* @param callback the new callback to send camera availability notices to
- * @param handler The handler on which the callback should be invoked, or
- * {@code null} to use the current thread's {@link android.os.Looper looper}.
+ * @param handler The handler on which the callback should be invoked, or {@code null} to use
+ * the current thread's {@link android.os.Looper looper}.
+ *
+ * @throws IllegalArgumentException if the handler is {@code null} but the current thread has
+ * no looper.
*/
public void registerAvailabilityCallback(AvailabilityCallback callback, Handler handler) {
if (handler == null) {
@@ -138,6 +142,52 @@
}
/**
+ * Register a callback to be notified about torch mode status.
+ *
+ * <p>Registering the same callback again will replace the handler with the
+ * new one provided.</p>
+ *
+ * <p>The first time a callback is registered, it is immediately called
+ * with the torch mode status of all currently known camera devices.</p>
+ *
+ * <p>Since this callback will be registered with the camera service, remember to unregister it
+ * once it is no longer needed; otherwise the callback will continue to receive events
+ * indefinitely and it may prevent other resources from being released. Specifically, the
+ * callbacks will be invoked independently of the general activity lifecycle and independently
+ * of the state of individual CameraManager instances.</p>
+ *
+ * @param callback The new callback to send torch mode status to
+ * @param handler The handler on which the callback should be invoked, or {@code null} to use
+ * the current thread's {@link android.os.Looper looper}.
+ *
+ * @throws IllegalArgumentException if the handler is {@code null} but the current thread has
+ * no looper.
+ */
+ public void registerTorchCallback(TorchCallback callback, Handler handler) {
+ if (handler == null) {
+ Looper looper = Looper.myLooper();
+ if (looper == null) {
+ throw new IllegalArgumentException(
+ "No handler given, and current thread has no looper!");
+ }
+ handler = new Handler(looper);
+ }
+ CameraManagerGlobal.get().registerTorchCallback(callback, handler);
+ }
+
+ /**
+ * Remove a previously-added callback; the callback will no longer receive torch mode status
+ * callbacks.
+ *
+ * <p>Removing a callback that isn't registered has no effect.</p>
+ *
+ * @param callback The callback to remove from the notification list
+ */
+ public void unregisterTorchCallback(TorchCallback callback) {
+ CameraManagerGlobal.get().unregisterTorchCallback(callback);
+ }
+
+ /**
* <p>Query the capabilities of a camera device. These capabilities are
* immutable for a given camera.</p>
*
@@ -384,6 +434,49 @@
}
/**
+ * Set the flash unit's torch mode of the camera of the given ID without opening the camera
+ * device.
+ *
+ * <p>Use {@link #getCameraIdList} to get the list of available camera devices and use
+ * {@link #getCameraCharacteristics} to check whether the camera device has a flash unit.
+ * Note that even if a camera device has a flash unit, turning on the torch mode may fail
+ * if the camera device or other camera resources needed to turn on the torch mode are in use.
+ * </p>
+ *
+ * <p> If {@link #setTorchMode} is called to turn on or off the torch mode successfully,
+ * {@link CameraManager.TorchCallback#onTorchModeChanged} will be invoked.
+ * However, even if turning on the torch mode is successful, the application does not have the
+ * exclusive ownership of the flash unit or the camera device. The torch mode will be turned
+ * off and becomes unavailable when the camera device that the flash unit belongs to becomes
+ * unavailable or when other camera resources to keep the torch on become unavailable (
+ * {@link CameraManager.TorchCallback#onTorchModeUnavailable} will be invoked). Also,
+ * other applications are free to call {@link #setTorchMode} to turn off the torch mode (
+ * {@link CameraManager.TorchCallback#onTorchModeChanged} will be invoked). If the latest
+ * application that turned on the torch mode exits, the torch mode will be turned off.
+ *
+ * @param cameraId
+ * The unique identifier of the camera device that the flash unit belongs to.
+ * @param enabled
+ * The desired state of the torch mode for the target camera device. Set to
+ * {@code true} to turn on the torch mode. Set to {@code false} to turn off the
+ * torch mode.
+ *
+ * @throws CameraAccessException if it failed to access the flash unit.
+ * {@link CameraAccessException#CAMERA_IN_USE} will be thrown if the camera device
+ * is in use. {@link CameraAccessException#MAX_CAMERAS_IN_USE} will be thrown if
+ * other camera resources needed to turn on the torch mode are in use.
+ * {@link CameraAccessException#CAMERA_DISCONNECTED} will be thrown if camera
+ * service is not available.
+ *
+ * @throws IllegalArgumentException if cameraId was null, cameraId doesn't match any currently
+ * or previously available camera device, or the camera device doesn't have a
+ * flash unit.
+ */
+ public void setTorchMode(String cameraId, boolean enabled) throws CameraAccessException {
+ CameraManagerGlobal.get().setTorchMode(cameraId, enabled);
+ }
+
+ /**
* A callback for camera devices becoming available or
* unavailable to open.
*
@@ -428,6 +521,63 @@
}
/**
+ * A callback for camera flash torch modes becoming unavailable, disabled, or enabled.
+ *
+ * <p>The torch mode becomes unavailable when the camera device it belongs to becomes
+ * unavailable or other camera resouces it needs become busy due to other higher priority
+ * camera activities. The torch mode becomes disabled when it was turned off or when the camera
+ * device it belongs to is no longer in use and other camera resources it needs are no longer
+ * busy. A camera's torch mode is turned off when an application calls {@link #setTorchMode} to
+ * turn off the camera's torch mode, or when an application turns on another camera's torch mode
+ * if keeping multiple torch modes on simultaneously is not supported. The torch mode becomes
+ * enabled when it is turned on via {@link #setTorchMode}.</p>
+ *
+ * <p>The torch mode is available to set via {@link #setTorchMode} only when it's in a disabled
+ * or enabled state.</p>
+ *
+ * <p>Extend this callback and pass an instance of the subclass to
+ * {@link CameraManager#registerTorchCallback} to be notified of such status changes.
+ * </p>
+ *
+ * @see registerTorchCallback
+ */
+ public static abstract class TorchCallback {
+ /**
+ * A camera's torch mode has become unavailable to set via {@link #setTorchMode}.
+ *
+ * <p>If torch mode was previously turned on by calling {@link #setTorchMode}, it will be
+ * turned off before {@link CameraManager.TorchCallback#onTorchModeUnavailable} is
+ * invoked. {@link #setTorchMode} will fail until the torch mode has entered a disabled or
+ * enabled state again.</p>
+ *
+ * <p>The default implementation of this method does nothing.</p>
+ *
+ * @param cameraId The unique identifier of the camera whose torch mode has become
+ * unavailable.
+ */
+ public void onTorchModeUnavailable(String cameraId) {
+ // default empty implementation
+ }
+
+ /**
+ * A camera's torch mode has become enabled or disabled and can be changed via
+ * {@link #setTorchMode}.
+ *
+ * <p>The default implementation of this method does nothing.</p>
+ *
+ * @param cameraId The unique identifier of the camera whose torch mode has been changed.
+ *
+ * @param enabled The state that the torch mode of the camera has been changed to.
+ * {@code true} when the torch mode has become on and available to be turned
+ * off. {@code false} when the torch mode has becomes off and available to
+ * be turned on.
+ */
+ public void onTorchModeChanged(String cameraId, boolean enabled) {
+ // default empty implementation
+ }
+ }
+
+ /**
* Return or create the list of currently connected camera devices.
*
* <p>In case of errors connecting to the camera service, will return an empty list.</p>
@@ -583,6 +733,27 @@
private final ArrayMap<AvailabilityCallback, Handler> mCallbackMap =
new ArrayMap<AvailabilityCallback, Handler>();
+ // Keep up-to-date with ICameraServiceListener.h
+
+ // torch mode has become not available to set via setTorchMode().
+ public static final int TORCH_STATUS_NOT_AVAILABLE = 0;
+ // torch mode is off and available to be turned on via setTorchMode().
+ public static final int TORCH_STATUS_AVAILABLE_OFF = 1;
+ // torch mode is on and available to be turned off via setTorchMode().
+ public static final int TORCH_STATUS_AVAILABLE_ON = 2;
+
+ // End enums shared with ICameraServiceListener.h
+
+ // torch client binder to set the torch mode with.
+ private Binder mTorchClientBinder = new Binder();
+
+ // Camera ID -> Torch status map
+ private final ArrayMap<String, Integer> mTorchStatus = new ArrayMap<String, Integer>();
+
+ // Registered torch callbacks and their handlers
+ private final ArrayMap<TorchCallback, Handler> mTorchCallbackMap =
+ new ArrayMap<TorchCallback, Handler>();
+
private final Object mLock = new Object();
// Access only through getCameraService to deal with binder death
@@ -668,15 +839,46 @@
}
}
+ public void setTorchMode(String cameraId, boolean enabled) throws CameraAccessException {
+ synchronized(mLock) {
+
+ if (cameraId == null) {
+ throw new IllegalArgumentException("cameraId was null");
+ }
+
+ ICameraService cameraService = getCameraService();
+ if (cameraService == null) {
+ throw new CameraAccessException(CameraAccessException.CAMERA_DISCONNECTED,
+ "Camera service is currently unavailable");
+ }
+
+ try {
+ int status = cameraService.setTorchMode(cameraId, enabled, mTorchClientBinder);
+ } catch(CameraRuntimeException e) {
+ int problem = e.getReason();
+ switch (problem) {
+ case CameraAccessException.CAMERA_ERROR:
+ throw new IllegalArgumentException(
+ "the camera device doesn't have a flash unit.");
+ default:
+ throw e.asChecked();
+ }
+ } catch (RemoteException e) {
+ throw new CameraAccessException(CameraAccessException.CAMERA_DISCONNECTED,
+ "Camera service is currently unavailable");
+ }
+ }
+ }
+
private void handleRecoverableSetupErrors(CameraRuntimeException e, String msg) {
int problem = e.getReason();
switch (problem) {
- case CameraAccessException.CAMERA_DISCONNECTED:
- String errorMsg = CameraAccessException.getDefaultMessage(problem);
- Log.w(TAG, msg + ": " + errorMsg);
- break;
- default:
- throw new IllegalStateException(msg, e.asChecked());
+ case CameraAccessException.CAMERA_DISCONNECTED:
+ String errorMsg = CameraAccessException.getDefaultMessage(problem);
+ Log.w(TAG, msg + ": " + errorMsg);
+ break;
+ default:
+ throw new IllegalStateException(msg, e.asChecked());
}
}
@@ -701,6 +903,17 @@
}
}
+ private boolean validTorchStatus(int status) {
+ switch (status) {
+ case TORCH_STATUS_NOT_AVAILABLE:
+ case TORCH_STATUS_AVAILABLE_ON:
+ case TORCH_STATUS_AVAILABLE_OFF:
+ return true;
+ default:
+ return false;
+ }
+ }
+
private void postSingleUpdate(final AvailabilityCallback callback, final Handler handler,
final String id, final int status) {
if (isAvailable(status)) {
@@ -722,6 +935,32 @@
}
}
+ private void postSingleTorchUpdate(final TorchCallback callback, final Handler handler,
+ final String id, final int status) {
+ switch(status) {
+ case TORCH_STATUS_AVAILABLE_ON:
+ case TORCH_STATUS_AVAILABLE_OFF:
+ handler.post(
+ new Runnable() {
+ @Override
+ public void run() {
+ callback.onTorchModeChanged(id, status ==
+ TORCH_STATUS_AVAILABLE_ON);
+ }
+ });
+ break;
+ default:
+ handler.post(
+ new Runnable() {
+ @Override
+ public void run() {
+ callback.onTorchModeUnavailable(id);
+ }
+ });
+ break;
+ }
+ }
+
/**
* Send the state of all known cameras to the provided listener, to initialize
* the listener's knowledge of camera state.
@@ -791,6 +1030,44 @@
}
} // onStatusChangedLocked
+ private void updateTorchCallbackLocked(TorchCallback callback, Handler handler) {
+ for (int i = 0; i < mTorchStatus.size(); i++) {
+ String id = mTorchStatus.keyAt(i);
+ Integer status = mTorchStatus.valueAt(i);
+ postSingleTorchUpdate(callback, handler, id, status);
+ }
+ }
+
+ private void onTorchStatusChangedLocked(int status, String id) {
+ if (DEBUG) {
+ Log.v(TAG,
+ String.format("Camera id %s has torch status changed to 0x%x", id, status));
+ }
+
+ if (!validTorchStatus(status)) {
+ Log.e(TAG, String.format("Ignoring invalid device %s torch status 0x%x", id,
+ status));
+ return;
+ }
+
+ Integer oldStatus = mTorchStatus.put(id, status);
+ if (oldStatus != null && oldStatus == status) {
+ if (DEBUG) {
+ Log.v(TAG, String.format(
+ "Torch status changed to 0x%x, which is what it already was",
+ status));
+ }
+ return;
+ }
+
+ final int callbackCount = mTorchCallbackMap.size();
+ for (int i = 0; i < callbackCount; i++) {
+ final Handler handler = mTorchCallbackMap.valueAt(i);
+ final TorchCallback callback = mTorchCallbackMap.keyAt(i);
+ postSingleTorchUpdate(callback, handler, id, status);
+ }
+ } // onTorchStatusChangedLocked
+
/**
* Register a callback to be notified about camera device availability with the
* global listener singleton.
@@ -820,6 +1097,22 @@
}
}
+ public void registerTorchCallback(TorchCallback callback, Handler handler) {
+ synchronized(mLock) {
+ Handler oldHandler = mTorchCallbackMap.put(callback, handler);
+ // For new callbacks, provide initial torch information
+ if (oldHandler == null) {
+ updateTorchCallbackLocked(callback, handler);
+ }
+ }
+ }
+
+ public void unregisterTorchCallback(TorchCallback callback) {
+ synchronized(mLock) {
+ mTorchCallbackMap.remove(callback);
+ }
+ }
+
/**
* Callback from camera service notifying the process about camera availability changes
*/
@@ -830,6 +1123,13 @@
}
}
+ @Override
+ public void onTorchStatusChanged(int status, String cameraId) throws RemoteException {
+ synchronized (mLock) {
+ onTorchStatusChangedLocked(status, cameraId);
+ }
+ }
+
/**
* Listener for camera service death.
*
@@ -844,9 +1144,9 @@
mCameraService = null;
- // Tell listeners that the cameras are _available_, because any existing clients
- // will have gotten disconnected. This is optimistic under the assumption that
- // the service will be back shortly.
+ // Tell listeners that the cameras and torch modes are _available_, because any
+ // existing clients will have gotten disconnected. This is optimistic under the
+ // assumption that the service will be back shortly.
//
// Without this, a camera service crash while a camera is open will never signal
// to listeners that previously in-use cameras are now available.
@@ -854,6 +1154,11 @@
String cameraId = mDeviceStatus.keyAt(i);
onStatusChangedLocked(STATUS_PRESENT, cameraId);
}
+ for (int i = 0; i < mTorchStatus.size(); i++) {
+ String cameraId = mTorchStatus.keyAt(i);
+ onTorchStatusChangedLocked(TORCH_STATUS_AVAILABLE_OFF, cameraId);
+ }
+
}
}
diff --git a/core/java/android/hardware/camera2/CameraMetadata.java b/core/java/android/hardware/camera2/CameraMetadata.java
index 1b10858..7f901c8 100644
--- a/core/java/android/hardware/camera2/CameraMetadata.java
+++ b/core/java/android/hardware/camera2/CameraMetadata.java
@@ -288,6 +288,13 @@
*/
public static final int LENS_FACING_BACK = 1;
+ /**
+ * <p>The camera device is an external camera, and has no fixed facing relative to the
+ * device's screen.</p>
+ * @see CameraCharacteristics#LENS_FACING
+ */
+ public static final int LENS_FACING_EXTERNAL = 2;
+
//
// Enumeration values for CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES
//
@@ -367,13 +374,19 @@
* The camera device supports basic manual control of the image post-processing
* stages. This means the following controls are guaranteed to be supported:</p>
* <ul>
- * <li>Manual tonemap control<ul>
+ * <li>
+ * <p>Manual tonemap control</p>
+ * <ul>
* <li>{@link CaptureRequest#TONEMAP_CURVE android.tonemap.curve}</li>
* <li>{@link CaptureRequest#TONEMAP_MODE android.tonemap.mode}</li>
* <li>{@link CameraCharacteristics#TONEMAP_MAX_CURVE_POINTS android.tonemap.maxCurvePoints}</li>
+ * <li>android.tonemap.gamma</li>
+ * <li>android.tonemap.presetCurve</li>
* </ul>
* </li>
- * <li>Manual white balance control<ul>
+ * <li>
+ * <p>Manual white balance control</p>
+ * <ul>
* <li>{@link CaptureRequest#COLOR_CORRECTION_TRANSFORM android.colorCorrection.transform}</li>
* <li>{@link CaptureRequest#COLOR_CORRECTION_GAINS android.colorCorrection.gains}</li>
* </ul>
@@ -432,23 +445,40 @@
public static final int REQUEST_AVAILABLE_CAPABILITIES_RAW = 3;
/**
- * <p>The camera device supports the Zero Shutter Lag use case.</p>
+ * <p>The camera device supports the Zero Shutter Lag reprocessing use case.</p>
* <ul>
- * <li>At least one input stream can be used.</li>
- * <li>RAW_OPAQUE is supported as an output/input format</li>
- * <li>Using RAW_OPAQUE does not cause a frame rate drop
+ * <li>One input stream is supported, that is, <code>{@link CameraCharacteristics#REQUEST_MAX_NUM_INPUT_STREAMS android.request.maxNumInputStreams} == 1</code>.</li>
+ * <li>OPAQUE is supported as an output/input format, that is,
+ * StreamConfigurationMap#getOutputSizes(klass) and
+ * StreamConfigurationMap#getInputSizes(klass) return non empty Size[] and have common
+ * sizes, where klass is android.media.OpaqueImageRingBufferQueue.class. See
+ * android.scaler.availableInputOutputFormatsMap for detailed information about
+ * OPAQUE format.</li>
+ * <li>android.scaler.availableInputOutputFormatsMap has the required map entries.</li>
+ * <li>Using OPAQUE does not cause a frame rate drop
* relative to the sensor's maximum capture rate (at that
- * resolution).</li>
- * <li>RAW_OPAQUE will be reprocessable into both YUV_420_888
+ * resolution), see android.scaler.availableInputOutputFormatsMap for more details.</li>
+ * <li>OPAQUE will be reprocessable into both YUV_420_888
* and JPEG formats.</li>
- * <li>The maximum available resolution for RAW_OPAQUE streams
+ * <li>The maximum available resolution for OPAQUE streams
* (both input/output) will match the maximum available
* resolution of JPEG streams.</li>
+ * <li>Only below controls are effective for reprocessing requests and
+ * will be present in capture results, other controls in reprocess
+ * requests will be ignored by the camera device.<ul>
+ * <li>android.jpeg.*</li>
+ * <li>{@link CaptureRequest#NOISE_REDUCTION_MODE android.noiseReduction.mode}</li>
+ * <li>{@link CaptureRequest#EDGE_MODE android.edge.mode}</li>
* </ul>
+ * </li>
+ * </ul>
+ *
+ * @see CaptureRequest#EDGE_MODE
+ * @see CaptureRequest#NOISE_REDUCTION_MODE
+ * @see CameraCharacteristics#REQUEST_MAX_NUM_INPUT_STREAMS
* @see CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES
- * @hide
*/
- public static final int REQUEST_AVAILABLE_CAPABILITIES_ZSL = 4;
+ public static final int REQUEST_AVAILABLE_CAPABILITIES_OPAQUE_REPROCESSING = 4;
/**
* <p>The camera device supports accurately reporting the sensor settings for many of
@@ -508,6 +538,45 @@
*/
public static final int REQUEST_AVAILABLE_CAPABILITIES_BURST_CAPTURE = 6;
+ /**
+ * <p>The camera device supports the YUV420_888 reprocessing use case, similar as
+ * OPAQUE_REPROCESSING, This capability requires the camera device to support the
+ * following:</p>
+ * <ul>
+ * <li>One input stream is supported, that is, <code>{@link CameraCharacteristics#REQUEST_MAX_NUM_INPUT_STREAMS android.request.maxNumInputStreams} == 1</code>.</li>
+ * <li>YUV420_888 is supported as a common format for both input and output, that is,
+ * StreamConfigurationMap#getOutputSizes(YUV420_888) and
+ * StreamConfigurationMap#getInputSizes(YUV420_888) return non empty Size[] and have
+ * common sizes.</li>
+ * <li>android.scaler.availableInputOutputFormatsMap has the required map entries.</li>
+ * <li>Using YUV420_888 does not cause a frame rate drop
+ * relative to the sensor's maximum capture rate (at that
+ * resolution), see android.scaler.availableInputOutputFormatsMap for more details.</li>
+ * <li>YUV420_888 will be reprocessable into both YUV_420_888
+ * and JPEG formats.</li>
+ * <li>The maximum available resolution for YUV420_888 streams
+ * (both input/output) will match the maximum available
+ * resolution of JPEG streams.</li>
+ * <li>Only the below controls are effective for reprocessing requests and will be
+ * present in capture results. The reprocess requests are from the original capture
+ * results that are assocaited with the intermidate YUV420_888 output buffers.
+ * All other controls in the reprocess requests will be ignored by the camera device.<ul>
+ * <li>android.jpeg.*</li>
+ * <li>{@link CaptureRequest#NOISE_REDUCTION_MODE android.noiseReduction.mode}</li>
+ * <li>{@link CaptureRequest#EDGE_MODE android.edge.mode}</li>
+ * <li>{@link CaptureRequest#REPROCESS_EFFECTIVE_EXPOSURE_FACTOR android.reprocess.effectiveExposureFactor}</li>
+ * </ul>
+ * </li>
+ * </ul>
+ *
+ * @see CaptureRequest#EDGE_MODE
+ * @see CaptureRequest#NOISE_REDUCTION_MODE
+ * @see CaptureRequest#REPROCESS_EFFECTIVE_EXPOSURE_FACTOR
+ * @see CameraCharacteristics#REQUEST_MAX_NUM_INPUT_STREAMS
+ * @see CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES
+ */
+ public static final int REQUEST_AVAILABLE_CAPABILITIES_YUV_REPROCESSING = 7;
+
//
// Enumeration values for CameraCharacteristics#SCALER_CROPPING_TYPE
//
@@ -966,6 +1035,14 @@
*/
public static final int CONTROL_AE_PRECAPTURE_TRIGGER_START = 1;
+ /**
+ * <p>The camera device will cancel any currently active or completed
+ * precapture metering sequence, the auto-exposure routine will return to its
+ * initial state.</p>
+ * @see CaptureRequest#CONTROL_AE_PRECAPTURE_TRIGGER
+ */
+ public static final int CONTROL_AE_PRECAPTURE_TRIGGER_CANCEL = 2;
+
//
// Enumeration values for CaptureRequest#CONTROL_AF_MODE
//
@@ -1823,6 +1900,13 @@
*/
public static final int NOISE_REDUCTION_MODE_HIGH_QUALITY = 2;
+ /**
+ * <p>MINIMAL noise reduction is applied without reducing frame rate relative to
+ * sensor output. </p>
+ * @see CaptureRequest#NOISE_REDUCTION_MODE
+ */
+ public static final int NOISE_REDUCTION_MODE_MINIMAL = 3;
+
//
// Enumeration values for CaptureRequest#SENSOR_TEST_PATTERN_MODE
//
@@ -2026,6 +2110,43 @@
*/
public static final int TONEMAP_MODE_HIGH_QUALITY = 2;
+ /**
+ * <p>Use the gamma value specified in android.tonemap.gamma to peform
+ * tonemapping.</p>
+ * <p>All color enhancement and tonemapping must be disabled, except
+ * for applying the tonemapping curve specified by android.tonemap.gamma.</p>
+ * <p>Must not slow down frame rate relative to raw sensor output.</p>
+ * @see CaptureRequest#TONEMAP_MODE
+ */
+ public static final int TONEMAP_MODE_GAMMA_VALUE = 3;
+
+ /**
+ * <p>Use the preset tonemapping curve specified in
+ * android.tonemap.presetCurve to peform tonemapping.</p>
+ * <p>All color enhancement and tonemapping must be disabled, except
+ * for applying the tonemapping curve specified by
+ * android.tonemap.presetCurve.</p>
+ * <p>Must not slow down frame rate relative to raw sensor output.</p>
+ * @see CaptureRequest#TONEMAP_MODE
+ */
+ public static final int TONEMAP_MODE_PRESET_CURVE = 4;
+
+ //
+ // Enumeration values for CaptureRequest#TONEMAP_PRESET_CURVE
+ //
+
+ /**
+ * <p>Tonemapping curve is defined by sRGB</p>
+ * @see CaptureRequest#TONEMAP_PRESET_CURVE
+ */
+ public static final int TONEMAP_PRESET_CURVE_SRGB = 0;
+
+ /**
+ * <p>Tonemapping curve is defined by ITU-R BT.709</p>
+ * @see CaptureRequest#TONEMAP_PRESET_CURVE
+ */
+ public static final int TONEMAP_PRESET_CURVE_REC709 = 1;
+
//
// Enumeration values for CaptureResult#CONTROL_AE_STATE
//
@@ -2073,7 +2194,10 @@
* <p>AE has been asked to do a precapture sequence
* and is currently executing it.</p>
* <p>Precapture can be triggered through setting
- * {@link CaptureRequest#CONTROL_AE_PRECAPTURE_TRIGGER android.control.aePrecaptureTrigger} to START.</p>
+ * {@link CaptureRequest#CONTROL_AE_PRECAPTURE_TRIGGER android.control.aePrecaptureTrigger} to START. Currently
+ * active and completed (if it causes camera device internal AE lock) precapture
+ * metering sequence can be canceled through setting
+ * {@link CaptureRequest#CONTROL_AE_PRECAPTURE_TRIGGER android.control.aePrecaptureTrigger} to CANCEL.</p>
* <p>Once PRECAPTURE completes, AE will transition to CONVERGED
* or FLASH_REQUIRED as appropriate. This is a transient
* state, the camera device may skip reporting this state in
diff --git a/core/java/android/hardware/camera2/CaptureRequest.java b/core/java/android/hardware/camera2/CaptureRequest.java
index b417496..7569ea5 100644
--- a/core/java/android/hardware/camera2/CaptureRequest.java
+++ b/core/java/android/hardware/camera2/CaptureRequest.java
@@ -552,6 +552,8 @@
* in this matrix result metadata. The transform should keep the magnitude
* of the output color values within <code>[0, 1.0]</code> (assuming input color
* values is within the normalized range <code>[0, 1.0]</code>), or clipping may occur.</p>
+ * <p>The valid range of each matrix element varies on different devices, but
+ * values within [-1.5, 3.0] are guaranteed not to be clipped.</p>
* <p><b>Units</b>: Unitless scale factors</p>
* <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
* <p><b>Full capability</b> -
@@ -575,6 +577,10 @@
* TRANSFORM_MATRIX.</p>
* <p>The gains in the result metadata are the gains actually
* applied by the camera device to the current frame.</p>
+ * <p>The valid range of gains varies on different devices, but gains
+ * between [1.0, 3.0] are guaranteed not to be clipped. Even if a given
+ * device allows gains below 1.0, this is usually not recommended because
+ * this can create color artifacts.</p>
* <p><b>Units</b>: Unitless gain factors</p>
* <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
* <p><b>Full capability</b> -
@@ -724,7 +730,14 @@
* ({@link CaptureRequest#SENSOR_EXPOSURE_TIME android.sensor.exposureTime}) and sensitivity ({@link CaptureRequest#SENSOR_SENSITIVITY android.sensor.sensitivity})
* parameters. The flash may be fired if the {@link CaptureRequest#CONTROL_AE_MODE android.control.aeMode}
* is ON_AUTO_FLASH/ON_AUTO_FLASH_REDEYE and the scene is too dark. If the
- * {@link CaptureRequest#CONTROL_AE_MODE android.control.aeMode} is ON_ALWAYS_FLASH, the scene may become overexposed.</p>
+ * {@link CaptureRequest#CONTROL_AE_MODE android.control.aeMode} is ON_ALWAYS_FLASH, the scene may become overexposed.
+ * Similarly, AE precapture trigger CANCEL has no effect when AE is already locked.</p>
+ * <p>When an AE precapture sequence is triggered, AE unlock will not be able to unlock
+ * the AE if AE is locked by the camera device internally during precapture metering
+ * sequence In other words, submitting requests with AE unlock has no effect for an
+ * ongoing precapture metering sequence. Otherwise, the precapture metering sequence
+ * will never succeed in a sequence of preview requests where AE lock is always set
+ * to <code>false</code>.</p>
* <p>Since the camera device has a pipeline of in-flight requests, the settings that
* get locked do not necessarily correspond to the settings that were present in the
* latest capture result received from the camera device, since additional captures
@@ -869,6 +882,11 @@
* included at all in the request settings. When included and
* set to START, the camera device will trigger the auto-exposure (AE)
* precapture metering sequence.</p>
+ * <p>When set to CANCEL, the camera device will cancel any active
+ * precapture metering trigger, and return to its initial AE state.
+ * If a precapture metering sequence is already completed, and the camera
+ * device has implicitly locked the AE for subsequent still capture, the
+ * CANCEL trigger will unlock the AE and return to its initial AE state.</p>
* <p>The precapture sequence should be triggered before starting a
* high-quality still capture for final metering decisions to
* be made, and for firing pre-capture flash pulses to estimate
@@ -884,7 +902,11 @@
* submitted. To ensure that the AE routine restarts normal scan, the application should
* submit a request with <code>{@link CaptureRequest#CONTROL_AE_LOCK android.control.aeLock} == true</code>, followed by a request
* with <code>{@link CaptureRequest#CONTROL_AE_LOCK android.control.aeLock} == false</code>, if the application decides not to submit a
- * still capture request after the precapture sequence completes.</p>
+ * still capture request after the precapture sequence completes. Alternatively, for
+ * API level 23 or newer devices, the CANCEL can be used to unlock the camera device
+ * internally locked AE if the application doesn't submit a still capture request after
+ * the AE precapture trigger. Note that, the CANCEL was added in API level 23, and must not
+ * be used in devices that have earlier API levels.</p>
* <p>The exact effect of auto-exposure (AE) precapture trigger
* depends on the current AE mode and state; see
* {@link CaptureResult#CONTROL_AE_STATE android.control.aeState} for AE precapture state transition
@@ -897,6 +919,7 @@
* <ul>
* <li>{@link #CONTROL_AE_PRECAPTURE_TRIGGER_IDLE IDLE}</li>
* <li>{@link #CONTROL_AE_PRECAPTURE_TRIGGER_START START}</li>
+ * <li>{@link #CONTROL_AE_PRECAPTURE_TRIGGER_CANCEL CANCEL}</li>
* </ul></p>
* <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
* <p><b>Limited capability</b> -
@@ -909,6 +932,7 @@
* @see CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL
* @see #CONTROL_AE_PRECAPTURE_TRIGGER_IDLE
* @see #CONTROL_AE_PRECAPTURE_TRIGGER_START
+ * @see #CONTROL_AE_PRECAPTURE_TRIGGER_CANCEL
*/
@PublicKey
public static final Key<Integer> CONTROL_AE_PRECAPTURE_TRIGGER =
@@ -1164,7 +1188,7 @@
* <p>This control (except for MANUAL) is only effective if
* <code>{@link CaptureRequest#CONTROL_MODE android.control.mode} != OFF</code> and any 3A routine is active.</p>
* <p>ZERO_SHUTTER_LAG will be supported if {@link CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES android.request.availableCapabilities}
- * contains ZSL. MANUAL will be supported if {@link CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES android.request.availableCapabilities}
+ * contains OPAQUE_REPROCESSING. MANUAL will be supported if {@link CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES android.request.availableCapabilities}
* contains MANUAL_SENSOR. Other intent values are always supported.</p>
* <p><b>Possible values:</b>
* <ul>
@@ -1249,10 +1273,6 @@
* update, as if this frame is never captured. This mode can be used in the scenario
* where the application doesn't want a 3A manual control capture to affect
* the subsequent auto 3A capture results.</p>
- * <p>LEGACY mode devices will only support AUTO and USE_SCENE_MODE modes.
- * LIMITED mode devices will only support OFF and OFF_KEEP_STATE if they
- * support the MANUAL_SENSOR and MANUAL_POST_PROCSESING capabilities.
- * FULL mode devices will always support OFF and OFF_KEEP_STATE.</p>
* <p><b>Possible values:</b>
* <ul>
* <li>{@link #CONTROL_MODE_OFF OFF}</li>
@@ -1260,9 +1280,12 @@
* <li>{@link #CONTROL_MODE_USE_SCENE_MODE USE_SCENE_MODE}</li>
* <li>{@link #CONTROL_MODE_OFF_KEEP_STATE OFF_KEEP_STATE}</li>
* </ul></p>
+ * <p><b>Available values for this device:</b><br>
+ * {@link CameraCharacteristics#CONTROL_AVAILABLE_MODES android.control.availableModes}</p>
* <p>This key is available on all devices.</p>
*
* @see CaptureRequest#CONTROL_AF_MODE
+ * @see CameraCharacteristics#CONTROL_AVAILABLE_MODES
* @see #CONTROL_MODE_OFF
* @see #CONTROL_MODE_AUTO
* @see #CONTROL_MODE_USE_SCENE_MODE
@@ -1382,6 +1405,10 @@
* camera device will use the highest-quality enhancement algorithms,
* even if it slows down capture rate. FAST means the camera device will
* not slow down capture rate when applying edge enhancement.</p>
+ * <p>For YUV_REPROCESSING, these FAST/HIGH_QUALITY modes both mean that the camera
+ * device will apply FAST/HIGH_QUALITY YUV-domain edge enhancement, respectively.
+ * The camera device may adjust its internal noise reduction parameters for best
+ * image quality based on the {@link CaptureRequest#REPROCESS_EFFECTIVE_EXPOSURE_FACTOR android.reprocess.effectiveExposureFactor}, if it is set.</p>
* <p><b>Possible values:</b>
* <ul>
* <li>{@link #EDGE_MODE_OFF OFF}</li>
@@ -1397,6 +1424,7 @@
*
* @see CameraCharacteristics#EDGE_AVAILABLE_EDGE_MODES
* @see CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL
+ * @see CaptureRequest#REPROCESS_EFFECTIVE_EXPOSURE_FACTOR
* @see #EDGE_MODE_OFF
* @see #EDGE_MODE_FAST
* @see #EDGE_MODE_HIGH_QUALITY
@@ -1761,18 +1789,28 @@
/**
* <p>Mode of operation for the noise reduction algorithm.</p>
* <p>The noise reduction algorithm attempts to improve image quality by removing
- * excessive noise added by the capture process, especially in dark conditions.
- * OFF means no noise reduction will be applied by the camera device.</p>
+ * excessive noise added by the capture process, especially in dark conditions.</p>
+ * <p>OFF means no noise reduction will be applied by the camera device, for both raw and
+ * YUV domain.</p>
+ * <p>MINIMAL means that only sensor raw domain basic noise reduction is enabled ,to remove
+ * demosaicing or other processing artifacts. For YUV_REPROCESSING, MINIMAL is same as OFF.
+ * This mode is optional, may not be support by all devices. The application should check
+ * {@link CameraCharacteristics#NOISE_REDUCTION_AVAILABLE_NOISE_REDUCTION_MODES android.noiseReduction.availableNoiseReductionModes} before using it.</p>
* <p>FAST/HIGH_QUALITY both mean camera device determined noise filtering
* will be applied. HIGH_QUALITY mode indicates that the camera device
* will use the highest-quality noise filtering algorithms,
* even if it slows down capture rate. FAST means the camera device will not
* slow down capture rate when applying noise filtering.</p>
+ * <p>For YUV_REPROCESSING, these FAST/HIGH_QUALITY modes both mean that the camera device
+ * will apply FAST/HIGH_QUALITY YUV domain noise reduction, respectively. The camera device
+ * may adjust the noise reduction parameters for best image quality based on the
+ * {@link CaptureRequest#REPROCESS_EFFECTIVE_EXPOSURE_FACTOR android.reprocess.effectiveExposureFactor} if it is set.</p>
* <p><b>Possible values:</b>
* <ul>
* <li>{@link #NOISE_REDUCTION_MODE_OFF OFF}</li>
* <li>{@link #NOISE_REDUCTION_MODE_FAST FAST}</li>
* <li>{@link #NOISE_REDUCTION_MODE_HIGH_QUALITY HIGH_QUALITY}</li>
+ * <li>{@link #NOISE_REDUCTION_MODE_MINIMAL MINIMAL}</li>
* </ul></p>
* <p><b>Available values for this device:</b><br>
* {@link CameraCharacteristics#NOISE_REDUCTION_AVAILABLE_NOISE_REDUCTION_MODES android.noiseReduction.availableNoiseReductionModes}</p>
@@ -1783,9 +1821,11 @@
*
* @see CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL
* @see CameraCharacteristics#NOISE_REDUCTION_AVAILABLE_NOISE_REDUCTION_MODES
+ * @see CaptureRequest#REPROCESS_EFFECTIVE_EXPOSURE_FACTOR
* @see #NOISE_REDUCTION_MODE_OFF
* @see #NOISE_REDUCTION_MODE_FAST
* @see #NOISE_REDUCTION_MODE_HIGH_QUALITY
+ * @see #NOISE_REDUCTION_MODE_MINIMAL
*/
@PublicKey
public static final Key<Integer> NOISE_REDUCTION_MODE =
@@ -2078,6 +2118,8 @@
* <li>{@link #SHADING_MODE_FAST FAST}</li>
* <li>{@link #SHADING_MODE_HIGH_QUALITY HIGH_QUALITY}</li>
* </ul></p>
+ * <p><b>Available values for this device:</b><br>
+ * {@link CameraCharacteristics#SHADING_AVAILABLE_MODES android.shading.availableModes}</p>
* <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
* <p><b>Full capability</b> -
* Present on all camera devices that report being {@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL_FULL HARDWARE_LEVEL_FULL} devices in the
@@ -2086,6 +2128,7 @@
* @see CaptureRequest#CONTROL_AE_MODE
* @see CaptureRequest#CONTROL_AWB_MODE
* @see CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL
+ * @see CameraCharacteristics#SHADING_AVAILABLE_MODES
* @see CaptureResult#STATISTICS_LENS_SHADING_CORRECTION_MAP
* @see CaptureRequest#STATISTICS_LENS_SHADING_MAP_MODE
* @see #SHADING_MODE_OFF
@@ -2148,12 +2191,15 @@
* <li>{@link #STATISTICS_LENS_SHADING_MAP_MODE_OFF OFF}</li>
* <li>{@link #STATISTICS_LENS_SHADING_MAP_MODE_ON ON}</li>
* </ul></p>
+ * <p><b>Available values for this device:</b><br>
+ * {@link CameraCharacteristics#STATISTICS_INFO_AVAILABLE_LENS_SHADING_MAP_MODES android.statistics.info.availableLensShadingMapModes}</p>
* <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
* <p><b>Full capability</b> -
* Present on all camera devices that report being {@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL_FULL HARDWARE_LEVEL_FULL} devices in the
* {@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL android.info.supportedHardwareLevel} key</p>
*
* @see CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL
+ * @see CameraCharacteristics#STATISTICS_INFO_AVAILABLE_LENS_SHADING_MAP_MODES
* @see #STATISTICS_LENS_SHADING_MAP_MODE_OFF
* @see #STATISTICS_LENS_SHADING_MAP_MODE_ON
*/
@@ -2340,6 +2386,8 @@
* <li>{@link #TONEMAP_MODE_CONTRAST_CURVE CONTRAST_CURVE}</li>
* <li>{@link #TONEMAP_MODE_FAST FAST}</li>
* <li>{@link #TONEMAP_MODE_HIGH_QUALITY HIGH_QUALITY}</li>
+ * <li>{@link #TONEMAP_MODE_GAMMA_VALUE GAMMA_VALUE}</li>
+ * <li>{@link #TONEMAP_MODE_PRESET_CURVE PRESET_CURVE}</li>
* </ul></p>
* <p><b>Available values for this device:</b><br>
* {@link CameraCharacteristics#TONEMAP_AVAILABLE_TONE_MAP_MODES android.tonemap.availableToneMapModes}</p>
@@ -2355,12 +2403,60 @@
* @see #TONEMAP_MODE_CONTRAST_CURVE
* @see #TONEMAP_MODE_FAST
* @see #TONEMAP_MODE_HIGH_QUALITY
+ * @see #TONEMAP_MODE_GAMMA_VALUE
+ * @see #TONEMAP_MODE_PRESET_CURVE
*/
@PublicKey
public static final Key<Integer> TONEMAP_MODE =
new Key<Integer>("android.tonemap.mode", int.class);
/**
+ * <p>Tonemapping curve to use when {@link CaptureRequest#TONEMAP_MODE android.tonemap.mode} is
+ * GAMMA_VALUE</p>
+ * <p>The tonemap curve will be defined the following formula:
+ * * OUT = pow(IN, 1.0 / gamma)
+ * where IN and OUT is the input pixel value scaled to range [0.0, 1.0],
+ * pow is the power function and gamma is the gamma value specified by this
+ * key.</p>
+ * <p>The same curve will be applied to all color channels. The camera device
+ * may clip the input gamma value to its supported range. The actual applied
+ * value will be returned in capture result.</p>
+ * <p>The valid range of gamma value varies on different devices, but values
+ * within [1.0, 5.0] are guaranteed not to be clipped.</p>
+ * <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
+ *
+ * @see CaptureRequest#TONEMAP_MODE
+ */
+ @PublicKey
+ public static final Key<Float> TONEMAP_GAMMA =
+ new Key<Float>("android.tonemap.gamma", float.class);
+
+ /**
+ * <p>Tonemapping curve to use when {@link CaptureRequest#TONEMAP_MODE android.tonemap.mode} is
+ * PRESET_CURVE</p>
+ * <p>The tonemap curve will be defined by specified standard.</p>
+ * <p>sRGB (approximated by 16 control points):</p>
+ * <p><img alt="sRGB tonemapping curve" src="../../../../images/camera2/metadata/android.tonemap.curveRed/srgb_tonemap.png" /></p>
+ * <p>Rec. 709 (approximated by 16 control points):</p>
+ * <p><img alt="Rec. 709 tonemapping curve" src="../../../../images/camera2/metadata/android.tonemap.curveRed/rec709_tonemap.png" /></p>
+ * <p>Note that above figures show a 16 control points approximation of preset
+ * curves. Camera devices may apply a different approximation to the curve.</p>
+ * <p><b>Possible values:</b>
+ * <ul>
+ * <li>{@link #TONEMAP_PRESET_CURVE_SRGB SRGB}</li>
+ * <li>{@link #TONEMAP_PRESET_CURVE_REC709 REC709}</li>
+ * </ul></p>
+ * <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
+ *
+ * @see CaptureRequest#TONEMAP_MODE
+ * @see #TONEMAP_PRESET_CURVE_SRGB
+ * @see #TONEMAP_PRESET_CURVE_REC709
+ */
+ @PublicKey
+ public static final Key<Integer> TONEMAP_PRESET_CURVE =
+ new Key<Integer>("android.tonemap.presetCurve", int.class);
+
+ /**
* <p>This LED is nominally used to indicate to the user
* that the camera is powered on and may be streaming images back to the
* Application Processor. In certain rare circumstances, the OS may
@@ -2426,6 +2522,52 @@
public static final Key<Boolean> BLACK_LEVEL_LOCK =
new Key<Boolean>("android.blackLevel.lock", boolean.class);
+ /**
+ * <p>The amount of exposure time increase factor applied to the original output
+ * frame by the application processing before sending for reprocessing.</p>
+ * <p>This is optional, and will be supported if the camera device supports YUV_REPROCESSING
+ * capability ({@link CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES android.request.availableCapabilities} contains YUV_REPROCESSING).</p>
+ * <p>For some YUV reprocessing use cases, the application may choose to filter the original
+ * output frames to effectively reduce the noise to the same level as a frame that was
+ * captured with longer exposure time. To be more specific, assuming the original captured
+ * images were captured with a sensitivity of S and an exposure time of T, the model in
+ * the camera device is that the amount of noise in the image would be approximately what
+ * would be expected if the original capture parameters had been a sensitivity of
+ * S/effectiveExposureFactor and an exposure time of T*effectiveExposureFactor, rather
+ * than S and T respectively. If the captured images were processed by the application
+ * before being sent for reprocessing, then the application may have used image processing
+ * algorithms and/or multi-frame image fusion to reduce the noise in the
+ * application-processed images (input images). By using the effectiveExposureFactor
+ * control, the application can communicate to the camera device the actual noise level
+ * improvement in the application-processed image. With this information, the camera
+ * device can select appropriate noise reduction and edge enhancement parameters to avoid
+ * excessive noise reduction ({@link CaptureRequest#NOISE_REDUCTION_MODE android.noiseReduction.mode}) and insufficient edge
+ * enhancement ({@link CaptureRequest#EDGE_MODE android.edge.mode}) being applied to the reprocessed frames.</p>
+ * <p>For example, for multi-frame image fusion use case, the application may fuse
+ * multiple output frames together to a final frame for reprocessing. When N image are
+ * fused into 1 image for reprocessing, the exposure time increase factor could be up to
+ * square root of N (based on a simple photon shot noise model). The camera device will
+ * adjust the reprocessing noise reduction and edge enhancement parameters accordingly to
+ * produce the best quality images.</p>
+ * <p>This is relative factor, 1.0 indicates the application hasn't processed the input
+ * buffer in a way that affects its effective exposure time.</p>
+ * <p>This control is only effective for YUV reprocessing capture request. For noise
+ * reduction reprocessing, it is only effective when <code>{@link CaptureRequest#NOISE_REDUCTION_MODE android.noiseReduction.mode} != OFF</code>.
+ * Similarly, for edge enhancement reprocessing, it is only effective when
+ * <code>{@link CaptureRequest#EDGE_MODE android.edge.mode} != OFF</code>.</p>
+ * <p><b>Units</b>: Relative exposure time increase factor.</p>
+ * <p><b>Range of valid values:</b><br>
+ * >= 1.0</p>
+ * <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
+ *
+ * @see CaptureRequest#EDGE_MODE
+ * @see CaptureRequest#NOISE_REDUCTION_MODE
+ * @see CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES
+ */
+ @PublicKey
+ public static final Key<Float> REPROCESS_EFFECTIVE_EXPOSURE_FACTOR =
+ new Key<Float>("android.reprocess.effectiveExposureFactor", float.class);
+
/*~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~
* End generated code
*~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~O@*/
diff --git a/core/java/android/hardware/camera2/CaptureResult.java b/core/java/android/hardware/camera2/CaptureResult.java
index f17100d..9d48a4c 100644
--- a/core/java/android/hardware/camera2/CaptureResult.java
+++ b/core/java/android/hardware/camera2/CaptureResult.java
@@ -403,6 +403,8 @@
* in this matrix result metadata. The transform should keep the magnitude
* of the output color values within <code>[0, 1.0]</code> (assuming input color
* values is within the normalized range <code>[0, 1.0]</code>), or clipping may occur.</p>
+ * <p>The valid range of each matrix element varies on different devices, but
+ * values within [-1.5, 3.0] are guaranteed not to be clipped.</p>
* <p><b>Units</b>: Unitless scale factors</p>
* <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
* <p><b>Full capability</b> -
@@ -426,6 +428,10 @@
* TRANSFORM_MATRIX.</p>
* <p>The gains in the result metadata are the gains actually
* applied by the camera device to the current frame.</p>
+ * <p>The valid range of gains varies on different devices, but gains
+ * between [1.0, 3.0] are guaranteed not to be clipped. Even if a given
+ * device allows gains below 1.0, this is usually not recommended because
+ * this can create color artifacts.</p>
* <p><b>Units</b>: Unitless gain factors</p>
* <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
* <p><b>Full capability</b> -
@@ -575,7 +581,14 @@
* ({@link CaptureRequest#SENSOR_EXPOSURE_TIME android.sensor.exposureTime}) and sensitivity ({@link CaptureRequest#SENSOR_SENSITIVITY android.sensor.sensitivity})
* parameters. The flash may be fired if the {@link CaptureRequest#CONTROL_AE_MODE android.control.aeMode}
* is ON_AUTO_FLASH/ON_AUTO_FLASH_REDEYE and the scene is too dark. If the
- * {@link CaptureRequest#CONTROL_AE_MODE android.control.aeMode} is ON_ALWAYS_FLASH, the scene may become overexposed.</p>
+ * {@link CaptureRequest#CONTROL_AE_MODE android.control.aeMode} is ON_ALWAYS_FLASH, the scene may become overexposed.
+ * Similarly, AE precapture trigger CANCEL has no effect when AE is already locked.</p>
+ * <p>When an AE precapture sequence is triggered, AE unlock will not be able to unlock
+ * the AE if AE is locked by the camera device internally during precapture metering
+ * sequence In other words, submitting requests with AE unlock has no effect for an
+ * ongoing precapture metering sequence. Otherwise, the precapture metering sequence
+ * will never succeed in a sequence of preview requests where AE lock is always set
+ * to <code>false</code>.</p>
* <p>Since the camera device has a pipeline of in-flight requests, the settings that
* get locked do not necessarily correspond to the settings that were present in the
* latest capture result received from the camera device, since additional captures
@@ -720,6 +733,11 @@
* included at all in the request settings. When included and
* set to START, the camera device will trigger the auto-exposure (AE)
* precapture metering sequence.</p>
+ * <p>When set to CANCEL, the camera device will cancel any active
+ * precapture metering trigger, and return to its initial AE state.
+ * If a precapture metering sequence is already completed, and the camera
+ * device has implicitly locked the AE for subsequent still capture, the
+ * CANCEL trigger will unlock the AE and return to its initial AE state.</p>
* <p>The precapture sequence should be triggered before starting a
* high-quality still capture for final metering decisions to
* be made, and for firing pre-capture flash pulses to estimate
@@ -735,7 +753,11 @@
* submitted. To ensure that the AE routine restarts normal scan, the application should
* submit a request with <code>{@link CaptureRequest#CONTROL_AE_LOCK android.control.aeLock} == true</code>, followed by a request
* with <code>{@link CaptureRequest#CONTROL_AE_LOCK android.control.aeLock} == false</code>, if the application decides not to submit a
- * still capture request after the precapture sequence completes.</p>
+ * still capture request after the precapture sequence completes. Alternatively, for
+ * API level 23 or newer devices, the CANCEL can be used to unlock the camera device
+ * internally locked AE if the application doesn't submit a still capture request after
+ * the AE precapture trigger. Note that, the CANCEL was added in API level 23, and must not
+ * be used in devices that have earlier API levels.</p>
* <p>The exact effect of auto-exposure (AE) precapture trigger
* depends on the current AE mode and state; see
* {@link CaptureResult#CONTROL_AE_STATE android.control.aeState} for AE precapture state transition
@@ -748,6 +770,7 @@
* <ul>
* <li>{@link #CONTROL_AE_PRECAPTURE_TRIGGER_IDLE IDLE}</li>
* <li>{@link #CONTROL_AE_PRECAPTURE_TRIGGER_START START}</li>
+ * <li>{@link #CONTROL_AE_PRECAPTURE_TRIGGER_CANCEL CANCEL}</li>
* </ul></p>
* <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
* <p><b>Limited capability</b> -
@@ -760,6 +783,7 @@
* @see CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL
* @see #CONTROL_AE_PRECAPTURE_TRIGGER_IDLE
* @see #CONTROL_AE_PRECAPTURE_TRIGGER_START
+ * @see #CONTROL_AE_PRECAPTURE_TRIGGER_CANCEL
*/
@PublicKey
public static final Key<Integer> CONTROL_AE_PRECAPTURE_TRIGGER =
@@ -892,11 +916,29 @@
* <td align="center">Ready for high-quality capture</td>
* </tr>
* <tr>
- * <td align="center">Any state</td>
+ * <td align="center">LOCKED</td>
+ * <td align="center">aeLock is ON and aePrecaptureTrigger is START</td>
+ * <td align="center">LOCKED</td>
+ * <td align="center">Precapture trigger is ignored when AE is already locked</td>
+ * </tr>
+ * <tr>
+ * <td align="center">LOCKED</td>
+ * <td align="center">aeLock is ON and aePrecaptureTrigger is CANCEL</td>
+ * <td align="center">LOCKED</td>
+ * <td align="center">Precapture trigger is ignored when AE is already locked</td>
+ * </tr>
+ * <tr>
+ * <td align="center">Any state (excluding LOCKED)</td>
* <td align="center">{@link CaptureRequest#CONTROL_AE_PRECAPTURE_TRIGGER android.control.aePrecaptureTrigger} is START</td>
* <td align="center">PRECAPTURE</td>
* <td align="center">Start AE precapture metering sequence</td>
* </tr>
+ * <tr>
+ * <td align="center">Any state (excluding LOCKED)</td>
+ * <td align="center">{@link CaptureRequest#CONTROL_AE_PRECAPTURE_TRIGGER android.control.aePrecaptureTrigger} is CANCEL</td>
+ * <td align="center">INACTIVE</td>
+ * <td align="center">Currently active precapture metering sequence is canceled</td>
+ * </tr>
* </tbody>
* </table>
* <p>For the above table, the camera device may skip reporting any state changes that happen
@@ -922,18 +964,30 @@
* <td align="center">Values are already good, transient states are skipped by camera device.</td>
* </tr>
* <tr>
- * <td align="center">Any state</td>
+ * <td align="center">Any state (excluding LOCKED)</td>
* <td align="center">{@link CaptureRequest#CONTROL_AE_PRECAPTURE_TRIGGER android.control.aePrecaptureTrigger} is START, sequence done</td>
* <td align="center">FLASH_REQUIRED</td>
* <td align="center">Converged but too dark w/o flash after a precapture sequence, transient states are skipped by camera device.</td>
* </tr>
* <tr>
- * <td align="center">Any state</td>
+ * <td align="center">Any state (excluding LOCKED)</td>
* <td align="center">{@link CaptureRequest#CONTROL_AE_PRECAPTURE_TRIGGER android.control.aePrecaptureTrigger} is START, sequence done</td>
* <td align="center">CONVERGED</td>
* <td align="center">Converged after a precapture sequence, transient states are skipped by camera device.</td>
* </tr>
* <tr>
+ * <td align="center">Any state (excluding LOCKED)</td>
+ * <td align="center">{@link CaptureRequest#CONTROL_AE_PRECAPTURE_TRIGGER android.control.aePrecaptureTrigger} is CANCEL, converged</td>
+ * <td align="center">FLASH_REQUIRED</td>
+ * <td align="center">Converged but too dark w/o flash after a precapture sequence is canceled, transient states are skipped by camera device.</td>
+ * </tr>
+ * <tr>
+ * <td align="center">Any state (excluding LOCKED)</td>
+ * <td align="center">{@link CaptureRequest#CONTROL_AE_PRECAPTURE_TRIGGER android.control.aePrecaptureTrigger} is CANCEL, converged</td>
+ * <td align="center">CONVERGED</td>
+ * <td align="center">Converged after a precapture sequenceis canceled, transient states are skipped by camera device.</td>
+ * </tr>
+ * <tr>
* <td align="center">CONVERGED</td>
* <td align="center">Camera device finished AE scan</td>
* <td align="center">FLASH_REQUIRED</td>
@@ -1637,7 +1691,7 @@
* <p>This control (except for MANUAL) is only effective if
* <code>{@link CaptureRequest#CONTROL_MODE android.control.mode} != OFF</code> and any 3A routine is active.</p>
* <p>ZERO_SHUTTER_LAG will be supported if {@link CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES android.request.availableCapabilities}
- * contains ZSL. MANUAL will be supported if {@link CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES android.request.availableCapabilities}
+ * contains OPAQUE_REPROCESSING. MANUAL will be supported if {@link CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES android.request.availableCapabilities}
* contains MANUAL_SENSOR. Other intent values are always supported.</p>
* <p><b>Possible values:</b>
* <ul>
@@ -1865,10 +1919,6 @@
* update, as if this frame is never captured. This mode can be used in the scenario
* where the application doesn't want a 3A manual control capture to affect
* the subsequent auto 3A capture results.</p>
- * <p>LEGACY mode devices will only support AUTO and USE_SCENE_MODE modes.
- * LIMITED mode devices will only support OFF and OFF_KEEP_STATE if they
- * support the MANUAL_SENSOR and MANUAL_POST_PROCSESING capabilities.
- * FULL mode devices will always support OFF and OFF_KEEP_STATE.</p>
* <p><b>Possible values:</b>
* <ul>
* <li>{@link #CONTROL_MODE_OFF OFF}</li>
@@ -1876,9 +1926,12 @@
* <li>{@link #CONTROL_MODE_USE_SCENE_MODE USE_SCENE_MODE}</li>
* <li>{@link #CONTROL_MODE_OFF_KEEP_STATE OFF_KEEP_STATE}</li>
* </ul></p>
+ * <p><b>Available values for this device:</b><br>
+ * {@link CameraCharacteristics#CONTROL_AVAILABLE_MODES android.control.availableModes}</p>
* <p>This key is available on all devices.</p>
*
* @see CaptureRequest#CONTROL_AF_MODE
+ * @see CameraCharacteristics#CONTROL_AVAILABLE_MODES
* @see #CONTROL_MODE_OFF
* @see #CONTROL_MODE_AUTO
* @see #CONTROL_MODE_USE_SCENE_MODE
@@ -1998,6 +2051,10 @@
* camera device will use the highest-quality enhancement algorithms,
* even if it slows down capture rate. FAST means the camera device will
* not slow down capture rate when applying edge enhancement.</p>
+ * <p>For YUV_REPROCESSING, these FAST/HIGH_QUALITY modes both mean that the camera
+ * device will apply FAST/HIGH_QUALITY YUV-domain edge enhancement, respectively.
+ * The camera device may adjust its internal noise reduction parameters for best
+ * image quality based on the {@link CaptureRequest#REPROCESS_EFFECTIVE_EXPOSURE_FACTOR android.reprocess.effectiveExposureFactor}, if it is set.</p>
* <p><b>Possible values:</b>
* <ul>
* <li>{@link #EDGE_MODE_OFF OFF}</li>
@@ -2013,6 +2070,7 @@
*
* @see CameraCharacteristics#EDGE_AVAILABLE_EDGE_MODES
* @see CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL
+ * @see CaptureRequest#REPROCESS_EFFECTIVE_EXPOSURE_FACTOR
* @see #EDGE_MODE_OFF
* @see #EDGE_MODE_FAST
* @see #EDGE_MODE_HIGH_QUALITY
@@ -2473,20 +2531,153 @@
new Key<Integer>("android.lens.state", int.class);
/**
+ * <p>The orientation of the camera relative to the sensor
+ * coordinate system.</p>
+ * <p>The four coefficients that describe the quarternion
+ * rotation from the Android sensor coordinate system to a
+ * camera-aligned coordinate system where the X-axis is
+ * aligned with the long side of the image sensor, the Y-axis
+ * is aligned with the short side of the image sensor, and
+ * the Z-axis is aligned with the optical axis of the sensor.</p>
+ * <p>To convert from the quarternion coefficients <code>(x,y,z,w)</code>
+ * to the axis of rotation <code>(a_x, a_y, a_z)</code> and rotation
+ * amount <code>theta</code>, the following formulas can be used:</p>
+ * <pre><code> theta = 2 * acos(w)
+ * a_x = x / sin(theta/2)
+ * a_y = y / sin(theta/2)
+ * a_z = z / sin(theta/2)
+ * </code></pre>
+ * <p>To create a 3x3 rotation matrix that applies the rotation
+ * defined by this quarternion, the following matrix can be
+ * used:</p>
+ * <pre><code>R = [ 1 - 2y^2 - 2z^2, 2xy - 2zw, 2xz + 2yw,
+ * 2xy + 2zw, 1 - 2x^2 - 2z^2, 2yz - 2xw,
+ * 2xz - 2yw, 2yz + 2xw, 1 - 2x^2 - 2y^2 ]
+ * </code></pre>
+ * <p>This matrix can then be used to apply the rotation to a
+ * column vector point with</p>
+ * <p><code>p' = Rp</code></p>
+ * <p>where <code>p</code> is in the device sensor coordinate system, and
+ * <code>p'</code> is in the camera-oriented coordinate system.</p>
+ * <p><b>Units</b>:
+ * Quarternion coefficients</p>
+ * <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
+ */
+ @PublicKey
+ public static final Key<float[]> LENS_POSE_ROTATION =
+ new Key<float[]>("android.lens.poseRotation", float[].class);
+
+ /**
+ * <p>Position of the camera optical center.</p>
+ * <p>As measured in the device sensor coordinate system, the
+ * position of the camera device's optical center, as a
+ * three-dimensional vector <code>(x,y,z)</code>.</p>
+ * <p>To transform a world position to a camera-device centered
+ * coordinate system, the position must be translated by this
+ * vector and then rotated by {@link CameraCharacteristics#LENS_POSE_ROTATION android.lens.poseRotation}.</p>
+ * <p><b>Units</b>: Meters</p>
+ * <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
+ *
+ * @see CameraCharacteristics#LENS_POSE_ROTATION
+ */
+ @PublicKey
+ public static final Key<float[]> LENS_POSE_TRANSLATION =
+ new Key<float[]>("android.lens.poseTranslation", float[].class);
+
+ /**
+ * <p>The parameters for this camera device's intrinsic
+ * calibration.</p>
+ * <p>The five calibration parameters that describe the
+ * transform from camera-centric 3D coordinates to sensor
+ * pixel coordinates:</p>
+ * <pre><code>[f_x, f_y, c_x, c_y, s]
+ * </code></pre>
+ * <p>Where <code>f_x</code> and <code>f_y</code> are the horizontal and vertical
+ * focal lengths, <code>[c_x, c_y]</code> is the position of the optical
+ * axis, and <code>s</code> is a skew parameter for the sensor plane not
+ * being aligned with the lens plane.</p>
+ * <p>These are typically used within a transformation matrix K:</p>
+ * <pre><code>K = [ f_x, s, c_x,
+ * 0, f_y, c_y,
+ * 0 0, 1 ]
+ * </code></pre>
+ * <p>which can then be combined with the camera pose rotation
+ * <code>R</code> and translation <code>t</code> ({@link CameraCharacteristics#LENS_POSE_ROTATION android.lens.poseRotation} and
+ * {@link CameraCharacteristics#LENS_POSE_TRANSLATION android.lens.poseTranslation}, respective) to calculate the
+ * complete transform from world coordinates to pixel
+ * coordinates:</p>
+ * <pre><code>P = [ K 0 * [ R t
+ * 0 1 ] 0 1 ]
+ * </code></pre>
+ * <p>and with <code>p_w</code> being a point in the world coordinate system
+ * and <code>p_s</code> being a point in the camera active pixel array
+ * coordinate system, and with the mapping including the
+ * homogeneous division by z:</p>
+ * <pre><code> p_h = (x_h, y_h, z_h) = P p_w
+ * p_s = p_h / z_h
+ * </code></pre>
+ * <p>so <code>[x_s, y_s]</code> is the pixel coordinates of the world
+ * point, <code>z_s = 1</code>, and <code>w_s</code> is a measurement of disparity
+ * (depth) in pixel coordinates.</p>
+ * <p><b>Units</b>:
+ * Pixels in the android.sensor.activeArraySize coordinate
+ * system.</p>
+ * <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
+ *
+ * @see CameraCharacteristics#LENS_POSE_ROTATION
+ * @see CameraCharacteristics#LENS_POSE_TRANSLATION
+ */
+ @PublicKey
+ public static final Key<float[]> LENS_INTRINSIC_CALIBRATION =
+ new Key<float[]>("android.lens.intrinsicCalibration", float[].class);
+
+ /**
+ * <p>The correction coefficients to correct for this camera device's
+ * radial lens distortion.</p>
+ * <p>Three cofficients <code>[kappa_1, kappa_2, kappa_3]</code> that
+ * can be used to correct the lens's radial geometric
+ * distortion with the mapping equations:</p>
+ * <pre><code> x_c = x_i * ( 1 + kappa_1 * r^2 + kappa_2 * r^4 + kappa_3 * r^6 )
+ * y_c = y_i * ( 1 + kappa_1 * r^2 + kappa_2 * r^4 + kappa_3 * r^6 )
+ * </code></pre>
+ * <p>where <code>[x_i, y_i]</code> are normalized coordinates with <code>(0,0)</code>
+ * at the lens optical center, and <code>[-1, 1]</code> are the edges of
+ * the active pixel array; and where <code>[x_c, y_c]</code> are the
+ * corrected normalized coordinates with radial distortion
+ * removed; and <code>r^2 = x_i^2 + y_i^2</code>.</p>
+ * <p><b>Units</b>:
+ * Coefficients for a 6th-degree even radial polynomial.</p>
+ * <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
+ */
+ @PublicKey
+ public static final Key<float[]> LENS_RADIAL_DISTORTION =
+ new Key<float[]>("android.lens.radialDistortion", float[].class);
+
+ /**
* <p>Mode of operation for the noise reduction algorithm.</p>
* <p>The noise reduction algorithm attempts to improve image quality by removing
- * excessive noise added by the capture process, especially in dark conditions.
- * OFF means no noise reduction will be applied by the camera device.</p>
+ * excessive noise added by the capture process, especially in dark conditions.</p>
+ * <p>OFF means no noise reduction will be applied by the camera device, for both raw and
+ * YUV domain.</p>
+ * <p>MINIMAL means that only sensor raw domain basic noise reduction is enabled ,to remove
+ * demosaicing or other processing artifacts. For YUV_REPROCESSING, MINIMAL is same as OFF.
+ * This mode is optional, may not be support by all devices. The application should check
+ * {@link CameraCharacteristics#NOISE_REDUCTION_AVAILABLE_NOISE_REDUCTION_MODES android.noiseReduction.availableNoiseReductionModes} before using it.</p>
* <p>FAST/HIGH_QUALITY both mean camera device determined noise filtering
* will be applied. HIGH_QUALITY mode indicates that the camera device
* will use the highest-quality noise filtering algorithms,
* even if it slows down capture rate. FAST means the camera device will not
* slow down capture rate when applying noise filtering.</p>
+ * <p>For YUV_REPROCESSING, these FAST/HIGH_QUALITY modes both mean that the camera device
+ * will apply FAST/HIGH_QUALITY YUV domain noise reduction, respectively. The camera device
+ * may adjust the noise reduction parameters for best image quality based on the
+ * {@link CaptureRequest#REPROCESS_EFFECTIVE_EXPOSURE_FACTOR android.reprocess.effectiveExposureFactor} if it is set.</p>
* <p><b>Possible values:</b>
* <ul>
* <li>{@link #NOISE_REDUCTION_MODE_OFF OFF}</li>
* <li>{@link #NOISE_REDUCTION_MODE_FAST FAST}</li>
* <li>{@link #NOISE_REDUCTION_MODE_HIGH_QUALITY HIGH_QUALITY}</li>
+ * <li>{@link #NOISE_REDUCTION_MODE_MINIMAL MINIMAL}</li>
* </ul></p>
* <p><b>Available values for this device:</b><br>
* {@link CameraCharacteristics#NOISE_REDUCTION_AVAILABLE_NOISE_REDUCTION_MODES android.noiseReduction.availableNoiseReductionModes}</p>
@@ -2497,9 +2688,11 @@
*
* @see CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL
* @see CameraCharacteristics#NOISE_REDUCTION_AVAILABLE_NOISE_REDUCTION_MODES
+ * @see CaptureRequest#REPROCESS_EFFECTIVE_EXPOSURE_FACTOR
* @see #NOISE_REDUCTION_MODE_OFF
* @see #NOISE_REDUCTION_MODE_FAST
* @see #NOISE_REDUCTION_MODE_HIGH_QUALITY
+ * @see #NOISE_REDUCTION_MODE_MINIMAL
*/
@PublicKey
public static final Key<Integer> NOISE_REDUCTION_MODE =
@@ -2984,6 +3177,8 @@
* <li>{@link #SHADING_MODE_FAST FAST}</li>
* <li>{@link #SHADING_MODE_HIGH_QUALITY HIGH_QUALITY}</li>
* </ul></p>
+ * <p><b>Available values for this device:</b><br>
+ * {@link CameraCharacteristics#SHADING_AVAILABLE_MODES android.shading.availableModes}</p>
* <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
* <p><b>Full capability</b> -
* Present on all camera devices that report being {@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL_FULL HARDWARE_LEVEL_FULL} devices in the
@@ -2992,6 +3187,7 @@
* @see CaptureRequest#CONTROL_AE_MODE
* @see CaptureRequest#CONTROL_AWB_MODE
* @see CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL
+ * @see CameraCharacteristics#SHADING_AVAILABLE_MODES
* @see CaptureResult#STATISTICS_LENS_SHADING_CORRECTION_MAP
* @see CaptureRequest#STATISTICS_LENS_SHADING_MAP_MODE
* @see #SHADING_MODE_OFF
@@ -3155,7 +3351,7 @@
/**
* <p>The shading map is a low-resolution floating-point map
* that lists the coefficients used to correct for vignetting, for each
- * Bayer color channel.</p>
+ * Bayer color channel of RAW image data.</p>
* <p>The least shaded section of the image should have a gain factor
* of 1; all other sections should have gains above 1.</p>
* <p>When {@link CaptureRequest#COLOR_CORRECTION_MODE android.colorCorrection.mode} = TRANSFORM_MATRIX, the map
@@ -3191,8 +3387,20 @@
* <img alt="Green (odd rows) lens shading map" src="../../../../images/camera2/metadata/android.statistics.lensShadingMap/green_o_shading.png" />
* <img alt="Blue lens shading map" src="../../../../images/camera2/metadata/android.statistics.lensShadingMap/blue_shading.png" /></p>
* <p>As a visualization only, inverting the full-color map to recover an
- * image of a gray wall (using bicubic interpolation for visual quality) as captured by the sensor gives:</p>
+ * image of a gray wall (using bicubic interpolation for visual quality)
+ * as captured by the sensor gives:</p>
* <p><img alt="Image of a uniform white wall (inverse shading map)" src="../../../../images/camera2/metadata/android.statistics.lensShadingMap/inv_shading.png" /></p>
+ * <p>Note that the RAW image data might be subject to lens shading
+ * correction not reported on this map. Query
+ * {@link CameraCharacteristics#SENSOR_INFO_LENS_SHADING_APPLIED android.sensor.info.lensShadingApplied} to see if RAW image data has subject
+ * to lens shading correction. If {@link CameraCharacteristics#SENSOR_INFO_LENS_SHADING_APPLIED android.sensor.info.lensShadingApplied}
+ * is TRUE, the RAW image data is subject to partial or full lens shading
+ * correction. In the case full lens shading correction is applied to RAW
+ * images, the gain factor map reported in this key will contain all 1.0 gains.
+ * In other words, the map reported in this key is the remaining lens shading
+ * that needs to be applied on the RAW image to get images without lens shading
+ * artifacts. See {@link CameraCharacteristics#REQUEST_MAX_NUM_OUTPUT_RAW android.request.maxNumOutputRaw} for a list of RAW image
+ * formats.</p>
* <p><b>Range of valid values:</b><br>
* Each gain factor is >= 1</p>
* <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
@@ -3202,6 +3410,8 @@
*
* @see CaptureRequest#COLOR_CORRECTION_MODE
* @see CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL
+ * @see CameraCharacteristics#REQUEST_MAX_NUM_OUTPUT_RAW
+ * @see CameraCharacteristics#SENSOR_INFO_LENS_SHADING_APPLIED
* @hide
*/
public static final Key<float[]> STATISTICS_LENS_SHADING_MAP =
@@ -3339,12 +3549,15 @@
* <li>{@link #STATISTICS_LENS_SHADING_MAP_MODE_OFF OFF}</li>
* <li>{@link #STATISTICS_LENS_SHADING_MAP_MODE_ON ON}</li>
* </ul></p>
+ * <p><b>Available values for this device:</b><br>
+ * {@link CameraCharacteristics#STATISTICS_INFO_AVAILABLE_LENS_SHADING_MAP_MODES android.statistics.info.availableLensShadingMapModes}</p>
* <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
* <p><b>Full capability</b> -
* Present on all camera devices that report being {@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL_FULL HARDWARE_LEVEL_FULL} devices in the
* {@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL android.info.supportedHardwareLevel} key</p>
*
* @see CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL
+ * @see CameraCharacteristics#STATISTICS_INFO_AVAILABLE_LENS_SHADING_MAP_MODES
* @see #STATISTICS_LENS_SHADING_MAP_MODE_OFF
* @see #STATISTICS_LENS_SHADING_MAP_MODE_ON
*/
@@ -3531,6 +3744,8 @@
* <li>{@link #TONEMAP_MODE_CONTRAST_CURVE CONTRAST_CURVE}</li>
* <li>{@link #TONEMAP_MODE_FAST FAST}</li>
* <li>{@link #TONEMAP_MODE_HIGH_QUALITY HIGH_QUALITY}</li>
+ * <li>{@link #TONEMAP_MODE_GAMMA_VALUE GAMMA_VALUE}</li>
+ * <li>{@link #TONEMAP_MODE_PRESET_CURVE PRESET_CURVE}</li>
* </ul></p>
* <p><b>Available values for this device:</b><br>
* {@link CameraCharacteristics#TONEMAP_AVAILABLE_TONE_MAP_MODES android.tonemap.availableToneMapModes}</p>
@@ -3546,12 +3761,60 @@
* @see #TONEMAP_MODE_CONTRAST_CURVE
* @see #TONEMAP_MODE_FAST
* @see #TONEMAP_MODE_HIGH_QUALITY
+ * @see #TONEMAP_MODE_GAMMA_VALUE
+ * @see #TONEMAP_MODE_PRESET_CURVE
*/
@PublicKey
public static final Key<Integer> TONEMAP_MODE =
new Key<Integer>("android.tonemap.mode", int.class);
/**
+ * <p>Tonemapping curve to use when {@link CaptureRequest#TONEMAP_MODE android.tonemap.mode} is
+ * GAMMA_VALUE</p>
+ * <p>The tonemap curve will be defined the following formula:
+ * * OUT = pow(IN, 1.0 / gamma)
+ * where IN and OUT is the input pixel value scaled to range [0.0, 1.0],
+ * pow is the power function and gamma is the gamma value specified by this
+ * key.</p>
+ * <p>The same curve will be applied to all color channels. The camera device
+ * may clip the input gamma value to its supported range. The actual applied
+ * value will be returned in capture result.</p>
+ * <p>The valid range of gamma value varies on different devices, but values
+ * within [1.0, 5.0] are guaranteed not to be clipped.</p>
+ * <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
+ *
+ * @see CaptureRequest#TONEMAP_MODE
+ */
+ @PublicKey
+ public static final Key<Float> TONEMAP_GAMMA =
+ new Key<Float>("android.tonemap.gamma", float.class);
+
+ /**
+ * <p>Tonemapping curve to use when {@link CaptureRequest#TONEMAP_MODE android.tonemap.mode} is
+ * PRESET_CURVE</p>
+ * <p>The tonemap curve will be defined by specified standard.</p>
+ * <p>sRGB (approximated by 16 control points):</p>
+ * <p><img alt="sRGB tonemapping curve" src="../../../../images/camera2/metadata/android.tonemap.curveRed/srgb_tonemap.png" /></p>
+ * <p>Rec. 709 (approximated by 16 control points):</p>
+ * <p><img alt="Rec. 709 tonemapping curve" src="../../../../images/camera2/metadata/android.tonemap.curveRed/rec709_tonemap.png" /></p>
+ * <p>Note that above figures show a 16 control points approximation of preset
+ * curves. Camera devices may apply a different approximation to the curve.</p>
+ * <p><b>Possible values:</b>
+ * <ul>
+ * <li>{@link #TONEMAP_PRESET_CURVE_SRGB SRGB}</li>
+ * <li>{@link #TONEMAP_PRESET_CURVE_REC709 REC709}</li>
+ * </ul></p>
+ * <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
+ *
+ * @see CaptureRequest#TONEMAP_MODE
+ * @see #TONEMAP_PRESET_CURVE_SRGB
+ * @see #TONEMAP_PRESET_CURVE_REC709
+ */
+ @PublicKey
+ public static final Key<Integer> TONEMAP_PRESET_CURVE =
+ new Key<Integer>("android.tonemap.presetCurve", int.class);
+
+ /**
* <p>This LED is nominally used to indicate to the user
* that the camera is powered on and may be streaming images back to the
* Application Processor. In certain rare circumstances, the OS may
@@ -3657,6 +3920,52 @@
public static final Key<Long> SYNC_FRAME_NUMBER =
new Key<Long>("android.sync.frameNumber", long.class);
+ /**
+ * <p>The amount of exposure time increase factor applied to the original output
+ * frame by the application processing before sending for reprocessing.</p>
+ * <p>This is optional, and will be supported if the camera device supports YUV_REPROCESSING
+ * capability ({@link CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES android.request.availableCapabilities} contains YUV_REPROCESSING).</p>
+ * <p>For some YUV reprocessing use cases, the application may choose to filter the original
+ * output frames to effectively reduce the noise to the same level as a frame that was
+ * captured with longer exposure time. To be more specific, assuming the original captured
+ * images were captured with a sensitivity of S and an exposure time of T, the model in
+ * the camera device is that the amount of noise in the image would be approximately what
+ * would be expected if the original capture parameters had been a sensitivity of
+ * S/effectiveExposureFactor and an exposure time of T*effectiveExposureFactor, rather
+ * than S and T respectively. If the captured images were processed by the application
+ * before being sent for reprocessing, then the application may have used image processing
+ * algorithms and/or multi-frame image fusion to reduce the noise in the
+ * application-processed images (input images). By using the effectiveExposureFactor
+ * control, the application can communicate to the camera device the actual noise level
+ * improvement in the application-processed image. With this information, the camera
+ * device can select appropriate noise reduction and edge enhancement parameters to avoid
+ * excessive noise reduction ({@link CaptureRequest#NOISE_REDUCTION_MODE android.noiseReduction.mode}) and insufficient edge
+ * enhancement ({@link CaptureRequest#EDGE_MODE android.edge.mode}) being applied to the reprocessed frames.</p>
+ * <p>For example, for multi-frame image fusion use case, the application may fuse
+ * multiple output frames together to a final frame for reprocessing. When N image are
+ * fused into 1 image for reprocessing, the exposure time increase factor could be up to
+ * square root of N (based on a simple photon shot noise model). The camera device will
+ * adjust the reprocessing noise reduction and edge enhancement parameters accordingly to
+ * produce the best quality images.</p>
+ * <p>This is relative factor, 1.0 indicates the application hasn't processed the input
+ * buffer in a way that affects its effective exposure time.</p>
+ * <p>This control is only effective for YUV reprocessing capture request. For noise
+ * reduction reprocessing, it is only effective when <code>{@link CaptureRequest#NOISE_REDUCTION_MODE android.noiseReduction.mode} != OFF</code>.
+ * Similarly, for edge enhancement reprocessing, it is only effective when
+ * <code>{@link CaptureRequest#EDGE_MODE android.edge.mode} != OFF</code>.</p>
+ * <p><b>Units</b>: Relative exposure time increase factor.</p>
+ * <p><b>Range of valid values:</b><br>
+ * >= 1.0</p>
+ * <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
+ *
+ * @see CaptureRequest#EDGE_MODE
+ * @see CaptureRequest#NOISE_REDUCTION_MODE
+ * @see CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES
+ */
+ @PublicKey
+ public static final Key<Float> REPROCESS_EFFECTIVE_EXPOSURE_FACTOR =
+ new Key<Float>("android.reprocess.effectiveExposureFactor", float.class);
+
/*~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~
* End generated code
*~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~O@*/
diff --git a/core/java/android/hardware/camera2/ICameraDeviceUser.aidl b/core/java/android/hardware/camera2/ICameraDeviceUser.aidl
index 50a58ed..01f2396 100644
--- a/core/java/android/hardware/camera2/ICameraDeviceUser.aidl
+++ b/core/java/android/hardware/camera2/ICameraDeviceUser.aidl
@@ -16,7 +16,7 @@
package android.hardware.camera2;
-import android.view.Surface;
+import android.hardware.camera2.params.OutputConfiguration;
import android.hardware.camera2.impl.CameraMetadataNative;
import android.hardware.camera2.CaptureRequest;
@@ -66,7 +66,7 @@
int deleteStream(int streamId);
// non-negative value is the stream ID. negative value is status_t
- int createStream(int width, int height, int format, in Surface surface);
+ int createStream(in OutputConfiguration outputConfiguration);
int createDefaultRequest(int templateId, out CameraMetadataNative request);
diff --git a/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java b/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java
index ec450bd1..38f8e39 100644
--- a/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java
+++ b/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java
@@ -28,6 +28,7 @@
import android.hardware.camera2.ICameraDeviceCallbacks;
import android.hardware.camera2.ICameraDeviceUser;
import android.hardware.camera2.TotalCaptureResult;
+import android.hardware.camera2.params.OutputConfiguration;
import android.hardware.camera2.utils.CameraBinderDecorator;
import android.hardware.camera2.utils.CameraRuntimeException;
import android.hardware.camera2.utils.LongParcelable;
@@ -78,7 +79,8 @@
private int mRepeatingRequestId = REQUEST_ID_NONE;
private final ArrayList<Integer> mRepeatingRequestIdDeletedList = new ArrayList<Integer>();
// Map stream IDs to Surfaces
- private final SparseArray<Surface> mConfiguredOutputs = new SparseArray<Surface>();
+ private final SparseArray<OutputConfiguration> mConfiguredOutputs =
+ new SparseArray<OutputConfiguration>();
private final String mCameraId;
private final CameraCharacteristics mCharacteristics;
@@ -314,7 +316,11 @@
public void configureOutputs(List<Surface> outputs) throws CameraAccessException {
// Leave this here for backwards compatibility with older code using this directly
- configureOutputsChecked(outputs);
+ ArrayList<OutputConfiguration> outputConfigs = new ArrayList<>(outputs.size());
+ for (Surface s : outputs) {
+ outputConfigs.add(new OutputConfiguration(s));
+ }
+ configureOutputsChecked(outputConfigs);
}
/**
@@ -333,28 +339,30 @@
*
* @throws CameraAccessException if there were any unexpected problems during configuration
*/
- public boolean configureOutputsChecked(List<Surface> outputs) throws CameraAccessException {
+ public boolean configureOutputsChecked(List<OutputConfiguration> outputs)
+ throws CameraAccessException {
// Treat a null input the same an empty list
if (outputs == null) {
- outputs = new ArrayList<Surface>();
+ outputs = new ArrayList<OutputConfiguration>();
}
boolean success = false;
synchronized(mInterfaceLock) {
checkIfCameraClosedOrInError();
-
- HashSet<Surface> addSet = new HashSet<Surface>(outputs); // Streams to create
- List<Integer> deleteList = new ArrayList<Integer>(); // Streams to delete
+ // Streams to create
+ HashSet<OutputConfiguration> addSet = new HashSet<OutputConfiguration>(outputs);
+ // Streams to delete
+ List<Integer> deleteList = new ArrayList<Integer>();
// Determine which streams need to be created, which to be deleted
for (int i = 0; i < mConfiguredOutputs.size(); ++i) {
int streamId = mConfiguredOutputs.keyAt(i);
- Surface s = mConfiguredOutputs.valueAt(i);
+ OutputConfiguration outConfig = mConfiguredOutputs.valueAt(i);
- if (!outputs.contains(s)) {
+ if (!outputs.contains(outConfig)) {
deleteList.add(streamId);
} else {
- addSet.remove(s); // Don't create a stream previously created
+ addSet.remove(outConfig); // Don't create a stream previously created
}
}
@@ -372,11 +380,11 @@
}
// Add all new streams
- for (Surface s : addSet) {
- // TODO: remove width,height,format since we are ignoring
- // it.
- int streamId = mRemoteDevice.createStream(0, 0, 0, s);
- mConfiguredOutputs.put(streamId, s);
+ for (OutputConfiguration outConfig : outputs) {
+ if (addSet.contains(outConfig)) {
+ int streamId = mRemoteDevice.createStream(outConfig);
+ mConfiguredOutputs.put(streamId, outConfig);
+ }
}
try {
@@ -417,6 +425,18 @@
public void createCaptureSession(List<Surface> outputs,
CameraCaptureSession.StateCallback callback, Handler handler)
throws CameraAccessException {
+ List<OutputConfiguration> outConfigurations = new ArrayList<>(outputs.size());
+ for (Surface surface : outputs) {
+ outConfigurations.add(new OutputConfiguration(surface));
+ }
+ createCaptureSessionByOutputConfiguration(outConfigurations, callback, handler);
+ }
+
+ @Override
+ public void createCaptureSessionByOutputConfiguration(
+ List<OutputConfiguration> outputConfigurations,
+ CameraCaptureSession.StateCallback callback, Handler handler)
+ throws CameraAccessException {
synchronized(mInterfaceLock) {
if (DEBUG) {
Log.d(TAG, "createCaptureSession");
@@ -434,7 +454,8 @@
boolean configureSuccess = true;
CameraAccessException pendingException = null;
try {
- configureSuccess = configureOutputsChecked(outputs); // and then block until IDLE
+ // configure outputs and then block until IDLE
+ configureSuccess = configureOutputsChecked(outputConfigurations);
} catch (CameraAccessException e) {
configureSuccess = false;
pendingException = e;
@@ -443,10 +464,14 @@
}
}
+ List<Surface> outSurfaces = new ArrayList<>(outputConfigurations.size());
+ for (OutputConfiguration config : outputConfigurations) {
+ outSurfaces.add(config.getSurface());
+ }
// Fire onConfigured if configureOutputs succeeded, fire onConfigureFailed otherwise.
CameraCaptureSessionImpl newSession =
new CameraCaptureSessionImpl(mNextSessionId++,
- outputs, callback, handler, this, mDeviceHandler,
+ outSurfaces, callback, handler, this, mDeviceHandler,
configureSuccess);
// TODO: wait until current session closes, then create the new session
diff --git a/core/java/android/hardware/camera2/impl/CameraMetadataNative.java b/core/java/android/hardware/camera2/impl/CameraMetadataNative.java
index f47ce79..e926a98 100644
--- a/core/java/android/hardware/camera2/impl/CameraMetadataNative.java
+++ b/core/java/android/hardware/camera2/impl/CameraMetadataNative.java
@@ -830,11 +830,19 @@
CameraCharacteristics.SCALER_AVAILABLE_MIN_FRAME_DURATIONS);
StreamConfigurationDuration[] stallDurations = getBase(
CameraCharacteristics.SCALER_AVAILABLE_STALL_DURATIONS);
+ StreamConfiguration[] depthConfigurations = getBase(
+ CameraCharacteristics.DEPTH_AVAILABLE_DEPTH_STREAM_CONFIGURATIONS);
+ StreamConfigurationDuration[] depthMinFrameDurations = getBase(
+ CameraCharacteristics.DEPTH_AVAILABLE_DEPTH_MIN_FRAME_DURATIONS);
+ StreamConfigurationDuration[] depthStallDurations = getBase(
+ CameraCharacteristics.DEPTH_AVAILABLE_DEPTH_STALL_DURATIONS);
HighSpeedVideoConfiguration[] highSpeedVideoConfigurations = getBase(
CameraCharacteristics.CONTROL_AVAILABLE_HIGH_SPEED_VIDEO_CONFIGURATIONS);
return new StreamConfigurationMap(
- configurations, minFrameDurations, stallDurations, highSpeedVideoConfigurations);
+ configurations, minFrameDurations, stallDurations,
+ depthConfigurations, depthMinFrameDurations, depthStallDurations,
+ highSpeedVideoConfigurations);
}
private <T> Integer getMaxRegions(Key<T> key) {
diff --git a/core/java/android/hardware/camera2/legacy/CameraDeviceUserShim.java b/core/java/android/hardware/camera2/legacy/CameraDeviceUserShim.java
index fcf172c..70f3463 100644
--- a/core/java/android/hardware/camera2/legacy/CameraDeviceUserShim.java
+++ b/core/java/android/hardware/camera2/legacy/CameraDeviceUserShim.java
@@ -26,6 +26,7 @@
import android.hardware.camera2.utils.LongParcelable;
import android.hardware.camera2.impl.CameraMetadataNative;
import android.hardware.camera2.impl.CaptureResultExtras;
+import android.hardware.camera2.params.OutputConfiguration;
import android.hardware.camera2.utils.CameraBinderDecorator;
import android.hardware.camera2.utils.CameraRuntimeException;
import android.os.ConditionVariable;
@@ -504,7 +505,7 @@
}
@Override
- public int createStream(int width, int height, int format, Surface surface) {
+ public int createStream(OutputConfiguration outputConfiguration) {
if (DEBUG) {
Log.d(TAG, "createStream called.");
}
@@ -518,8 +519,12 @@
Log.e(TAG, "Cannot create stream, beginConfigure hasn't been called yet.");
return CameraBinderDecorator.INVALID_OPERATION;
}
+ if (outputConfiguration.getRotation() != OutputConfiguration.ROTATION_0) {
+ Log.e(TAG, "Cannot create stream, stream rotation is not supported.");
+ return CameraBinderDecorator.INVALID_OPERATION;
+ }
int id = ++mSurfaceIdCounter;
- mSurfaces.put(id, surface);
+ mSurfaces.put(id, outputConfiguration.getSurface());
return id;
}
}
diff --git a/core/java/android/hardware/camera2/legacy/LegacyMetadataMapper.java b/core/java/android/hardware/camera2/legacy/LegacyMetadataMapper.java
index 347db05..802b938 100644
--- a/core/java/android/hardware/camera2/legacy/LegacyMetadataMapper.java
+++ b/core/java/android/hardware/camera2/legacy/LegacyMetadataMapper.java
@@ -474,6 +474,15 @@
m.set(CONTROL_AE_COMPENSATION_STEP, ParamsUtils.createRational(step));
}
+
+ /*
+ * control.aeLockAvailable
+ */
+ {
+ boolean aeLockAvailable = p.isAutoExposureLockSupported();
+
+ m.set(CONTROL_AE_LOCK_AVAILABLE, aeLockAvailable);
+ }
}
@@ -571,6 +580,16 @@
Log.v(TAG, "mapControlAwb - control.awbAvailableModes set to " +
ListUtils.listToString(awbAvail));
}
+
+
+ /*
+ * control.awbLockAvailable
+ */
+ {
+ boolean awbLockAvailable = p.isAutoWhiteBalanceLockSupported();
+
+ m.set(CONTROL_AWB_LOCK_AVAILABLE, awbLockAvailable);
+ }
}
}
@@ -618,17 +637,44 @@
/*
* android.control.availableSceneModes
*/
+ int maxNumDetectedFaces = p.getMaxNumDetectedFaces();
List<String> sceneModes = p.getSupportedSceneModes();
List<Integer> supportedSceneModes =
ArrayUtils.convertStringListToIntList(sceneModes, sLegacySceneModes, sSceneModes);
- if (supportedSceneModes == null) { // camera1 doesn't support scene mode settings
- supportedSceneModes = new ArrayList<Integer>();
- supportedSceneModes.add(CONTROL_SCENE_MODE_DISABLED); // disabled is always available
+
+ // Special case where the only scene mode listed is AUTO => no scene mode
+ if (sceneModes != null && sceneModes.size() == 1 &&
+ sceneModes.get(0) == Parameters.SCENE_MODE_AUTO) {
+ supportedSceneModes = null;
}
- if (p.getMaxNumDetectedFaces() > 0) { // always supports FACE_PRIORITY when face detecting
- supportedSceneModes.add(CONTROL_SCENE_MODE_FACE_PRIORITY);
+
+ boolean sceneModeSupported = true;
+ if (supportedSceneModes == null && maxNumDetectedFaces == 0) {
+ sceneModeSupported = false;
}
- m.set(CONTROL_AVAILABLE_SCENE_MODES, ArrayUtils.toIntArray(supportedSceneModes));
+
+ if (sceneModeSupported) {
+ if (supportedSceneModes == null) {
+ supportedSceneModes = new ArrayList<Integer>();
+ }
+ if (maxNumDetectedFaces > 0) { // always supports FACE_PRIORITY when face detecting
+ supportedSceneModes.add(CONTROL_SCENE_MODE_FACE_PRIORITY);
+ }
+ // Remove all DISABLED occurrences
+ if (supportedSceneModes.contains(CONTROL_SCENE_MODE_DISABLED)) {
+ while(supportedSceneModes.remove(new Integer(CONTROL_SCENE_MODE_DISABLED))) {}
+ }
+ m.set(CONTROL_AVAILABLE_SCENE_MODES, ArrayUtils.toIntArray(supportedSceneModes));
+ } else {
+ m.set(CONTROL_AVAILABLE_SCENE_MODES, new int[] {CONTROL_SCENE_MODE_DISABLED});
+ }
+
+ /*
+ * android.control.availableModes
+ */
+ m.set(CONTROL_AVAILABLE_MODES, sceneModeSupported ?
+ new int[] { CONTROL_MODE_AUTO, CONTROL_MODE_USE_SCENE_MODE } :
+ new int[] { CONTROL_MODE_AUTO });
}
private static void mapLens(CameraMetadataNative m, Camera.Parameters p) {
diff --git a/core/java/android/hardware/camera2/params/OutputConfiguration.aidl b/core/java/android/hardware/camera2/params/OutputConfiguration.aidl
new file mode 100644
index 0000000..0921cd8
--- /dev/null
+++ b/core/java/android/hardware/camera2/params/OutputConfiguration.aidl
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) 2015 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.hardware.camera2.params;
+
+/** @hide */
+parcelable OutputConfiguration;
diff --git a/core/java/android/hardware/camera2/params/OutputConfiguration.java b/core/java/android/hardware/camera2/params/OutputConfiguration.java
new file mode 100644
index 0000000..0a4ed39
--- /dev/null
+++ b/core/java/android/hardware/camera2/params/OutputConfiguration.java
@@ -0,0 +1,165 @@
+/*
+ * Copyright (C) 2015 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.hardware.camera2.params;
+
+import android.hardware.camera2.CameraDevice;
+import android.util.Log;
+import android.view.Surface;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import static com.android.internal.util.Preconditions.*;
+
+/**
+ * A class for describing camera output, which contains a {@link Surface} and its specific
+ * configuration for creating capture session.
+ *
+ * @see CameraDevice#createCaptureSession
+ *
+ * @hide
+ */
+public final class OutputConfiguration implements Parcelable {
+
+ /**
+ * Rotation constant: 0 degree rotation (no rotation)
+ */
+ public static final int ROTATION_0 = 0;
+
+ /**
+ * Rotation constant: 90 degree counterclockwise rotation.
+ */
+ public static final int ROTATION_90 = 1;
+
+ /**
+ * Rotation constant: 180 degree counterclockwise rotation.
+ */
+ public static final int ROTATION_180 = 2;
+
+ /**
+ * Rotation constant: 270 degree counterclockwise rotation.
+ */
+ public static final int ROTATION_270 = 3;
+
+ /**
+ * Create a new immutable SurfaceConfiguration instance.
+ *
+ * @param surface
+ * A Surface for camera to output to.
+ *
+ * <p>This constructor creates a default configuration</p>
+ *
+ */
+ public OutputConfiguration(Surface surface) {
+ checkNotNull(surface, "Surface must not be null");
+ mSurface = surface;
+ mRotation = ROTATION_0;
+ }
+
+ /**
+ * Create a new immutable SurfaceConfiguration instance.
+ *
+ * <p>This constructor takes an argument for desired camera rotation</p>
+ *
+ * @param surface
+ * A Surface for camera to output to.
+ * @param rotation
+ * The desired rotation to be applied on camera output. Value must be one of
+ * ROTATION_[0, 90, 180, 270]. Note that when the rotation is 90 or 270 degree,
+ * application should make sure corresponding surface size has width and height
+ * transposed corresponding to the width and height without rotation. For example,
+ * if application needs camera to capture 1280x720 picture and rotate it by 90 degree,
+ * application should set rotation to {@code ROTATION_90} and make sure the
+ * corresponding Surface size is 720x1280. Note that {@link CameraDevice} might
+ * throw {@code IllegalArgumentException} if device cannot perform such rotation.
+ *
+ */
+ public OutputConfiguration(Surface surface, int rotation) {
+ checkNotNull(surface, "Surface must not be null");
+ checkArgumentInRange(rotation, ROTATION_0, ROTATION_270, "Rotation constant");
+ mSurface = surface;
+ mRotation = rotation;
+ }
+
+ /**
+ * Create an OutputConfiguration from Parcel.
+ */
+ private OutputConfiguration(Parcel source) {
+ int rotation = source.readInt();
+ Surface surface = Surface.CREATOR.createFromParcel(source);
+ checkNotNull(surface, "Surface must not be null");
+ checkArgumentInRange(rotation, ROTATION_0, ROTATION_270, "Rotation constant");
+ mSurface = surface;
+ mRotation = rotation;
+ }
+
+ /**
+ * Get the {@link Surface} associated with this {@link OutputConfiguration}.
+ *
+ * @return the {@link Surface} associated with this {@link OutputConfiguration}.
+ */
+ public Surface getSurface() {
+ return mSurface;
+ }
+
+ /**
+ * Get the rotation associated with this {@link OutputConfiguration}.
+ *
+ * @return the rotation associated with this {@link OutputConfiguration}.
+ * Value will be one of ROTATION_[0, 90, 180, 270]
+ */
+ public int getRotation() {
+ return mRotation;
+ }
+
+ public static final Parcelable.Creator<OutputConfiguration> CREATOR =
+ new Parcelable.Creator<OutputConfiguration>() {
+ @Override
+ public OutputConfiguration createFromParcel(Parcel source) {
+ try {
+ OutputConfiguration outputConfiguration = new OutputConfiguration(source);
+ return outputConfiguration;
+ } catch (Exception e) {
+ Log.e(TAG, "Exception creating OutputConfiguration from parcel", e);
+ return null;
+ }
+ }
+
+ @Override
+ public OutputConfiguration[] newArray(int size) {
+ return new OutputConfiguration[size];
+ }
+ };
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ if (dest == null) {
+ throw new IllegalArgumentException("dest must not be null");
+ }
+ dest.writeInt(mRotation);
+ mSurface.writeToParcel(dest, flags);
+ }
+
+ private static final String TAG = "OutputConfiguration";
+ private final Surface mSurface;
+ private final int mRotation;
+}
diff --git a/core/java/android/hardware/camera2/params/StreamConfigurationMap.java b/core/java/android/hardware/camera2/params/StreamConfigurationMap.java
index 479c842..a875b47 100644
--- a/core/java/android/hardware/camera2/params/StreamConfigurationMap.java
+++ b/core/java/android/hardware/camera2/params/StreamConfigurationMap.java
@@ -90,11 +90,28 @@
StreamConfiguration[] configurations,
StreamConfigurationDuration[] minFrameDurations,
StreamConfigurationDuration[] stallDurations,
+ StreamConfiguration[] depthConfigurations,
+ StreamConfigurationDuration[] depthMinFrameDurations,
+ StreamConfigurationDuration[] depthStallDurations,
HighSpeedVideoConfiguration[] highSpeedVideoConfigurations) {
mConfigurations = checkArrayElementsNotNull(configurations, "configurations");
mMinFrameDurations = checkArrayElementsNotNull(minFrameDurations, "minFrameDurations");
mStallDurations = checkArrayElementsNotNull(stallDurations, "stallDurations");
+
+ if (depthConfigurations == null) {
+ mDepthConfigurations = new StreamConfiguration[0];
+ mDepthMinFrameDurations = new StreamConfigurationDuration[0];
+ mDepthStallDurations = new StreamConfigurationDuration[0];
+ } else {
+ mDepthConfigurations = checkArrayElementsNotNull(depthConfigurations,
+ "depthConfigurations");
+ mDepthMinFrameDurations = checkArrayElementsNotNull(depthMinFrameDurations,
+ "depthMinFrameDurations");
+ mDepthStallDurations = checkArrayElementsNotNull(depthStallDurations,
+ "depthStallDurations");
+ }
+
if (highSpeedVideoConfigurations == null) {
mHighSpeedVideoConfigurations = new HighSpeedVideoConfiguration[0];
} else {
@@ -111,9 +128,24 @@
if (count == null) {
count = 0;
}
- count = count + 1;
- map.put(config.getFormat(), count);
+ map.put(config.getFormat(), count + 1);
+ }
+
+ // For each depth format, track how many sizes there are available to configure
+ for (StreamConfiguration config : mDepthConfigurations) {
+ if (!config.isOutput()) {
+ // Ignoring input depth configs
+ continue;
+ }
+
+ Integer count = mDepthOutputFormats.get(config.getFormat());
+
+ if (count == null) {
+ count = 0;
+ }
+
+ mDepthOutputFormats.put(config.getFormat(), count + 1);
}
if (!mOutputFormats.containsKey(HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED)) {
@@ -215,8 +247,13 @@
public boolean isOutputSupportedFor(int format) {
checkArgumentFormat(format);
- format = imageFormatToInternal(format);
- return getFormatsMap(/*output*/true).containsKey(format);
+ int internalFormat = imageFormatToInternal(format);
+ int dataspace = imageFormatToDataspace(format);
+ if (dataspace == HAL_DATASPACE_DEPTH) {
+ return mDepthOutputFormats.containsKey(internalFormat);
+ } else {
+ return getFormatsMap(/*output*/true).containsKey(internalFormat);
+ }
}
/**
@@ -387,7 +424,8 @@
return null;
}
- return getInternalFormatSizes(HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED, /*output*/true);
+ return getInternalFormatSizes(HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED,
+ HAL_DATASPACE_UNKNOWN,/*output*/true);
}
/**
@@ -600,7 +638,10 @@
checkNotNull(size, "size must not be null");
checkArgumentFormatSupported(format, /*output*/true);
- return getInternalFormatDuration(imageFormatToInternal(format), size, DURATION_MIN_FRAME);
+ return getInternalFormatDuration(imageFormatToInternal(format),
+ imageFormatToDataspace(format),
+ size,
+ DURATION_MIN_FRAME);
}
/**
@@ -653,6 +694,7 @@
}
return getInternalFormatDuration(HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED,
+ HAL_DATASPACE_UNKNOWN,
size, DURATION_MIN_FRAME);
}
@@ -742,7 +784,9 @@
checkArgumentFormatSupported(format, /*output*/true);
return getInternalFormatDuration(imageFormatToInternal(format),
- size, DURATION_STALL);
+ imageFormatToDataspace(format),
+ size,
+ DURATION_STALL);
}
/**
@@ -779,7 +823,7 @@
}
return getInternalFormatDuration(HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED,
- size, DURATION_STALL);
+ HAL_DATASPACE_UNKNOWN, size, DURATION_STALL);
}
/**
@@ -858,6 +902,7 @@
case HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED:
case HAL_PIXEL_FORMAT_BLOB:
case HAL_PIXEL_FORMAT_RAW_OPAQUE:
+ case HAL_PIXEL_FORMAT_Y16:
return format;
case ImageFormat.JPEG:
throw new IllegalArgumentException(
@@ -897,8 +942,8 @@
}
/**
- * Convert a public-visible {@code ImageFormat} into an internal format
- * compatible with {@code graphics.h}.
+ * Convert an internal format compatible with {@code graphics.h} into public-visible
+ * {@code ImageFormat}. This assumes the dataspace of the format is not HAL_DATASPACE_DEPTH.
*
* <p>In particular these formats are converted:
* <ul>
@@ -912,7 +957,8 @@
*
* <p>All other formats are returned as-is, no further invalid check is performed.</p>
*
- * <p>This function is the dual of {@link #imageFormatToInternal}.</p>
+ * <p>This function is the dual of {@link #imageFormatToInternal} for dataspaces other than
+ * HAL_DATASPACE_DEPTH.</p>
*
* @param format image format from {@link ImageFormat} or {@link PixelFormat}
* @return the converted image formats
@@ -941,6 +987,55 @@
}
/**
+ * Convert an internal format compatible with {@code graphics.h} into public-visible
+ * {@code ImageFormat}. This assumes the dataspace of the format is HAL_DATASPACE_DEPTH.
+ *
+ * <p>In particular these formats are converted:
+ * <ul>
+ * <li>HAL_PIXEL_FORMAT_BLOB => ImageFormat.DEPTH_POINT_CLOUD
+ * <li>HAL_PIXEL_FORMAT_Y16 => ImageFormat.DEPTH16
+ * </ul>
+ * </p>
+ *
+ * <p>Passing in an implementation-defined format which has no public equivalent will fail;
+ * as will passing in a public format which has a different internal format equivalent.
+ * See {@link #checkArgumentFormat} for more details about a legal public format.</p>
+ *
+ * <p>All other formats are returned as-is, no further invalid check is performed.</p>
+ *
+ * <p>This function is the dual of {@link #imageFormatToInternal} for formats associated with
+ * HAL_DATASPACE_DEPTH.</p>
+ *
+ * @param format image format from {@link ImageFormat} or {@link PixelFormat}
+ * @return the converted image formats
+ *
+ * @throws IllegalArgumentException
+ * if {@code format} is {@code HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED} or
+ * {@link ImageFormat#JPEG}
+ *
+ * @see ImageFormat
+ * @see PixelFormat
+ * @see #checkArgumentFormat
+ */
+ static int depthFormatToPublic(int format) {
+ switch (format) {
+ case HAL_PIXEL_FORMAT_BLOB:
+ return ImageFormat.DEPTH_POINT_CLOUD;
+ case HAL_PIXEL_FORMAT_Y16:
+ return ImageFormat.DEPTH16;
+ case ImageFormat.JPEG:
+ throw new IllegalArgumentException(
+ "ImageFormat.JPEG is an unknown internal format");
+ case HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED:
+ throw new IllegalArgumentException(
+ "IMPLEMENTATION_DEFINED must not leak to public API");
+ default:
+ throw new IllegalArgumentException(
+ "Unknown DATASPACE_DEPTH format " + format);
+ }
+ }
+
+ /**
* Convert image formats from internal to public formats (in-place).
*
* @param formats an array of image formats
@@ -967,6 +1062,8 @@
* <p>In particular these formats are converted:
* <ul>
* <li>ImageFormat.JPEG => HAL_PIXEL_FORMAT_BLOB
+ * <li>ImageFormat.DEPTH_POINT_CLOUD => HAL_PIXEL_FORMAT_BLOB
+ * <li>ImageFormat.DEPTH16 => HAL_PIXEL_FORMAT_Y16
* </ul>
* </p>
*
@@ -990,7 +1087,10 @@
static int imageFormatToInternal(int format) {
switch (format) {
case ImageFormat.JPEG:
+ case ImageFormat.DEPTH_POINT_CLOUD:
return HAL_PIXEL_FORMAT_BLOB;
+ case ImageFormat.DEPTH16:
+ return HAL_PIXEL_FORMAT_Y16;
case HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED:
throw new IllegalArgumentException(
"IMPLEMENTATION_DEFINED is not allowed via public API");
@@ -1000,6 +1100,48 @@
}
/**
+ * Convert a public format compatible with {@code ImageFormat} to an internal dataspace
+ * from {@code graphics.h}.
+ *
+ * <p>In particular these formats are converted:
+ * <ul>
+ * <li>ImageFormat.JPEG => HAL_DATASPACE_JFIF
+ * <li>ImageFormat.DEPTH_POINT_CLOUD => HAL_DATASPACE_DEPTH
+ * <li>ImageFormat.DEPTH16 => HAL_DATASPACE_DEPTH
+ * <li>others => HAL_DATASPACE_UNKNOWN
+ * </ul>
+ * </p>
+ *
+ * <p>Passing in an implementation-defined format here will fail (it's not a public format);
+ * as will passing in an internal format which has a different public format equivalent.
+ * See {@link #checkArgumentFormat} for more details about a legal public format.</p>
+ *
+ * <p>All other formats are returned as-is, no invalid check is performed.</p>
+ *
+ * <p>This function is the dual of {@link #imageFormatToPublic}.</p>
+ *
+ * @param format public image format from {@link ImageFormat} or {@link PixelFormat}
+ * @return the converted image formats
+ *
+ * @see ImageFormat
+ * @see PixelFormat
+ *
+ * @throws IllegalArgumentException
+ * if {@code format} was {@code HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED}
+ */
+ static int imageFormatToDataspace(int format) {
+ switch (format) {
+ case ImageFormat.JPEG:
+ return HAL_DATASPACE_JFIF;
+ case ImageFormat.DEPTH_POINT_CLOUD:
+ case ImageFormat.DEPTH16:
+ return HAL_DATASPACE_DEPTH;
+ default:
+ return HAL_DATASPACE_UNKNOWN;
+ }
+ }
+
+ /**
* Convert image formats from public to internal formats (in-place).
*
* @param formats an array of image formats
@@ -1028,13 +1170,16 @@
return null;
}
- format = imageFormatToInternal(format);
+ int internalFormat = imageFormatToInternal(format);
+ int dataspace = imageFormatToDataspace(format);
- return getInternalFormatSizes(format, output);
+ return getInternalFormatSizes(internalFormat, dataspace, output);
}
- private Size[] getInternalFormatSizes(int format, boolean output) {
- HashMap<Integer, Integer> formatsMap = getFormatsMap(output);
+ private Size[] getInternalFormatSizes(int format, int dataspace, boolean output) {
+
+ HashMap<Integer, Integer> formatsMap =
+ (dataspace == HAL_DATASPACE_DEPTH) ? mDepthOutputFormats : getFormatsMap(output);
Integer sizesCount = formatsMap.get(format);
if (sizesCount == null) {
@@ -1045,7 +1190,11 @@
Size[] sizes = new Size[len];
int sizeIndex = 0;
- for (StreamConfiguration config : mConfigurations) {
+ StreamConfiguration[] configurations =
+ (dataspace == HAL_DATASPACE_DEPTH) ? mDepthConfigurations : mConfigurations;
+
+
+ for (StreamConfiguration config : configurations) {
if (config.getFormat() == format && config.isOutput() == output) {
sizes[sizeIndex++] = config.getSize();
}
@@ -1068,15 +1217,19 @@
for (int format : getFormatsMap(output).keySet()) {
if (format != HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED &&
format != HAL_PIXEL_FORMAT_RAW_OPAQUE) {
- formats[i++] = format;
+ formats[i++] = imageFormatToPublic(format);
}
}
-
+ if (output) {
+ for (int format : mDepthOutputFormats.keySet()) {
+ formats[i++] = depthFormatToPublic(format);
+ }
+ }
if (formats.length != i) {
throw new AssertionError("Too few formats " + i + ", expected " + formats.length);
}
- return imageFormatToPublic(formats);
+ return formats;
}
/** Get the format -> size count map for either output or input formats */
@@ -1084,14 +1237,14 @@
return output ? mOutputFormats : mInputFormats;
}
- private long getInternalFormatDuration(int format, Size size, int duration) {
+ private long getInternalFormatDuration(int format, int dataspace, Size size, int duration) {
// assume format is already checked, since its internal
- if (!arrayContains(getInternalFormatSizes(format, /*output*/true), size)) {
+ if (!arrayContains(getInternalFormatSizes(format, dataspace, /*output*/true), size)) {
throw new IllegalArgumentException("size was not supported");
}
- StreamConfigurationDuration[] durations = getDurations(duration);
+ StreamConfigurationDuration[] durations = getDurations(duration, dataspace);
for (StreamConfigurationDuration configurationDuration : durations) {
if (configurationDuration.getFormat() == format &&
@@ -1110,12 +1263,14 @@
* @see #DURATION_MIN_FRAME
* @see #DURATION_STALL
* */
- private StreamConfigurationDuration[] getDurations(int duration) {
+ private StreamConfigurationDuration[] getDurations(int duration, int dataspace) {
switch (duration) {
case DURATION_MIN_FRAME:
- return mMinFrameDurations;
+ return (dataspace == HAL_DATASPACE_DEPTH) ?
+ mDepthMinFrameDurations : mMinFrameDurations;
case DURATION_STALL:
- return mStallDurations;
+ return (dataspace == HAL_DATASPACE_DEPTH) ?
+ mDepthStallDurations : mStallDurations;
default:
throw new IllegalArgumentException("duration was invalid");
}
@@ -1132,6 +1287,9 @@
if (formatsMap.containsKey(HAL_PIXEL_FORMAT_RAW_OPAQUE)) {
size -= 1;
}
+ if (output) {
+ size += mDepthOutputFormats.size();
+ }
return size;
}
@@ -1154,10 +1312,14 @@
private static final int HAL_PIXEL_FORMAT_BLOB = 0x21;
private static final int HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED = 0x22;
private static final int HAL_PIXEL_FORMAT_RAW_OPAQUE = 0x24;
+ private static final int HAL_PIXEL_FORMAT_Y16 = 0x20363159;
+
+ private static final int HAL_DATASPACE_UNKNOWN = 0x0;
+ private static final int HAL_DATASPACE_JFIF = 0x101;
+ private static final int HAL_DATASPACE_DEPTH = 0x1000;
/**
- * @see #getDurations(int)
- * @see #getDurationDefault(int)
+ * @see #getDurations(int, int)
*/
private static final int DURATION_MIN_FRAME = 0;
private static final int DURATION_STALL = 1;
@@ -1165,6 +1327,11 @@
private final StreamConfiguration[] mConfigurations;
private final StreamConfigurationDuration[] mMinFrameDurations;
private final StreamConfigurationDuration[] mStallDurations;
+
+ private final StreamConfiguration[] mDepthConfigurations;
+ private final StreamConfigurationDuration[] mDepthMinFrameDurations;
+ private final StreamConfigurationDuration[] mDepthStallDurations;
+
private final HighSpeedVideoConfiguration[] mHighSpeedVideoConfigurations;
/** ImageFormat -> num output sizes mapping */
@@ -1173,6 +1340,9 @@
/** ImageFormat -> num input sizes mapping */
private final HashMap</*ImageFormat*/Integer, /*Count*/Integer> mInputFormats =
new HashMap<Integer, Integer>();
+ /** ImageFormat -> num depth output sizes mapping */
+ private final HashMap</*ImageFormat*/Integer, /*Count*/Integer> mDepthOutputFormats =
+ new HashMap<Integer, Integer>();
/** High speed video Size -> FPS range count mapping*/
private final HashMap</*HighSpeedVideoSize*/Size, /*Count*/Integer> mHighSpeedVideoSizeMap =
new HashMap<Size, Integer>();
diff --git a/core/java/android/net/BaseDhcpStateMachine.java b/core/java/android/net/BaseDhcpStateMachine.java
new file mode 100644
index 0000000..a25847d
--- /dev/null
+++ b/core/java/android/net/BaseDhcpStateMachine.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2015 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;
+
+import com.android.internal.util.StateMachine;
+
+/**
+ * Interface that must be implemented by DHCP state machines.
+ *
+ * This is an abstract class instead of a Java interface so that callers can just declare an object
+ * of this type and be able to call all the methods defined by either StateMachine or this class.
+ *
+ * @hide
+ */
+public abstract class BaseDhcpStateMachine extends StateMachine {
+ protected BaseDhcpStateMachine(String tag) {
+ super(tag);
+ }
+ public abstract void registerForPreDhcpNotification();
+ public abstract void doQuit();
+}
diff --git a/core/java/android/net/BaseNetworkStateTracker.java b/core/java/android/net/BaseNetworkStateTracker.java
deleted file mode 100644
index e4e5b1e..0000000
--- a/core/java/android/net/BaseNetworkStateTracker.java
+++ /dev/null
@@ -1,205 +0,0 @@
-/*
- * Copyright (C) 2012 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;
-
-import android.content.Context;
-import android.os.Handler;
-import android.os.Messenger;
-
-import java.util.concurrent.atomic.AtomicBoolean;
-
-import com.android.internal.util.Preconditions;
-
-/**
- * Interface to control and observe state of a specific network, hiding
- * network-specific details from {@link ConnectivityManager}. Surfaces events
- * through the registered {@link Handler} to enable {@link ConnectivityManager}
- * to respond to state changes over time.
- *
- * @hide
- */
-public abstract class BaseNetworkStateTracker implements NetworkStateTracker {
- // TODO: better document threading expectations
- // TODO: migrate to make NetworkStateTracker abstract class
-
- public static final String PROP_TCP_BUFFER_UNKNOWN = "net.tcp.buffersize.unknown";
- public static final String PROP_TCP_BUFFER_WIFI = "net.tcp.buffersize.wifi";
-
- protected Context mContext;
- private Handler mTarget;
-
- protected NetworkInfo mNetworkInfo;
- protected LinkProperties mLinkProperties;
- protected NetworkCapabilities mNetworkCapabilities;
- protected Network mNetwork = new Network(ConnectivityManager.NETID_UNSET);
-
- private AtomicBoolean mTeardownRequested = new AtomicBoolean(false);
- private AtomicBoolean mPrivateDnsRouteSet = new AtomicBoolean(false);
- private AtomicBoolean mDefaultRouteSet = new AtomicBoolean(false);
-
- public BaseNetworkStateTracker(int networkType) {
- mNetworkInfo = new NetworkInfo(
- networkType, -1, ConnectivityManager.getNetworkTypeName(networkType), null);
- mLinkProperties = new LinkProperties();
- mNetworkCapabilities = new NetworkCapabilities();
- }
-
- protected BaseNetworkStateTracker() {
- // By default, let the sub classes construct everything
- }
-
- @Deprecated
- protected Handler getTargetHandler() {
- return mTarget;
- }
-
- protected final void dispatchStateChanged() {
- // TODO: include snapshot of other fields when sending
- mTarget.obtainMessage(EVENT_STATE_CHANGED, getNetworkInfo()).sendToTarget();
- }
-
- protected final void dispatchConfigurationChanged() {
- // TODO: include snapshot of other fields when sending
- mTarget.obtainMessage(EVENT_CONFIGURATION_CHANGED, getNetworkInfo()).sendToTarget();
- }
-
- @Override
- public void startMonitoring(Context context, Handler target) {
- mContext = Preconditions.checkNotNull(context);
- mTarget = Preconditions.checkNotNull(target);
- startMonitoringInternal();
- }
-
- protected void startMonitoringInternal() {
-
- }
-
- @Override
- public NetworkInfo getNetworkInfo() {
- return new NetworkInfo(mNetworkInfo);
- }
-
- @Override
- public LinkProperties getLinkProperties() {
- return new LinkProperties(mLinkProperties);
- }
-
- @Override
- public NetworkCapabilities getNetworkCapabilities() {
- return new NetworkCapabilities(mNetworkCapabilities);
- }
-
- @Override
- public LinkQualityInfo getLinkQualityInfo() {
- return null;
- }
-
- @Override
- public void captivePortalCheckCompleted(boolean isCaptivePortal) {
- // not implemented
- }
-
- @Override
- public boolean setRadio(boolean turnOn) {
- // Base tracker doesn't handle radios
- return true;
- }
-
- @Override
- public boolean isAvailable() {
- return mNetworkInfo.isAvailable();
- }
-
- @Override
- public void setUserDataEnable(boolean enabled) {
- // Base tracker doesn't handle enabled flags
- }
-
- @Override
- public void setPolicyDataEnable(boolean enabled) {
- // Base tracker doesn't handle enabled flags
- }
-
- @Override
- public boolean isPrivateDnsRouteSet() {
- return mPrivateDnsRouteSet.get();
- }
-
- @Override
- public void privateDnsRouteSet(boolean enabled) {
- mPrivateDnsRouteSet.set(enabled);
- }
-
- @Override
- public boolean isDefaultRouteSet() {
- return mDefaultRouteSet.get();
- }
-
- @Override
- public void defaultRouteSet(boolean enabled) {
- mDefaultRouteSet.set(enabled);
- }
-
- @Override
- public boolean isTeardownRequested() {
- return mTeardownRequested.get();
- }
-
- @Override
- public void setTeardownRequested(boolean isRequested) {
- mTeardownRequested.set(isRequested);
- }
-
- @Override
- public void setDependencyMet(boolean met) {
- // Base tracker doesn't handle dependencies
- }
-
- @Override
- public void supplyMessenger(Messenger messenger) {
- // not supported on this network
- }
-
- @Override
- public String getNetworkInterfaceName() {
- if (mLinkProperties != null) {
- return mLinkProperties.getInterfaceName();
- } else {
- return null;
- }
- }
-
- @Override
- public void startSampling(SamplingDataTracker.SamplingSnapshot s) {
- // nothing to do
- }
-
- @Override
- public void stopSampling(SamplingDataTracker.SamplingSnapshot s) {
- // nothing to do
- }
-
- @Override
- public void setNetId(int netId) {
- mNetwork = new Network(netId);
- }
-
- @Override
- public Network getNetwork() {
- return mNetwork;
- }
-}
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index eb2df0b..a00246f 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -1793,25 +1793,6 @@
}
/**
- * Sets a secondary requirement bit for the given networkType.
- * This requirement bit is generally under the control of the carrier
- * or its agents and is not directly controlled by the user.
- *
- * @param networkType The network who's dependence has changed
- * @param met Boolean - true if network use is OK, false if not
- *
- * <p>This method requires the call to hold the permission
- * {@link android.Manifest.permission#CONNECTIVITY_INTERNAL}.
- * {@hide}
- */
- public void setDataDependency(int networkType, boolean met) {
- try {
- mService.setDataDependency(networkType, met);
- } catch (RemoteException e) {
- }
- }
-
- /**
* Returns true if the hardware supports the given network type
* else it returns false. This doesn't indicate we have coverage
* or are authorized onto a network, just whether or not the
@@ -1892,20 +1873,6 @@
}
/**
- * Supply the backend messenger for a network tracker
- *
- * @param networkType NetworkType to set
- * @param messenger {@link Messenger}
- * {@hide}
- */
- public void supplyMessenger(int networkType, Messenger messenger) {
- try {
- mService.supplyMessenger(networkType, messenger);
- } catch (RemoteException e) {
- }
- }
-
- /**
* Check mobile provisioning.
*
* @param suggestedTimeOutMs, timeout in milliseconds
@@ -2370,7 +2337,7 @@
* successfully finding a network for the applications request. Retrieve it with
* {@link android.content.Intent#getParcelableExtra(String)}.
* <p>
- * Note that if you intend to invoke (@link #setProcessDefaultNetwork(Network)) or
+ * Note that if you intend to invoke {@link #setProcessDefaultNetwork} or
* {@link Network#openConnection(java.net.URL)} then you must get a
* ConnectivityManager instance before doing so.
*/
diff --git a/core/java/android/net/DhcpStateMachine.java b/core/java/android/net/DhcpStateMachine.java
index 5151a04..1b8adc8 100644
--- a/core/java/android/net/DhcpStateMachine.java
+++ b/core/java/android/net/DhcpStateMachine.java
@@ -47,7 +47,7 @@
*
* @hide
*/
-public class DhcpStateMachine extends StateMachine {
+public class DhcpStateMachine extends BaseDhcpStateMachine {
private static final String TAG = "DhcpStateMachine";
private static final boolean DBG = false;
@@ -161,6 +161,7 @@
* This is used by Wifi at this time for the purpose of doing BT-Wifi coex
* handling during Dhcp
*/
+ @Override
public void registerForPreDhcpNotification() {
mRegisteredForPreDhcpNotification = true;
}
@@ -170,6 +171,7 @@
*
* @hide
*/
+ @Override
public void doQuit() {
quit();
}
diff --git a/core/java/android/net/IConnectivityManager.aidl b/core/java/android/net/IConnectivityManager.aidl
index 46af112..d8852f8 100644
--- a/core/java/android/net/IConnectivityManager.aidl
+++ b/core/java/android/net/IConnectivityManager.aidl
@@ -102,8 +102,6 @@
ProxyInfo getDefaultProxy();
- void setDataDependency(int networkType, boolean met);
-
boolean prepareVpn(String oldPackage, String newPackage);
void setVpnPackageAuthorization(boolean authorized);
@@ -120,8 +118,6 @@
void captivePortalCheckCompleted(in NetworkInfo info, boolean isCaptivePortal);
- void supplyMessenger(int networkType, in Messenger messenger);
-
int findConnectionTypeForIface(in String iface);
int checkMobileProvisioning(int suggestedTimeOutMs);
diff --git a/core/java/android/net/MobileDataStateTracker.java b/core/java/android/net/MobileDataStateTracker.java
deleted file mode 100644
index abbb7b8..0000000
--- a/core/java/android/net/MobileDataStateTracker.java
+++ /dev/null
@@ -1,910 +0,0 @@
-/*
- * Copyright (C) 2008 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;
-
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.net.NetworkInfo.DetailedState;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.Looper;
-import android.os.Message;
-import android.os.Messenger;
-import android.os.RemoteException;
-import android.os.ServiceManager;
-import android.telephony.PhoneStateListener;
-import android.telephony.SignalStrength;
-import android.telephony.TelephonyManager;
-import android.text.TextUtils;
-import android.util.Slog;
-
-import com.android.internal.telephony.DctConstants;
-import com.android.internal.telephony.ITelephony;
-import com.android.internal.telephony.PhoneConstants;
-import com.android.internal.telephony.TelephonyIntents;
-import com.android.internal.util.AsyncChannel;
-
-import java.io.CharArrayWriter;
-import java.io.PrintWriter;
-import java.util.concurrent.atomic.AtomicBoolean;
-
-/**
- * Track the state of mobile data connectivity. This is done by
- * receiving broadcast intents from the Phone process whenever
- * the state of data connectivity changes.
- *
- * {@hide}
- */
-public class MobileDataStateTracker extends BaseNetworkStateTracker {
-
- private static final String TAG = "MobileDataStateTracker";
- private static final boolean DBG = false;
- private static final boolean VDBG = false;
-
- private PhoneConstants.DataState mMobileDataState;
- private ITelephony mPhoneService;
-
- private String mApnType;
- private NetworkInfo mNetworkInfo;
- private boolean mTeardownRequested = false;
- private Handler mTarget;
- private Context mContext;
- private LinkProperties mLinkProperties;
- private boolean mPrivateDnsRouteSet = false;
- private boolean mDefaultRouteSet = false;
-
- // NOTE: these are only kept for debugging output; actual values are
- // maintained in DataConnectionTracker.
- protected boolean mUserDataEnabled = true;
- protected boolean mPolicyDataEnabled = true;
-
- private Handler mHandler;
- private AsyncChannel mDataConnectionTrackerAc;
-
- private AtomicBoolean mIsCaptivePortal = new AtomicBoolean(false);
-
- private SignalStrength mSignalStrength;
-
- private SamplingDataTracker mSamplingDataTracker = new SamplingDataTracker();
-
- private static final int UNKNOWN = LinkQualityInfo.UNKNOWN_INT;
-
- /**
- * Create a new MobileDataStateTracker
- * @param netType the ConnectivityManager network type
- * @param tag the name of this network
- */
- public MobileDataStateTracker(int netType, String tag) {
- mNetworkInfo = new NetworkInfo(netType,
- TelephonyManager.getDefault().getNetworkType(), tag,
- TelephonyManager.getDefault().getNetworkTypeName());
- mApnType = networkTypeToApnType(netType);
- }
-
- /**
- * Begin monitoring data connectivity.
- *
- * @param context is the current Android context
- * @param target is the Hander to which to return the events.
- */
- public void startMonitoring(Context context, Handler target) {
- mTarget = target;
- mContext = context;
-
- mHandler = new MdstHandler(target.getLooper(), this);
-
- IntentFilter filter = new IntentFilter();
- filter.addAction(TelephonyIntents.ACTION_ANY_DATA_CONNECTION_STATE_CHANGED);
- filter.addAction(TelephonyIntents.ACTION_DATA_CONNECTION_CONNECTED_TO_PROVISIONING_APN);
- filter.addAction(TelephonyIntents.ACTION_DATA_CONNECTION_FAILED);
-
- mContext.registerReceiver(new MobileDataStateReceiver(), filter);
- mMobileDataState = PhoneConstants.DataState.DISCONNECTED;
-
- TelephonyManager tm = (TelephonyManager)mContext.getSystemService(
- Context.TELEPHONY_SERVICE);
- tm.listen(mPhoneStateListener, PhoneStateListener.LISTEN_SIGNAL_STRENGTHS);
- }
-
- private final PhoneStateListener mPhoneStateListener = new PhoneStateListener() {
- @Override
- public void onSignalStrengthsChanged(SignalStrength signalStrength) {
- mSignalStrength = signalStrength;
- }
- };
-
- static class MdstHandler extends Handler {
- private MobileDataStateTracker mMdst;
-
- MdstHandler(Looper looper, MobileDataStateTracker mdst) {
- super(looper);
- mMdst = mdst;
- }
-
- @Override
- public void handleMessage(Message msg) {
- switch (msg.what) {
- case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED:
- if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) {
- if (VDBG) {
- mMdst.log("MdstHandler connected");
- }
- mMdst.mDataConnectionTrackerAc = (AsyncChannel) msg.obj;
- } else {
- if (VDBG) {
- mMdst.log("MdstHandler %s NOT connected error=" + msg.arg1);
- }
- }
- break;
- case AsyncChannel.CMD_CHANNEL_DISCONNECTED:
- if (VDBG) mMdst.log("Disconnected from DataStateTracker");
- mMdst.mDataConnectionTrackerAc = null;
- break;
- default: {
- if (VDBG) mMdst.log("Ignorning unknown message=" + msg);
- break;
- }
- }
- }
- }
-
- public boolean isPrivateDnsRouteSet() {
- return mPrivateDnsRouteSet;
- }
-
- public void privateDnsRouteSet(boolean enabled) {
- mPrivateDnsRouteSet = enabled;
- }
-
- public NetworkInfo getNetworkInfo() {
- return mNetworkInfo;
- }
-
- public boolean isDefaultRouteSet() {
- return mDefaultRouteSet;
- }
-
- public void defaultRouteSet(boolean enabled) {
- mDefaultRouteSet = enabled;
- }
-
- /**
- * This is not implemented.
- */
- public void releaseWakeLock() {
- }
-
- private void updateLinkProperitesAndCapatilities(Intent intent) {
- mLinkProperties = intent.getParcelableExtra(
- PhoneConstants.DATA_LINK_PROPERTIES_KEY);
- if (mLinkProperties == null) {
- loge("CONNECTED event did not supply link properties.");
- mLinkProperties = new LinkProperties();
- }
- mLinkProperties.setMtu(mContext.getResources().getInteger(
- com.android.internal.R.integer.config_mobile_mtu));
- mNetworkCapabilities = intent.getParcelableExtra(
- PhoneConstants.DATA_NETWORK_CAPABILITIES_KEY);
- if (mNetworkCapabilities == null) {
- loge("CONNECTED event did not supply network capabilities.");
- mNetworkCapabilities = new NetworkCapabilities();
- }
- }
-
- private class MobileDataStateReceiver extends BroadcastReceiver {
- @Override
- public void onReceive(Context context, Intent intent) {
- if (intent.getAction().equals(TelephonyIntents.
- ACTION_DATA_CONNECTION_CONNECTED_TO_PROVISIONING_APN)) {
- String apnName = intent.getStringExtra(PhoneConstants.DATA_APN_KEY);
- String apnType = intent.getStringExtra(PhoneConstants.DATA_APN_TYPE_KEY);
- if (!TextUtils.equals(mApnType, apnType)) {
- return;
- }
- if (DBG) {
- log("Broadcast received: " + intent.getAction() + " apnType=" + apnType
- + " apnName=" + apnName);
- }
-
- // Make us in the connecting state until we make a new TYPE_MOBILE_PROVISIONING
- mMobileDataState = PhoneConstants.DataState.CONNECTING;
- updateLinkProperitesAndCapatilities(intent);
- mNetworkInfo.setIsConnectedToProvisioningNetwork(true);
-
- // Change state to SUSPENDED so setDetailedState
- // sends EVENT_STATE_CHANGED to connectivityService
- setDetailedState(DetailedState.SUSPENDED, "", apnName);
- } else if (intent.getAction().equals(TelephonyIntents.
- ACTION_ANY_DATA_CONNECTION_STATE_CHANGED)) {
- String apnType = intent.getStringExtra(PhoneConstants.DATA_APN_TYPE_KEY);
- if (VDBG) {
- log(String.format("Broadcast received: ACTION_ANY_DATA_CONNECTION_STATE_CHANGED"
- + "mApnType=%s %s received apnType=%s", mApnType,
- TextUtils.equals(apnType, mApnType) ? "==" : "!=", apnType));
- }
- if (!TextUtils.equals(apnType, mApnType)) {
- return;
- }
- // Assume this isn't a provisioning network.
- mNetworkInfo.setIsConnectedToProvisioningNetwork(false);
- if (DBG) {
- log("Broadcast received: " + intent.getAction() + " apnType=" + apnType);
- }
-
- int oldSubtype = mNetworkInfo.getSubtype();
- int newSubType = TelephonyManager.getDefault().getNetworkType();
- String subTypeName = TelephonyManager.getDefault().getNetworkTypeName();
- mNetworkInfo.setSubtype(newSubType, subTypeName);
- if (newSubType != oldSubtype && mNetworkInfo.isConnected()) {
- Message msg = mTarget.obtainMessage(EVENT_NETWORK_SUBTYPE_CHANGED,
- oldSubtype, 0, mNetworkInfo);
- msg.sendToTarget();
- }
-
- PhoneConstants.DataState state = Enum.valueOf(PhoneConstants.DataState.class,
- intent.getStringExtra(PhoneConstants.STATE_KEY));
- String reason = intent.getStringExtra(PhoneConstants.STATE_CHANGE_REASON_KEY);
- String apnName = intent.getStringExtra(PhoneConstants.DATA_APN_KEY);
- mNetworkInfo.setRoaming(intent.getBooleanExtra(
- PhoneConstants.DATA_NETWORK_ROAMING_KEY, false));
- if (VDBG) {
- log(mApnType + " setting isAvailable to " +
- intent.getBooleanExtra(PhoneConstants.NETWORK_UNAVAILABLE_KEY,false));
- }
- mNetworkInfo.setIsAvailable(!intent.getBooleanExtra(
- PhoneConstants.NETWORK_UNAVAILABLE_KEY, false));
-
- if (DBG) {
- log("Received state=" + state + ", old=" + mMobileDataState +
- ", reason=" + (reason == null ? "(unspecified)" : reason));
- }
- if (mMobileDataState != state) {
- mMobileDataState = state;
- switch (state) {
- case DISCONNECTED:
- if(isTeardownRequested()) {
- setTeardownRequested(false);
- }
-
- setDetailedState(DetailedState.DISCONNECTED, reason, apnName);
- // can't do this here - ConnectivityService needs it to clear stuff
- // it's ok though - just leave it to be refreshed next time
- // we connect.
- //if (DBG) log("clearing mInterfaceName for "+ mApnType +
- // " as it DISCONNECTED");
- //mInterfaceName = null;
- break;
- case CONNECTING:
- setDetailedState(DetailedState.CONNECTING, reason, apnName);
- break;
- case SUSPENDED:
- setDetailedState(DetailedState.SUSPENDED, reason, apnName);
- break;
- case CONNECTED:
- updateLinkProperitesAndCapatilities(intent);
- setDetailedState(DetailedState.CONNECTED, reason, apnName);
- break;
- }
-
- if (VDBG) {
- Slog.d(TAG, "TelephonyMgr.DataConnectionStateChanged");
- if (mNetworkInfo != null) {
- Slog.d(TAG, "NetworkInfo = " + mNetworkInfo);
- Slog.d(TAG, "subType = " + mNetworkInfo.getSubtype());
- Slog.d(TAG, "subType = " + mNetworkInfo.getSubtypeName());
- }
- if (mLinkProperties != null) {
- Slog.d(TAG, "LinkProperties = " + mLinkProperties);
- } else {
- Slog.d(TAG, "LinkProperties = " );
- }
-
- if (mNetworkCapabilities != null) {
- Slog.d(TAG, mNetworkCapabilities.toString());
- } else {
- Slog.d(TAG, "NetworkCapabilities = " );
- }
- }
-
-
- /* lets not sample traffic data across state changes */
- mSamplingDataTracker.resetSamplingData();
- } else {
- // There was no state change. Check if LinkProperties has been updated.
- if (TextUtils.equals(reason, PhoneConstants.REASON_LINK_PROPERTIES_CHANGED)) {
- mLinkProperties = intent.getParcelableExtra(
- PhoneConstants.DATA_LINK_PROPERTIES_KEY);
- if (mLinkProperties == null) {
- loge("No link property in LINK_PROPERTIES change event.");
- mLinkProperties = new LinkProperties();
- }
- // Just update reason field in this NetworkInfo
- mNetworkInfo.setDetailedState(mNetworkInfo.getDetailedState(), reason,
- mNetworkInfo.getExtraInfo());
- Message msg = mTarget.obtainMessage(EVENT_CONFIGURATION_CHANGED,
- mNetworkInfo);
- msg.sendToTarget();
- }
- }
- } else if (intent.getAction().
- equals(TelephonyIntents.ACTION_DATA_CONNECTION_FAILED)) {
- String apnType = intent.getStringExtra(PhoneConstants.DATA_APN_TYPE_KEY);
- if (!TextUtils.equals(apnType, mApnType)) {
- if (DBG) {
- log(String.format(
- "Broadcast received: ACTION_ANY_DATA_CONNECTION_FAILED ignore, " +
- "mApnType=%s != received apnType=%s", mApnType, apnType));
- }
- return;
- }
- // Assume this isn't a provisioning network.
- mNetworkInfo.setIsConnectedToProvisioningNetwork(false);
- String reason = intent.getStringExtra(PhoneConstants.FAILURE_REASON_KEY);
- String apnName = intent.getStringExtra(PhoneConstants.DATA_APN_KEY);
- if (DBG) {
- log("Broadcast received: " + intent.getAction() +
- " reason=" + reason == null ? "null" : reason);
- }
- setDetailedState(DetailedState.FAILED, reason, apnName);
- } else {
- if (DBG) log("Broadcast received: ignore " + intent.getAction());
- }
- }
- }
-
- private void getPhoneService(boolean forceRefresh) {
- if ((mPhoneService == null) || forceRefresh) {
- mPhoneService = ITelephony.Stub.asInterface(ServiceManager.getService("phone"));
- }
- }
-
- /**
- * Report whether data connectivity is possible.
- */
- public boolean isAvailable() {
- return mNetworkInfo.isAvailable();
- }
-
- /**
- * Return the system properties name associated with the tcp buffer sizes
- * for this network.
- */
- public String getTcpBufferSizesPropName() {
- String networkTypeStr = "unknown";
- TelephonyManager tm = new TelephonyManager(mContext);
- //TODO We have to edit the parameter for getNetworkType regarding CDMA
- switch(tm.getNetworkType()) {
- case TelephonyManager.NETWORK_TYPE_GPRS:
- networkTypeStr = "gprs";
- break;
- case TelephonyManager.NETWORK_TYPE_EDGE:
- networkTypeStr = "edge";
- break;
- case TelephonyManager.NETWORK_TYPE_UMTS:
- networkTypeStr = "umts";
- break;
- case TelephonyManager.NETWORK_TYPE_HSDPA:
- networkTypeStr = "hsdpa";
- break;
- case TelephonyManager.NETWORK_TYPE_HSUPA:
- networkTypeStr = "hsupa";
- break;
- case TelephonyManager.NETWORK_TYPE_HSPA:
- networkTypeStr = "hspa";
- break;
- case TelephonyManager.NETWORK_TYPE_HSPAP:
- networkTypeStr = "hspap";
- break;
- case TelephonyManager.NETWORK_TYPE_CDMA:
- networkTypeStr = "cdma";
- break;
- case TelephonyManager.NETWORK_TYPE_1xRTT:
- networkTypeStr = "1xrtt";
- break;
- case TelephonyManager.NETWORK_TYPE_EVDO_0:
- networkTypeStr = "evdo";
- break;
- case TelephonyManager.NETWORK_TYPE_EVDO_A:
- networkTypeStr = "evdo";
- break;
- case TelephonyManager.NETWORK_TYPE_EVDO_B:
- networkTypeStr = "evdo";
- break;
- case TelephonyManager.NETWORK_TYPE_IDEN:
- networkTypeStr = "iden";
- break;
- case TelephonyManager.NETWORK_TYPE_LTE:
- case TelephonyManager.NETWORK_TYPE_IWLAN:
- networkTypeStr = "lte";
- break;
- case TelephonyManager.NETWORK_TYPE_EHRPD:
- networkTypeStr = "ehrpd";
- break;
- default:
- loge("unknown network type: " + tm.getNetworkType());
- }
- return "net.tcp.buffersize." + networkTypeStr;
- }
-
- /**
- * Tear down mobile data connectivity, i.e., disable the ability to create
- * mobile data connections.
- * TODO - make async and return nothing?
- */
- public boolean teardown() {
- setTeardownRequested(true);
- return (setEnableApn(mApnType, false) != PhoneConstants.APN_REQUEST_FAILED);
- }
-
- /**
- * @return true if this is ready to operate
- */
- public boolean isReady() {
- return mDataConnectionTrackerAc != null;
- }
-
- @Override
- public void captivePortalCheckCompleted(boolean isCaptivePortal) {
- if (mIsCaptivePortal.getAndSet(isCaptivePortal) != isCaptivePortal) {
- // Captive portal change enable/disable failing fast
- setEnableFailFastMobileData(
- isCaptivePortal ? DctConstants.ENABLED : DctConstants.DISABLED);
- }
- }
-
- /**
- * Record the detailed state of a network, and if it is a
- * change from the previous state, send a notification to
- * any listeners.
- * @param state the new {@code DetailedState}
- * @param reason a {@code String} indicating a reason for the state change,
- * if one was supplied. May be {@code null}.
- * @param extraInfo optional {@code String} providing extra information about the state change
- */
- private void setDetailedState(NetworkInfo.DetailedState state, String reason,
- String extraInfo) {
- if (DBG) log("setDetailed state, old ="
- + mNetworkInfo.getDetailedState() + " and new state=" + state);
- if (state != mNetworkInfo.getDetailedState()) {
- boolean wasConnecting = (mNetworkInfo.getState() == NetworkInfo.State.CONNECTING);
- String lastReason = mNetworkInfo.getReason();
- /*
- * If a reason was supplied when the CONNECTING state was entered, and no
- * reason was supplied for entering the CONNECTED state, then retain the
- * reason that was supplied when going to CONNECTING.
- */
- if (wasConnecting && state == NetworkInfo.DetailedState.CONNECTED && reason == null
- && lastReason != null)
- reason = lastReason;
- mNetworkInfo.setDetailedState(state, reason, extraInfo);
- Message msg = mTarget.obtainMessage(EVENT_STATE_CHANGED, new NetworkInfo(mNetworkInfo));
- msg.sendToTarget();
- }
- }
-
- public void setTeardownRequested(boolean isRequested) {
- mTeardownRequested = isRequested;
- }
-
- public boolean isTeardownRequested() {
- return mTeardownRequested;
- }
-
- /**
- * Re-enable mobile data connectivity after a {@link #teardown()}.
- * TODO - make async and always get a notification?
- */
- public boolean reconnect() {
- boolean retValue = false; //connected or expect to be?
- setTeardownRequested(false);
- switch (setEnableApn(mApnType, true)) {
- case PhoneConstants.APN_ALREADY_ACTIVE:
- // need to set self to CONNECTING so the below message is handled.
- retValue = true;
- break;
- case PhoneConstants.APN_REQUEST_STARTED:
- // set IDLE here , avoid the following second FAILED not sent out
- mNetworkInfo.setDetailedState(DetailedState.IDLE, null, null);
- retValue = true;
- break;
- case PhoneConstants.APN_REQUEST_FAILED:
- case PhoneConstants.APN_TYPE_NOT_AVAILABLE:
- break;
- default:
- loge("Error in reconnect - unexpected response.");
- break;
- }
- return retValue;
- }
-
- /**
- * Turn on or off the mobile radio. No connectivity will be possible while the
- * radio is off. The operation is a no-op if the radio is already in the desired state.
- * @param turnOn {@code true} if the radio should be turned on, {@code false} if
- */
- public boolean setRadio(boolean turnOn) {
- getPhoneService(false);
- /*
- * If the phone process has crashed in the past, we'll get a
- * RemoteException and need to re-reference the service.
- */
- for (int retry = 0; retry < 2; retry++) {
- if (mPhoneService == null) {
- loge("Ignoring mobile radio request because could not acquire PhoneService");
- break;
- }
-
- try {
- return mPhoneService.setRadio(turnOn);
- } catch (RemoteException e) {
- if (retry == 0) getPhoneService(true);
- }
- }
-
- loge("Could not set radio power to " + (turnOn ? "on" : "off"));
- return false;
- }
-
-
- public void setInternalDataEnable(boolean enabled) {
- if (DBG) log("setInternalDataEnable: E enabled=" + enabled);
- final AsyncChannel channel = mDataConnectionTrackerAc;
- if (channel != null) {
- channel.sendMessage(DctConstants.EVENT_SET_INTERNAL_DATA_ENABLE,
- enabled ? DctConstants.ENABLED : DctConstants.DISABLED);
- }
- if (VDBG) log("setInternalDataEnable: X enabled=" + enabled);
- }
-
- @Override
- public void setUserDataEnable(boolean enabled) {
- if (DBG) log("setUserDataEnable: E enabled=" + enabled);
- final AsyncChannel channel = mDataConnectionTrackerAc;
- if (channel != null) {
- channel.sendMessage(DctConstants.CMD_SET_USER_DATA_ENABLE,
- enabled ? DctConstants.ENABLED : DctConstants.DISABLED);
- mUserDataEnabled = enabled;
- }
- if (VDBG) log("setUserDataEnable: X enabled=" + enabled);
- }
-
- @Override
- public void setPolicyDataEnable(boolean enabled) {
- if (DBG) log("setPolicyDataEnable(enabled=" + enabled + ")");
- final AsyncChannel channel = mDataConnectionTrackerAc;
- if (channel != null) {
- channel.sendMessage(DctConstants.CMD_SET_POLICY_DATA_ENABLE,
- enabled ? DctConstants.ENABLED : DctConstants.DISABLED);
- mPolicyDataEnabled = enabled;
- }
- }
-
- /**
- * Eanble/disable FailFast
- *
- * @param enabled is DctConstants.ENABLED/DISABLED
- */
- public void setEnableFailFastMobileData(int enabled) {
- if (DBG) log("setEnableFailFastMobileData(enabled=" + enabled + ")");
- final AsyncChannel channel = mDataConnectionTrackerAc;
- if (channel != null) {
- channel.sendMessage(DctConstants.CMD_SET_ENABLE_FAIL_FAST_MOBILE_DATA, enabled);
- }
- }
-
- /**
- * carrier dependency is met/unmet
- * @param met
- */
- public void setDependencyMet(boolean met) {
- Bundle bundle = Bundle.forPair(DctConstants.APN_TYPE_KEY, mApnType);
- try {
- if (DBG) log("setDependencyMet: E met=" + met);
- Message msg = Message.obtain();
- msg.what = DctConstants.CMD_SET_DEPENDENCY_MET;
- msg.arg1 = (met ? DctConstants.ENABLED : DctConstants.DISABLED);
- msg.setData(bundle);
- mDataConnectionTrackerAc.sendMessage(msg);
- if (VDBG) log("setDependencyMet: X met=" + met);
- } catch (NullPointerException e) {
- loge("setDependencyMet: X mAc was null" + e);
- }
- }
-
- /**
- * Inform DCT mobile provisioning has started, it ends when provisioning completes.
- */
- public void enableMobileProvisioning(String url) {
- if (DBG) log("enableMobileProvisioning(url=" + url + ")");
- final AsyncChannel channel = mDataConnectionTrackerAc;
- if (channel != null) {
- Message msg = Message.obtain();
- msg.what = DctConstants.CMD_ENABLE_MOBILE_PROVISIONING;
- msg.setData(Bundle.forPair(DctConstants.PROVISIONING_URL_KEY, url));
- channel.sendMessage(msg);
- }
- }
-
- /**
- * Return if this network is the provisioning network. Valid only if connected.
- * @param met
- */
- public boolean isProvisioningNetwork() {
- boolean retVal;
- try {
- Message msg = Message.obtain();
- msg.what = DctConstants.CMD_IS_PROVISIONING_APN;
- msg.setData(Bundle.forPair(DctConstants.APN_TYPE_KEY, mApnType));
- Message result = mDataConnectionTrackerAc.sendMessageSynchronously(msg);
- retVal = result.arg1 == DctConstants.ENABLED;
- } catch (NullPointerException e) {
- loge("isProvisioningNetwork: X " + e);
- retVal = false;
- }
- if (DBG) log("isProvisioningNetwork: retVal=" + retVal);
- return retVal;
- }
-
- @Override
- public String toString() {
- final CharArrayWriter writer = new CharArrayWriter();
- final PrintWriter pw = new PrintWriter(writer);
- pw.print("Mobile data state: "); pw.println(mMobileDataState);
- pw.print("Data enabled: user="); pw.print(mUserDataEnabled);
- pw.print(", policy="); pw.println(mPolicyDataEnabled);
- return writer.toString();
- }
-
- /**
- * Internal method supporting the ENABLE_MMS feature.
- * @param apnType the type of APN to be enabled or disabled (e.g., mms)
- * @param enable {@code true} to enable the specified APN type,
- * {@code false} to disable it.
- * @return an integer value representing the outcome of the request.
- */
- private int setEnableApn(String apnType, boolean enable) {
- getPhoneService(false);
- /*
- * If the phone process has crashed in the past, we'll get a
- * RemoteException and need to re-reference the service.
- */
- for (int retry = 0; retry < 2; retry++) {
- if (mPhoneService == null) {
- loge("Ignoring feature request because could not acquire PhoneService");
- break;
- }
-
-// try {
-// if (enable) {
-// return mPhoneService.enableApnType(apnType);
-// } else {
-// return mPhoneService.disableApnType(apnType);
-// }
-// } catch (RemoteException e) {
-// if (retry == 0) getPhoneService(true);
-// }
- }
-
- loge("Could not " + (enable ? "enable" : "disable") + " APN type \"" + apnType + "\"");
- return PhoneConstants.APN_REQUEST_FAILED;
- }
-
- public static String networkTypeToApnType(int netType) {
- switch(netType) {
- case ConnectivityManager.TYPE_MOBILE:
- return PhoneConstants.APN_TYPE_DEFAULT; // TODO - use just one of these
- case ConnectivityManager.TYPE_MOBILE_MMS:
- return PhoneConstants.APN_TYPE_MMS;
- case ConnectivityManager.TYPE_MOBILE_SUPL:
- return PhoneConstants.APN_TYPE_SUPL;
- case ConnectivityManager.TYPE_MOBILE_DUN:
- return PhoneConstants.APN_TYPE_DUN;
- case ConnectivityManager.TYPE_MOBILE_HIPRI:
- return PhoneConstants.APN_TYPE_HIPRI;
- case ConnectivityManager.TYPE_MOBILE_FOTA:
- return PhoneConstants.APN_TYPE_FOTA;
- case ConnectivityManager.TYPE_MOBILE_IMS:
- return PhoneConstants.APN_TYPE_IMS;
- case ConnectivityManager.TYPE_MOBILE_CBS:
- return PhoneConstants.APN_TYPE_CBS;
- case ConnectivityManager.TYPE_MOBILE_IA:
- return PhoneConstants.APN_TYPE_IA;
- case ConnectivityManager.TYPE_MOBILE_EMERGENCY:
- return PhoneConstants.APN_TYPE_EMERGENCY;
- default:
- sloge("Error mapping networkType " + netType + " to apnType.");
- return null;
- }
- }
-
-
- /**
- * @see android.net.NetworkStateTracker#getLinkProperties()
- */
- @Override
- public LinkProperties getLinkProperties() {
- return new LinkProperties(mLinkProperties);
- }
-
- public void supplyMessenger(Messenger messenger) {
- if (VDBG) log(mApnType + " got supplyMessenger");
- AsyncChannel ac = new AsyncChannel();
- ac.connect(mContext, MobileDataStateTracker.this.mHandler, messenger);
- }
-
- private void log(String s) {
- Slog.d(TAG, mApnType + ": " + s);
- }
-
- private void loge(String s) {
- Slog.e(TAG, mApnType + ": " + s);
- }
-
- static private void sloge(String s) {
- Slog.e(TAG, s);
- }
-
- @Override
- public LinkQualityInfo getLinkQualityInfo() {
- if (mNetworkInfo == null || mNetworkInfo.getType() == ConnectivityManager.TYPE_NONE) {
- // no data available yet; just return
- return null;
- }
-
- MobileLinkQualityInfo li = new MobileLinkQualityInfo();
-
- li.setNetworkType(mNetworkInfo.getType());
-
- mSamplingDataTracker.setCommonLinkQualityInfoFields(li);
-
- if (mNetworkInfo.getSubtype() != TelephonyManager.NETWORK_TYPE_UNKNOWN) {
- li.setMobileNetworkType(mNetworkInfo.getSubtype());
-
- NetworkDataEntry entry = getNetworkDataEntry(mNetworkInfo.getSubtype());
- if (entry != null) {
- li.setTheoreticalRxBandwidth(entry.downloadBandwidth);
- li.setTheoreticalRxBandwidth(entry.uploadBandwidth);
- li.setTheoreticalLatency(entry.latency);
- }
-
- if (mSignalStrength != null) {
- li.setNormalizedSignalStrength(getNormalizedSignalStrength(
- li.getMobileNetworkType(), mSignalStrength));
- }
- }
-
- SignalStrength ss = mSignalStrength;
- if (ss != null) {
-
- li.setRssi(ss.getGsmSignalStrength());
- li.setGsmErrorRate(ss.getGsmBitErrorRate());
- li.setCdmaDbm(ss.getCdmaDbm());
- li.setCdmaEcio(ss.getCdmaEcio());
- li.setEvdoDbm(ss.getEvdoDbm());
- li.setEvdoEcio(ss.getEvdoEcio());
- li.setEvdoSnr(ss.getEvdoSnr());
- li.setLteSignalStrength(ss.getLteSignalStrength());
- li.setLteRsrp(ss.getLteRsrp());
- li.setLteRsrq(ss.getLteRsrq());
- li.setLteRssnr(ss.getLteRssnr());
- li.setLteCqi(ss.getLteCqi());
- }
-
- if (VDBG) {
- Slog.d(TAG, "Returning LinkQualityInfo with"
- + " MobileNetworkType = " + String.valueOf(li.getMobileNetworkType())
- + " Theoretical Rx BW = " + String.valueOf(li.getTheoreticalRxBandwidth())
- + " gsm Signal Strength = " + String.valueOf(li.getRssi())
- + " cdma Signal Strength = " + String.valueOf(li.getCdmaDbm())
- + " evdo Signal Strength = " + String.valueOf(li.getEvdoDbm())
- + " Lte Signal Strength = " + String.valueOf(li.getLteSignalStrength()));
- }
-
- return li;
- }
-
- static class NetworkDataEntry {
- public int networkType;
- public int downloadBandwidth; // in kbps
- public int uploadBandwidth; // in kbps
- public int latency; // in millisecond
-
- NetworkDataEntry(int i1, int i2, int i3, int i4) {
- networkType = i1;
- downloadBandwidth = i2;
- uploadBandwidth = i3;
- latency = i4;
- }
- }
-
- private static NetworkDataEntry [] mTheoreticalBWTable = new NetworkDataEntry[] {
- new NetworkDataEntry(TelephonyManager.NETWORK_TYPE_EDGE, 237, 118, UNKNOWN),
- new NetworkDataEntry(TelephonyManager.NETWORK_TYPE_GPRS, 48, 40, UNKNOWN),
- new NetworkDataEntry(TelephonyManager.NETWORK_TYPE_UMTS, 384, 64, UNKNOWN),
- new NetworkDataEntry(TelephonyManager.NETWORK_TYPE_HSDPA, 14400, UNKNOWN, UNKNOWN),
- new NetworkDataEntry(TelephonyManager.NETWORK_TYPE_HSUPA, 14400, 5760, UNKNOWN),
- new NetworkDataEntry(TelephonyManager.NETWORK_TYPE_HSPA, 14400, 5760, UNKNOWN),
- new NetworkDataEntry(TelephonyManager.NETWORK_TYPE_HSPAP, 21000, 5760, UNKNOWN),
- new NetworkDataEntry(TelephonyManager.NETWORK_TYPE_CDMA, UNKNOWN, UNKNOWN, UNKNOWN),
- new NetworkDataEntry(TelephonyManager.NETWORK_TYPE_1xRTT, UNKNOWN, UNKNOWN, UNKNOWN),
- new NetworkDataEntry(TelephonyManager.NETWORK_TYPE_EVDO_0, 2468, 153, UNKNOWN),
- new NetworkDataEntry(TelephonyManager.NETWORK_TYPE_EVDO_A, 3072, 1800, UNKNOWN),
- new NetworkDataEntry(TelephonyManager.NETWORK_TYPE_EVDO_B, 14700, 1800, UNKNOWN),
- new NetworkDataEntry(TelephonyManager.NETWORK_TYPE_IDEN, UNKNOWN, UNKNOWN, UNKNOWN),
- new NetworkDataEntry(TelephonyManager.NETWORK_TYPE_LTE, 100000, 50000, UNKNOWN),
- new NetworkDataEntry(TelephonyManager.NETWORK_TYPE_EHRPD, UNKNOWN, UNKNOWN, UNKNOWN),
- };
-
- private static NetworkDataEntry getNetworkDataEntry(int networkType) {
- for (NetworkDataEntry entry : mTheoreticalBWTable) {
- if (entry.networkType == networkType) {
- return entry;
- }
- }
-
- Slog.e(TAG, "Could not find Theoretical BW entry for " + String.valueOf(networkType));
- return null;
- }
-
- private static int getNormalizedSignalStrength(int networkType, SignalStrength ss) {
-
- int level;
-
- switch(networkType) {
- case TelephonyManager.NETWORK_TYPE_EDGE:
- case TelephonyManager.NETWORK_TYPE_GPRS:
- case TelephonyManager.NETWORK_TYPE_UMTS:
- case TelephonyManager.NETWORK_TYPE_HSDPA:
- case TelephonyManager.NETWORK_TYPE_HSUPA:
- case TelephonyManager.NETWORK_TYPE_HSPA:
- case TelephonyManager.NETWORK_TYPE_HSPAP:
- level = ss.getGsmLevel();
- break;
- case TelephonyManager.NETWORK_TYPE_CDMA:
- case TelephonyManager.NETWORK_TYPE_1xRTT:
- level = ss.getCdmaLevel();
- break;
- case TelephonyManager.NETWORK_TYPE_EVDO_0:
- case TelephonyManager.NETWORK_TYPE_EVDO_A:
- case TelephonyManager.NETWORK_TYPE_EVDO_B:
- level = ss.getEvdoLevel();
- break;
- case TelephonyManager.NETWORK_TYPE_LTE:
- level = ss.getLteLevel();
- break;
- case TelephonyManager.NETWORK_TYPE_IDEN:
- case TelephonyManager.NETWORK_TYPE_EHRPD:
- default:
- return UNKNOWN;
- }
-
- return (level * LinkQualityInfo.NORMALIZED_SIGNAL_STRENGTH_RANGE) /
- SignalStrength.NUM_SIGNAL_STRENGTH_BINS;
- }
-
- @Override
- public void startSampling(SamplingDataTracker.SamplingSnapshot s) {
- mSamplingDataTracker.startSampling(s);
- }
-
- @Override
- public void stopSampling(SamplingDataTracker.SamplingSnapshot s) {
- mSamplingDataTracker.stopSampling(s);
- }
-}
diff --git a/core/java/android/net/NetworkCapabilities.java b/core/java/android/net/NetworkCapabilities.java
index a7f9c5b..8c8bfab 100644
--- a/core/java/android/net/NetworkCapabilities.java
+++ b/core/java/android/net/NetworkCapabilities.java
@@ -148,9 +148,9 @@
*/
public static final int NET_CAPABILITY_TRUSTED = 14;
- /*
+ /**
* Indicates that this network is not a VPN. This capability is set by default and should be
- * explicitly cleared when creating VPN networks.
+ * explicitly cleared for VPN networks.
*/
public static final int NET_CAPABILITY_NOT_VPN = 15;
diff --git a/core/java/android/net/NetworkStateTracker.java b/core/java/android/net/NetworkStateTracker.java
deleted file mode 100644
index c80782c..0000000
--- a/core/java/android/net/NetworkStateTracker.java
+++ /dev/null
@@ -1,250 +0,0 @@
-/*
- * Copyright (C) 2008 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;
-
-import android.content.Context;
-import android.os.Handler;
-import android.os.Messenger;
-
-import static com.android.internal.util.Protocol.BASE_NETWORK_STATE_TRACKER;
-
-/**
- * Interface provides the {@link com.android.server.ConnectivityService}
- * with three services. Events to the ConnectivityService when
- * changes occur, an API for controlling the network and storage
- * for network specific information.
- *
- * The Connectivity will call startMonitoring before any other
- * method is called.
- *
- * {@hide}
- */
-public interface NetworkStateTracker {
-
- /**
- * -------------------------------------------------------------
- * Event Interface back to ConnectivityService.
- *
- * The events that are to be sent back to the Handler passed
- * to startMonitoring when the particular event occurs.
- * -------------------------------------------------------------
- */
-
- /**
- * The network state has changed and the NetworkInfo object
- * contains the new state.
- *
- * msg.what = EVENT_STATE_CHANGED
- * msg.obj = NetworkInfo object
- */
- public static final int EVENT_STATE_CHANGED = BASE_NETWORK_STATE_TRACKER;
-
- /**
- * msg.what = EVENT_CONFIGURATION_CHANGED
- * msg.obj = NetworkInfo object
- */
- public static final int EVENT_CONFIGURATION_CHANGED = BASE_NETWORK_STATE_TRACKER + 1;
-
- /**
- * msg.what = EVENT_RESTORE_DEFAULT_NETWORK
- * msg.obj = FeatureUser object
- */
- public static final int EVENT_RESTORE_DEFAULT_NETWORK = BASE_NETWORK_STATE_TRACKER + 2;
-
- /**
- * msg.what = EVENT_NETWORK_SUBTYPE_CHANGED
- * msg.obj = NetworkInfo object
- */
- public static final int EVENT_NETWORK_SUBTYPE_CHANGED = BASE_NETWORK_STATE_TRACKER + 3;
-
- /**
- * msg.what = EVENT_NETWORK_CONNECTED
- * msg.obj = LinkProperties object
- */
- public static final int EVENT_NETWORK_CONNECTED = BASE_NETWORK_STATE_TRACKER + 4;
-
- /**
- * msg.what = EVENT_NETWORK_CONNECTION_DISCONNECTED
- * msg.obj = LinkProperties object, same iface name
- */
- public static final int EVENT_NETWORK_DISCONNECTED = BASE_NETWORK_STATE_TRACKER + 5;
-
- /**
- * -------------------------------------------------------------
- * Control Interface
- * -------------------------------------------------------------
- */
- /**
- * Begin monitoring data connectivity.
- *
- * This is the first method called when this interface is used.
- *
- * @param context is the current Android context
- * @param target is the Hander to which to return the events.
- */
- public void startMonitoring(Context context, Handler target);
-
- /**
- * Fetch NetworkInfo for the network
- */
- public NetworkInfo getNetworkInfo();
-
- /**
- * Return the LinkProperties for the connection.
- *
- * @return a copy of the LinkProperties, is never null.
- */
- public LinkProperties getLinkProperties();
-
- /**
- * @return a copy of this connections capabilities, may be empty but never null.
- */
- public NetworkCapabilities getNetworkCapabilities();
-
- /**
- * Get interesting information about this network link
- * @return a copy of link information, null if not available
- */
- public LinkQualityInfo getLinkQualityInfo();
-
- /**
- * Return the system properties name associated with the tcp buffer sizes
- * for this network.
- */
- public String getTcpBufferSizesPropName();
-
- /**
- * Disable connectivity to a network
- * @return {@code true} if a teardown occurred, {@code false} if the
- * teardown did not occur.
- */
- public boolean teardown();
-
- /**
- * Reenable connectivity to a network after a {@link #teardown()}.
- * @return {@code true} if we're connected or expect to be connected
- */
- public boolean reconnect();
-
- /**
- * Captive portal check has completed
- */
- public void captivePortalCheckCompleted(boolean isCaptive);
-
- /**
- * Turn the wireless radio off for a network.
- * @param turnOn {@code true} to turn the radio on, {@code false}
- */
- public boolean setRadio(boolean turnOn);
-
- /**
- * Returns an indication of whether this network is available for
- * connections. A value of {@code false} means that some quasi-permanent
- * condition prevents connectivity to this network.
- *
- * NOTE that this is broken on multi-connection devices. Should be fixed in J release
- * TODO - fix on multi-pdp devices
- */
- public boolean isAvailable();
-
- /**
- * User control of data connection through this network, typically persisted
- * internally.
- */
- public void setUserDataEnable(boolean enabled);
-
- /**
- * Policy control of data connection through this network, typically not
- * persisted internally. Usually used when {@link NetworkPolicy#limitBytes}
- * is passed.
- */
- public void setPolicyDataEnable(boolean enabled);
-
- /**
- * -------------------------------------------------------------
- * Storage API used by ConnectivityService for saving
- * Network specific information.
- * -------------------------------------------------------------
- */
-
- /**
- * Check if private DNS route is set for the network
- */
- public boolean isPrivateDnsRouteSet();
-
- /**
- * Set a flag indicating private DNS route is set
- */
- public void privateDnsRouteSet(boolean enabled);
-
- /**
- * Check if default route is set
- */
- public boolean isDefaultRouteSet();
-
- /**
- * Set a flag indicating default route is set for the network
- */
- public void defaultRouteSet(boolean enabled);
-
- /**
- * Check if tear down was requested
- */
- public boolean isTeardownRequested();
-
- /**
- * Indicate tear down requested from connectivity
- */
- public void setTeardownRequested(boolean isRequested);
-
- /**
- * An external dependency has been met/unmet
- */
- public void setDependencyMet(boolean met);
-
- /*
- * Called once to setup async channel between this and
- * the underlying network specific code.
- */
- public void supplyMessenger(Messenger messenger);
-
- /*
- * Network interface name that we'll lookup for sampling data
- */
- public String getNetworkInterfaceName();
-
- /*
- * Save the starting sample
- */
- public void startSampling(SamplingDataTracker.SamplingSnapshot s);
-
- /*
- * Save the ending sample
- */
- public void stopSampling(SamplingDataTracker.SamplingSnapshot s);
-
- /*
- * Record the current netId
- */
- public void setNetId(int netId);
-
- /*
- * ?
- */
- public Network getNetwork();
-
-}
diff --git a/core/java/android/net/NetworkUtils.java b/core/java/android/net/NetworkUtils.java
index d2a2997..02fbe73 100644
--- a/core/java/android/net/NetworkUtils.java
+++ b/core/java/android/net/NetworkUtils.java
@@ -16,9 +16,11 @@
package android.net;
+import java.io.FileDescriptor;
import java.net.InetAddress;
import java.net.Inet4Address;
import java.net.Inet6Address;
+import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.Collection;
import java.util.Locale;
@@ -56,6 +58,30 @@
/**
* Start the DHCP client daemon, in order to have it request addresses
+ * for the named interface. This returns {@code true} if the DHCPv4 daemon
+ * starts, {@code false} otherwise. This call blocks until such time as a
+ * result is available or the default discovery timeout has been reached.
+ * Callers should check {@link #getDhcpResults} to determine whether DHCP
+ * succeeded or failed, and if it succeeded, to fetch the {@link DhcpResults}.
+ * @param interfaceName the name of the interface to configure
+ * @return {@code true} for success, {@code false} for failure
+ */
+ public native static boolean startDhcp(String interfaceName);
+
+ /**
+ * Initiate renewal on the DHCP client daemon for the named interface. This
+ * returns {@code true} if the DHCPv4 daemon has been notified, {@code false}
+ * otherwise. This call blocks until such time as a result is available or
+ * the default renew timeout has been reached. Callers should check
+ * {@link #getDhcpResults} to determine whether DHCP succeeded or failed,
+ * and if it succeeded, to fetch the {@link DhcpResults}.
+ * @param interfaceName the name of the interface to configure
+ * @return {@code true} for success, {@code false} for failure
+ */
+ public native static boolean startDhcpRenew(String interfaceName);
+
+ /**
+ * Start the DHCP client daemon, in order to have it request addresses
* for the named interface, and then configure the interface with those
* addresses. This call blocks until it obtains a result (either success
* or failure) from the daemon.
@@ -64,17 +90,31 @@
* the IP address information.
* @return {@code true} for success, {@code false} for failure
*/
- public native static boolean runDhcp(String interfaceName, DhcpResults dhcpResults);
+ public static boolean runDhcp(String interfaceName, DhcpResults dhcpResults) {
+ return startDhcp(interfaceName) && getDhcpResults(interfaceName, dhcpResults);
+ }
/**
- * Initiate renewal on the Dhcp client daemon. This call blocks until it obtains
+ * Initiate renewal on the DHCP client daemon. This call blocks until it obtains
* a result (either success or failure) from the daemon.
* @param interfaceName the name of the interface to configure
* @param dhcpResults if the request succeeds, this object is filled in with
* the IP address information.
* @return {@code true} for success, {@code false} for failure
*/
- public native static boolean runDhcpRenew(String interfaceName, DhcpResults dhcpResults);
+ public static boolean runDhcpRenew(String interfaceName, DhcpResults dhcpResults) {
+ return startDhcpRenew(interfaceName) && getDhcpResults(interfaceName, dhcpResults);
+ }
+
+ /**
+ * Fetch results from the DHCP client daemon. This call returns {@code true} if
+ * if there are results available to be read, {@code false} otherwise.
+ * @param interfaceName the name of the interface to configure
+ * @param dhcpResults if the request succeeds, this object is filled in with
+ * the IP address information.
+ * @return {@code true} for success, {@code false} for failure
+ */
+ public native static boolean getDhcpResults(String interfaceName, DhcpResults dhcpResults);
/**
* Shut down the DHCP client daemon.
@@ -101,6 +141,11 @@
public native static String getDhcpError();
/**
+ * Attaches a socket filter that accepts DHCP packets to the given socket.
+ */
+ public native static void attachDhcpFilter(FileDescriptor fd) throws SocketException;
+
+ /**
* Binds the current process to the network designated by {@code netId}. All sockets created
* in the future (and not explicitly bound via a bound {@link SocketFactory} (see
* {@link Network#getSocketFactory}) will be bound to this network. Note that if this
@@ -133,6 +178,15 @@
public native static int bindSocketToNetwork(int socketfd, int netId);
/**
+ * Protect {@code fd} from VPN connections. After protecting, data sent through
+ * this socket will go directly to the underlying network, so its traffic will not be
+ * forwarded through the VPN.
+ */
+ public static boolean protectFromVpn(FileDescriptor fd) {
+ return protectFromVpn(fd.getInt$());
+ }
+
+ /**
* Protect {@code socketfd} from VPN connections. After protecting, data sent through
* this socket will go directly to the underlying network, so its traffic will not be
* forwarded through the VPN.
@@ -192,6 +246,25 @@
}
/**
+ * Convert an IPv4 netmask to a prefix length, checking that the netmask is contiguous.
+ * @param netmask as a {@code Inet4Address}.
+ * @return the network prefix length
+ * @throws IllegalArgumentException the specified netmask was not contiguous.
+ * @hide
+ */
+ public static int netmaskToPrefixLength(Inet4Address netmask) {
+ // inetAddressToInt returns an int in *network* byte order.
+ int i = Integer.reverseBytes(inetAddressToInt(netmask));
+ int prefixLength = Integer.bitCount(i);
+ int trailingZeros = Integer.numberOfTrailingZeros(i);
+ if (trailingZeros != 32 - prefixLength) {
+ throw new IllegalArgumentException("Non-contiguous netmask: " + Integer.toHexString(i));
+ }
+ return prefixLength;
+ }
+
+
+ /**
* Create an InetAddress from a string where the string must be a standard
* representation of a V4 or V6 address. Avoids doing a DNS lookup on failure
* but it will throw an IllegalArgumentException in that case.
@@ -271,6 +344,22 @@
}
/**
+ * Returns the implicit netmask of an IPv4 address, as was the custom before 1993.
+ */
+ public static int getImplicitNetmask(Inet4Address address) {
+ int firstByte = address.getAddress()[0] & 0xff; // Convert to an unsigned value.
+ if (firstByte < 128) {
+ return 8;
+ } else if (firstByte < 192) {
+ return 16;
+ } else if (firstByte < 224) {
+ return 24;
+ } else {
+ return 32; // Will likely not end well for other reasons.
+ }
+ }
+
+ /**
* Utility method to parse strings such as "192.0.2.5/24" or "2001:db8::cafe:d00d/64".
* @hide
*/
diff --git a/core/java/android/net/ProxyDataTracker.java b/core/java/android/net/ProxyDataTracker.java
deleted file mode 100644
index 7d23125..0000000
--- a/core/java/android/net/ProxyDataTracker.java
+++ /dev/null
@@ -1,207 +0,0 @@
-/*
- * Copyright (C) 2014 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;
-
-import android.content.BroadcastReceiver;
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.content.ServiceConnection;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.IBinder;
-import android.os.Message;
-import android.os.Messenger;
-import android.os.RemoteException;
-import android.os.UserHandle;
-import android.util.Log;
-
-import java.net.InetAddress;
-import java.net.UnknownHostException;
-import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.concurrent.atomic.AtomicInteger;
-
-/**
- * A data tracker responsible for bringing up and tearing down the system proxy server.
- *
- * {@hide}
- */
-public class ProxyDataTracker extends BaseNetworkStateTracker {
- private static final String TAG = "ProxyDataTracker";
- private static final String NETWORK_TYPE = "PROXY";
-
- // TODO: investigate how to get these DNS addresses from the system.
- private static final String DNS1 = "8.8.8.8";
- private static final String DNS2 = "8.8.4.4";
- private static final String INTERFACE_NAME = "ifb0";
- private static final String REASON_ENABLED = "enabled";
- private static final String REASON_DISABLED = "disabled";
- private static final String REASON_PROXY_DOWN = "proxy_down";
-
- private static final int MSG_TEAR_DOWN_REQUEST = 1;
- private static final int MSG_SETUP_REQUEST = 2;
-
- private static final String PERMISSION_PROXY_STATUS_SENDER =
- "android.permission.ACCESS_NETWORK_CONDITIONS";
- private static final String ACTION_PROXY_STATUS_CHANGE =
- "com.android.net.PROXY_STATUS_CHANGE";
- private static final String KEY_IS_PROXY_AVAILABLE = "is_proxy_available";
- private static final String KEY_REPLY_TO_MESSENGER_BINDER = "reply_to_messenger_binder";
- private static final String KEY_REPLY_TO_MESSENGER_BINDER_BUNDLE =
- "reply_to_messenger_binder_bundle";
-
- private Handler mTarget;
- private Messenger mProxyStatusService;
- private AtomicBoolean mReconnectRequested = new AtomicBoolean(false);
- private AtomicBoolean mIsProxyAvailable = new AtomicBoolean(false);
- private final AtomicInteger mDefaultGatewayAddr = new AtomicInteger(0);
-
- private final BroadcastReceiver mProxyStatusServiceListener = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- if (intent.getAction().equals(ACTION_PROXY_STATUS_CHANGE)) {
- mIsProxyAvailable.set(intent.getBooleanExtra(KEY_IS_PROXY_AVAILABLE, false));
- if (mIsProxyAvailable.get()) {
- Bundle bundle = intent.getBundleExtra(KEY_REPLY_TO_MESSENGER_BINDER_BUNDLE);
- if (bundle == null || bundle.getBinder(KEY_REPLY_TO_MESSENGER_BINDER) == null) {
- Log.e(TAG, "no messenger binder in the intent to send future requests");
- mIsProxyAvailable.set(false);
- return;
- }
- mProxyStatusService =
- new Messenger(bundle.getBinder(KEY_REPLY_TO_MESSENGER_BINDER));
- // If there is a pending reconnect request, do it now.
- if (mReconnectRequested.get()) {
- reconnect();
- }
- } else {
- setDetailedState(NetworkInfo.DetailedState.DISCONNECTED,
- REASON_PROXY_DOWN, null);
- }
- } else {
- Log.d(TAG, "Unrecognized broadcast intent");
- }
- }
- };
-
- /**
- * Create a new ProxyDataTracker
- */
- public ProxyDataTracker() {
- mNetworkInfo = new NetworkInfo(ConnectivityManager.TYPE_PROXY, 0, NETWORK_TYPE, "");
- mLinkProperties = new LinkProperties();
- mNetworkCapabilities = new NetworkCapabilities();
- mNetworkInfo.setIsAvailable(true);
- try {
- mLinkProperties.addDnsServer(InetAddress.getByName(DNS1));
- mLinkProperties.addDnsServer(InetAddress.getByName(DNS2));
- mLinkProperties.setInterfaceName(INTERFACE_NAME);
- } catch (UnknownHostException e) {
- Log.e(TAG, "Could not add DNS address", e);
- }
- }
-
- @Override
- public Object clone() throws CloneNotSupportedException {
- throw new CloneNotSupportedException();
- }
-
- @Override
- public void startMonitoring(Context context, Handler target) {
- mContext = context;
- mTarget = target;
- mContext.registerReceiver(mProxyStatusServiceListener,
- new IntentFilter(ACTION_PROXY_STATUS_CHANGE),
- PERMISSION_PROXY_STATUS_SENDER,
- null);
- }
-
- /**
- * Disable connectivity to the network.
- */
- public boolean teardown() {
- setTeardownRequested(true);
- mReconnectRequested.set(false);
- try {
- if (mIsProxyAvailable.get() && mProxyStatusService != null) {
- mProxyStatusService.send(Message.obtain(null, MSG_TEAR_DOWN_REQUEST));
- }
- } catch (RemoteException e) {
- Log.e(TAG, "Unable to connect to proxy status service", e);
- return false;
- }
- setDetailedState(NetworkInfo.DetailedState.DISCONNECTED, REASON_DISABLED, null);
- return true;
- }
-
- /**
- * Re-enable proxy data connectivity after a {@link #teardown()}.
- */
- public boolean reconnect() {
- mReconnectRequested.set(true);
- setTeardownRequested(false);
- if (!mIsProxyAvailable.get()) {
- Log.w(TAG, "Reconnect requested even though proxy service is not up. Bailing.");
- return false;
- }
- setDetailedState(NetworkInfo.DetailedState.CONNECTING, REASON_ENABLED, null);
-
- try {
- mProxyStatusService.send(Message.obtain(null, MSG_SETUP_REQUEST));
- } catch (RemoteException e) {
- Log.e(TAG, "Unable to connect to proxy status service", e);
- setDetailedState(NetworkInfo.DetailedState.DISCONNECTED, REASON_PROXY_DOWN, null);
- return false;
- }
- // We'll assume proxy is set up successfully. If not, a status change broadcast will be
- // received afterwards to indicate any failure.
- setDetailedState(NetworkInfo.DetailedState.CONNECTED, REASON_ENABLED, null);
- return true;
- }
-
- /**
- * Fetch default gateway address for the network
- */
- public int getDefaultGatewayAddr() {
- return mDefaultGatewayAddr.get();
- }
-
- /**
- * Return the system properties name associated with the tcp buffer sizes
- * for this network.
- */
- public String getTcpBufferSizesPropName() {
- return "net.tcp.buffersize.wifi";
- }
-
- /**
- * Record the detailed state of a network, and if it is a
- * change from the previous state, send a notification to
- * any listeners.
- * @param state the new @{code DetailedState}
- * @param reason a {@code String} indicating a reason for the state change,
- * if one was supplied. May be {@code null}.
- * @param extraInfo optional {@code String} providing extra information about the state change
- */
- private void setDetailedState(NetworkInfo.DetailedState state, String reason,
- String extraInfo) {
- mNetworkInfo.setDetailedState(state, reason, extraInfo);
- Message msg = mTarget.obtainMessage(EVENT_STATE_CHANGED, mNetworkInfo);
- msg.sendToTarget();
- }
-}
diff --git a/core/java/android/net/SamplingDataTracker.java b/core/java/android/net/SamplingDataTracker.java
deleted file mode 100644
index acd56f2..0000000
--- a/core/java/android/net/SamplingDataTracker.java
+++ /dev/null
@@ -1,300 +0,0 @@
-/*
- * Copyright (C) 2013 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;
-
-
-import android.os.SystemClock;
-import android.util.Slog;
-
-import java.io.BufferedReader;
-import java.io.FileNotFoundException;
-import java.io.FileReader;
-import java.io.IOException;
-import java.util.Iterator;
-import java.util.Map;
-
-/**
- * @hide
- */
-public class SamplingDataTracker
-{
- private static final boolean DBG = false;
- private static final String TAG = "SamplingDataTracker";
-
- public static class SamplingSnapshot
- {
- public long mTxByteCount;
- public long mRxByteCount;
- public long mTxPacketCount;
- public long mRxPacketCount;
- public long mTxPacketErrorCount;
- public long mRxPacketErrorCount;
- public long mTimestamp;
- }
-
- public static void getSamplingSnapshots(Map<String, SamplingSnapshot> mapIfaceToSample) {
-
- BufferedReader reader = null;
- try {
- reader = new BufferedReader(new FileReader("/proc/net/dev"));
-
- // Skip over the line bearing column titles (there are 2 lines)
- String line;
- reader.readLine();
- reader.readLine();
-
- while ((line = reader.readLine()) != null) {
-
- // remove leading whitespace
- line = line.trim();
-
- String[] tokens = line.split("[ ]+");
- if (tokens.length < 17) {
- continue;
- }
-
- /* column format is
- * Interface (Recv)bytes packets errs drop fifo frame compressed multicast \
- * (Transmit)bytes packets errs drop fifo colls carrier compress
- */
-
- String currentIface = tokens[0].split(":")[0];
- if (DBG) Slog.d(TAG, "Found data for interface " + currentIface);
- if (mapIfaceToSample.containsKey(currentIface)) {
-
- try {
- SamplingSnapshot ss = new SamplingSnapshot();
-
- ss.mTxByteCount = Long.parseLong(tokens[1]);
- ss.mTxPacketCount = Long.parseLong(tokens[2]);
- ss.mTxPacketErrorCount = Long.parseLong(tokens[3]);
- ss.mRxByteCount = Long.parseLong(tokens[9]);
- ss.mRxPacketCount = Long.parseLong(tokens[10]);
- ss.mRxPacketErrorCount = Long.parseLong(tokens[11]);
-
- ss.mTimestamp = SystemClock.elapsedRealtime();
-
- if (DBG) {
- Slog.d(TAG, "Interface = " + currentIface);
- Slog.d(TAG, "ByteCount = " + String.valueOf(ss.mTxByteCount));
- Slog.d(TAG, "TxPacketCount = " + String.valueOf(ss.mTxPacketCount));
- Slog.d(TAG, "TxPacketErrorCount = "
- + String.valueOf(ss.mTxPacketErrorCount));
- Slog.d(TAG, "RxByteCount = " + String.valueOf(ss.mRxByteCount));
- Slog.d(TAG, "RxPacketCount = " + String.valueOf(ss.mRxPacketCount));
- Slog.d(TAG, "RxPacketErrorCount = "
- + String.valueOf(ss.mRxPacketErrorCount));
- Slog.d(TAG, "Timestamp = " + String.valueOf(ss.mTimestamp));
- Slog.d(TAG, "---------------------------");
- }
-
- mapIfaceToSample.put(currentIface, ss);
-
- } catch (NumberFormatException e) {
- // just ignore this data point
- }
- }
- }
-
- if (DBG) {
- Iterator it = mapIfaceToSample.entrySet().iterator();
- while (it.hasNext()) {
- Map.Entry kvpair = (Map.Entry)it.next();
- if (kvpair.getValue() == null) {
- Slog.d(TAG, "could not find snapshot for interface " + kvpair.getKey());
- }
- }
- }
- } catch(FileNotFoundException e) {
- Slog.e(TAG, "could not find /proc/net/dev");
- } catch (IOException e) {
- Slog.e(TAG, "could not read /proc/net/dev");
- } finally {
- try {
- if (reader != null) {
- reader.close();
- }
- } catch (IOException e) {
- Slog.e(TAG, "could not close /proc/net/dev");
- }
- }
- }
-
- // Snapshots from previous sampling interval
- private SamplingSnapshot mBeginningSample;
- private SamplingSnapshot mEndingSample;
-
- // Starting snapshot of current interval
- private SamplingSnapshot mLastSample;
-
- // Protects sampling data from concurrent access
- public final Object mSamplingDataLock = new Object();
-
- // We need long enough time for a good sample
- private final int MINIMUM_SAMPLING_INTERVAL = 15 * 1000;
-
- // statistics is useless unless we have enough data
- private final int MINIMUM_SAMPLED_PACKETS = 30;
-
- public void startSampling(SamplingSnapshot s) {
- synchronized(mSamplingDataLock) {
- mLastSample = s;
- }
- }
-
- public void stopSampling(SamplingSnapshot s) {
- synchronized(mSamplingDataLock) {
- if (mLastSample != null) {
- if (s.mTimestamp - mLastSample.mTimestamp > MINIMUM_SAMPLING_INTERVAL
- && getSampledPacketCount(mLastSample, s) > MINIMUM_SAMPLED_PACKETS) {
- mBeginningSample = mLastSample;
- mEndingSample = s;
- mLastSample = null;
- } else {
- if (DBG) Slog.d(TAG, "Throwing current sample away because it is too small");
- }
- }
- }
- }
-
- public void resetSamplingData() {
- if (DBG) Slog.d(TAG, "Resetting sampled network data");
- synchronized(mSamplingDataLock) {
-
- // We could just take another sample here and treat it as an
- // 'ending sample' effectively shortening sampling interval, but that
- // requires extra work (specifically, reading the sample needs to be
- // done asynchronously)
-
- mLastSample = null;
- }
- }
-
- public long getSampledTxByteCount() {
- synchronized(mSamplingDataLock) {
- if (mBeginningSample != null && mEndingSample != null) {
- return mEndingSample.mTxByteCount - mBeginningSample.mTxByteCount;
- } else {
- return LinkQualityInfo.UNKNOWN_LONG;
- }
- }
- }
-
- public long getSampledTxPacketCount() {
- synchronized(mSamplingDataLock) {
- if (mBeginningSample != null && mEndingSample != null) {
- return mEndingSample.mTxPacketCount - mBeginningSample.mTxPacketCount;
- } else {
- return LinkQualityInfo.UNKNOWN_LONG;
- }
- }
- }
-
- public long getSampledTxPacketErrorCount() {
- synchronized(mSamplingDataLock) {
- if (mBeginningSample != null && mEndingSample != null) {
- return mEndingSample.mTxPacketErrorCount - mBeginningSample.mTxPacketErrorCount;
- } else {
- return LinkQualityInfo.UNKNOWN_LONG;
- }
- }
- }
-
- public long getSampledRxByteCount() {
- synchronized(mSamplingDataLock) {
- if (mBeginningSample != null && mEndingSample != null) {
- return mEndingSample.mRxByteCount - mBeginningSample.mRxByteCount;
- } else {
- return LinkQualityInfo.UNKNOWN_LONG;
- }
- }
- }
-
- public long getSampledRxPacketCount() {
- synchronized(mSamplingDataLock) {
- if (mBeginningSample != null && mEndingSample != null) {
- return mEndingSample.mRxPacketCount - mBeginningSample.mRxPacketCount;
- } else {
- return LinkQualityInfo.UNKNOWN_LONG;
- }
- }
- }
-
- public long getSampledPacketCount() {
- return getSampledPacketCount(mBeginningSample, mEndingSample);
- }
-
- public long getSampledPacketCount(SamplingSnapshot begin, SamplingSnapshot end) {
- if (begin != null && end != null) {
- long rxPacketCount = end.mRxPacketCount - begin.mRxPacketCount;
- long txPacketCount = end.mTxPacketCount - begin.mTxPacketCount;
- return rxPacketCount + txPacketCount;
- } else {
- return LinkQualityInfo.UNKNOWN_LONG;
- }
- }
-
- public long getSampledPacketErrorCount() {
- if (mBeginningSample != null && mEndingSample != null) {
- long rxPacketErrorCount = getSampledRxPacketErrorCount();
- long txPacketErrorCount = getSampledTxPacketErrorCount();
- return rxPacketErrorCount + txPacketErrorCount;
- } else {
- return LinkQualityInfo.UNKNOWN_LONG;
- }
- }
-
- public long getSampledRxPacketErrorCount() {
- synchronized(mSamplingDataLock) {
- if (mBeginningSample != null && mEndingSample != null) {
- return mEndingSample.mRxPacketErrorCount - mBeginningSample.mRxPacketErrorCount;
- } else {
- return LinkQualityInfo.UNKNOWN_LONG;
- }
- }
- }
-
- public long getSampleTimestamp() {
- synchronized(mSamplingDataLock) {
- if (mEndingSample != null) {
- return mEndingSample.mTimestamp;
- } else {
- return LinkQualityInfo.UNKNOWN_LONG;
- }
- }
- }
-
- public int getSampleDuration() {
- synchronized(mSamplingDataLock) {
- if (mBeginningSample != null && mEndingSample != null) {
- return (int) (mEndingSample.mTimestamp - mBeginningSample.mTimestamp);
- } else {
- return LinkQualityInfo.UNKNOWN_INT;
- }
- }
- }
-
- public void setCommonLinkQualityInfoFields(LinkQualityInfo li) {
- synchronized(mSamplingDataLock) {
- li.setLastDataSampleTime(getSampleTimestamp());
- li.setDataSampleDuration(getSampleDuration());
- li.setPacketCount(getSampledPacketCount());
- li.setPacketErrorCount(getSampledPacketErrorCount());
- }
- }
-}
-
diff --git a/core/java/android/net/dhcp/DhcpStateMachine.java b/core/java/android/net/dhcp/DhcpStateMachine.java
deleted file mode 100644
index bc9a798..0000000
--- a/core/java/android/net/dhcp/DhcpStateMachine.java
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Copyright (C) 2010 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.dhcp;
-
-import java.net.InetAddress;
-import java.util.List;
-
-/**
- * This class defines the "next steps" which occur after a given DHCP
- * packet has been received.
- */
-interface DhcpStateMachine {
- /**
- * Signals that an offer packet has been received with the specified
- * parameters.
- */
- public void onOfferReceived(boolean broadcast, int transactionId,
- byte[] myMac, InetAddress offeredIpAddress,
- InetAddress serverIpAddress);
-
- /**
- * Signals that a NAK packet has been received.
- */
- public void onNakReceived();
-
- /**
- * Signals that the final ACK has been received from the server.
- */
- public void onAckReceived(InetAddress myIpAddress, InetAddress myNetMask,
- InetAddress myGateway, List<InetAddress> myDnsServers,
- InetAddress myDhcpServer, int leaseTime);
-
- /**
- * Signals that a client's DISCOVER packet has been received with the
- * specified parameters.
- */
- public void onDiscoverReceived(boolean broadcast, int transactionId,
- byte[] clientMac, byte[] requestedParameterList);
-
- /**
- * Signals that a client's REQUEST packet has been received with the
- * specified parameters.
- */
- public void onRequestReceived(boolean broadcast, int transactionId,
- byte[] clientMac, InetAddress requestedIp, byte[] requestedParams,
- String clientHostName);
-
- /**
- * Signals that a client's INFORM packet has been received with the
- * specified parameters.
- */
- public void onInformReceived(int transactionId, byte[] clientMac,
- InetAddress preassignedIp, byte[] requestedParams);
-
- /**
- * Signals that a client's DECLINE packet has been received with the
- * specified parameters.
- */
- public void onDeclineReceived(byte[] clientMac, InetAddress declinedIp);
-}
diff --git a/core/java/android/provider/CallLog.java b/core/java/android/provider/CallLog.java
index f023df7..2df9dbf 100644
--- a/core/java/android/provider/CallLog.java
+++ b/core/java/android/provider/CallLog.java
@@ -33,9 +33,12 @@
import android.provider.ContactsContract.CommonDataKinds.Phone;
import android.provider.ContactsContract.Data;
import android.provider.ContactsContract.DataUsageFeedback;
+import android.telecom.PhoneAccount;
import android.telecom.PhoneAccountHandle;
+import android.telecom.TelecomManager;
import android.telephony.PhoneNumberUtils;
import android.text.TextUtils;
+import android.util.Log;
import com.android.internal.telephony.CallerInfo;
import com.android.internal.telephony.PhoneConstants;
@@ -46,6 +49,8 @@
* The CallLog provider contains information about placed and received calls.
*/
public class CallLog {
+ private static final String LOG_TAG = "CallLog";
+
public static final String AUTHORITY = "call_log";
/**
@@ -336,24 +341,44 @@
// that was encoded into call log databases.
/**
- * The component name of the account in string form.
+ * The component name of the account used to place or receive the call; in string form.
* <P>Type: TEXT</P>
*/
public static final String PHONE_ACCOUNT_COMPONENT_NAME = "subscription_component_name";
/**
- * The identifier of a account that is unique to a specified component.
+ * The identifier for the account used to place or receive the call.
* <P>Type: TEXT</P>
*/
public static final String PHONE_ACCOUNT_ID = "subscription_id";
/**
- * The identifier of a account that is unique to a specified component. Equivalent value
- * to {@link #PHONE_ACCOUNT_ID}. For ContactsProvider internal use only.
+ * The address associated with the account used to place or receive the call; in string
+ * form. For SIM-based calls, this is the user's own phone number.
+ * <P>Type: TEXT</P>
+ *
+ * @hide
+ */
+ public static final String PHONE_ACCOUNT_ADDRESS = "phone_account_address";
+
+ /**
+ * Indicates that the entry will be hidden from all queries until the associated
+ * {@link android.telecom.PhoneAccount} is registered with the system.
* <P>Type: INTEGER</P>
*
* @hide
*/
+ public static final String PHONE_ACCOUNT_HIDDEN = "phone_account_hidden";
+
+ /**
+ * The subscription ID used to place this call. This is no longer used and has been
+ * replaced with PHONE_ACCOUNT_COMPONENT_NAME/PHONE_ACCOUNT_ID.
+ * For ContactsProvider internal use only.
+ * <P>Type: INTEGER</P>
+ *
+ * @Deprecated
+ * @hide
+ */
public static final String SUB_ID = "sub_id";
/**
@@ -421,6 +446,29 @@
long start, int duration, Long dataUsage, boolean addForAllUsers) {
final ContentResolver resolver = context.getContentResolver();
int numberPresentation = PRESENTATION_ALLOWED;
+ boolean isHidden = false;
+
+ TelecomManager tm = null;
+ try {
+ tm = TelecomManager.from(context);
+ } catch (UnsupportedOperationException e) {}
+
+ String accountAddress = null;
+ if (tm != null && accountHandle != null) {
+ PhoneAccount account = tm.getPhoneAccount(accountHandle);
+ if (account != null) {
+ Uri address = account.getSubscriptionAddress();
+ if (address != null) {
+ accountAddress = address.getSchemeSpecificPart();
+ }
+ } else {
+ // We could not find the account through telecom. For call log entries that
+ // are added with a phone account which is not registered, we automatically
+ // mark them as hidden. They are unhidden once the account is registered.
+ Log.i(LOG_TAG, "Marking call log entry as hidden.");
+ isHidden = true;
+ }
+ }
// Remap network specified number presentation types
// PhoneConstants.PRESENTATION_xxx to calllog number presentation types
@@ -463,6 +511,8 @@
}
values.put(PHONE_ACCOUNT_COMPONENT_NAME, accountComponentString);
values.put(PHONE_ACCOUNT_ID, accountId);
+ values.put(PHONE_ACCOUNT_ADDRESS, accountAddress);
+ values.put(PHONE_ACCOUNT_HIDDEN, Integer.valueOf(isHidden ? 1 : 0));
values.put(NEW, Integer.valueOf(1));
if (callType == MISSED_TYPE) {
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index d773d4a..2647247 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -5436,6 +5436,14 @@
"hdmi_control_auto_device_off_enabled";
/**
+ * Whether to use the DHCP client from Lollipop and earlier instead of the newer Android DHCP
+ * client.
+ * (0 = false, 1 = true)
+ * @hide
+ */
+ public static final String LEGACY_DHCP_CLIENT = "legacy_dhcp_client";
+
+ /**
* Whether TV will switch to MHL port when a mobile device is plugged in.
* (0 = false, 1 = true)
* @hide
diff --git a/core/java/android/provider/VoicemailContract.java b/core/java/android/provider/VoicemailContract.java
index d71ad03..0da4fd5 100644
--- a/core/java/android/provider/VoicemailContract.java
+++ b/core/java/android/provider/VoicemailContract.java
@@ -19,10 +19,18 @@
import android.Manifest;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
+import android.content.ContentResolver;
+import android.content.ContentValues;
+import android.content.Context;
import android.content.Intent;
import android.database.ContentObserver;
+import android.database.Cursor;
import android.net.Uri;
import android.provider.CallLog.Calls;
+import android.telecom.PhoneAccountHandle;
+import android.telecom.Voicemail;
+
+import java.util.List;
/**
* The contract between the voicemail provider and applications. Contains
@@ -199,13 +207,100 @@
*/
public static final String _DATA = "_data";
+ // Note: PHONE_ACCOUNT_* constant values are "subscription_*" due to a historic naming
+ // that was encoded into call log databases.
+
+ /**
+ * The component name of the account in string form.
+ * <P>Type: TEXT</P>
+ */
+ public static final String PHONE_ACCOUNT_COMPONENT_NAME = "subscription_component_name";
+
+ /**
+ * The identifier of a account that is unique to a specified component.
+ * <P>Type: TEXT</P>
+ */
+ public static final String PHONE_ACCOUNT_ID = "subscription_id";
+
+ /**
+ * Flag used to indicate that local, unsynced changes are present.
+ * Currently, this is used to indicate that the voicemail was read or deleted.
+ * The value will be 1 if dirty is true, 0 if false.
+ * <P>Type: INTEGER (boolean)</P>
+ */
+ public static final String DIRTY = "dirty";
+
+ /**
+ * Flag used to indicate that the voicemail was deleted but not synced to the server.
+ * A deleted row should be ignored.
+ * The value will be 1 if deleted is true, 0 if false.
+ * <P>Type: INTEGER (boolean)</P>
+ */
+ public static final String DELETED = "deleted";
+
/**
* A convenience method to build voicemail URI specific to a source package by appending
* {@link VoicemailContract#PARAM_KEY_SOURCE_PACKAGE} param to the base URI.
*/
public static Uri buildSourceUri(String packageName) {
return Voicemails.CONTENT_URI.buildUpon()
- .appendQueryParameter(PARAM_KEY_SOURCE_PACKAGE, packageName).build();
+ .appendQueryParameter(PARAM_KEY_SOURCE_PACKAGE, packageName)
+ .build();
+ }
+
+ /**
+ * Inserts a new voicemail into the voicemail content provider.
+ *
+ * @param context The context of the app doing the inserting
+ * @param voicemail Data to be inserted
+ * @return {@link Uri} of the newly inserted {@link Voicemail}
+ */
+ public static Uri insert(Context context, Voicemail voicemail) {
+ ContentResolver contentResolver = context.getContentResolver();
+ ContentValues contentValues = getContentValues(voicemail);
+ return contentResolver.insert(Voicemails.CONTENT_URI, contentValues);
+ }
+
+ /**
+ * Inserts a list of voicemails into the voicemail content provider.
+ *
+ * @param context The context of the app doing the inserting
+ * @param voicemails Data to be inserted
+ * @return the number of voicemails inserted
+ */
+ public static int insert(Context context, List<Voicemail> voicemails) {
+ ContentResolver contentResolver = context.getContentResolver();
+ int count = voicemails.size();
+ for (int i = 0; i < count; i++) {
+ ContentValues contentValues = getContentValues(voicemails.get(i));
+ contentResolver.insert(Voicemails.CONTENT_URI, contentValues);
+ }
+ return count;
+ }
+
+ /**
+ * Clears all voicemails accessible to this voicemail content provider for the calling
+ * package. By default, a package only has permission to delete voicemails it inserted.
+ *
+ * @return the number of voicemails deleted
+ */
+ public static int deleteAll(Context context) {
+ return context.getContentResolver().delete(
+ buildSourceUri(context.getPackageName()), "", new String[0]);
+ }
+
+ /**
+ * Maps structured {@link Voicemail} to {@link ContentValues} in content provider.
+ */
+ private static ContentValues getContentValues(Voicemail voicemail) {
+ ContentValues contentValues = new ContentValues();
+ contentValues.put(Voicemails.DATE, String.valueOf(voicemail.getTimestampMillis()));
+ contentValues.put(Voicemails.NUMBER, voicemail.getNumber());
+ contentValues.put(Voicemails.DURATION, String.valueOf(voicemail.getDuration()));
+ contentValues.put(Voicemails.SOURCE_PACKAGE, voicemail.getSourcePackage());
+ contentValues.put(Voicemails.SOURCE_DATA, voicemail.getSourceData());
+ contentValues.put(Voicemails.IS_READ, voicemail.isRead() ? 1 : 0);
+ return contentValues;
}
}
@@ -222,10 +317,27 @@
private Status() {
}
/**
- * The package name of the voicemail source. There can only be a one entry per source.
+ * The package name of the voicemail source. There can only be a one entry per account
+ * per source.
* <P>Type: TEXT</P>
*/
public static final String SOURCE_PACKAGE = SOURCE_PACKAGE_FIELD;
+
+ // Note: Multiple entries may exist for a single source if they are differentiated by the
+ // PHONE_ACCOUNT_* fields.
+
+ /**
+ * The component name of the account in string form.
+ * <P>Type: TEXT</P>
+ */
+ public static final String PHONE_ACCOUNT_COMPONENT_NAME = "phone_account_component_name";
+
+ /**
+ * The identifier of a account that is unique to a specified component.
+ * <P>Type: TEXT</P>
+ */
+ public static final String PHONE_ACCOUNT_ID = "phone_account_id";
+
/**
* The URI to call to invoke source specific voicemail settings screen. On a user request
* to setup voicemail an intent with action VIEW with this URI will be fired by the system.
@@ -318,5 +430,50 @@
return Status.CONTENT_URI.buildUpon()
.appendQueryParameter(PARAM_KEY_SOURCE_PACKAGE, packageName).build();
}
+
+ /**
+ * A helper method to set the status of a voicemail source.
+ *
+ * @param context The context from the package calling the method. This will be the source.
+ * @param accountHandle The handle for the account the source is associated with.
+ * @param configurationState See {@link Status#CONFIGURATION_STATE}
+ * @param dataChannelState See {@link Status#DATA_CHANNEL_STATE}
+ * @param notificationChannelState See {@link Status#NOTIFICATION_CHANNEL_STATE}
+ */
+ public static void setStatus(Context context, PhoneAccountHandle accountHandle,
+ int configurationState, int dataChannelState, int notificationChannelState) {
+ ContentResolver contentResolver = context.getContentResolver();
+ Uri statusUri = buildSourceUri(context.getPackageName());
+ ContentValues values = new ContentValues();
+ values.put(Status.PHONE_ACCOUNT_COMPONENT_NAME,
+ accountHandle.getComponentName().toString());
+ values.put(Status.PHONE_ACCOUNT_ID, accountHandle.getId());
+ values.put(Status.CONFIGURATION_STATE, configurationState);
+ values.put(Status.DATA_CHANNEL_STATE, dataChannelState);
+ values.put(Status.NOTIFICATION_CHANNEL_STATE, notificationChannelState);
+
+ if (isStatusPresent(contentResolver, statusUri)) {
+ contentResolver.update(statusUri, values, null, null);
+ } else {
+ contentResolver.insert(statusUri, values);
+ }
+ }
+
+ /**
+ * Determines if a voicemail source exists in the status table.
+ *
+ * @param contentResolver A content resolver constructed from the appropriate context.
+ * @param statusUri The content uri for the source.
+ * @return {@code true} if a status entry for this source exists
+ */
+ private static boolean isStatusPresent(ContentResolver contentResolver, Uri statusUri) {
+ Cursor cursor = null;
+ try {
+ cursor = contentResolver.query(statusUri, null, null, null, null);
+ return cursor != null && cursor.getCount() != 0;
+ } finally {
+ if (cursor != null) cursor.close();
+ }
+ }
}
}
diff --git a/core/java/android/view/TextureView.java b/core/java/android/view/TextureView.java
index 59ec058..ad34f02 100644
--- a/core/java/android/view/TextureView.java
+++ b/core/java/android/view/TextureView.java
@@ -723,6 +723,12 @@
mSurface.release();
}
mSurface = surfaceTexture;
+
+ // If the view is visible, update the listener in the new surface to use
+ // the existing listener in the view.
+ if (((mViewFlags & VISIBILITY_MASK) == VISIBLE)) {
+ mSurface.setOnFrameAvailableListener(mUpdateListener, mAttachInfo.mHandler);
+ }
mUpdateSurface = true;
invalidateParentIfNeeded();
}
diff --git a/core/java/com/android/internal/util/Protocol.java b/core/java/com/android/internal/util/Protocol.java
index d9ebc25..a106f48 100644
--- a/core/java/com/android/internal/util/Protocol.java
+++ b/core/java/com/android/internal/util/Protocol.java
@@ -52,6 +52,7 @@
public static final int BASE_WIFI_RTT_SERVICE = 0x00027300;
public static final int BASE_WIFI_PASSPOINT_MANAGER = 0x00028000;
public static final int BASE_WIFI_PASSPOINT_SERVICE = 0x00028100;
+ public static final int BASE_WIFI_LOGGER = 0x00028300;
public static final int BASE_DHCP = 0x00030000;
public static final int BASE_DATA_CONNECTION = 0x00040000;
public static final int BASE_DATA_CONNECTION_AC = 0x00041000;
diff --git a/core/jni/android_net_NetUtils.cpp b/core/jni/android_net_NetUtils.cpp
index 8b9f574..e97d61e 100644
--- a/core/jni/android_net_NetUtils.cpp
+++ b/core/jni/android_net_NetUtils.cpp
@@ -24,6 +24,14 @@
#include <android_runtime/AndroidRuntime.h>
#include <utils/Log.h>
#include <arpa/inet.h>
+#include <net/if.h>
+#include <linux/filter.h>
+#include <linux/if.h>
+#include <linux/if_ether.h>
+#include <linux/if_packet.h>
+#include <net/if_ether.h>
+#include <netinet/ip.h>
+#include <netinet/udp.h>
#include <cutils/properties.h>
extern "C" {
@@ -31,27 +39,18 @@
int ifc_disable(const char *ifname);
int ifc_reset_connections(const char *ifname, int reset_mask);
-int dhcp_do_request(const char * const ifname,
- const char *ipaddr,
- const char *gateway,
- uint32_t *prefixLength,
- const char *dns[],
- const char *server,
- uint32_t *lease,
- const char *vendorInfo,
- const char *domains,
- const char *mtu);
-
-int dhcp_do_request_renew(const char * const ifname,
- const char *ipaddr,
- const char *gateway,
- uint32_t *prefixLength,
- const char *dns[],
- const char *server,
- uint32_t *lease,
- const char *vendorInfo,
- const char *domains,
- const char *mtu);
+int dhcp_start(const char * const ifname);
+int dhcp_start_renew(const char * const ifname);
+int dhcp_get_results(const char * const ifname,
+ const char *ipaddr,
+ const char *gateway,
+ uint32_t *prefixLength,
+ const char *dns[],
+ const char *server,
+ uint32_t *lease,
+ const char *vendorInfo,
+ const char *domains,
+ const char *mtu);
int dhcp_stop(const char *ifname);
int dhcp_release_lease(const char *ifname);
@@ -62,6 +61,8 @@
namespace android {
+static const uint16_t kDhcpClientPort = 68;
+
/*
* The following remembers the jfieldID's of the fields
* of the DhcpInfo Java object, so that we don't have
@@ -93,8 +94,8 @@
return (jint)result;
}
-static jboolean android_net_utils_runDhcpCommon(JNIEnv* env, jobject clazz, jstring ifname,
- jobject dhcpResults, bool renew)
+static jboolean android_net_utils_getDhcpResults(JNIEnv* env, jobject clazz, jstring ifname,
+ jobject dhcpResults)
{
int result;
char ipaddr[PROPERTY_VALUE_MAX];
@@ -114,15 +115,10 @@
const char *nameStr = env->GetStringUTFChars(ifname, NULL);
if (nameStr == NULL) return (jboolean)false;
- if (renew) {
- result = ::dhcp_do_request_renew(nameStr, ipaddr, gateway, &prefixLength,
- dns, server, &lease, vendorInfo, domains, mtu);
- } else {
- result = ::dhcp_do_request(nameStr, ipaddr, gateway, &prefixLength,
- dns, server, &lease, vendorInfo, domains, mtu);
- }
+ result = ::dhcp_get_results(nameStr, ipaddr, gateway, &prefixLength,
+ dns, server, &lease, vendorInfo, domains, mtu);
if (result != 0) {
- ALOGD("dhcp_do_request failed : %s (%s)", nameStr, renew ? "renew" : "new");
+ ALOGD("dhcp_get_results failed : %s (%s)", nameStr, ::dhcp_get_errmsg());
}
env->ReleaseStringUTFChars(ifname, nameStr);
@@ -182,19 +178,28 @@
return (jboolean)(result == 0);
}
-
-static jboolean android_net_utils_runDhcp(JNIEnv* env, jobject clazz, jstring ifname, jobject info)
+static jboolean android_net_utils_startDhcp(JNIEnv* env, jobject clazz, jstring ifname)
{
- return android_net_utils_runDhcpCommon(env, clazz, ifname, info, false);
+ const char *nameStr = env->GetStringUTFChars(ifname, NULL);
+ if (nameStr == NULL) return (jboolean)false;
+ if (::dhcp_start(nameStr) != 0) {
+ ALOGD("dhcp_start failed : %s", nameStr);
+ return (jboolean)false;
+ }
+ return (jboolean)true;
}
-static jboolean android_net_utils_runDhcpRenew(JNIEnv* env, jobject clazz, jstring ifname,
- jobject info)
+static jboolean android_net_utils_startDhcpRenew(JNIEnv* env, jobject clazz, jstring ifname)
{
- return android_net_utils_runDhcpCommon(env, clazz, ifname, info, true);
+ const char *nameStr = env->GetStringUTFChars(ifname, NULL);
+ if (nameStr == NULL) return (jboolean)false;
+ if (::dhcp_start_renew(nameStr) != 0) {
+ ALOGD("dhcp_start_renew failed : %s", nameStr);
+ return (jboolean)false;
+ }
+ return (jboolean)true;
}
-
static jboolean android_net_utils_stopDhcp(JNIEnv* env, jobject clazz, jstring ifname)
{
int result;
@@ -220,6 +225,44 @@
return env->NewStringUTF(::dhcp_get_errmsg());
}
+static void android_net_utils_attachDhcpFilter(JNIEnv *env, jobject clazz, jobject javaFd)
+{
+ int fd = jniGetFDFromFileDescriptor(env, javaFd);
+ uint32_t ip_offset = sizeof(ether_header);
+ uint32_t proto_offset = ip_offset + offsetof(iphdr, protocol);
+ uint32_t flags_offset = ip_offset + offsetof(iphdr, frag_off);
+ uint32_t dport_indirect_offset = ip_offset + offsetof(udphdr, dest);
+ struct sock_filter filter_code[] = {
+ // Check the protocol is UDP.
+ BPF_STMT(BPF_LD | BPF_B | BPF_ABS, proto_offset),
+ BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, IPPROTO_UDP, 0, 6),
+
+ // Check this is not a fragment.
+ BPF_STMT(BPF_LD | BPF_H | BPF_ABS, flags_offset),
+ BPF_JUMP(BPF_JMP | BPF_JSET | BPF_K, 0x1fff, 4, 0),
+
+ // Get the IP header length.
+ BPF_STMT(BPF_LDX | BPF_B | BPF_MSH, ip_offset),
+
+ // Check the destination port.
+ BPF_STMT(BPF_LD | BPF_H | BPF_IND, dport_indirect_offset),
+ BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, kDhcpClientPort, 0, 1),
+
+ // Accept or reject.
+ BPF_STMT(BPF_RET | BPF_K, 0xffff),
+ BPF_STMT(BPF_RET | BPF_K, 0)
+ };
+ struct sock_fprog filter = {
+ sizeof(filter_code) / sizeof(filter_code[0]),
+ filter_code,
+ };
+
+ if (setsockopt(fd, SOL_SOCKET, SO_ATTACH_FILTER, &filter, sizeof(filter)) != 0) {
+ jniThrowExceptionFmt(env, "java/net/SocketException",
+ "setsockopt(SO_ATTACH_FILTER): %s", strerror(errno));
+ }
+}
+
static jboolean android_net_utils_bindProcessToNetwork(JNIEnv *env, jobject thiz, jint netId)
{
return (jboolean) !setNetworkForProcess(netId);
@@ -247,6 +290,7 @@
return (jboolean) !protectFromVpn(socket);
}
+
// ----------------------------------------------------------------------------
/*
@@ -255,8 +299,9 @@
static JNINativeMethod gNetworkUtilMethods[] = {
/* name, signature, funcPtr */
{ "resetConnections", "(Ljava/lang/String;I)I", (void *)android_net_utils_resetConnections },
- { "runDhcp", "(Ljava/lang/String;Landroid/net/DhcpResults;)Z", (void *)android_net_utils_runDhcp },
- { "runDhcpRenew", "(Ljava/lang/String;Landroid/net/DhcpResults;)Z", (void *)android_net_utils_runDhcpRenew },
+ { "startDhcp", "(Ljava/lang/String;)Z", (void *)android_net_utils_startDhcp },
+ { "startDhcpRenew", "(Ljava/lang/String;)Z", (void *)android_net_utils_startDhcpRenew },
+ { "getDhcpResults", "(Ljava/lang/String;Landroid/net/DhcpResults;)Z", (void *)android_net_utils_getDhcpResults },
{ "stopDhcp", "(Ljava/lang/String;)Z", (void *)android_net_utils_stopDhcp },
{ "releaseDhcpLease", "(Ljava/lang/String;)Z", (void *)android_net_utils_releaseDhcpLease },
{ "getDhcpError", "()Ljava/lang/String;", (void*) android_net_utils_getDhcpError },
@@ -265,6 +310,7 @@
{ "bindProcessToNetworkForHostResolution", "(I)Z", (void*) android_net_utils_bindProcessToNetworkForHostResolution },
{ "bindSocketToNetwork", "(II)I", (void*) android_net_utils_bindSocketToNetwork },
{ "protectFromVpn", "(I)Z", (void*)android_net_utils_protectFromVpn },
+ { "attachDhcpFilter", "(Ljava/io/FileDescriptor;)V", (void*) android_net_utils_attachDhcpFilter },
};
int register_android_net_NetworkUtils(JNIEnv* env)
diff --git a/core/jni/android_view_Surface.cpp b/core/jni/android_view_Surface.cpp
index a39ff8e..6b0ce71 100644
--- a/core/jni/android_view_Surface.cpp
+++ b/core/jni/android_view_Surface.cpp
@@ -129,6 +129,100 @@
return surfaceObj;
}
+int android_view_Surface_mapPublicFormatToHalFormat(PublicFormat f) {
+
+ switch(f) {
+ case JPEG:
+ case DEPTH_POINT_CLOUD:
+ return HAL_PIXEL_FORMAT_BLOB;
+ case DEPTH16:
+ return HAL_PIXEL_FORMAT_Y16;
+ case RAW_SENSOR:
+ return HAL_PIXEL_FORMAT_RAW16;
+ default:
+ // Most formats map 1:1
+ return static_cast<int>(f);
+ }
+}
+
+android_dataspace android_view_Surface_mapPublicFormatToHalDataspace(
+ PublicFormat f) {
+ switch(f) {
+ case JPEG:
+ return HAL_DATASPACE_JFIF;
+ case DEPTH_POINT_CLOUD:
+ case DEPTH16:
+ return HAL_DATASPACE_DEPTH;
+ case RAW_SENSOR:
+ case RAW10:
+ return HAL_DATASPACE_ARBITRARY;
+ case YUV_420_888:
+ case NV21:
+ case YV12:
+ return HAL_DATASPACE_JFIF;
+ default:
+ // Most formats map to UNKNOWN
+ return HAL_DATASPACE_UNKNOWN;
+ }
+}
+
+PublicFormat android_view_Surface_mapHalFormatDataspaceToPublicFormat(
+ int format, android_dataspace dataSpace) {
+ switch(format) {
+ case HAL_PIXEL_FORMAT_RGBA_8888:
+ case HAL_PIXEL_FORMAT_RGBX_8888:
+ case HAL_PIXEL_FORMAT_RGB_888:
+ case HAL_PIXEL_FORMAT_RGB_565:
+ case HAL_PIXEL_FORMAT_Y8:
+ case HAL_PIXEL_FORMAT_RAW10:
+ case HAL_PIXEL_FORMAT_YCbCr_420_888:
+ case HAL_PIXEL_FORMAT_YV12:
+ // Enums overlap in both name and value
+ return static_cast<PublicFormat>(format);
+ case HAL_PIXEL_FORMAT_RAW16:
+ // Name differs, though value is the same
+ return RAW_SENSOR;
+ case HAL_PIXEL_FORMAT_YCbCr_422_SP:
+ // Name differs, though the value is the same
+ return NV16;
+ case HAL_PIXEL_FORMAT_YCrCb_420_SP:
+ // Name differs, though the value is the same
+ return NV21;
+ case HAL_PIXEL_FORMAT_YCbCr_422_I:
+ // Name differs, though the value is the same
+ return YUY2;
+ case HAL_PIXEL_FORMAT_Y16:
+ // Dataspace-dependent
+ switch (dataSpace) {
+ case HAL_DATASPACE_DEPTH:
+ return DEPTH16;
+ default:
+ // Assume non-depth Y16 is just Y16.
+ return Y16;
+ }
+ break;
+ case HAL_PIXEL_FORMAT_BLOB:
+ // Dataspace-dependent
+ switch (dataSpace) {
+ case HAL_DATASPACE_DEPTH:
+ return DEPTH_POINT_CLOUD;
+ case HAL_DATASPACE_JFIF:
+ return JPEG;
+ default:
+ // Assume otherwise-marked blobs are also JPEG
+ return JPEG;
+ }
+ break;
+ case HAL_PIXEL_FORMAT_BGRA_8888:
+ case HAL_PIXEL_FORMAT_RAW_OPAQUE:
+ case HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED:
+ // Not defined in public API
+ return UNKNOWN;
+
+ default:
+ return UNKNOWN;
+ }
+}
// ----------------------------------------------------------------------------
static inline bool isSurfaceValid(const sp<Surface>& sur) {
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 3de2268..f1da2f9 100755
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -486,6 +486,18 @@
<!-- Wifi driver supports batched scan -->
<bool translatable="false" name="config_wifi_batched_scan_supported">false</bool>
+ <!-- Idle Receive current for wifi radio. 0 by default-->
+ <integer translatable="false" name="config_wifi_idle_receive_cur_ma">1</integer>
+
+ <!-- Rx current for wifi radio. 0 by default-->
+ <integer translatable="false" name="config_wifi_active_rx_cur_ma">2</integer>
+
+ <!-- Tx current for wifi radio. 0 by default-->
+ <integer translatable="false" name="config_wifi_tx_cur_ma">3</integer>
+
+ <!-- Operating volatage for wifi radio. 0 by default-->
+ <integer translatable="false" name="config_wifi_operating_voltage_mv">4</integer>
+
<!-- Flag indicating whether the we should enable the automatic brightness in Settings.
Software implementation will be used if config_hardware_auto_brightness_available is not set -->
<bool name="config_automatic_brightness_available">false</bool>
@@ -1087,6 +1099,18 @@
device does not support multiple advertisement-->
<integer translatable="false" name="config_bluetooth_max_advertisers">0</integer>
+ <!-- Idle current for bluetooth controller. 0 by default-->
+ <integer translatable="false" name="config_bluetooth_idle_cur_ma">1</integer>
+
+ <!-- Rx current for bluetooth controller. 0 by default-->
+ <integer translatable="false" name="config_bluetooth_rx_cur_ma">2</integer>
+
+ <!-- Tx current for bluetooth controller. 0 by default-->
+ <integer translatable="false" name="config_bluetooth_tx_cur_ma">3</integer>
+
+ <!-- Operating volatage for bluetooth controller. 0 by default-->
+ <integer translatable="false" name="config_bluetooth_operating_voltage_mv">4</integer>
+
<!-- The default data-use polling period. -->
<integer name="config_datause_polling_period_sec">600</integer>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index aaa8323..23ed5ad 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -3840,10 +3840,10 @@
</plurals>
<!-- A notification is shown when a wifi captive portal network is detected. This is the notification's title. -->
- <string name="wifi_available_sign_in">Sign into Wi-Fi network</string>
+ <string name="wifi_available_sign_in">Sign in to Wi-Fi network</string>
<!-- A notification is shown when a captive portal network is detected. This is the notification's title. -->
- <string name="network_available_sign_in">Sign into network</string>
+ <string name="network_available_sign_in">Sign in to network</string>
<!-- A notification is shown when a captive portal network is detected. This is the notification's message. -->
<string name="network_available_sign_in_detailed"><xliff:g id="network_ssid">%1$s</xliff:g></string>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 6a998e4..4bf7735 100755
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -328,6 +328,10 @@
<java-symbol type="integer" name="config_wifi_framework_current_network_boost" />
<java-symbol type="string" name="config_wifi_random_mac_oui" />
<java-symbol type="integer" name="config_wifi_network_switching_blacklist_time" />
+ <java-symbol type="integer" name="config_wifi_idle_receive_cur_ma" />
+ <java-symbol type="integer" name="config_wifi_active_rx_cur_ma" />
+ <java-symbol type="integer" name="config_wifi_tx_cur_ma" />
+ <java-symbol type="integer" name="config_wifi_operating_voltage_mv" />
<java-symbol type="bool" name="editable_voicemailnumber" />
@@ -344,6 +348,10 @@
<java-symbol type="integer" name="config_wifi_framework_current_network_boost" />
<java-symbol type="integer" name="config_bluetooth_max_advertisers" />
<java-symbol type="integer" name="config_bluetooth_max_scan_filters" />
+ <java-symbol type="integer" name="config_bluetooth_idle_cur_ma" />
+ <java-symbol type="integer" name="config_bluetooth_rx_cur_ma" />
+ <java-symbol type="integer" name="config_bluetooth_tx_cur_ma" />
+ <java-symbol type="integer" name="config_bluetooth_operating_voltage_mv" />
<java-symbol type="integer" name="config_cursorWindowSize" />
<java-symbol type="integer" name="config_doublePressOnPowerBehavior" />
<java-symbol type="integer" name="config_extraFreeKbytesAdjust" />
diff --git a/core/tests/coretests/src/android/net/NetworkUtilsTest.java b/core/tests/coretests/src/android/net/NetworkUtilsTest.java
new file mode 100644
index 0000000..8d51c3b
--- /dev/null
+++ b/core/tests/coretests/src/android/net/NetworkUtilsTest.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2015 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;
+
+import android.net.NetworkUtils;
+import android.test.suitebuilder.annotation.SmallTest;
+
+import java.net.Inet4Address;
+import java.net.InetAddress;
+
+import junit.framework.TestCase;
+
+public class NetworkUtilsTest extends TestCase {
+
+ private InetAddress Address(String addr) {
+ return InetAddress.parseNumericAddress(addr);
+ }
+
+ private Inet4Address IPv4Address(String addr) {
+ return (Inet4Address) Address(addr);
+ }
+
+ @SmallTest
+ public void testGetImplicitNetmask() {
+ assertEquals(8, NetworkUtils.getImplicitNetmask(IPv4Address("4.2.2.2")));
+ assertEquals(8, NetworkUtils.getImplicitNetmask(IPv4Address("10.5.6.7")));
+ assertEquals(16, NetworkUtils.getImplicitNetmask(IPv4Address("173.194.72.105")));
+ assertEquals(16, NetworkUtils.getImplicitNetmask(IPv4Address("172.23.68.145")));
+ assertEquals(24, NetworkUtils.getImplicitNetmask(IPv4Address("192.0.2.1")));
+ assertEquals(24, NetworkUtils.getImplicitNetmask(IPv4Address("192.168.5.1")));
+ assertEquals(32, NetworkUtils.getImplicitNetmask(IPv4Address("224.0.0.1")));
+ assertEquals(32, NetworkUtils.getImplicitNetmask(IPv4Address("255.6.7.8")));
+ }
+
+ private void assertInvalidNetworkMask(Inet4Address addr) {
+ try {
+ NetworkUtils.netmaskToPrefixLength(addr);
+ fail("Invalid netmask " + addr.getHostAddress() + " did not cause exception");
+ } catch (IllegalArgumentException expected) {
+ }
+ }
+
+ @SmallTest
+ public void testNetmaskToPrefixLength() {
+ assertEquals(0, NetworkUtils.netmaskToPrefixLength(IPv4Address("0.0.0.0")));
+ assertEquals(9, NetworkUtils.netmaskToPrefixLength(IPv4Address("255.128.0.0")));
+ assertEquals(17, NetworkUtils.netmaskToPrefixLength(IPv4Address("255.255.128.0")));
+ assertEquals(23, NetworkUtils.netmaskToPrefixLength(IPv4Address("255.255.254.0")));
+ assertEquals(31, NetworkUtils.netmaskToPrefixLength(IPv4Address("255.255.255.254")));
+ assertEquals(32, NetworkUtils.netmaskToPrefixLength(IPv4Address("255.255.255.255")));
+
+ assertInvalidNetworkMask(IPv4Address("0.0.0.1"));
+ assertInvalidNetworkMask(IPv4Address("255.255.255.253"));
+ assertInvalidNetworkMask(IPv4Address("255.255.0.255"));
+ }
+}
diff --git a/docs/html/images/camera2/metadata/android.tonemap.curveRed/gamma_tonemap.png b/docs/html/images/camera2/metadata/android.tonemap.curveRed/gamma_tonemap.png
index ec89e37..a02fd89 100644
--- a/docs/html/images/camera2/metadata/android.tonemap.curveRed/gamma_tonemap.png
+++ b/docs/html/images/camera2/metadata/android.tonemap.curveRed/gamma_tonemap.png
Binary files differ
diff --git a/docs/html/images/camera2/metadata/android.tonemap.curveRed/inverse_tonemap.png b/docs/html/images/camera2/metadata/android.tonemap.curveRed/inverse_tonemap.png
index cf0c63d..c309ac5 100644
--- a/docs/html/images/camera2/metadata/android.tonemap.curveRed/inverse_tonemap.png
+++ b/docs/html/images/camera2/metadata/android.tonemap.curveRed/inverse_tonemap.png
Binary files differ
diff --git a/docs/html/images/camera2/metadata/android.tonemap.curveRed/linear_tonemap.png b/docs/html/images/camera2/metadata/android.tonemap.curveRed/linear_tonemap.png
index f226a54..414fad4 100644
--- a/docs/html/images/camera2/metadata/android.tonemap.curveRed/linear_tonemap.png
+++ b/docs/html/images/camera2/metadata/android.tonemap.curveRed/linear_tonemap.png
Binary files differ
diff --git a/docs/html/images/camera2/metadata/android.tonemap.curveRed/rec709_tonemap.png b/docs/html/images/camera2/metadata/android.tonemap.curveRed/rec709_tonemap.png
new file mode 100644
index 0000000..c147a87
--- /dev/null
+++ b/docs/html/images/camera2/metadata/android.tonemap.curveRed/rec709_tonemap.png
Binary files differ
diff --git a/docs/html/images/camera2/metadata/android.tonemap.curveRed/srgb_tonemap.png b/docs/html/images/camera2/metadata/android.tonemap.curveRed/srgb_tonemap.png
index ded0645..4ce2125 100644
--- a/docs/html/images/camera2/metadata/android.tonemap.curveRed/srgb_tonemap.png
+++ b/docs/html/images/camera2/metadata/android.tonemap.curveRed/srgb_tonemap.png
Binary files differ
diff --git a/graphics/java/android/graphics/ImageFormat.java b/graphics/java/android/graphics/ImageFormat.java
index 3efb9c0..49c4247 100644
--- a/graphics/java/android/graphics/ImageFormat.java
+++ b/graphics/java/android/graphics/ImageFormat.java
@@ -356,6 +356,38 @@
public static final int RAW10 = 0x25;
/**
+ * Android dense depth image format.
+ *
+ * Each pixel is 16 bits, representing a depth ranging measurement from
+ * a depth camera or similar sensor.
+ *
+ * <p>This format assumes
+ * <ul>
+ * <li>an even width</li>
+ * <li>an even height</li>
+ * <li>a horizontal stride multiple of 16 pixels</li>
+ * </ul>
+ * </p>
+ *
+ * <pre> y_size = stride * height </pre>
+ *
+ * When produced by a camera, the units are millimeters.
+ */
+ public static final int DEPTH16 = 0x44363159;
+
+ /**
+ * Android sparse depth point cloud format.
+ *
+ * <p>A variable-length list of 3D points, with each point represented
+ * by a triple of floats.</p>
+ *
+ * <p>The number of points is {@code (size of the buffer in bytes) / 12}.
+ *
+ * The coordinate system and units depend on the source of the point cloud data.
+ */
+ public static final int DEPTH_POINT_CLOUD = 0x101;
+
+ /**
* Use this function to retrieve the number of bits per pixel of an
* ImageFormat.
*
@@ -376,6 +408,7 @@
case Y8:
return 8;
case Y16:
+ case DEPTH16:
return 16;
case NV21:
return 12;
@@ -412,6 +445,8 @@
case YUV_420_888:
case RAW_SENSOR:
case RAW10:
+ case DEPTH16:
+ case DEPTH_POINT_CLOUD:
return true;
}
diff --git a/include/android_runtime/android_view_Surface.h b/include/android_runtime/android_view_Surface.h
index 53e8b49..10c75f1 100644
--- a/include/android_runtime/android_view_Surface.h
+++ b/include/android_runtime/android_view_Surface.h
@@ -26,6 +26,33 @@
class Surface;
class IGraphicBufferProducer;
+/**
+ * Enum mirroring the public API definitions for image and pixel formats.
+ * Some of these are hidden in the public API
+ *
+ * Keep up to date with android.graphics.ImageFormat and
+ * android.graphics.PixelFormat
+ */
+enum PublicFormat {
+ UNKNOWN = 0x0,
+ RGBA_8888 = 0x1,
+ RGBX_8888 = 0x2,
+ RGB_888 = 0x3,
+ RGB_565 = 0x4,
+ NV16 = 0x10,
+ NV21 = 0x11,
+ YUY2 = 0x14,
+ RAW_SENSOR = 0x20,
+ YUV_420_888 = 0x23,
+ RAW10 = 0x25,
+ JPEG = 0x100,
+ DEPTH_POINT_CLOUD = 0x101,
+ YV12 = 0x32315659,
+ Y8 = 0x20203859, // @hide
+ Y16 = 0x20363159, // @hide
+ DEPTH16 = 0x44363159
+};
+
/* Gets the underlying ANativeWindow for a Surface. */
extern sp<ANativeWindow> android_view_Surface_getNativeWindow(
JNIEnv* env, jobject surfaceObj);
@@ -40,6 +67,21 @@
extern jobject android_view_Surface_createFromIGraphicBufferProducer(JNIEnv* env,
const sp<IGraphicBufferProducer>& bufferProducer);
+/* Convert from android.graphics.ImageFormat/PixelFormat enums to graphics.h HAL
+ * format */
+extern int android_view_Surface_mapPublicFormatToHalFormat(PublicFormat f);
+
+/* Convert from android.graphics.ImageFormat/PixelFormat enums to graphics.h HAL
+ * dataspace */
+extern android_dataspace android_view_Surface_mapPublicFormatToHalDataspace(
+ PublicFormat f);
+
+/* Convert from HAL format, dataspace pair to
+ * android.graphics.ImageFormat/PixelFormat.
+ * For unknown/unspecified pairs, returns PublicFormat::UNKNOWN */
+extern PublicFormat android_view_Surface_mapHalFormatDataspaceToPublicFormat(
+ int format, android_dataspace dataSpace);
+
} // namespace android
#endif // _ANDROID_VIEW_SURFACE_H
diff --git a/media/java/android/media/ImageReader.java b/media/java/android/media/ImageReader.java
index 8d6a588..824a7ad 100644
--- a/media/java/android/media/ImageReader.java
+++ b/media/java/android/media/ImageReader.java
@@ -483,6 +483,8 @@
case ImageFormat.Y16:
case ImageFormat.RAW_SENSOR:
case ImageFormat.RAW10:
+ case ImageFormat.DEPTH16:
+ case ImageFormat.DEPTH_POINT_CLOUD:
return 1;
default:
throw new UnsupportedOperationException(
diff --git a/media/jni/android_media_ImageReader.cpp b/media/jni/android_media_ImageReader.cpp
index 890b039..57a7b2c 100644
--- a/media/jni/android_media_ImageReader.cpp
+++ b/media/jni/android_media_ImageReader.cpp
@@ -95,6 +95,9 @@
void setBufferFormat(int format) { mFormat = format; }
int getBufferFormat() { return mFormat; }
+ void setBufferDataspace(android_dataspace dataSpace) { mDataSpace = dataSpace; }
+ android_dataspace getBufferDataspace() { return mDataSpace; }
+
void setBufferWidth(int width) { mWidth = width; }
int getBufferWidth() { return mWidth; }
@@ -111,6 +114,7 @@
jobject mWeakThiz;
jclass mClazz;
int mFormat;
+ android_dataspace mDataSpace;
int mWidth;
int mHeight;
};
@@ -263,29 +267,6 @@
env->SetLongField(thiz, gSurfaceImageClassInfo.mLockedBuffer, reinterpret_cast<jlong>(buffer));
}
-// Some formats like JPEG defined with different values between android.graphics.ImageFormat and
-// graphics.h, need convert to the one defined in graphics.h here.
-static int Image_getPixelFormat(JNIEnv* env, int format)
-{
- int jpegFormat;
- jfieldID fid;
-
- ALOGV("%s: format = 0x%x", __FUNCTION__, format);
-
- jclass imageFormatClazz = env->FindClass("android/graphics/ImageFormat");
- ALOG_ASSERT(imageFormatClazz != NULL);
-
- fid = env->GetStaticFieldID(imageFormatClazz, "JPEG", "I");
- jpegFormat = env->GetStaticIntField(imageFormatClazz, fid);
-
- // Translate the JPEG to BLOB for camera purpose.
- if (format == jpegFormat) {
- format = HAL_PIXEL_FORMAT_BLOB;
- }
-
- return format;
-}
-
static uint32_t Image_getJpegSize(CpuConsumer::LockedBuffer* buffer, bool usingRGBAOverride)
{
ALOG_ASSERT(buffer != NULL, "Input buffer is NULL!!!");
@@ -430,7 +411,7 @@
pData = buffer->data;
dataSize = Image_getJpegSize(buffer, usingRGBAOverride);
break;
- case HAL_PIXEL_FORMAT_RAW_SENSOR:
+ case HAL_PIXEL_FORMAT_RAW16:
// Single plane 16bpp bayer data.
bytesPerPixel = 2;
ALOG_ASSERT(idx == 0, "Wrong index: %d", idx);
@@ -483,7 +464,7 @@
}
static jint Image_imageGetPixelStride(JNIEnv* env, CpuConsumer::LockedBuffer* buffer, int idx,
- int32_t readerFormat)
+ int32_t halReaderFormat)
{
ALOGV("%s: buffer index: %d", __FUNCTION__, idx);
ALOG_ASSERT((idx < IMAGE_READER_MAX_NUM_PLANES) && (idx >= 0), "Index is out of range:%d", idx);
@@ -493,7 +474,7 @@
int32_t fmt = buffer->flexFormat;
- fmt = applyFormatOverrides(fmt, readerFormat);
+ fmt = applyFormatOverrides(fmt, halReaderFormat);
switch (fmt) {
case HAL_PIXEL_FORMAT_YCbCr_420_888:
@@ -518,7 +499,7 @@
pixelStride = 0;
break;
case HAL_PIXEL_FORMAT_Y16:
- case HAL_PIXEL_FORMAT_RAW_SENSOR:
+ case HAL_PIXEL_FORMAT_RAW16:
case HAL_PIXEL_FORMAT_RGB_565:
// Single plane 16bpp data.
ALOG_ASSERT(idx == 0, "Wrong index: %d", idx);
@@ -544,7 +525,7 @@
}
static jint Image_imageGetRowStride(JNIEnv* env, CpuConsumer::LockedBuffer* buffer, int idx,
- int32_t readerFormat)
+ int32_t halReaderFormat)
{
ALOGV("%s: buffer index: %d", __FUNCTION__, idx);
ALOG_ASSERT((idx < IMAGE_READER_MAX_NUM_PLANES) && (idx >= 0));
@@ -554,7 +535,7 @@
int32_t fmt = buffer->flexFormat;
- fmt = applyFormatOverrides(fmt, readerFormat);
+ fmt = applyFormatOverrides(fmt, halReaderFormat);
switch (fmt) {
case HAL_PIXEL_FORMAT_YCbCr_420_888:
@@ -585,7 +566,7 @@
rowStride = buffer->stride;
break;
case HAL_PIXEL_FORMAT_Y16:
- case HAL_PIXEL_FORMAT_RAW_SENSOR:
+ case HAL_PIXEL_FORMAT_RAW16:
// In native side, strides are specified in pixels, not in bytes.
// Single plane 16bpp bayer data. even width/height,
// row stride multiple of 16 pixels (32 bytes)
@@ -683,11 +664,16 @@
{
status_t res;
int nativeFormat;
+ android_dataspace nativeDataspace;
ALOGV("%s: width:%d, height: %d, format: 0x%x, maxImages:%d",
__FUNCTION__, width, height, format, maxImages);
- nativeFormat = Image_getPixelFormat(env, format);
+ PublicFormat publicFormat = static_cast<PublicFormat>(format);
+ nativeFormat = android_view_Surface_mapPublicFormatToHalFormat(
+ publicFormat);
+ nativeDataspace = android_view_Surface_mapPublicFormatToHalDataspace(
+ publicFormat);
sp<IGraphicBufferProducer> gbProducer;
sp<IGraphicBufferConsumer> gbConsumer;
@@ -711,10 +697,11 @@
consumer->setFrameAvailableListener(ctx);
ImageReader_setNativeContext(env, thiz, ctx);
ctx->setBufferFormat(nativeFormat);
+ ctx->setBufferDataspace(nativeDataspace);
ctx->setBufferWidth(width);
ctx->setBufferHeight(height);
- // Set the width/height/format to the CpuConsumer
+ // Set the width/height/format/dataspace to the CpuConsumer
res = consumer->setDefaultBufferSize(width, height);
if (res != OK) {
jniThrowException(env, "java/lang/IllegalStateException",
@@ -726,6 +713,12 @@
jniThrowException(env, "java/lang/IllegalStateException",
"Failed to set CpuConsumer buffer format");
}
+ res = consumer->setDefaultBufferDataSpace(nativeDataspace);
+ if (res != OK) {
+ jniThrowException(env, "java/lang/IllegalStateException",
+ "Failed to set CpuConsumer buffer dataSpace");
+ }
+
}
static void ImageReader_close(JNIEnv* env, jobject thiz)
@@ -885,6 +878,8 @@
static jobject Image_createSurfacePlane(JNIEnv* env, jobject thiz, int idx, int readerFormat)
{
int rowStride, pixelStride;
+ PublicFormat publicReaderFormat = static_cast<PublicFormat>(readerFormat);
+
ALOGV("%s: buffer index: %d", __FUNCTION__, idx);
CpuConsumer::LockedBuffer* buffer = Image_getLockedBuffer(env, thiz);
@@ -894,10 +889,11 @@
jniThrowException(env, "java/lang/IllegalStateException", "Image was released");
}
- readerFormat = Image_getPixelFormat(env, readerFormat);
+ int halReaderFormat = android_view_Surface_mapPublicFormatToHalFormat(
+ publicReaderFormat);
- rowStride = Image_imageGetRowStride(env, buffer, idx, readerFormat);
- pixelStride = Image_imageGetPixelStride(env, buffer, idx, readerFormat);
+ rowStride = Image_imageGetRowStride(env, buffer, idx, halReaderFormat);
+ pixelStride = Image_imageGetPixelStride(env, buffer, idx, halReaderFormat);
jobject surfPlaneObj = env->NewObject(gSurfacePlaneClassInfo.clazz,
gSurfacePlaneClassInfo.ctor, thiz, idx, rowStride, pixelStride);
@@ -910,6 +906,7 @@
uint8_t *base = NULL;
uint32_t size = 0;
jobject byteBuffer;
+ PublicFormat readerPublicFormat = static_cast<PublicFormat>(readerFormat);
ALOGV("%s: buffer index: %d", __FUNCTION__, idx);
@@ -919,10 +916,11 @@
jniThrowException(env, "java/lang/IllegalStateException", "Image was released");
}
- readerFormat = Image_getPixelFormat(env, readerFormat);
+ int readerHalFormat = android_view_Surface_mapPublicFormatToHalFormat(
+ readerPublicFormat);
// Create byteBuffer from native buffer
- Image_getLockedBufferInfo(env, buffer, idx, &base, &size, readerFormat);
+ Image_getLockedBufferInfo(env, buffer, idx, &base, &size, readerHalFormat);
if (size > static_cast<uint32_t>(INT32_MAX)) {
// Byte buffer have 'int capacity', so check the range
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraBinderTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraBinderTest.java
index cc50c43..362bbc4 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraBinderTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraBinderTest.java
@@ -316,6 +316,11 @@
throws RemoteException {
Log.v(TAG, String.format("Camera %d has status changed to 0x%x", cameraId, status));
}
+ public void onTorchStatusChanged(int status, String cameraId)
+ throws RemoteException {
+ Log.v(TAG, String.format("Camera %s has torch status changed to 0x%x",
+ cameraId, status));
+ }
}
/**
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraDeviceBinderTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraDeviceBinderTest.java
index 3cae19d..e05e1fc 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraDeviceBinderTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraDeviceBinderTest.java
@@ -25,6 +25,7 @@
import android.hardware.camera2.ICameraDeviceUser;
import android.hardware.camera2.impl.CameraMetadataNative;
import android.hardware.camera2.impl.CaptureResultExtras;
+import android.hardware.camera2.params.OutputConfiguration;
import android.hardware.camera2.utils.BinderHolder;
import android.media.Image;
import android.media.ImageReader;
@@ -67,6 +68,7 @@
private CameraBinderTestUtils mUtils;
private ICameraDeviceCallbacks.Stub mMockCb;
private Surface mSurface;
+ private OutputConfiguration mOutputConfiguration;
private HandlerThread mHandlerThread;
private Handler mHandler;
ImageReader mImageReader;
@@ -147,6 +149,7 @@
MAX_NUM_IMAGES);
mImageReader.setOnImageAvailableListener(new ImageDropperListener(), mHandler);
mSurface = mImageReader.getSurface();
+ mOutputConfiguration = new OutputConfiguration(mSurface);
}
private CaptureRequest.Builder createDefaultBuilder(boolean needStream) throws Exception {
@@ -161,8 +164,7 @@
assertFalse(request.isEmpty());
assertFalse(metadata.isEmpty());
if (needStream) {
- int streamId = mCameraUser.createStream(/* ignored */10, /* ignored */20,
- /* ignored */30, mSurface);
+ int streamId = mCameraUser.createStream(mOutputConfiguration);
assertEquals(0, streamId);
request.addTarget(mSurface);
}
@@ -235,12 +237,11 @@
@SmallTest
public void testCreateStream() throws Exception {
- int streamId = mCameraUser.createStream(/* ignored */10, /* ignored */20, /* ignored */30,
- mSurface);
+ int streamId = mCameraUser.createStream(mOutputConfiguration);
assertEquals(0, streamId);
assertEquals(CameraBinderTestUtils.ALREADY_EXISTS,
- mCameraUser.createStream(/* ignored */0, /* ignored */0, /* ignored */0, mSurface));
+ mCameraUser.createStream(mOutputConfiguration));
assertEquals(CameraBinderTestUtils.NO_ERROR, mCameraUser.deleteStream(streamId));
}
@@ -257,20 +258,19 @@
public void testCreateStreamTwo() throws Exception {
// Create first stream
- int streamId = mCameraUser.createStream(/* ignored */0, /* ignored */0, /* ignored */0,
- mSurface);
+ int streamId = mCameraUser.createStream(mOutputConfiguration);
assertEquals(0, streamId);
assertEquals(CameraBinderTestUtils.ALREADY_EXISTS,
- mCameraUser.createStream(/* ignored */0, /* ignored */0, /* ignored */0, mSurface));
+ mCameraUser.createStream(mOutputConfiguration));
// Create second stream with a different surface.
SurfaceTexture surfaceTexture = new SurfaceTexture(/* ignored */0);
surfaceTexture.setDefaultBufferSize(640, 480);
Surface surface2 = new Surface(surfaceTexture);
+ OutputConfiguration output2 = new OutputConfiguration(surface2);
- int streamId2 = mCameraUser.createStream(/* ignored */0, /* ignored */0, /* ignored */0,
- surface2);
+ int streamId2 = mCameraUser.createStream(output2);
assertEquals(1, streamId2);
// Clean up streams
diff --git a/packages/CaptivePortalLogin/res/values-en-rGB/strings.xml b/packages/CaptivePortalLogin/res/values-en-rGB/strings.xml
index 687a14e..bfda753 100644
--- a/packages/CaptivePortalLogin/res/values-en-rGB/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-en-rGB/strings.xml
@@ -4,5 +4,5 @@
<string name="app_name" msgid="5934709770924185752">"CaptivePortalLogin"</string>
<string name="action_use_network" msgid="6076184727448466030">"Use this network as is"</string>
<string name="action_do_not_use_network" msgid="4577366536956516683">"Do not use this network"</string>
- <string name="action_bar_label" msgid="2573986763322074279">"Sign-in to network"</string>
+ <string name="action_bar_label" msgid="2573986763322074279">"Sign in to network"</string>
</resources>
diff --git a/packages/CaptivePortalLogin/res/values-en-rIN/strings.xml b/packages/CaptivePortalLogin/res/values-en-rIN/strings.xml
index 687a14e..bfda753 100644
--- a/packages/CaptivePortalLogin/res/values-en-rIN/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-en-rIN/strings.xml
@@ -4,5 +4,5 @@
<string name="app_name" msgid="5934709770924185752">"CaptivePortalLogin"</string>
<string name="action_use_network" msgid="6076184727448466030">"Use this network as is"</string>
<string name="action_do_not_use_network" msgid="4577366536956516683">"Do not use this network"</string>
- <string name="action_bar_label" msgid="2573986763322074279">"Sign-in to network"</string>
+ <string name="action_bar_label" msgid="2573986763322074279">"Sign in to network"</string>
</resources>
diff --git a/packages/CaptivePortalLogin/res/values/strings.xml b/packages/CaptivePortalLogin/res/values/strings.xml
index 1b0f0a4..8348be9 100644
--- a/packages/CaptivePortalLogin/res/values/strings.xml
+++ b/packages/CaptivePortalLogin/res/values/strings.xml
@@ -4,6 +4,6 @@
<string name="app_name">CaptivePortalLogin</string>
<string name="action_use_network">Use this network as is</string>
<string name="action_do_not_use_network">Do not use this network</string>
- <string name="action_bar_label">Sign-in to network</string>
+ <string name="action_bar_label">Sign in to network</string>
</resources>
diff --git a/services/Android.mk b/services/Android.mk
index 3c94f43..e4b0cbb 100644
--- a/services/Android.mk
+++ b/services/Android.mk
@@ -24,6 +24,7 @@
appwidget \
backup \
devicepolicy \
+ net \
print \
restrictions \
usage \
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index b72b29d..d9ef766 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -48,7 +48,6 @@
import android.net.INetworkStatsService;
import android.net.LinkProperties;
import android.net.LinkProperties.CompareResult;
-import android.net.MobileDataStateTracker;
import android.net.Network;
import android.net.NetworkAgent;
import android.net.NetworkCapabilities;
@@ -59,12 +58,10 @@
import android.net.NetworkQuotaInfo;
import android.net.NetworkRequest;
import android.net.NetworkState;
-import android.net.NetworkStateTracker;
import android.net.NetworkUtils;
import android.net.Proxy;
import android.net.ProxyInfo;
import android.net.RouteInfo;
-import android.net.SamplingDataTracker;
import android.net.UidRange;
import android.net.Uri;
import android.os.Binder;
@@ -153,9 +150,6 @@
private static final boolean DBG = true;
private static final boolean VDBG = false;
- // network sampling debugging
- private static final boolean SAMPLE_DBG = false;
-
private static final boolean LOGD_RULES = false;
// TODO: create better separation between radio types and network types
@@ -166,33 +160,10 @@
private static final String NETWORK_RESTORE_DELAY_PROP_NAME =
"android.telephony.apn-restore";
- // Default value if FAIL_FAST_TIME_MS is not set
- private static final int DEFAULT_FAIL_FAST_TIME_MS = 1 * 60 * 1000;
- // system property that can override DEFAULT_FAIL_FAST_TIME_MS
- private static final String FAIL_FAST_TIME_MS =
- "persist.radio.fail_fast_time_ms";
-
- private static final String ACTION_PKT_CNT_SAMPLE_INTERVAL_ELAPSED =
- "android.net.ConnectivityService.action.PKT_CNT_SAMPLE_INTERVAL_ELAPSED";
-
- private static final int SAMPLE_INTERVAL_ELAPSED_REQUEST_CODE = 0;
-
// How long to delay to removal of a pending intent based request.
// See Settings.Secure.CONNECTIVITY_RELEASE_PENDING_INTENT_DELAY_MS
private final int mReleasePendingIntentDelayMs;
- private PendingIntent mSampleIntervalElapsedIntent;
-
- // Set network sampling interval at 12 minutes, this way, even if the timers get
- // aggregated, it will fire at around 15 minutes, which should allow us to
- // aggregate this timer with other timers (specially the socket keep alive timers)
- private static final int DEFAULT_SAMPLING_INTERVAL_IN_SECONDS = (SAMPLE_DBG ? 30 : 12 * 60);
-
- // start network sampling a minute after booting ...
- private static final int DEFAULT_START_SAMPLING_INTERVAL_IN_SECONDS = (SAMPLE_DBG ? 30 : 60);
-
- AlarmManager mAlarmManager;
-
private Tethering mTethering;
private final PermissionMonitor mPermissionMonitor;
@@ -212,13 +183,6 @@
/** Set of ifaces that are costly. */
private HashSet<String> mMeteredIfaces = Sets.newHashSet();
- /**
- * Sometimes we want to refer to the individual network state
- * trackers separately, and sometimes we just want to treat them
- * abstractly.
- */
- private NetworkStateTracker mNetTrackers[];
-
private Context mContext;
private int mNetworkPreference;
// 0 is full bad, 100 is full good
@@ -278,28 +242,11 @@
private static final int EVENT_APPLY_GLOBAL_HTTP_PROXY = 9;
/**
- * used internally to set external dependency met/unmet
- * arg1 = ENABLED (met) or DISABLED (unmet)
- * arg2 = NetworkType
- */
- private static final int EVENT_SET_DEPENDENCY_MET = 10;
-
- /**
* used internally to send a sticky broadcast delayed.
*/
private static final int EVENT_SEND_STICKY_BROADCAST_INTENT = 11;
/**
- * Used internally to disable fail fast of mobile data
- */
- private static final int EVENT_ENABLE_FAIL_FAST_MOBILE_DATA = 14;
-
- /**
- * used internally to indicate that data sampling interval is up
- */
- private static final int EVENT_SAMPLE_INTERVAL_ELAPSED = 15;
-
- /**
* PAC manager has received new port.
*/
private static final int EVENT_PROXY_HAS_CHANGED = 16;
@@ -419,8 +366,6 @@
private DataConnectionStats mDataConnectionStats;
- private AtomicInteger mEnableFailFastMobileDataTag = new AtomicInteger(0);
-
TelephonyManager mTelephonyManager;
// sequence number for Networks; keep in sync with system/netd/NetworkController.cpp
@@ -650,9 +595,6 @@
com.android.internal.R.integer.config_networkTransitionTimeout);
mPendingIntentWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
- mNetTrackers = new NetworkStateTracker[
- ConnectivityManager.MAX_NETWORK_TYPE+1];
-
mNetConfigs = new NetworkConfig[ConnectivityManager.MAX_NETWORK_TYPE+1];
// TODO: What is the "correct" way to do determine if this is a wifi only device?
@@ -740,23 +682,6 @@
mDataConnectionStats = new DataConnectionStats(mContext);
mDataConnectionStats.startMonitoring();
- mAlarmManager = (AlarmManager)mContext.getSystemService(Context.ALARM_SERVICE);
-
- IntentFilter filter = new IntentFilter();
- filter.addAction(ACTION_PKT_CNT_SAMPLE_INTERVAL_ELAPSED);
- mContext.registerReceiver(
- new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- String action = intent.getAction();
- if (action.equals(ACTION_PKT_CNT_SAMPLE_INTERVAL_ELAPSED)) {
- mHandler.sendMessage(mHandler.obtainMessage
- (EVENT_SAMPLE_INTERVAL_ELAPSED));
- }
- }
- },
- new IntentFilter(filter));
-
mPacManager = new PacManager(mContext, mHandler, EVENT_PROXY_HAS_CHANGED);
mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
@@ -782,15 +707,6 @@
throw new IllegalStateException("No free netIds");
}
- private boolean teardown(NetworkStateTracker netTracker) {
- if (netTracker.teardown()) {
- netTracker.setTeardownRequested(true);
- return true;
- } else {
- return false;
- }
- }
-
private NetworkState getFilteredNetworkState(int networkType, int uid) {
NetworkInfo info = null;
LinkProperties lp = null;
@@ -1350,22 +1266,6 @@
return true;
}
- public void setDataDependency(int networkType, boolean met) {
- enforceConnectivityInternalPermission();
-
- mHandler.sendMessage(mHandler.obtainMessage(EVENT_SET_DEPENDENCY_MET,
- (met ? ENABLED : DISABLED), networkType));
- }
-
- private void handleSetDependencyMet(int networkType, boolean met) {
- if (mNetTrackers[networkType] != null) {
- if (DBG) {
- log("handleSetDependencyMet(" + networkType + ", " + met + ")");
- }
- mNetTrackers[networkType].setDependencyMet(met);
- }
- }
-
private INetworkPolicyListener mPolicyListener = new INetworkPolicyListener.Stub() {
@Override
public void onUidRulesChanged(int uid, int uidRules) {
@@ -1406,21 +1306,6 @@
if (LOGD_RULES) {
log("onRestrictBackgroundChanged(restrictBackground=" + restrictBackground + ")");
}
-
- // kick off connectivity change broadcast for active network, since
- // global background policy change is radical.
- // TODO: Dead code; remove.
- //
- // final int networkType = mActiveDefaultNetwork;
- // if (isNetworkTypeValid(networkType)) {
- // final NetworkStateTracker tracker = mNetTrackers[networkType];
- // if (tracker != null) {
- // final NetworkInfo info = tracker.getNetworkInfo();
- // if (info != null && info.isConnected()) {
- // sendConnectedBroadcast(info);
- // }
- // }
- // }
}
};
@@ -1536,14 +1421,6 @@
}
void systemReady() {
- // start network sampling ..
- Intent intent = new Intent(ACTION_PKT_CNT_SAMPLE_INTERVAL_ELAPSED);
- intent.setPackage(mContext.getPackageName());
-
- mSampleIntervalElapsedIntent = PendingIntent.getBroadcast(mContext,
- SAMPLE_INTERVAL_ELAPSED_REQUEST_CODE, intent, 0);
- setAlarm(DEFAULT_START_SAMPLING_INTERVAL_IN_SECONDS * 1000, mSampleIntervalElapsedIntent);
-
loadGlobalProxy();
synchronized(this) {
@@ -2015,66 +1892,6 @@
}
break;
}
- case NetworkStateTracker.EVENT_STATE_CHANGED: {
- info = (NetworkInfo) msg.obj;
- NetworkInfo.State state = info.getState();
-
- if (VDBG || (state == NetworkInfo.State.CONNECTED) ||
- (state == NetworkInfo.State.DISCONNECTED) ||
- (state == NetworkInfo.State.SUSPENDED)) {
- log("ConnectivityChange for " +
- info.getTypeName() + ": " +
- state + "/" + info.getDetailedState());
- }
-
- EventLogTags.writeConnectivityStateChanged(
- info.getType(), info.getSubtype(), info.getDetailedState().ordinal());
-
- if (info.isConnectedToProvisioningNetwork()) {
- /**
- * TODO: Create ConnectivityManager.TYPE_MOBILE_PROVISIONING
- * for now its an in between network, its a network that
- * is actually a default network but we don't want it to be
- * announced as such to keep background applications from
- * trying to use it. It turns out that some still try so we
- * take the additional step of clearing any default routes
- * to the link that may have incorrectly setup by the lower
- * levels.
- */
- LinkProperties lp = getLinkPropertiesForType(info.getType());
- if (DBG) {
- log("EVENT_STATE_CHANGED: connected to provisioning network, lp=" + lp);
- }
-
- // Clear any default routes setup by the radio so
- // any activity by applications trying to use this
- // connection will fail until the provisioning network
- // is enabled.
- /*
- for (RouteInfo r : lp.getRoutes()) {
- removeRoute(lp, r, TO_DEFAULT_TABLE,
- mNetTrackers[info.getType()].getNetwork().netId);
- }
- */
- } else if (state == NetworkInfo.State.DISCONNECTED) {
- } else if (state == NetworkInfo.State.SUSPENDED) {
- } else if (state == NetworkInfo.State.CONNECTED) {
- // handleConnect(info);
- }
- notifyLockdownVpn(null);
- break;
- }
- case NetworkStateTracker.EVENT_CONFIGURATION_CHANGED: {
- info = (NetworkInfo) msg.obj;
- // TODO: Temporary allowing network configuration
- // change not resetting sockets.
- // @see bug/4455071
- /*
- handleConnectivityChange(info.getType(), mCurrentLinkProperties[info.getType()],
- false);
- */
- break;
- }
}
}
}
@@ -2439,34 +2256,11 @@
handleDeprecatedGlobalHttpProxy();
break;
}
- case EVENT_SET_DEPENDENCY_MET: {
- boolean met = (msg.arg1 == ENABLED);
- handleSetDependencyMet(msg.arg2, met);
- break;
- }
case EVENT_SEND_STICKY_BROADCAST_INTENT: {
Intent intent = (Intent)msg.obj;
sendStickyBroadcast(intent);
break;
}
- case EVENT_ENABLE_FAIL_FAST_MOBILE_DATA: {
- int tag = mEnableFailFastMobileDataTag.get();
- if (msg.arg1 == tag) {
- MobileDataStateTracker mobileDst =
- (MobileDataStateTracker) mNetTrackers[ConnectivityManager.TYPE_MOBILE];
- if (mobileDst != null) {
- mobileDst.setEnableFailFastMobileData(msg.arg2);
- }
- } else {
- log("EVENT_ENABLE_FAIL_FAST_MOBILE_DATA: stale arg1:" + msg.arg1
- + " != tag:" + tag);
- }
- break;
- }
- case EVENT_SAMPLE_INTERVAL_ELAPSED: {
- handleNetworkSamplingTimeout();
- break;
- }
case EVENT_PROXY_HAS_CHANGED: {
handleApplyDefaultProxy((ProxyInfo)msg.obj);
break;
@@ -3066,14 +2860,6 @@
}
}
- public void supplyMessenger(int networkType, Messenger messenger) {
- enforceConnectivityInternalPermission();
-
- if (isNetworkTypeValid(networkType) && mNetTrackers[networkType] != null) {
- mNetTrackers[networkType].supplyMessenger(messenger);
- }
- }
-
public int findConnectionTypeForIface(String iface) {
enforceConnectivityInternalPermission();
@@ -3091,23 +2877,6 @@
return ConnectivityManager.TYPE_NONE;
}
- /**
- * Have mobile data fail fast if enabled.
- *
- * @param enabled DctConstants.ENABLED/DISABLED
- */
- private void setEnableFailFastMobileData(int enabled) {
- int tag;
-
- if (enabled == DctConstants.ENABLED) {
- tag = mEnableFailFastMobileDataTag.incrementAndGet();
- } else {
- tag = mEnableFailFastMobileDataTag.get();
- }
- mHandler.sendMessage(mHandler.obtainMessage(EVENT_ENABLE_FAIL_FAST_MOBILE_DATA, tag,
- enabled));
- }
-
@Override
public int checkMobileProvisioning(int suggestedTimeOutMs) {
// TODO: Remove? Any reason to trigger a provisioning check?
@@ -3392,69 +3161,6 @@
}
};
- /* Infrastructure for network sampling */
-
- private void handleNetworkSamplingTimeout() {
-
- if (SAMPLE_DBG) log("Sampling interval elapsed, updating statistics ..");
-
- // initialize list of interfaces ..
- Map<String, SamplingDataTracker.SamplingSnapshot> mapIfaceToSample =
- new HashMap<String, SamplingDataTracker.SamplingSnapshot>();
- for (NetworkStateTracker tracker : mNetTrackers) {
- if (tracker != null) {
- String ifaceName = tracker.getNetworkInterfaceName();
- if (ifaceName != null) {
- mapIfaceToSample.put(ifaceName, null);
- }
- }
- }
-
- // Read samples for all interfaces
- SamplingDataTracker.getSamplingSnapshots(mapIfaceToSample);
-
- // process samples for all networks
- for (NetworkStateTracker tracker : mNetTrackers) {
- if (tracker != null) {
- String ifaceName = tracker.getNetworkInterfaceName();
- SamplingDataTracker.SamplingSnapshot ss = mapIfaceToSample.get(ifaceName);
- if (ss != null) {
- // end the previous sampling cycle
- tracker.stopSampling(ss);
- // start a new sampling cycle ..
- tracker.startSampling(ss);
- }
- }
- }
-
- if (SAMPLE_DBG) log("Done.");
-
- int samplingIntervalInSeconds = Settings.Global.getInt(mContext.getContentResolver(),
- Settings.Global.CONNECTIVITY_SAMPLING_INTERVAL_IN_SECONDS,
- DEFAULT_SAMPLING_INTERVAL_IN_SECONDS);
-
- if (SAMPLE_DBG) {
- log("Setting timer for " + String.valueOf(samplingIntervalInSeconds) + "seconds");
- }
-
- setAlarm(samplingIntervalInSeconds * 1000, mSampleIntervalElapsedIntent);
- }
-
- /**
- * Sets a network sampling alarm.
- */
- void setAlarm(int timeoutInMilliseconds, PendingIntent intent) {
- long wakeupTime = SystemClock.elapsedRealtime() + timeoutInMilliseconds;
- int alarmType;
- if (Resources.getSystem().getBoolean(
- R.bool.config_networkSamplingWakesDevice)) {
- alarmType = AlarmManager.ELAPSED_REALTIME_WAKEUP;
- } else {
- alarmType = AlarmManager.ELAPSED_REALTIME;
- }
- mAlarmManager.set(alarmType, wakeupTime, intent);
- }
-
private final HashMap<Messenger, NetworkFactoryInfo> mNetworkFactoryInfos =
new HashMap<Messenger, NetworkFactoryInfo>();
private final HashMap<NetworkRequest, NetworkRequestInfo> mNetworkRequests =
diff --git a/services/core/java/com/android/server/NetworkManagementService.java b/services/core/java/com/android/server/NetworkManagementService.java
index 8c56c8c..0437a2a 100644
--- a/services/core/java/com/android/server/NetworkManagementService.java
+++ b/services/core/java/com/android/server/NetworkManagementService.java
@@ -1374,7 +1374,8 @@
mConnector.execute("softap", "set", wlanIface);
} else {
mConnector.execute("softap", "set", wlanIface, wifiConfig.SSID,
- "broadcast", "6", getSecurityType(wifiConfig),
+ "broadcast", Integer.toString(wifiConfig.apChannel),
+ getSecurityType(wifiConfig),
new SensitiveArg(wifiConfig.preSharedKey));
}
mConnector.execute("softap", "startap");
diff --git a/services/core/java/com/android/server/telecom/TelecomLoaderService.java b/services/core/java/com/android/server/telecom/TelecomLoaderService.java
index 64a67fc..22fee22 100644
--- a/services/core/java/com/android/server/telecom/TelecomLoaderService.java
+++ b/services/core/java/com/android/server/telecom/TelecomLoaderService.java
@@ -63,7 +63,7 @@
private static final ComponentName SERVICE_COMPONENT = new ComponentName(
"com.android.server.telecom",
- "com.android.server.telecom.TelecomService");
+ "com.android.server.telecom.components.TelecomService");
private static final String SERVICE_ACTION = "com.android.ITelecomService";
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 334cdf6..0705fbd 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -677,7 +677,8 @@
mSystemServiceManager.startService("com.android.server.wifi.RttService");
- if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_ETHERNET)) {
+ if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_ETHERNET) ||
+ mPackageManager.hasSystemFeature(PackageManager.FEATURE_USB_HOST)) {
mSystemServiceManager.startService(ETHERNET_SERVICE_CLASS);
}
diff --git a/services/net/Android.mk b/services/net/Android.mk
new file mode 100644
index 0000000..336bc45
--- /dev/null
+++ b/services/net/Android.mk
@@ -0,0 +1,10 @@
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := services.net
+
+LOCAL_SRC_FILES += \
+ $(call all-java-files-under,java)
+
+include $(BUILD_STATIC_JAVA_LIBRARY)
diff --git a/core/java/android/net/dhcp/DhcpAckPacket.java b/services/net/java/android/net/dhcp/DhcpAckPacket.java
similarity index 77%
rename from core/java/android/net/dhcp/DhcpAckPacket.java
rename to services/net/java/android/net/dhcp/DhcpAckPacket.java
index 7b8be9c..25b8093 100644
--- a/core/java/android/net/dhcp/DhcpAckPacket.java
+++ b/services/net/java/android/net/dhcp/DhcpAckPacket.java
@@ -16,7 +16,6 @@
package android.net.dhcp;
-import java.net.InetAddress;
import java.net.Inet4Address;
import java.nio.ByteBuffer;
@@ -28,12 +27,11 @@
/**
* The address of the server which sent this packet.
*/
- private final InetAddress mSrcIp;
+ private final Inet4Address mSrcIp;
- DhcpAckPacket(int transId, boolean broadcast, InetAddress serverAddress,
- InetAddress clientIp, byte[] clientMac) {
- super(transId, Inet4Address.ANY, clientIp, serverAddress,
- Inet4Address.ANY, clientMac, broadcast);
+ DhcpAckPacket(int transId, boolean broadcast, Inet4Address serverAddress,
+ Inet4Address clientIp, byte[] clientMac) {
+ super(transId, INADDR_ANY, clientIp, serverAddress, INADDR_ANY, clientMac, broadcast);
mBroadcast = broadcast;
mSrcIp = serverAddress;
}
@@ -42,7 +40,7 @@
String s = super.toString();
String dnsServers = " DNS servers: ";
- for (InetAddress dnsServer: mDnsServers) {
+ for (Inet4Address dnsServer: mDnsServers) {
dnsServers += dnsServer.toString() + " ";
}
@@ -57,8 +55,8 @@
*/
public ByteBuffer buildPacket(int encap, short destUdp, short srcUdp) {
ByteBuffer result = ByteBuffer.allocate(MAX_LENGTH);
- InetAddress destIp = mBroadcast ? Inet4Address.ALL : mYourIp;
- InetAddress srcIp = mBroadcast ? Inet4Address.ANY : mSrcIp;
+ Inet4Address destIp = mBroadcast ? INADDR_BROADCAST : mYourIp;
+ Inet4Address srcIp = mBroadcast ? INADDR_ANY : mSrcIp;
fillInPacket(encap, destIp, srcIp, destUdp, srcUdp, result,
DHCP_BOOTREPLY, mBroadcast);
@@ -98,12 +96,4 @@
return v.intValue();
}
}
-
- /**
- * Notifies the specified state machine of the ACK packet parameters.
- */
- public void doNextOp(DhcpStateMachine machine) {
- machine.onAckReceived(mYourIp, mSubnetMask, mGateway, mDnsServers,
- mServerIdentifier, getInt(mLeaseTime));
- }
}
diff --git a/services/net/java/android/net/dhcp/DhcpClient.java b/services/net/java/android/net/dhcp/DhcpClient.java
new file mode 100644
index 0000000..57cc251
--- /dev/null
+++ b/services/net/java/android/net/dhcp/DhcpClient.java
@@ -0,0 +1,807 @@
+/*
+ * Copyright (C) 2015 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.dhcp;
+
+import com.android.internal.util.HexDump;
+import com.android.internal.util.Protocol;
+import com.android.internal.util.State;
+import com.android.internal.util.StateMachine;
+
+import android.app.AlarmManager;
+import android.app.PendingIntent;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.net.DhcpResults;
+import android.net.BaseDhcpStateMachine;
+import android.net.DhcpStateMachine;
+import android.net.InterfaceConfiguration;
+import android.net.LinkAddress;
+import android.net.NetworkUtils;
+import android.os.IBinder;
+import android.os.INetworkManagementService;
+import android.os.Message;
+import android.os.PowerManager;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.os.SystemClock;
+import android.system.ErrnoException;
+import android.system.Os;
+import android.system.PacketSocketAddress;
+import android.util.Log;
+import android.util.TimeUtils;
+
+import java.io.FileDescriptor;
+import java.io.IOException;
+import java.lang.Thread;
+import java.net.Inet4Address;
+import java.net.InetSocketAddress;
+import java.net.NetworkInterface;
+import java.net.SocketException;
+import java.nio.BufferUnderflowException;
+import java.nio.ByteBuffer;
+import java.util.Arrays;
+import java.util.Random;
+
+import libcore.io.IoUtils;
+
+import static android.system.OsConstants.*;
+import static android.net.dhcp.DhcpPacket.*;
+
+/**
+ * A DHCPv4 client.
+ *
+ * Written to behave similarly to the DhcpStateMachine + dhcpcd 5.5.6 combination used in Android
+ * 5.1 and below, as configured on Nexus 6. The interface is the same as DhcpStateMachine.
+ *
+ * TODO:
+ *
+ * - Exponential backoff when receiving NAKs (not specified by the RFC, but current behaviour).
+ * - Support persisting lease state and support INIT-REBOOT. Android 5.1 does this, but it does not
+ * do so correctly: instead of requesting the lease last obtained on a particular network (e.g., a
+ * given SSID), it requests the last-leased IP address on the same interface, causing a delay if
+ * the server NAKs or a timeout if it doesn't.
+ *
+ * Known differences from current behaviour:
+ *
+ * - Does not request the "static routes" option.
+ * - Does not support BOOTP servers. DHCP has been around since 1993, should be everywhere now.
+ * - Requests the "broadcast" option, but does nothing with it.
+ * - Rejects invalid subnet masks such as 255.255.255.1 (current code treats that as 255.255.255.0).
+ *
+ * @hide
+ */
+public class DhcpClient extends BaseDhcpStateMachine {
+
+ private static final String TAG = "DhcpClient";
+ private static final boolean DBG = true;
+ private static final boolean STATE_DBG = false;
+ private static final boolean MSG_DBG = false;
+
+ // Timers and timeouts.
+ private static final int SECONDS = 1000;
+ private static final int FIRST_TIMEOUT_MS = 2 * SECONDS;
+ private static final int MAX_TIMEOUT_MS = 128 * SECONDS;
+
+ // This is not strictly needed, since the client is asynchronous and implements exponential
+ // backoff. It's maintained for backwards compatibility with the previous DHCP code, which was
+ // a blocking operation with a 30-second timeout. We pick 36 seconds so we can send packets at
+ // t=0, t=2, t=6, t=14, t=30, allowing for 10% jitter.
+ private static final int DHCP_TIMEOUT_MS = 36 * SECONDS;
+
+ // Messages.
+ private static final int BASE = Protocol.BASE_DHCP + 100;
+ private static final int CMD_KICK = BASE + 1;
+ private static final int CMD_RECEIVED_PACKET = BASE + 2;
+ private static final int CMD_TIMEOUT = BASE + 3;
+
+ // DHCP parameters that we request.
+ private static final byte[] REQUESTED_PARAMS = new byte[] {
+ DHCP_SUBNET_MASK,
+ DHCP_ROUTER,
+ DHCP_DNS_SERVER,
+ DHCP_DOMAIN_NAME,
+ DHCP_MTU,
+ DHCP_BROADCAST_ADDRESS, // TODO: currently ignored.
+ DHCP_LEASE_TIME,
+ DHCP_RENEWAL_TIME,
+ DHCP_REBINDING_TIME,
+ };
+
+ // DHCP flag that means "yes, we support unicast."
+ private static final boolean DO_UNICAST = false;
+
+ // System services / libraries we use.
+ private final Context mContext;
+ private final AlarmManager mAlarmManager;
+ private final Random mRandom;
+ private final INetworkManagementService mNMService;
+
+ // Sockets.
+ // - We use a packet socket to receive, because servers send us packets bound for IP addresses
+ // which we have not yet configured, and the kernel protocol stack drops these.
+ // - We use a UDP socket to send, so the kernel handles ARP and routing for us (DHCP servers can
+ // be off-link as well as on-link).
+ private FileDescriptor mPacketSock;
+ private FileDescriptor mUdpSock;
+ private ReceiveThread mReceiveThread;
+
+ // State variables.
+ private final StateMachine mController;
+ private final PendingIntent mKickIntent;
+ private final PendingIntent mTimeoutIntent;
+ private final PendingIntent mRenewIntent;
+ private final String mIfaceName;
+
+ private boolean mRegisteredForPreDhcpNotification;
+ private NetworkInterface mIface;
+ private byte[] mHwAddr;
+ private PacketSocketAddress mInterfaceBroadcastAddr;
+ private int mTransactionId;
+ private DhcpResults mDhcpLease;
+ private long mDhcpLeaseExpiry;
+ private DhcpResults mOffer;
+
+ // States.
+ private State mStoppedState = new StoppedState();
+ private State mDhcpState = new DhcpState();
+ private State mDhcpInitState = new DhcpInitState();
+ private State mDhcpSelectingState = new DhcpSelectingState();
+ private State mDhcpRequestingState = new DhcpRequestingState();
+ private State mDhcpBoundState = new DhcpBoundState();
+ private State mDhcpRenewingState = new DhcpRenewingState();
+ private State mDhcpRebindingState = new DhcpRebindingState();
+ private State mDhcpInitRebootState = new DhcpInitRebootState();
+ private State mDhcpRebootingState = new DhcpRebootingState();
+ private State mWaitBeforeStartState = new WaitBeforeStartState(mDhcpInitState);
+ private State mWaitBeforeRenewalState = new WaitBeforeRenewalState(mDhcpRenewingState);
+
+ private DhcpClient(Context context, StateMachine controller, String iface) {
+ super(TAG);
+
+ mContext = context;
+ mController = controller;
+ mIfaceName = iface;
+
+ addState(mStoppedState);
+ addState(mDhcpState);
+ addState(mDhcpInitState, mDhcpState);
+ addState(mWaitBeforeStartState, mDhcpState);
+ addState(mDhcpSelectingState, mDhcpState);
+ addState(mDhcpRequestingState, mDhcpState);
+ addState(mDhcpBoundState, mDhcpState);
+ addState(mWaitBeforeRenewalState, mDhcpState);
+ addState(mDhcpRenewingState, mDhcpState);
+ addState(mDhcpRebindingState, mDhcpState);
+ addState(mDhcpInitRebootState, mDhcpState);
+ addState(mDhcpRebootingState, mDhcpState);
+
+ setInitialState(mStoppedState);
+
+ mAlarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);
+ IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE);
+ mNMService = INetworkManagementService.Stub.asInterface(b);
+
+ mRandom = new Random();
+
+ mKickIntent = createStateMachineCommandIntent("KICK", CMD_KICK);
+ mTimeoutIntent = createStateMachineCommandIntent("TIMEOUT", CMD_TIMEOUT);
+ mRenewIntent = createStateMachineCommandIntent("RENEW", DhcpStateMachine.CMD_RENEW_DHCP);
+ }
+
+ @Override
+ public void registerForPreDhcpNotification() {
+ mRegisteredForPreDhcpNotification = true;
+ }
+
+ public static BaseDhcpStateMachine makeDhcpStateMachine(
+ Context context, StateMachine controller, String intf) {
+ DhcpClient client = new DhcpClient(context, controller, intf);
+ client.start();
+ return client;
+ }
+
+ /**
+ * Constructs a PendingIntent that sends the specified command to the state machine. This is
+ * implemented by creating an Intent with the specified parameters, and creating and registering
+ * a BroadcastReceiver for it. The broadcast must be sent by a process that holds the
+ * {@code CONNECTIVITY_INTERNAL} permission.
+ *
+ * @param cmdName the name of the command. The intent's action will be
+ * {@code android.net.dhcp.DhcpClient.<cmdName>}
+ * @param cmd the command to send to the state machine when the PendingIntent is triggered.
+ * @return the PendingIntent
+ */
+ private PendingIntent createStateMachineCommandIntent(final String cmdName, final int cmd) {
+ String action = DhcpClient.class.getName() + "." + cmdName;
+
+ // TODO: figure out what values to pass to intent.setPackage() and intent.setClass() that
+ // result in the Intent being received by this class and nowhere else, and use them.
+ Intent intent = new Intent(action, null)
+ .addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
+ PendingIntent pendingIntent = PendingIntent.getBroadcast(mContext, cmd, intent, 0);
+
+ mContext.registerReceiver(
+ new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ sendMessage(cmd);
+ }
+ },
+ new IntentFilter(action),
+ android.Manifest.permission.CONNECTIVITY_INTERNAL,
+ null);
+
+ return pendingIntent;
+ }
+
+ private boolean initInterface() {
+ try {
+ mIface = NetworkInterface.getByName(mIfaceName);
+ mHwAddr = mIface.getHardwareAddress();
+ mInterfaceBroadcastAddr = new PacketSocketAddress(mIface.getIndex(),
+ DhcpPacket.ETHER_BROADCAST);
+ return true;
+ } catch(SocketException e) {
+ Log.wtf(TAG, "Can't determine ifindex or MAC address for " + mIfaceName);
+ return false;
+ }
+ }
+
+ private void initTransactionId() {
+ mTransactionId = mRandom.nextInt();
+ }
+
+ private boolean initSockets() {
+ try {
+ mPacketSock = Os.socket(AF_PACKET, SOCK_RAW, ETH_P_IP);
+ PacketSocketAddress addr = new PacketSocketAddress((short) ETH_P_IP, mIface.getIndex());
+ Os.bind(mPacketSock, addr);
+ NetworkUtils.attachDhcpFilter(mPacketSock);
+ } catch(SocketException|ErrnoException e) {
+ Log.e(TAG, "Error creating packet socket", e);
+ return false;
+ }
+ try {
+ mUdpSock = Os.socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+ Os.setsockoptInt(mUdpSock, SOL_SOCKET, SO_REUSEADDR, 1);
+ Os.setsockoptIfreq(mUdpSock, SOL_SOCKET, SO_BINDTODEVICE, mIfaceName);
+ Os.setsockoptInt(mUdpSock, SOL_SOCKET, SO_BROADCAST, 1);
+ Os.bind(mUdpSock, Inet4Address.ANY, DhcpPacket.DHCP_CLIENT);
+ NetworkUtils.protectFromVpn(mUdpSock);
+ } catch(SocketException|ErrnoException e) {
+ Log.e(TAG, "Error creating UDP socket", e);
+ return false;
+ }
+ return true;
+ }
+
+ private void closeSockets() {
+ IoUtils.closeQuietly(mUdpSock);
+ IoUtils.closeQuietly(mPacketSock);
+ }
+
+ private boolean setIpAddress(LinkAddress address) {
+ InterfaceConfiguration ifcg = new InterfaceConfiguration();
+ ifcg.setLinkAddress(address);
+ try {
+ mNMService.setInterfaceConfig(mIfaceName, ifcg);
+ } catch (RemoteException|IllegalStateException e) {
+ Log.e(TAG, "Error configuring IP address : " + e);
+ return false;
+ }
+ return true;
+ }
+
+ class ReceiveThread extends Thread {
+
+ private final byte[] mPacket = new byte[DhcpPacket.MAX_LENGTH];
+ private boolean stopped = false;
+
+ public void halt() {
+ stopped = true;
+ closeSockets(); // Interrupts the read() call the thread is blocked in.
+ }
+
+ @Override
+ public void run() {
+ maybeLog("Starting receive thread");
+ while (!stopped) {
+ try {
+ int length = Os.read(mPacketSock, mPacket, 0, mPacket.length);
+ DhcpPacket packet = null;
+ packet = DhcpPacket.decodeFullPacket(mPacket, length, DhcpPacket.ENCAP_L2);
+ if (packet != null) {
+ maybeLog("Received packet: " + packet);
+ sendMessage(CMD_RECEIVED_PACKET, packet);
+ }
+ } catch(IOException|ErrnoException e) {
+ Log.e(TAG, "Read error", e);
+ }
+ }
+ maybeLog("Stopping receive thread");
+ }
+ }
+
+ private boolean transmitPacket(ByteBuffer buf, String description, Inet4Address to) {
+ try {
+ if (to.equals(INADDR_BROADCAST)) {
+ maybeLog("Broadcasting " + description);
+ Os.sendto(mPacketSock, buf.array(), 0, buf.limit(), 0, mInterfaceBroadcastAddr);
+ } else {
+ maybeLog("Unicasting " + description + " to " + to.getHostAddress());
+ Os.sendto(mUdpSock, buf, 0, to, DhcpPacket.DHCP_SERVER);
+ }
+ } catch(ErrnoException|IOException e) {
+ Log.e(TAG, "Can't send packet: ", e);
+ return false;
+ }
+ return true;
+ }
+
+ private boolean sendDiscoverPacket() {
+ ByteBuffer packet = DhcpPacket.buildDiscoverPacket(
+ DhcpPacket.ENCAP_L2, mTransactionId, mHwAddr, DO_UNICAST, REQUESTED_PARAMS);
+ return transmitPacket(packet, "DHCPDISCOVER", INADDR_BROADCAST);
+ }
+
+ private boolean sendRequestPacket(
+ Inet4Address clientAddress, Inet4Address requestedAddress,
+ Inet4Address serverAddress, Inet4Address to) {
+ // TODO: should we use the transaction ID from the server?
+ int encap = to.equals(INADDR_BROADCAST) ? DhcpPacket.ENCAP_L2 : DhcpPacket.ENCAP_BOOTP;
+
+ ByteBuffer packet = DhcpPacket.buildRequestPacket(
+ encap, mTransactionId, clientAddress,
+ DO_UNICAST, mHwAddr, requestedAddress,
+ serverAddress, REQUESTED_PARAMS, null);
+ String description = "DHCPREQUEST ciaddr=" + clientAddress.getHostAddress() +
+ " request=" + requestedAddress.getHostAddress() +
+ " to=" + serverAddress.getHostAddress();
+ return transmitPacket(packet, description, to);
+ }
+
+ private void scheduleRenew() {
+ long now = SystemClock.elapsedRealtime();
+ long alarmTime = (now + mDhcpLeaseExpiry) / 2;
+ mAlarmManager.cancel(mRenewIntent);
+ mAlarmManager.setExact(AlarmManager.ELAPSED_REALTIME_WAKEUP, alarmTime, mRenewIntent);
+ Log.d(TAG, "Scheduling renewal in " + ((alarmTime - now) / 1000) + "s");
+ }
+
+ private void notifyLease() {
+ mController.sendMessage(DhcpStateMachine.CMD_POST_DHCP_ACTION,
+ DhcpStateMachine.DHCP_SUCCESS, 0, mDhcpLease);
+ }
+
+ private void notifyFailure() {
+ mController.sendMessage(DhcpStateMachine.CMD_POST_DHCP_ACTION,
+ DhcpStateMachine.DHCP_FAILURE, 0, null);
+ }
+
+ private void clearDhcpState() {
+ mDhcpLease = null;
+ mDhcpLeaseExpiry = 0;
+ mOffer = null;
+ }
+
+ /**
+ * Quit the DhcpStateMachine.
+ *
+ * @hide
+ */
+ @Override
+ public void doQuit() {
+ Log.d(TAG, "doQuit");
+ quit();
+ }
+
+ protected void onQuitting() {
+ Log.d(TAG, "onQuitting");
+ mController.sendMessage(DhcpStateMachine.CMD_ON_QUIT);
+ }
+
+ private void maybeLog(String msg) {
+ if (DBG) Log.d(TAG, msg);
+ }
+
+ abstract class LoggingState extends State {
+ public void enter() {
+ if (STATE_DBG) Log.d(TAG, "Entering state " + getName());
+ }
+
+ private String messageName(int what) {
+ switch (what) {
+ case DhcpStateMachine.CMD_START_DHCP:
+ return "CMD_START_DHCP";
+ case DhcpStateMachine.CMD_STOP_DHCP:
+ return "CMD_STOP_DHCP";
+ case DhcpStateMachine.CMD_RENEW_DHCP:
+ return "CMD_RENEW_DHCP";
+ case DhcpStateMachine.CMD_PRE_DHCP_ACTION:
+ return "CMD_PRE_DHCP_ACTION";
+ case DhcpStateMachine.CMD_PRE_DHCP_ACTION_COMPLETE:
+ return "CMD_PRE_DHCP_ACTION_COMPLETE";
+ case DhcpStateMachine.CMD_POST_DHCP_ACTION:
+ return "CMD_POST_DHCP_ACTION";
+ case CMD_KICK:
+ return "CMD_KICK";
+ case CMD_RECEIVED_PACKET:
+ return "CMD_RECEIVED_PACKET";
+ default:
+ return Integer.toString(what);
+ }
+ }
+
+ private String messageToString(Message message) {
+ long now = SystemClock.uptimeMillis();
+ StringBuilder b = new StringBuilder(" ");
+ TimeUtils.formatDuration(message.getWhen() - now, b);
+ b.append(" ").append(messageName(message.what))
+ .append(" ").append(message.arg1)
+ .append(" ").append(message.arg2)
+ .append(" ").append(message.obj);
+ return b.toString();
+ }
+
+ @Override
+ public boolean processMessage(Message message) {
+ if (MSG_DBG) {
+ Log.d(TAG, getName() + messageToString(message));
+ }
+ return NOT_HANDLED;
+ }
+ }
+
+ // Sends CMD_PRE_DHCP_ACTION to the controller, waits for the controller to respond with
+ // CMD_PRE_DHCP_ACTION_COMPLETE, and then transitions to mOtherState.
+ abstract class WaitBeforeOtherState extends LoggingState {
+ protected State mOtherState;
+
+ @Override
+ public void enter() {
+ super.enter();
+ mController.sendMessage(DhcpStateMachine.CMD_PRE_DHCP_ACTION);
+ }
+
+ @Override
+ public boolean processMessage(Message message) {
+ super.processMessage(message);
+ switch (message.what) {
+ case DhcpStateMachine.CMD_PRE_DHCP_ACTION_COMPLETE:
+ transitionTo(mOtherState);
+ return HANDLED;
+ default:
+ return NOT_HANDLED;
+ }
+ }
+ }
+
+ class StoppedState extends LoggingState {
+ @Override
+ public boolean processMessage(Message message) {
+ super.processMessage(message);
+ switch (message.what) {
+ case DhcpStateMachine.CMD_START_DHCP:
+ if (mRegisteredForPreDhcpNotification) {
+ transitionTo(mWaitBeforeStartState);
+ } else {
+ transitionTo(mDhcpInitState);
+ }
+ return HANDLED;
+ default:
+ return NOT_HANDLED;
+ }
+ }
+ }
+
+ class WaitBeforeStartState extends WaitBeforeOtherState {
+ public WaitBeforeStartState(State otherState) {
+ super();
+ mOtherState = otherState;
+ }
+ }
+
+ class WaitBeforeRenewalState extends WaitBeforeOtherState {
+ public WaitBeforeRenewalState(State otherState) {
+ super();
+ mOtherState = otherState;
+ }
+ }
+
+ class DhcpState extends LoggingState {
+ @Override
+ public void enter() {
+ super.enter();
+ clearDhcpState();
+ if (initInterface() && initSockets()) {
+ mReceiveThread = new ReceiveThread();
+ mReceiveThread.start();
+ } else {
+ notifyFailure();
+ transitionTo(mStoppedState);
+ }
+ }
+
+ @Override
+ public void exit() {
+ mReceiveThread.halt(); // Also closes sockets.
+ clearDhcpState();
+ }
+
+ @Override
+ public boolean processMessage(Message message) {
+ super.processMessage(message);
+ switch (message.what) {
+ case DhcpStateMachine.CMD_STOP_DHCP:
+ transitionTo(mStoppedState);
+ return HANDLED;
+ default:
+ return NOT_HANDLED;
+ }
+ }
+ }
+
+ public boolean isValidPacket(DhcpPacket packet) {
+ // TODO: check checksum.
+ int xid = packet.getTransactionId();
+ if (xid != mTransactionId) {
+ Log.d(TAG, "Unexpected transaction ID " + xid + ", expected " + mTransactionId);
+ return false;
+ }
+ if (!Arrays.equals(packet.getClientMac(), mHwAddr)) {
+ Log.d(TAG, "MAC addr mismatch: got " +
+ HexDump.toHexString(packet.getClientMac()) + ", expected " +
+ HexDump.toHexString(packet.getClientMac()));
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Retransmits packets using jittered exponential backoff with an optional timeout. Packet
+ * transmission is triggered by CMD_KICK, which is sent by an AlarmManager alarm.
+ *
+ * Concrete subclasses must implement sendPacket, which is called when the alarm fires and a
+ * packet needs to be transmitted, and receivePacket, which is triggered by CMD_RECEIVED_PACKET
+ * sent by the receive thread. They may implement timeout, which is called when the timeout
+ * fires.
+ */
+ abstract class PacketRetransmittingState extends LoggingState {
+
+ private int mTimer;
+ protected int mTimeout = 0;
+
+ @Override
+ public void enter() {
+ super.enter();
+ initTimer();
+ maybeInitTimeout();
+ sendMessage(CMD_KICK);
+ }
+
+ @Override
+ public boolean processMessage(Message message) {
+ super.processMessage(message);
+ switch (message.what) {
+ case CMD_KICK:
+ sendPacket();
+ scheduleKick();
+ return HANDLED;
+ case CMD_RECEIVED_PACKET:
+ receivePacket((DhcpPacket) message.obj);
+ return HANDLED;
+ case CMD_TIMEOUT:
+ timeout();
+ return HANDLED;
+ default:
+ return NOT_HANDLED;
+ }
+ }
+
+ public void exit() {
+ mAlarmManager.cancel(mKickIntent);
+ mAlarmManager.cancel(mTimeoutIntent);
+ }
+
+ abstract protected boolean sendPacket();
+ abstract protected void receivePacket(DhcpPacket packet);
+ protected void timeout() {}
+
+ protected void initTimer() {
+ mTimer = FIRST_TIMEOUT_MS;
+ }
+
+ protected int jitterTimer(int baseTimer) {
+ int maxJitter = baseTimer / 10;
+ int jitter = mRandom.nextInt(2 * maxJitter) - maxJitter;
+ return baseTimer + jitter;
+ }
+
+ protected void scheduleKick() {
+ long now = SystemClock.elapsedRealtime();
+ long timeout = jitterTimer(mTimer);
+ long alarmTime = now + timeout;
+ mAlarmManager.cancel(mKickIntent);
+ mAlarmManager.setExact(AlarmManager.ELAPSED_REALTIME_WAKEUP, alarmTime, mKickIntent);
+ mTimer *= 2;
+ if (mTimer > MAX_TIMEOUT_MS) {
+ mTimer = MAX_TIMEOUT_MS;
+ }
+ }
+
+ protected void maybeInitTimeout() {
+ if (mTimeout > 0) {
+ long alarmTime = SystemClock.elapsedRealtime() + mTimeout;
+ mAlarmManager.setExact(
+ AlarmManager.ELAPSED_REALTIME_WAKEUP, alarmTime, mTimeoutIntent);
+ }
+ }
+ }
+
+ class DhcpInitState extends PacketRetransmittingState {
+ public DhcpInitState() {
+ super();
+ mTimeout = DHCP_TIMEOUT_MS;
+ }
+
+ @Override
+ public void enter() {
+ super.enter();
+ initTransactionId();
+ }
+
+ protected boolean sendPacket() {
+ return sendDiscoverPacket();
+ }
+
+ protected void timeout() {
+ maybeLog("Timeout");
+ notifyFailure();
+ }
+
+ protected void receivePacket(DhcpPacket packet) {
+ if (!isValidPacket(packet)) return;
+ if (!(packet instanceof DhcpOfferPacket)) return;
+ mOffer = packet.toDhcpResults();
+ if (mOffer != null) {
+ Log.d(TAG, "Got pending lease: " + mOffer);
+ transitionTo(mDhcpRequestingState);
+ }
+ }
+ }
+
+ // Not implemented. We request the first offer we receive.
+ class DhcpSelectingState extends LoggingState {
+ }
+
+ class DhcpRequestingState extends PacketRetransmittingState {
+ public DhcpRequestingState() {
+ super();
+ mTimeout = DHCP_TIMEOUT_MS / 2;
+ }
+
+ protected boolean sendPacket() {
+ return sendRequestPacket(
+ INADDR_ANY, // ciaddr
+ (Inet4Address) mOffer.ipAddress.getAddress(), // DHCP_REQUESTED_IP
+ (Inet4Address) mOffer.serverAddress, // DHCP_SERVER_IDENTIFIER
+ INADDR_BROADCAST); // packet destination address
+ }
+
+ protected void receivePacket(DhcpPacket packet) {
+ if (!isValidPacket(packet)) return;
+ if ((packet instanceof DhcpAckPacket)) {
+ DhcpResults results = packet.toDhcpResults();
+ if (results != null) {
+ mDhcpLease = results;
+ Log.d(TAG, "Confirmed lease: " + mDhcpLease);
+ mDhcpLeaseExpiry = SystemClock.elapsedRealtime() +
+ mDhcpLease.leaseDuration * 1000;
+ mOffer = null;
+ transitionTo(mDhcpBoundState);
+ }
+ } else if (packet instanceof DhcpNakPacket) {
+ Log.d(TAG, "Received NAK, returning to INIT");
+ mOffer = null;
+ transitionTo(mDhcpInitState);
+ }
+ }
+
+ protected void timeout() {
+ notifyFailure();
+ transitionTo(mDhcpInitState);
+ }
+ }
+
+ class DhcpBoundState extends LoggingState {
+ @Override
+ public void enter() {
+ super.enter();
+ if (!setIpAddress(mDhcpLease.ipAddress)) {
+ notifyFailure();
+ transitionTo(mStoppedState);
+ }
+ notifyLease();
+ // TODO: DhcpStateMachine only supports renewing at 50% of the lease time, and does not
+ // support rebinding. Fix this.
+ scheduleRenew();
+ }
+
+ @Override
+ public boolean processMessage(Message message) {
+ super.processMessage(message);
+ switch (message.what) {
+ case DhcpStateMachine.CMD_RENEW_DHCP:
+ if (mRegisteredForPreDhcpNotification) {
+ transitionTo(mWaitBeforeRenewalState);
+ } else {
+ transitionTo(mDhcpRenewingState);
+ }
+ return HANDLED;
+ default:
+ return NOT_HANDLED;
+ }
+ }
+ }
+
+ // TODO: timeout.
+ class DhcpRenewingState extends PacketRetransmittingState {
+ public DhcpRenewingState() {
+ super();
+ mTimeout = DHCP_TIMEOUT_MS;
+ }
+
+ @Override
+ public void enter() {
+ super.enter();
+ initTransactionId();
+ }
+
+ protected boolean sendPacket() {
+ return sendRequestPacket(
+ (Inet4Address) mDhcpLease.ipAddress.getAddress(), // ciaddr
+ INADDR_ANY, // DHCP_REQUESTED_IP
+ INADDR_ANY, // DHCP_SERVER_IDENTIFIER
+ (Inet4Address) mDhcpLease.serverAddress); // packet destination address
+ }
+
+ protected void receivePacket(DhcpPacket packet) {
+ if (!isValidPacket(packet)) return;
+ if ((packet instanceof DhcpAckPacket)) {
+ DhcpResults results = packet.toDhcpResults();
+ mDhcpLease.leaseDuration = results.leaseDuration;
+ mDhcpLeaseExpiry = SystemClock.elapsedRealtime() +
+ mDhcpLease.leaseDuration * 1000;
+ transitionTo(mDhcpBoundState);
+ } else if (packet instanceof DhcpNakPacket) {
+ transitionTo(mDhcpInitState);
+ }
+ }
+ }
+
+ // Not implemented. DhcpStateMachine does not implement it either.
+ class DhcpRebindingState extends LoggingState {
+ }
+
+ class DhcpInitRebootState extends LoggingState {
+ }
+
+ class DhcpRebootingState extends LoggingState {
+ }
+}
diff --git a/core/java/android/net/dhcp/DhcpDeclinePacket.java b/services/net/java/android/net/dhcp/DhcpDeclinePacket.java
similarity index 81%
rename from core/java/android/net/dhcp/DhcpDeclinePacket.java
rename to services/net/java/android/net/dhcp/DhcpDeclinePacket.java
index 7646eb4..9d985ac 100644
--- a/core/java/android/net/dhcp/DhcpDeclinePacket.java
+++ b/services/net/java/android/net/dhcp/DhcpDeclinePacket.java
@@ -16,7 +16,7 @@
package android.net.dhcp;
-import java.net.InetAddress;
+import java.net.Inet4Address;
import java.nio.ByteBuffer;
/**
@@ -26,8 +26,8 @@
/**
* Generates a DECLINE packet with the specified parameters.
*/
- DhcpDeclinePacket(int transId, InetAddress clientIp, InetAddress yourIp,
- InetAddress nextIp, InetAddress relayIp,
+ DhcpDeclinePacket(int transId, Inet4Address clientIp, Inet4Address yourIp,
+ Inet4Address nextIp, Inet4Address relayIp,
byte[] clientMac) {
super(transId, clientIp, yourIp, nextIp, relayIp, clientMac, false);
}
@@ -55,11 +55,4 @@
void finishPacket(ByteBuffer buffer) {
// None needed
}
-
- /**
- * Informs the state machine of the arrival of a DECLINE packet.
- */
- public void doNextOp(DhcpStateMachine machine) {
- machine.onDeclineReceived(mClientMac, mRequestedIp);
- }
}
diff --git a/core/java/android/net/dhcp/DhcpDiscoverPacket.java b/services/net/java/android/net/dhcp/DhcpDiscoverPacket.java
similarity index 73%
rename from core/java/android/net/dhcp/DhcpDiscoverPacket.java
rename to services/net/java/android/net/dhcp/DhcpDiscoverPacket.java
index 0e2d39b..a031080 100644
--- a/core/java/android/net/dhcp/DhcpDiscoverPacket.java
+++ b/services/net/java/android/net/dhcp/DhcpDiscoverPacket.java
@@ -16,7 +16,6 @@
package android.net.dhcp;
-import java.net.InetAddress;
import java.net.Inet4Address;
import java.nio.ByteBuffer;
@@ -28,8 +27,7 @@
* Generates a DISCOVER packet with the specified parameters.
*/
DhcpDiscoverPacket(int transId, byte[] clientMac, boolean broadcast) {
- super(transId, Inet4Address.ANY, Inet4Address.ANY, Inet4Address.ANY,
- Inet4Address.ANY, clientMac, broadcast);
+ super(transId, INADDR_ANY, INADDR_ANY, INADDR_ANY, INADDR_ANY, clientMac, broadcast);
}
public String toString() {
@@ -43,10 +41,8 @@
*/
public ByteBuffer buildPacket(int encap, short destUdp, short srcUdp) {
ByteBuffer result = ByteBuffer.allocate(MAX_LENGTH);
- InetAddress destIp = Inet4Address.ALL;
-
- fillInPacket(encap, Inet4Address.ALL, Inet4Address.ANY, destUdp, srcUdp,
- result, DHCP_BOOTREQUEST, true);
+ fillInPacket(encap, INADDR_BROADCAST, INADDR_ANY, destUdp,
+ srcUdp, result, DHCP_BOOTREQUEST, mBroadcast);
result.flip();
return result;
}
@@ -56,16 +52,8 @@
*/
void finishPacket(ByteBuffer buffer) {
addTlv(buffer, DHCP_MESSAGE_TYPE, DHCP_MESSAGE_TYPE_DISCOVER);
+ addCommonClientTlvs(buffer);
addTlv(buffer, DHCP_PARAMETER_LIST, mRequestedParams);
addTlvEnd(buffer);
}
-
- /**
- * Informs the state machine of the arrival of a DISCOVER packet.
- */
- public void doNextOp(DhcpStateMachine machine) {
- // currently omitted: host name
- machine.onDiscoverReceived(mBroadcast, mTransId, mClientMac,
- mRequestedParams);
- }
}
diff --git a/core/java/android/net/dhcp/DhcpInformPacket.java b/services/net/java/android/net/dhcp/DhcpInformPacket.java
similarity index 77%
rename from core/java/android/net/dhcp/DhcpInformPacket.java
rename to services/net/java/android/net/dhcp/DhcpInformPacket.java
index da73216..8bc7cdd 100644
--- a/core/java/android/net/dhcp/DhcpInformPacket.java
+++ b/services/net/java/android/net/dhcp/DhcpInformPacket.java
@@ -16,7 +16,7 @@
package android.net.dhcp;
-import java.net.InetAddress;
+import java.net.Inet4Address;
import java.nio.ByteBuffer;
/**
@@ -26,8 +26,8 @@
/**
* Generates an INFORM packet with the specified parameters.
*/
- DhcpInformPacket(int transId, InetAddress clientIp, InetAddress yourIp,
- InetAddress nextIp, InetAddress relayIp,
+ DhcpInformPacket(int transId, Inet4Address clientIp, Inet4Address yourIp,
+ Inet4Address nextIp, Inet4Address relayIp,
byte[] clientMac) {
super(transId, clientIp, yourIp, nextIp, relayIp, clientMac, false);
}
@@ -62,15 +62,4 @@
addTlv(buffer, DHCP_PARAMETER_LIST, mRequestedParams);
addTlvEnd(buffer);
}
-
- /**
- * Informs the state machine of the arrival of an INFORM packet. Not
- * used currently.
- */
- public void doNextOp(DhcpStateMachine machine) {
- InetAddress clientRequest =
- mRequestedIp == null ? mClientIp : mRequestedIp;
- machine.onInformReceived(mTransId, mClientMac, clientRequest,
- mRequestedParams);
- }
}
diff --git a/core/java/android/net/dhcp/DhcpNakPacket.java b/services/net/java/android/net/dhcp/DhcpNakPacket.java
similarity index 78%
rename from core/java/android/net/dhcp/DhcpNakPacket.java
rename to services/net/java/android/net/dhcp/DhcpNakPacket.java
index 1f340ad..1390ea7 100644
--- a/core/java/android/net/dhcp/DhcpNakPacket.java
+++ b/services/net/java/android/net/dhcp/DhcpNakPacket.java
@@ -16,7 +16,6 @@
package android.net.dhcp;
-import java.net.InetAddress;
import java.net.Inet4Address;
import java.nio.ByteBuffer;
@@ -27,10 +26,10 @@
/**
* Generates a NAK packet with the specified parameters.
*/
- DhcpNakPacket(int transId, InetAddress clientIp, InetAddress yourIp,
- InetAddress nextIp, InetAddress relayIp,
+ DhcpNakPacket(int transId, Inet4Address clientIp, Inet4Address yourIp,
+ Inet4Address nextIp, Inet4Address relayIp,
byte[] clientMac) {
- super(transId, Inet4Address.ANY, Inet4Address.ANY, nextIp, relayIp,
+ super(transId, INADDR_ANY, INADDR_ANY, nextIp, relayIp,
clientMac, false);
}
@@ -44,8 +43,8 @@
*/
public ByteBuffer buildPacket(int encap, short destUdp, short srcUdp) {
ByteBuffer result = ByteBuffer.allocate(MAX_LENGTH);
- InetAddress destIp = mClientIp;
- InetAddress srcIp = mYourIp;
+ Inet4Address destIp = mClientIp;
+ Inet4Address srcIp = mYourIp;
fillInPacket(encap, destIp, srcIp, destUdp, srcUdp, result,
DHCP_BOOTREPLY, mBroadcast);
@@ -62,11 +61,4 @@
addTlv(buffer, DHCP_MESSAGE, mMessage);
addTlvEnd(buffer);
}
-
- /**
- * Notifies the specified state machine of the newly-arrived NAK packet.
- */
- public void doNextOp(DhcpStateMachine machine) {
- machine.onNakReceived();
- }
}
diff --git a/core/java/android/net/dhcp/DhcpOfferPacket.java b/services/net/java/android/net/dhcp/DhcpOfferPacket.java
similarity index 77%
rename from core/java/android/net/dhcp/DhcpOfferPacket.java
rename to services/net/java/android/net/dhcp/DhcpOfferPacket.java
index f1c30e1..b1f3bbd 100644
--- a/core/java/android/net/dhcp/DhcpOfferPacket.java
+++ b/services/net/java/android/net/dhcp/DhcpOfferPacket.java
@@ -16,7 +16,6 @@
package android.net.dhcp;
-import java.net.InetAddress;
import java.net.Inet4Address;
import java.nio.ByteBuffer;
@@ -27,15 +26,14 @@
/**
* The IP address of the server which sent this packet.
*/
- private final InetAddress mSrcIp;
+ private final Inet4Address mSrcIp;
/**
* Generates a OFFER packet with the specified parameters.
*/
- DhcpOfferPacket(int transId, boolean broadcast, InetAddress serverAddress,
- InetAddress clientIp, byte[] clientMac) {
- super(transId, Inet4Address.ANY, clientIp, Inet4Address.ANY,
- Inet4Address.ANY, clientMac, broadcast);
+ DhcpOfferPacket(int transId, boolean broadcast, Inet4Address serverAddress,
+ Inet4Address clientIp, byte[] clientMac) {
+ super(transId, INADDR_ANY, clientIp, INADDR_ANY, INADDR_ANY, clientMac, broadcast);
mSrcIp = serverAddress;
}
@@ -44,7 +42,7 @@
String dnsServers = ", DNS servers: ";
if (mDnsServers != null) {
- for (InetAddress dnsServer: mDnsServers) {
+ for (Inet4Address dnsServer: mDnsServers) {
dnsServers += dnsServer + " ";
}
}
@@ -59,8 +57,8 @@
*/
public ByteBuffer buildPacket(int encap, short destUdp, short srcUdp) {
ByteBuffer result = ByteBuffer.allocate(MAX_LENGTH);
- InetAddress destIp = mBroadcast ? Inet4Address.ALL : mYourIp;
- InetAddress srcIp = mBroadcast ? Inet4Address.ANY : mSrcIp;
+ Inet4Address destIp = mBroadcast ? INADDR_BROADCAST : mYourIp;
+ Inet4Address srcIp = mBroadcast ? INADDR_ANY : mSrcIp;
fillInPacket(encap, destIp, srcIp, destUdp, srcUdp, result,
DHCP_BOOTREPLY, mBroadcast);
@@ -89,12 +87,4 @@
addTlv(buffer, DHCP_DNS_SERVER, mDnsServers);
addTlvEnd(buffer);
}
-
- /**
- * Notifies the state machine of the OFFER packet parameters.
- */
- public void doNextOp(DhcpStateMachine machine) {
- machine.onOfferReceived(mBroadcast, mTransId, mClientMac, mYourIp,
- mServerIdentifier);
- }
}
diff --git a/core/java/android/net/dhcp/DhcpPacket.java b/services/net/java/android/net/dhcp/DhcpPacket.java
similarity index 60%
rename from core/java/android/net/dhcp/DhcpPacket.java
rename to services/net/java/android/net/dhcp/DhcpPacket.java
index c7c25f0..a232a6e 100644
--- a/core/java/android/net/dhcp/DhcpPacket.java
+++ b/services/net/java/android/net/dhcp/DhcpPacket.java
@@ -1,13 +1,23 @@
package android.net.dhcp;
-import java.net.InetAddress;
+import android.net.DhcpResults;
+import android.net.LinkAddress;
+import android.net.NetworkUtils;
+import android.os.Build;
+import android.os.SystemProperties;
+import android.system.OsConstants;
+
+import java.io.UnsupportedEncodingException;
+import java.net.Inet4Address;
import java.net.UnknownHostException;
+import java.nio.BufferUnderflowException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.charset.StandardCharsets;
import java.nio.ShortBuffer;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.List;
/**
@@ -18,6 +28,13 @@
abstract class DhcpPacket {
protected static final String TAG = "DhcpPacket";
+ public static final Inet4Address INADDR_ANY = (Inet4Address) Inet4Address.ANY;
+ public static final Inet4Address INADDR_BROADCAST = (Inet4Address) Inet4Address.ALL;
+ public static final byte[] ETHER_BROADCAST = new byte[] {
+ (byte) 0xff, (byte) 0xff, (byte) 0xff,
+ (byte) 0xff, (byte) 0xff, (byte) 0xff,
+ };
+
/**
* Packet encapsulations.
*/
@@ -26,6 +43,14 @@
public static final int ENCAP_BOOTP = 2; // BOOTP contents only
/**
+ * Minimum length of a DHCP packet, excluding options, in the above encapsulations.
+ */
+ public static final int MIN_PACKET_LENGTH_BOOTP = 236; // See diagram in RFC 2131, section 2.
+ public static final int MIN_PACKET_LENGTH_L3 = MIN_PACKET_LENGTH_BOOTP + 20 + 8;
+ public static final int MIN_PACKET_LENGTH_L2 = MIN_PACKET_LENGTH_L3 + 14;
+
+ public static final int MAX_OPTION_LEN = 255;
+ /**
* IP layer definitions.
*/
private static final byte IP_TYPE_UDP = (byte) 0x11;
@@ -85,19 +110,19 @@
* DHCP Optional Type: DHCP Subnet Mask
*/
protected static final byte DHCP_SUBNET_MASK = 1;
- protected InetAddress mSubnetMask;
+ protected Inet4Address mSubnetMask;
/**
* DHCP Optional Type: DHCP Router
*/
protected static final byte DHCP_ROUTER = 3;
- protected InetAddress mGateway;
+ protected Inet4Address mGateway;
/**
* DHCP Optional Type: DHCP DNS Server
*/
protected static final byte DHCP_DNS_SERVER = 6;
- protected List<InetAddress> mDnsServers;
+ protected List<Inet4Address> mDnsServers;
/**
* DHCP Optional Type: DHCP Host Name
@@ -112,16 +137,22 @@
protected String mDomainName;
/**
+ * DHCP Optional Type: DHCP Interface MTU
+ */
+ protected static final byte DHCP_MTU = 26;
+ protected Short mMtu;
+
+ /**
* DHCP Optional Type: DHCP BROADCAST ADDRESS
*/
protected static final byte DHCP_BROADCAST_ADDRESS = 28;
- protected InetAddress mBroadcastAddress;
+ protected Inet4Address mBroadcastAddress;
/**
* DHCP Optional Type: DHCP Requested IP Address
*/
protected static final byte DHCP_REQUESTED_IP = 50;
- protected InetAddress mRequestedIp;
+ protected Inet4Address mRequestedIp;
/**
* DHCP Optional Type: DHCP Lease Time
@@ -146,7 +177,7 @@
* DHCP Optional Type: DHCP Server Identifier
*/
protected static final byte DHCP_SERVER_IDENTIFIER = 54;
- protected InetAddress mServerIdentifier;
+ protected Inet4Address mServerIdentifier;
/**
* DHCP Optional Type: DHCP Parameter List
@@ -161,14 +192,28 @@
protected String mMessage;
/**
+ * DHCP Optional Type: Maximum DHCP Message Size
+ */
+ protected static final byte DHCP_MAX_MESSAGE_SIZE = 57;
+ protected Short mMaxMessageSize;
+
+ /**
* DHCP Optional Type: DHCP Renewal Time Value
*/
protected static final byte DHCP_RENEWAL_TIME = 58;
+ protected Integer mT1;
+
+ /**
+ * DHCP Optional Type: Rebinding Time Value
+ */
+ protected static final byte DHCP_REBINDING_TIME = 59;
+ protected Integer mT2;
/**
* DHCP Optional Type: Vendor Class Identifier
*/
protected static final byte DHCP_VENDOR_CLASS_ID = 60;
+ protected String mVendorId;
/**
* DHCP Optional Type: DHCP Client Identifier
@@ -185,10 +230,10 @@
* proposed by the client (from an earlier DHCP negotiation) or
* supplied by the server.
*/
- protected final InetAddress mClientIp;
- protected final InetAddress mYourIp;
- private final InetAddress mNextIp;
- private final InetAddress mRelayIp;
+ protected final Inet4Address mClientIp;
+ protected final Inet4Address mYourIp;
+ private final Inet4Address mNextIp;
+ private final Inet4Address mRelayIp;
/**
* Does the client request a broadcast response?
@@ -201,13 +246,6 @@
protected final byte[] mClientMac;
/**
- * Asks the packet object to signal the next operation in the DHCP
- * protocol. The available actions are methods defined in the
- * DhcpStateMachine interface.
- */
- public abstract void doNextOp(DhcpStateMachine stateMachine);
-
- /**
* Asks the packet object to create a ByteBuffer serialization of
* the packet for transmission.
*/
@@ -220,8 +258,8 @@
*/
abstract void finishPacket(ByteBuffer buffer);
- protected DhcpPacket(int transId, InetAddress clientIp, InetAddress yourIp,
- InetAddress nextIp, InetAddress relayIp,
+ protected DhcpPacket(int transId, Inet4Address clientIp, Inet4Address yourIp,
+ Inet4Address nextIp, Inet4Address relayIp,
byte[] clientMac, boolean broadcast) {
mTransId = transId;
mClientIp = clientIp;
@@ -240,15 +278,23 @@
}
/**
+ * Returns the client MAC.
+ */
+ public byte[] getClientMac() {
+ return mClientMac;
+ }
+
+ /**
* Creates a new L3 packet (including IP header) containing the
* DHCP udp packet. This method relies upon the delegated method
* finishPacket() to insert the per-packet contents.
*/
- protected void fillInPacket(int encap, InetAddress destIp,
- InetAddress srcIp, short destUdp, short srcUdp, ByteBuffer buf,
+ protected void fillInPacket(int encap, Inet4Address destIp,
+ Inet4Address srcIp, short destUdp, short srcUdp, ByteBuffer buf,
byte requestCode, boolean broadcast) {
byte[] destIpArray = destIp.getAddress();
byte[] srcIpArray = srcIp.getAddress();
+ int ipHeaderOffset = 0;
int ipLengthOffset = 0;
int ipChecksumOffset = 0;
int endIpHeader = 0;
@@ -259,11 +305,17 @@
buf.clear();
buf.order(ByteOrder.BIG_ENDIAN);
+ if (encap == ENCAP_L2) {
+ buf.put(ETHER_BROADCAST);
+ buf.put(mClientMac);
+ buf.putShort((short) OsConstants.ETH_P_IP);
+ }
+
// if a full IP packet needs to be generated, put the IP & UDP
// headers in place, and pre-populate with artificial values
// needed to seed the IP checksum.
- if (encap == ENCAP_L3) {
- // fake IP header, used in the IP-header checksum
+ if (encap <= ENCAP_L3) {
+ ipHeaderOffset = buf.position();
buf.put(IP_VERSION_HEADER_LEN);
buf.put(IP_TOS_LOWDELAY); // tos: IPTOS_LOWDELAY
ipLengthOffset = buf.position();
@@ -322,7 +374,7 @@
// If an IP packet is being built, the IP & UDP checksums must be
// computed.
- if (encap == ENCAP_L3) {
+ if (encap <= ENCAP_L3) {
// fix UDP header: insert length
short udpLen = (short)(buf.position() - udpHeaderOffset);
buf.putShort(udpLengthOffset, udpLen);
@@ -345,10 +397,10 @@
udpHeaderOffset,
buf.position()));
// fix IP header: insert length
- buf.putShort(ipLengthOffset, (short)buf.position());
+ buf.putShort(ipLengthOffset, (short)(buf.position() - ipHeaderOffset));
// fixup IP-header checksum
buf.putShort(ipChecksumOffset,
- (short) checksum(buf, 0, 0, endIpHeader));
+ (short) checksum(buf, 0, ipHeaderOffset, endIpHeader));
}
}
@@ -356,13 +408,8 @@
* Converts a signed short value to an unsigned int value. Needed
* because Java does not have unsigned types.
*/
- private int intAbs(short v) {
- if (v < 0) {
- int r = v + 65536;
- return r;
- } else {
- return(v);
- }
+ private static int intAbs(short v) {
+ return v & 0xFFFF;
}
/**
@@ -412,7 +459,7 @@
/**
* Adds an optional parameter containing a single byte value.
*/
- protected void addTlv(ByteBuffer buf, byte type, byte value) {
+ protected static void addTlv(ByteBuffer buf, byte type, byte value) {
buf.put(type);
buf.put((byte) 1);
buf.put(value);
@@ -421,8 +468,12 @@
/**
* Adds an optional parameter containing an array of bytes.
*/
- protected void addTlv(ByteBuffer buf, byte type, byte[] payload) {
+ protected static void addTlv(ByteBuffer buf, byte type, byte[] payload) {
if (payload != null) {
+ if (payload.length > MAX_OPTION_LEN) {
+ throw new IllegalArgumentException("DHCP option too long: "
+ + payload.length + " vs. " + MAX_OPTION_LEN);
+ }
buf.put(type);
buf.put((byte) payload.length);
buf.put(payload);
@@ -432,7 +483,7 @@
/**
* Adds an optional parameter containing an IP address.
*/
- protected void addTlv(ByteBuffer buf, byte type, InetAddress addr) {
+ protected static void addTlv(ByteBuffer buf, byte type, Inet4Address addr) {
if (addr != null) {
addTlv(buf, type, addr.getAddress());
}
@@ -441,21 +492,38 @@
/**
* Adds an optional parameter containing a list of IP addresses.
*/
- protected void addTlv(ByteBuffer buf, byte type, List<InetAddress> addrs) {
- if (addrs != null && addrs.size() > 0) {
- buf.put(type);
- buf.put((byte)(4 * addrs.size()));
+ protected static void addTlv(ByteBuffer buf, byte type, List<Inet4Address> addrs) {
+ if (addrs == null || addrs.size() == 0) return;
- for (InetAddress addr : addrs) {
- buf.put(addr.getAddress());
- }
+ int optionLen = 4 * addrs.size();
+ if (optionLen > MAX_OPTION_LEN) {
+ throw new IllegalArgumentException("DHCP option too long: "
+ + optionLen + " vs. " + MAX_OPTION_LEN);
+ }
+
+ buf.put(type);
+ buf.put((byte)(optionLen));
+
+ for (Inet4Address addr : addrs) {
+ buf.put(addr.getAddress());
+ }
+ }
+
+ /**
+ * Adds an optional parameter containing a short integer
+ */
+ protected static void addTlv(ByteBuffer buf, byte type, Short value) {
+ if (value != null) {
+ buf.put(type);
+ buf.put((byte) 2);
+ buf.putShort(value.shortValue());
}
}
/**
* Adds an optional parameter containing a simple integer
*/
- protected void addTlv(ByteBuffer buf, byte type, Integer value) {
+ protected static void addTlv(ByteBuffer buf, byte type, Integer value) {
if (value != null) {
buf.put(type);
buf.put((byte) 4);
@@ -464,27 +532,36 @@
}
/**
- * Adds an optional parameter containing and ASCII string.
+ * Adds an optional parameter containing an ASCII string.
*/
- protected void addTlv(ByteBuffer buf, byte type, String str) {
- if (str != null) {
- buf.put(type);
- buf.put((byte) str.length());
-
- for (int i = 0; i < str.length(); i++) {
- buf.put((byte) str.charAt(i));
- }
+ protected static void addTlv(ByteBuffer buf, byte type, String str) {
+ try {
+ addTlv(buf, type, str.getBytes("US-ASCII"));
+ } catch (UnsupportedEncodingException e) {
+ throw new IllegalArgumentException("String is not US-ASCII: " + str);
}
}
/**
* Adds the special end-of-optional-parameters indicator.
*/
- protected void addTlvEnd(ByteBuffer buf) {
+ protected static void addTlvEnd(ByteBuffer buf) {
buf.put((byte) 0xFF);
}
/**
+ * Adds common client TLVs.
+ *
+ * TODO: Does this belong here? The alternative would be to modify all the buildXyzPacket
+ * methods to take them.
+ */
+ protected void addCommonClientTlvs(ByteBuffer buf) {
+ addTlv(buf, DHCP_MAX_MESSAGE_SIZE, (short) MAX_LENGTH);
+ addTlv(buf, DHCP_VENDOR_CLASS_ID, "android-dhcp-" + Build.VERSION.RELEASE);
+ addTlv(buf, DHCP_HOST_NAME, SystemProperties.get("net.hostname"));
+ }
+
+ /**
* Converts a MAC from an array of octets to an ASCII string.
*/
public static String macToString(byte[] mac) {
@@ -515,13 +592,13 @@
* Reads a four-octet value from a ByteBuffer and construct
* an IPv4 address from that value.
*/
- private static InetAddress readIpAddress(ByteBuffer packet) {
- InetAddress result = null;
+ private static Inet4Address readIpAddress(ByteBuffer packet) {
+ Inet4Address result = null;
byte[] ipAddr = new byte[4];
packet.get(ipAddr);
try {
- result = InetAddress.getByAddress(ipAddr);
+ result = (Inet4Address) Inet4Address.getByAddress(ipAddr);
} catch (UnknownHostException ex) {
// ipAddr is numeric, so this should not be
// triggered. However, if it is, just nullify
@@ -553,25 +630,34 @@
{
// bootp parameters
int transactionId;
- InetAddress clientIp;
- InetAddress yourIp;
- InetAddress nextIp;
- InetAddress relayIp;
+ Inet4Address clientIp;
+ Inet4Address yourIp;
+ Inet4Address nextIp;
+ Inet4Address relayIp;
byte[] clientMac;
- List<InetAddress> dnsServers = new ArrayList<InetAddress>();
- InetAddress gateway = null; // aka router
- Integer leaseTime = null;
- InetAddress serverIdentifier = null;
- InetAddress netMask = null;
+ List<Inet4Address> dnsServers = new ArrayList<Inet4Address>();
+ Inet4Address gateway = null; // aka router
+ Inet4Address serverIdentifier = null;
+ Inet4Address netMask = null;
String message = null;
String vendorId = null;
byte[] expectedParams = null;
String hostName = null;
String domainName = null;
- InetAddress ipSrc = null;
- InetAddress ipDst = null;
- InetAddress bcAddr = null;
- InetAddress requestedIp = null;
+ Inet4Address ipSrc = null;
+ Inet4Address ipDst = null;
+ Inet4Address bcAddr = null;
+ Inet4Address requestedIp = null;
+
+ // The following are all unsigned integers. Internally we store them as signed integers of
+ // the same length because that way we're guaranteed that they can't be out of the range of
+ // the unsigned field in the packet. Callers wanting to pass in an unsigned value will need
+ // to cast it.
+ Short mtu = null;
+ Short maxMessageSize = null;
+ Integer leaseTime = null;
+ Integer T1 = null;
+ Integer T2 = null;
// dhcp options
byte dhcpType = (byte) 0xFF;
@@ -580,7 +666,10 @@
// check to see if we need to parse L2, IP, and UDP encaps
if (pktType == ENCAP_L2) {
- // System.out.println("buffer len " + packet.limit());
+ if (packet.remaining() < MIN_PACKET_LENGTH_L2) {
+ return null;
+ }
+
byte[] l2dst = new byte[6];
byte[] l2src = new byte[6];
@@ -589,13 +678,21 @@
short l2type = packet.getShort();
- if (l2type != 0x0800)
+ if (l2type != OsConstants.ETH_P_IP)
return null;
}
- if ((pktType == ENCAP_L2) || (pktType == ENCAP_L3)) {
- // assume l2type is 0x0800, i.e. IP
- byte ipType = packet.get();
+ if (pktType <= ENCAP_L3) {
+ if (packet.remaining() < MIN_PACKET_LENGTH_L3) {
+ return null;
+ }
+
+ byte ipTypeAndLength = packet.get();
+ int ipVersion = (ipTypeAndLength & 0xf0) >> 4;
+ if (ipVersion != 4) {
+ return null;
+ }
+
// System.out.println("ipType is " + ipType);
byte ipDiffServicesField = packet.get();
short ipTotalLength = packet.getShort();
@@ -612,6 +709,14 @@
if (ipProto != IP_TYPE_UDP) // UDP
return null;
+ // Skip options. This cannot cause us to read beyond the end of the buffer because the
+ // IPv4 header cannot be more than (0x0f * 4) = 60 bytes long, and that is less than
+ // MIN_PACKET_LENGTH_L3.
+ int optionWords = ((ipTypeAndLength & 0x0f) - 5);
+ for (int i = 0; i < optionWords; i++) {
+ packet.getInt();
+ }
+
// assume UDP
short udpSrcPort = packet.getShort();
short udpDstPort = packet.getShort();
@@ -622,7 +727,11 @@
return null;
}
- // assume bootp
+ // We need to check the length even for ENCAP_L3 because the IPv4 header is variable-length.
+ if (pktType > ENCAP_BOOTP || packet.remaining() < MIN_PACKET_LENGTH_BOOTP) {
+ return null;
+ }
+
byte type = packet.get();
byte hwType = packet.get();
byte addrLen = packet.get();
@@ -635,13 +744,13 @@
try {
packet.get(ipv4addr);
- clientIp = InetAddress.getByAddress(ipv4addr);
+ clientIp = (Inet4Address) Inet4Address.getByAddress(ipv4addr);
packet.get(ipv4addr);
- yourIp = InetAddress.getByAddress(ipv4addr);
+ yourIp = (Inet4Address) Inet4Address.getByAddress(ipv4addr);
packet.get(ipv4addr);
- nextIp = InetAddress.getByAddress(ipv4addr);
+ nextIp = (Inet4Address) Inet4Address.getByAddress(ipv4addr);
packet.get(ipv4addr);
- relayIp = InetAddress.getByAddress(ipv4addr);
+ relayIp = (Inet4Address) Inet4Address.getByAddress(ipv4addr);
} catch (UnknownHostException ex) {
return null;
}
@@ -663,88 +772,105 @@
boolean notFinishedOptions = true;
while ((packet.position() < packet.limit()) && notFinishedOptions) {
- byte optionType = packet.get();
+ try {
+ byte optionType = packet.get();
- if (optionType == (byte) 0xFF) {
- notFinishedOptions = false;
- } else {
- byte optionLen = packet.get();
- int expectedLen = 0;
+ if (optionType == (byte) 0xFF) {
+ notFinishedOptions = false;
+ } else {
+ int optionLen = packet.get() & 0xFF;
+ int expectedLen = 0;
- switch(optionType) {
- case DHCP_SUBNET_MASK:
- netMask = readIpAddress(packet);
- expectedLen = 4;
- break;
- case DHCP_ROUTER:
- gateway = readIpAddress(packet);
- expectedLen = 4;
- break;
- case DHCP_DNS_SERVER:
- expectedLen = 0;
+ switch(optionType) {
+ case DHCP_SUBNET_MASK:
+ netMask = readIpAddress(packet);
+ expectedLen = 4;
+ break;
+ case DHCP_ROUTER:
+ gateway = readIpAddress(packet);
+ expectedLen = 4;
+ break;
+ case DHCP_DNS_SERVER:
+ for (expectedLen = 0; expectedLen < optionLen; expectedLen += 4) {
+ dnsServers.add(readIpAddress(packet));
+ }
+ break;
+ case DHCP_HOST_NAME:
+ expectedLen = optionLen;
+ hostName = readAsciiString(packet, optionLen);
+ break;
+ case DHCP_MTU:
+ expectedLen = 2;
+ mtu = Short.valueOf(packet.getShort());
+ break;
+ case DHCP_DOMAIN_NAME:
+ expectedLen = optionLen;
+ domainName = readAsciiString(packet, optionLen);
+ break;
+ case DHCP_BROADCAST_ADDRESS:
+ bcAddr = readIpAddress(packet);
+ expectedLen = 4;
+ break;
+ case DHCP_REQUESTED_IP:
+ requestedIp = readIpAddress(packet);
+ expectedLen = 4;
+ break;
+ case DHCP_LEASE_TIME:
+ leaseTime = Integer.valueOf(packet.getInt());
+ expectedLen = 4;
+ break;
+ case DHCP_MESSAGE_TYPE:
+ dhcpType = packet.get();
+ expectedLen = 1;
+ break;
+ case DHCP_SERVER_IDENTIFIER:
+ serverIdentifier = readIpAddress(packet);
+ expectedLen = 4;
+ break;
+ case DHCP_PARAMETER_LIST:
+ expectedParams = new byte[optionLen];
+ packet.get(expectedParams);
+ expectedLen = optionLen;
+ break;
+ case DHCP_MESSAGE:
+ expectedLen = optionLen;
+ message = readAsciiString(packet, optionLen);
+ break;
+ case DHCP_MAX_MESSAGE_SIZE:
+ expectedLen = 2;
+ maxMessageSize = Short.valueOf(packet.getShort());
+ break;
+ case DHCP_RENEWAL_TIME:
+ expectedLen = 4;
+ T1 = Integer.valueOf(packet.getInt());
+ break;
+ case DHCP_REBINDING_TIME:
+ expectedLen = 4;
+ T2 = Integer.valueOf(packet.getInt());
+ break;
+ case DHCP_VENDOR_CLASS_ID:
+ expectedLen = optionLen;
+ vendorId = readAsciiString(packet, optionLen);
+ break;
+ case DHCP_CLIENT_IDENTIFIER: { // Client identifier
+ byte[] id = new byte[optionLen];
+ packet.get(id);
+ expectedLen = optionLen;
+ } break;
+ default:
+ // ignore any other parameters
+ for (int i = 0; i < optionLen; i++) {
+ expectedLen++;
+ byte throwaway = packet.get();
+ }
+ }
- for (expectedLen = 0; expectedLen < optionLen;
- expectedLen += 4) {
- dnsServers.add(readIpAddress(packet));
- }
- break;
- case DHCP_HOST_NAME:
- expectedLen = optionLen;
- hostName = readAsciiString(packet, optionLen);
- break;
- case DHCP_DOMAIN_NAME:
- expectedLen = optionLen;
- domainName = readAsciiString(packet, optionLen);
- break;
- case DHCP_BROADCAST_ADDRESS:
- bcAddr = readIpAddress(packet);
- expectedLen = 4;
- break;
- case DHCP_REQUESTED_IP:
- requestedIp = readIpAddress(packet);
- expectedLen = 4;
- break;
- case DHCP_LEASE_TIME:
- leaseTime = Integer.valueOf(packet.getInt());
- expectedLen = 4;
- break;
- case DHCP_MESSAGE_TYPE:
- dhcpType = packet.get();
- expectedLen = 1;
- break;
- case DHCP_SERVER_IDENTIFIER:
- serverIdentifier = readIpAddress(packet);
- expectedLen = 4;
- break;
- case DHCP_PARAMETER_LIST:
- expectedParams = new byte[optionLen];
- packet.get(expectedParams);
- expectedLen = optionLen;
- break;
- case DHCP_MESSAGE:
- expectedLen = optionLen;
- message = readAsciiString(packet, optionLen);
- break;
- case DHCP_VENDOR_CLASS_ID:
- expectedLen = optionLen;
- vendorId = readAsciiString(packet, optionLen);
- break;
- case DHCP_CLIENT_IDENTIFIER: { // Client identifier
- byte[] id = new byte[optionLen];
- packet.get(id);
- expectedLen = optionLen;
- } break;
- default:
- // ignore any other parameters
- for (int i = 0; i < optionLen; i++) {
- expectedLen++;
- byte throwaway = packet.get();
- }
+ if (expectedLen != optionLen) {
+ return null;
+ }
}
-
- if (expectedLen != optionLen) {
- return null;
- }
+ } catch (BufferUnderflowException e) {
+ return null;
}
}
@@ -795,23 +921,67 @@
newPacket.mHostName = hostName;
newPacket.mLeaseTime = leaseTime;
newPacket.mMessage = message;
+ newPacket.mMtu = mtu;
newPacket.mRequestedIp = requestedIp;
newPacket.mRequestedParams = expectedParams;
newPacket.mServerIdentifier = serverIdentifier;
newPacket.mSubnetMask = netMask;
+ newPacket.mMaxMessageSize = maxMessageSize;
+ newPacket.mT1 = T1;
+ newPacket.mT2 = T2;
+ newPacket.mVendorId = vendorId;
return newPacket;
}
/**
- * Parse a packet from an array of bytes.
+ * Parse a packet from an array of bytes, stopping at the given length.
*/
- public static DhcpPacket decodeFullPacket(byte[] packet, int pktType)
+ public static DhcpPacket decodeFullPacket(byte[] packet, int length, int pktType)
{
- ByteBuffer buffer = ByteBuffer.wrap(packet).order(ByteOrder.BIG_ENDIAN);
+ ByteBuffer buffer = ByteBuffer.wrap(packet, 0, length).order(ByteOrder.BIG_ENDIAN);
return decodeFullPacket(buffer, pktType);
}
/**
+ * Construct a DhcpResults object from a DHCP reply packet.
+ */
+ public DhcpResults toDhcpResults() {
+ Inet4Address ipAddress = mYourIp;
+ if (ipAddress == Inet4Address.ANY) {
+ ipAddress = mClientIp;
+ if (ipAddress == Inet4Address.ANY) {
+ return null;
+ }
+ }
+
+ int prefixLength;
+ if (mSubnetMask != null) {
+ try {
+ prefixLength = NetworkUtils.netmaskToPrefixLength(mSubnetMask);
+ } catch (IllegalArgumentException e) {
+ // Non-contiguous netmask.
+ return null;
+ }
+ } else {
+ prefixLength = NetworkUtils.getImplicitNetmask(ipAddress);
+ }
+
+ DhcpResults results = new DhcpResults();
+ try {
+ results.ipAddress = new LinkAddress(ipAddress, prefixLength);
+ } catch (IllegalArgumentException e) {
+ return null;
+ }
+ results.gateway = mGateway;
+ results.dnsServers.addAll(mDnsServers);
+ results.domains = mDomainName;
+ results.serverAddress = mServerIdentifier;
+ results.vendorInfo = mVendorId;
+ results.leaseDuration = mLeaseTime;
+ return results;
+ }
+
+ /**
* Builds a DHCP-DISCOVER packet from the required specified
* parameters.
*/
@@ -828,10 +998,10 @@
* parameters.
*/
public static ByteBuffer buildOfferPacket(int encap, int transactionId,
- boolean broadcast, InetAddress serverIpAddr, InetAddress clientIpAddr,
- byte[] mac, Integer timeout, InetAddress netMask, InetAddress bcAddr,
- InetAddress gateway, List<InetAddress> dnsServers,
- InetAddress dhcpServerIdentifier, String domainName) {
+ boolean broadcast, Inet4Address serverIpAddr, Inet4Address clientIpAddr,
+ byte[] mac, Integer timeout, Inet4Address netMask, Inet4Address bcAddr,
+ Inet4Address gateway, List<Inet4Address> dnsServers,
+ Inet4Address dhcpServerIdentifier, String domainName) {
DhcpPacket pkt = new DhcpOfferPacket(
transactionId, broadcast, serverIpAddr, clientIpAddr, mac);
pkt.mGateway = gateway;
@@ -848,10 +1018,10 @@
* Builds a DHCP-ACK packet from the required specified parameters.
*/
public static ByteBuffer buildAckPacket(int encap, int transactionId,
- boolean broadcast, InetAddress serverIpAddr, InetAddress clientIpAddr,
- byte[] mac, Integer timeout, InetAddress netMask, InetAddress bcAddr,
- InetAddress gateway, List<InetAddress> dnsServers,
- InetAddress dhcpServerIdentifier, String domainName) {
+ boolean broadcast, Inet4Address serverIpAddr, Inet4Address clientIpAddr,
+ byte[] mac, Integer timeout, Inet4Address netMask, Inet4Address bcAddr,
+ Inet4Address gateway, List<Inet4Address> dnsServers,
+ Inet4Address dhcpServerIdentifier, String domainName) {
DhcpPacket pkt = new DhcpAckPacket(
transactionId, broadcast, serverIpAddr, clientIpAddr, mac);
pkt.mGateway = gateway;
@@ -868,7 +1038,7 @@
* Builds a DHCP-NAK packet from the required specified parameters.
*/
public static ByteBuffer buildNakPacket(int encap, int transactionId,
- InetAddress serverIpAddr, InetAddress clientIpAddr, byte[] mac) {
+ Inet4Address serverIpAddr, Inet4Address clientIpAddr, byte[] mac) {
DhcpPacket pkt = new DhcpNakPacket(transactionId, clientIpAddr,
serverIpAddr, serverIpAddr, serverIpAddr, mac);
pkt.mMessage = "requested address not available";
@@ -880,9 +1050,9 @@
* Builds a DHCP-REQUEST packet from the required specified parameters.
*/
public static ByteBuffer buildRequestPacket(int encap,
- int transactionId, InetAddress clientIp, boolean broadcast,
- byte[] clientMac, InetAddress requestedIpAddress,
- InetAddress serverIdentifier, byte[] requestedParams, String hostName) {
+ int transactionId, Inet4Address clientIp, boolean broadcast,
+ byte[] clientMac, Inet4Address requestedIpAddress,
+ Inet4Address serverIdentifier, byte[] requestedParams, String hostName) {
DhcpPacket pkt = new DhcpRequestPacket(transactionId, clientIp,
clientMac, broadcast);
pkt.mRequestedIp = requestedIpAddress;
diff --git a/core/java/android/net/dhcp/DhcpRequestPacket.java b/services/net/java/android/net/dhcp/DhcpRequestPacket.java
similarity index 69%
rename from core/java/android/net/dhcp/DhcpRequestPacket.java
rename to services/net/java/android/net/dhcp/DhcpRequestPacket.java
index cf32957..42b7b0c 100644
--- a/core/java/android/net/dhcp/DhcpRequestPacket.java
+++ b/services/net/java/android/net/dhcp/DhcpRequestPacket.java
@@ -18,7 +18,6 @@
import android.util.Log;
-import java.net.InetAddress;
import java.net.Inet4Address;
import java.nio.ByteBuffer;
@@ -29,10 +28,9 @@
/**
* Generates a REQUEST packet with the specified parameters.
*/
- DhcpRequestPacket(int transId, InetAddress clientIp, byte[] clientMac,
+ DhcpRequestPacket(int transId, Inet4Address clientIp, byte[] clientMac,
boolean broadcast) {
- super(transId, clientIp, Inet4Address.ANY, Inet4Address.ANY,
- Inet4Address.ANY, clientMac, broadcast);
+ super(transId, clientIp, INADDR_ANY, INADDR_ANY, INADDR_ANY, clientMac, broadcast);
}
public String toString() {
@@ -48,7 +46,7 @@
public ByteBuffer buildPacket(int encap, short destUdp, short srcUdp) {
ByteBuffer result = ByteBuffer.allocate(MAX_LENGTH);
- fillInPacket(encap, Inet4Address.ALL, Inet4Address.ANY, destUdp, srcUdp,
+ fillInPacket(encap, INADDR_BROADCAST, INADDR_ANY, destUdp, srcUdp,
result, DHCP_BOOTREQUEST, mBroadcast);
result.flip();
return result;
@@ -65,22 +63,15 @@
System.arraycopy(mClientMac, 0, clientId, 1, 6);
addTlv(buffer, DHCP_MESSAGE_TYPE, DHCP_MESSAGE_TYPE_REQUEST);
- addTlv(buffer, DHCP_PARAMETER_LIST, mRequestedParams);
- addTlv(buffer, DHCP_REQUESTED_IP, mRequestedIp);
- addTlv(buffer, DHCP_SERVER_IDENTIFIER, mServerIdentifier);
+ if (!INADDR_ANY.equals(mRequestedIp)) {
+ addTlv(buffer, DHCP_REQUESTED_IP, mRequestedIp);
+ }
+ if (!INADDR_ANY.equals(mServerIdentifier)) {
+ addTlv(buffer, DHCP_SERVER_IDENTIFIER, mServerIdentifier);
+ }
addTlv(buffer, DHCP_CLIENT_IDENTIFIER, clientId);
+ addCommonClientTlvs(buffer);
+ addTlv(buffer, DHCP_PARAMETER_LIST, mRequestedParams);
addTlvEnd(buffer);
}
-
- /**
- * Notifies the specified state machine of the REQUEST packet parameters.
- */
- public void doNextOp(DhcpStateMachine machine) {
- InetAddress clientRequest =
- mRequestedIp == null ? mClientIp : mRequestedIp;
- Log.v(TAG, "requested IP is " + mRequestedIp + " and client IP is " +
- mClientIp);
- machine.onRequestReceived(mBroadcast, mTransId, mClientMac,
- clientRequest, mRequestedParams, mHostName);
- }
}
diff --git a/services/tests/servicestests/src/com/android/server/ConnectivityServiceTest.java b/services/tests/servicestests/src/com/android/server/ConnectivityServiceTest.java
index beb353a..c198900 100644
--- a/services/tests/servicestests/src/com/android/server/ConnectivityServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/ConnectivityServiceTest.java
@@ -20,7 +20,6 @@
import static android.net.ConnectivityManager.TYPE_MOBILE;
import static android.net.ConnectivityManager.TYPE_WIFI;
import static android.net.ConnectivityManager.getNetworkTypeName;
-import static android.net.NetworkStateTracker.EVENT_STATE_CHANGED;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Matchers.eq;
import static org.mockito.Matchers.isA;
diff --git a/telecomm/java/android/telecom/AuthenticatorService.java b/telecomm/java/android/telecom/AuthenticatorService.java
new file mode 100644
index 0000000..39717c3
--- /dev/null
+++ b/telecomm/java/android/telecom/AuthenticatorService.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2015 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.telecom;
+import android.accounts.AbstractAccountAuthenticator;
+import android.accounts.Account;
+import android.accounts.AccountAuthenticatorResponse;
+import android.accounts.NetworkErrorException;
+import android.app.Service;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Bundle;
+import android.os.IBinder;
+
+/**
+ * A generic stub account authenticator service often used for sync adapters that do not directly
+ * involve accounts.
+ */
+public class AuthenticatorService extends Service {
+ private static Authenticator mAuthenticator;
+
+ @Override
+ public void onCreate() {
+ mAuthenticator = new Authenticator(this);
+ }
+
+ @Override
+ public IBinder onBind(Intent intent) {
+ return mAuthenticator.getIBinder();
+ }
+
+ /**
+ * Stub account authenticator. All methods either return null or throw an exception.
+ */
+ public class Authenticator extends AbstractAccountAuthenticator {
+ public Authenticator(Context context) {
+ super(context);
+ }
+
+ @Override
+ public Bundle editProperties(AccountAuthenticatorResponse accountAuthenticatorResponse,
+ String s) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public Bundle addAccount(AccountAuthenticatorResponse accountAuthenticatorResponse,
+ String s, String s2, String[] strings, Bundle bundle)
+ throws NetworkErrorException {
+ return null;
+ }
+
+ @Override
+ public Bundle confirmCredentials(AccountAuthenticatorResponse accountAuthenticatorResponse,
+ Account account, Bundle bundle)
+ throws NetworkErrorException {
+ return null;
+ }
+
+ @Override
+ public Bundle getAuthToken(AccountAuthenticatorResponse accountAuthenticatorResponse,
+ Account account, String s, Bundle bundle)
+ throws NetworkErrorException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public String getAuthTokenLabel(String s) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public Bundle updateCredentials(AccountAuthenticatorResponse accountAuthenticatorResponse,
+ Account account, String s, Bundle bundle)
+ throws NetworkErrorException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public Bundle hasFeatures(AccountAuthenticatorResponse accountAuthenticatorResponse,
+ Account account, String[] strings)
+ throws NetworkErrorException {
+ throw new UnsupportedOperationException();
+ }
+ }
+}
diff --git a/telecomm/java/android/telecom/Call.java b/telecomm/java/android/telecom/Call.java
index c1d2f9b..436f20a 100644
--- a/telecomm/java/android/telecom/Call.java
+++ b/telecomm/java/android/telecom/Call.java
@@ -141,28 +141,42 @@
public static final int CAPABILITY_MANAGE_CONFERENCE = 0x00000080;
/**
- * Local device supports video telephony.
+ * Local device supports receiving video.
* @hide
*/
- public static final int CAPABILITY_SUPPORTS_VT_LOCAL = 0x00000100;
+ public static final int CAPABILITY_SUPPORTS_VT_LOCAL_RX = 0x00000100;
/**
- * Remote device supports video telephony.
+ * Local device supports transmitting video.
* @hide
*/
- public static final int CAPABILITY_SUPPORTS_VT_REMOTE = 0x00000200;
+ public static final int CAPABILITY_SUPPORTS_VT_LOCAL_TX = 0x00000200;
/**
- * Call is using high definition audio.
+ * Local device supports bidirectional video calling.
* @hide
*/
- public static final int CAPABILITY_HIGH_DEF_AUDIO = 0x00000400;
+ public static final int CAPABILITY_SUPPORTS_VT_LOCAL =
+ CAPABILITY_SUPPORTS_VT_LOCAL_RX | CAPABILITY_SUPPORTS_VT_LOCAL_TX;
/**
- * Call is using WIFI.
+ * Remote device supports receiving video.
* @hide
*/
- public static final int CAPABILITY_WIFI = 0x00000800;
+ public static final int CAPABILITY_SUPPORTS_VT_REMOTE_RX = 0x00000400;
+
+ /**
+ * Remote device supports transmitting video.
+ * @hide
+ */
+ public static final int CAPABILITY_SUPPORTS_VT_REMOTE_TX = 0x00000800;
+
+ /**
+ * Remote device supports bidirectional video calling.
+ * @hide
+ */
+ public static final int CAPABILITY_SUPPORTS_VT_REMOTE =
+ CAPABILITY_SUPPORTS_VT_REMOTE_RX | CAPABILITY_SUPPORTS_VT_REMOTE_TX;
/**
* Call is able to be separated from its parent {@code Conference}, if any.
@@ -183,10 +197,37 @@
public static final int CAPABILITY_GENERIC_CONFERENCE = 0x00004000;
/**
+ * Call is using high definition audio.
+ * @hide
+ */
+ public static final int CAPABILITY_HIGH_DEF_AUDIO = 0x00008000;
+
+ /**
+ * Call is using WIFI.
+ * @hide
+ */
+ public static final int CAPABILITY_WIFI = 0x00010000;
+
+ //******************************************************************************************
+ // Next CAPABILITY value: 0x00020000
+ //******************************************************************************************
+
+ /**
+ * Indicates that the current device callback number should be shown.
+ *
+ * @hide
+ */
+ public static final int CAPABILITY_SHOW_CALLBACK_NUMBER = 0x00020000;
+
+ /**
* Speed up audio setup for MT call.
* @hide
*/
- public static final int CAPABILITY_SPEED_UP_MT_AUDIO = 0x00008000;
+ public static final int CAPABILITY_SPEED_UP_MT_AUDIO = 0x00040000;
+
+ //******************************************************************************************
+ // Next CAPABILITY value: 0x00080000
+ //******************************************************************************************
private final Uri mHandle;
private final int mHandlePresentation;
@@ -255,9 +296,21 @@
if (can(capabilities, CAPABILITY_MANAGE_CONFERENCE)) {
builder.append(" CAPABILITY_MANAGE_CONFERENCE");
}
+ if (can(capabilities, CAPABILITY_SUPPORTS_VT_LOCAL_RX)) {
+ builder.append(" CAPABILITY_SUPPORTS_VT_LOCAL_RX");
+ }
+ if (can(capabilities, CAPABILITY_SUPPORTS_VT_LOCAL_TX)) {
+ builder.append(" CAPABILITY_SUPPORTS_VT_LOCAL_TX");
+ }
if (can(capabilities, CAPABILITY_SUPPORTS_VT_LOCAL)) {
builder.append(" CAPABILITY_SUPPORTS_VT_LOCAL");
}
+ if (can(capabilities, CAPABILITY_SUPPORTS_VT_REMOTE_RX)) {
+ builder.append(" CAPABILITY_SUPPORTS_VT_REMOTE_RX");
+ }
+ if (can(capabilities, CAPABILITY_SUPPORTS_VT_REMOTE_TX)) {
+ builder.append(" CAPABILITY_SUPPORTS_VT_REMOTE_TX");
+ }
if (can(capabilities, CAPABILITY_SUPPORTS_VT_REMOTE)) {
builder.append(" CAPABILITY_SUPPORTS_VT_REMOTE");
}
@@ -270,8 +323,11 @@
if (can(capabilities, CAPABILITY_GENERIC_CONFERENCE)) {
builder.append(" CAPABILITY_GENERIC_CONFERENCE");
}
+ if (can(capabilities, CAPABILITY_SHOW_CALLBACK_NUMBER)) {
+ builder.append(" CAPABILITY_SHOW_CALLBACK_NUMBER");
+ }
if (can(capabilities, CAPABILITY_SPEED_UP_MT_AUDIO)) {
- builder.append(" CAPABILITY_SPEED_UP_IMS_MT_AUDIO");
+ builder.append(" CAPABILITY_SPEED_UP_MT_AUDIO");
}
builder.append("]");
return builder.toString();
diff --git a/telecomm/java/android/telecom/Connection.java b/telecomm/java/android/telecom/Connection.java
index 569163a..bab064e 100644
--- a/telecomm/java/android/telecom/Connection.java
+++ b/telecomm/java/android/telecom/Connection.java
@@ -106,28 +106,42 @@
public static final int CAPABILITY_MANAGE_CONFERENCE = 0x00000080;
/**
- * Local device supports video telephony.
+ * Local device supports receiving video.
* @hide
*/
- public static final int CAPABILITY_SUPPORTS_VT_LOCAL = 0x00000100;
+ public static final int CAPABILITY_SUPPORTS_VT_LOCAL_RX = 0x00000100;
/**
- * Remote device supports video telephony.
+ * Local device supports transmitting video.
* @hide
*/
- public static final int CAPABILITY_SUPPORTS_VT_REMOTE = 0x00000200;
+ public static final int CAPABILITY_SUPPORTS_VT_LOCAL_TX = 0x00000200;
/**
- * Connection is using high definition audio.
+ * Local device supports bidirectional video calling.
* @hide
*/
- public static final int CAPABILITY_HIGH_DEF_AUDIO = 0x00000400;
+ public static final int CAPABILITY_SUPPORTS_VT_LOCAL =
+ CAPABILITY_SUPPORTS_VT_LOCAL_RX | CAPABILITY_SUPPORTS_VT_LOCAL_TX;
/**
- * Connection is using WIFI.
+ * Remote device supports receiving video.
* @hide
*/
- public static final int CAPABILITY_WIFI = 0x00000800;
+ public static final int CAPABILITY_SUPPORTS_VT_REMOTE_RX = 0x00000400;
+
+ /**
+ * Remote device supports transmitting video.
+ * @hide
+ */
+ public static final int CAPABILITY_SUPPORTS_VT_REMOTE_TX = 0x00000800;
+
+ /**
+ * Remote device supports bidirectional video calling.
+ * @hide
+ */
+ public static final int CAPABILITY_SUPPORTS_VT_REMOTE =
+ CAPABILITY_SUPPORTS_VT_REMOTE_RX | CAPABILITY_SUPPORTS_VT_REMOTE_TX;
/**
* Connection is able to be separated from its parent {@code Conference}, if any.
@@ -148,10 +162,33 @@
public static final int CAPABILITY_GENERIC_CONFERENCE = 0x00004000;
/**
+ * Connection is using high definition audio.
+ * @hide
+ */
+ public static final int CAPABILITY_HIGH_DEF_AUDIO = 0x00008000;
+
+ /**
+ * Connection is using WIFI.
+ * @hide
+ */
+ public static final int CAPABILITY_WIFI = 0x00010000;
+
+ /**
+ * Indicates that the current device callback number should be shown.
+ *
+ * @hide
+ */
+ public static final int CAPABILITY_SHOW_CALLBACK_NUMBER = 0x00020000;
+
+ /**
* Speed up audio setup for MT call.
* @hide
*/
- public static final int CAPABILITY_SPEED_UP_MT_AUDIO = 0x00008000;
+ public static final int CAPABILITY_SPEED_UP_MT_AUDIO = 0x00040000;
+
+ //**********************************************************************************************
+ // Next CAPABILITY value: 0x00080000
+ //**********************************************************************************************
// Flag controlling whether PII is emitted into the logs
private static final boolean PII_DEBUG = Log.isLoggable(android.util.Log.DEBUG);
@@ -224,9 +261,21 @@
if (can(capabilities, CAPABILITY_MANAGE_CONFERENCE)) {
builder.append(" CAPABILITY_MANAGE_CONFERENCE");
}
+ if (can(capabilities, CAPABILITY_SUPPORTS_VT_LOCAL_RX)) {
+ builder.append(" CAPABILITY_SUPPORTS_VT_LOCAL_RX");
+ }
+ if (can(capabilities, CAPABILITY_SUPPORTS_VT_LOCAL_TX)) {
+ builder.append(" CAPABILITY_SUPPORTS_VT_LOCAL_TX");
+ }
if (can(capabilities, CAPABILITY_SUPPORTS_VT_LOCAL)) {
builder.append(" CAPABILITY_SUPPORTS_VT_LOCAL");
}
+ if (can(capabilities, CAPABILITY_SUPPORTS_VT_REMOTE_RX)) {
+ builder.append(" CAPABILITY_SUPPORTS_VT_REMOTE_RX");
+ }
+ if (can(capabilities, CAPABILITY_SUPPORTS_VT_REMOTE_TX)) {
+ builder.append(" CAPABILITY_SUPPORTS_VT_REMOTE_TX");
+ }
if (can(capabilities, CAPABILITY_SUPPORTS_VT_REMOTE)) {
builder.append(" CAPABILITY_SUPPORTS_VT_REMOTE");
}
@@ -239,8 +288,11 @@
if (can(capabilities, CAPABILITY_GENERIC_CONFERENCE)) {
builder.append(" CAPABILITY_GENERIC_CONFERENCE");
}
+ if (can(capabilities, CAPABILITY_SHOW_CALLBACK_NUMBER)) {
+ builder.append(" CAPABILITY_SHOW_CALLBACK_NUMBER");
+ }
if (can(capabilities, CAPABILITY_SPEED_UP_MT_AUDIO)) {
- builder.append(" CAPABILITY_SPEED_UP_IMS_MT_AUDIO");
+ builder.append(" CAPABILITY_SPEED_UP_MT_AUDIO");
}
builder.append("]");
return builder.toString();
diff --git a/telecomm/java/android/telecom/PhoneAccount.java b/telecomm/java/android/telecom/PhoneAccount.java
index 052a481..a94c2f6 100644
--- a/telecomm/java/android/telecom/PhoneAccount.java
+++ b/telecomm/java/android/telecom/PhoneAccount.java
@@ -40,15 +40,13 @@
/**
* Represents a distinct method to place or receive a phone call. Apps which can place calls and
* want those calls to be integrated into the dialer and in-call UI should build an instance of
- * this class and register it with the system using {@link TelecomManager#registerPhoneAccount}.
+ * this class and register it with the system using {@link TelecomManager}.
* <p>
* {@link TelecomManager} uses registered {@link PhoneAccount}s to present the user with
* alternative options when placing a phone call. When building a {@link PhoneAccount}, the app
- * should supply a valid {@link PhoneAccountHandle} that references the {@link ConnectionService}
+ * should supply a valid {@link PhoneAccountHandle} that references the connection service
* implementation Telecom will use to interact with the app.
- * @hide
*/
-@SystemApi
public class PhoneAccount implements Parcelable {
/**
@@ -62,7 +60,9 @@
* if the user has explicitly selected it to be used as the default connection manager.
* <p>
* See {@link #getCapabilities}
+ * @hide
*/
+ @SystemApi
public static final int CAPABILITY_CONNECTION_MANAGER = 0x1;
/**
@@ -76,6 +76,7 @@
* <p>
* {@hide}
*/
+ @SystemApi
public static final int CAPABILITY_CALL_PROVIDER = 0x2;
/**
@@ -94,6 +95,7 @@
* See {@link #getCapabilities}
* @hide
*/
+ @SystemApi
public static final int CAPABILITY_VIDEO_CALLING = 0x8;
/**
@@ -111,6 +113,7 @@
* See {@link #getCapabilities}
* @hide
*/
+ @SystemApi
public static final int CAPABILITY_MULTI_USER = 0x20;
/**
@@ -203,6 +206,7 @@
}
/** @hide */
+ @SystemApi
public Builder setAccountHandle(PhoneAccountHandle accountHandle) {
mAccountHandle = accountHandle;
return this;
@@ -333,6 +337,7 @@
* @return The builder.
* @hide
*/
+ @SystemApi
public Builder addSupportedUriScheme(String uriScheme) {
if (!TextUtils.isEmpty(uriScheme) && !mSupportedUriSchemes.contains(uriScheme)) {
this.mSupportedUriSchemes.add(uriScheme);
@@ -423,6 +428,7 @@
* @return The builder.
* @hide
*/
+ @SystemApi
public Builder toBuilder() { return new Builder(this); }
/**
diff --git a/telecomm/java/android/telecom/PhoneAccountHandle.java b/telecomm/java/android/telecom/PhoneAccountHandle.java
index 97af41a..4600b72 100644
--- a/telecomm/java/android/telecom/PhoneAccountHandle.java
+++ b/telecomm/java/android/telecom/PhoneAccountHandle.java
@@ -29,16 +29,13 @@
* The unique identifier for a {@link PhoneAccount}. A {@code PhoneAccountHandle} is made of two
* parts:
* <ul>
- * <li>The component name of the associated {@link ConnectionService}.</li>
+ * <li>The component name of the associated connection service.</li>
* <li>A string identifier that is unique across {@code PhoneAccountHandle}s with the same
* component name.</li>
* </ul>
*
- * See {@link PhoneAccount},
- * {@link TelecomManager#registerPhoneAccount TelecomManager.registerPhoneAccount}.
- * @hide
+ * See {@link PhoneAccount}, {@link TelecomManager}.
*/
-@SystemApi
public class PhoneAccountHandle implements Parcelable {
private final ComponentName mComponentName;
private final String mId;
@@ -51,6 +48,7 @@
}
/** @hide */
+ @SystemApi
public PhoneAccountHandle(
ComponentName componentName,
String id,
@@ -61,8 +59,8 @@
}
/**
- * The {@code ComponentName} of the {@link android.telecom.ConnectionService} which is
- * responsible for making phone calls using this {@code PhoneAccountHandle}.
+ * The {@code ComponentName} of the connection service which is responsible for making phone
+ * calls using this {@code PhoneAccountHandle}.
*
* @return A suitable {@code ComponentName}.
*/
@@ -72,9 +70,9 @@
/**
* A string that uniquely distinguishes this particular {@code PhoneAccountHandle} from all the
- * others supported by the {@link ConnectionService} that created it.
+ * others supported by the connection service that created it.
* <p>
- * A {@code ConnectionService} must select identifiers that are stable for the lifetime of
+ * A connection service must select identifiers that are stable for the lifetime of
* their users' relationship with their service, across many Android devices. For example, a
* good set of identifiers might be the email addresses with which with users registered for
* their accounts with a particular service. Depending on how a service chooses to operate,
@@ -82,6 +80,9 @@
* ({@code 0}, {@code 1}, {@code 2}, ...) that are generated locally on each phone and could
* collide with values generated on other phones or after a data wipe of a given phone.
*
+ * Important: A non-unique identifier could cause non-deterministic call-log backup/restore
+ * behavior.
+ *
* @return A service-specific unique identifier for this {@code PhoneAccountHandle}.
*/
public String getId() {
@@ -92,6 +93,7 @@
* @return the {@link UserHandle} to use when connecting to this PhoneAccount.
* @hide
*/
+ @SystemApi
public UserHandle getUserHandle() {
return mUserHandle;
}
diff --git a/telecomm/java/android/telecom/TelecomManager.java b/telecomm/java/android/telecom/TelecomManager.java
index 1a6b292..8be3e66 100644
--- a/telecomm/java/android/telecom/TelecomManager.java
+++ b/telecomm/java/android/telecom/TelecomManager.java
@@ -92,6 +92,15 @@
"android.telecom.action.CHANGE_PHONE_ACCOUNTS";
/**
+ * The {@link android.content.Intent} action used indicate that a new phone account was
+ * just registered.
+ * @hide
+ */
+ @SystemApi
+ public static final String ACTION_PHONE_ACCOUNT_REGISTERED =
+ "android.telecom.action.PHONE_ACCOUNT_REGISTERED";
+
+ /**
* Optional extra for {@link android.content.Intent#ACTION_CALL} containing a boolean that
* determines whether the speakerphone should be automatically turned on for an outgoing call.
*/
@@ -106,7 +115,6 @@
* {@link VideoProfile.VideoState#BIDIRECTIONAL},
* {@link VideoProfile.VideoState#RX_ENABLED},
* {@link VideoProfile.VideoState#TX_ENABLED}.
- * @hide
*/
public static final String EXTRA_START_CALL_WITH_VIDEO_STATE =
"android.telecom.extra.START_CALL_WITH_VIDEO_STATE";
@@ -117,9 +125,7 @@
* {@link PhoneAccountHandle} to use when making the call.
* <p class="note">
* Retrieve with {@link android.content.Intent#getParcelableExtra(String)}.
- * @hide
*/
- @SystemApi
public static final String EXTRA_PHONE_ACCOUNT_HANDLE =
"android.telecom.extra.PHONE_ACCOUNT_HANDLE";
@@ -139,10 +145,7 @@
* {@link android.content.Intent#ACTION_DIAL} {@code Intent} containing a {@link Bundle}
* which contains metadata about the call. This {@link Bundle} will be saved into
* {@code Call.Details}.
- *
- * @hide
*/
- @SystemApi
public static final String EXTRA_OUTGOING_CALL_EXTRAS =
"android.telecom.extra.OUTGOING_CALL_EXTRAS";
@@ -554,9 +557,7 @@
*
* @param account The {@link PhoneAccountHandle}.
* @return The {@link PhoneAccount} object.
- * @hide
*/
- @SystemApi
public PhoneAccount getPhoneAccount(PhoneAccountHandle account) {
try {
if (isServiceConnected()) {
diff --git a/telecomm/java/android/telecom/VideoProfile.java b/telecomm/java/android/telecom/VideoProfile.java
index f5cb054..e62e994 100644
--- a/telecomm/java/android/telecom/VideoProfile.java
+++ b/telecomm/java/android/telecom/VideoProfile.java
@@ -21,8 +21,6 @@
/**
* Represents attributes of video calls.
- *
- * {@hide}
*/
public class VideoProfile implements Parcelable {
/**
diff --git a/telecomm/java/android/telecom/Voicemail.java b/telecomm/java/android/telecom/Voicemail.java
new file mode 100644
index 0000000..864c6b1
--- /dev/null
+++ b/telecomm/java/android/telecom/Voicemail.java
@@ -0,0 +1,266 @@
+/*
+ * Copyright (C) 2015 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.telecom;
+
+import android.net.Uri;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * Represents a single voicemail stored in the voicemail content provider.
+ */
+public class Voicemail implements Parcelable {
+ private final Long mTimestamp;
+ private final String mNumber;
+ private final Long mId;
+ private final Long mDuration;
+ private final String mSource;
+ private final String mProviderData;
+ private final Uri mUri;
+ private final Boolean mIsRead;
+ private final Boolean mHasContent;
+
+ private Voicemail(Long timestamp, String number, Long id, Long duration, String source,
+ String providerData, Uri uri, Boolean isRead, Boolean hasContent) {
+ mTimestamp = timestamp;
+ mNumber = number;
+ mId = id;
+ mDuration = duration;
+ mSource = source;
+ mProviderData = providerData;
+ mUri = uri;
+ mIsRead = isRead;
+ mHasContent = hasContent;
+ }
+
+ /**
+ * Create a {@link Builder} for a new {@link Voicemail} to be inserted.
+ * <p>
+ * The number and the timestamp are mandatory for insertion.
+ */
+ public static Builder createForInsertion(long timestamp, String number) {
+ return new Builder().setNumber(number).setTimestamp(timestamp);
+ }
+
+ /**
+ * Builder pattern for creating a {@link Voicemail}. The builder must be created with the
+ * {@link #createForInsertion(long, String)} method.
+ * <p>
+ * This class is <b>not thread safe</b>
+ */
+ public static class Builder {
+ private Long mBuilderTimestamp;
+ private String mBuilderNumber;
+ private Long mBuilderId;
+ private Long mBuilderDuration;
+ private String mBuilderSourcePackage;
+ private String mBuilderSourceData;
+ private Uri mBuilderUri;
+ private Boolean mBuilderIsRead;
+ private boolean mBuilderHasContent;
+
+ /** You should use the correct factory method to construct a builder. */
+ private Builder() {
+ }
+
+ public Builder setNumber(String number) {
+ mBuilderNumber = number;
+ return this;
+ }
+
+ public Builder setTimestamp(long timestamp) {
+ mBuilderTimestamp = timestamp;
+ return this;
+ }
+
+ public Builder setId(long id) {
+ mBuilderId = id;
+ return this;
+ }
+
+ public Builder setDuration(long duration) {
+ mBuilderDuration = duration;
+ return this;
+ }
+
+ public Builder setSourcePackage(String sourcePackage) {
+ mBuilderSourcePackage = sourcePackage;
+ return this;
+ }
+
+ public Builder setSourceData(String sourceData) {
+ mBuilderSourceData = sourceData;
+ return this;
+ }
+
+ public Builder setUri(Uri uri) {
+ mBuilderUri = uri;
+ return this;
+ }
+
+ public Builder setIsRead(boolean isRead) {
+ mBuilderIsRead = isRead;
+ return this;
+ }
+
+ public Builder setHasContent(boolean hasContent) {
+ mBuilderHasContent = hasContent;
+ return this;
+ }
+
+ public Voicemail build() {
+ mBuilderId = mBuilderId == null ? -1 : mBuilderId;
+ mBuilderTimestamp = mBuilderTimestamp == null ? 0 : mBuilderTimestamp;
+ mBuilderDuration = mBuilderDuration == null ? 0: mBuilderDuration;
+ mBuilderIsRead = mBuilderIsRead == null ? false : mBuilderIsRead;
+ return new Voicemail(mBuilderTimestamp, mBuilderNumber, mBuilderId, mBuilderDuration,
+ mBuilderSourcePackage, mBuilderSourceData, mBuilderUri, mBuilderIsRead,
+ mBuilderHasContent);
+ }
+ }
+
+ /**
+ * The identifier of the voicemail in the content provider.
+ * <p>
+ * This may be missing in the case of a new {@link Voicemail} that we plan to insert into the
+ * content provider, since until it has been inserted we don't know what id it should have. If
+ * none is specified, we return -1.
+ */
+ public long getId() {
+ return mId;
+ }
+
+ /** The number of the person leaving the voicemail, empty string if unknown, null if not set. */
+ public String getNumber() {
+ return mNumber;
+ }
+
+ /** The timestamp the voicemail was received, in millis since the epoch, zero if not set. */
+ public long getTimestampMillis() {
+ return mTimestamp;
+ }
+
+ /** Gets the duration of the voicemail in millis, or zero if the field is not set. */
+ public long getDuration() {
+ return mDuration;
+ }
+
+ /**
+ * Returns the package name of the source that added this voicemail, or null if this field is
+ * not set.
+ */
+ public String getSourcePackage() {
+ return mSource;
+ }
+
+ /**
+ * Returns the application-specific data type stored with the voicemail, or null if this field
+ * is not set.
+ * <p>
+ * Source data is typically used as an identifier to uniquely identify the voicemail against
+ * the voicemail server. This is likely to be something like the IMAP UID, or some other
+ * server-generated identifying string.
+ */
+ public String getSourceData() {
+ return mProviderData;
+ }
+
+ /**
+ * Gets the Uri that can be used to refer to this voicemail, and to make it play.
+ * <p>
+ * Returns null if we don't know the Uri.
+ */
+ public Uri getUri() {
+ return mUri;
+ }
+
+ /**
+ * Tells us if the voicemail message has been marked as read.
+ * <p>
+ * Always returns false if this field has not been set, i.e. if hasRead() returns false.
+ */
+ public boolean isRead() {
+ return mIsRead;
+ }
+
+ /**
+ * Tells us if there is content stored at the Uri.
+ */
+ public boolean hasContent() {
+ return mHasContent;
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeLong(mTimestamp);
+ dest.writeCharSequence(mNumber);
+ dest.writeLong(mId);
+ dest.writeLong(mDuration);
+ dest.writeCharSequence(mSource);
+ dest.writeCharSequence(mProviderData);
+ if (mUri == null) {
+ dest.writeInt(0);
+ } else {
+ dest.writeInt(1);
+ mUri.writeToParcel(dest, flags);
+ }
+ if (mIsRead) {
+ dest.writeInt(1);
+ } else {
+ dest.writeInt(0);
+ }
+ if (mHasContent) {
+ dest.writeInt(1);
+ } else {
+ dest.writeInt(0);
+ }
+ }
+
+ public static final Creator<Voicemail> CREATOR
+ = new Creator<Voicemail>() {
+ @Override
+ public Voicemail createFromParcel(Parcel in) {
+ return new Voicemail(in);
+ }
+
+ @Override
+ public Voicemail[] newArray(int size) {
+ return new Voicemail[size];
+ }
+ };
+
+ private Voicemail(Parcel in) {
+ mTimestamp = in.readLong();
+ mNumber = (String) in.readCharSequence();
+ mId = in.readLong();
+ mDuration = in.readLong();
+ mSource = (String) in.readCharSequence();
+ mProviderData = (String) in.readCharSequence();
+ if (in.readInt() > 0) {
+ mUri = Uri.CREATOR.createFromParcel(in);
+ } else {
+ mUri = null;
+ }
+ mIsRead = in.readInt() > 0 ? true : false;
+ mHasContent = in.readInt() > 0 ? true : false;
+ }
+}
\ No newline at end of file
diff --git a/telephony/java/android/telephony/PhoneNumberUtils.java b/telephony/java/android/telephony/PhoneNumberUtils.java
index c043659..3572846 100644
--- a/telephony/java/android/telephony/PhoneNumberUtils.java
+++ b/telephony/java/android/telephony/PhoneNumberUtils.java
@@ -34,11 +34,11 @@
import android.text.Spannable;
import android.text.SpannableStringBuilder;
import android.text.TextUtils;
-import android.telephony.Rlog;
import android.text.style.TtsSpan;
import android.util.SparseIntArray;
-import static com.android.internal.telephony.PhoneConstants.SUBSCRIPTION_KEY;
+import static com.android.internal.telephony.TelephonyProperties.PROPERTY_ICC_OPERATOR_ISO_COUNTRY;
+import static com.android.internal.telephony.TelephonyProperties.PROPERTY_OPERATOR_ISO_COUNTRY;
import static com.android.internal.telephony.TelephonyProperties.PROPERTY_OPERATOR_IDP_STRING;
import java.util.Locale;
@@ -2311,15 +2311,13 @@
*
* @param phoneNumber A {@code CharSequence} the entirety of which represents a phone number.
* @return A {@code CharSequence} with appropriate annotations.
- *
- * @hide
*/
- public static CharSequence ttsSpanAsPhoneNumber(CharSequence phoneNumber) {
+ public static CharSequence getPhoneTtsSpannable(CharSequence phoneNumber) {
if (phoneNumber == null) {
return null;
}
Spannable spannable = Spannable.Factory.getInstance().newSpannable(phoneNumber);
- PhoneNumberUtils.ttsSpanAsPhoneNumber(spannable, 0, spannable.length());
+ PhoneNumberUtils.addPhoneTtsSpan(spannable, 0, spannable.length());
return spannable;
}
@@ -2330,19 +2328,83 @@
* @param s A {@code Spannable} to annotate.
* @param start The starting character position of the phone number in {@code s}.
* @param end The ending character position of the phone number in {@code s}.
- *
- * @hide
*/
- public static void ttsSpanAsPhoneNumber(Spannable s, int start, int end) {
- s.setSpan(
- new TtsSpan.TelephoneBuilder()
- .setNumberParts(splitAtNonNumerics(s.subSequence(start, end)))
- .build(),
+ public static void addPhoneTtsSpan(Spannable s, int start, int end) {
+ s.setSpan(getPhoneTtsSpan(s.subSequence(start, end).toString()),
start,
end,
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
}
+ /**
+ * Wrap the supplied {@code CharSequence} with a {@code TtsSpan}, annotating it as
+ * containing a phone number in its entirety.
+ *
+ * @param phoneNumber A {@code CharSequence} the entirety of which represents a phone number.
+ * @return A {@code CharSequence} with appropriate annotations.
+ * @deprecated Renamed {@link #getPhoneTtsSpannable}.
+ *
+ * @hide
+ */
+ @Deprecated
+ public static CharSequence ttsSpanAsPhoneNumber(CharSequence phoneNumber) {
+ return getPhoneTtsSpannable(phoneNumber);
+ }
+
+ /**
+ * Attach a {@link TtsSpan} to the supplied {@code Spannable} at the indicated location,
+ * annotating that location as containing a phone number.
+ *
+ * @param s A {@code Spannable} to annotate.
+ * @param start The starting character position of the phone number in {@code s}.
+ * @param end The ending character position of the phone number in {@code s}.
+ *
+ * @deprecated Renamed {@link #addPhoneTtsSpan}.
+ *
+ * @hide
+ */
+ @Deprecated
+ public static void ttsSpanAsPhoneNumber(Spannable s, int start, int end) {
+ addPhoneTtsSpan(s, start, end);
+ }
+
+ /**
+ * Create a {@code TtsSpan} for the supplied {@code String}.
+ *
+ * @param phoneNumberString A {@code String} the entirety of which represents a phone number.
+ * @return A {@code TtsSpan} for {@param phoneNumberString}.
+ */
+ public static TtsSpan getPhoneTtsSpan(String phoneNumberString) {
+ if (phoneNumberString == null) {
+ return null;
+ }
+
+ // Parse the phone number
+ final PhoneNumberUtil phoneNumberUtil = PhoneNumberUtil.getInstance();
+ PhoneNumber phoneNumber = null;
+ try {
+ // Don't supply a defaultRegion so this fails for non-international numbers because
+ // we don't want to TalkBalk to read a country code (e.g. +1) if it is not already
+ // present
+ phoneNumber = phoneNumberUtil.parse(phoneNumberString, /* defaultRegion */ null);
+ } catch (NumberParseException ignored) {
+ }
+
+ // Build a telephone tts span
+ final TtsSpan.TelephoneBuilder builder = new TtsSpan.TelephoneBuilder();
+ if (phoneNumber == null) {
+ // Strip separators otherwise TalkBack will be silent
+ // (this behavior was observed with TalkBalk 4.0.2 from their alpha channel)
+ builder.setNumberParts(splitAtNonNumerics(phoneNumberString));
+ } else {
+ if (phoneNumber.hasCountryCode()) {
+ builder.setCountryCode(Integer.toString(phoneNumber.getCountryCode()));
+ }
+ builder.setNumberParts(Long.toString(phoneNumber.getNationalNumber()));
+ }
+ return builder.build();
+ }
+
// Split a phone number like "+20(123)-456#" using spaces, ignoring anything that is not
// a digit, to produce a result like "20 123 456".
private static String splitAtNonNumerics(CharSequence number) {
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index b8de144..e1a3de7 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -29,6 +29,7 @@
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.SystemProperties;
+import android.telecom.PhoneAccount;
import android.util.Log;
import com.android.internal.telecom.ITelecomService;
@@ -3779,7 +3780,7 @@
/**
* Returns the IMS Registration Status
- *@hide
+ * @hide
*/
public boolean isImsRegistered() {
try {
@@ -4158,4 +4159,21 @@
ServiceState.rilRadioTechnologyToString(type));
}
}
+
+ /**
+ * Returns the subscription ID for the given phone account.
+ * @hide
+ */
+ public int getSubIdForPhoneAccount(PhoneAccount phoneAccount) {
+ int retval = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
+ try {
+ ITelephony service = getITelephony();
+ if (service != null) {
+ retval = service.getSubIdForPhoneAccount(phoneAccount);
+ }
+ } catch (RemoteException e) {
+ }
+
+ return retval;
+ }
}
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index bb0bd04..d03fa3a 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -18,6 +18,7 @@
import android.content.Intent;
import android.os.Bundle;
+import android.telecom.PhoneAccount;
import android.telephony.CellInfo;
import android.telephony.IccOpenLogicalChannelResponse;
import android.telephony.NeighboringCellInfo;
@@ -891,4 +892,9 @@
* {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
*/
String getDeviceId();
+
+ /**
+ * Returns the subscription ID associated with the specified PhoneAccount.
+ */
+ int getSubIdForPhoneAccount(in PhoneAccount phoneAccount);
}
diff --git a/wifi/java/android/net/wifi/IRttManager.aidl b/wifi/java/android/net/wifi/IRttManager.aidl
index d929f55..90f66c4 100644
--- a/wifi/java/android/net/wifi/IRttManager.aidl
+++ b/wifi/java/android/net/wifi/IRttManager.aidl
@@ -15,8 +15,8 @@
*/
package android.net.wifi;
-
import android.os.Messenger;
+import android.net.wifi.RttManager;
/**
* {@hide}
@@ -24,4 +24,5 @@
interface IRttManager
{
Messenger getMessenger();
+ RttManager.RttCapabilities getRttCapabilities();
}
diff --git a/wifi/java/android/net/wifi/IWifiManager.aidl b/wifi/java/android/net/wifi/IWifiManager.aidl
index ca95ec1..5342494 100644
--- a/wifi/java/android/net/wifi/IWifiManager.aidl
+++ b/wifi/java/android/net/wifi/IWifiManager.aidl
@@ -79,6 +79,8 @@
void setCountryCode(String country, boolean persist);
+ String getCountryCode();
+
void setFrequencyBand(int band, boolean persist);
int getFrequencyBand();
diff --git a/wifi/java/android/net/wifi/RttManager.aidl b/wifi/java/android/net/wifi/RttManager.aidl
new file mode 100644
index 0000000..5c6d447
--- /dev/null
+++ b/wifi/java/android/net/wifi/RttManager.aidl
@@ -0,0 +1,18 @@
+/**
+ * Copyright (c) 2015, 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;
+parcelable RttManager.RttCapabilities;
\ No newline at end of file
diff --git a/wifi/java/android/net/wifi/RttManager.java b/wifi/java/android/net/wifi/RttManager.java
index 57343c5..65ecf5d 100644
--- a/wifi/java/android/net/wifi/RttManager.java
+++ b/wifi/java/android/net/wifi/RttManager.java
@@ -26,10 +26,19 @@
private static final boolean DBG = true;
private static final String TAG = "RttManager";
- public static final int RTT_TYPE_UNSPECIFIED = 0;
- public static final int RTT_TYPE_ONE_SIDED = 1;
- public static final int RTT_TYPE_11_V = 2;
- public static final int RTT_TYPE_11_MC = 4;
+ /** @deprecated Type must be specified*/
+ @Deprecated
+ public static final int RTT_TYPE_UNSPECIFIED = 0;
+ public static final int RTT_TYPE_ONE_SIDED = 1;
+
+ /** @deprecated It is not supported*/
+ @Deprecated
+ public static final int RTT_TYPE_11_V = 2;
+ public static final int RTT_TYPE_TWO_SIDED = 4;
+
+ /** @deprecated It is not supported*/
+ @Deprecated
+ public static final int RTT_TYPE_11_MC = 4;
public static final int RTT_PEER_TYPE_UNSPECIFIED = 0;
public static final int RTT_PEER_TYPE_AP = 1;
@@ -42,6 +51,9 @@
public static final int RTT_CHANNEL_WIDTH_80P80 = 4;
public static final int RTT_CHANNEL_WIDTH_5 = 5;
public static final int RTT_CHANNEL_WIDTH_10 = 6;
+
+ /** @deprecated channel info must be specified*/
+ @Deprecated
public static final int RTT_CHANNEL_WIDTH_UNSPECIFIED = -1;
public static final int RTT_STATUS_SUCCESS = 0;
@@ -53,6 +65,12 @@
public static final int RTT_STATUS_FAIL_AP_ON_DIFF_CHANNEL = 6;
public static final int RTT_STATUS_FAIL_NO_CAPABILITY = 7;
public static final int RTT_STATUS_ABORTED = 8;
+ //if the T1-T4 or TOD/TOA Timestamp is illegal
+ public static final int RTT_STATUS_FAIL_INVALID_TS = 9;
+ //11mc protocol failed, eg, unrecognized FTMR/FTM
+ public static final int RTT_STATUS_FAIL_PROTOCOL = 10;
+ public static final int RTT_STATUS_FAIL_SCHEDULE = 11;
+ public static final int RTT_STATUS_FAIL_BUSY_TRY_LATER = 12;
public static final int REASON_UNSPECIFIED = -1;
public static final int REASON_NOT_AVAILABLE = -2;
@@ -61,41 +79,269 @@
public static final String DESCRIPTION_KEY = "android.net.wifi.RttManager.Description";
+ /**
+ * RTT BW supported bit mask
+ */
+ public static final int RTT_BW_5_SUPPORT = 0x1;
+ public static final int RTT_BW_10_SUPPORT = 0x2;
+ public static final int RTT_BW_20_SUPPORT = 0x4;
+ public static final int RTT_BW_40_SUPPORT = 0x8;
+ public static final int RTT_BW_80_SUPPORT = 0x10;
+ public static final int RTT_BW_160_SUPPORT = 0x20;
+
+ /**
+ * RTT Preamble Support bit mask
+ */
+ public static final int PREAMBLE_LEGACY = 0x1;
+ public static final int PREAMBLE_HT = 0x2;
+ public static final int PREAMBLE_VHT = 0x4;
+
+ /** @deprecated It has been replaced by RttCapabilities*/
+ @Deprecated
public class Capabilities {
public int supportedType;
public int supportedPeerType;
}
+ /** @deprecated It has been replaced by getRttCapabilities*/
+ @Deprecated
public Capabilities getCapabilities() {
return new Capabilities();
}
+ /**
+ * This class describe the RTT capability of the Hardware
+ */
+ public static class RttCapabilities implements Parcelable {
+ /** @deprecated It is not supported*/
+ @Deprecated
+ public boolean supportedType;
+ /** @deprecated It is not supported*/
+ @Deprecated
+ public boolean supportedPeerType;
+ //1-sided rtt measurement is supported
+ public boolean oneSidedRttSupported;
+ //11mc 2-sided rtt measurement is supported
+ public boolean twoSided11McRttSupported;
+ //location configuration information supported
+ public boolean lciSupported;
+ //location civic records supported
+ public boolean lcrSupported;
+ //preamble supported, see bit mask definition above
+ public int preambleSupported;
+ //RTT bandwidth supported
+ public int bwSupported;
+
+ @Override
+ public String toString() {
+ StringBuffer sb = new StringBuffer();
+ sb.append("oneSidedRtt ").
+ append(oneSidedRttSupported ? "is Supported. " : "is not supported. ").
+ append("twoSided11McRtt ").
+ append(twoSided11McRttSupported ? "is Supported. " : "is not supported. ").
+ append("lci ").
+ append(lciSupported ? "is Supported. " : "is not supported. ").
+ append("lcr ").
+ append(lcrSupported ? "is Supported. " : "is not supported. ");
+
+ if ((preambleSupported & PREAMBLE_LEGACY) != 0) {
+ sb.append("Legacy ");
+ }
+
+ if ((preambleSupported & PREAMBLE_HT) != 0) {
+ sb.append("HT ");
+ }
+
+ if ((preambleSupported & PREAMBLE_VHT) != 0) {
+ sb.append("VHT ");
+ }
+
+ sb.append("is supported. \n");
+
+ if ((bwSupported & RTT_BW_5_SUPPORT) != 0) {
+ sb.append("5 MHz ");
+ }
+
+ if ((bwSupported & RTT_BW_10_SUPPORT) != 0) {
+ sb.append("10 MHz ");
+ }
+
+ if ((bwSupported & RTT_BW_20_SUPPORT) != 0) {
+ sb.append("20 MHz ");
+ }
+
+ if ((bwSupported & RTT_BW_40_SUPPORT) != 0) {
+ sb.append("40 MHz ");
+ }
+
+ if ((bwSupported & RTT_BW_80_SUPPORT) != 0) {
+ sb.append("80 MHz ");
+ }
+
+ if ((bwSupported & RTT_BW_160_SUPPORT) != 0) {
+ sb.append("160 MHz ");
+ }
+
+ sb.append("is supported.");
+
+ return sb.toString();
+ }
+ /** Implement the Parcelable interface {@hide} */
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ /** Implement the Parcelable interface {@hide} */
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeInt(oneSidedRttSupported ? 1 : 0);
+ dest.writeInt(twoSided11McRttSupported ? 1 : 0);
+ dest.writeInt(lciSupported ? 1 : 0);
+ dest.writeInt(lcrSupported ? 1 : 0);
+ dest.writeInt(preambleSupported);
+ dest.writeInt(bwSupported);
+
+ }
+
+ /** Implement the Parcelable interface {@hide} */
+ public static final Creator<RttCapabilities> CREATOR =
+ new Creator<RttCapabilities>() {
+ public RttCapabilities createFromParcel(Parcel in) {
+ RttCapabilities capabilities = new RttCapabilities();
+ capabilities.oneSidedRttSupported = in.readInt() == 1 ? true : false;
+ capabilities.twoSided11McRttSupported = in.readInt() == 1 ? true : false;
+ capabilities.lciSupported = in.readInt() == 1 ? true : false;
+ capabilities.lcrSupported = in.readInt() == 1 ? true : false;
+ capabilities.preambleSupported = in.readInt();
+ capabilities.bwSupported = in.readInt();
+ return capabilities;
+ }
+ /** Implement the Parcelable interface {@hide} */
+ @Override
+ public RttCapabilities[] newArray(int size) {
+ return new RttCapabilities[size];
+ }
+ };
+ }
+
+ public RttCapabilities getRttCapabilities() {
+ synchronized (sCapabilitiesLock) {
+ if (mRttCapabilities == null) {
+ try {
+ mRttCapabilities = mService.getRttCapabilities();
+ } catch (RemoteException e) {
+ Log.e(TAG, "Can not get RTT Capabilities");
+ }
+ }
+ return mRttCapabilities;
+ }
+ }
+
/** specifies parameters for RTT request */
public static class RttParams {
-
- /** type of device being ranged; one of RTT_PEER_TYPE_AP or RTT_PEER_TYPE_STA */
+ /**
+ * type of destination device being ranged; one of RTT_PEER_TYPE_AP or RTT_PEER_TYPE_STA
+ */
public int deviceType;
- /** type of RTT being sought; one of RTT_TYPE_ONE_SIDED
- * RTT_TYPE_11_V or RTT_TYPE_11_MC or RTT_TYPE_UNSPECIFIED */
+ /**
+ * type of RTT measurement method; one of RTT_TYPE_ONE_SIDED or RTT_TYPE_TWO_SIDED.
+ */
public int requestType;
/** mac address of the device being ranged */
public String bssid;
- /** channel frequency that the device is on; optional */
+ /**
+ * The primary 20 MHz frequency (in MHz) of the channel over which the client is
+ * communicating with the access point.Similar as ScanResult.frequency
+ */
public int frequency;
- /** optional channel width. wider channels result in better accuracy,
- * but they take longer time, and even get aborted may times; use
- * RTT_CHANNEL_WIDTH_UNSPECIFIED if not specifying */
+ /**
+ * channel width used for RTT measurement. User need verify the highest BW the destination
+ * support (from scan result etc) before set this value. Wider channels result usually give
+ * better accuracy. However, the frame loss can increase. Similar as ScanResult.channelWidth
+ */
public int channelWidth;
- /** number of samples to be taken */
+ /**
+ * Not used if the AP bandwidth is 20 MHz
+ * If the AP use 40, 80 or 160 MHz, this is the center frequency
+ * if the AP use 80 + 80 MHz, this is the center frequency of the first segment
+ * similar as ScanResult.centerFreq0
+ */
+ public int centerFreq0;
+
+ /**
+ * Only used if the AP bandwidth is 80 + 80 MHz
+ * if the AP use 80 + 80 MHz, this is the center frequency of the second segment
+ * similar as ScanResult.centerFreq1
+ */
+ public int centerFreq1;
+ /**
+ * number of samples to be taken
+ * @deprecated It has been replaced by numSamplesPerBurst
+ */
+ @Deprecated
public int num_samples;
- /** number of retries if a sample fails */
+ /**
+ * number of retries if a sample fails
+ * @deprecated It has been replaced by numRetriesPerMeasurementFrame
+ */
+ @Deprecated
public int num_retries;
+
+ /** Number of burst. fixed to 1 for single side RTT*/
+ public int numberBurst;
+
+ /** valid only if numberBurst > 1, interval between burst(ms). Not used by singe side RTT */
+ public int interval;
+
+ /** number of samples to be taken in one burst*/
+ public int numSamplesPerBurst;
+
+ /** number of retries for each measurement frame if a sample fails
+ * Only used by single side RTT
+ */
+ public int numRetriesPerMeasurementFrame;
+
+ /** number of retries for FTMR frame if fails Only used by 80211MC double side RTT */
+ public int numRetriesPerFTMR;
+
+ /** Request LCI information */
+ public boolean LCIRequest;
+
+ /** Request LCR information */
+ public boolean LCRRequest;
+
+ /** Timeout for each burst, unit of 250 us*/
+ public int burstTimeout;
+
+ /** preamble used for RTT measurement
+ * should be one of PREAMBLE_LEGACY, PREAMBLE_HT, PREAMBLE_VHT
+ */
+ public int preamble;
+
+ /** bandWidth used for RTT measurement.User need verify the highest BW the destination
+ * support (from scan result etc) before set this value. Wider channels result usually give
+ * better accuracy. However, the frame loss can increase too.
+ * should be one of RTT_CHANNEL_WIDTH_20 to RTT_CHANNEL_WIDTH_80
+ */
+ public int bandwidth;
+
+ public RttParams() {
+ //provide initial value for RttParams
+ deviceType = RTT_PEER_TYPE_AP;
+ numberBurst = 1;
+ numSamplesPerBurst = 8;
+ numRetriesPerMeasurementFrame = 0;
+ burstTimeout = 40 + numSamplesPerBurst *4;
+ preamble = PREAMBLE_LEGACY;
+ bandwidth = RTT_CHANNEL_WIDTH_20;
+ }
}
/** pseudo-private class used to parcel arguments */
@@ -121,10 +367,20 @@
dest.writeInt(params.deviceType);
dest.writeInt(params.requestType);
dest.writeString(params.bssid);
- dest.writeInt(params.frequency);
dest.writeInt(params.channelWidth);
- dest.writeInt(params.num_samples);
- dest.writeInt(params.num_retries);
+ dest.writeInt(params.frequency);
+ dest.writeInt(params.centerFreq0);
+ dest.writeInt(params.centerFreq1);
+ dest.writeInt(params.numberBurst);
+ dest.writeInt(params.interval);
+ dest.writeInt(params.numSamplesPerBurst);
+ dest.writeInt(params.numRetriesPerMeasurementFrame);
+ dest.writeInt(params.numRetriesPerFTMR);
+ dest.writeInt(params.LCIRequest ? 1 : 0);
+ dest.writeInt(params.LCRRequest ? 1 : 0);
+ dest.writeInt(params.burstTimeout);
+ dest.writeInt(params.preamble);
+ dest.writeInt(params.bandwidth);
}
} else {
dest.writeInt(0);
@@ -148,11 +404,20 @@
params[i].deviceType = in.readInt();
params[i].requestType = in.readInt();
params[i].bssid = in.readString();
- params[i].frequency = in.readInt();
params[i].channelWidth = in.readInt();
- params[i].num_samples = in.readInt();
- params[i].num_retries = in.readInt();
-
+ params[i].frequency = in.readInt();
+ params[i].centerFreq0 = in.readInt();
+ params[i].centerFreq1 = in.readInt();
+ params[i].numberBurst = in.readInt();
+ params[i].interval = in.readInt();
+ params[i].numSamplesPerBurst = in.readInt();
+ params[i].numRetriesPerMeasurementFrame = in.readInt();
+ params[i].numRetriesPerFTMR = in.readInt();
+ params[i].LCIRequest = in.readInt() == 1 ? true : false;
+ params[i].LCRRequest = in.readInt() == 1 ? true : false;
+ params[i].burstTimeout = in.readInt();
+ params[i].preamble = in.readInt();
+ params[i].bandwidth = in.readInt();
}
ParcelableRttParams parcelableParams = new ParcelableRttParams(params);
@@ -165,46 +430,143 @@
};
}
+ public class wifiInformationElement {
+ /** Information Element ID*/
+ public int id;
+ public String data;
+ }
/** specifies RTT results */
public static class RttResult {
/** mac address of the device being ranged */
public String bssid;
+ /** # of burst for this measurement*/
+ public int burstNumber;
+
+ /** total number of measurement frames in this measurement*/
+ public int measurementFrameNumber;
+
+ /** total successful number of measurement frames in this measurement*/
+ public int successMeasurementFrameNumber;
+
+ /** Maximum number of frames per burst supported by peer */
+ public int frameNumberPerBurstPeer;
+
/** status of the request */
public int status;
- /** type of the request used */
+ /**
+ * type of the request used
+ * @deprecated It has been replaced by measurementType
+ */
+ @Deprecated
public int requestType;
+ /** RTT measurement method type used, shoudl be one of RTT_TYPE_ONE_SIDED or
+ * RTT_TYPE_TWO_SIDED.
+ */
+ public int measurementType;
+
+ /** please retry RTT measurement after this S since peer indicate busy at ths moment*/
+ public int retryAfterDuration;
+
/** timestamp of completion, in microsecond since boot */
public long ts;
- /** average RSSI observed */
+ /** average RSSI observed, unit of 0.5 dB */
public int rssi;
- /** RSSI spread (i.e. max - min) */
+ /**
+ * RSSI spread (i.e. max - min)
+ * @deprecated It has been replaced by rssi_spread
+ */
+ @Deprecated
public int rssi_spread;
- /** average transmit rate */
+ /**RSSI spread (i.e. max - min), unit of 0.5 dB */
+ public int rssiSpread;
+
+ /**
+ * average transmit rate
+ * @deprecated It has been replaced by txRate
+ */
+ @Deprecated
public int tx_rate;
- /** average round trip time in nano second */
+ /** average transmit rate */
+ public int txRate;
+
+ /** average receiving rate */
+ public int rxRate;
+
+ /**
+ * average round trip time in nano second
+ * @deprecated It has been replaced by rtt
+ */
+ @Deprecated
public long rtt_ns;
- /** standard deviation observed in round trip time */
+ /** average round trip time in 0.1 nano second */
+ public long rtt;
+
+ /**
+ * standard deviation observed in round trip time
+ * @deprecated It has been replaced by rttStandardDeviation
+ */
+ @Deprecated
public long rtt_sd_ns;
- /** spread (i.e. max - min) round trip time */
+ /** standard deviation of RTT in 0.1 ns */
+ public long rttStandardDeviation;
+
+ /**
+ * spread (i.e. max - min) round trip time
+ * @deprecated It has been replaced by rttSpread
+ */
+ @Deprecated
public long rtt_spread_ns;
- /** average distance in centimeter, computed based on rtt_ns */
+ /** spread (i.e. max - min) RTT in 0.1 ns */
+ public long rttSpread;
+
+ /**
+ * average distance in centimeter, computed based on rtt_ns
+ * @deprecated It has been replaced by distance
+ */
+ @Deprecated
public int distance_cm;
- /** standard deviation observed in distance */
+ /** average distance in cm, computed based on rtt */
+ public int distance;
+
+ /**
+ * standard deviation observed in distance
+ * @deprecated It has been replaced with distanceStandardDeviation
+ */
+ @Deprecated
public int distance_sd_cm;
- /** spread (i.e. max - min) distance */
+ /** standard deviation observed in distance in cm*/
+ public int distanceStandardDeviation;
+
+ /**
+ * spread (i.e. max - min) distance
+ * @deprecated It has been replaced by distanceSpread
+ */
+ @Deprecated
public int distance_spread_cm;
+
+ /** spread (i.e. max - min) distance in cm */
+ public int distanceSpread;
+
+ /** the duration of this measurement burst*/
+ public int burstDuration;
+
+ /** LCI information Element*/
+ wifiInformationElement LCI;
+
+ /** LCR information Element*/
+ wifiInformationElement LCR;
}
@@ -228,18 +590,28 @@
dest.writeInt(mResults.length);
for (RttResult result : mResults) {
dest.writeString(result.bssid);
+ dest.writeInt(result.burstNumber);
+ dest.writeInt(result.measurementFrameNumber);
+ dest.writeInt(result.successMeasurementFrameNumber);
+ dest.writeInt(result.frameNumberPerBurstPeer);
dest.writeInt(result.status);
- dest.writeInt(result.requestType);
+ dest.writeInt(result.measurementType);
+ dest.writeInt(result.retryAfterDuration);
dest.writeLong(result.ts);
dest.writeInt(result.rssi);
- dest.writeInt(result.rssi_spread);
- dest.writeInt(result.tx_rate);
- dest.writeLong(result.rtt_ns);
- dest.writeLong(result.rtt_sd_ns);
- dest.writeLong(result.rtt_spread_ns);
- dest.writeInt(result.distance_cm);
- dest.writeInt(result.distance_sd_cm);
- dest.writeInt(result.distance_spread_cm);
+ dest.writeInt(result.rssiSpread);
+ dest.writeInt(result.txRate);
+ dest.writeLong(result.rtt);
+ dest.writeLong(result.rttStandardDeviation);
+ dest.writeLong(result.rttSpread);
+ dest.writeInt(result.distance);
+ dest.writeInt(result.distanceStandardDeviation);
+ dest.writeInt(result.distanceSpread);
+ dest.writeInt(result.burstDuration);
+ //dest.writeInt(result.LCI.id);
+ //dest.writeString(result.LCI.data);
+ //dest.writeInt(result.LCR.id);
+ //dest.writeString(result.LCR.data);
}
} else {
dest.writeInt(0);
@@ -261,18 +633,28 @@
for (int i = 0; i < num; i++) {
results[i] = new RttResult();
results[i].bssid = in.readString();
+ results[i].burstNumber = in.readInt();
+ results[i].measurementFrameNumber = in.readInt();
+ results[i].successMeasurementFrameNumber = in.readInt();
+ results[i].frameNumberPerBurstPeer = in.readInt();
results[i].status = in.readInt();
- results[i].requestType = in.readInt();
+ results[i].measurementType = in.readInt();
+ results[i].retryAfterDuration = in.readInt();
results[i].ts = in.readLong();
results[i].rssi = in.readInt();
- results[i].rssi_spread = in.readInt();
- results[i].tx_rate = in.readInt();
- results[i].rtt_ns = in.readLong();
- results[i].rtt_sd_ns = in.readLong();
- results[i].rtt_spread_ns = in.readLong();
- results[i].distance_cm = in.readInt();
- results[i].distance_sd_cm = in.readInt();
- results[i].distance_spread_cm = in.readInt();
+ results[i].rssiSpread = in.readInt();
+ results[i].txRate = in.readInt();
+ results[i].rtt = in.readLong();
+ results[i].rttStandardDeviation = in.readLong();
+ results[i].rttSpread = in.readLong();
+ results[i].distance = in.readInt();
+ results[i].distanceStandardDeviation = in.readInt();
+ results[i].distanceSpread = in.readInt();
+ results[i].burstDuration = in.readInt();
+ //results[i].LCI.id = in.readInt();
+ //results[i].LCI.data = in.readString();
+ //results[i].LCR.id = in.readInt();
+ //results[i].LCR.data = in.readString();
}
ParcelableRttResults parcelableResults = new ParcelableRttResults(results);
@@ -292,7 +674,70 @@
public void onAborted();
}
+ private boolean rttParamSanity(RttParams params, int index) {
+ if (mRttCapabilities == null) {
+ if(getRttCapabilities() == null) {
+ Log.e(TAG, "Can not get RTT capabilities");
+ //throw new IllegalStateException("RTT chip is not working");
+ }
+ }
+
+ if (params.deviceType != RTT_PEER_TYPE_AP) {
+ return false;
+ } else if (params.requestType != RTT_TYPE_ONE_SIDED && params.requestType !=
+ RTT_TYPE_TWO_SIDED) {
+ Log.e(TAG, "Request " + index + ": Illegal Request Type: " + params.requestType);
+ return false;
+ } else if (params.requestType == RTT_TYPE_ONE_SIDED &&
+ !mRttCapabilities.oneSidedRttSupported) {
+ Log.e(TAG, "Request " + index + ": One side RTT is not supported");
+ return false;
+ } else if (params.requestType == RTT_TYPE_TWO_SIDED &&
+ !mRttCapabilities.twoSided11McRttSupported) {
+ Log.e(TAG, "Request " + index + ": two side RTT is not supported");
+ return false;
+ } else if ( params.numberBurst <= 0 ) {
+ Log.e(TAG, "Request " + index + ": Illegal number of burst: " + params.numberBurst);
+ return false;
+ } else if (params.numberBurst > 1 && params.interval <= 0) {
+ Log.e(TAG, "Request " + index + ": Illegal interval value: " + params.interval);
+ return false;
+ } else if (params.numSamplesPerBurst <= 0) {
+ Log.e(TAG, "Request " + index + ": Illegal sample number per burst: " +
+ params.numSamplesPerBurst);
+ return false;
+ } else if (params.numRetriesPerMeasurementFrame < 0 || params.numRetriesPerFTMR < 0) {
+ Log.e(TAG, "Request " + index + ": Illegal retry number");
+ return false;
+ } else if (params.LCIRequest && !mRttCapabilities.lciSupported) {
+ Log.e(TAG, "Request " + index + ": LCI is not supported");
+ return false;
+ } else if (params.LCRRequest && !mRttCapabilities.lcrSupported) {
+ Log.e(TAG, "Request " + index + ": LCR is not supported");
+ return false;
+ } else if (params.burstTimeout <= 0){
+ Log.e(TAG, "Request " + index + ": Illegal burst timeout: " + params.burstTimeout);
+ return false;
+ } else if ((params.preamble & mRttCapabilities.preambleSupported) == 0) {
+ Log.e(TAG, "Request " + index + ": Do not support this preamble: " + params.preamble);
+ return false;
+ } else if ((params.bandwidth & mRttCapabilities.bwSupported) == 0) {
+ Log.e(TAG, "Request " + index + ": Do not support this bandwidth: " + params.bandwidth);
+ return false;
+ }
+
+ return true;
+ }
+
public void startRanging(RttParams[] params, RttListener listener) {
+ int index = 0;
+ for(RttParams rttParam : params) {
+ if (!rttParamSanity(rttParam, index)) {
+ throw new IllegalArgumentException("RTT Request Parameter Illegal");
+ }
+ index++;
+ }
+
validateChannel();
ParcelableRttParams parcelableParams = new ParcelableRttParams(params);
sAsyncChannel.sendMessage(CMD_OP_START_RANGING,
@@ -315,12 +760,14 @@
private Context mContext;
private IRttManager mService;
+ private RttCapabilities mRttCapabilities;
private static final int INVALID_KEY = 0;
private static int sListenerKey = 1;
private static final SparseArray sListenerMap = new SparseArray();
private static final Object sListenerMapLock = new Object();
+ private static final Object sCapabilitiesLock = new Object();
private static AsyncChannel sAsyncChannel;
private static CountDownLatch sConnected;
diff --git a/wifi/java/android/net/wifi/ScanResult.java b/wifi/java/android/net/wifi/ScanResult.java
index 9729c91..e8a51e3 100644
--- a/wifi/java/android/net/wifi/ScanResult.java
+++ b/wifi/java/android/net/wifi/ScanResult.java
@@ -53,11 +53,55 @@
*/
public int level;
/**
- * The frequency in MHz of the channel over which the client is communicating
+ * The primary 20 MHz frequency (in MHz) of the channel over which the client is communicating
* with the access point.
*/
public int frequency;
+ /**
+ * AP Channel bandwidth is 20 MHZ
+ */
+ public static final int CHANNEL_WIDTH_20MHZ = 0;
+ /**
+ * AP Channel bandwidth is 40 MHZ
+ */
+ public static final int CHANNEL_WIDTH_40MHZ = 1;
+ /**
+ * AP Channel bandwidth is 80 MHZ
+ */
+ public static final int CHANNEL_WIDTH_80MHZ = 2;
+ /**
+ * AP Channel bandwidth is 160 MHZ
+ */
+ public static final int CHANNEL_WIDTH_160MHZ = 3;
+ /**
+ * AP Channel bandwidth is 160 MHZ, but 80MHZ + 80MHZ
+ */
+ public static final int CHANNEL_WIDTH_80MHZ_PLUS_MHZ = 4;
+
+ /**
+ * AP Channel bandwidth
+ */
+ public int channelWidth;
+
+ /**
+ * Not used if the AP bandwidth is 20 MHz
+ * If the AP use 40, 80 or 160 MHz, this is the center frequency
+ * if the AP use 80 + 80 MHz, this is the center frequency of the first segment
+ */
+ public int centerFreq0;
+
+ /**
+ * Only used if the AP bandwidth is 80 + 80 MHz
+ * if the AP use 80 + 80 MHz, this is the center frequency of the second segment
+ */
+ public int centerFreq1;
+
+ /**
+ * Whether the AP support 802.11mc Responder
+ */
+ public boolean is80211McRTTResponder;
+
/**
* timestamp in microseconds (since boot) when
* this result was last seen.
@@ -169,6 +213,21 @@
public int distanceSdCm;
/**
+ * Indicates if the scan result represents a passpoint AP
+ */
+ public boolean passpointNetwork;
+
+ /**
+ * Indicates if venue name
+ */
+ public String venueName;
+
+ /**
+ * Indicates operator name
+ */
+ public String operatorFriendlyName;
+
+ /**
* {@hide}
*/
public final static int UNSPECIFIED = -1;
@@ -235,6 +294,11 @@
this.timestamp = tsf;
this.distanceCm = UNSPECIFIED;
this.distanceSdCm = UNSPECIFIED;
+ this.channelWidth = UNSPECIFIED;
+ this.centerFreq0 = UNSPECIFIED;
+ this.centerFreq1 = UNSPECIFIED;
+ this.is80211McRTTResponder = false;
+ this.passpointNetwork = false;
}
/** {@hide} */
@@ -249,6 +313,31 @@
this.timestamp = tsf;
this.distanceCm = distCm;
this.distanceSdCm = distSdCm;
+ this.channelWidth = UNSPECIFIED;
+ this.centerFreq0 = UNSPECIFIED;
+ this.centerFreq1 = UNSPECIFIED;
+ this.is80211McRTTResponder = false;
+ this.passpointNetwork = false;
+ }
+
+ /** {@hide} */
+ public ScanResult(WifiSsid wifiSsid, String BSSID, String caps, int level, int frequency,
+ long tsf, int distCm, int distSdCm, int channelWidth, int centerFreq0, int centerFreq1,
+ boolean is80211McRTTResponder) {
+ this.wifiSsid = wifiSsid;
+ this.SSID = (wifiSsid != null) ? wifiSsid.toString() : WifiSsid.NONE;
+ this.BSSID = BSSID;
+ this.capabilities = caps;
+ this.level = level;
+ this.frequency = frequency;
+ this.timestamp = tsf;
+ this.distanceCm = distCm;
+ this.distanceSdCm = distSdCm;
+ this.channelWidth = channelWidth;
+ this.centerFreq0 = centerFreq0;
+ this.centerFreq1 = centerFreq1;
+ this.is80211McRTTResponder = is80211McRTTResponder;
+ this.passpointNetwork = false;
}
/** copy constructor {@hide} */
@@ -260,6 +349,10 @@
capabilities = source.capabilities;
level = source.level;
frequency = source.frequency;
+ channelWidth = source.channelWidth;
+ centerFreq0 = source.centerFreq0;
+ centerFreq1 = source.centerFreq1;
+ is80211McRTTResponder = source.is80211McRTTResponder;
timestamp = source.timestamp;
distanceCm = source.distanceCm;
distanceSdCm = source.distanceSdCm;
@@ -270,6 +363,9 @@
numUsage = source.numUsage;
numIpConfigFailures = source.numIpConfigFailures;
isAutoJoinCandidate = source.isAutoJoinCandidate;
+ passpointNetwork = source.passpointNetwork;
+ venueName = source.venueName;
+ operatorFriendlyName = source.operatorFriendlyName;
}
}
@@ -303,9 +399,15 @@
sb.append(", distanceSd: ").append((distanceSdCm != UNSPECIFIED ? distanceSdCm : "?")).
append("(cm)");
+ sb.append(", passpoint: ").append(passpointNetwork ? "yes" : "no");
if (autoJoinStatus != 0) {
sb.append(", status: ").append(autoJoinStatus);
}
+ sb.append(", ChannelBandwidth: ").append(channelWidth);
+ sb.append(", centerFreq0: ").append(centerFreq0);
+ sb.append(", centerFreq1: ").append(centerFreq1);
+ sb.append(", 80211mcResponder: ").append(is80211McRTTResponder?
+ "is supported":"is not supported");
return sb.toString();
}
@@ -329,6 +431,10 @@
dest.writeLong(timestamp);
dest.writeInt(distanceCm);
dest.writeInt(distanceSdCm);
+ dest.writeInt(channelWidth);
+ dest.writeInt(centerFreq0);
+ dest.writeInt(centerFreq1);
+ dest.writeInt(is80211McRTTResponder ? 1 : 0);
dest.writeLong(seen);
dest.writeInt(autoJoinStatus);
dest.writeInt(untrusted ? 1 : 0);
@@ -336,6 +442,10 @@
dest.writeInt(numUsage);
dest.writeInt(numIpConfigFailures);
dest.writeInt(isAutoJoinCandidate);
+ dest.writeInt(passpointNetwork ? 1 : 0);
+ dest.writeString(venueName);
+ dest.writeString(operatorFriendlyName);
+
if (informationElements != null) {
dest.writeInt(informationElements.length);
for (int i = 0; i < informationElements.length; i++) {
@@ -364,7 +474,11 @@
in.readInt(),
in.readLong(),
in.readInt(),
- in.readInt()
+ in.readInt(),
+ in.readInt(),
+ in.readInt(),
+ in.readInt(),
+ in.readInt() == 1
);
sr.seen = in.readLong();
sr.autoJoinStatus = in.readInt();
@@ -373,6 +487,9 @@
sr.numUsage = in.readInt();
sr.numIpConfigFailures = in.readInt();
sr.isAutoJoinCandidate = in.readInt();
+ sr.passpointNetwork = in.readInt() == 1;
+ sr.venueName = in.readString();
+ sr.operatorFriendlyName = in.readString();
int n = in.readInt();
if (n != 0) {
sr.informationElements = new InformationElement[n];
diff --git a/wifi/java/android/net/wifi/WifiActivityEnergyInfo.java b/wifi/java/android/net/wifi/WifiActivityEnergyInfo.java
index 533b8bc..c9a2f07 100644
--- a/wifi/java/android/net/wifi/WifiActivityEnergyInfo.java
+++ b/wifi/java/android/net/wifi/WifiActivityEnergyInfo.java
@@ -116,6 +116,7 @@
return (int)mControllerIdleTimeMs;
}
+
/**
* product of current(mA), voltage(V) and time(ms)
* @return energy used
diff --git a/wifi/java/android/net/wifi/WifiConfiguration.java b/wifi/java/android/net/wifi/WifiConfiguration.java
index 87db951..34ae386 100644
--- a/wifi/java/android/net/wifi/WifiConfiguration.java
+++ b/wifi/java/android/net/wifi/WifiConfiguration.java
@@ -19,19 +19,18 @@
import android.annotation.SystemApi;
import android.net.IpConfiguration;
import android.net.IpConfiguration.ProxySettings;
-import android.net.IpConfiguration.IpAssignment;
import android.net.ProxyInfo;
import android.net.StaticIpConfiguration;
import android.os.Parcel;
import android.os.Parcelable;
import android.text.TextUtils;
-import android.annotation.SystemApi;
import java.util.HashMap;
import java.util.BitSet;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
+import java.util.HashSet;
/**
* A class representing a configured Wi-Fi network, including the
@@ -59,6 +58,7 @@
public static final String updateIdentiferVarName = "update_identifier";
/** {@hide} */
public static final int INVALID_NETWORK_ID = -1;
+
/**
* Recognized key management schemes.
*/
@@ -233,17 +233,21 @@
* <code>XX:XX:XX:XX:XX:XX</code> where each <code>X</code> is a hex digit.
*/
public String BSSID;
+
/**
- * Fully qualified domain name (FQDN) of AAA server or RADIUS server
- * e.g. {@code "mail.example.com"}.
+ * The band which AP resides on
+ * 0-2G 1-5G
+ * By default, 2G is chosen
*/
- public String FQDN;
+ public int apBand = 0;
+
/**
- * Network access identifier (NAI) realm, for Passpoint credential.
- * e.g. {@code "myhost.example.com"}.
- * @hide
+ * The channel which AP resides on,currently, US only
+ * 2G 1-11
+ * 5G 36,40,44,48,149,153,157,161,165
+ * 0 - find a random available channel according to the apBand
*/
- public String naiRealm;
+ public int apChannel = 0;
/**
* Pre-shared key for use with WPA-PSK.
@@ -328,6 +332,21 @@
public WifiEnterpriseConfig enterpriseConfig;
/**
+ * Fully qualified domain name of a passpoint configuration
+ */
+ public String FQDN;
+
+ /**
+ * Service provider name, for Passpoint credential.
+ */
+ public String providerFriendlyName;
+
+ /**
+ * Roaming Consortium Id, for Passpoint credential.
+ */
+ public HashSet<Long> roamingConsortiumIds;
+
+ /**
* @hide
*/
private IpConfiguration mIpConfiguration;
@@ -862,7 +881,7 @@
SSID = null;
BSSID = null;
FQDN = null;
- naiRealm = null;
+ roamingConsortiumIds = new HashSet<Long>();
priority = 0;
hiddenSSID = false;
disableReason = DISABLED_UNKNOWN_REASON;
@@ -907,11 +926,37 @@
}
}
+ if (TextUtils.isEmpty(FQDN) == false) {
+ /* this is passpoint configuration; it must not have an SSID */
+ if (TextUtils.isEmpty(SSID) == false) {
+ return false;
+ }
+ /* this is passpoint configuration; it must have a providerFriendlyName */
+ if (TextUtils.isEmpty(providerFriendlyName)) {
+ return false;
+ }
+ /* this is passpoint configuration; it must have enterprise config */
+ if (enterpriseConfig == null
+ || enterpriseConfig.getEapMethod() == WifiEnterpriseConfig.Eap.NONE ) {
+ return false;
+ }
+ }
+
// TODO: Add more checks
return true;
}
/**
+ * Identify if this configuration represents a passpoint network
+ */
+ public boolean isPasspoint() {
+ return !TextUtils.isEmpty(FQDN)
+ && !TextUtils.isEmpty(providerFriendlyName)
+ && enterpriseConfig != null
+ && enterpriseConfig.getEapMethod() != WifiEnterpriseConfig.Eap.NONE;
+ }
+
+ /**
* Helper function, identify if a configuration is linked
* @hide
*/
@@ -1042,8 +1087,9 @@
sbuf.append("- DSBLE ");
}
sbuf.append("ID: ").append(this.networkId).append(" SSID: ").append(this.SSID).
+ append(" PROVIDER-NAME: ").append(this.providerFriendlyName).
append(" BSSID: ").append(this.BSSID).append(" FQDN: ").append(this.FQDN).
- append(" REALM: ").append(this.naiRealm).append(" PRIO: ").append(this.priority).
+ append(" PRIO: ").append(this.priority).
append('\n');
if (this.numConnectionFailures > 0) {
sbuf.append(" numConnectFailures ").append(this.numConnectionFailures).append("\n");
@@ -1383,6 +1429,8 @@
String key;
if (allowCached && mCachedConfigKey != null) {
key = mCachedConfigKey;
+ } else if (providerFriendlyName != null) {
+ key = FQDN + KeyMgmt.strings[KeyMgmt.WPA_EAP];
} else {
if (allowedKeyManagement.get(KeyMgmt.WPA_PSK)) {
key = SSID + KeyMgmt.strings[KeyMgmt.WPA_PSK];
@@ -1498,9 +1546,17 @@
SSID = source.SSID;
BSSID = source.BSSID;
FQDN = source.FQDN;
- naiRealm = source.naiRealm;
+ roamingConsortiumIds = new HashSet<Long>();
+ for (Long roamingConsortiumId : source.roamingConsortiumIds) {
+ roamingConsortiumIds.add(roamingConsortiumId);
+ }
+
+ providerFriendlyName = source.providerFriendlyName;
preSharedKey = source.preSharedKey;
+ apBand = source.apBand;
+ apChannel = source.apChannel;
+
wepKeys = new String[4];
for (int i = 0; i < wepKeys.length; i++) {
wepKeys[i] = source.wepKeys[i];
@@ -1593,9 +1649,15 @@
dest.writeInt(disableReason);
dest.writeString(SSID);
dest.writeString(BSSID);
+ dest.writeInt(apBand);
+ dest.writeInt(apChannel);
dest.writeString(autoJoinBSSID);
dest.writeString(FQDN);
- dest.writeString(naiRealm);
+ dest.writeString(providerFriendlyName);
+ dest.writeInt(roamingConsortiumIds.size());
+ for (Long roamingConsortiumId : roamingConsortiumIds) {
+ dest.writeLong(roamingConsortiumId);
+ }
dest.writeString(preSharedKey);
for (String wepKey : wepKeys) {
dest.writeString(wepKey);
@@ -1658,9 +1720,15 @@
config.disableReason = in.readInt();
config.SSID = in.readString();
config.BSSID = in.readString();
+ config.apBand = in.readInt();
+ config.apChannel = in.readInt();
config.autoJoinBSSID = in.readString();
config.FQDN = in.readString();
- config.naiRealm = in.readString();
+ config.providerFriendlyName = in.readString();
+ int numRoamingConsortiumIds = in.readInt();
+ for (int i = 0; i < numRoamingConsortiumIds; i++) {
+ config.roamingConsortiumIds.add(in.readLong());
+ }
config.preSharedKey = in.readString();
for (int i = 0; i < config.wepKeys.length; i++) {
config.wepKeys[i] = in.readString();
diff --git a/wifi/java/android/net/wifi/WifiEnterpriseConfig.java b/wifi/java/android/net/wifi/WifiEnterpriseConfig.java
index cf3cba3..440ad61 100644
--- a/wifi/java/android/net/wifi/WifiEnterpriseConfig.java
+++ b/wifi/java/android/net/wifi/WifiEnterpriseConfig.java
@@ -54,6 +54,8 @@
/** @hide */
public static final String SUBJECT_MATCH_KEY = "subject_match";
/** @hide */
+ public static final String ALTSUBJECT_MATCH_KEY = "altsubject_match";
+ /** @hide */
public static final String OPP_KEY_CACHING = "proactive_key_caching";
/**
* String representing the keystore OpenSSL ENGINE's ID.
@@ -93,6 +95,11 @@
public static final String ENGINE_ID_KEY = "engine_id";
/** @hide */
public static final String PRIVATE_KEY_ID_KEY = "key_id";
+ /** @hide */
+ public static final String REALM_KEY = "realm";
+ /** @hide */
+ public static final String PLMN_KEY = "plmn";
+
private HashMap<String, String> mFields = new HashMap<String, String>();
private X509Certificate mCaCert;
@@ -228,8 +235,10 @@
public static final int SIM = 4;
/** EAP-Authentication and Key Agreement */
public static final int AKA = 5;
+ /** EAP-Authentication and Key Agreement Prime */
+ public static final int AKA_PRIME = 6;
/** @hide */
- public static final String[] strings = { "PEAP", "TLS", "TTLS", "PWD", "SIM", "AKA" };
+ public static final String[] strings = { "PEAP", "TLS", "TTLS", "PWD", "SIM", "AKA", "AKA'" };
/** Prevent initialization */
private Eap() {}
@@ -279,6 +288,7 @@
case Eap.TTLS:
case Eap.SIM:
case Eap.AKA:
+ case Eap.AKA_PRIME:
mFields.put(EAP_KEY, Eap.strings[eapMethod]);
mFields.put(OPP_KEY_CACHING, "1");
break;
@@ -530,22 +540,74 @@
}
/**
- * Set subject match. This is the substring to be matched against the subject of the
- * authentication server certificate.
+ * Set subject match (deprecated). This is the substring to be matched against the subject of
+ * the authentication server certificate.
* @param subjectMatch substring to be matched
+ * @deprecated in favor of altSubjectMatch
*/
public void setSubjectMatch(String subjectMatch) {
setFieldValue(SUBJECT_MATCH_KEY, subjectMatch, "");
}
/**
- * Get subject match
+ * Get subject match (deprecated)
* @return the subject match string
+ * @deprecated in favor of altSubjectMatch
*/
public String getSubjectMatch() {
return getFieldValue(SUBJECT_MATCH_KEY, "");
}
+ /**
+ * Set alternate subject match. This is the substring to be matched against the
+ * alternate subject of the authentication server certificate.
+ * @param altSubjectMatch substring to be matched, for example
+ * DNS:server.example.com;EMAIL:server@example.com
+ */
+ public void setAltSubjectMatch(String altSubjectMatch) {
+ setFieldValue(ALTSUBJECT_MATCH_KEY, altSubjectMatch, "");
+ }
+
+ /**
+ * Get alternate subject match
+ * @return the alternate subject match string
+ */
+ public String getAltSubjectMatch() {
+ return getFieldValue(ALTSUBJECT_MATCH_KEY, "");
+ }
+
+ /**
+ * Set realm for passpoint credential
+ * @param realm the realm
+ */
+ public void setRealm(String realm) {
+ setFieldValue(REALM_KEY, realm, "");
+ }
+
+ /**
+ * Get realm for passpoint credential
+ * @return the realm
+ */
+ public String getRealm() {
+ return getFieldValue(REALM_KEY, "");
+ }
+
+ /**
+ * Set plmn for passpoint credential
+ * @param plmn the plmn value derived from mcc & mnc
+ */
+ public void setPlmn(String plmn) {
+ setFieldValue(PLMN_KEY, plmn, "");
+ }
+
+ /**
+ * Set plmn for passpoint credential
+ * @return the plmn
+ */
+ public String getPlmn() {
+ return getFieldValue(PLMN_KEY, "");
+ }
+
/** See {@link WifiConfiguration#getKeyIdForCredentials} @hide */
String getKeyId(WifiEnterpriseConfig current) {
String eap = mFields.get(EAP_KEY);
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index 97e10dc..f8a6e3f 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -839,6 +839,14 @@
public static final int WIFI_FEATURE_TDLS_OFFCHANNEL = 0x2000; // Support for TDLS off channel
/** @hide */
public static final int WIFI_FEATURE_EPR = 0x4000; // Enhanced power reporting
+ /** @hide */
+ public static final int WIFI_FEATURE_AP_STA = 0x8000; // Support for AP STA Concurrency
+ /** @hide */
+ public static final int WIFI_FEATURE_LINK_LAYER_STATS = 0x10000; // Link layer stats collection
+ /** @hide */
+ public static final int WIFI_FEATURE_LOGGER = 0x20000; // WiFi Logger
+ /** @hide */
+ public static final int WIFI_FEATURE_HAL_EPNO = 0x40000; // WiFi PNO enhanced
private int getSupportedFeatures() {
try {
@@ -950,7 +958,7 @@
* @return true if this adapter supports advanced power/performance counters
*/
public boolean isEnhancedPowerReportingSupported() {
- return isFeatureSupported(WIFI_FEATURE_EPR);
+ return isFeatureSupported(WIFI_FEATURE_LINK_LAYER_STATS);
}
/**
@@ -1238,6 +1246,21 @@
}
/**
+ * get the country code.
+ * @return the country code in ISO 3166 format.
+ *
+ * @hide
+ */
+ public String getCountryCode() {
+ try {
+ String country = mService.getCountryCode();
+ return(country);
+ } catch (RemoteException e) {
+ return null;
+ }
+ }
+
+ /**
* Set the operational frequency band.
* @param band One of
* {@link #WIFI_FREQUENCY_BAND_AUTO},
diff --git a/wifi/java/android/net/wifi/WifiScanner.java b/wifi/java/android/net/wifi/WifiScanner.java
index aaa2f98..fea934f 100644
--- a/wifi/java/android/net/wifi/WifiScanner.java
+++ b/wifi/java/android/net/wifi/WifiScanner.java
@@ -158,6 +158,11 @@
public int reportEvents;
/** defines number of bssids to cache from each scan */
public int numBssidsPerScan;
+ /**
+ * defines number of scans to cache; use it with REPORT_EVENT_AFTER_BUFFER_FULL
+ * to wake up at fixed interval
+ */
+ public int maxScansToCache;
/** Implement the Parcelable interface {@hide} */
public int describeContents() {
@@ -170,6 +175,7 @@
dest.writeInt(periodInMs);
dest.writeInt(reportEvents);
dest.writeInt(numBssidsPerScan);
+ dest.writeInt(maxScansToCache);
if (channels != null) {
dest.writeInt(channels.length);
@@ -194,6 +200,7 @@
settings.periodInMs = in.readInt();
settings.reportEvents = in.readInt();
settings.numBssidsPerScan = in.readInt();
+ settings.maxScansToCache = in.readInt();
int num_channels = in.readInt();
settings.channels = new ChannelSpec[num_channels];
for (int i = 0; i < num_channels; i++) {
@@ -215,8 +222,143 @@
}
- /** @hide */
+ /**
+ * all the information garnered from a single scan
+ */
+ public static class ScanData implements Parcelable {
+ /** scan identifier */
+ private int mId;
+ /** additional information about scan
+ * 0 => no special issues encountered in the scan
+ * non-zero => scan was truncated, so results may not be complete
+ */
+ private int mFlags;
+ /** all scan results discovered in this scan, sorted by timestamp in ascending order */
+ private ScanResult mResults[];
+
+ ScanData() {}
+
+ public ScanData(int id, int flags, ScanResult[] results) {
+ mId = id;
+ mFlags = flags;
+ mResults = results;
+ }
+
+ public ScanData(ScanData s) {
+ mId = s.mId;
+ mFlags = s.mFlags;
+ mResults = new ScanResult[s.mResults.length];
+ for (int i = 0; i < s.mResults.length; i++) {
+ ScanResult result = s.mResults[i];
+ WifiSsid wifiSsid = WifiSsid.createFromAsciiEncoded(result.SSID);
+ ScanResult newResult = new ScanResult(result);
+ newResult.wifiSsid = wifiSsid;
+ mResults[i] = newResult;
+ }
+ }
+
+ public int getId() {
+ return mId;
+ }
+
+ public int getFlags() {
+ return mFlags;
+ }
+
+ public ScanResult[] getResults() {
+ return mResults;
+ }
+
+ /** Implement the Parcelable interface {@hide} */
+ public int describeContents() {
+ return 0;
+ }
+
+ /** Implement the Parcelable interface {@hide} */
+ public void writeToParcel(Parcel dest, int flags) {
+ if (mResults != null) {
+ dest.writeInt(mId);
+ dest.writeInt(mFlags);
+ dest.writeInt(mResults.length);
+ for (int i = 0; i < mResults.length; i++) {
+ ScanResult result = mResults[i];
+ result.writeToParcel(dest, flags);
+ }
+ } else {
+ dest.writeInt(0);
+ }
+ }
+
+ /** Implement the Parcelable interface {@hide} */
+ public static final Creator<ScanData> CREATOR =
+ new Creator<ScanData>() {
+ public ScanData createFromParcel(Parcel in) {
+ int id = in.readInt();
+ int flags = in.readInt();
+ int n = in.readInt();
+ ScanResult results[] = new ScanResult[n];
+ for (int i = 0; i < n; i++) {
+ results[i] = ScanResult.CREATOR.createFromParcel(in);
+ }
+ return new ScanData(id, flags, results);
+ }
+
+ public ScanData[] newArray(int size) {
+ return new ScanData[size];
+ }
+ };
+ }
+
+ public static class ParcelableScanData implements Parcelable {
+
+ public ScanData mResults[];
+
+ public ParcelableScanData(ScanData[] results) {
+ mResults = results;
+ }
+
+ public ScanData[] getResults() {
+ return mResults;
+ }
+
+ /** Implement the Parcelable interface {@hide} */
+ public int describeContents() {
+ return 0;
+ }
+
+ /** Implement the Parcelable interface {@hide} */
+ public void writeToParcel(Parcel dest, int flags) {
+ if (mResults != null) {
+ dest.writeInt(mResults.length);
+ for (int i = 0; i < mResults.length; i++) {
+ ScanData result = mResults[i];
+ result.writeToParcel(dest, flags);
+ }
+ } else {
+ dest.writeInt(0);
+ }
+ }
+
+ /** Implement the Parcelable interface {@hide} */
+ public static final Creator<ParcelableScanData> CREATOR =
+ new Creator<ParcelableScanData>() {
+ public ParcelableScanData createFromParcel(Parcel in) {
+ int n = in.readInt();
+ ScanData results[] = new ScanData[n];
+ for (int i = 0; i < n; i++) {
+ results[i] = ScanData.CREATOR.createFromParcel(in);
+ }
+ return new ParcelableScanData(results);
+ }
+
+ public ParcelableScanData[] newArray(int size) {
+ return new ParcelableScanData[size];
+ }
+ };
+ }
+
public static class ParcelableScanResults implements Parcelable {
+
public ScanResult mResults[];
public ParcelableScanResults(ScanResult[] results) {
@@ -264,7 +406,8 @@
}
/**
- * interface to get scan events on; specify this on {@link #startBackgroundScan}
+ * interface to get scan events on; specify this on {@link #startBackgroundScan} or
+ * {@link #startScan}
*/
public interface ScanListener extends ActionListener {
/**
@@ -273,10 +416,15 @@
*/
public void onPeriodChanged(int periodInMs);
/**
- * reports results retrieved from background scan
+ * reports results retrieved from background scan and single shot scans
+ * @deprecated in favor of {@link #onResults(ScanData[])}
*/
public void onResults(ScanResult[] results);
/**
+ * reports results retrieved from background scan and single shot scans
+ */
+ public void onResults(ScanData[] results);
+ /**
* reports full scan result for each access point found in scan
*/
public void onFullResult(ScanResult fullScanResult);
@@ -303,13 +451,36 @@
sAsyncChannel.sendMessage(CMD_STOP_BACKGROUND_SCAN, 0, removeListener(listener));
}
/**
- * retrieves currently available scan results
+ * reports currently available scan results on appropriate listeners
*/
public ScanResult[] getScanResults() {
validateChannel();
Message reply = sAsyncChannel.sendMessageSynchronously(CMD_GET_SCAN_RESULTS, 0);
- ScanResult[] results = (ScanResult[]) reply.obj;
- return results;
+ // return reply.what == CMD_OP_SUCCEEDED;
+ return null;
+ }
+
+ /**
+ * starts a single scan and reports results asynchronously
+ * @param settings specifies various parameters for the scan; for more information look at
+ * {@link ScanSettings}
+ * @param listener specifies the object to report events to. This object is also treated as a
+ * key for this scan, and must also be specified to cancel the scan. Multiple
+ * scans should also not share this object.
+ */
+ public void startScan(ScanSettings settings, ScanListener listener) {
+ validateChannel();
+ sAsyncChannel.sendMessage(CMD_START_SINGLE_SCAN, 0, putListener(listener), settings);
+ }
+
+ /**
+ * stops an ongoing single shot scan; only useful after {@link #startScan} if onResults()
+ * hasn't been called on the listener, ignored otherwise
+ * @param listener
+ */
+ public void stopScan(ScanListener listener) {
+ validateChannel();
+ sAsyncChannel.sendMessage(CMD_STOP_SINGLE_SCAN, 0, removeListener(listener));
}
/** specifies information about an access point of interest */
@@ -468,6 +639,10 @@
* @param results list of scan results, one for each access point visible currently
*/
public void onFound(ScanResult[] results);
+ /** indicates that access points were missed by on going scans
+ * @param results list of scan results, for each access point that is not visible anymore
+ */
+ public void onLost(ScanResult[] results);
}
/** @hide */
@@ -593,6 +768,12 @@
public static final int CMD_PERIOD_CHANGED = BASE + 19;
/** @hide */
public static final int CMD_FULL_SCAN_RESULT = BASE + 20;
+ /** @hide */
+ public static final int CMD_START_SINGLE_SCAN = BASE + 21;
+ /** @hide */
+ public static final int CMD_STOP_SINGLE_SCAN = BASE + 22;
+ /** @hide */
+ public static final int CMD_SINGLE_SCAN_COMPLETED = BASE + 23;
private Context mContext;
private IWifiScanner mService;
@@ -800,7 +981,7 @@
break;
case CMD_SCAN_RESULT :
((ScanListener) listener).onResults(
- ((ParcelableScanResults) msg.obj).getResults());
+ ((ParcelableScanData) msg.obj).getResults());
return;
case CMD_FULL_SCAN_RESULT :
ScanResult result = (ScanResult) msg.obj;
@@ -813,6 +994,10 @@
((BssidListener) listener).onFound(
((ParcelableScanResults) msg.obj).getResults());
return;
+ case CMD_AP_LOST:
+ ((BssidListener) listener).onLost(
+ ((ParcelableScanResults) msg.obj).getResults());
+ return;
case CMD_WIFI_CHANGE_DETECTED:
((WifiChangeListener) listener).onChanging(
((ParcelableScanResults) msg.obj).getResults());
@@ -821,6 +1006,10 @@
((WifiChangeListener) listener).onQuiescence(
((ParcelableScanResults) msg.obj).getResults());
return;
+ case CMD_SINGLE_SCAN_COMPLETED:
+ Log.d(TAG, "removing listener for single scan");
+ removeListener(msg.arg2);
+ break;
default:
if (DBG) Log.d(TAG, "Ignoring message " + msg.what);
return;
diff --git a/wifi/java/android/net/wifi/passpoint/IWifiPasspointManager.aidl b/wifi/java/android/net/wifi/passpoint/IWifiPasspointManager.aidl
new file mode 100644
index 0000000..50bec33
--- /dev/null
+++ b/wifi/java/android/net/wifi/passpoint/IWifiPasspointManager.aidl
@@ -0,0 +1,45 @@
+/**
+ * Copyright (c) 2014, 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.passpoint;
+
+import android.net.wifi.ScanResult;
+import android.net.wifi.passpoint.WifiPasspointPolicy;
+import android.net.wifi.passpoint.WifiPasspointCredential;
+import android.os.Messenger;
+
+/**
+ * Interface that allows controlling and querying Wifi Passpoint connectivity.
+ *
+ * {@hide}
+ */
+interface IWifiPasspointManager
+{
+ Messenger getMessenger();
+
+ int getPasspointState();
+
+ List<WifiPasspointPolicy> requestCredentialMatch(in List<ScanResult> requested);
+
+ List<WifiPasspointCredential> getCredentials();
+
+ boolean addCredential(in WifiPasspointCredential cred);
+
+ boolean updateCredential(in WifiPasspointCredential cred);
+
+ boolean removeCredential(in WifiPasspointCredential cred);
+}
+
diff --git a/wifi/java/android/net/wifi/passpoint/WifiPasspointCredential.aidl b/wifi/java/android/net/wifi/passpoint/WifiPasspointCredential.aidl
new file mode 100644
index 0000000..cfd3605
--- /dev/null
+++ b/wifi/java/android/net/wifi/passpoint/WifiPasspointCredential.aidl
@@ -0,0 +1,19 @@
+/**
+ * Copyright (c) 2014, 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.passpoint;
+
+parcelable WifiPasspointCredential;
diff --git a/wifi/java/android/net/wifi/passpoint/WifiPasspointCredential.java b/wifi/java/android/net/wifi/passpoint/WifiPasspointCredential.java
new file mode 100644
index 0000000..0a7230f
--- /dev/null
+++ b/wifi/java/android/net/wifi/passpoint/WifiPasspointCredential.java
@@ -0,0 +1,667 @@
+/*
+ * Copyright (C) 2014 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.passpoint;
+
+import android.net.wifi.WifiEnterpriseConfig;
+import android.os.Parcelable;
+import android.os.Parcel;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+
+
+/**
+ * A class representing a Wi-Fi Passpoint credential.
+ * @hide
+ */
+public class WifiPasspointCredential implements Parcelable {
+
+ private final static String TAG = "PasspointCredential";
+ private final static boolean DBG = true;
+
+ /** Wi-Fi nodes**/
+ private String mWifiSpFqdn;
+
+ /** PerProviderSubscription nodes **/
+ private String mCredentialName;
+
+ /** SubscriptionUpdate nodes **/
+ private String mSubscriptionUpdateInterval;
+ private String mSubscriptionUpdateMethod;
+ private String mSubscriptionUpdateRestriction;
+ private String mSubscriptionUpdateURI;
+ private String mSubscriptionUpdateUsername;
+ private String mSubscriptionUpdatePassword;
+
+ /** HomeSP nodes **/
+ private String mHomeSpFqdn;
+ private String mFriendlyName;
+ private Collection<WifiPasspointDmTree.HomeOIList> mHomeOIList;
+ private Collection<WifiPasspointDmTree.OtherHomePartners> mOtherHomePartnerList;
+
+ /** SubscriptionParameters nodes**/
+ private String mCreationDate;
+ private String mExpirationDate;
+
+ /** Credential nodes **/
+ private String mType;
+ private String mInnerMethod;
+ private String mCertType;
+ private String mCertSha256Fingerprint;
+ private String mUpdateIdentifier;
+ private String mUsername;
+ private String mPasswd;
+ private String mRealm;
+ private String mImsi;
+ private String mMcc;
+ private String mMnc;
+ private String mCaRootCert;
+ private String mClientCert;
+ private boolean mCheckAaaServerCertStatus;
+
+ /** Policy nodes **/
+ private String mPolicyUpdateUri;
+ private String mPolicyUpdateInterval;
+ private String mPolicyUpdateUsername;
+ private String mPolicyUpdatePassword;
+ private String mPolicyUpdateRestriction;
+ private String mPolicyUpdateMethod;
+ private Collection<WifiPasspointDmTree.PreferredRoamingPartnerList> mPreferredRoamingPartnerList;
+ private Collection<WifiPasspointDmTree.MinBackhaulThresholdNetwork> mMinBackhaulThresholdNetwork;
+ private Collection<WifiPasspointDmTree.SPExclusionList> mSpExclusionList;
+ private Collection<WifiPasspointDmTree.RequiredProtoPortTuple> mRequiredProtoPortTuple;
+ private String mMaxBssLoad;
+
+ /** CrednetialPriority node **/
+ private int mCrednetialPriority;
+
+ /** AAAServerTrustRoot nodes **/
+ private String mAaaCertUrl;
+ private String mAaaSha256Fingerprint;
+
+ /** Others **/
+ private boolean mIsMachineRemediation;
+ private boolean mUserPreferred = false;
+ private String mWifiTreePath;
+ private WifiEnterpriseConfig mEnterpriseConfig;
+
+ /** @hide */
+ public WifiPasspointCredential() {}
+
+ /**
+ * Constructor
+ * @param realm Realm of the passpoint credential
+ * @param fqdn Fully qualified domain name (FQDN) of the credential
+ * @param config Enterprise config, must be either EAP-TLS or EAP-TTLS
+ * @see WifiEnterpriseConfig
+ */
+ public WifiPasspointCredential(String realm, String fqdn, WifiEnterpriseConfig config) {
+ mRealm = realm;
+ switch (config.getEapMethod()) {
+ case WifiEnterpriseConfig.Eap.TLS:
+ case WifiEnterpriseConfig.Eap.TTLS:
+ mEnterpriseConfig = new WifiEnterpriseConfig(config);
+ break;
+ default:
+ // ignore
+ }
+ }
+
+ /** @hide */
+ public WifiPasspointCredential(String type,
+ String caroot,
+ String clientcert,
+ String mcc,
+ String mnc,
+ WifiPasspointDmTree.SpFqdn sp,
+ WifiPasspointDmTree.CredentialInfo credinfo) {
+
+ if (credinfo == null) {
+ return;
+ }
+
+ mType = type;
+ mCaRootCert = caroot;
+ mClientCert = clientcert;
+
+ mWifiSpFqdn = sp.nodeName;
+ mUpdateIdentifier = sp.perProviderSubscription.UpdateIdentifier;
+
+ mCredentialName = credinfo.nodeName;
+ mOtherHomePartnerList = credinfo.homeSP.otherHomePartners.values();
+
+ Set set = credinfo.aAAServerTrustRoot.entrySet();
+ Iterator i = set.iterator();
+ if (i.hasNext()) {
+ Map.Entry entry3 = (Map.Entry) i.next();
+ WifiPasspointDmTree.AAAServerTrustRoot aaa = (WifiPasspointDmTree.AAAServerTrustRoot) entry3.getValue();
+ mAaaCertUrl = aaa.CertURL;
+ mAaaSha256Fingerprint = aaa.CertSHA256Fingerprint;
+ }
+
+ mCertType = credinfo.credential.digitalCertificate.CertificateType;
+ mCertSha256Fingerprint = credinfo.credential.digitalCertificate.CertSHA256Fingerprint;
+ mUsername = credinfo.credential.usernamePassword.Username;
+ mPasswd = credinfo.credential.usernamePassword.Password;
+ mIsMachineRemediation = credinfo.credential.usernamePassword.MachineManaged;
+ mInnerMethod = credinfo.credential.usernamePassword.eAPMethod.InnerMethod;
+ mImsi = credinfo.credential.sim.IMSI;
+ mMcc = mcc;
+ mMnc = mnc;
+ mCreationDate = credinfo.credential.CreationDate;
+ mExpirationDate = credinfo.credential.ExpirationDate;
+ mRealm = credinfo.credential.Realm;
+
+ if (credinfo.credentialPriority == null) {
+ mCrednetialPriority = 128;
+ } else {
+ mCrednetialPriority = Integer.parseInt(credinfo.credentialPriority);
+ }
+
+ mHomeSpFqdn = credinfo.homeSP.FQDN;
+
+ mSubscriptionUpdateInterval = credinfo.subscriptionUpdate.UpdateInterval;
+ mSubscriptionUpdateMethod = credinfo.subscriptionUpdate.UpdateMethod;
+ mSubscriptionUpdateRestriction = credinfo.subscriptionUpdate.Restriction;
+ mSubscriptionUpdateURI = credinfo.subscriptionUpdate.URI;
+ mSubscriptionUpdateUsername = credinfo.subscriptionUpdate.usernamePassword.Username;
+ mSubscriptionUpdatePassword = credinfo.subscriptionUpdate.usernamePassword.Password;
+
+ mPolicyUpdateUri = credinfo.policy.policyUpdate.URI;
+ mPolicyUpdateInterval = credinfo.policy.policyUpdate.UpdateInterval;
+ mPolicyUpdateUsername = credinfo.policy.policyUpdate.usernamePassword.Username;
+ mPolicyUpdatePassword = credinfo.policy.policyUpdate.usernamePassword.Password;
+ mPolicyUpdateRestriction = credinfo.policy.policyUpdate.Restriction;
+ mPolicyUpdateMethod = credinfo.policy.policyUpdate.UpdateMethod;
+ mPreferredRoamingPartnerList = credinfo.policy.preferredRoamingPartnerList.values();
+ mMinBackhaulThresholdNetwork = credinfo.policy.minBackhaulThreshold.values();
+ mRequiredProtoPortTuple = credinfo.policy.requiredProtoPortTuple.values();
+ mMaxBssLoad = credinfo.policy.maximumBSSLoadValue;
+ mSpExclusionList = credinfo.policy.sPExclusionList.values();
+
+ mHomeOIList = credinfo.homeSP.homeOIList.values();
+ mFriendlyName = credinfo.homeSP.FriendlyName;
+ mCheckAaaServerCertStatus = credinfo.credential.CheckAAAServerCertStatus;
+ }
+
+ /** @hide */
+ public String getUpdateIdentifier() {
+ return mUpdateIdentifier;
+ }
+
+ /** @hide */
+ public String getUpdateMethod() {
+ return mSubscriptionUpdateMethod;
+ }
+
+ /** @hide */
+ public void setUpdateMethod(String method) {
+ mSubscriptionUpdateMethod = method;
+ }
+
+ /** @hide */
+ public String getWifiSpFqdn() {
+ return mWifiSpFqdn;
+ }
+
+ /** @hide */
+ public String getCredName() {
+ return mCredentialName;
+ }
+
+ /** @hide */
+ public String getType() {
+ return mType;
+ }
+
+ /**
+ * Get enterprise config of this Passpoint credential.
+ * @return Enterprise config
+ * @see WifiEnterpriseConfig
+ */
+ public WifiEnterpriseConfig getEnterpriseConfig() {
+ return new WifiEnterpriseConfig(mEnterpriseConfig);
+ }
+
+ /**
+ * Set enterprise config of this Passpoint credential.
+ * @param config Enterprise config, must be either EAP-TLS or EAP-TTLS
+ * @see WifiEnterpriseConfig
+ */
+ public void setEnterpriseConfig(WifiEnterpriseConfig config) {
+ // TODO
+ }
+
+ /** @hide */
+ public String getCertType() {
+ return mCertType;
+ }
+
+ /** @hide */
+ public String getCertSha256Fingerprint() {
+ return mCertSha256Fingerprint;
+ }
+
+ /** @hide */
+ public String getUserName() {
+ return mUsername;
+ }
+
+ /** @hide */
+ public String getPassword() {
+ // TODO: guarded by connectivity internal
+ return mPasswd;
+ }
+
+ /** @hide */
+ public String getImsi() {
+ return mImsi;
+ }
+
+ /** @hide */
+ public String getMcc() {
+ return mMcc;
+ }
+
+ /** @hide */
+ public String getMnc() {
+ return mMnc;
+ }
+
+ /** @hide */
+ public String getCaRootCertPath() {
+ return mCaRootCert;
+ }
+
+ /** @hide */
+ public String getClientCertPath() {
+ return mClientCert;
+ }
+
+ /**
+ * Get the realm of this Passpoint credential.
+ * @return Realm
+ */
+ public String getRealm() {
+ return mRealm;
+ }
+
+ /**
+ * Set the ream of this Passpoint credential.
+ * @param realm Realm
+ */
+ public void setRealm(String realm) {
+ mRealm = realm;
+ }
+
+ /** @hide */
+ public int getPriority() {
+ if (mUserPreferred) {
+ return 0;
+ }
+
+ return mCrednetialPriority;
+ }
+
+ /**
+ * Get the fully qualified domain name (FQDN) of this Passpoint credential.
+ * @return FQDN
+ */
+ public String getHomeSpFqdn() {
+ return mHomeSpFqdn;
+ }
+
+ /**
+ * Set the fully qualified domain name (FQDN) of this Passpoint credential.
+ * @param fqdn FQDN
+ */
+ public void setHomeFqdn(String fqdn) {
+ mHomeSpFqdn = fqdn;
+ }
+
+
+ /** @hide */
+ public Collection<WifiPasspointDmTree.OtherHomePartners> getOtherHomePartnerList() {
+ return mOtherHomePartnerList;
+ }
+
+ /** @hide */
+ public String getSubscriptionUpdateUsername() {
+ return mSubscriptionUpdateUsername;
+ }
+
+ /** @hide */
+ public String getSubscriptionUpdatePassword() {
+ return mSubscriptionUpdatePassword;
+ }
+
+ /** @hide */
+ public String getPolicyUpdateUri() {
+ return mPolicyUpdateUri;
+ }
+
+ /** @hide */
+ public String getPolicyUpdateInterval() {
+ return mPolicyUpdateInterval;
+ }
+
+ /** @hide */
+ public String getPolicyUpdateUsername() {
+ return mPolicyUpdateUsername;
+ }
+
+ /** @hide */
+ public String getPolicyUpdatePassword() {
+ return mPolicyUpdatePassword;
+ }
+
+ /** @hide */
+ public String getPolicyUpdateRestriction() {
+ return mPolicyUpdateRestriction;
+ }
+
+ /** @hide */
+ public String getPolicyUpdateMethod() {
+ return mPolicyUpdateMethod;
+ }
+
+ /** @hide */
+ public String getCreationDate() {
+ return mCreationDate;
+ }
+
+ /** @hide */
+ public String getExpirationDate() {
+ return mExpirationDate;
+ }
+
+ /** @hide */
+ public void setExpirationDate(String expirationdate) {
+ mExpirationDate = expirationdate;
+ }
+
+ /** @hide */
+ public Collection<WifiPasspointDmTree.PreferredRoamingPartnerList> getPreferredRoamingPartnerList() {
+ return mPreferredRoamingPartnerList;
+ }
+
+ /** @hide */
+ public Collection<WifiPasspointDmTree.HomeOIList> getHomeOiList() {
+ return mHomeOIList;
+ }
+
+ /** @hide */
+ public Collection<WifiPasspointDmTree.MinBackhaulThresholdNetwork> getBackhaulThresholdList() {
+ return mMinBackhaulThresholdNetwork;
+ }
+
+ /** @hide */
+ public Collection<WifiPasspointDmTree.RequiredProtoPortTuple> getRequiredProtoPortList() {
+ return mRequiredProtoPortTuple;
+ }
+
+ /** @hide */
+ public Collection<WifiPasspointDmTree.SPExclusionList> getSPExclusionList() {
+ return mSpExclusionList;
+ }
+
+ /** @hide */
+ public boolean getIsMachineRemediation() {
+ return mIsMachineRemediation;
+ }
+
+ /** @hide */
+ public String getAaaCertUrl() {
+ return mAaaCertUrl;
+ }
+
+ /** @hide */
+ public String getAaaSha256Fingerprint() {
+ return mAaaSha256Fingerprint;
+ }
+
+ /** @hide */
+ public String getSubscriptionUpdateRestriction() {
+ return mSubscriptionUpdateRestriction;
+ }
+
+ /** @hide */
+ public String getSubscriptionUpdateURI() {
+ return mSubscriptionUpdateURI;
+ }
+
+ /** @hide */
+ public String getSubscriptionUpdateInterval() {
+ return mSubscriptionUpdateInterval;
+ }
+
+ /** @hide */
+ public String getFriendlyName() {
+ return mFriendlyName;
+ }
+
+ /** @hide */
+ public String getMaxBssLoad() {
+ return mMaxBssLoad;
+ }
+
+ /** @hide */
+ public boolean getUserPreference() {
+ return mUserPreferred;
+ }
+
+ /** @hide */
+ public boolean getCheckAaaServerCertStatus() {
+ return mCheckAaaServerCertStatus;
+ }
+
+ /** @hide */
+ public void setUserPreference(boolean value) {
+ mUserPreferred = value;
+ }
+
+ @Override
+ /** @hide */
+ public boolean equals(Object obj) {
+ boolean result = false;
+ if (obj instanceof WifiPasspointCredential) {
+ final WifiPasspointCredential other = (WifiPasspointCredential) obj;
+ if (this.mType.equals(other.mType)) {
+ if (this.mType.equals("TTLS")) {
+ result = this.mUsername.equals(other.mUsername) &&
+ this.mPasswd.equals(other.mPasswd) &&
+ this.mRealm.equals(other.mRealm) &&
+ this.mHomeSpFqdn.equals(other.mHomeSpFqdn);
+ }
+ if (this.mType.equals("TLS")) {
+ result = this.mRealm.equals(other.mRealm) &&
+ this.mHomeSpFqdn.equals(other.mHomeSpFqdn) &&
+ this.mClientCert.equals(other.mClientCert);
+ }
+ if (this.mType.equals("SIM")) {
+ result = this.mMcc.equals(other.mMcc) &&
+ this.mMnc.equals(other.mMnc) &&
+ this.mImsi.equals(other.mImsi) &&
+ this.mHomeSpFqdn.equals(other.mHomeSpFqdn);
+ }
+ }
+ }
+ return result;
+ }
+
+ @Override
+ /** @hide */
+ public String toString() {
+ StringBuffer sb = new StringBuffer();
+ String none = "<none>";
+
+ if (!DBG) {
+ sb.append(none);
+ } else {
+ sb.append(", UpdateIdentifier: ")
+ .append(mUpdateIdentifier == null ? none : mUpdateIdentifier)
+ .append(", SubscriptionUpdateMethod: ")
+ .append(mSubscriptionUpdateMethod == null ? none : mSubscriptionUpdateMethod)
+ .append(", Type: ").append(mType == null ? none : mType)
+ .append(", Username: ").append(mUsername == null ? none : mUsername)
+ .append(", Passwd: ").append(mPasswd == null ? none : mPasswd)
+ .append(", SubDMAccUsername: ")
+ .append(mSubscriptionUpdateUsername == null ? none : mSubscriptionUpdateUsername)
+ .append(", SubDMAccPassword: ")
+ .append(mSubscriptionUpdatePassword == null ? none : mSubscriptionUpdatePassword)
+ .append(", PolDMAccUsername: ")
+ .append(mPolicyUpdateUsername == null ? none : mPolicyUpdateUsername)
+ .append(", PolDMAccPassword: ")
+ .append(mPolicyUpdatePassword == null ? none : mPolicyUpdatePassword)
+ .append(", Imsi: ").append(mImsi == null ? none : mImsi)
+ .append(", Mcc: ").append(mMcc == null ? none : mMcc)
+ .append(", Mnc: ").append(mMnc == null ? none : mMnc)
+ .append(", CaRootCert: ").append(mCaRootCert == null ? none : mCaRootCert)
+ .append(", Realm: ").append(mRealm == null ? none : mRealm)
+ .append(", Priority: ").append(mCrednetialPriority)
+ .append(", Fqdn: ").append(mHomeSpFqdn == null ? none : mHomeSpFqdn)
+ .append(", Otherhomepartners: ")
+ .append(mOtherHomePartnerList == null ? none : mOtherHomePartnerList)
+ .append(", ExpirationDate: ")
+ .append(mExpirationDate == null ? none : mExpirationDate)
+ .append(", MaxBssLoad: ").append(mMaxBssLoad == null ? none : mMaxBssLoad)
+ .append(", SPExclusionList: ").append(mSpExclusionList);
+
+ if (mPreferredRoamingPartnerList != null) {
+ sb.append("PreferredRoamingPartnerList:");
+ for (WifiPasspointDmTree.PreferredRoamingPartnerList prpListItem : mPreferredRoamingPartnerList) {
+ sb.append("[fqdnmatch:").append(prpListItem.FQDN_Match).
+ append(", priority:").append(prpListItem.Priority).
+ append(", country:").append(prpListItem.Country).append("]");
+ }
+ }
+
+ if (mHomeOIList != null) {
+ sb.append("HomeOIList:");
+ for (WifiPasspointDmTree.HomeOIList HomeOIListItem : mHomeOIList) {
+ sb.append("[HomeOI:").append(HomeOIListItem.HomeOI).
+ append(", HomeOIRequired:").append(HomeOIListItem.HomeOIRequired).
+ append("]");
+ }
+ }
+
+ if (mMinBackhaulThresholdNetwork != null) {
+ sb.append("BackHaulThreshold:");
+ for (WifiPasspointDmTree.MinBackhaulThresholdNetwork BhtListItem : mMinBackhaulThresholdNetwork) {
+ sb.append("[networkType:").append(BhtListItem.NetworkType).
+ append(", dlBandwidth:").append(BhtListItem.DLBandwidth).
+ append(", ulBandwidth:").append(BhtListItem.ULBandwidth).
+ append("]");
+ }
+ }
+
+ if (mRequiredProtoPortTuple != null) {
+ sb.append("WifiMORequiredProtoPortTupleList:");
+ for (WifiPasspointDmTree.RequiredProtoPortTuple RpptListItem : mRequiredProtoPortTuple) {
+ sb.append("[IPProtocol:").append(RpptListItem.IPProtocol).
+ append(", PortNumber:").append(RpptListItem.PortNumber).
+ append("]");
+ }
+ }
+ }
+ return sb.toString();
+ }
+
+ /** Implement the Parcelable interface {@hide} */
+ public int describeContents() {
+ return 0;
+ }
+
+ /** Implement the Parcelable interface {@hide} */
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeString(mWifiSpFqdn);
+ dest.writeString(mCredentialName);
+ dest.writeString(mType);
+ dest.writeInt(mCrednetialPriority);
+ dest.writeString(mHomeSpFqdn);
+ dest.writeString(mRealm);
+ }
+
+ /** Implement the Parcelable interface {@hide} */
+ public void readFromParcel(Parcel in) {
+ mWifiSpFqdn = in.readString();
+ mCredentialName = in.readString();
+ mType = in.readString();
+ mCrednetialPriority = in.readInt();
+ mHomeSpFqdn = in.readString();
+ mRealm = in.readString();
+ }
+
+ /** Implement the Parcelable interface {@hide} */
+ public static final Creator<WifiPasspointCredential> CREATOR =
+ new Creator<WifiPasspointCredential>() {
+ public WifiPasspointCredential createFromParcel(Parcel in) {
+ WifiPasspointCredential pc = new WifiPasspointCredential();
+ pc.mWifiSpFqdn = in.readString();
+ pc.mCredentialName = in.readString();
+ pc.mType = in.readString();
+ pc.mCrednetialPriority = in.readInt();
+ pc.mHomeSpFqdn = in.readString();
+ pc.mRealm = in.readString();
+ return pc;
+ }
+
+ public WifiPasspointCredential[] newArray(int size) {
+ return new WifiPasspointCredential[size];
+ }
+ };
+
+ /** @hide */
+ public int compareTo(WifiPasspointCredential another) {
+
+ //The smaller the higher
+ if (mCrednetialPriority < another.mCrednetialPriority) {
+ return -1;
+ } else if (mCrednetialPriority == another.mCrednetialPriority) {
+ return this.mType.compareTo(another.mType);
+ } else {
+ return 1;
+ }
+ }
+
+ @Override
+ /** @hide */
+ public int hashCode() {
+ int hash = 208;
+ if (mType != null) {
+ hash += mType.hashCode();
+ }
+ if (mRealm != null) {
+ hash += mRealm.hashCode();
+ }
+ if (mHomeSpFqdn != null) {
+ hash += mHomeSpFqdn.hashCode();
+ }
+ if (mUsername != null) {
+ hash += mUsername.hashCode();
+ }
+ if (mPasswd != null) {
+ hash += mPasswd.hashCode();
+ }
+
+ return hash;
+ }
+}
diff --git a/wifi/java/android/net/wifi/passpoint/WifiPasspointDmTree.aidl b/wifi/java/android/net/wifi/passpoint/WifiPasspointDmTree.aidl
new file mode 100644
index 0000000..6a88b2e
--- /dev/null
+++ b/wifi/java/android/net/wifi/passpoint/WifiPasspointDmTree.aidl
@@ -0,0 +1,19 @@
+/**
+ * Copyright (c) 2014, 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.passpoint;
+
+parcelable WifiPasspointDmTree;
diff --git a/wifi/java/android/net/wifi/passpoint/WifiPasspointDmTree.java b/wifi/java/android/net/wifi/passpoint/WifiPasspointDmTree.java
new file mode 100644
index 0000000..bbf5fc6
--- /dev/null
+++ b/wifi/java/android/net/wifi/passpoint/WifiPasspointDmTree.java
@@ -0,0 +1,1377 @@
+/*
+ * Copyright (C) 2014 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.passpoint;
+
+import android.os.Parcelable;
+import android.os.Parcel;
+import android.util.Log;
+
+import java.util.HashMap;
+
+/**
+ * Required Mobile Device Management Tree Structure
+ *
+ * +----------+
+ * | ./(Root) |
+ * +----+-----+
+ * |
+ * +---------+ | +---------+ +---------+
+ * | DevInfo |-----------+---------| Wi-Fi |--|SP FQDN* |
+ * +---------+ | +---------+ +---------+
+ * +---------+ | |
+ * |DevDetail|-----------+ +-----------------------+
+ * +---------+ |PerproviderSubscription|--<X>+
+ * +-----------------------+
+ *
+ * This class contains all nodes start from Wi-Fi
+ * @hide
+ **/
+public class WifiPasspointDmTree implements Parcelable {
+ private final static String TAG = "WifiTree";
+ public int PpsMoId;//plugfest used only
+ public HashMap<String, SpFqdn> spFqdn = new HashMap<String, SpFqdn>();//Maps.newHashMap();
+
+ public SpFqdn createSpFqdn(String name) {
+ SpFqdn obj = new SpFqdn(name);
+ spFqdn.put(name, obj);
+ return obj;
+ }
+
+ public static class SpFqdn implements Parcelable {
+ public String nodeName;
+ public PerProviderSubscription perProviderSubscription = new PerProviderSubscription();
+
+ public SpFqdn(String name) {
+ nodeName = name;
+ }
+
+ public SpFqdn() {
+ }
+
+ public SpFqdn(Parcel in) {
+ readFromParcel(in);
+ }
+
+ public int describeContents() {
+ return 0;
+ }
+
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeString(nodeName);
+ out.writeParcelable(perProviderSubscription, flags);
+ }
+
+ public void readFromParcel(Parcel in) {
+ if (in == null) {
+ //log here
+ } else {
+ nodeName = in.readString();
+ perProviderSubscription = in.readParcelable(PerProviderSubscription.class
+ .getClassLoader());
+ }
+ }
+
+ public static final Parcelable.Creator<SpFqdn> CREATOR = new Parcelable.Creator<SpFqdn>() {
+ public SpFqdn createFromParcel(Parcel in) {
+ return new SpFqdn(in);
+ }
+
+ public SpFqdn[] newArray(int size) {
+ return new SpFqdn[size];
+ }
+ };
+ }
+
+ /**
+ * PerProviderSubscription
+ **/
+ public static class PerProviderSubscription implements Parcelable {
+ /**
+ * PerProviderSubscription/UpdateIdentifier
+ **/
+ public String UpdateIdentifier;
+ public HashMap<String, CredentialInfo> credentialInfo = new HashMap<String, CredentialInfo>();
+
+ public CredentialInfo createCredentialInfo(String name) {
+ CredentialInfo obj = new CredentialInfo(name);
+ credentialInfo.put(name, obj);
+ return obj;
+ }
+
+ public PerProviderSubscription() {
+ }
+
+ public PerProviderSubscription(Parcel in) {
+ readFromParcel(in);
+ }
+
+ public int describeContents() {
+ return 0;
+ }
+
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeString(UpdateIdentifier);
+ out.writeMap(credentialInfo);
+ }
+
+ public void readFromParcel(Parcel in) {
+ if (in == null) {
+ //log here
+ } else {
+ UpdateIdentifier = in.readString();
+ in.readMap(credentialInfo, CredentialInfo.class.getClassLoader());
+ }
+ }
+
+ public static final Parcelable.Creator<PerProviderSubscription> CREATOR = new Parcelable.Creator<PerProviderSubscription>() {
+ public PerProviderSubscription createFromParcel(Parcel in) {
+ return new PerProviderSubscription(in);
+ }
+
+ public PerProviderSubscription[] newArray(int size) {
+ return new PerProviderSubscription[size];
+ }
+ };
+
+ }
+
+ /**
+ * PerProviderSubscription/<X+>
+ * This interior node contains the Home SP information, subscription policy, management and credential information.
+ **/
+ public static class CredentialInfo implements Parcelable {
+ public String nodeName;
+ public Policy policy = new Policy();
+ public String credentialPriority;
+ public HashMap<String, AAAServerTrustRoot> aAAServerTrustRoot = new HashMap<String, AAAServerTrustRoot>();
+ public SubscriptionUpdate subscriptionUpdate = new SubscriptionUpdate();
+ public HomeSP homeSP = new HomeSP();
+ public SubscriptionParameters subscriptionParameters = new SubscriptionParameters();
+ public Credential credential = new Credential();
+ public Extension extension = new Extension();
+
+ public CredentialInfo(String nn) {
+ nodeName = nn;
+ }
+
+ public AAAServerTrustRoot createAAAServerTrustRoot(String name, String url, String fp) {
+ AAAServerTrustRoot obj = new AAAServerTrustRoot(name, url, fp);
+ aAAServerTrustRoot.put(name, obj);
+ return obj;
+ }
+
+ public CredentialInfo() {
+ }
+
+ public CredentialInfo(Parcel in) {
+ readFromParcel(in);
+ }
+
+ public int describeContents() {
+ return 0;
+ }
+
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeString(nodeName);
+ out.writeParcelable(policy, flags);
+ out.writeString(credentialPriority);
+ out.writeMap(aAAServerTrustRoot);
+ out.writeParcelable(subscriptionUpdate, flags);
+ out.writeParcelable(homeSP, flags);
+ out.writeParcelable(subscriptionParameters, flags);
+ out.writeParcelable(credential, flags);
+ //out.writeParcelable(extension, flags);
+ }
+
+ public void readFromParcel(Parcel in) {
+ if (in == null) {
+ //log here
+ } else {
+ nodeName = in.readString();
+ policy = in.readParcelable(Policy.class.getClassLoader());
+ credentialPriority = in.readString();
+ in.readMap(aAAServerTrustRoot, AAAServerTrustRoot.class.getClassLoader());
+ subscriptionUpdate = in.readParcelable(SubscriptionUpdate.class.getClassLoader());
+ homeSP = in.readParcelable(HomeSP.class.getClassLoader());
+ subscriptionParameters = in.readParcelable(SubscriptionParameters.class
+ .getClassLoader());
+ credential = in.readParcelable(Credential.class.getClassLoader());
+ //extension = in.readParcelable(Extension.class.getClassLoader());
+ }
+ }
+
+ public static final Parcelable.Creator<CredentialInfo> CREATOR = new Parcelable.Creator<CredentialInfo>() {
+ public CredentialInfo createFromParcel(Parcel in) {
+ return new CredentialInfo(in);
+ }
+
+ public CredentialInfo[] newArray(int size) {
+ return new CredentialInfo[size];
+ }
+ };
+
+ }
+
+ /**
+ * PerProviderSubscription/<X+>/Policy
+ **/
+ public static class Policy implements Parcelable {
+ public HashMap<String, PreferredRoamingPartnerList> preferredRoamingPartnerList = new HashMap<String, PreferredRoamingPartnerList>();
+ public HashMap<String, MinBackhaulThresholdNetwork> minBackhaulThreshold = new HashMap<String, MinBackhaulThresholdNetwork>();
+ public PolicyUpdate policyUpdate = new PolicyUpdate();
+ public HashMap<String, SPExclusionList> sPExclusionList = new HashMap<String, SPExclusionList>();
+ public HashMap<String, RequiredProtoPortTuple> requiredProtoPortTuple = new HashMap<String, RequiredProtoPortTuple>();
+ public String maximumBSSLoadValue;
+
+ public PreferredRoamingPartnerList createPreferredRoamingPartnerList(String name,
+ String fqdn, String priority, String country) {
+ PreferredRoamingPartnerList obj = new PreferredRoamingPartnerList(name, fqdn, priority,
+ country);
+ preferredRoamingPartnerList.put(name, obj);
+ return obj;
+ }
+
+ public MinBackhaulThresholdNetwork createMinBackhaulThreshold(String name, String type,
+ String dl, String ul) {
+ MinBackhaulThresholdNetwork obj = new MinBackhaulThresholdNetwork(name, type, dl, ul);
+ minBackhaulThreshold.put(name, obj);
+ return obj;
+ }
+
+ public SPExclusionList createSPExclusionList(String name, String ssid) {
+ SPExclusionList obj = new SPExclusionList(name, ssid);
+ sPExclusionList.put(name, obj);
+ return obj;
+ }
+
+ public RequiredProtoPortTuple createRequiredProtoPortTuple(String name, String proto,
+ String port) {
+ RequiredProtoPortTuple obj = new RequiredProtoPortTuple(name, proto, port);
+ requiredProtoPortTuple.put(name, obj);
+ return obj;
+ }
+
+ public Policy() {
+ }
+
+ public Policy(Parcel in) {
+ readFromParcel(in);
+ }
+
+ public int describeContents() {
+ return 0;
+ }
+
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeMap(preferredRoamingPartnerList);
+ out.writeMap(minBackhaulThreshold);
+ out.writeParcelable(policyUpdate, flags);
+ out.writeMap(sPExclusionList);
+ out.writeMap(requiredProtoPortTuple);
+ out.writeString(maximumBSSLoadValue);
+ }
+
+ public void readFromParcel(Parcel in) {
+ if (in == null) {
+ //log here
+ } else {
+ in.readMap(preferredRoamingPartnerList,
+ PreferredRoamingPartnerList.class.getClassLoader());
+ in.readMap(minBackhaulThreshold, MinBackhaulThresholdNetwork.class.getClassLoader());
+ policyUpdate = in.readParcelable(PolicyUpdate.class.getClassLoader());
+ in.readMap(sPExclusionList, SPExclusionList.class.getClassLoader());
+ in.readMap(requiredProtoPortTuple, RequiredProtoPortTuple.class.getClassLoader());
+ maximumBSSLoadValue = in.readString();
+
+ }
+ }
+
+ public static final Parcelable.Creator<Policy> CREATOR = new Parcelable.Creator<Policy>() {
+ public Policy createFromParcel(Parcel in) {
+ return new Policy(in);
+ }
+
+ public Policy[] newArray(int size) {
+ return new Policy[size];
+ }
+ };
+
+ }
+
+ /**
+ * PerProviderSubscription/<X+>/Policy/PreferredRoamingPartnerList/<X+>
+ **/
+ public static class PreferredRoamingPartnerList implements Parcelable {
+ public String nodeName;
+ public String FQDN_Match; //maximum 255 + ",includeSubdomains", equals 273
+ public String Priority;
+ public String Country; // maximum 600 octets
+
+ public PreferredRoamingPartnerList(String nn, String f, String p, String c) {
+ nodeName = nn;
+ FQDN_Match = f;
+ Priority = p;
+ Country = c;
+ }
+
+ public PreferredRoamingPartnerList() {
+ }
+
+ public PreferredRoamingPartnerList(Parcel in) {
+ readFromParcel(in);
+ }
+
+ public int describeContents() {
+ return 0;
+ }
+
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeString(nodeName);
+ out.writeString(FQDN_Match);
+ out.writeString(Priority);
+ out.writeString(Country);
+ }
+
+ public void readFromParcel(Parcel in) {
+ if (in == null) {
+ //log here
+ } else {
+ nodeName = in.readString();
+ FQDN_Match = in.readString();
+ Priority = in.readString();
+ Country = in.readString();
+ }
+ }
+
+ public static final Parcelable.Creator<PreferredRoamingPartnerList> CREATOR = new Parcelable.Creator<PreferredRoamingPartnerList>() {
+ public PreferredRoamingPartnerList createFromParcel(Parcel in) {
+ return new PreferredRoamingPartnerList(in);
+ }
+
+ public PreferredRoamingPartnerList[] newArray(int size) {
+ return new PreferredRoamingPartnerList[size];
+ }
+ };
+ }
+
+ /**
+ * PerProviderSubscription/<X+>/Policy/MinBackhaulThreshold
+ **/
+ public static class MinBackhaulThresholdNetwork implements Parcelable {
+ public String nodeName;
+ public String NetworkType;
+ public String DLBandwidth;
+ public String ULBandwidth;
+
+ public MinBackhaulThresholdNetwork(String nn, String nt, String d, String u) {
+ nodeName = nn;
+ NetworkType = nt;
+ DLBandwidth = d;
+ ULBandwidth = u;
+ }
+
+ public MinBackhaulThresholdNetwork() {
+ }
+
+ public MinBackhaulThresholdNetwork(Parcel in) {
+ readFromParcel(in);
+ }
+
+ public int describeContents() {
+ return 0;
+ }
+
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeString(nodeName);
+ out.writeString(NetworkType);
+ out.writeString(DLBandwidth);
+ out.writeString(ULBandwidth);
+ }
+
+ public void readFromParcel(Parcel in) {
+ if (in == null) {
+ //log here
+ } else {
+ nodeName = in.readString();
+ NetworkType = in.readString();
+ DLBandwidth = in.readString();
+ ULBandwidth = in.readString();
+ }
+ }
+
+ public static final Parcelable.Creator<MinBackhaulThresholdNetwork> CREATOR = new Parcelable.Creator<MinBackhaulThresholdNetwork>() {
+ public MinBackhaulThresholdNetwork createFromParcel(Parcel in) {
+ return new MinBackhaulThresholdNetwork(in);
+ }
+
+ public MinBackhaulThresholdNetwork[] newArray(int size) {
+ return new MinBackhaulThresholdNetwork[size];
+ }
+ };
+
+ }
+
+ /**
+ * PerProviderSubscription/<X+>/Policy/PolicyUpdate
+ **/
+ public static class PolicyUpdate implements Parcelable {
+ public String UpdateInterval;
+ public String UpdateMethod;
+ public String Restriction;
+ public String URI;
+ public UsernamePassword usernamePassword = new UsernamePassword();
+ public String Other;
+ public TrustRoot trustRoot = new TrustRoot();
+
+ public PolicyUpdate() {
+ }
+
+ public PolicyUpdate(Parcel in) {
+ readFromParcel(in);
+ }
+
+ public int describeContents() {
+ return 0;
+ }
+
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeString(UpdateInterval);
+ out.writeString(UpdateMethod);
+ out.writeString(Restriction);
+ out.writeString(URI);
+ out.writeParcelable(usernamePassword, flags);
+ out.writeString(Other);
+ out.writeParcelable(trustRoot, flags);
+
+ }
+
+ public void readFromParcel(Parcel in) {
+ if (in == null) {
+ //log here
+ } else {
+ UpdateInterval = in.readString();
+ UpdateMethod = in.readString();
+ Restriction = in.readString();
+ URI = in.readString();
+ usernamePassword = in.readParcelable(UsernamePassword.class.getClassLoader());
+ Other = in.readString();
+ trustRoot = in.readParcelable(TrustRoot.class.getClassLoader());
+ }
+ }
+
+ public static final Parcelable.Creator<PolicyUpdate> CREATOR = new Parcelable.Creator<PolicyUpdate>() {
+ public PolicyUpdate createFromParcel(Parcel in) {
+ return new PolicyUpdate(in);
+ }
+
+ public PolicyUpdate[] newArray(int size) {
+ return new PolicyUpdate[size];
+ }
+ };
+ }
+
+ /**
+ * PerProviderSubscription/<X+>/Policy/SPExclusionList
+ **/
+ public static class SPExclusionList implements Parcelable {
+ public String nodeName;
+ public String SSID;
+
+ public SPExclusionList(String nn, String s) {
+ nodeName = nn;
+ SSID = s;
+ }
+
+ public SPExclusionList() {
+ }
+
+ public SPExclusionList(Parcel in) {
+ readFromParcel(in);
+ }
+
+ public int describeContents() {
+ return 0;
+ }
+
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeString(nodeName);
+ out.writeString(SSID);
+ }
+
+ public void readFromParcel(Parcel in) {
+ if (in == null) {
+ //log here
+ } else {
+ nodeName = in.readString();
+ SSID = in.readString();
+ }
+ }
+
+ public static final Parcelable.Creator<SPExclusionList> CREATOR = new Parcelable.Creator<SPExclusionList>() {
+ public SPExclusionList createFromParcel(Parcel in) {
+ return new SPExclusionList(in);
+ }
+
+ public SPExclusionList[] newArray(int size) {
+ return new SPExclusionList[size];
+ }
+ };
+ }
+
+ /**
+ * PerProviderSubscription/<X+>/Policy/RequiredProtoPortTuple
+ **/
+ public static class RequiredProtoPortTuple implements Parcelable {
+ public String nodeName;
+ public String IPProtocol;
+ public String PortNumber;
+
+ public RequiredProtoPortTuple() {
+ }
+
+ public RequiredProtoPortTuple(String nn, String protocol, String port) {
+ nodeName = nn;
+ IPProtocol = protocol;
+ PortNumber = port;
+ }
+
+ public RequiredProtoPortTuple(Parcel in) {
+ readFromParcel(in);
+ }
+
+ public int describeContents() {
+ return 0;
+ }
+
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeString(nodeName);
+ out.writeString(IPProtocol);
+ out.writeString(PortNumber);
+ }
+
+ public void readFromParcel(Parcel in) {
+ if (in == null) {
+ //log here
+ } else {
+ nodeName = in.readString();
+ IPProtocol = in.readString();
+ PortNumber = in.readString();
+ }
+ }
+
+ public static final Parcelable.Creator<RequiredProtoPortTuple> CREATOR = new Parcelable.Creator<RequiredProtoPortTuple>() {
+ public RequiredProtoPortTuple createFromParcel(Parcel in) {
+ return new RequiredProtoPortTuple(in);
+ }
+
+ public RequiredProtoPortTuple[] newArray(int size) {
+ return new RequiredProtoPortTuple[size];
+ }
+ };
+ }
+
+ /**
+ * PerProviderSubscription/<X+>/AAAServerTrustRoot
+ **/
+ public static class AAAServerTrustRoot implements Parcelable {
+ public String nodeName;
+ public String CertURL;
+ public String CertSHA256Fingerprint;
+
+ public AAAServerTrustRoot(String nn, String url, String fp) {
+ nodeName = nn;
+ CertURL = url;
+ CertSHA256Fingerprint = fp;
+ }
+
+ public AAAServerTrustRoot() {
+ }
+
+ public AAAServerTrustRoot(Parcel in) {
+ readFromParcel(in);
+ }
+
+ public int describeContents() {
+ return 0;
+ }
+
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeString(nodeName);
+ out.writeString(CertURL);
+ out.writeString(CertSHA256Fingerprint);
+ }
+
+ public void readFromParcel(Parcel in) {
+ if (in == null) {
+ //log here
+ } else {
+ nodeName = in.readString();
+ CertURL = in.readString();
+ CertSHA256Fingerprint = in.readString();
+ }
+ }
+
+ public static final Parcelable.Creator<AAAServerTrustRoot> CREATOR = new Parcelable.Creator<AAAServerTrustRoot>() {
+ public AAAServerTrustRoot createFromParcel(Parcel in) {
+ return new AAAServerTrustRoot(in);
+ }
+
+ public AAAServerTrustRoot[] newArray(int size) {
+ return new AAAServerTrustRoot[size];
+ }
+ };
+ }
+
+ /**
+ * PerProviderSubscription/<X+>/SubscriptionUpdate
+ **/
+ public static class SubscriptionUpdate implements Parcelable {
+ public String UpdateInterval;
+ public String UpdateMethod;
+ public String Restriction;
+ public String URI;
+ public UsernamePassword usernamePassword = new UsernamePassword();
+ public String Other;
+ public TrustRoot trustRoot = new TrustRoot();
+
+ public SubscriptionUpdate() {
+ }
+
+ public SubscriptionUpdate(Parcel in) {
+ readFromParcel(in);
+ }
+
+ public int describeContents() {
+ return 0;
+ }
+
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeString(UpdateInterval);
+ out.writeString(UpdateMethod);
+ out.writeString(Restriction);
+ out.writeString(URI);
+ out.writeParcelable(usernamePassword, flags);
+ out.writeString(Other);
+ out.writeParcelable(trustRoot, flags);
+ }
+
+ public void readFromParcel(Parcel in) {
+ if (in == null) {
+ //log here
+ } else {
+ UpdateInterval = in.readString();
+ UpdateMethod = in.readString();
+ Restriction = in.readString();
+ URI = in.readString();
+ usernamePassword = in.readParcelable(UsernamePassword.class.getClassLoader());
+ Other = in.readString();
+ trustRoot = in.readParcelable(TrustRoot.class.getClassLoader());
+ }
+ }
+
+ public static final Parcelable.Creator<SubscriptionUpdate> CREATOR = new Parcelable.Creator<SubscriptionUpdate>() {
+ public SubscriptionUpdate createFromParcel(Parcel in) {
+ return new SubscriptionUpdate(in);
+ }
+
+ public SubscriptionUpdate[] newArray(int size) {
+ return new SubscriptionUpdate[size];
+ }
+ };
+
+ }
+
+ /**
+ * PerProviderSubscription/<X+>/Policy/PolicyUpdate/TrustRoot
+ * PerProviderSubscription/<X+>/SubscriptionUpdate/TrustRoot
+ * PerProviderSubscription/<X+>/AAAServerTrustRoot/<X+>
+ **/
+ public static class TrustRoot implements Parcelable {
+ public String CertURL;
+ public String CertSHA256Fingerprint;
+
+ public TrustRoot() {
+ }
+
+ public TrustRoot(Parcel in) {
+ readFromParcel(in);
+ }
+
+ public int describeContents() {
+ return 0;
+ }
+
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeString(CertURL);
+ out.writeString(CertSHA256Fingerprint);
+ }
+
+ public void readFromParcel(Parcel in) {
+ if (in == null) {
+ //log here
+ } else {
+ CertURL = in.readString();
+ CertSHA256Fingerprint = in.readString();
+ }
+ }
+
+ public static final Parcelable.Creator<TrustRoot> CREATOR = new Parcelable.Creator<TrustRoot>() {
+ public TrustRoot createFromParcel(Parcel in) {
+ return new TrustRoot(in);
+ }
+
+ public TrustRoot[] newArray(int size) {
+ return new TrustRoot[size];
+ }
+ };
+ }
+
+ /**
+ * PerProviderSubscription/<X+>/Policy/PolicyUpdate/UsernamePassword
+ * PerProviderSubscription/<X+>/SubscriptionUpdate/UsernamePassword
+ * PerProviderSubscription/<X+>/Credential/UsernamePassword
+ **/
+ public static class UsernamePassword implements Parcelable {
+ public String Username;
+ public String Password;
+ //following are Credential node used only
+ public boolean MachineManaged;
+ public String SoftTokenApp;
+ public String AbleToShare;
+ public EAPMethod eAPMethod = new EAPMethod();
+
+ public UsernamePassword() {
+ }
+
+ public UsernamePassword(Parcel in) {
+ readFromParcel(in);
+ }
+
+ public int describeContents() {
+ return 0;
+ }
+
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeString(Username);
+ out.writeString(Password);
+ out.writeInt(MachineManaged ? 1 : 0);
+ out.writeString(SoftTokenApp);
+ out.writeString(AbleToShare);
+ out.writeParcelable(eAPMethod, flags);
+ }
+
+ public void readFromParcel(Parcel in) {
+ if (in == null) {
+ //log here
+ } else {
+ Username = in.readString();
+ Password = in.readString();
+ MachineManaged = (in.readInt() == 1) ? true : false;
+ SoftTokenApp = in.readString();
+ AbleToShare = in.readString();
+ eAPMethod = in.readParcelable(EAPMethod.class.getClassLoader());
+ }
+ }
+
+ public static final Parcelable.Creator<UsernamePassword> CREATOR = new Parcelable.Creator<UsernamePassword>() {
+ public UsernamePassword createFromParcel(Parcel in) {
+ return new UsernamePassword(in);
+ }
+
+ public UsernamePassword[] newArray(int size) {
+ return new UsernamePassword[size];
+ }
+ };
+
+ }
+
+ /**
+ * PerProviderSubscription/<X+>/Credential/UsernamePassword/EAPMethod
+ **/
+ public static class EAPMethod implements Parcelable {
+ public String EAPType;
+ public String VendorId;
+ public String VendorType;
+ public String InnerEAPType;
+ public String InnerVendorId;
+ public String InnerVendorType;
+ public String InnerMethod;
+
+ public EAPMethod() {
+ }
+
+ public EAPMethod(Parcel in) {
+ readFromParcel(in);
+ }
+
+ public int describeContents() {
+ return 0;
+ }
+
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeString(EAPType);
+ out.writeString(VendorId);
+ out.writeString(VendorType);
+ out.writeString(InnerEAPType);
+ out.writeString(InnerVendorId);
+ out.writeString(InnerVendorType);
+ out.writeString(InnerMethod);
+ }
+
+ public void readFromParcel(Parcel in) {
+ if (in == null) {
+ //log here
+ } else {
+ EAPType = in.readString();
+ VendorId = in.readString();
+ VendorType = in.readString();
+ InnerEAPType = in.readString();
+ InnerVendorId = in.readString();
+ InnerVendorType = in.readString();
+ InnerMethod = in.readString();
+ }
+ }
+
+ public static final Parcelable.Creator<EAPMethod> CREATOR = new Parcelable.Creator<EAPMethod>() {
+ public EAPMethod createFromParcel(Parcel in) {
+ return new EAPMethod(in);
+ }
+
+ public EAPMethod[] newArray(int size) {
+ return new EAPMethod[size];
+ }
+ };
+ }
+
+ /**
+ * PerProviderSubscription/<X+>/HomeSP
+ **/
+ public static class HomeSP implements Parcelable {
+ public HashMap<String, NetworkID> networkID = new HashMap<String, NetworkID>();
+ public String FriendlyName;
+ public String IconURL;
+ public String FQDN;
+ public HashMap<String, HomeOIList> homeOIList = new HashMap<String, HomeOIList>();
+ public HashMap<String, OtherHomePartners> otherHomePartners = new HashMap<String, OtherHomePartners>();
+ public String RoamingConsortiumOI;
+
+ public NetworkID createNetworkID(String name, String ssid, String hessid) {
+ NetworkID obj = new NetworkID(name, ssid, hessid);
+ networkID.put(name, obj);
+ return obj;
+ }
+
+ public HomeOIList createHomeOIList(String name, String homeoi, boolean required) {
+ HomeOIList obj = new HomeOIList(name, homeoi, required);
+ homeOIList.put(name, obj);
+ return obj;
+ }
+
+ public OtherHomePartners createOtherHomePartners(String name, String fqdn) {
+ OtherHomePartners obj = new OtherHomePartners(name, fqdn);
+ otherHomePartners.put(name, obj);
+ return obj;
+ }
+
+ public HomeSP() {
+ }
+
+ public HomeSP(Parcel in) {
+ readFromParcel(in);
+ }
+
+ public int describeContents() {
+ return 0;
+ }
+
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeMap(networkID);
+ out.writeString(FriendlyName);
+ out.writeString(IconURL);
+ out.writeString(FQDN);
+ out.writeMap(homeOIList);
+ out.writeMap(otherHomePartners);
+ out.writeString(RoamingConsortiumOI);
+ }
+
+ public void readFromParcel(Parcel in) {
+ if (in == null) {
+ //log here
+ } else {
+ in.readMap(networkID, NetworkID.class.getClassLoader());
+ FriendlyName = in.readString();
+ IconURL = in.readString();
+ FQDN = in.readString();
+ in.readMap(homeOIList, HomeOIList.class.getClassLoader());
+ in.readMap(otherHomePartners, OtherHomePartners.class.getClassLoader());
+ RoamingConsortiumOI = in.readString();
+ }
+ }
+
+ public static final Parcelable.Creator<HomeSP> CREATOR = new Parcelable.Creator<HomeSP>() {
+ public HomeSP createFromParcel(Parcel in) {
+ return new HomeSP(in);
+ }
+
+ public HomeSP[] newArray(int size) {
+ return new HomeSP[size];
+ }
+ };
+
+ }
+
+ /**
+ * PerProviderSubscription/<X+>/HomeSP/NetworkID
+ **/
+ public static class NetworkID implements Parcelable {
+ public String nodeName;
+ public String SSID;
+ public String HESSID;
+
+ public NetworkID(String nn, String s, String h) {
+ nodeName = nn;
+ SSID = s;
+ HESSID = h;
+ }
+
+ public NetworkID() {
+ }
+
+ public NetworkID(Parcel in) {
+ readFromParcel(in);
+ }
+
+ public int describeContents() {
+ return 0;
+ }
+
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeString(nodeName);
+ out.writeString(SSID);
+ out.writeString(HESSID);
+ }
+
+ public void readFromParcel(Parcel in) {
+ if (in == null) {
+ //log here
+ } else {
+ nodeName = in.readString();
+ SSID = in.readString();
+ HESSID = in.readString();
+ }
+ }
+
+ public static final Parcelable.Creator<NetworkID> CREATOR = new Parcelable.Creator<NetworkID>() {
+ public NetworkID createFromParcel(Parcel in) {
+ return new NetworkID(in);
+ }
+
+ public NetworkID[] newArray(int size) {
+ return new NetworkID[size];
+ }
+ };
+
+ }
+
+ /**
+ * PerProviderSubscription/<X+>/HomeSP/HomeOIList
+ **/
+ public static class HomeOIList implements Parcelable {
+ public String nodeName;
+ public String HomeOI;
+ public boolean HomeOIRequired;
+
+ public HomeOIList(String nn, String h, boolean r) {
+ nodeName = nn;
+ HomeOI = h;
+ HomeOIRequired = r;
+ }
+
+ public HomeOIList() {
+ }
+
+ public HomeOIList(Parcel in) {
+ readFromParcel(in);
+ }
+
+ public int describeContents() {
+ return 0;
+ }
+
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeString(nodeName);
+ out.writeString(HomeOI);
+ out.writeInt(HomeOIRequired ? 1 : 0);
+ }
+
+ public void readFromParcel(Parcel in) {
+ if (in == null) {
+ //log here
+ } else {
+ nodeName = in.readString();
+ HomeOI = in.readString();
+ HomeOIRequired = (in.readInt() == 1) ? true : false;
+ }
+ }
+
+ public static final Parcelable.Creator<HomeOIList> CREATOR = new Parcelable.Creator<HomeOIList>() {
+ public HomeOIList createFromParcel(Parcel in) {
+ return new HomeOIList(in);
+ }
+
+ public HomeOIList[] newArray(int size) {
+ return new HomeOIList[size];
+ }
+ };
+
+ }
+
+ /**
+ * PerProviderSubscription/<X+>/HomeSP/OtherHomePartners
+ **/
+ public static class OtherHomePartners implements Parcelable {
+ public String nodeName;
+ public String FQDN;
+
+ public OtherHomePartners(String nn, String f) {
+ nodeName = nn;
+ FQDN = f;
+ }
+
+ public OtherHomePartners() {
+ }
+
+ public OtherHomePartners(Parcel in) {
+ readFromParcel(in);
+ }
+
+ public int describeContents() {
+ return 0;
+ }
+
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeString(nodeName);
+ out.writeString(FQDN);
+ }
+
+ public void readFromParcel(Parcel in) {
+ if (in == null) {
+ //log here
+ } else {
+ nodeName = in.readString();
+ FQDN = in.readString();
+ }
+ }
+
+ public static final Parcelable.Creator<OtherHomePartners> CREATOR = new Parcelable.Creator<OtherHomePartners>() {
+ public OtherHomePartners createFromParcel(Parcel in) {
+ return new OtherHomePartners(in);
+ }
+
+ public OtherHomePartners[] newArray(int size) {
+ return new OtherHomePartners[size];
+ }
+ };
+
+ }
+
+ /**
+ * PerProviderSubscription/<X+>/SubscriptionParameters
+ **/
+ public static class SubscriptionParameters implements Parcelable {
+ public String CreationDate;
+ public String ExpirationDate;
+ public String TypeOfSubscription;
+ public UsageLimits usageLimits = new UsageLimits();
+
+ public SubscriptionParameters() {
+ }
+
+ public SubscriptionParameters(Parcel in) {
+ readFromParcel(in);
+ }
+
+ public int describeContents() {
+ return 0;
+ }
+
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeString(CreationDate);
+ out.writeString(ExpirationDate);
+ out.writeString(TypeOfSubscription);
+ out.writeParcelable(usageLimits, flags);
+ }
+
+ public void readFromParcel(Parcel in) {
+ if (in == null) {
+ //log here
+ } else {
+ CreationDate = in.readString();
+ ExpirationDate = in.readString();
+ TypeOfSubscription = in.readString();
+ usageLimits = in.readParcelable(UsageLimits.class.getClassLoader());
+ }
+ }
+
+ public static final Parcelable.Creator<SubscriptionParameters> CREATOR = new Parcelable.Creator<SubscriptionParameters>() {
+ public SubscriptionParameters createFromParcel(Parcel in) {
+ return new SubscriptionParameters(in);
+ }
+
+ public SubscriptionParameters[] newArray(int size) {
+ return new SubscriptionParameters[size];
+ }
+ };
+
+ }
+
+ /**
+ * PerProviderSubscription/<X+>/SubscriptionParameters/UsageLimits
+ **/
+ public static class UsageLimits implements Parcelable {
+ public String DataLimit;
+ public String StartDate;
+ public String TimeLimit;
+ public String UsageTimePeriod;
+
+ public UsageLimits() {
+ }
+
+ public UsageLimits(Parcel in) {
+ readFromParcel(in);
+ }
+
+ public int describeContents() {
+ return 0;
+ }
+
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeString(DataLimit);
+ out.writeString(StartDate);
+ out.writeString(TimeLimit);
+ out.writeString(UsageTimePeriod);
+ }
+
+ public void readFromParcel(Parcel in) {
+ if (in == null) {
+ //log here
+ } else {
+ DataLimit = in.readString();
+ StartDate = in.readString();
+ TimeLimit = in.readString();
+ UsageTimePeriod = in.readString();
+ }
+ }
+
+ public static final Parcelable.Creator<UsageLimits> CREATOR = new Parcelable.Creator<UsageLimits>() {
+ public UsageLimits createFromParcel(Parcel in) {
+ return new UsageLimits(in);
+ }
+
+ public UsageLimits[] newArray(int size) {
+ return new UsageLimits[size];
+ }
+ };
+ }
+
+ /**
+ * PerProviderSubscription/<X+>/Credential
+ **/
+ public static class Credential implements Parcelable {
+ public String CreationDate;
+ public String ExpirationDate;
+ public UsernamePassword usernamePassword = new UsernamePassword();
+ public DigitalCertificate digitalCertificate = new DigitalCertificate();
+ public String Realm;
+ public boolean CheckAAAServerCertStatus;
+ public SIM sim = new SIM();
+
+ public Credential() {
+ }
+
+ public Credential(Parcel in) {
+ readFromParcel(in);
+ }
+
+ public int describeContents() {
+ return 0;
+ }
+
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeString(CreationDate);
+ out.writeString(ExpirationDate);
+ out.writeParcelable(usernamePassword, flags);
+ out.writeParcelable(digitalCertificate, flags);
+ out.writeString(Realm);
+ out.writeInt(CheckAAAServerCertStatus ? 1 : 0);
+ out.writeParcelable(sim, flags);
+ }
+
+ public void readFromParcel(Parcel in) {
+ if (in == null) {
+ //log here
+ } else {
+ CreationDate = in.readString();
+ ExpirationDate = in.readString();
+ usernamePassword = in.readParcelable(UsernamePassword.class.getClassLoader());
+ digitalCertificate = in.readParcelable(DigitalCertificate.class.getClassLoader());
+ Realm = in.readString();
+ CheckAAAServerCertStatus = (in.readInt() == 1) ? true : false;
+ sim = in.readParcelable(SIM.class.getClassLoader());
+ }
+ }
+
+ public static final Parcelable.Creator<Credential> CREATOR = new Parcelable.Creator<Credential>() {
+ public Credential createFromParcel(Parcel in) {
+ return new Credential(in);
+ }
+
+ public Credential[] newArray(int size) {
+ return new Credential[size];
+ }
+ };
+ }
+
+ /**
+ * PerProviderSubscription/<X+>/Credential/DigitalCertificate
+ **/
+ public static class DigitalCertificate implements Parcelable {
+ public String CertificateType;
+ public String CertSHA256Fingerprint;
+
+ public DigitalCertificate() {
+ }
+
+ public DigitalCertificate(Parcel in) {
+ readFromParcel(in);
+ }
+
+ public int describeContents() {
+ return 0;
+ }
+
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeString(CertificateType);
+ out.writeString(CertSHA256Fingerprint);
+ }
+
+ public void readFromParcel(Parcel in) {
+ if (in == null) {
+ //log here
+ } else {
+ CertificateType = in.readString();
+ CertSHA256Fingerprint = in.readString();
+ }
+ }
+
+ public static final Parcelable.Creator<DigitalCertificate> CREATOR = new Parcelable.Creator<DigitalCertificate>() {
+ public DigitalCertificate createFromParcel(Parcel in) {
+ return new DigitalCertificate(in);
+ }
+
+ public DigitalCertificate[] newArray(int size) {
+ return new DigitalCertificate[size];
+ }
+ };
+
+ }
+
+ /**
+ * PerProviderSubscription/<X+>/Credential/SIM
+ **/
+ public static class SIM implements Parcelable {
+ public String IMSI;
+ public String EAPType;
+
+ public SIM() {
+ }
+
+ public SIM(Parcel in) {
+ readFromParcel(in);
+ }
+
+ public int describeContents() {
+ return 0;
+ }
+
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeString(IMSI);
+ out.writeString(EAPType);
+ }
+
+ public void readFromParcel(Parcel in) {
+ if (in == null) {
+ //log here
+ } else {
+ IMSI = in.readString();
+ EAPType = in.readString();
+ }
+ }
+
+ public static final Parcelable.Creator<SIM> CREATOR = new Parcelable.Creator<SIM>() {
+ public SIM createFromParcel(Parcel in) {
+ return new SIM(in);
+ }
+
+ public SIM[] newArray(int size) {
+ return new SIM[size];
+ }
+ };
+
+ }
+
+ /**
+ * PerProviderSubscription/<X+>/Extension
+ **/
+ public static class Extension {
+ public String empty;
+ }
+
+ public WifiPasspointDmTree() {
+ }
+
+ public WifiPasspointDmTree(Parcel in) {
+ readFromParcel(in);
+ }
+
+ public int describeContents() {
+ return 0;
+ }
+
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeMap(spFqdn);
+ }
+
+ public void readFromParcel(Parcel in) {
+ if (in == null) {
+ //log here
+ } else {
+ in.readMap(spFqdn, SpFqdn.class.getClassLoader());
+ }
+ }
+
+ public static final Parcelable.Creator<WifiPasspointDmTree> CREATOR = new Parcelable.Creator<WifiPasspointDmTree>() {
+ public WifiPasspointDmTree createFromParcel(Parcel in) {
+ return new WifiPasspointDmTree(in);
+ }
+
+ public WifiPasspointDmTree[] newArray(int size) {
+ return new WifiPasspointDmTree[size];
+ }
+ };
+
+}
diff --git a/wifi/java/android/net/wifi/passpoint/WifiPasspointInfo.aidl b/wifi/java/android/net/wifi/passpoint/WifiPasspointInfo.aidl
new file mode 100644
index 0000000..27f23bc
--- /dev/null
+++ b/wifi/java/android/net/wifi/passpoint/WifiPasspointInfo.aidl
@@ -0,0 +1,19 @@
+/**
+ * Copyright (c) 2014, 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.passpoint;
+
+parcelable WifiPasspointInfo;
diff --git a/wifi/java/android/net/wifi/passpoint/WifiPasspointInfo.java b/wifi/java/android/net/wifi/passpoint/WifiPasspointInfo.java
new file mode 100644
index 0000000..33db3f5
--- /dev/null
+++ b/wifi/java/android/net/wifi/passpoint/WifiPasspointInfo.java
@@ -0,0 +1,559 @@
+/*
+ * Copyright (C) 2014 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.passpoint;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/** @hide */
+public class WifiPasspointInfo implements Parcelable {
+
+ /** TODO doc */
+ public static final int ANQP_CAPABILITY = 1 << 0;
+
+ /** TODO doc */
+ public static final int VENUE_NAME = 1 << 1;
+
+ /** TODO doc */
+ public static final int NETWORK_AUTH_TYPE = 1 << 2;
+
+ /** TODO doc */
+ public static final int ROAMING_CONSORTIUM = 1 << 3;
+
+ /** TODO doc */
+ public static final int IP_ADDR_TYPE_AVAILABILITY = 1 << 4;
+
+ /** TODO doc */
+ public static final int NAI_REALM = 1 << 5;
+
+ /** TODO doc */
+ public static final int CELLULAR_NETWORK = 1 << 6;
+
+ /** TODO doc */
+ public static final int DOMAIN_NAME = 1 << 7;
+
+ /** TODO doc */
+ public static final int HOTSPOT_CAPABILITY = 1 << 8;
+
+ /** TODO doc */
+ public static final int OPERATOR_FRIENDLY_NAME = 1 << 9;
+
+ /** TODO doc */
+ public static final int WAN_METRICS = 1 << 10;
+
+ /** TODO doc */
+ public static final int CONNECTION_CAPABILITY = 1 << 11;
+
+ /** TODO doc */
+ public static final int OSU_PROVIDER = 1 << 12;
+
+ /** TODO doc */
+ public static final int PRESET_CRED_MATCH =
+ ANQP_CAPABILITY |
+ HOTSPOT_CAPABILITY |
+ NAI_REALM |
+ CELLULAR_NETWORK |
+ DOMAIN_NAME;
+
+ /** TODO doc */
+ public static final int PRESET_ALL =
+ ANQP_CAPABILITY |
+ VENUE_NAME |
+ NETWORK_AUTH_TYPE |
+ ROAMING_CONSORTIUM |
+ IP_ADDR_TYPE_AVAILABILITY |
+ NAI_REALM |
+ CELLULAR_NETWORK |
+ DOMAIN_NAME |
+ HOTSPOT_CAPABILITY |
+ OPERATOR_FRIENDLY_NAME |
+ WAN_METRICS |
+ CONNECTION_CAPABILITY |
+ OSU_PROVIDER;
+
+
+ public static class WanMetrics {
+ public static final int STATUS_RESERVED = 0;
+ public static final int STATUS_UP = 1;
+ public static final int STATUS_DOWN = 2;
+ public static final int STATUS_TEST = 3;
+
+ public int wanInfo;
+ public long downlinkSpeed;
+ public long uplinkSpeed;
+ public int downlinkLoad;
+ public int uplinkLoad;
+ public int lmd;
+
+ public int getLinkStatus() {
+ return wanInfo & 0x3;
+ }
+
+ public boolean getSymmetricLink() {
+ return (wanInfo & (1 << 2)) != 0;
+ }
+
+ public boolean getAtCapacity() {
+ return (wanInfo & (1 << 3)) != 0;
+ }
+
+ @Override
+ public String toString() {
+ return wanInfo + "," + downlinkSpeed + "," + uplinkSpeed + "," +
+ downlinkLoad + "," + uplinkLoad + "," + lmd;
+ }
+ }
+
+ public static class IpProtoPort {
+ public static final int STATUS_CLOSED = 0;
+ public static final int STATUS_OPEN = 1;
+ public static final int STATUS_UNKNOWN = 2;
+
+ public int proto;
+ public int port;
+ public int status;
+
+ @Override
+ public String toString() {
+ return proto + "," + port + "," + status;
+ }
+ }
+
+ public static class NetworkAuthType {
+ public static final int TYPE_TERMS_AND_CONDITION = 0;
+ public static final int TYPE_ONLINE_ENROLLMENT = 1;
+ public static final int TYPE_HTTP_REDIRECTION = 2;
+ public static final int TYPE_DNS_REDIRECTION = 3;
+
+ public int type;
+ public String redirectUrl;
+
+ @Override
+ public String toString() {
+ return type + "," + redirectUrl;
+ }
+ }
+
+ public static class IpAddressType {
+ public static final int IPV6_NOT_AVAILABLE = 0;
+ public static final int IPV6_AVAILABLE = 1;
+ public static final int IPV6_UNKNOWN = 2;
+
+ public static final int IPV4_NOT_AVAILABLE = 0;
+ public static final int IPV4_PUBLIC = 1;
+ public static final int IPV4_PORT_RESTRICTED = 2;
+ public static final int IPV4_SINGLE_NAT = 3;
+ public static final int IPV4_DOUBLE_NAT = 4;
+ public static final int IPV4_PORT_RESTRICTED_SINGLE_NAT = 5;
+ public static final int IPV4_PORT_RESTRICTED_DOUBLE_NAT = 6;
+ public static final int IPV4_PORT_UNKNOWN = 7;
+
+ private static final int NULL_VALUE = -1;
+
+ public int availability;
+
+ public int getIpv6Availability() {
+ return availability & 0x3;
+ }
+
+ public int getIpv4Availability() {
+ return (availability & 0xFF) >> 2;
+ }
+
+ @Override
+ public String toString() {
+ return getIpv6Availability() + "," + getIpv4Availability();
+ }
+ }
+
+ public static class NaiRealm {
+ public static final int ENCODING_RFC4282 = 0;
+ public static final int ENCODING_UTF8 = 1;
+
+ public int encoding;
+ public String realm;
+
+ @Override
+ public String toString() {
+ return encoding + "," + realm;
+ }
+ }
+
+ public static class CellularNetwork {
+ public String mcc;
+ public String mnc;
+
+ @Override
+ public String toString() {
+ return mcc + "," + mnc;
+ }
+ }
+
+ /** BSSID */
+ public String bssid;
+
+ /** venue name */
+ public String venueName;
+
+ /** list of network authentication types */
+ public List<NetworkAuthType> networkAuthTypeList;
+
+ /** list of roaming consortium OIs */
+ public List<String> roamingConsortiumList;
+
+ /** IP address availability */
+ public IpAddressType ipAddrTypeAvailability;
+
+ /** list of NAI realm */
+ public List<NaiRealm> naiRealmList;
+
+ /** list of 3GPP cellular network */
+ public List<CellularNetwork> cellularNetworkList;
+
+ /** list of fully qualified domain name (FQDN) */
+ public List<String> domainNameList;
+
+ /** HS 2.0 operator friendly name */
+ public String operatorFriendlyName;
+
+ /** HS 2.0 wan metrics */
+ public WanMetrics wanMetrics;
+
+ /** list of HS 2.0 IP proto port */
+ public List<IpProtoPort> connectionCapabilityList;
+
+ /** list of HS 2.0 OSU providers */
+ public List<WifiPasspointOsuProvider> osuProviderList;
+
+ /**
+ * Convert mask to ANQP subtypes, for supplicant command use.
+ *
+ * @param mask The ANQP subtypes mask.
+ * @return String of ANQP subtypes, good for supplicant command use
+ * @hide
+ */
+ public static String toAnqpSubtypes(int mask) {
+ StringBuilder sb = new StringBuilder();
+ if ((mask & ANQP_CAPABILITY) != 0)
+ sb.append("257,");
+ if ((mask & VENUE_NAME) != 0)
+ sb.append("258,");
+ if ((mask & NETWORK_AUTH_TYPE) != 0)
+ sb.append("260,");
+ if ((mask & ROAMING_CONSORTIUM) != 0)
+ sb.append("261,");
+ if ((mask & IP_ADDR_TYPE_AVAILABILITY) != 0)
+ sb.append("262,");
+ if ((mask & NAI_REALM) != 0)
+ sb.append("263,");
+ if ((mask & CELLULAR_NETWORK) != 0)
+ sb.append("264,");
+ if ((mask & DOMAIN_NAME) != 0)
+ sb.append("268,");
+ if ((mask & HOTSPOT_CAPABILITY) != 0)
+ sb.append("hs20:2,");
+ if ((mask & OPERATOR_FRIENDLY_NAME) != 0)
+ sb.append("hs20:3,");
+ if ((mask & WAN_METRICS) != 0)
+ sb.append("hs20:4,");
+ if ((mask & CONNECTION_CAPABILITY) != 0)
+ sb.append("hs20:5,");
+ if ((mask & OSU_PROVIDER) != 0)
+ sb.append("hs20:8,");
+ if (sb.length() > 0)
+ sb.deleteCharAt(sb.length() - 1);
+ return sb.toString();
+ }
+
+ @Override
+ public String toString() {
+ StringBuffer sb = new StringBuffer();
+
+ sb.append("BSSID: ").append("(").append(bssid).append(")");
+
+ if (venueName != null)
+ sb.append(" venueName: ").append("(")
+ .append(venueName.replace("\n", "\\n")).append(")");
+
+ if (networkAuthTypeList != null) {
+ sb.append(" networkAuthType: ");
+ for (NetworkAuthType auth : networkAuthTypeList)
+ sb.append("(").append(auth.toString()).append(")");
+ }
+
+ if (roamingConsortiumList != null) {
+ sb.append(" roamingConsortium: ");
+ for (String oi : roamingConsortiumList)
+ sb.append("(").append(oi).append(")");
+ }
+
+ if (ipAddrTypeAvailability != null) {
+ sb.append(" ipAddrTypeAvaibility: ").append("(")
+ .append(ipAddrTypeAvailability.toString()).append(")");
+ }
+
+ if (naiRealmList != null) {
+ sb.append(" naiRealm: ");
+ for (NaiRealm realm : naiRealmList)
+ sb.append("(").append(realm.toString()).append(")");
+ }
+
+ if (cellularNetworkList != null) {
+ sb.append(" cellularNetwork: ");
+ for (CellularNetwork plmn : cellularNetworkList)
+ sb.append("(").append(plmn.toString()).append(")");
+ }
+
+ if (domainNameList != null) {
+ sb.append(" domainName: ");
+ for (String fqdn : domainNameList)
+ sb.append("(").append(fqdn).append(")");
+ }
+
+ if (operatorFriendlyName != null)
+ sb.append(" operatorFriendlyName: ").append("(")
+ .append(operatorFriendlyName).append(")");
+
+ if (wanMetrics != null)
+ sb.append(" wanMetrics: ").append("(")
+ .append(wanMetrics.toString()).append(")");
+
+ if (connectionCapabilityList != null) {
+ sb.append(" connectionCapability: ");
+ for (IpProtoPort ip : connectionCapabilityList)
+ sb.append("(").append(ip.toString()).append(")");
+ }
+
+ if (osuProviderList != null) {
+ sb.append(" osuProviderList: ");
+ for (WifiPasspointOsuProvider osu : osuProviderList)
+ sb.append("(").append(osu.toString()).append(")");
+ }
+
+ return sb.toString();
+ }
+
+ /** Implement the Parcelable interface {@hide} */
+ @Override
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeString(bssid);
+ out.writeString(venueName);
+
+ if (networkAuthTypeList == null) {
+ out.writeInt(0);
+ } else {
+ out.writeInt(networkAuthTypeList.size());
+ for (NetworkAuthType auth : networkAuthTypeList) {
+ out.writeInt(auth.type);
+ out.writeString(auth.redirectUrl);
+ }
+ }
+
+ if (roamingConsortiumList == null) {
+ out.writeInt(0);
+ } else {
+ out.writeInt(roamingConsortiumList.size());
+ for (String oi : roamingConsortiumList)
+ out.writeString(oi);
+ }
+
+ if (ipAddrTypeAvailability == null) {
+ out.writeInt(IpAddressType.NULL_VALUE);
+ } else {
+ out.writeInt(ipAddrTypeAvailability.availability);
+ }
+
+ if (naiRealmList == null) {
+ out.writeInt(0);
+ } else {
+ out.writeInt(naiRealmList.size());
+ for (NaiRealm realm : naiRealmList) {
+ out.writeInt(realm.encoding);
+ out.writeString(realm.realm);
+ }
+ }
+
+ if (cellularNetworkList == null) {
+ out.writeInt(0);
+ } else {
+ out.writeInt(cellularNetworkList.size());
+ for (CellularNetwork plmn : cellularNetworkList) {
+ out.writeString(plmn.mcc);
+ out.writeString(plmn.mnc);
+ }
+ }
+
+
+ if (domainNameList == null) {
+ out.writeInt(0);
+ } else {
+ out.writeInt(domainNameList.size());
+ for (String fqdn : domainNameList)
+ out.writeString(fqdn);
+ }
+
+ out.writeString(operatorFriendlyName);
+
+ if (wanMetrics == null) {
+ out.writeInt(0);
+ } else {
+ out.writeInt(1);
+ out.writeInt(wanMetrics.wanInfo);
+ out.writeLong(wanMetrics.downlinkSpeed);
+ out.writeLong(wanMetrics.uplinkSpeed);
+ out.writeInt(wanMetrics.downlinkLoad);
+ out.writeInt(wanMetrics.uplinkLoad);
+ out.writeInt(wanMetrics.lmd);
+ }
+
+ if (connectionCapabilityList == null) {
+ out.writeInt(0);
+ } else {
+ out.writeInt(connectionCapabilityList.size());
+ for (IpProtoPort ip : connectionCapabilityList) {
+ out.writeInt(ip.proto);
+ out.writeInt(ip.port);
+ out.writeInt(ip.status);
+ }
+ }
+
+ if (osuProviderList == null) {
+ out.writeInt(0);
+ } else {
+ out.writeInt(osuProviderList.size());
+ for (WifiPasspointOsuProvider osu : osuProviderList)
+ osu.writeToParcel(out, flags);
+ }
+ }
+
+ /** Implement the Parcelable interface {@hide} */
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ /** Implement the Parcelable interface {@hide} */
+ public static final Parcelable.Creator<WifiPasspointInfo> CREATOR =
+ new Parcelable.Creator<WifiPasspointInfo>() {
+ @Override
+ public WifiPasspointInfo createFromParcel(Parcel in) {
+ WifiPasspointInfo p = new WifiPasspointInfo();
+ int n;
+
+ p.bssid = in.readString();
+ p.venueName = in.readString();
+
+ n = in.readInt();
+ if (n > 0) {
+ p.networkAuthTypeList = new ArrayList<NetworkAuthType>();
+ for (int i = 0; i < n; i++) {
+ NetworkAuthType auth = new NetworkAuthType();
+ auth.type = in.readInt();
+ auth.redirectUrl = in.readString();
+ p.networkAuthTypeList.add(auth);
+ }
+ }
+
+ n = in.readInt();
+ if (n > 0) {
+ p.roamingConsortiumList = new ArrayList<String>();
+ for (int i = 0; i < n; i++)
+ p.roamingConsortiumList.add(in.readString());
+ }
+
+ n = in.readInt();
+ if (n != IpAddressType.NULL_VALUE) {
+ p.ipAddrTypeAvailability = new IpAddressType();
+ p.ipAddrTypeAvailability.availability = n;
+ }
+
+ n = in.readInt();
+ if (n > 0) {
+ p.naiRealmList = new ArrayList<NaiRealm>();
+ for (int i = 0; i < n; i++) {
+ NaiRealm realm = new NaiRealm();
+ realm.encoding = in.readInt();
+ realm.realm = in.readString();
+ p.naiRealmList.add(realm);
+ }
+ }
+
+ n = in.readInt();
+ if (n > 0) {
+ p.cellularNetworkList = new ArrayList<CellularNetwork>();
+ for (int i = 0; i < n; i++) {
+ CellularNetwork plmn = new CellularNetwork();
+ plmn.mcc = in.readString();
+ plmn.mnc = in.readString();
+ p.cellularNetworkList.add(plmn);
+ }
+ }
+
+ n = in.readInt();
+ if (n > 0) {
+ p.domainNameList = new ArrayList<String>();
+ for (int i = 0; i < n; i++)
+ p.domainNameList.add(in.readString());
+ }
+
+ p.operatorFriendlyName = in.readString();
+
+ n = in.readInt();
+ if (n > 0) {
+ p.wanMetrics = new WanMetrics();
+ p.wanMetrics.wanInfo = in.readInt();
+ p.wanMetrics.downlinkSpeed = in.readLong();
+ p.wanMetrics.uplinkSpeed = in.readLong();
+ p.wanMetrics.downlinkLoad = in.readInt();
+ p.wanMetrics.uplinkLoad = in.readInt();
+ p.wanMetrics.lmd = in.readInt();
+ }
+
+ n = in.readInt();
+ if (n > 0) {
+ p.connectionCapabilityList = new ArrayList<IpProtoPort>();
+ for (int i = 0; i < n; i++) {
+ IpProtoPort ip = new IpProtoPort();
+ ip.proto = in.readInt();
+ ip.port = in.readInt();
+ ip.status = in.readInt();
+ p.connectionCapabilityList.add(ip);
+ }
+ }
+
+ n = in.readInt();
+ if (n > 0) {
+ p.osuProviderList = new ArrayList<WifiPasspointOsuProvider>();
+ for (int i = 0; i < n; i++) {
+ WifiPasspointOsuProvider osu = WifiPasspointOsuProvider.CREATOR
+ .createFromParcel(in);
+ p.osuProviderList.add(osu);
+ }
+ }
+
+ return p;
+ }
+
+ @Override
+ public WifiPasspointInfo[] newArray(int size) {
+ return new WifiPasspointInfo[size];
+ }
+ };
+}
diff --git a/wifi/java/android/net/wifi/passpoint/WifiPasspointManager.java b/wifi/java/android/net/wifi/passpoint/WifiPasspointManager.java
new file mode 100644
index 0000000..0245a3d
--- /dev/null
+++ b/wifi/java/android/net/wifi/passpoint/WifiPasspointManager.java
@@ -0,0 +1,567 @@
+/*
+ * Copyright (C) 2014 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.passpoint;
+
+import android.content.Context;
+import android.net.wifi.ScanResult;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
+import android.os.Messenger;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.os.RemoteException;
+import android.util.Log;
+
+import com.android.internal.util.AsyncChannel;
+import com.android.internal.util.Protocol;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * Provides APIs for managing Wifi Passpoint credentials.
+ * @hide
+ */
+public class WifiPasspointManager {
+
+ private static final String TAG = "PasspointManager";
+
+ private static final boolean DBG = true;
+
+ /* Passpoint states values */
+
+ /** Passpoint is in an unknown state. This should only occur in boot time */
+ public static final int PASSPOINT_STATE_UNKNOWN = 0;
+
+ /** Passpoint is disabled. This occurs when wifi is disabled */
+ public static final int PASSPOINT_STATE_DISABLED = 1;
+
+ /** Passpoint is enabled and in discovery state */
+ public static final int PASSPOINT_STATE_DISCOVERY = 2;
+
+ /** Passpoint is enabled and in access state */
+ public static final int PASSPOINT_STATE_ACCESS = 3;
+
+ /** Passpoint is enabled and in provisioning state */
+ public static final int PASSPOINT_STATE_PROVISION = 4;
+
+ /* Passpoint callback error codes */
+
+ /** Indicates that the operation failed due to an internal error */
+ public static final int REASON_ERROR = 0;
+
+ /** Indicates that the operation failed because wifi is disabled */
+ public static final int REASON_WIFI_DISABLED = 1;
+
+ /** Indicates that the operation failed because the framework is busy */
+ public static final int REASON_BUSY = 2;
+
+ /** Indicates that the operation failed because parameter is invalid */
+ public static final int REASON_INVALID_PARAMETER = 3;
+
+ /** Indicates that the operation failed because the server is not trusted */
+ public static final int REASON_NOT_TRUSTED = 4;
+
+ /**
+ * protocol supported for Passpoint
+ */
+ public static final String PROTOCOL_DM = "OMA-DM-ClientInitiated";
+
+ /**
+ * protocol supported for Passpoint
+ */
+ public static final String PROTOCOL_SOAP = "SPP-ClientInitiated";
+
+ /* Passpoint broadcasts */
+
+ /**
+ * Broadcast intent action indicating that the state of Passpoint
+ * connectivity has changed
+ */
+ public static final String PASSPOINT_STATE_CHANGED_ACTION =
+ "android.net.wifi.passpoint.STATE_CHANGE";
+
+ /**
+ * Broadcast intent action indicating that the saved Passpoint credential
+ * list has changed
+ */
+ public static final String PASSPOINT_CRED_CHANGED_ACTION =
+ "android.net.wifi.passpoint.CRED_CHANGE";
+
+ /**
+ * Broadcast intent action indicating that Passpoint online sign up is
+ * avaiable.
+ */
+ public static final String PASSPOINT_OSU_AVAILABLE_ACTION =
+ "android.net.wifi.passpoint.OSU_AVAILABLE";
+
+ /**
+ * Broadcast intent action indicating that user remediation is required
+ */
+ public static final String PASSPOINT_USER_REM_REQ_ACTION =
+ "android.net.wifi.passpoint.USER_REM_REQ";
+
+ /**
+ * Interface for callback invocation when framework channel is lost
+ */
+ public interface ChannelListener {
+ /**
+ * The channel to the framework has been disconnected. Application could
+ * try re-initializing using {@link #initialize}
+ */
+ public void onChannelDisconnected();
+ }
+
+ /**
+ * Interface for callback invocation on an application action
+ */
+ public interface ActionListener {
+ /** The operation succeeded */
+ public void onSuccess();
+
+ /**
+ * The operation failed
+ *
+ * @param reason The reason for failure could be one of
+ * {@link #WIFI_DISABLED}, {@link #ERROR} or {@link #BUSY}
+ */
+ public void onFailure(int reason);
+ }
+
+ /**
+ * Interface for callback invocation when doing OSU or user remediation
+ */
+ public interface OsuRemListener {
+ /** The operation succeeded */
+ public void onSuccess();
+
+ /**
+ * The operation failed
+ *
+ * @param reason The reason for failure could be one of
+ * {@link #WIFI_DISABLED}, {@link #ERROR} or {@link #BUSY}
+ */
+ public void onFailure(int reason);
+
+ /**
+ * Browser launch is requried for user interaction. When this callback
+ * is called, app should launch browser / webview to the given URI.
+ *
+ * @param uri URI for browser launch
+ */
+ public void onBrowserLaunch(String uri);
+
+ /**
+ * When this is called, app should dismiss the previously lanched browser.
+ */
+ public void onBrowserDismiss();
+ }
+
+ /**
+ * A channel that connects the application to the wifi passpoint framework.
+ * Most passpoint operations require a Channel as an argument.
+ * An instance of Channel is obtained by doing a call on {@link #initialize}
+ */
+ public static class Channel {
+ private final static int INVALID_LISTENER_KEY = 0;
+
+ private ChannelListener mChannelListener;
+
+ private HashMap<Integer, Object> mListenerMap = new HashMap<Integer, Object>();
+ private HashMap<Integer, Integer> mListenerMapCount = new HashMap<Integer, Integer>();
+ private Object mListenerMapLock = new Object();
+ private int mListenerKey = 0;
+
+ private List<ScanResult> mAnqpRequest = new LinkedList<ScanResult>();
+ private Object mAnqpRequestLock = new Object();
+
+ private AsyncChannel mAsyncChannel;
+ private PasspointHandler mHandler;
+ Context mContext;
+
+ Channel(Context context, Looper looper, ChannelListener l) {
+ mAsyncChannel = new AsyncChannel();
+ mHandler = new PasspointHandler(looper);
+ mChannelListener = l;
+ mContext = context;
+ }
+
+ private int putListener(Object listener) {
+ return putListener(listener, 1);
+ }
+
+ private int putListener(Object listener, int count) {
+ if (listener == null || count <= 0)
+ return INVALID_LISTENER_KEY;
+ int key;
+ synchronized (mListenerMapLock) {
+ do {
+ key = mListenerKey++;
+ } while (key == INVALID_LISTENER_KEY);
+ mListenerMap.put(key, listener);
+ mListenerMapCount.put(key, count);
+ }
+ return key;
+ }
+
+ private Object peekListener(int key) {
+ Log.d(TAG, "peekListener() key=" + key);
+ if (key == INVALID_LISTENER_KEY)
+ return null;
+ synchronized (mListenerMapLock) {
+ return mListenerMap.get(key);
+ }
+ }
+
+
+ private Object getListener(int key, boolean forceRemove) {
+ Log.d(TAG, "getListener() key=" + key + " force=" + forceRemove);
+ if (key == INVALID_LISTENER_KEY)
+ return null;
+ synchronized (mListenerMapLock) {
+ if (!forceRemove) {
+ int count = mListenerMapCount.get(key);
+ Log.d(TAG, "count=" + count);
+ mListenerMapCount.put(key, --count);
+ if (count > 0)
+ return null;
+ }
+ Log.d(TAG, "remove key");
+ mListenerMapCount.remove(key);
+ return mListenerMap.remove(key);
+ }
+ }
+
+ private void anqpRequestStart(ScanResult sr) {
+ Log.d(TAG, "anqpRequestStart sr.bssid=" + sr.BSSID);
+ synchronized (mAnqpRequestLock) {
+ mAnqpRequest.add(sr);
+ }
+ }
+
+ private void anqpRequestFinish(WifiPasspointInfo result) {
+ Log.d(TAG, "anqpRequestFinish pi.bssid=" + result.bssid);
+ synchronized (mAnqpRequestLock) {
+ for (ScanResult sr : mAnqpRequest)
+ if (sr.BSSID.equals(result.bssid)) {
+ Log.d(TAG, "find hit " + result.bssid);
+ /* sr.passpoint = result; */
+ mAnqpRequest.remove(sr);
+ Log.d(TAG, "mAnqpRequest.len=" + mAnqpRequest.size());
+ break;
+ }
+ }
+ }
+
+ private void anqpRequestFinish(ScanResult sr) {
+ Log.d(TAG, "anqpRequestFinish sr.bssid=" + sr.BSSID);
+ synchronized (mAnqpRequestLock) {
+ for (ScanResult sr1 : mAnqpRequest)
+ if (sr1.BSSID.equals(sr.BSSID)) {
+ mAnqpRequest.remove(sr1);
+ break;
+ }
+ }
+ }
+
+ class PasspointHandler extends Handler {
+ PasspointHandler(Looper looper) {
+ super(looper);
+ }
+
+ @Override
+ public void handleMessage(Message message) {
+ Object listener = null;
+
+ switch (message.what) {
+ case AsyncChannel.CMD_CHANNEL_DISCONNECTED:
+ if (mChannelListener != null) {
+ mChannelListener.onChannelDisconnected();
+ mChannelListener = null;
+ }
+ break;
+
+ case REQUEST_ANQP_INFO_SUCCEEDED:
+ WifiPasspointInfo result = (WifiPasspointInfo) message.obj;
+ anqpRequestFinish(result);
+ listener = getListener(message.arg2, false);
+ if (listener != null) {
+ ((ActionListener) listener).onSuccess();
+ }
+ break;
+
+ case REQUEST_ANQP_INFO_FAILED:
+ anqpRequestFinish((ScanResult) message.obj);
+ listener = getListener(message.arg2, false);
+ if (listener == null)
+ getListener(message.arg2, true);
+ if (listener != null) {
+ ((ActionListener) listener).onFailure(message.arg1);
+ }
+ break;
+
+ case START_OSU_SUCCEEDED:
+ listener = getListener(message.arg2, true);
+ if (listener != null) {
+ ((OsuRemListener) listener).onSuccess();
+ }
+ break;
+
+ case START_OSU_FAILED:
+ listener = getListener(message.arg2, true);
+ if (listener != null) {
+ ((OsuRemListener) listener).onFailure(message.arg1);
+ }
+ break;
+
+ case START_OSU_BROWSER:
+ listener = peekListener(message.arg2);
+ if (listener != null) {
+ ParcelableString str = (ParcelableString) message.obj;
+ if (str == null || str.string == null)
+ ((OsuRemListener) listener).onBrowserDismiss();
+ else
+ ((OsuRemListener) listener).onBrowserLaunch(str.string);
+ }
+ break;
+
+ default:
+ Log.d(TAG, "Ignored " + message);
+ break;
+ }
+ }
+ }
+
+ }
+
+ public static class ParcelableString implements Parcelable {
+ public String string;
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeString(string);
+ }
+
+ public static final Parcelable.Creator<ParcelableString> CREATOR =
+ new Parcelable.Creator<ParcelableString>() {
+ @Override
+ public ParcelableString createFromParcel(Parcel in) {
+ ParcelableString ret = new ParcelableString();
+ ret.string = in.readString();
+ return ret;
+ }
+ @Override
+ public ParcelableString[] newArray(int size) {
+ return new ParcelableString[size];
+ }
+ };
+ }
+
+ private static final int BASE = Protocol.BASE_WIFI_PASSPOINT_MANAGER;
+
+ public static final int REQUEST_ANQP_INFO = BASE + 1;
+ public static final int REQUEST_ANQP_INFO_FAILED = BASE + 2;
+ public static final int REQUEST_ANQP_INFO_SUCCEEDED = BASE + 3;
+ public static final int REQUEST_OSU_ICON = BASE + 4;
+ public static final int REQUEST_OSU_ICON_FAILED = BASE + 5;
+ public static final int REQUEST_OSU_ICON_SUCCEEDED = BASE + 6;
+ public static final int START_OSU = BASE + 7;
+ public static final int START_OSU_BROWSER = BASE + 8;
+ public static final int START_OSU_FAILED = BASE + 9;
+ public static final int START_OSU_SUCCEEDED = BASE + 10;
+
+ private Context mContext;
+ IWifiPasspointManager mService;
+
+ /**
+ * TODO: doc
+ * @param context
+ * @param service
+ */
+ public WifiPasspointManager(Context context, IWifiPasspointManager service) {
+ mContext = context;
+ mService = service;
+ }
+
+ /**
+ * Registers the application with the framework. This function must be the
+ * first to be called before any async passpoint operations are performed.
+ *
+ * @param srcContext is the context of the source
+ * @param srcLooper is the Looper on which the callbacks are receivied
+ * @param listener for callback at loss of framework communication. Can be
+ * null.
+ * @return Channel instance that is necessary for performing any further
+ * passpoint operations
+ *
+ */
+ public Channel initialize(Context srcContext, Looper srcLooper, ChannelListener listener) {
+ Messenger messenger = getMessenger();
+ if (messenger == null)
+ return null;
+
+ Channel c = new Channel(srcContext, srcLooper, listener);
+ if (c.mAsyncChannel.connectSync(srcContext, c.mHandler, messenger)
+ == AsyncChannel.STATUS_SUCCESSFUL) {
+ return c;
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * STOPSHIP: temp solution, should use supplicant manager instead, check
+ * with b/13931972
+ */
+ public Messenger getMessenger() {
+ try {
+ return mService.getMessenger();
+ } catch (RemoteException e) {
+ return null;
+ }
+ }
+
+ public int getPasspointState() {
+ try {
+ return mService.getPasspointState();
+ } catch (RemoteException e) {
+ return PASSPOINT_STATE_UNKNOWN;
+ }
+ }
+
+ public void requestAnqpInfo(Channel c, List<ScanResult> requested, int mask,
+ ActionListener listener) {
+ Log.d(TAG, "requestAnqpInfo start");
+ Log.d(TAG, "requested.size=" + requested.size());
+ checkChannel(c);
+ List<ScanResult> list = new ArrayList<ScanResult>();
+ for (ScanResult sr : requested)
+ if (sr.capabilities.contains("[HS20]")) {
+ list.add(sr);
+ c.anqpRequestStart(sr);
+ Log.d(TAG, "adding " + sr.BSSID);
+ }
+ int count = list.size();
+ Log.d(TAG, "after filter, count=" + count);
+ if (count == 0) {
+ if (DBG)
+ Log.d(TAG, "ANQP info request contains no HS20 APs, skipped");
+ listener.onSuccess();
+ return;
+ }
+ int key = c.putListener(listener, count);
+ for (ScanResult sr : list)
+ c.mAsyncChannel.sendMessage(REQUEST_ANQP_INFO, mask, key, sr);
+ Log.d(TAG, "requestAnqpInfo end");
+ }
+
+ public void requestOsuIcons(Channel c, List<WifiPasspointOsuProvider> requested,
+ int resolution, ActionListener listener) {
+ }
+
+ public List<WifiPasspointPolicy> requestCredentialMatch(List<ScanResult> requested) {
+ try {
+ return mService.requestCredentialMatch(requested);
+ } catch (RemoteException e) {
+ return null;
+ }
+ }
+
+ /**
+ * Get a list of saved Passpoint credentials. Only those credentials owned
+ * by the caller will be returned.
+ *
+ * @return The list of credentials
+ */
+ public List<WifiPasspointCredential> getCredentials() {
+ try {
+ return mService.getCredentials();
+ } catch (RemoteException e) {
+ return null;
+ }
+ }
+
+ /**
+ * Add a new Passpoint credential.
+ *
+ * @param cred The credential to be added
+ * @return {@code true} if the operation succeeds, {@code false} otherwise
+ */
+ public boolean addCredential(WifiPasspointCredential cred) {
+ try {
+ return mService.addCredential(cred);
+ } catch (RemoteException e) {
+ return false;
+ }
+ }
+
+ /**
+ * Update an existing Passpoint credential. Only system or the owner of this
+ * credential has the permission to do this.
+ *
+ * @param cred The credential to be updated
+ * @return {@code true} if the operation succeeds, {@code false} otherwise
+ */
+ public boolean updateCredential(WifiPasspointCredential cred) {
+ try {
+ return mService.updateCredential(cred);
+ } catch (RemoteException e) {
+ return false;
+ }
+ }
+
+ /**
+ * Remove an existing Passpoint credential. Only system or the owner of this
+ * credential has the permission to do this.
+ *
+ * @param cred The credential to be removed
+ * @return {@code true} if the operation succeeds, {@code false} otherwise
+ */
+ public boolean removeCredential(WifiPasspointCredential cred) {
+ try {
+ return mService.removeCredential(cred);
+ } catch (RemoteException e) {
+ return false;
+ }
+ }
+
+ public void startOsu(Channel c, WifiPasspointOsuProvider osu, OsuRemListener listener) {
+ Log.d(TAG, "startOsu start");
+ checkChannel(c);
+ int key = c.putListener(listener);
+ c.mAsyncChannel.sendMessage(START_OSU, 0, key, osu);
+ Log.d(TAG, "startOsu end");
+ }
+
+ public void startRemediation(Channel c, OsuRemListener listener) {
+ }
+
+ public void connect(WifiPasspointPolicy policy) {
+ }
+
+ private static void checkChannel(Channel c) {
+ if (c == null) throw new IllegalArgumentException("Channel needs to be initialized");
+ }
+}
diff --git a/wifi/java/android/net/wifi/passpoint/WifiPasspointOsuProvider.aidl b/wifi/java/android/net/wifi/passpoint/WifiPasspointOsuProvider.aidl
new file mode 100644
index 0000000..088136f
--- /dev/null
+++ b/wifi/java/android/net/wifi/passpoint/WifiPasspointOsuProvider.aidl
@@ -0,0 +1,19 @@
+/**
+ * Copyright (c) 2014, 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.passpoint;
+
+parcelable WifiPasspointOsuProvider;
diff --git a/wifi/java/android/net/wifi/passpoint/WifiPasspointOsuProvider.java b/wifi/java/android/net/wifi/passpoint/WifiPasspointOsuProvider.java
new file mode 100644
index 0000000..b54b70c
--- /dev/null
+++ b/wifi/java/android/net/wifi/passpoint/WifiPasspointOsuProvider.java
@@ -0,0 +1,152 @@
+/*
+ * Copyright (C) 2014 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.passpoint;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/** @hide */
+public class WifiPasspointOsuProvider implements Parcelable {
+
+ /** TODO: doc
+ * @hide
+ */
+ public static final int OSU_METHOD_UNKNOWN = -1;
+
+ /** TODO: doc
+ * @hide
+ */
+ public static final int OSU_METHOD_OMADM = 0;
+
+ /** TODO: doc
+ * @hide
+ */
+ public static final int OSU_METHOD_SOAP = 1;
+
+ /** TODO: doc */
+ public String ssid;
+
+ /** TODO: doc */
+ public String friendlyName;
+
+ /** TODO: doc
+ * @hide
+ */
+ public String serverUri;
+
+ /** TODO: doc
+ * @hide
+ */
+ public int osuMethod = OSU_METHOD_UNKNOWN;
+
+ /** TODO: doc */
+ public int iconWidth;
+
+ /** TODO: doc */
+ public int iconHeight;
+
+ /** TODO: doc */
+ public String iconType;
+
+ /** TODO: doc */
+ public String iconFileName;
+
+ /** TODO: doc */
+ public Object icon; // TODO: should change to image format
+
+ /** TODO: doc */
+ public String osuNai;
+
+ /** TODO: doc */
+ public String osuService;
+
+ /** default constructor @hide */
+ public WifiPasspointOsuProvider() {
+ // TODO
+ }
+
+ /** copy constructor @hide */
+ public WifiPasspointOsuProvider(WifiPasspointOsuProvider source) {
+ // TODO
+ }
+
+ @Override
+ public String toString() {
+ StringBuffer sb = new StringBuffer();
+ sb.append("SSID: ").append("<").append(ssid).append(">");
+ if (friendlyName != null)
+ sb.append(" friendlyName: ").append("<").append(friendlyName).append(">");
+ if (serverUri != null)
+ sb.append(" serverUri: ").append("<").append(serverUri).append(">");
+ sb.append(" osuMethod: ").append("<").append(osuMethod).append(">");
+ if (iconFileName != null) {
+ sb.append(" icon: <").append(iconWidth).append("x")
+ .append(iconHeight).append(" ")
+ .append(iconType).append(" ")
+ .append(iconFileName).append(">");
+ }
+ if (osuNai != null)
+ sb.append(" osuNai: ").append("<").append(osuNai).append(">");
+ if (osuService != null)
+ sb.append(" osuService: ").append("<").append(osuService).append(">");
+ return sb.toString();
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeString(ssid);
+ out.writeString(friendlyName);
+ out.writeString(serverUri);
+ out.writeInt(osuMethod);
+ out.writeInt(iconWidth);
+ out.writeInt(iconHeight);
+ out.writeString(iconType);
+ out.writeString(iconFileName);
+ out.writeString(osuNai);
+ out.writeString(osuService);
+ // TODO: icon image?
+ }
+
+ public static final Parcelable.Creator<WifiPasspointOsuProvider> CREATOR =
+ new Parcelable.Creator<WifiPasspointOsuProvider>() {
+ @Override
+ public WifiPasspointOsuProvider createFromParcel(Parcel in) {
+ WifiPasspointOsuProvider osu = new WifiPasspointOsuProvider();
+ osu.ssid = in.readString();
+ osu.friendlyName = in.readString();
+ osu.serverUri = in.readString();
+ osu.osuMethod = in.readInt();
+ osu.iconWidth = in.readInt();
+ osu.iconHeight = in.readInt();
+ osu.iconType = in.readString();
+ osu.iconFileName = in.readString();
+ osu.osuNai = in.readString();
+ osu.osuService = in.readString();
+ return osu;
+ }
+
+ @Override
+ public WifiPasspointOsuProvider[] newArray(int size) {
+ return new WifiPasspointOsuProvider[size];
+ }
+ };
+}
diff --git a/wifi/java/android/net/wifi/passpoint/WifiPasspointPolicy.aidl b/wifi/java/android/net/wifi/passpoint/WifiPasspointPolicy.aidl
new file mode 100644
index 0000000..1d61da0
--- /dev/null
+++ b/wifi/java/android/net/wifi/passpoint/WifiPasspointPolicy.aidl
@@ -0,0 +1,19 @@
+/**
+ * Copyright (c) 2014, 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.passpoint;
+
+parcelable WifiPasspointPolicy;
diff --git a/wifi/java/android/net/wifi/passpoint/WifiPasspointPolicy.java b/wifi/java/android/net/wifi/passpoint/WifiPasspointPolicy.java
new file mode 100644
index 0000000..f84ac88
--- /dev/null
+++ b/wifi/java/android/net/wifi/passpoint/WifiPasspointPolicy.java
@@ -0,0 +1,386 @@
+/*
+ * Copyright (C) 2014 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.passpoint;
+
+import android.net.wifi.WifiConfiguration;
+import android.net.wifi.ScanResult;
+import android.os.Parcelable;
+import android.os.Parcel;
+import android.security.Credentials;
+import android.util.Log;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.util.List;
+
+
+/** @hide */
+public class WifiPasspointPolicy implements Parcelable {
+
+ private final static String TAG = "PasspointPolicy";
+
+ /** @hide */
+ public static final int HOME_SP = 0;
+
+ /** @hide */
+ public static final int ROAMING_PARTNER = 1;
+
+ /** @hide */
+ public static final int UNRESTRICTED = 2;
+
+ private String mName;
+ private int mCredentialPriority;
+ private int mRoamingPriority;
+ private String mBssid;
+ private String mSsid;
+ private WifiPasspointCredential mCredential;
+ private int mRestriction;// Permitted values are "HomeSP", "RoamingPartner", or "Unrestricted"
+ private boolean mIsHomeSp;
+
+ private final String INT_PRIVATE_KEY = "private_key";
+ private final String INT_PHASE2 = "phase2";
+ private final String INT_PASSWORD = "password";
+ private final String INT_IDENTITY = "identity";
+ private final String INT_EAP = "eap";
+ private final String INT_CLIENT_CERT = "client_cert";
+ private final String INT_CA_CERT = "ca_cert";
+ private final String INT_ANONYMOUS_IDENTITY = "anonymous_identity";
+ private final String INT_SIM_SLOT = "sim_slot";
+ private final String INT_ENTERPRISEFIELD_NAME ="android.net.wifi.WifiConfiguration$EnterpriseField";
+ private final String ISO8601DATEFORMAT = "yyyy-MM-dd'T'HH:mm:ss'Z'";
+ private final String ENTERPRISE_PHASE2_MSCHAPV2 = "auth=MSCHAPV2";
+ private final String ENTERPRISE_PHASE2_MSCHAP = "auth=MSCHAP";
+
+ /** @hide */
+ public WifiPasspointPolicy(String name, String ssid,
+ String bssid, WifiPasspointCredential pc,
+ int restriction, boolean ishomesp) {
+ mName = name;
+ if (pc != null) {
+ mCredentialPriority = pc.getPriority();
+ }
+ //PerProviderSubscription/<X+>/Policy/PreferredRoamingPartnerList/<X+>/Priority
+ mRoamingPriority = 128; //default priority value of 128
+ mSsid = ssid;
+ mCredential = pc;
+ mBssid = bssid;
+ mRestriction = restriction;
+ mIsHomeSp = ishomesp;
+ }
+
+ public String getSsid() {
+ return mSsid;
+ }
+
+ /** @hide */
+ public void setBssid(String bssid) {
+ mBssid = bssid;
+ }
+
+ public String getBssid() {
+ return mBssid;
+ }
+
+ /** @hide */
+ public void setRestriction(int r) {
+ mRestriction = r;
+ }
+
+ /** @hide */
+ public int getRestriction() {
+ return mRestriction;
+ }
+
+ /** @hide */
+ public void setHomeSp(boolean b) {
+ mIsHomeSp = b;
+ }
+
+ /** @hide */
+ public boolean isHomeSp() {
+ return mIsHomeSp;
+ }
+
+ /** @hide */
+ public void setCredential(WifiPasspointCredential newCredential) {
+ mCredential = newCredential;
+ }
+
+ public WifiPasspointCredential getCredential() {
+ // TODO: return a copy
+ return mCredential;
+ }
+
+ /** @hide */
+ public void setCredentialPriority(int priority) {
+ mCredentialPriority = priority;
+ }
+
+ /** @hide */
+ public void setRoamingPriority(int priority) {
+ mRoamingPriority = priority;
+ }
+
+ public int getCredentialPriority() {
+ return mCredentialPriority;
+ }
+
+ public int getRoamingPriority() {
+ return mRoamingPriority;
+ }
+
+ public WifiConfiguration createWifiConfiguration() {
+ WifiConfiguration wfg = new WifiConfiguration();
+ if (mBssid != null) {
+ Log.d(TAG, "create bssid:" + mBssid);
+ wfg.BSSID = mBssid;
+ }
+
+ if (mSsid != null) {
+ Log.d(TAG, "create ssid:" + mSsid);
+ wfg.SSID = mSsid;
+ }
+ //TODO: 1. add pmf configuration
+ // 2. add ocsp configuration
+ // 3. add eap-sim configuration
+ /*Key management*/
+ wfg.status = WifiConfiguration.Status.ENABLED;
+ wfg.allowedKeyManagement.clear();
+ wfg.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_EAP);
+ wfg.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.IEEE8021X);
+
+ /*Group Ciphers*/
+ wfg.allowedGroupCiphers.clear();
+ wfg.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP);
+ wfg.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.TKIP);
+
+ /*Protocols*/
+ wfg.allowedProtocols.clear();
+ wfg.allowedProtocols.set(WifiConfiguration.Protocol.RSN);
+ wfg.allowedProtocols.set(WifiConfiguration.Protocol.WPA);
+
+ Class[] enterpriseFieldArray = WifiConfiguration.class.getClasses();
+ Class<?> enterpriseFieldClass = null;
+
+
+ for(Class<?> myClass : enterpriseFieldArray) {
+ if(myClass.getName().equals(INT_ENTERPRISEFIELD_NAME)) {
+ enterpriseFieldClass = myClass;
+ break;
+ }
+ }
+ Log.d(TAG, "class chosen " + enterpriseFieldClass.getName() );
+
+
+ Field anonymousId = null, caCert = null, clientCert = null,
+ eap = null, identity = null, password = null,
+ phase2 = null, privateKey = null;
+
+ Field[] fields = WifiConfiguration.class.getFields();
+
+
+ for (Field tempField : fields) {
+ if (tempField.getName().trim().equals(INT_ANONYMOUS_IDENTITY)) {
+ anonymousId = tempField;
+ Log.d(TAG, "field " + anonymousId.getName() );
+ } else if (tempField.getName().trim().equals(INT_CA_CERT)) {
+ caCert = tempField;
+ } else if (tempField.getName().trim().equals(INT_CLIENT_CERT)) {
+ clientCert = tempField;
+ Log.d(TAG, "field " + clientCert.getName() );
+ } else if (tempField.getName().trim().equals(INT_EAP)) {
+ eap = tempField;
+ Log.d(TAG, "field " + eap.getName() );
+ } else if (tempField.getName().trim().equals(INT_IDENTITY)) {
+ identity = tempField;
+ Log.d(TAG, "field " + identity.getName() );
+ } else if (tempField.getName().trim().equals(INT_PASSWORD)) {
+ password = tempField;
+ Log.d(TAG, "field " + password.getName() );
+ } else if (tempField.getName().trim().equals(INT_PHASE2)) {
+ phase2 = tempField;
+ Log.d(TAG, "field " + phase2.getName() );
+
+ } else if (tempField.getName().trim().equals(INT_PRIVATE_KEY)) {
+ privateKey = tempField;
+ }
+ }
+
+
+ Method setValue = null;
+
+ for(Method m: enterpriseFieldClass.getMethods()) {
+ if(m.getName().trim().equals("setValue")) {
+ Log.d(TAG, "method " + m.getName() );
+ setValue = m;
+ break;
+ }
+ }
+
+ try {
+ // EAP
+ String eapmethod = mCredential.getType();
+ Log.d(TAG, "eapmethod:" + eapmethod);
+ setValue.invoke(eap.get(wfg), eapmethod);
+
+ // Username, password, EAP Phase 2
+ if ("TTLS".equals(eapmethod)) {
+ setValue.invoke(phase2.get(wfg), ENTERPRISE_PHASE2_MSCHAPV2);
+ setValue.invoke(identity.get(wfg), mCredential.getUserName());
+ setValue.invoke(password.get(wfg), mCredential.getPassword());
+ setValue.invoke(anonymousId.get(wfg), "anonymous@" + mCredential.getRealm());
+ }
+
+ // EAP CA Certificate
+ String cacertificate = null;
+ String rootCA = mCredential.getCaRootCertPath();
+ if (rootCA == null){
+ cacertificate = null;
+ } else {
+ cacertificate = "keystore://" + Credentials.WIFI + "HS20" + Credentials.CA_CERTIFICATE + rootCA;
+ }
+ Log.d(TAG, "cacertificate:" + cacertificate);
+ setValue.invoke(caCert.get(wfg), cacertificate);
+
+ //User certificate
+ if ("TLS".equals(eapmethod)) {
+ String usercertificate = null;
+ String privatekey = null;
+ String clientCertPath = mCredential.getClientCertPath();
+ if (clientCertPath != null){
+ privatekey = "keystore://" + Credentials.WIFI + "HS20" + Credentials.USER_PRIVATE_KEY + clientCertPath;
+ usercertificate = "keystore://" + Credentials.WIFI + "HS20" + Credentials.USER_CERTIFICATE + clientCertPath;
+ }
+ Log.d(TAG, "privatekey:" + privatekey);
+ Log.d(TAG, "usercertificate:" + usercertificate);
+ if (privatekey != null && usercertificate != null) {
+ setValue.invoke(privateKey.get(wfg), privatekey);
+ setValue.invoke(clientCert.get(wfg), usercertificate);
+ }
+ }
+ } catch (Exception e) {
+ Log.d(TAG, "createWifiConfiguration err:" + e);
+ }
+
+ return wfg;
+ }
+
+ /** {@inheritDoc} @hide */
+ public int compareTo(WifiPasspointPolicy another) {
+ Log.d(TAG, "this:" + this);
+ Log.d(TAG, "another:" + another);
+
+ if (another == null) {
+ return -1;
+ } else if (this.mIsHomeSp == true && another.isHomeSp() == false) {
+ //home sp priority is higher then roaming
+ Log.d(TAG, "compare HomeSP first, this is HomeSP, another isn't");
+ return -1;
+ } else if ((this.mIsHomeSp == true && another.isHomeSp() == true)) {
+ Log.d(TAG, "both HomeSP");
+ //if both home sp, compare credential priority
+ if (this.mCredentialPriority < another.getCredentialPriority()) {
+ Log.d(TAG, "this priority is higher");
+ return -1;
+ } else if (this.mCredentialPriority == another.getCredentialPriority()) {
+ Log.d(TAG, "both priorities equal");
+ //if priority still the same, compare name(ssid)
+ if (this.mName.compareTo(another.mName) != 0) {
+ Log.d(TAG, "compare mName return:" + this.mName.compareTo(another.mName));
+ return this.mName.compareTo(another.mName);
+ }
+ /**
+ *if name still the same, compare credential
+ *the device may has two more credentials(TLS,SIM..etc)
+ *it can associate to one AP(same ssid). so we should compare by credential
+ */
+ if (this.mCredential != null && another.mCredential != null) {
+ if (this.mCredential.compareTo(another.mCredential) != 0) {
+ Log.d(TAG,
+ "compare mCredential return:" + this.mName.compareTo(another.mName));
+ return this.mCredential.compareTo(another.mCredential);
+ }
+ }
+ } else {
+ return 1;
+ }
+ } else if ((this.mIsHomeSp == false && another.isHomeSp() == false)) {
+ Log.d(TAG, "both RoamingSp");
+ //if both roaming sp, compare roaming priority(preferredRoamingPartnerList/<X+>/priority)
+ if (this.mRoamingPriority < another.getRoamingPriority()) {
+ Log.d(TAG, "this priority is higher");
+ return -1;
+ } else if (this.mRoamingPriority == another.getRoamingPriority()) {//priority equals, compare name
+ Log.d(TAG, "both priorities equal");
+ //if priority still the same, compare name(ssid)
+ if (this.mName.compareTo(another.mName) != 0) {
+ Log.d(TAG, "compare mName return:" + this.mName.compareTo(another.mName));
+ return this.mName.compareTo(another.mName);
+ }
+ //if name still the same, compare credential
+ if (this.mCredential != null && another.mCredential != null) {
+ if (this.mCredential.compareTo(another.mCredential) != 0) {
+ Log.d(TAG,
+ "compare mCredential return:"
+ + this.mCredential.compareTo(another.mCredential));
+ return this.mCredential.compareTo(another.mCredential);
+ }
+ }
+ } else {
+ return 1;
+ }
+ }
+
+ Log.d(TAG, "both policies equal");
+ return 0;
+ }
+
+ @Override
+ /** @hide */
+ public String toString() {
+ return "PasspointPolicy: name=" + mName + " CredentialPriority=" + mCredentialPriority +
+ " mRoamingPriority" + mRoamingPriority +
+ " ssid=" + mSsid + " restriction=" + mRestriction +
+ " ishomesp=" + mIsHomeSp + " Credential=" + mCredential;
+ }
+
+ /** Implement the Parcelable interface {@hide} */
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ /** Implement the Parcelable interface {@hide} */
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ // TODO
+ }
+
+ /** Implement the Parcelable interface {@hide} */
+ public static final Creator<WifiPasspointPolicy> CREATOR =
+ new Creator<WifiPasspointPolicy>() {
+ @Override
+ public WifiPasspointPolicy createFromParcel(Parcel in) {
+ return null;
+ }
+
+ @Override
+ public WifiPasspointPolicy[] newArray(int size) {
+ return new WifiPasspointPolicy[size];
+ }
+ };
+}