diff options
51 files changed, 2200 insertions, 582 deletions
diff --git a/Android.bp b/Android.bp index ab2bd9d98a6b..580df85f7dad 100644 --- a/Android.bp +++ b/Android.bp @@ -704,7 +704,6 @@ java_defaults { required: [ // TODO: remove gps_debug when the build system propagates "required" properly. "gps_debug.conf", - "libtextclassifier", // Loaded with System.loadLibrary by android.view.textclassifier "libmedia2_jni", ], @@ -830,7 +829,12 @@ aidl_interface { "core/java/android/net/IIpMemoryStore.aidl", "core/java/android/net/INetworkStackConnector.aidl", "core/java/android/net/INetworkStackStatusCallback.aidl", + "core/java/android/net/IpPrefixParcelable.aidl", + "core/java/android/net/LinkAddressParcelable.aidl", + "core/java/android/net/LinkPropertiesParcelable.aidl", "core/java/android/net/PrivateDnsConfigParcel.aidl", + "core/java/android/net/ProxyInfoParcelable.aidl", + "core/java/android/net/RouteInfoParcelable.aidl", "core/java/android/net/dhcp/DhcpServingParamsParcel.aidl", "core/java/android/net/dhcp/IDhcpServer.aidl", "core/java/android/net/dhcp/IDhcpServerCallbacks.aidl", @@ -850,6 +854,10 @@ java_library { "nist-sip", "tagsoup", "rappor", + "libtextclassifier-java", + ], + required: [ + "libtextclassifier", ], dxflags: ["--core-library"], } @@ -1256,7 +1264,6 @@ stubs_defaults { "ext", "framework", "voip-common", - "android.test.mock.impl", ], local_sourcepaths: frameworks_base_subdirs, installable: false, diff --git a/api/current.txt b/api/current.txt index 7c7429ffedaf..e4ecd5ee9798 100755 --- a/api/current.txt +++ b/api/current.txt @@ -41302,10 +41302,10 @@ package android.telecom { ctor public CallRedirectionService(); method public final void cancelCall(); method public final android.os.IBinder onBind(android.content.Intent); - method public abstract void onPlaceCall(android.net.Uri, android.telecom.PhoneAccountHandle); + method public abstract void onPlaceCall(android.net.Uri, android.telecom.PhoneAccountHandle, boolean); method public final boolean onUnbind(android.content.Intent); method public final void placeCallUnmodified(); - method public final void redirectCall(android.net.Uri, android.telecom.PhoneAccountHandle); + method public final void redirectCall(android.net.Uri, android.telecom.PhoneAccountHandle, boolean); field public static final java.lang.String SERVICE_INTERFACE = "android.telecom.CallRedirectionService"; } @@ -43336,7 +43336,7 @@ package android.telephony.data { field public static final int PROTOCOL_IPV6 = 1; // 0x1 field public static final int PROTOCOL_PPP = 3; // 0x3 field public static final int TYPE_CBS = 128; // 0x80 - field public static final int TYPE_DEFAULT = 1; // 0x1 + field public static final int TYPE_DEFAULT = 17; // 0x11 field public static final int TYPE_DUN = 8; // 0x8 field public static final int TYPE_EMERGENCY = 512; // 0x200 field public static final int TYPE_FOTA = 32; // 0x20 @@ -43380,6 +43380,7 @@ package android.telephony.emergency { method public int compareTo(android.telephony.emergency.EmergencyNumber); method public int describeContents(); method public java.lang.String getCountryIso(); + method public int getEmergencyCallRouting(); method public int getEmergencyNumberSourceBitmask(); method public java.util.List<java.lang.Integer> getEmergencyNumberSources(); method public java.util.List<java.lang.Integer> getEmergencyServiceCategories(); @@ -43390,6 +43391,9 @@ package android.telephony.emergency { method public boolean isInEmergencyServiceCategories(int); method public void writeToParcel(android.os.Parcel, int); field public static final android.os.Parcelable.Creator<android.telephony.emergency.EmergencyNumber> CREATOR; + field public static final int EMERGENCY_CALL_ROUTING_EMERGENCY = 1; // 0x1 + field public static final int EMERGENCY_CALL_ROUTING_NORMAL = 2; // 0x2 + field public static final int EMERGENCY_CALL_ROUTING_UNKNOWN = 0; // 0x0 field public static final int EMERGENCY_NUMBER_SOURCE_DATABASE = 16; // 0x10 field public static final int EMERGENCY_NUMBER_SOURCE_DEFAULT = 8; // 0x8 field public static final int EMERGENCY_NUMBER_SOURCE_MODEM_CONFIG = 4; // 0x4 @@ -43427,6 +43431,7 @@ package android.telephony.euicc { } public class EuiccManager { + method public android.telephony.euicc.EuiccManager createForCardId(int); method public void deleteSubscription(int, android.app.PendingIntent); method public void downloadSubscription(android.telephony.euicc.DownloadableSubscription, boolean, android.app.PendingIntent); method public java.lang.String getEid(); diff --git a/api/system-current.txt b/api/system-current.txt index 1bf6cf995eba..9cdc68284b14 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -6040,6 +6040,7 @@ package android.telephony.ims { method public android.os.Bundle getCallExtras(); method public int getCallType(); method public static int getCallTypeFromVideoState(int); + method public int getEmergencyCallRouting(); method public int getEmergencyServiceCategories(); method public android.telephony.ims.ImsStreamMediaProfile getMediaProfile(); method public int getRestrictCause(); @@ -6053,6 +6054,7 @@ package android.telephony.ims { method public void setCallExtraBoolean(java.lang.String, boolean); method public void setCallExtraInt(java.lang.String, int); method public void setCallRestrictCause(int); + method public void setEmergencyCallRouting(int); method public void setEmergencyServiceCategories(int); method public void updateCallExtras(android.telephony.ims.ImsCallProfile); method public void updateCallType(android.telephony.ims.ImsCallProfile); diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto index 7cfa58fb7bba..38130c89ce5a 100644 --- a/cmds/statsd/src/atoms.proto +++ b/cmds/statsd/src/atoms.proto @@ -24,6 +24,8 @@ import "frameworks/base/cmds/statsd/src/atom_field_options.proto"; import "frameworks/base/core/proto/android/app/enums.proto"; import "frameworks/base/core/proto/android/app/job/enums.proto"; import "frameworks/base/core/proto/android/bluetooth/enums.proto"; +import "frameworks/base/core/proto/android/bluetooth/hci/enums.proto"; +import "frameworks/base/core/proto/android/bluetooth/hfp/enums.proto"; import "frameworks/base/core/proto/android/net/networkcapabilities.proto"; import "frameworks/base/core/proto/android/os/enums.proto"; import "frameworks/base/core/proto/android/server/connectivity/data_stall_event.proto"; @@ -129,6 +131,9 @@ message Atom { LowMemReported low_mem_reported = 81; NetworkDnsEventReported network_dns_event_reported = 116; DataStallEvent data_stall_event = 121; + BluetoothLinkLayerConnectionEvent bluetooth_link_layer_connection_event = 125; + BluetoothAclConnectionStateChanged bluetooth_acl_connection_state_changed = 126; + BluetoothScoConnectionStateChanged bluetooth_sco_connection_state_changed = 127; } // Pulled events will start at field 10000. @@ -996,10 +1001,12 @@ message BluetoothEnabledStateChanged { } /** - * Logs when a Bluetooth device connects and disconnects. + * Logs when profiles on a Bluetooth device connects and disconnects. * * Logged from: - * packages/apps/Bluetooth/src/com/android/bluetooth/btservice/AdapterProperties.java + * packages/apps/Bluetooth/src/com/android/bluetooth/btservice/RemoteDevices.java + * + * Next Tag: 5 */ message BluetoothConnectionStateChanged { // The state of the connection. @@ -1008,13 +1015,152 @@ message BluetoothConnectionStateChanged { // An identifier that can be used to match connect and disconnect events. // Currently is last two bytes of a hash of a device level ID and // the mac address of the bluetooth device that is connected. - optional int32 obfuscated_id = 2; + // Deprecated: use obfuscated_id instead, this one is always 0 for Q+ + optional int32 OBSOLETE_obfuscated_id = 2 [deprecated = true]; // The profile that is connected. Eg. GATT, A2DP, HEADSET. // From android.bluetooth.BluetoothAdapter.java + // Default: 0 when not used optional int32 bt_profile = 3; + // An identifier that can be used to match events for this device. + // Currently, this is a salted hash of the MAC address of this Bluetooth device. + // Salt: Randomly generated 256 bit value + // Hash algorithm: HMAC-SHA256 + // Size: 32 byte + // Default: null or empty if the device identifier is not known + optional bytes obfuscated_id = 4 [(android.os.statsd.log_mode) = MODE_BYTES]; +} + +/** + * Logs when a Bluetooth device connects and disconnects over ACL + * + * Logged from: + * packages/apps/Bluetooth/src/com/android/bluetooth/btservice/AdapterProperties.java + * + * Next Tag: 3 + */ +message BluetoothAclConnectionStateChanged { + // An identifier that can be used to match events for this device. + // Currently, this is a salted hash of the MAC address of this Bluetooth device. + // Salt: Randomly generated 256 bit value + // Hash algorithm: HMAC-SHA256 + // Size: 32 byte + // Default: null or empty if the device identifier is not known + optional bytes obfuscated_id = 1 [(android.os.statsd.log_mode) = MODE_BYTES]; + // The state of the connection. + // Eg: CONNECTING, CONNECTED, DISCONNECTING, DISCONNECTED. + optional android.bluetooth.ConnectionStateEnum state = 2; } /** + * Logs when a Bluetooth device connects and disconnects over SCO + * + * Logged from: + * packages/apps/Bluetooth/src/com/android/bluetooth/hfp/HeadsetStateMachine.java + * packages/apps/Bluetooth/src/com/android/bluetooth/hfp/HeadsetClientStateMachine.java + * + * Next Tag: 4 + */ +message BluetoothScoConnectionStateChanged { + // An identifier that can be used to match events for this device. + // Currently, this is a salted hash of the MAC address of this Bluetooth device. + // Salt: Randomly generated 256 bit value + // Hash algorithm: HMAC-SHA256 + // Size: 32 byte + // Default: null or empty if the device identifier is not known + optional bytes obfuscated_id = 1 [(android.os.statsd.log_mode) = MODE_BYTES]; + // The state of the connection. + // Eg: CONNECTING, CONNECTED, DISCONNECTING, DISCONNECTED. + optional android.bluetooth.ConnectionStateEnum state = 2; + // Codec used for this SCO connection + // Default: UNKNOWN + optional android.bluetooth.hfp.ScoCodec codec = 3; +} + +// Logs when there is an event affecting Bluetooth device's link layer connection. +// - This event is triggered when there is a related HCI command or event +// - Users of this metrics can deduce Bluetooth device's connection state from these events +// - HCI commands are logged before the command is sent, after receiving command status, and after +// receiving command complete +// - HCI events are logged when they arrive +// +// Low level log from system/bt +// +// Bluetooth classic commands: +// - CMD_CREATE_CONNECTION +// - CMD_DISCONNECT +// - CMD_CREATE_CONNECTION_CANCEL +// - CMD_ACCEPT_CONNECTION_REQUEST +// - CMD_REJECT_CONNECTION_REQUEST +// - CMD_SETUP_ESCO_CONNECTION +// - CMD_ACCEPT_ESCO_CONNECTION +// - CMD_REJECT_ESCO_CONNECTION +// - CMD_ENH_SETUP_ESCO_CONNECTION +// - CMD_ENH_ACCEPT_ESCO_CONNECTION +// +// Bluetooth low energy commands: +// - CMD_BLE_CREATE_LL_CONN [Only logged on error or when initiator filter policy is 0x00] +// - CMD_BLE_CREATE_CONN_CANCEL [Only logged when there is an error] +// - CMD_BLE_EXTENDED_CREATE_CONNECTION [Only logged on error or when initiator filter policy is 0x00] +// - CMD_BLE_CLEAR_WHITE_LIST +// - CMD_BLE_ADD_WHITE_LIST +// - CMD_BLE_REMOVE_WHITE_LIST +// +// Bluetooth classic events: +// - EVT_CONNECTION_COMP +// - EVT_CONNECTION_REQUEST +// - EVT_DISCONNECTION_COMP +// - EVT_ESCO_CONNECTION_COMP +// - EVT_ESCO_CONNECTION_CHANGED +// +// Bluetooth low energy meta events: +// - BLE_EVT_CONN_COMPLETE_EVT +// - BLE_EVT_ENHANCED_CONN_COMPLETE_EVT +// +// Next tag: 10 +message BluetoothLinkLayerConnectionEvent { + // An identifier that can be used to match events for this device. + // Currently, this is a salted hash of the MAC address of this Bluetooth device. + // Salt: Randomly generated 256 bit value + // Hash algorithm: HMAC-SHA256 + // Size: 32 byte + // Default: null or empty if the device identifier is not known + optional bytes obfuscated_id = 1 [(android.os.statsd.log_mode) = MODE_BYTES]; + // Connection handle of this connection if available + // Range: 0x0000 - 0x0EFF (12 bits) + // Default: 0xFFFF if the handle is unknown + optional int32 connection_handle = 2; + // Direction of the link + // Default: DIRECTION_UNKNOWN + optional android.bluetooth.DirectionEnum direction = 3; + // Type of this link + // Default: LINK_TYPE_UNKNOWN + optional android.bluetooth.LinkTypeEnum type = 4; + + // Reason metadata for this link layer connection event, rules for interpretation: + // 1. If hci_cmd is set and valid, hci_event can be either EVT_COMMAND_STATUS or + // EVT_COMMAND_COMPLETE, ignore hci_ble_event in this case + // 2. If hci_event is set to EVT_BLE_META, look at hci_ble_event; otherwise, if hci_event is + // set and valid, ignore hci_ble_event + + // HCI command associated with this event + // Default: CMD_UNKNOWN + optional android.bluetooth.hci.CommandEnum hci_cmd = 5; + // HCI event associated with this event + // Default: EVT_UNKNOWN + optional android.bluetooth.hci.EventEnum hci_event = 6; + // HCI BLE meta event associated with this event + // Default: BLE_EVT_UNKNOWN + optional android.bluetooth.hci.BleMetaEventEnum hci_ble_event = 7; + // HCI command status code if this is triggerred by hci_cmd + // Default: STATUS_UNKNOWN + optional android.bluetooth.hci.StatusEnum cmd_status = 8; + // HCI reason code associated with this event + // Default: STATUS_UNKNOWN + optional android.bluetooth.hci.StatusEnum reason_code = 9; +} + + +/** * Logs when something is plugged into or removed from the USB-C connector. * * Logged from: diff --git a/config/hiddenapi-greylist.txt b/config/hiddenapi-greylist.txt index 7b1c26afb42c..2bd813e14937 100644 --- a/config/hiddenapi-greylist.txt +++ b/config/hiddenapi-greylist.txt @@ -3643,11 +3643,9 @@ Lcom/android/internal/telephony/SubscriptionInfoUpdater;->logd(Ljava/lang/String Lcom/android/internal/telephony/SubscriptionInfoUpdater;->mContext:Landroid/content/Context; Lcom/android/internal/telephony/SubscriptionInfoUpdater;->mCurrentlyActiveUserId:I Lcom/android/internal/telephony/SubscriptionInfoUpdater;->mIccId:[Ljava/lang/String; -Lcom/android/internal/telephony/SubscriptionInfoUpdater;->mInsertSimState:[I Lcom/android/internal/telephony/SubscriptionInfoUpdater;->mPackageManager:Landroid/content/pm/IPackageManager; Lcom/android/internal/telephony/SubscriptionInfoUpdater;->mPhone:[Lcom/android/internal/telephony/Phone; Lcom/android/internal/telephony/SubscriptionInfoUpdater;->PROJECT_SIM_NUM:I -Lcom/android/internal/telephony/SubscriptionInfoUpdater;->updateSubscriptionInfoByIccId()V Lcom/android/internal/telephony/TelephonyCapabilities;->supportsAdn(I)Z Lcom/android/internal/telephony/TelephonyProperties;->PROPERTY_ICC_OPERATOR_NUMERIC:Ljava/lang/String; Lcom/android/internal/telephony/test/InterpreterEx;-><init>(Ljava/lang/String;)V diff --git a/core/java/android/net/IpPrefixParcelable.aidl b/core/java/android/net/IpPrefixParcelable.aidl new file mode 100644 index 000000000000..93a8d41936cc --- /dev/null +++ b/core/java/android/net/IpPrefixParcelable.aidl @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. +*/ + +package android.net; + +parcelable IpPrefixParcelable { + String address; + int prefixLength; +}
\ No newline at end of file diff --git a/core/java/android/net/LinkAddressParcelable.aidl b/core/java/android/net/LinkAddressParcelable.aidl new file mode 100644 index 000000000000..af8e79b21f69 --- /dev/null +++ b/core/java/android/net/LinkAddressParcelable.aidl @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. +*/ + +package android.net; + +parcelable LinkAddressParcelable { + String address; + int prefixLength; + int flags; + int scope; +}
\ No newline at end of file diff --git a/core/java/android/net/LinkPropertiesParcelable.aidl b/core/java/android/net/LinkPropertiesParcelable.aidl new file mode 100644 index 000000000000..b153dc70e1b8 --- /dev/null +++ b/core/java/android/net/LinkPropertiesParcelable.aidl @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. +*/ + +package android.net; + +import android.net.IpPrefixParcelable; +import android.net.LinkAddressParcelable; +import android.net.ProxyInfoParcelable; +import android.net.RouteInfoParcelable; + +parcelable LinkPropertiesParcelable { + String ifaceName; + LinkAddressParcelable[] linkAddresses; + String[] dnses; + String[] pcscfs; + String[] validatedPrivateDnses; + boolean usePrivateDns; + String privateDnsServerName; + String domains; + RouteInfoParcelable[] routes; + ProxyInfoParcelable httpProxy; + int mtu; + String tcpBufferSizes; + IpPrefixParcelable nat64Prefix; + LinkPropertiesParcelable[] stackedLinks; +}
\ No newline at end of file diff --git a/core/java/android/net/NetworkSpecifier.java b/core/java/android/net/NetworkSpecifier.java index 9ce2a5bd1b54..12cdc342e28e 100644 --- a/core/java/android/net/NetworkSpecifier.java +++ b/core/java/android/net/NetworkSpecifier.java @@ -17,7 +17,7 @@ package android.net; /** - * Describes specific properties of a network for use in a {@link NetworkRequest}. + * Describes specific properties of a requested network for use in a {@link NetworkRequest}. * * Applications cannot instantiate this class by themselves, but can obtain instances of * subclasses of this class via other APIs. @@ -49,4 +49,29 @@ public abstract class NetworkSpecifier { public void assertValidFromUid(int requestorUid) { // empty } + + /** + * Optional method which can be overridden by concrete implementations of NetworkSpecifier to + * perform any redaction of information from the NetworkSpecifier, e.g. if it contains + * sensitive information. The default implementation simply returns the object itself - i.e. + * no information is redacted. A concrete implementation may return a modified (copy) of the + * NetworkSpecifier, or even return a null to fully remove all information. + * <p> + * This method is relevant to NetworkSpecifier objects used by agents - those are shared with + * apps by default. Some agents may store sensitive matching information in the specifier, + * e.g. a Wi-Fi SSID (which should not be shared since it may leak location). Those classes + * can redact to a null. Other agents use the Network Specifier to share public information + * with apps - those should not be redacted. + * <p> + * The default implementation redacts no information. + * + * @return A NetworkSpecifier object to be passed along to the requesting app. + * + * @hide + */ + public NetworkSpecifier redact() { + // TODO (b/122160111): convert default to null once all platform NetworkSpecifiers + // implement this method. + return this; + } } diff --git a/core/java/android/net/ProxyInfoParcelable.aidl b/core/java/android/net/ProxyInfoParcelable.aidl new file mode 100644 index 000000000000..59fd8467b820 --- /dev/null +++ b/core/java/android/net/ProxyInfoParcelable.aidl @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. +*/ + +package android.net; + +parcelable ProxyInfoParcelable { + String host; + int port; + String[] exclusionList; + String pacFileUrl; +} diff --git a/core/java/android/net/RouteInfoParcelable.aidl b/core/java/android/net/RouteInfoParcelable.aidl new file mode 100644 index 000000000000..15bcdcfc2000 --- /dev/null +++ b/core/java/android/net/RouteInfoParcelable.aidl @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. +*/ + +package android.net; + +import android.net.IpPrefixParcelable; + +parcelable RouteInfoParcelable { + IpPrefixParcelable destination; + String gatewayAddr; + String ifaceName; + int type; +} diff --git a/core/java/android/view/LayoutInflater.java b/core/java/android/view/LayoutInflater.java index 723289005651..f2259b045c0a 100644 --- a/core/java/android/view/LayoutInflater.java +++ b/core/java/android/view/LayoutInflater.java @@ -28,6 +28,7 @@ import android.content.res.XmlResourceParser; import android.graphics.Canvas; import android.os.Handler; import android.os.Message; +import android.os.SystemProperties; import android.os.Trace; import android.util.AttributeSet; import android.util.Log; @@ -37,6 +38,9 @@ import android.widget.FrameLayout; import com.android.internal.R; +import dalvik.system.PathClassLoader; +import java.io.File; +import java.lang.reflect.Method; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; @@ -71,6 +75,10 @@ public abstract class LayoutInflater { private static final String TAG = LayoutInflater.class.getSimpleName(); private static final boolean DEBUG = false; + private static final String USE_PRECOMPILED_LAYOUT_SYSTEM_PROPERTY + = "view.precompiled_layout_enabled"; + private static final String COMPILED_VIEW_DEX_FILE_NAME = "/compiled_view.dex"; + /** Empty stack trace used to avoid log spam in re-throw exceptions. */ private static final StackTraceElement[] EMPTY_STACK_TRACE = new StackTraceElement[0]; @@ -92,6 +100,13 @@ public abstract class LayoutInflater { private Factory2 mPrivateFactory; private Filter mFilter; + // Indicates whether we should try to inflate layouts using a precompiled layout instead of + // inflating from the XML resource. + private boolean mUseCompiledView; + // This variable holds the classloader that will be used to look for precompiled layouts. The + // The classloader includes the generated compiled_view.dex file. + private ClassLoader mPrecompiledClassLoader; + @UnsupportedAppUsage final Object[] mConstructorArgs = new Object[2]; @@ -214,6 +229,7 @@ public abstract class LayoutInflater { */ protected LayoutInflater(Context context) { mContext = context; + initPrecompiledViews(); } /** @@ -230,6 +246,7 @@ public abstract class LayoutInflater { mFactory2 = original.mFactory2; mPrivateFactory = original.mPrivateFactory; setFilter(original.mFilter); + initPrecompiledViews(); } /** @@ -371,6 +388,29 @@ public abstract class LayoutInflater { } } + private void initPrecompiledViews() { + try { + mUseCompiledView = + SystemProperties.getBoolean(USE_PRECOMPILED_LAYOUT_SYSTEM_PROPERTY, false); + if (mUseCompiledView) { + mPrecompiledClassLoader = mContext.getClassLoader(); + String dexFile = mContext.getCodeCacheDir() + COMPILED_VIEW_DEX_FILE_NAME; + if (new File(dexFile).exists()) { + mPrecompiledClassLoader = new PathClassLoader(dexFile, mPrecompiledClassLoader); + } else { + // If the precompiled layout file doesn't exist, then disable precompiled + // layouts. + mUseCompiledView = false; + } + } + } catch (Throwable e) { + if (DEBUG) { + Log.e(TAG, "Failed to initialized precompiled views layouts", e); + } + mUseCompiledView = false; + } + } + /** * Inflate a new view hierarchy from the specified xml resource. Throws * {@link InflateException} if there is an error. @@ -427,10 +467,14 @@ public abstract class LayoutInflater { final Resources res = getContext().getResources(); if (DEBUG) { Log.d(TAG, "INFLATING from resource: \"" + res.getResourceName(resource) + "\" (" - + Integer.toHexString(resource) + ")"); + + Integer.toHexString(resource) + ")"); } - final XmlResourceParser parser = res.getLayout(resource); + View view = tryInflatePrecompiled(resource, res, root, attachToRoot); + if (view != null) { + return view; + } + XmlResourceParser parser = res.getLayout(resource); try { return inflate(parser, root, attachToRoot); } finally { @@ -438,6 +482,73 @@ public abstract class LayoutInflater { } } + private @Nullable + View tryInflatePrecompiled(@LayoutRes int resource, Resources res, @Nullable ViewGroup root, + boolean attachToRoot) { + if (!mUseCompiledView) { + return null; + } + + Trace.traceBegin(Trace.TRACE_TAG_VIEW, "inflate (precompiled)"); + + // Try to inflate using a precompiled layout. + String pkg = res.getResourcePackageName(resource); + String layout = res.getResourceEntryName(resource); + + try { + Class clazz = mPrecompiledClassLoader.loadClass("" + pkg + ".CompiledView"); + Method inflater = clazz.getMethod(layout, Context.class, int.class); + View view = (View) inflater.invoke(null, mContext, resource); + + if (view != null && root != null) { + // We were able to use the precompiled inflater, but now we need to do some work to + // attach the view to the root correctly. + XmlResourceParser parser = res.getLayout(resource); + try { + AttributeSet attrs = Xml.asAttributeSet(parser); + advanceToRootNode(parser); + ViewGroup.LayoutParams params = root.generateLayoutParams(attrs); + + if (attachToRoot) { + root.addView(view, params); + } else { + view.setLayoutParams(params); + } + } finally { + parser.close(); + } + } + + return view; + } catch (Throwable e) { + if (DEBUG) { + Log.e(TAG, "Failed to use precompiled view", e); + } + } finally { + Trace.traceEnd(Trace.TRACE_TAG_VIEW); + } + return null; + } + + /** + * Advances the given parser to the first START_TAG. Throws InflateException if no start tag is + * found. + */ + private void advanceToRootNode(XmlPullParser parser) + throws InflateException, IOException, XmlPullParserException { + // Look for the root node. + int type; + while ((type = parser.next()) != XmlPullParser.START_TAG && + type != XmlPullParser.END_DOCUMENT) { + // Empty + } + + if (type != XmlPullParser.START_TAG) { + throw new InflateException(parser.getPositionDescription() + + ": No start tag found!"); + } + } + /** * Inflate a new view hierarchy from the specified XML node. Throws * {@link InflateException} if there is an error. @@ -471,18 +582,7 @@ public abstract class LayoutInflater { View result = root; try { - // Look for the root node. - int type; - while ((type = parser.next()) != XmlPullParser.START_TAG && - type != XmlPullParser.END_DOCUMENT) { - // Empty - } - - if (type != XmlPullParser.START_TAG) { - throw new InflateException(parser.getPositionDescription() - + ": No start tag found!"); - } - + advanceToRootNode(parser); final String name = parser.getName(); if (DEBUG) { @@ -985,82 +1085,85 @@ public abstract class LayoutInflater { + "reference. The layout ID " + value + " is not valid."); } - final XmlResourceParser childParser = context.getResources().getLayout(layout); + final View precompiled = tryInflatePrecompiled(layout, context.getResources(), + (ViewGroup) parent, /*attachToRoot=*/true); + if (precompiled == null) { + final XmlResourceParser childParser = context.getResources().getLayout(layout); - try { - final AttributeSet childAttrs = Xml.asAttributeSet(childParser); + try { + final AttributeSet childAttrs = Xml.asAttributeSet(childParser); - while ((type = childParser.next()) != XmlPullParser.START_TAG && - type != XmlPullParser.END_DOCUMENT) { - // Empty. - } + while ((type = childParser.next()) != XmlPullParser.START_TAG && + type != XmlPullParser.END_DOCUMENT) { + // Empty. + } - if (type != XmlPullParser.START_TAG) { - throw new InflateException(childParser.getPositionDescription() + - ": No start tag found!"); - } + if (type != XmlPullParser.START_TAG) { + throw new InflateException(childParser.getPositionDescription() + + ": No start tag found!"); + } - final String childName = childParser.getName(); + final String childName = childParser.getName(); - if (TAG_MERGE.equals(childName)) { - // The <merge> tag doesn't support android:theme, so - // nothing special to do here. - rInflate(childParser, parent, context, childAttrs, false); - } else { - final View view = createViewFromTag(parent, childName, - context, childAttrs, hasThemeOverride); - final ViewGroup group = (ViewGroup) parent; - - final TypedArray a = context.obtainStyledAttributes( - attrs, R.styleable.Include); - final int id = a.getResourceId(R.styleable.Include_id, View.NO_ID); - final int visibility = a.getInt(R.styleable.Include_visibility, -1); - a.recycle(); - - // We try to load the layout params set in the <include /> tag. - // If the parent can't generate layout params (ex. missing width - // or height for the framework ViewGroups, though this is not - // necessarily true of all ViewGroups) then we expect it to throw - // a runtime exception. - // We catch this exception and set localParams accordingly: true - // means we successfully loaded layout params from the <include> - // tag, false means we need to rely on the included layout params. - ViewGroup.LayoutParams params = null; - try { - params = group.generateLayoutParams(attrs); - } catch (RuntimeException e) { - // Ignore, just fail over to child attrs. - } - if (params == null) { - params = group.generateLayoutParams(childAttrs); - } - view.setLayoutParams(params); + if (TAG_MERGE.equals(childName)) { + // The <merge> tag doesn't support android:theme, so + // nothing special to do here. + rInflate(childParser, parent, context, childAttrs, false); + } else { + final View view = createViewFromTag(parent, childName, + context, childAttrs, hasThemeOverride); + final ViewGroup group = (ViewGroup) parent; + + final TypedArray a = context.obtainStyledAttributes( + attrs, R.styleable.Include); + final int id = a.getResourceId(R.styleable.Include_id, View.NO_ID); + final int visibility = a.getInt(R.styleable.Include_visibility, -1); + a.recycle(); + + // We try to load the layout params set in the <include /> tag. + // If the parent can't generate layout params (ex. missing width + // or height for the framework ViewGroups, though this is not + // necessarily true of all ViewGroups) then we expect it to throw + // a runtime exception. + // We catch this exception and set localParams accordingly: true + // means we successfully loaded layout params from the <include> + // tag, false means we need to rely on the included layout params. + ViewGroup.LayoutParams params = null; + try { + params = group.generateLayoutParams(attrs); + } catch (RuntimeException e) { + // Ignore, just fail over to child attrs. + } + if (params == null) { + params = group.generateLayoutParams(childAttrs); + } + view.setLayoutParams(params); - // Inflate all children. - rInflateChildren(childParser, view, childAttrs, true); + // Inflate all children. + rInflateChildren(childParser, view, childAttrs, true); - if (id != View.NO_ID) { - view.setId(id); - } + if (id != View.NO_ID) { + view.setId(id); + } - switch (visibility) { - case 0: - view.setVisibility(View.VISIBLE); - break; - case 1: - view.setVisibility(View.INVISIBLE); - break; - case 2: - view.setVisibility(View.GONE); - break; - } + switch (visibility) { + case 0: + view.setVisibility(View.VISIBLE); + break; + case 1: + view.setVisibility(View.INVISIBLE); + break; + case 2: + view.setVisibility(View.GONE); + break; + } - group.addView(view); + group.addView(view); + } + } finally { + childParser.close(); } - } finally { - childParser.close(); } - LayoutInflater.consumeChildElements(parser); } diff --git a/core/java/android/view/textclassifier/TextClassifierImpl.java b/core/java/android/view/textclassifier/TextClassifierImpl.java index 6e5751abbc40..00a267c20342 100644 --- a/core/java/android/view/textclassifier/TextClassifierImpl.java +++ b/core/java/android/view/textclassifier/TextClassifierImpl.java @@ -43,6 +43,8 @@ import android.provider.ContactsContract; import com.android.internal.annotations.GuardedBy; import com.android.internal.util.Preconditions; +import com.google.android.textclassifier.AnnotatorModel; + import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; @@ -91,7 +93,7 @@ public final class TextClassifierImpl implements TextClassifier { @GuardedBy("mLock") // Do not access outside this lock. private ModelFile mModel; @GuardedBy("mLock") // Do not access outside this lock. - private TextClassifierImplNative mNative; + private AnnotatorModel mNative; private final Object mLoggerLock = new Object(); @GuardedBy("mLoggerLock") // Do not access outside this lock. @@ -124,7 +126,7 @@ public final class TextClassifierImpl implements TextClassifier { && rangeLength <= mSettings.getSuggestSelectionMaxRangeLength()) { final String localesString = concatenateLocales(request.getDefaultLocales()); final ZonedDateTime refTime = ZonedDateTime.now(); - final TextClassifierImplNative nativeImpl = getNative(request.getDefaultLocales()); + final AnnotatorModel nativeImpl = getNative(request.getDefaultLocales()); final int start; final int end; if (mSettings.isModelDarkLaunchEnabled() && !request.isDarkLaunchAllowed()) { @@ -133,7 +135,7 @@ public final class TextClassifierImpl implements TextClassifier { } else { final int[] startEnd = nativeImpl.suggestSelection( string, request.getStartIndex(), request.getEndIndex(), - new TextClassifierImplNative.SelectionOptions(localesString)); + new AnnotatorModel.SelectionOptions(localesString)); start = startEnd[0]; end = startEnd[1]; } @@ -141,10 +143,10 @@ public final class TextClassifierImpl implements TextClassifier { && start >= 0 && end <= string.length() && start <= request.getStartIndex() && end >= request.getEndIndex()) { final TextSelection.Builder tsBuilder = new TextSelection.Builder(start, end); - final TextClassifierImplNative.ClassificationResult[] results = + final AnnotatorModel.ClassificationResult[] results = nativeImpl.classifyText( string, start, end, - new TextClassifierImplNative.ClassificationOptions( + new AnnotatorModel.ClassificationOptions( refTime.toInstant().toEpochMilli(), refTime.getZone().getId(), localesString)); @@ -183,11 +185,11 @@ public final class TextClassifierImpl implements TextClassifier { final String localesString = concatenateLocales(request.getDefaultLocales()); final ZonedDateTime refTime = request.getReferenceTime() != null ? request.getReferenceTime() : ZonedDateTime.now(); - final TextClassifierImplNative.ClassificationResult[] results = + final AnnotatorModel.ClassificationResult[] results = getNative(request.getDefaultLocales()) .classifyText( string, request.getStartIndex(), request.getEndIndex(), - new TextClassifierImplNative.ClassificationOptions( + new AnnotatorModel.ClassificationOptions( refTime.toInstant().toEpochMilli(), refTime.getZone().getId(), localesString)); @@ -227,17 +229,17 @@ public final class TextClassifierImpl implements TextClassifier { ? request.getEntityConfig().resolveEntityListModifications( getEntitiesForHints(request.getEntityConfig().getHints())) : mSettings.getEntityListDefault(); - final TextClassifierImplNative nativeImpl = + final AnnotatorModel nativeImpl = getNative(request.getDefaultLocales()); - final TextClassifierImplNative.AnnotatedSpan[] annotations = + final AnnotatorModel.AnnotatedSpan[] annotations = nativeImpl.annotate( textString, - new TextClassifierImplNative.AnnotationOptions( + new AnnotatorModel.AnnotationOptions( refTime.toInstant().toEpochMilli(), refTime.getZone().getId(), concatenateLocales(request.getDefaultLocales()))); - for (TextClassifierImplNative.AnnotatedSpan span : annotations) { - final TextClassifierImplNative.ClassificationResult[] results = + for (AnnotatorModel.AnnotatedSpan span : annotations) { + final AnnotatorModel.ClassificationResult[] results = span.getClassification(); if (results.length == 0 || !entitiesToIdentify.contains(results[0].getCollection())) { @@ -296,7 +298,7 @@ public final class TextClassifierImpl implements TextClassifier { } } - private TextClassifierImplNative getNative(LocaleList localeList) + private AnnotatorModel getNative(LocaleList localeList) throws FileNotFoundException { synchronized (mLock) { localeList = localeList == null ? LocaleList.getEmptyLocaleList() : localeList; @@ -309,7 +311,7 @@ public final class TextClassifierImpl implements TextClassifier { destroyNativeIfExistsLocked(); final ParcelFileDescriptor fd = ParcelFileDescriptor.open( new File(bestModel.getPath()), ParcelFileDescriptor.MODE_READ_ONLY); - mNative = new TextClassifierImplNative(fd.getFd()); + mNative = new AnnotatorModel(fd.getFd()); closeAndLogError(fd); mModel = bestModel; } @@ -397,14 +399,14 @@ public final class TextClassifierImpl implements TextClassifier { } private TextClassification createClassificationResult( - TextClassifierImplNative.ClassificationResult[] classifications, + AnnotatorModel.ClassificationResult[] classifications, String text, int start, int end, @Nullable Instant referenceTime) { final String classifiedText = text.substring(start, end); final TextClassification.Builder builder = new TextClassification.Builder() .setText(classifiedText); final int size = classifications.length; - TextClassifierImplNative.ClassificationResult highestScoringResult = null; + AnnotatorModel.ClassificationResult highestScoringResult = null; float highestScore = Float.MIN_VALUE; for (int i = 0; i < size; i++) { builder.setEntityType(classifications[i].getCollection(), @@ -467,9 +469,9 @@ public final class TextClassifierImpl implements TextClassifier { try { final ParcelFileDescriptor modelFd = ParcelFileDescriptor.open( file, ParcelFileDescriptor.MODE_READ_ONLY); - final int version = TextClassifierImplNative.getVersion(modelFd.getFd()); + final int version = AnnotatorModel.getVersion(modelFd.getFd()); final String supportedLocalesStr = - TextClassifierImplNative.getLocales(modelFd.getFd()); + AnnotatorModel.getLocales(modelFd.getFd()); if (supportedLocalesStr.isEmpty()) { Log.d(DEFAULT_LOG_TAG, "Ignoring " + file.getAbsolutePath()); return null; @@ -657,7 +659,7 @@ public final class TextClassifierImpl implements TextClassifier { public static List<LabeledIntent> create( Context context, @Nullable Instant referenceTime, - TextClassifierImplNative.ClassificationResult classification, + AnnotatorModel.ClassificationResult classification, String text) { final String type = classification.getCollection().trim().toLowerCase(Locale.ENGLISH); text = text.trim(); diff --git a/core/java/android/view/textclassifier/TextClassifierImplNative.java b/core/java/android/view/textclassifier/TextClassifierImplNative.java deleted file mode 100644 index 3d4c8f2863ea..000000000000 --- a/core/java/android/view/textclassifier/TextClassifierImplNative.java +++ /dev/null @@ -1,301 +0,0 @@ -/* - * Copyright (C) 2017 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.view.textclassifier; - -import android.content.res.AssetFileDescriptor; - -/** - * Java wrapper for TextClassifier native library interface. This library is used for detecting - * entities in text. - */ -final class TextClassifierImplNative { - - static { - System.loadLibrary("textclassifier"); - } - - private final long mModelPtr; - - /** - * Creates a new instance of TextClassifierImplNative, using the provided model image, given as - * a file descriptor. - */ - TextClassifierImplNative(int fd) { - mModelPtr = nativeNew(fd); - if (mModelPtr == 0L) { - throw new IllegalArgumentException("Couldn't initialize TC from file descriptor."); - } - } - - /** - * Creates a new instance of TextClassifierImplNative, using the provided model image, given as - * a file path. - */ - TextClassifierImplNative(String path) { - mModelPtr = nativeNewFromPath(path); - if (mModelPtr == 0L) { - throw new IllegalArgumentException("Couldn't initialize TC from given file."); - } - } - - /** - * Creates a new instance of TextClassifierImplNative, using the provided model image, given as - * an AssetFileDescriptor. - */ - TextClassifierImplNative(AssetFileDescriptor afd) { - mModelPtr = nativeNewFromAssetFileDescriptor(afd, afd.getStartOffset(), afd.getLength()); - if (mModelPtr == 0L) { - throw new IllegalArgumentException( - "Couldn't initialize TC from given AssetFileDescriptor"); - } - } - - /** - * Given a string context and current selection, computes the SmartSelection suggestion. - * - * <p>The begin and end are character indices into the context UTF8 string. selectionBegin is - * the character index where the selection begins, and selectionEnd is the index of one - * character past the selection span. - * - * <p>The return value is an array of two ints: suggested selection beginning and end, with the - * same semantics as the input selectionBeginning and selectionEnd. - */ - public int[] suggestSelection( - String context, int selectionBegin, int selectionEnd, SelectionOptions options) { - return nativeSuggestSelection(mModelPtr, context, selectionBegin, selectionEnd, options); - } - - /** - * Given a string context and current selection, classifies the type of the selected text. - * - * <p>The begin and end params are character indices in the context string. - * - * <p>Returns an array of ClassificationResult objects with the probability scores for different - * collections. - */ - public ClassificationResult[] classifyText( - String context, int selectionBegin, int selectionEnd, ClassificationOptions options) { - return nativeClassifyText(mModelPtr, context, selectionBegin, selectionEnd, options); - } - - /** - * Annotates given input text. The annotations should cover the whole input context except for - * whitespaces, and are sorted by their position in the context string. - */ - public AnnotatedSpan[] annotate(String text, AnnotationOptions options) { - return nativeAnnotate(mModelPtr, text, options); - } - - /** Frees up the allocated memory. */ - public void close() { - nativeClose(mModelPtr); - } - - /** Returns a comma separated list of locales supported by the model as BCP 47 tags. */ - public static String getLocales(int fd) { - return nativeGetLocales(fd); - } - - /** Returns the version of the model. */ - public static int getVersion(int fd) { - return nativeGetVersion(fd); - } - - /** Represents a datetime parsing result from classifyText calls. */ - public static final class DatetimeResult { - static final int GRANULARITY_YEAR = 0; - static final int GRANULARITY_MONTH = 1; - static final int GRANULARITY_WEEK = 2; - static final int GRANULARITY_DAY = 3; - static final int GRANULARITY_HOUR = 4; - static final int GRANULARITY_MINUTE = 5; - static final int GRANULARITY_SECOND = 6; - - private final long mTimeMsUtc; - private final int mGranularity; - - DatetimeResult(long timeMsUtc, int granularity) { - mGranularity = granularity; - mTimeMsUtc = timeMsUtc; - } - - public long getTimeMsUtc() { - return mTimeMsUtc; - } - - public int getGranularity() { - return mGranularity; - } - } - - /** Represents a result of classifyText method call. */ - public static final class ClassificationResult { - private final String mCollection; - private final float mScore; - private final DatetimeResult mDatetimeResult; - - ClassificationResult( - String collection, float score, DatetimeResult datetimeResult) { - mCollection = collection; - mScore = score; - mDatetimeResult = datetimeResult; - } - - public String getCollection() { - if (mCollection.equals(TextClassifier.TYPE_DATE) && mDatetimeResult != null) { - switch (mDatetimeResult.getGranularity()) { - case DatetimeResult.GRANULARITY_HOUR: - // fall through - case DatetimeResult.GRANULARITY_MINUTE: - // fall through - case DatetimeResult.GRANULARITY_SECOND: - return TextClassifier.TYPE_DATE_TIME; - default: - return TextClassifier.TYPE_DATE; - } - } - return mCollection; - } - - public float getScore() { - return mScore; - } - - public DatetimeResult getDatetimeResult() { - return mDatetimeResult; - } - } - - /** Represents a result of Annotate call. */ - public static final class AnnotatedSpan { - private final int mStartIndex; - private final int mEndIndex; - private final ClassificationResult[] mClassification; - - AnnotatedSpan( - int startIndex, int endIndex, ClassificationResult[] classification) { - mStartIndex = startIndex; - mEndIndex = endIndex; - mClassification = classification; - } - - public int getStartIndex() { - return mStartIndex; - } - - public int getEndIndex() { - return mEndIndex; - } - - public ClassificationResult[] getClassification() { - return mClassification; - } - } - - /** Represents options for the suggestSelection call. */ - public static final class SelectionOptions { - private final String mLocales; - - SelectionOptions(String locales) { - mLocales = locales; - } - - public String getLocales() { - return mLocales; - } - } - - /** Represents options for the classifyText call. */ - public static final class ClassificationOptions { - private final long mReferenceTimeMsUtc; - private final String mReferenceTimezone; - private final String mLocales; - - ClassificationOptions(long referenceTimeMsUtc, String referenceTimezone, String locale) { - mReferenceTimeMsUtc = referenceTimeMsUtc; - mReferenceTimezone = referenceTimezone; - mLocales = locale; - } - - public long getReferenceTimeMsUtc() { - return mReferenceTimeMsUtc; - } - - public String getReferenceTimezone() { - return mReferenceTimezone; - } - - public String getLocale() { - return mLocales; - } - } - - /** Represents options for the Annotate call. */ - public static final class AnnotationOptions { - private final long mReferenceTimeMsUtc; - private final String mReferenceTimezone; - private final String mLocales; - - AnnotationOptions(long referenceTimeMsUtc, String referenceTimezone, String locale) { - mReferenceTimeMsUtc = referenceTimeMsUtc; - mReferenceTimezone = referenceTimezone; - mLocales = locale; - } - - public long getReferenceTimeMsUtc() { - return mReferenceTimeMsUtc; - } - - public String getReferenceTimezone() { - return mReferenceTimezone; - } - - public String getLocale() { - return mLocales; - } - } - - private static native long nativeNew(int fd); - - private static native long nativeNewFromPath(String path); - - private static native long nativeNewFromAssetFileDescriptor( - AssetFileDescriptor afd, long offset, long size); - - private static native int[] nativeSuggestSelection( - long context, - String text, - int selectionBegin, - int selectionEnd, - SelectionOptions options); - - private static native ClassificationResult[] nativeClassifyText( - long context, - String text, - int selectionBegin, - int selectionEnd, - ClassificationOptions options); - - private static native AnnotatedSpan[] nativeAnnotate( - long context, String text, AnnotationOptions options); - - private static native void nativeClose(long context); - - private static native String nativeGetLocales(int fd); - - private static native int nativeGetVersion(int fd); -} diff --git a/core/proto/Android.bp b/core/proto/Android.bp new file mode 100644 index 000000000000..80cc2d4cab94 --- /dev/null +++ b/core/proto/Android.bp @@ -0,0 +1,27 @@ +// Copyright (C) 2018 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. + +// C++ library for Bluetooth platform wide protobuf definitions +cc_library_static { + name: "libbt-platform-protos-lite", + host_supported: true, + proto: { + export_proto_headers: true, + type: "lite", + }, + srcs: [ + "android/bluetooth/enums.proto", + "android/bluetooth/hci/enums.proto", + ], +} diff --git a/core/proto/android/bluetooth/enums.proto b/core/proto/android/bluetooth/enums.proto index d0c922664351..76c240ecff4d 100644 --- a/core/proto/android/bluetooth/enums.proto +++ b/core/proto/android/bluetooth/enums.proto @@ -41,3 +41,18 @@ enum EnableDisableReasonEnum { ENABLE_DISABLE_REASON_USER_SWITCH = 8; ENABLE_DISABLE_REASON_RESTORE_USER_SETTING = 9; } + +enum DirectionEnum { + DIRECTION_UNKNOWN = 0; + DIRECTION_OUTGOING = 1; + DIRECTION_INCOMING = 2; +} + +// First item is the default value, other values follow Bluetooth spec definition +enum LinkTypeEnum { + // Link type is at most 1 byte (0xFF), thus 0xFFF must not be a valid value + LINK_TYPE_UNKNOWN = 0xFFF; + LINK_TYPE_SCO = 0x00; + LINK_TYPE_ACL = 0x01; + LINK_TYPE_ESCO = 0x02; +} diff --git a/core/proto/android/bluetooth/hci/enums.proto b/core/proto/android/bluetooth/hci/enums.proto new file mode 100644 index 000000000000..e1d96bbce68a --- /dev/null +++ b/core/proto/android/bluetooth/hci/enums.proto @@ -0,0 +1,519 @@ +/* + * Copyright 2018 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. + */ + +syntax = "proto2"; +package android.bluetooth.hci; + +option java_outer_classname = "BluetoothHciProtoEnums"; +option java_multiple_files = true; + +// HCI command opcodes (OCF+OGF) from Bluetooth 5.0 specification Vol 2, Part E, Section 7 +// Original definition: system/bt/stack/include/hcidefs.h +enum CommandEnum { + // Opcode is at most 2 bytes (0xFFFF), thus 0xFFFFF must not be a valid value + CMD_UNKNOWN = 0xFFFFF; + // Link control commands 0x0400 + CMD_INQUIRY = 0x0401; + CMD_INQUIRY_CANCEL = 0x0402; + CMD_PERIODIC_INQUIRY_MODE = 0x0403; + CMD_EXIT_PERIODIC_INQUIRY_MODE = 0x0404; + CMD_CREATE_CONNECTION = 0x0405; + CMD_DISCONNECT = 0x0406; + CMD_ADD_SCO_CONNECTION = 0x0407; // Deprecated since Bluetooth 1.2 + CMD_CREATE_CONNECTION_CANCEL = 0x0408; + CMD_ACCEPT_CONNECTION_REQUEST = 0x0409; + CMD_REJECT_CONNECTION_REQUEST = 0x040A; + CMD_LINK_KEY_REQUEST_REPLY = 0x040B; + CMD_LINK_KEY_REQUEST_NEG_REPLY = 0x040C; + CMD_PIN_CODE_REQUEST_REPLY = 0x040D; + CMD_PIN_CODE_REQUEST_NEG_REPLY = 0x040E; + CMD_CHANGE_CONN_PACKET_TYPE = 0x040F; + CMD_AUTHENTICATION_REQUESTED = 0x0411; + CMD_SET_CONN_ENCRYPTION = 0x0413; + CMD_CHANGE_CONN_LINK_KEY = 0x0415; + CMD_MASTER_LINK_KEY = 0x0417; + CMD_RMT_NAME_REQUEST = 0x0419; + CMD_RMT_NAME_REQUEST_CANCEL = 0x041A; + CMD_READ_RMT_FEATURES = 0x041B; + CMD_READ_RMT_EXT_FEATURES = 0x041C; + CMD_READ_RMT_VERSION_INFO = 0x041D; + CMD_READ_RMT_CLOCK_OFFSET = 0x041F; + CMD_READ_LMP_HANDLE = 0x0420; + CMD_SETUP_ESCO_CONNECTION = 0x0428; + CMD_ACCEPT_ESCO_CONNECTION = 0x0429; + CMD_REJECT_ESCO_CONNECTION = 0x042A; + CMD_IO_CAPABILITY_REQUEST_REPLY = 0x042B; + CMD_USER_CONF_REQUEST_REPLY = 0x042C; + CMD_USER_CONF_VALUE_NEG_REPLY = 0x042D; + CMD_USER_PASSKEY_REQ_REPLY = 0x042E; + CMD_USER_PASSKEY_REQ_NEG_REPLY = 0x042F; + CMD_REM_OOB_DATA_REQ_REPLY = 0x0430; + CMD_REM_OOB_DATA_REQ_NEG_REPLY = 0x0433; + CMD_IO_CAP_REQ_NEG_REPLY = 0x0434; + // BEGIN: AMP commands (not used in system/bt) + CMD_CREATE_PHYSICAL_LINK = 0x0435; + CMD_ACCEPT_PHYSICAL_LINK = 0x0436; + CMD_DISCONNECT_PHYSICAL_LINK = 0x0437; + CMD_CREATE_LOGICAL_LINK = 0x0438; + CMD_ACCEPT_LOGICAL_LINK = 0x0439; + CMD_DISCONNECT_LOGICAL_LINK = 0x043A; + CMD_LOGICAL_LINK_CANCEL = 0x043B; + CMD_FLOW_SPEC_MODIFY = 0x043C; + // END: AMP commands + CMD_ENH_SETUP_ESCO_CONNECTION = 0x043D; + CMD_ENH_ACCEPT_ESCO_CONNECTION = 0x043E; + CMD_TRUNCATED_PAGE = 0x043F; + CMD_TRUNCATED_PAGE_CANCEL = 0x0440; + CMD_SET_CLB = 0x0441; + CMD_RECEIVE_CLB = 0x0442; + CMD_START_SYNC_TRAIN = 0x0443; + CMD_RECEIVE_SYNC_TRAIN = 0x0444; + CMD_REM_OOB_EXTENDED_DATA_REQ_REPLY = 0x0445; // Not currently used in system/bt + // Link policy commands 0x0800 + CMD_HOLD_MODE = 0x0801; + CMD_SNIFF_MODE = 0x0803; + CMD_EXIT_SNIFF_MODE = 0x0804; + CMD_PARK_MODE = 0x0805; + CMD_EXIT_PARK_MODE = 0x0806; + CMD_QOS_SETUP = 0x0807; + CMD_ROLE_DISCOVERY = 0x0809; + CMD_SWITCH_ROLE = 0x080B; + CMD_READ_POLICY_SETTINGS = 0x080C; + CMD_WRITE_POLICY_SETTINGS = 0x080D; + CMD_READ_DEF_POLICY_SETTINGS = 0x080E; + CMD_WRITE_DEF_POLICY_SETTINGS = 0x080F; + CMD_FLOW_SPECIFICATION = 0x0810; + CMD_SNIFF_SUB_RATE = 0x0811; + // Host controller baseband commands 0x0C00 + CMD_SET_EVENT_MASK = 0x0C01; + CMD_RESET = 0x0C03; + CMD_SET_EVENT_FILTER = 0x0C05; + CMD_FLUSH = 0x0C08; + CMD_READ_PIN_TYPE = 0x0C09; + CMD_WRITE_PIN_TYPE = 0x0C0A; + CMD_CREATE_NEW_UNIT_KEY = 0x0C0B; + CMD_GET_MWS_TRANS_LAYER_CFG = 0x0C0C; // Deprecated (not used in spec) + CMD_READ_STORED_LINK_KEY = 0x0C0D; + CMD_WRITE_STORED_LINK_KEY = 0x0C11; + CMD_DELETE_STORED_LINK_KEY = 0x0C12; + CMD_CHANGE_LOCAL_NAME = 0x0C13; + CMD_READ_LOCAL_NAME = 0x0C14; + CMD_READ_CONN_ACCEPT_TOUT = 0x0C15; + CMD_WRITE_CONN_ACCEPT_TOUT = 0x0C16; + CMD_READ_PAGE_TOUT = 0x0C17; + CMD_WRITE_PAGE_TOUT = 0x0C18; + CMD_READ_SCAN_ENABLE = 0x0C19; + CMD_WRITE_SCAN_ENABLE = 0x0C1A; + CMD_READ_PAGESCAN_CFG = 0x0C1B; + CMD_WRITE_PAGESCAN_CFG = 0x0C1C; + CMD_READ_INQUIRYSCAN_CFG = 0x0C1D; + CMD_WRITE_INQUIRYSCAN_CFG = 0x0C1E; + CMD_READ_AUTHENTICATION_ENABLE = 0x0C1F; + CMD_WRITE_AUTHENTICATION_ENABLE = 0x0C20; + CMD_READ_ENCRYPTION_MODE = 0x0C21; // Deprecated + CMD_WRITE_ENCRYPTION_MODE = 0x0C22; // Deprecated + CMD_READ_CLASS_OF_DEVICE = 0x0C23; + CMD_WRITE_CLASS_OF_DEVICE = 0x0C24; + CMD_READ_VOICE_SETTINGS = 0x0C25; + CMD_WRITE_VOICE_SETTINGS = 0x0C26; + CMD_READ_AUTOMATIC_FLUSH_TIMEOUT = 0x0C27; + CMD_WRITE_AUTOMATIC_FLUSH_TIMEOUT = 0x0C28; + CMD_READ_NUM_BCAST_REXMITS = 0x0C29; + CMD_WRITE_NUM_BCAST_REXMITS = 0x0C2A; + CMD_READ_HOLD_MODE_ACTIVITY = 0x0C2B; + CMD_WRITE_HOLD_MODE_ACTIVITY = 0x0C2C; + CMD_READ_TRANSMIT_POWER_LEVEL = 0x0C2D; + CMD_READ_SCO_FLOW_CTRL_ENABLE = 0x0C2E; + CMD_WRITE_SCO_FLOW_CTRL_ENABLE = 0x0C2F; + CMD_SET_HC_TO_HOST_FLOW_CTRL = 0x0C31; + CMD_HOST_BUFFER_SIZE = 0x0C33; + CMD_HOST_NUM_PACKETS_DONE = 0x0C35; + CMD_READ_LINK_SUPER_TOUT = 0x0C36; + CMD_WRITE_LINK_SUPER_TOUT = 0x0C37; + CMD_READ_NUM_SUPPORTED_IAC = 0x0C38; + CMD_READ_CURRENT_IAC_LAP = 0x0C39; + CMD_WRITE_CURRENT_IAC_LAP = 0x0C3A; + CMD_READ_PAGESCAN_PERIOD_MODE = 0x0C3B; // Deprecated + CMD_WRITE_PAGESCAN_PERIOD_MODE = 0x0C3C; // Deprecated + CMD_READ_PAGESCAN_MODE = 0x0C3D; // Deprecated + CMD_WRITE_PAGESCAN_MODE = 0x0C3E; // Deprecated + CMD_SET_AFH_CHANNELS = 0x0C3F; + CMD_READ_INQSCAN_TYPE = 0x0C42; + CMD_WRITE_INQSCAN_TYPE = 0x0C43; + CMD_READ_INQUIRY_MODE = 0x0C44; + CMD_WRITE_INQUIRY_MODE = 0x0C45; + CMD_READ_PAGESCAN_TYPE = 0x0C46; + CMD_WRITE_PAGESCAN_TYPE = 0x0C47; + CMD_READ_AFH_ASSESSMENT_MODE = 0x0C48; + CMD_WRITE_AFH_ASSESSMENT_MODE = 0x0C49; + CMD_READ_EXT_INQ_RESPONSE = 0x0C51; + CMD_WRITE_EXT_INQ_RESPONSE = 0x0C52; + CMD_REFRESH_ENCRYPTION_KEY = 0x0C53; + CMD_READ_SIMPLE_PAIRING_MODE = 0x0C55; + CMD_WRITE_SIMPLE_PAIRING_MODE = 0x0C56; + CMD_READ_LOCAL_OOB_DATA = 0x0C57; + CMD_READ_INQ_TX_POWER_LEVEL = 0x0C58; + CMD_WRITE_INQ_TX_POWER_LEVEL = 0x0C59; + CMD_READ_ERRONEOUS_DATA_RPT = 0x0C5A; + CMD_WRITE_ERRONEOUS_DATA_RPT = 0x0C5B; + CMD_ENHANCED_FLUSH = 0x0C5F; + CMD_SEND_KEYPRESS_NOTIF = 0x0C60; + CMD_READ_LOGICAL_LINK_ACCEPT_TIMEOUT = 0x0C61; + CMD_WRITE_LOGICAL_LINK_ACCEPT_TIMEOUT = 0x0C62; + CMD_SET_EVENT_MASK_PAGE_2 = 0x0C63; + CMD_READ_LOCATION_DATA = 0x0C64; + CMD_WRITE_LOCATION_DATA = 0x0C65; + CMD_READ_FLOW_CONTROL_MODE = 0x0C66; + CMD_WRITE_FLOW_CONTROL_MODE = 0x0C67; + CMD_READ_ENHANCED_TX_PWR_LEVEL = 0x0C68; // Not currently used in system/bt + CMD_READ_BE_FLUSH_TOUT = 0x0C69; + CMD_WRITE_BE_FLUSH_TOUT = 0x0C6A; + CMD_SHORT_RANGE_MODE = 0x0C6B; + CMD_READ_BLE_HOST_SUPPORT = 0x0C6C; + CMD_WRITE_BLE_HOST_SUPPORT = 0x0C6D; + CMD_SET_MWS_CHANNEL_PARAMETERS = 0x0C6E; + CMD_SET_EXTERNAL_FRAME_CONFIGURATION = 0x0C6F; + CMD_SET_MWS_SIGNALING = 0x0C70; + CMD_SET_MWS_TRANSPORT_LAYER = 0x0C71; + CMD_SET_MWS_SCAN_FREQUENCY_TABLE = 0x0C72; + CMD_SET_MWS_PATTERN_CONFIGURATION = 0x0C73; + CMD_SET_RESERVED_LT_ADDR = 0x0C74; + CMD_DELETE_RESERVED_LT_ADDR = 0x0C75; + CMD_WRITE_CLB_DATA = 0x0C76; + CMD_READ_SYNC_TRAIN_PARAM = 0x0C77; + CMD_WRITE_SYNC_TRAIN_PARAM = 0x0C78; + CMD_READ_SECURE_CONNS_SUPPORT = 0x0C79; + CMD_WRITE_SECURE_CONNS_SUPPORT = 0x0C7A; + CMD_READ_AUTHED_PAYLOAD_TIMEOUT = 0x0C7B; // Not currently used in system/bt + CMD_WRITE_AUTHED_PAYLOAD_TIMEOUT = 0x0C7C; // Not currently used in system/bt + CMD_READ_LOCAL_OOB_EXTENDED_DATA = 0x0C7D; // Not currently used in system/bt + CMD_READ_EXTENDED_PAGE_TIMEOUT = 0x0C7E; // Not currently used in system/bt + CMD_WRITE_EXTENDED_PAGE_TIMEOUT = 0x0C7F; // Not currently used in system/bt + CMD_READ_EXTENDED_INQUIRY_LENGTH = 0x0C80; // Not currently used in system/bt + CMD_WRITE_EXTENDED_INQUIRY_LENGTH = 0x0C81; // Not currently used in system/bt + // Informational parameter commands 0x1000 + CMD_READ_LOCAL_VERSION_INFO = 0x1001; + CMD_READ_LOCAL_SUPPORTED_CMDS = 0x1002; + CMD_READ_LOCAL_FEATURES = 0x1003; + CMD_READ_LOCAL_EXT_FEATURES = 0x1004; + CMD_READ_BUFFER_SIZE = 0x1005; + CMD_READ_COUNTRY_CODE = 0x1007; // Deprecated + CMD_READ_BD_ADDR = 0x1009; + CMD_READ_DATA_BLOCK_SIZE = 0x100A; + CMD_READ_LOCAL_SUPPORTED_CODECS = 0x100B; + // Status parameter commands 0x1400 + CMD_READ_FAILED_CONTACT_COUNTER = 0x1401; + CMD_RESET_FAILED_CONTACT_COUNTER = 0x1402; + CMD_GET_LINK_QUALITY = 0x1403; + CMD_READ_RSSI = 0x1405; + CMD_READ_AFH_CH_MAP = 0x1406; + CMD_READ_CLOCK = 0x1407; + CMD_READ_ENCR_KEY_SIZE = 0x1408; + CMD_READ_LOCAL_AMP_INFO = 0x1409; + CMD_READ_LOCAL_AMP_ASSOC = 0x140A; + CMD_WRITE_REMOTE_AMP_ASSOC = 0x140B; + CMD_GET_MWS_TRANSPORT_CFG = 0x140C; // Not currently used in system/bt + CMD_SET_TRIGGERED_CLK_CAPTURE = 0x140D; // Not currently used in system/bt + // Testing commands 0x1800 + CMD_READ_LOOPBACK_MODE = 0x1801; + CMD_WRITE_LOOPBACK_MODE = 0x1802; + CMD_ENABLE_DEV_UNDER_TEST_MODE = 0x1803; + CMD_WRITE_SIMP_PAIR_DEBUG_MODE = 0x1804; + CMD_ENABLE_AMP_RCVR_REPORTS = 0x1807; + CMD_AMP_TEST_END = 0x1808; + CMD_AMP_TEST = 0x1809; + CMD_WRITE_SECURE_CONN_TEST_MODE = 0x180A; // Not currently used in system/bt + // BLE commands 0x2000 + CMD_BLE_SET_EVENT_MASK = 0x2001; + CMD_BLE_READ_BUFFER_SIZE = 0x2002; + CMD_BLE_READ_LOCAL_SPT_FEAT = 0x2003; + CMD_BLE_WRITE_LOCAL_SPT_FEAT = 0x2004; + CMD_BLE_WRITE_RANDOM_ADDR = 0x2005; + CMD_BLE_WRITE_ADV_PARAMS = 0x2006; + CMD_BLE_READ_ADV_CHNL_TX_POWER = 0x2007; + CMD_BLE_WRITE_ADV_DATA = 0x2008; + CMD_BLE_WRITE_SCAN_RSP_DATA = 0x2009; + CMD_BLE_WRITE_ADV_ENABLE = 0x200A; + CMD_BLE_WRITE_SCAN_PARAMS = 0x200B; + CMD_BLE_WRITE_SCAN_ENABLE = 0x200C; + CMD_BLE_CREATE_LL_CONN = 0x200D; + CMD_BLE_CREATE_CONN_CANCEL = 0x200E; + CMD_BLE_READ_WHITE_LIST_SIZE = 0x200F; + CMD_BLE_CLEAR_WHITE_LIST = 0x2010; + CMD_BLE_ADD_WHITE_LIST = 0x2011; + CMD_BLE_REMOVE_WHITE_LIST = 0x2012; + CMD_BLE_UPD_LL_CONN_PARAMS = 0x2013; + CMD_BLE_SET_HOST_CHNL_CLASS = 0x2014; + CMD_BLE_READ_CHNL_MAP = 0x2015; + CMD_BLE_READ_REMOTE_FEAT = 0x2016; + CMD_BLE_ENCRYPT = 0x2017; + CMD_BLE_RAND = 0x2018; + CMD_BLE_START_ENC = 0x2019; + CMD_BLE_LTK_REQ_REPLY = 0x201A; + CMD_BLE_LTK_REQ_NEG_REPLY = 0x201B; + CMD_BLE_READ_SUPPORTED_STATES = 0x201C; + CMD_BLE_RECEIVER_TEST = 0x201D; + CMD_BLE_TRANSMITTER_TEST = 0x201E; + CMD_BLE_TEST_END = 0x201F; + CMD_BLE_RC_PARAM_REQ_REPLY = 0x2020; + CMD_BLE_RC_PARAM_REQ_NEG_REPLY = 0x2021; + CMD_BLE_SET_DATA_LENGTH = 0x2022; + CMD_BLE_READ_DEFAULT_DATA_LENGTH = 0x2023; + CMD_BLE_WRITE_DEFAULT_DATA_LENGTH = 0x2024; + CMD_BLE_GENERATE_DHKEY = 0x2026; // Not currently used in system/bt + CMD_BLE_ADD_DEV_RESOLVING_LIST = 0x2027; + CMD_BLE_RM_DEV_RESOLVING_LIST = 0x2028; + CMD_BLE_CLEAR_RESOLVING_LIST = 0x2029; + CMD_BLE_READ_RESOLVING_LIST_SIZE = 0x202A; + CMD_BLE_READ_RESOLVABLE_ADDR_PEER = 0x202B; + CMD_BLE_READ_RESOLVABLE_ADDR_LOCAL = 0x202C; + CMD_BLE_SET_ADDR_RESOLUTION_ENABLE = 0x202D; + CMD_BLE_SET_RAND_PRIV_ADDR_TIMOUT = 0x202E; + CMD_BLE_READ_MAXIMUM_DATA_LENGTH = 0x202F; + CMD_BLE_READ_PHY = 0x2030; + CMD_BLE_SET_DEFAULT_PHY = 0x2031; + CMD_BLE_SET_PHY = 0x2032; + CMD_BLE_ENH_RECEIVER_TEST = 0x2033; + CMD_BLE_ENH_TRANSMITTER_TEST = 0x2034; + CMD_BLE_SET_EXT_ADVERTISING_RANDOM_ADDRESS = 0x2035; + CMD_BLE_SET_EXT_ADVERTISING_PARAM = 0x2036; + CMD_BLE_SET_EXT_ADVERTISING_DATA = 0x2037; + CMD_BLE_SET_EXT_ADVERTISING_SCAN_RESP = 0x2038; + CMD_BLE_SET_EXT_ADVERTISING_ENABLE = 0x2039; + CMD_BLE_READ_MAXIMUM_ADVERTISING_DATA_LENGTH = 0x203A; + CMD_BLE_READ_NUMBER_OF_SUPPORTED_ADVERTISING_SETS = 0x203B; + CMD_BLE_REMOVE_ADVERTISING_SET = 0x203C; + CMD_BLE_CLEAR_ADVERTISING_SETS = 0x203D; + CMD_BLE_SET_PERIODIC_ADVERTISING_PARAM = 0x203E; + CMD_BLE_SET_PERIODIC_ADVERTISING_DATA = 0x203F; + CMD_BLE_SET_PERIODIC_ADVERTISING_ENABLE = 0x2040; + CMD_BLE_SET_EXTENDED_SCAN_PARAMETERS = 0x2041; + CMD_BLE_SET_EXTENDED_SCAN_ENABLE = 0x2042; + CMD_BLE_EXTENDED_CREATE_CONNECTION = 0x2043; + CMD_BLE_PERIODIC_ADVERTISING_CREATE_SYNC = 0x2044; + CMD_BLE_PERIODIC_ADVERTISING_CREATE_SYNC_CANCEL = 0x2045; + CMD_BLE_PERIODIC_ADVERTISING_TERMINATE_SYNC = 0x2046; + CMD_BLE_ADD_DEVICE_TO_PERIODIC_ADVERTISING_LIST = 0x2047; + CMD_BLE_RM_DEVICE_FROM_PERIODIC_ADVERTISING_LIST = 0x2048; + CMD_BLE_CLEAR_PERIODIC_ADVERTISING_LIST = 0x2049; + CMD_BLE_READ_PERIODIC_ADVERTISING_LIST_SIZE = 0x204A; + CMD_BLE_READ_TRANSMIT_POWER = 0x204B; + CMD_BLE_READ_RF_COMPENS_POWER = 0x204C; + CMD_BLE_WRITE_RF_COMPENS_POWER = 0x204D; + CMD_BLE_SET_PRIVACY_MODE = 0x204E; + // Vendor specific commands 0xFC00 and above + // Android vendor specific commands defined in + // https://source.android.com/devices/bluetooth/hci_requirements#vendor-specific-capabilities + CMD_BLE_VENDOR_CAP = 0xFD53; + CMD_BLE_MULTI_ADV = 0xFD54; + CMD_BLE_BATCH_SCAN = 0xFD56; + CMD_BLE_ADV_FILTER = 0xFD57; + CMD_BLE_TRACK_ADV = 0xFD58; + CMD_BLE_ENERGY_INFO = 0xFD59; + CMD_BLE_EXTENDED_SCAN_PARAMS = 0xFD5A; + CMD_CONTROLLER_DEBUG_INFO = 0xFD5B; + CMD_CONTROLLER_A2DP_OPCODE = 0xFD5D; + CMD_BRCM_SET_ACL_PRIORITY = 0xFC57; + // Other vendor specific commands below here +} + +// HCI event codes from the Bluetooth 5.0 specification Vol 2, Part 7, Section 7 +// Original definition: system/bt/stack/include/hcidefs.h +enum EventEnum { + // Event is at most 1 byte (0xFF), thus 0xFFF must not be a valid value + EVT_UNKNOWN = 0xFFF; + EVT_INQUIRY_COMP = 0x01; + EVT_INQUIRY_RESULT = 0x02; + EVT_CONNECTION_COMP = 0x03; + EVT_CONNECTION_REQUEST = 0x04; + EVT_DISCONNECTION_COMP = 0x05; + EVT_AUTHENTICATION_COMP = 0x06; + EVT_RMT_NAME_REQUEST_COMP = 0x07; + EVT_ENCRYPTION_CHANGE = 0x08; + EVT_CHANGE_CONN_LINK_KEY = 0x09; + EVT_MASTER_LINK_KEY_COMP = 0x0A; + EVT_READ_RMT_FEATURES_COMP = 0x0B; + EVT_READ_RMT_VERSION_COMP = 0x0C; + EVT_QOS_SETUP_COMP = 0x0D; + EVT_COMMAND_COMPLETE = 0x0E; + EVT_COMMAND_STATUS = 0x0F; + EVT_HARDWARE_ERROR = 0x10; + EVT_FLUSH_OCCURED = 0x11; + EVT_ROLE_CHANGE = 0x12; + EVT_NUM_COMPL_DATA_PKTS = 0x13; + EVT_MODE_CHANGE = 0x14; + EVT_RETURN_LINK_KEYS = 0x15; + EVT_PIN_CODE_REQUEST = 0x16; + EVT_LINK_KEY_REQUEST = 0x17; + EVT_LINK_KEY_NOTIFICATION = 0x18; + EVT_LOOPBACK_COMMAND = 0x19; + EVT_DATA_BUF_OVERFLOW = 0x1A; + EVT_MAX_SLOTS_CHANGED = 0x1B; + EVT_READ_CLOCK_OFF_COMP = 0x1C; + EVT_CONN_PKT_TYPE_CHANGE = 0x1D; + EVT_QOS_VIOLATION = 0x1E; + EVT_PAGE_SCAN_MODE_CHANGE = 0x1F; // Deprecated + EVT_PAGE_SCAN_REP_MODE_CHNG = 0x20; + EVT_FLOW_SPECIFICATION_COMP = 0x21; + EVT_INQUIRY_RSSI_RESULT = 0x22; + EVT_READ_RMT_EXT_FEATURES_COMP = 0x23; + EVT_ESCO_CONNECTION_COMP = 0x2C; + EVT_ESCO_CONNECTION_CHANGED = 0x2D; + EVT_SNIFF_SUB_RATE = 0x2E; + EVT_EXTENDED_INQUIRY_RESULT = 0x2F; + EVT_ENCRYPTION_KEY_REFRESH_COMP = 0x30; + EVT_IO_CAPABILITY_REQUEST = 0x31; + EVT_IO_CAPABILITY_RESPONSE = 0x32; + EVT_USER_CONFIRMATION_REQUEST = 0x33; + EVT_USER_PASSKEY_REQUEST = 0x34; + EVT_REMOTE_OOB_DATA_REQUEST = 0x35; + EVT_SIMPLE_PAIRING_COMPLETE = 0x36; + EVT_LINK_SUPER_TOUT_CHANGED = 0x38; + EVT_ENHANCED_FLUSH_COMPLETE = 0x39; + EVT_USER_PASSKEY_NOTIFY = 0x3B; + EVT_KEYPRESS_NOTIFY = 0x3C; + EVT_RMT_HOST_SUP_FEAT_NOTIFY = 0x3D; + EVT_BLE_META = 0x3E; + EVT_PHYSICAL_LINK_COMP = 0x40; + EVT_CHANNEL_SELECTED = 0x41; + EVT_DISC_PHYSICAL_LINK_COMP = 0x42; + EVT_PHY_LINK_LOSS_EARLY_WARNING = 0x43; + EVT_PHY_LINK_RECOVERY = 0x44; + EVT_LOGICAL_LINK_COMP = 0x45; + EVT_DISC_LOGICAL_LINK_COMP = 0x46; + EVT_FLOW_SPEC_MODIFY_COMP = 0x47; + EVT_NUM_COMPL_DATA_BLOCKS = 0x48; + EVT_AMP_TEST_START = 0x49; // Not currently used in system/bt + EVT_AMP_TEST_END = 0x4A; // Not currently used in system/bt + EVT_AMP_RECEIVER_RPT = 0x4B; // Not currently used in system/bt + EVT_SHORT_RANGE_MODE_COMPLETE = 0x4C; + EVT_AMP_STATUS_CHANGE = 0x4D; + EVT_SET_TRIGGERED_CLOCK_CAPTURE = 0x4E; + EVT_SYNC_TRAIN_CMPL = 0x4F; // Not currently used in system/bt + EVT_SYNC_TRAIN_RCVD = 0x50; // Not currently used in system/bt + EVT_CONNLESS_SLAVE_BROADCAST_RCVD = 0x51; // Not currently used in system/bt + EVT_CONNLESS_SLAVE_BROADCAST_TIMEOUT = 0x52; // Not currently used in system/bt + EVT_TRUNCATED_PAGE_CMPL = 0x53; // Not currently used in system/bt + EVT_SLAVE_PAGE_RES_TIMEOUT = 0x54; // Not currently used in system/bt + EVT_CONNLESS_SLAVE_BROADCAST_CHNL_MAP_CHANGE = 0x55; // Not currently used in system/bt + EVT_INQUIRY_RES_NOTIFICATION = 0x56; // Not currently used in system/bt + EVT_AUTHED_PAYLOAD_TIMEOUT = 0x57; // Not currently used in system/bt + EVT_SAM_STATUS_CHANGE = 0x58; // Not currently used in system/bt +} + +// Bluetooth low energy related meta event codes +// from the Bluetooth 5.0 specification Vol 2, Part E, Section 7.7.65 +// Original definition: system/bt/stack/include/hcidefs.h +enum BleMetaEventEnum { + // BLE meta event code is at most 1 byte (0xFF), thus 0xFFF must not be a valid value + BLE_EVT_UNKNOWN = 0xFFF; + BLE_EVT_CONN_COMPLETE_EVT = 0x01; + BLE_EVT_ADV_PKT_RPT_EVT = 0x02; + BLE_EVT_LL_CONN_PARAM_UPD_EVT = 0x03; + BLE_EVT_READ_REMOTE_FEAT_CMPL_EVT = 0x04; + BLE_EVT_LTK_REQ_EVT = 0x05; + BLE_EVT_RC_PARAM_REQ_EVT = 0x06; + BLE_EVT_DATA_LENGTH_CHANGE_EVT = 0x07; + BLE_EVT_READ_LOCAL_P256_PUB_KEY = 0x08; // Not currently used in system/bt + BLE_EVT_GEN_DHKEY_CMPL = 0x09; // Not currently used in system/bt + BLE_EVT_ENHANCED_CONN_COMPLETE_EVT = 0x0a; + BLE_EVT_DIRECT_ADV_EVT = 0x0b; + BLE_EVT_PHY_UPDATE_COMPLETE_EVT = 0x0c; + BLE_EVT_EXTENDED_ADVERTISING_REPORT_EVT = 0x0D; + BLE_EVT_PERIODIC_ADV_SYNC_EST_EVT = 0x0E; + BLE_EVT_PERIODIC_ADV_REPORT_EVT = 0x0F; + BLE_EVT_PERIODIC_ADV_SYNC_LOST_EVT = 0x10; + BLE_EVT_SCAN_TIMEOUT_EVT = 0x11; + BLE_EVT_ADVERTISING_SET_TERMINATED_EVT = 0x12; + BLE_EVT_SCAN_REQ_RX_EVT = 0x13; + BLE_EVT_CHNL_SELECTION_ALGORITHM = 0x14; // Not currently used in system/bt +} + +// HCI status code from the Bluetooth 5.0 specification Vol 2, Part D. +// Original definition: system/bt/stack/include/hcidefs.h +enum StatusEnum { + // Status is at most 1 byte (0xFF), thus 0xFFF must not be a valid value + STATUS_UNKNOWN = 0xFFF; + STATUS_SUCCESS = 0x00; + STATUS_ILLEGAL_COMMAND = 0x01; + STATUS_NO_CONNECTION = 0x02; + STATUS_HW_FAILURE = 0x03; + STATUS_PAGE_TIMEOUT = 0x04; + STATUS_AUTH_FAILURE = 0x05; + STATUS_KEY_MISSING = 0x06; + STATUS_MEMORY_FULL = 0x07; + STATUS_CONNECTION_TOUT = 0x08; + STATUS_MAX_NUM_OF_CONNECTIONS = 0x09; + STATUS_MAX_NUM_OF_SCOS = 0x0A; + STATUS_CONNECTION_EXISTS = 0x0B; + STATUS_COMMAND_DISALLOWED = 0x0C; + STATUS_HOST_REJECT_RESOURCES = 0x0D; + STATUS_HOST_REJECT_SECURITY = 0x0E; + STATUS_HOST_REJECT_DEVICE = 0x0F; + STATUS_HOST_TIMEOUT = 0x10; + STATUS_UNSUPPORTED_VALUE = 0x11; + STATUS_ILLEGAL_PARAMETER_FMT = 0x12; + STATUS_PEER_USER = 0x13; + STATUS_PEER_LOW_RESOURCES = 0x14; + STATUS_PEER_POWER_OFF = 0x15; + STATUS_CONN_CAUSE_LOCAL_HOST = 0x16; + STATUS_REPEATED_ATTEMPTS = 0x17; + STATUS_PAIRING_NOT_ALLOWED = 0x18; + STATUS_UNKNOWN_LMP_PDU = 0x19; + STATUS_UNSUPPORTED_REM_FEATURE = 0x1A; + STATUS_SCO_OFFSET_REJECTED = 0x1B; + STATUS_SCO_INTERVAL_REJECTED = 0x1C; + STATUS_SCO_AIR_MODE = 0x1D; + STATUS_INVALID_LMP_PARAM = 0x1E; + STATUS_UNSPECIFIED = 0x1F; + STATUS_UNSUPPORTED_LMP_FEATURE = 0x20; + STATUS_ROLE_CHANGE_NOT_ALLOWED = 0x21; + STATUS_LMP_RESPONSE_TIMEOUT = 0x22; + STATUS_LMP_STATUS_TRANS_COLLISION = 0x23; + STATUS_LMP_PDU_NOT_ALLOWED = 0x24; + STATUS_ENCRY_MODE_NOT_ACCEPTABLE = 0x25; + STATUS_UNIT_KEY_USED = 0x26; + STATUS_QOS_NOT_SUPPORTED = 0x27; + STATUS_INSTANT_PASSED = 0x28; + STATUS_PAIRING_WITH_UNIT_KEY_NOT_SUPPORTED = 0x29; + STATUS_DIFF_TRANSACTION_COLLISION = 0x2A; + STATUS_UNDEFINED_0x2B = 0x2B; // Not used + STATUS_QOS_UNACCEPTABLE_PARAM = 0x2C; + STATUS_QOS_REJECTED = 0x2D; + STATUS_CHAN_CLASSIF_NOT_SUPPORTED = 0x2E; + STATUS_INSUFFCIENT_SECURITY = 0x2F; + STATUS_PARAM_OUT_OF_RANGE = 0x30; + STATUS_UNDEFINED_0x31 = 0x31; // Not used + STATUS_ROLE_SWITCH_PENDING = 0x32; + STATUS_UNDEFINED_0x33 = 0x33; + STATUS_RESERVED_SLOT_VIOLATION = 0x34; + STATUS_ROLE_SWITCH_FAILED = 0x35; + STATUS_INQ_RSP_DATA_TOO_LARGE = 0x36; + STATUS_SIMPLE_PAIRING_NOT_SUPPORTED = 0x37; + STATUS_HOST_BUSY_PAIRING = 0x38; + STATUS_REJ_NO_SUITABLE_CHANNEL = 0x39; + STATUS_CONTROLLER_BUSY = 0x3A; + STATUS_UNACCEPT_CONN_INTERVAL = 0x3B; + STATUS_ADVERTISING_TIMEOUT = 0x3C; + STATUS_CONN_TOUT_DUE_TO_MIC_FAILURE = 0x3D; + STATUS_CONN_FAILED_ESTABLISHMENT = 0x3E; + STATUS_MAC_CONNECTION_FAILED = 0x3F; + STATUS_LT_ADDR_ALREADY_IN_USE = 0x40; + STATUS_LT_ADDR_NOT_ALLOCATED = 0x41; + STATUS_CLB_NOT_ENABLED = 0x42; + STATUS_CLB_DATA_TOO_BIG = 0x43; + STATUS_OPERATION_CANCELED_BY_HOST = 0x44; // Not currently used in system/bt +} diff --git a/core/proto/android/bluetooth/hfp/enums.proto b/core/proto/android/bluetooth/hfp/enums.proto new file mode 100644 index 000000000000..d286e4b64d67 --- /dev/null +++ b/core/proto/android/bluetooth/hfp/enums.proto @@ -0,0 +1,28 @@ +/* + * Copyright 2018 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. + */ + +syntax = "proto2"; +package android.bluetooth.hfp; + +option java_outer_classname = "BluetoothHfpProtoEnums"; +option java_multiple_files = true; + +enum ScoCodec { + SCO_CODEC_UNKNOWN = 0; + SCO_CODEC_CVSD = 1; + // Default codec behind Wide Band Speech + SCO_CODEC_MSBC = 2; +}
\ No newline at end of file diff --git a/data/etc/platform.xml b/data/etc/platform.xml index 73c10d238a60..afe791344f7b 100644 --- a/data/etc/platform.xml +++ b/data/etc/platform.xml @@ -182,11 +182,11 @@ code to link against. --> <library name="android.test.base" - file="/system/framework/android.test.base.impl.jar" /> + file="/system/framework/android.test.base.jar" /> <library name="android.test.mock" - file="/system/framework/android.test.mock.impl.jar" /> + file="/system/framework/android.test.mock.jar" /> <library name="android.test.runner" - file="/system/framework/android.test.runner.impl.jar" /> + file="/system/framework/android.test.runner.jar" /> <!-- In BOOT_JARS historically, and now added to legacy applications. --> <library name="android.hidl.base-V1.0-java" diff --git a/packages/SettingsLib/src/com/android/settingslib/drawer/CategoryKey.java b/packages/SettingsLib/src/com/android/settingslib/drawer/CategoryKey.java index dd8bfda43ff9..1310e57785e8 100644 --- a/packages/SettingsLib/src/com/android/settingslib/drawer/CategoryKey.java +++ b/packages/SettingsLib/src/com/android/settingslib/drawer/CategoryKey.java @@ -51,6 +51,12 @@ public final class CategoryKey { public static final String CATEGORY_GESTURES = "com.android.settings.category.ia.gestures"; public static final String CATEGORY_NIGHT_DISPLAY = "com.android.settings.category.ia.night_display"; + public static final String CATEGORY_ABOUT_LEGAL = + "com.android.settings.category.ia.about_legal"; + public static final String CATEGORY_MY_DEVICE_INFO = + "com.android.settings.category.ia.my_device_info"; + public static final String CATEGORY_BATTERY_SAVER_SETTINGS = + "com.android.settings.category.ia.battery_saver_settings"; public static final Map<String, String> KEY_COMPAT_MAP; diff --git a/services/core/java/com/android/server/BluetoothManagerService.java b/services/core/java/com/android/server/BluetoothManagerService.java index 555e89947a64..5ea3390d4e46 100644 --- a/services/core/java/com/android/server/BluetoothManagerService.java +++ b/services/core/java/com/android/server/BluetoothManagerService.java @@ -279,7 +279,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { Slog.d(TAG, "Airplane Mode change - current state: " + BluetoothAdapter.nameForState( - st)); + st) + ", isAirplaneModeOn()=" + isAirplaneModeOn()); if (isAirplaneModeOn()) { // Clear registered LE apps to force shut-off diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index d6f3e2ba4835..00550d9c660e 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -1494,6 +1494,9 @@ public class ConnectivityService extends IConnectivityManager.Stub newNc.setUids(null); newNc.setSSID(null); } + if (newNc.getNetworkSpecifier() != null) { + newNc.setNetworkSpecifier(newNc.getNetworkSpecifier().redact()); + } return newNc; } @@ -5358,7 +5361,8 @@ public class ConnectivityService extends IConnectivityManager.Stub } switch (notificationType) { case ConnectivityManager.CALLBACK_AVAILABLE: { - putParcelable(bundle, new NetworkCapabilities(networkAgent.networkCapabilities)); + putParcelable(bundle, networkCapabilitiesRestrictedForCallerPermissions( + networkAgent.networkCapabilities, nri.mPid, nri.mUid)); putParcelable(bundle, new LinkProperties(networkAgent.linkProperties)); // For this notification, arg1 contains the blocked status. msg.arg1 = arg1; diff --git a/services/core/java/com/android/server/camera/CameraServiceProxy.java b/services/core/java/com/android/server/camera/CameraServiceProxy.java index 0ee55ed2e832..527539d8ce0d 100644 --- a/services/core/java/com/android/server/camera/CameraServiceProxy.java +++ b/services/core/java/com/android/server/camera/CameraServiceProxy.java @@ -21,6 +21,7 @@ import android.content.Intent; import android.content.IntentFilter; import android.hardware.ICameraService; import android.hardware.ICameraServiceProxy; +import android.media.AudioManager; import android.metrics.LogMaker; import android.nfc.INfcAdapter; import android.os.Binder; @@ -393,6 +394,19 @@ public class CameraServiceProxy extends SystemService boolean wasEmpty = mActiveCameraUsage.isEmpty(); switch (newCameraState) { case ICameraServiceProxy.CAMERA_STATE_OPEN: + // Notify the audio subsystem about the facing of the most-recently opened + // camera This can be used to select the best audio tuning in case video + // recording with that camera will happen. Since only open events are used, if + // multiple cameras are opened at once, the one opened last will be used to + // select audio tuning. + AudioManager audioManager = getContext().getSystemService(AudioManager.class); + if (audioManager != null) { + // Map external to front for audio tuning purposes + String facingStr = (facing == ICameraServiceProxy.CAMERA_FACING_BACK) ? + "back" : "front"; + String facingParameter = "cameraFacing=" + facingStr; + audioManager.setParameters(facingParameter); + } break; case ICameraServiceProxy.CAMERA_STATE_ACTIVE: CameraUsageEvent newEvent = new CameraUsageEvent(facing, clientName, apiLevel); diff --git a/services/core/java/com/android/server/connectivity/PacManager.java b/services/core/java/com/android/server/connectivity/PacManager.java index 3ea9810f2d76..97896889f243 100644 --- a/services/core/java/com/android/server/connectivity/PacManager.java +++ b/services/core/java/com/android/server/connectivity/PacManager.java @@ -282,6 +282,7 @@ public class PacManager { private void setCurrentProxyScript(String script) { if (mProxyService == null) { Log.e(TAG, "setCurrentProxyScript: no proxy service"); + return; } try { mProxyService.setPacFile(script); diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java index 10d979863a96..0569b912bbfb 100644 --- a/services/java/com/android/server/SystemServer.java +++ b/services/java/com/android/server/SystemServer.java @@ -56,6 +56,7 @@ import android.os.SystemProperties; import android.os.Trace; import android.os.UserHandle; import android.os.storage.IStorageManager; +import android.provider.Settings; import android.sysprop.VoldProperties; import android.util.DisplayMetrics; import android.util.EventLog; @@ -966,6 +967,18 @@ public final class SystemServer { Slog.e("System", "************ Failure starting core service", e); } + // Before things start rolling, be sure we have decided whether + // we are in safe mode. + final boolean safeMode = wm.detectSafeMode(); + if (safeMode) { + // If yes, immediately turn on the global setting for airplane mode. + // Note that this does not send broadcasts at this stage because + // subsystems are not yet up. We will send broadcasts later to ensure + // all listeners have the chance to react with special handling. + Settings.Global.putInt(context.getContentResolver(), + Settings.Global.AIRPLANE_MODE_ON, 1); + } + StatusBarManagerService statusBar = null; INotificationManager notification = null; LocationManagerService location = null; @@ -1672,9 +1685,6 @@ public final class SystemServer { mSystemServiceManager.startService(StatsCompanionService.Lifecycle.class); traceEnd(); - // Before things start rolling, be sure we have decided whether - // we are in safe mode. - final boolean safeMode = wm.detectSafeMode(); if (safeMode) { traceBeginAndSlog("EnterSafeModeAndDisableJitCompilation"); mActivityManagerService.enterSafeMode(); @@ -1862,6 +1872,20 @@ public final class SystemServer { reportWtf("starting System UI", e); } traceEnd(); + // Enable airplane mode in safe mode. setAirplaneMode() cannot be called + // earlier as it sends broadcasts to other services. + // TODO: This may actually be too late if radio firmware already started leaking + // RF before the respective services start. However, fixing this requires changes + // to radio firmware and interfaces. + if (safeMode) { + traceBeginAndSlog("EnableAirplaneModeInSafeMode"); + try { + connectivityF.setAirplaneMode(true); + } catch (Throwable e) { + reportWtf("enabling Airplane Mode during Safe Mode bootup", e); + } + traceEnd(); + } traceBeginAndSlog("MakeNetworkManagementServiceReady"); try { if (networkManagementF != null) networkManagementF.systemReady(); diff --git a/services/net/java/android/net/shared/LinkPropertiesParcelableUtil.java b/services/net/java/android/net/shared/LinkPropertiesParcelableUtil.java new file mode 100644 index 000000000000..5b77f543c62b --- /dev/null +++ b/services/net/java/android/net/shared/LinkPropertiesParcelableUtil.java @@ -0,0 +1,222 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net.shared; + +import static android.net.shared.ParcelableUtil.fromParcelableArray; +import static android.net.shared.ParcelableUtil.toParcelableArray; + +import android.annotation.Nullable; +import android.net.InetAddresses; +import android.net.IpPrefix; +import android.net.IpPrefixParcelable; +import android.net.LinkAddress; +import android.net.LinkAddressParcelable; +import android.net.LinkProperties; +import android.net.LinkPropertiesParcelable; +import android.net.ProxyInfo; +import android.net.ProxyInfoParcelable; +import android.net.RouteInfo; +import android.net.RouteInfoParcelable; +import android.net.Uri; + +import java.net.InetAddress; +import java.util.Arrays; + +/** + * Collection of utility methods to convert to and from stable AIDL parcelables for LinkProperties + * and its attributes. + * @hide + */ +public final class LinkPropertiesParcelableUtil { + + /** + * Convert a ProxyInfo to a ProxyInfoParcelable + */ + public static ProxyInfoParcelable toStableParcelable(@Nullable ProxyInfo proxyInfo) { + if (proxyInfo == null) { + return null; + } + final ProxyInfoParcelable parcel = new ProxyInfoParcelable(); + parcel.host = proxyInfo.getHost(); + parcel.port = proxyInfo.getPort(); + parcel.exclusionList = proxyInfo.getExclusionList(); + parcel.pacFileUrl = proxyInfo.getPacFileUrl().toString(); + return parcel; + } + + /** + * Convert a ProxyInfoParcelable to a ProxyInfo + */ + public static ProxyInfo fromStableParcelable(@Nullable ProxyInfoParcelable parcel) { + if (parcel == null) { + return null; + } + if (Uri.EMPTY.toString().equals(parcel.pacFileUrl)) { + return ProxyInfo.buildDirectProxy( + parcel.host, parcel.port, Arrays.asList(parcel.exclusionList)); + } else { + return ProxyInfo.buildPacProxy(Uri.parse(parcel.pacFileUrl)); + } + } + + /** + * Convert an IpPrefixParcelable to an IpPrefix + */ + public static IpPrefixParcelable toStableParcelable(@Nullable IpPrefix ipPrefix) { + if (ipPrefix == null) { + return null; + } + final IpPrefixParcelable parcel = new IpPrefixParcelable(); + parcel.address = ipPrefix.getAddress().getHostAddress(); + parcel.prefixLength = ipPrefix.getPrefixLength(); + return parcel; + } + + /** + * Convert an IpPrefix to an IpPrefixParcelable + */ + public static IpPrefix fromStableParcelable(@Nullable IpPrefixParcelable parcel) { + if (parcel == null) { + return null; + } + return new IpPrefix(InetAddresses.parseNumericAddress(parcel.address), parcel.prefixLength); + } + + /** + * Convert a RouteInfoParcelable to a RouteInfo + */ + public static RouteInfoParcelable toStableParcelable(@Nullable RouteInfo routeInfo) { + if (routeInfo == null) { + return null; + } + final RouteInfoParcelable parcel = new RouteInfoParcelable(); + parcel.destination = toStableParcelable(routeInfo.getDestination()); + parcel.gatewayAddr = routeInfo.getGateway().getHostAddress(); + parcel.ifaceName = routeInfo.getInterface(); + parcel.type = routeInfo.getType(); + return parcel; + } + + /** + * Convert a RouteInfo to a RouteInfoParcelable + */ + public static RouteInfo fromStableParcelable(@Nullable RouteInfoParcelable parcel) { + if (parcel == null) { + return null; + } + final IpPrefix destination = fromStableParcelable(parcel.destination); + return new RouteInfo( + destination, InetAddresses.parseNumericAddress(parcel.gatewayAddr), + parcel.ifaceName, parcel.type); + } + + /** + * Convert a LinkAddressParcelable to a LinkAddress + */ + public static LinkAddressParcelable toStableParcelable(@Nullable LinkAddress la) { + if (la == null) { + return null; + } + final LinkAddressParcelable parcel = new LinkAddressParcelable(); + parcel.address = la.getAddress().getHostAddress(); + parcel.prefixLength = la.getPrefixLength(); + parcel.flags = la.getFlags(); + parcel.scope = la.getScope(); + return parcel; + } + + /** + * Convert a LinkAddress to a LinkAddressParcelable + */ + public static LinkAddress fromStableParcelable(@Nullable LinkAddressParcelable parcel) { + if (parcel == null) { + return null; + } + return new LinkAddress( + InetAddresses.parseNumericAddress(parcel.address), + parcel.prefixLength, + parcel.flags, + parcel.scope); + } + + /** + * Convert a LinkProperties to a LinkPropertiesParcelable + */ + public static LinkPropertiesParcelable toStableParcelable(@Nullable LinkProperties lp) { + if (lp == null) { + return null; + } + final LinkPropertiesParcelable parcel = new LinkPropertiesParcelable(); + parcel.ifaceName = lp.getInterfaceName(); + parcel.linkAddresses = toParcelableArray( + lp.getLinkAddresses(), + LinkPropertiesParcelableUtil::toStableParcelable, + LinkAddressParcelable.class); + parcel.dnses = toParcelableArray( + lp.getDnsServers(), InetAddress::getHostAddress, String.class); + parcel.pcscfs = toParcelableArray( + lp.getPcscfServers(), InetAddress::getHostAddress, String.class); + parcel.validatedPrivateDnses = toParcelableArray( + lp.getValidatedPrivateDnsServers(), InetAddress::getHostAddress, String.class); + parcel.usePrivateDns = lp.isPrivateDnsActive(); + parcel.privateDnsServerName = lp.getPrivateDnsServerName(); + parcel.domains = lp.getDomains(); + parcel.routes = toParcelableArray( + lp.getRoutes(), LinkPropertiesParcelableUtil::toStableParcelable, + RouteInfoParcelable.class); + parcel.httpProxy = toStableParcelable(lp.getHttpProxy()); + parcel.mtu = lp.getMtu(); + parcel.tcpBufferSizes = lp.getTcpBufferSizes(); + parcel.nat64Prefix = toStableParcelable(lp.getNat64Prefix()); + parcel.stackedLinks = toParcelableArray( + lp.getStackedLinks(), LinkPropertiesParcelableUtil::toStableParcelable, + LinkPropertiesParcelable.class); + return parcel; + } + + /** + * Convert a LinkPropertiesParcelable to a LinkProperties + */ + public static LinkProperties fromStableParcelable(@Nullable LinkPropertiesParcelable parcel) { + if (parcel == null) { + return null; + } + final LinkProperties lp = new LinkProperties(); + lp.setInterfaceName(parcel.ifaceName); + lp.setLinkAddresses(fromParcelableArray(parcel.linkAddresses, + LinkPropertiesParcelableUtil::fromStableParcelable)); + lp.setDnsServers(fromParcelableArray(parcel.dnses, InetAddresses::parseNumericAddress)); + lp.setPcscfServers(fromParcelableArray(parcel.pcscfs, InetAddresses::parseNumericAddress)); + lp.setValidatedPrivateDnsServers( + fromParcelableArray(parcel.validatedPrivateDnses, + InetAddresses::parseNumericAddress)); + lp.setUsePrivateDns(parcel.usePrivateDns); + lp.setPrivateDnsServerName(parcel.privateDnsServerName); + lp.setDomains(parcel.domains); + for (RouteInfoParcelable route : parcel.routes) { + lp.addRoute(fromStableParcelable(route)); + } + lp.setHttpProxy(fromStableParcelable(parcel.httpProxy)); + lp.setMtu(parcel.mtu); + lp.setTcpBufferSizes(parcel.tcpBufferSizes); + lp.setNat64Prefix(fromStableParcelable(parcel.nat64Prefix)); + for (LinkPropertiesParcelable stackedLink : parcel.stackedLinks) { + lp.addStackedLink(fromStableParcelable(stackedLink)); + } + return lp; + } +} diff --git a/services/net/java/android/net/shared/ParcelableUtil.java b/services/net/java/android/net/shared/ParcelableUtil.java new file mode 100644 index 000000000000..a18976c9eee6 --- /dev/null +++ b/services/net/java/android/net/shared/ParcelableUtil.java @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net.shared; + +import android.annotation.NonNull; + +import java.lang.reflect.Array; +import java.util.ArrayList; +import java.util.List; +import java.util.function.Function; + +/** + * Utility methods to help convert to/from stable parcelables. + * @hide + */ +public final class ParcelableUtil { + // Below methods could be implemented easily with streams, but streams are frowned upon in + // frameworks code. + + /** + * Convert a list of BaseType items to an array of ParcelableType items using the specified + * converter function. + */ + public static <ParcelableType, BaseType> ParcelableType[] toParcelableArray( + @NonNull List<BaseType> base, + @NonNull Function<BaseType, ParcelableType> conv, + @NonNull Class<ParcelableType> parcelClass) { + final ParcelableType[] out = (ParcelableType[]) Array.newInstance(parcelClass, base.size()); + int i = 0; + for (BaseType b : base) { + out[i] = conv.apply(b); + i++; + } + return out; + } + + /** + * Convert an array of ParcelableType items to a list of BaseType items using the specified + * converter function. + */ + public static <ParcelableType, BaseType> ArrayList<BaseType> fromParcelableArray( + @NonNull ParcelableType[] parceled, @NonNull Function<ParcelableType, BaseType> conv) { + final ArrayList<BaseType> out = new ArrayList<>(parceled.length); + for (ParcelableType t : parceled) { + out.add(conv.apply(t)); + } + return out; + } +} diff --git a/telecomm/java/android/telecom/CallRedirectionService.java b/telecomm/java/android/telecom/CallRedirectionService.java index b906d0bf3136..329911776993 100644 --- a/telecomm/java/android/telecom/CallRedirectionService.java +++ b/telecomm/java/android/telecom/CallRedirectionService.java @@ -16,6 +16,7 @@ package android.telecom; +import android.annotation.NonNull; import android.annotation.SdkConstant; import android.app.Service; import android.content.Intent; @@ -27,8 +28,8 @@ import android.os.Message; import android.os.RemoteException; import com.android.internal.os.SomeArgs; -import com.android.internal.telecom.ICallRedirectionService; import com.android.internal.telecom.ICallRedirectionAdapter; +import com.android.internal.telecom.ICallRedirectionService; /** * This service can be implemented to interact between Telecom and its implementor @@ -62,22 +63,35 @@ public abstract class CallRedirectionService extends Service { /** * Telecom calls this method to inform the implemented {@link CallRedirectionService} of - * a new outgoing call which is being placed. + * a new outgoing call which is being placed. Telecom does not request to redirect emergency + * calls and does not request to redirect calls with gateway information. + * + * <p>Telecom will cancel the call if Telecom does not receive a response in 5 seconds from + * the implemented {@link CallRedirectionService} set by users. * - * The implemented {@link CallRedirectionService} can call {@link #placeCallUnmodified()}, - * {@link #redirectCall(Uri, PhoneAccountHandle)}, and {@link #cancelCall()} only from here. + * <p>The implemented {@link CallRedirectionService} can call {@link #placeCallUnmodified()}, + * {@link #redirectCall(Uri, PhoneAccountHandle, boolean)}, and {@link #cancelCall()} only + * from here. * - * @param handle the phone number dialed by the user - * @param targetPhoneAccount the {@link PhoneAccountHandle} on which the call will be placed. + * @param handle the phone number dialed by the user, represented in E.164 format if possible + * @param initialPhoneAccount the {@link PhoneAccountHandle} on which the call will be placed. + * @param allowInteractiveResponse a boolean to tell if the implemented + * {@link CallRedirectionService} should allow interactive + * responses with users. Will be {@code false} if, for example + * the device is in car mode and the user would not be able to + * interact with their device. */ - public abstract void onPlaceCall(Uri handle, PhoneAccountHandle targetPhoneAccount); + public abstract void onPlaceCall(@NonNull Uri handle, + @NonNull PhoneAccountHandle initialPhoneAccount, + boolean allowInteractiveResponse); /** * The implemented {@link CallRedirectionService} calls this method to response a request - * received via {@link #onPlaceCall(Uri, PhoneAccountHandle)} to inform Telecom that no changes - * are required to the outgoing call, and that the call should be placed as-is. + * received via {@link #onPlaceCall(Uri, PhoneAccountHandle, boolean)} to inform Telecom that + * no changes are required to the outgoing call, and that the call should be placed as-is. * - * This can only be called from implemented {@link #onPlaceCall(Uri, PhoneAccountHandle)}. + * <p>This can only be called from implemented + * {@link #onPlaceCall(Uri, PhoneAccountHandle, boolean)}. * */ public final void placeCallUnmodified() { @@ -89,29 +103,39 @@ public abstract class CallRedirectionService extends Service { /** * The implemented {@link CallRedirectionService} calls this method to response a request - * received via {@link #onPlaceCall(Uri, PhoneAccountHandle)} to inform Telecom that changes - * are required to the phone number or/and {@link PhoneAccountHandle} for the outgoing call. + * received via {@link #onPlaceCall(Uri, PhoneAccountHandle, boolean)} to inform Telecom that + * changes are required to the phone number or/and {@link PhoneAccountHandle} for the outgoing + * call. Telecom will cancel the call if the implemented {@link CallRedirectionService} + * replies Telecom a handle for an emergency number. * - * This can only be called from implemented {@link #onPlaceCall(Uri, PhoneAccountHandle)}. + * <p>This can only be called from implemented + * {@link #onPlaceCall(Uri, PhoneAccountHandle, boolean)}. * * @param handle the new phone number to dial * @param targetPhoneAccount the {@link PhoneAccountHandle} to use when placing the call. * If {@code null}, no change will be made to the * {@link PhoneAccountHandle} used to place the call. + * @param confirmFirst Telecom will ask users to confirm the redirection via a yes/no dialog + * if the confirmFirst is true, and if the redirection request of this + * response was sent with a true flag of allowInteractiveResponse via + * {@link #onPlaceCall(Uri, PhoneAccountHandle, boolean)} */ - public final void redirectCall(Uri handle, PhoneAccountHandle targetPhoneAccount) { + public final void redirectCall(@NonNull Uri handle, + @NonNull PhoneAccountHandle targetPhoneAccount, + boolean confirmFirst) { try { - mCallRedirectionAdapter.redirectCall(handle, targetPhoneAccount); + mCallRedirectionAdapter.redirectCall(handle, targetPhoneAccount, confirmFirst); } catch (RemoteException e) { } } /** * The implemented {@link CallRedirectionService} calls this method to response a request - * received via {@link #onPlaceCall(Uri, PhoneAccountHandle)} to inform Telecom that an outgoing - * call should be canceled entirely. + * received via {@link #onPlaceCall(Uri, PhoneAccountHandle, boolean)} to inform Telecom that + * an outgoing call should be canceled entirely. * - * This can only be called from implemented {@link #onPlaceCall(Uri, PhoneAccountHandle)}. + * <p>This can only be called from implemented + * {@link #onPlaceCall(Uri, PhoneAccountHandle, boolean)}. * */ public final void cancelCall() { @@ -137,7 +161,8 @@ public abstract class CallRedirectionService extends Service { SomeArgs args = (SomeArgs) msg.obj; try { mCallRedirectionAdapter = (ICallRedirectionAdapter) args.arg1; - onPlaceCall((Uri) args.arg2, (PhoneAccountHandle) args.arg3); + onPlaceCall((Uri) args.arg2, (PhoneAccountHandle) args.arg3, + (boolean) args.arg4); } finally { args.recycle(); } @@ -152,15 +177,20 @@ public abstract class CallRedirectionService extends Service { * Telecom calls this method to inform the CallRedirectionService of a new outgoing call * which is about to be placed. * @param handle the phone number dialed by the user - * @param targetPhoneAccount the URI of the number the user dialed + * @param initialPhoneAccount the URI of the number the user dialed + * @param allowInteractiveResponse a boolean to tell if the implemented + * {@link CallRedirectionService} should allow interactive + * responses with users. */ @Override - public void placeCall(ICallRedirectionAdapter adapter, Uri handle, - PhoneAccountHandle targetPhoneAccount) { + public void placeCall(@NonNull ICallRedirectionAdapter adapter, @NonNull Uri handle, + @NonNull PhoneAccountHandle initialPhoneAccount, + boolean allowInteractiveResponse) { SomeArgs args = SomeArgs.obtain(); args.arg1 = adapter; args.arg2 = handle; - args.arg3 = targetPhoneAccount; + args.arg3 = initialPhoneAccount; + args.arg4 = allowInteractiveResponse; mHandler.obtainMessage(MSG_PLACE_CALL, args).sendToTarget(); } } diff --git a/telecomm/java/com/android/internal/telecom/ICallRedirectionAdapter.aidl b/telecomm/java/com/android/internal/telecom/ICallRedirectionAdapter.aidl index 46bf983f52a2..0a42a3f4f02e 100644 --- a/telecomm/java/com/android/internal/telecom/ICallRedirectionAdapter.aidl +++ b/telecomm/java/com/android/internal/telecom/ICallRedirectionAdapter.aidl @@ -31,5 +31,6 @@ oneway interface ICallRedirectionAdapter { void placeCallUnmodified(); - void redirectCall(in Uri handle, in PhoneAccountHandle targetPhoneAccount); + void redirectCall(in Uri handle, in PhoneAccountHandle targetPhoneAccount, + boolean confirmFirst); } diff --git a/telecomm/java/com/android/internal/telecom/ICallRedirectionService.aidl b/telecomm/java/com/android/internal/telecom/ICallRedirectionService.aidl index d8d360beb64d..c1bc44007b0b 100644 --- a/telecomm/java/com/android/internal/telecom/ICallRedirectionService.aidl +++ b/telecomm/java/com/android/internal/telecom/ICallRedirectionService.aidl @@ -30,5 +30,5 @@ import com.android.internal.telecom.ICallRedirectionAdapter; */ oneway interface ICallRedirectionService { void placeCall(in ICallRedirectionAdapter adapter, in Uri handle, - in PhoneAccountHandle targetPhoneAccount); + in PhoneAccountHandle initialPhoneAccount, boolean allowInteractiveResponse); } diff --git a/telephony/java/android/telephony/CellConfigLte.java b/telephony/java/android/telephony/CellConfigLte.java index 35769f04c5ae..eafbfbc5076d 100644 --- a/telephony/java/android/telephony/CellConfigLte.java +++ b/telephony/java/android/telephony/CellConfigLte.java @@ -34,6 +34,11 @@ public class CellConfigLte implements Parcelable { } /** @hide */ + public CellConfigLte(android.hardware.radio.V1_4.CellConfigLte cellConfig) { + mIsEndcAvailable = cellConfig.isEndcAvailable; + } + + /** @hide */ public CellConfigLte(boolean isEndcAvailable) { mIsEndcAvailable = isEndcAvailable; } diff --git a/telephony/java/android/telephony/CellInfo.java b/telephony/java/android/telephony/CellInfo.java index b761bd7bf70c..8ce5c54c810e 100644 --- a/telephony/java/android/telephony/CellInfo.java +++ b/telephony/java/android/telephony/CellInfo.java @@ -19,8 +19,10 @@ package android.telephony; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.UnsupportedAppUsage; +import android.hardware.radio.V1_4.CellInfo.Info; import android.os.Parcel; import android.os.Parcelable; +import android.os.SystemClock; import com.android.internal.annotations.VisibleForTesting; @@ -318,6 +320,13 @@ public abstract class CellInfo implements Parcelable { } /** @hide */ + protected CellInfo(android.hardware.radio.V1_4.CellInfo ci) { + this.mRegistered = ci.isRegistered; + this.mTimeStamp = SystemClock.elapsedRealtimeNanos(); + this.mCellConnectionStatus = ci.connectionStatus; + } + + /** @hide */ public static CellInfo create(android.hardware.radio.V1_0.CellInfo ci) { if (ci == null) return null; switch(ci.cellInfoType) { @@ -342,4 +351,17 @@ public abstract class CellInfo implements Parcelable { default: return null; } } + + /** @hide */ + public static CellInfo create(android.hardware.radio.V1_4.CellInfo ci) { + if (ci == null) return null; + switch (ci.info.getDiscriminator()) { + case Info.hidl_discriminator.gsm: return new CellInfoGsm(ci); + case Info.hidl_discriminator.cdma: return new CellInfoCdma(ci); + case Info.hidl_discriminator.lte: return new CellInfoLte(ci); + case Info.hidl_discriminator.wcdma: return new CellInfoWcdma(ci); + case Info.hidl_discriminator.tdscdma: return new CellInfoTdscdma(ci); + default: return null; + } + } } diff --git a/telephony/java/android/telephony/CellInfoCdma.java b/telephony/java/android/telephony/CellInfoCdma.java index c9f07dab6bbd..4440108879f2 100644 --- a/telephony/java/android/telephony/CellInfoCdma.java +++ b/telephony/java/android/telephony/CellInfoCdma.java @@ -67,6 +67,15 @@ public final class CellInfoCdma extends CellInfo implements Parcelable { new CellSignalStrengthCdma(cic.signalStrengthCdma, cic.signalStrengthEvdo); } + /** @hide */ + public CellInfoCdma(android.hardware.radio.V1_4.CellInfo ci) { + super(ci); + final android.hardware.radio.V1_2.CellInfoCdma cic = ci.info.cdma(); + mCellIdentityCdma = new CellIdentityCdma(cic.cellIdentityCdma); + mCellSignalStrengthCdma = + new CellSignalStrengthCdma(cic.signalStrengthCdma, cic.signalStrengthEvdo); + } + @Override public CellIdentityCdma getCellIdentity() { return mCellIdentityCdma; diff --git a/telephony/java/android/telephony/CellInfoGsm.java b/telephony/java/android/telephony/CellInfoGsm.java index ad16dfae7295..248adfcb2d90 100644 --- a/telephony/java/android/telephony/CellInfoGsm.java +++ b/telephony/java/android/telephony/CellInfoGsm.java @@ -63,6 +63,14 @@ public final class CellInfoGsm extends CellInfo implements Parcelable { mCellSignalStrengthGsm = new CellSignalStrengthGsm(cig.signalStrengthGsm); } + /** @hide */ + public CellInfoGsm(android.hardware.radio.V1_4.CellInfo ci) { + super(ci); + final android.hardware.radio.V1_2.CellInfoGsm cig = ci.info.gsm(); + mCellIdentityGsm = new CellIdentityGsm(cig.cellIdentityGsm); + mCellSignalStrengthGsm = new CellSignalStrengthGsm(cig.signalStrengthGsm); + } + @Override public CellIdentityGsm getCellIdentity() { return mCellIdentityGsm; diff --git a/telephony/java/android/telephony/CellInfoLte.java b/telephony/java/android/telephony/CellInfoLte.java index 75938317bf44..8e8ce8a1f5de 100644 --- a/telephony/java/android/telephony/CellInfoLte.java +++ b/telephony/java/android/telephony/CellInfoLte.java @@ -70,6 +70,15 @@ public final class CellInfoLte extends CellInfo implements Parcelable { mCellConfig = new CellConfigLte(); } + /** @hide */ + public CellInfoLte(android.hardware.radio.V1_4.CellInfo ci) { + super(ci); + final android.hardware.radio.V1_4.CellInfoLte cil = ci.info.lte(); + mCellIdentityLte = new CellIdentityLte(cil.base.cellIdentityLte); + mCellSignalStrengthLte = new CellSignalStrengthLte(cil.base.signalStrengthLte); + mCellConfig = new CellConfigLte(cil.cellConfig); + } + @Override public CellIdentityLte getCellIdentity() { if (DBG) log("getCellIdentity: " + mCellIdentityLte); diff --git a/telephony/java/android/telephony/CellInfoTdscdma.java b/telephony/java/android/telephony/CellInfoTdscdma.java index a8c49b7bf68e..2ab38fb77a90 100644 --- a/telephony/java/android/telephony/CellInfoTdscdma.java +++ b/telephony/java/android/telephony/CellInfoTdscdma.java @@ -64,6 +64,14 @@ public final class CellInfoTdscdma extends CellInfo implements Parcelable { mCellSignalStrengthTdscdma = new CellSignalStrengthTdscdma(cit.signalStrengthTdscdma); } + /** @hide */ + public CellInfoTdscdma(android.hardware.radio.V1_4.CellInfo ci) { + super(ci); + final android.hardware.radio.V1_2.CellInfoTdscdma cit = ci.info.tdscdma(); + mCellIdentityTdscdma = new CellIdentityTdscdma(cit.cellIdentityTdscdma); + mCellSignalStrengthTdscdma = new CellSignalStrengthTdscdma(cit.signalStrengthTdscdma); + } + @Override public CellIdentityTdscdma getCellIdentity() { return mCellIdentityTdscdma; } diff --git a/telephony/java/android/telephony/CellInfoWcdma.java b/telephony/java/android/telephony/CellInfoWcdma.java index a427e80fd65c..65e047077639 100644 --- a/telephony/java/android/telephony/CellInfoWcdma.java +++ b/telephony/java/android/telephony/CellInfoWcdma.java @@ -63,6 +63,14 @@ public final class CellInfoWcdma extends CellInfo implements Parcelable { mCellSignalStrengthWcdma = new CellSignalStrengthWcdma(ciw.signalStrengthWcdma); } + /** @hide */ + public CellInfoWcdma(android.hardware.radio.V1_4.CellInfo ci) { + super(ci); + final android.hardware.radio.V1_2.CellInfoWcdma ciw = ci.info.wcdma(); + mCellIdentityWcdma = new CellIdentityWcdma(ciw.cellIdentityWcdma); + mCellSignalStrengthWcdma = new CellSignalStrengthWcdma(ciw.signalStrengthWcdma); + } + @Override public CellIdentityWcdma getCellIdentity() { return mCellIdentityWcdma; diff --git a/telephony/java/android/telephony/PhoneStateListener.java b/telephony/java/android/telephony/PhoneStateListener.java index c81670139eae..9fee5932dadc 100644 --- a/telephony/java/android/telephony/PhoneStateListener.java +++ b/telephony/java/android/telephony/PhoneStateListener.java @@ -805,9 +805,11 @@ public class PhoneStateListener { PhoneStateListener psl = mPhoneStateListenerWeakRef.get(); if (psl == null) return; - Binder.withCleanCallingIdentity( - () -> mExecutor.execute( - () -> psl.onDataConnectionStateChanged(state, networkType))); + Binder.withCleanCallingIdentity(() -> mExecutor.execute( + () -> { + psl.onDataConnectionStateChanged(state, networkType); + psl.onDataConnectionStateChanged(state); + })); } public void onDataActivity(int direction) { diff --git a/telephony/java/android/telephony/SignalStrength.java b/telephony/java/android/telephony/SignalStrength.java index e77042d1930f..ad3ca6d129c9 100644 --- a/telephony/java/android/telephony/SignalStrength.java +++ b/telephony/java/android/telephony/SignalStrength.java @@ -86,11 +86,6 @@ public class SignalStrength implements Parcelable { CellSignalStrengthTdscdma mTdscdma; CellSignalStrengthLte mLte; - /** Parameters from the framework */ - @UnsupportedAppUsage - private int mLteRsrpBoost; // offset to be reduced from the rsrp threshold while calculating - // signal strength level - /** * Create a new SignalStrength from a intent notifier Bundle * @@ -140,7 +135,6 @@ public class SignalStrength implements Parcelable { mWcdma = wcdma; mTdscdma = tdscdma; mLte = lte; - mLteRsrpBoost = 0; } /** @@ -211,7 +205,6 @@ public class SignalStrength implements Parcelable { /** @hide */ public void updateLevel(PersistableBundle cc, ServiceState ss) { - mLteRsrpBoost = ss.getLteEarfcnRsrpBoost(); mCdma.updateLevel(cc, ss); mGsm.updateLevel(cc, ss); mWcdma.updateLevel(cc, ss); @@ -241,7 +234,6 @@ public class SignalStrength implements Parcelable { mWcdma = new CellSignalStrengthWcdma(s.mWcdma); mTdscdma = new CellSignalStrengthTdscdma(s.mTdscdma); mLte = new CellSignalStrengthLte(s.mLte); - mLteRsrpBoost = s.mLteRsrpBoost; } /** @@ -258,7 +250,6 @@ public class SignalStrength implements Parcelable { mWcdma = in.readParcelable(CellSignalStrengthWcdma.class.getClassLoader()); mTdscdma = in.readParcelable(CellSignalStrengthTdscdma.class.getClassLoader()); mLte = in.readParcelable(CellSignalStrengthLte.class.getClassLoader()); - mLteRsrpBoost = in.readInt(); } /** @@ -270,8 +261,6 @@ public class SignalStrength implements Parcelable { out.writeParcelable(mWcdma, flags); out.writeParcelable(mTdscdma, flags); out.writeParcelable(mLte, flags); - - out.writeInt(mLteRsrpBoost); } /** @@ -384,11 +373,6 @@ public class SignalStrength implements Parcelable { return mLte.getCqi(); } - /** @hide */ - public int getLteRsrpBoost() { - return mLteRsrpBoost; - } - /** * Retrieve an abstract level value for the overall signal strength. * @@ -616,7 +600,7 @@ public class SignalStrength implements Parcelable { */ @Override public int hashCode() { - return Objects.hash(mCdma, mGsm, mWcdma, mTdscdma, mLte, mLteRsrpBoost); + return Objects.hash(mCdma, mGsm, mWcdma, mTdscdma, mLte); } /** @@ -632,8 +616,7 @@ public class SignalStrength implements Parcelable { && mGsm.equals(s.mGsm) && mWcdma.equals(s.mWcdma) && mTdscdma.equals(s.mTdscdma) - && mLte.equals(s.mLte) - && mLteRsrpBoost == s.mLteRsrpBoost; + && mLte.equals(s.mLte); } /** @@ -647,7 +630,6 @@ public class SignalStrength implements Parcelable { .append(",mWcdma=").append(mWcdma) .append(",mTdscdma=").append(mTdscdma) .append(",mLte=").append(mLte) - .append(",mLteRsrpBoost=").append(mLteRsrpBoost) .append(",primary=").append(getPrimary().getClass().getSimpleName()) .append("}") .toString(); @@ -666,8 +648,6 @@ public class SignalStrength implements Parcelable { mWcdma = m.getParcelable("Wcdma"); mTdscdma = m.getParcelable("Tdscdma"); mLte = m.getParcelable("Lte"); - - mLteRsrpBoost = m.getInt("LteRsrpBoost"); } /** @@ -683,8 +663,6 @@ public class SignalStrength implements Parcelable { m.putParcelable("Wcdma", mWcdma); m.putParcelable("Tdscdma", mTdscdma); m.putParcelable("Lte", mLte); - - m.putInt("LteRsrpBoost", mLteRsrpBoost); } /** diff --git a/telephony/java/android/telephony/data/ApnSetting.java b/telephony/java/android/telephony/data/ApnSetting.java index 200b5403eea9..8d148c36f3e7 100644 --- a/telephony/java/android/telephony/data/ApnSetting.java +++ b/telephony/java/android/telephony/data/ApnSetting.java @@ -81,7 +81,7 @@ public class ApnSetting implements Parcelable { */ public static final int TYPE_ALL = ApnTypes.ALL; /** APN type for default data traffic. */ - public static final int TYPE_DEFAULT = ApnTypes.DEFAULT; + public static final int TYPE_DEFAULT = ApnTypes.DEFAULT | ApnTypes.HIPRI; /** APN type for MMS traffic. */ public static final int TYPE_MMS = ApnTypes.MMS; /** APN type for SUPL assisted GPS. */ @@ -1019,7 +1019,7 @@ public class ApnSetting implements Parcelable { return false; } // DEFAULT can handle HIPRI. - if (hasApnType(type) || (type == TYPE_HIPRI && hasApnType(TYPE_DEFAULT))) { + if (hasApnType(type)) { return true; } return false; diff --git a/telephony/java/android/telephony/emergency/EmergencyNumber.java b/telephony/java/android/telephony/emergency/EmergencyNumber.java index fe062d5d974a..a94b163ffd75 100644 --- a/telephony/java/android/telephony/emergency/EmergencyNumber.java +++ b/telephony/java/android/telephony/emergency/EmergencyNumber.java @@ -29,6 +29,7 @@ import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; import java.util.HashSet; import java.util.List; +import java.util.Objects; import java.util.Set; /** @@ -198,21 +199,53 @@ public final class EmergencyNumber implements Parcelable, Comparable<EmergencyNu EMERGENCY_NUMBER_SOURCE_SET.add(EMERGENCY_NUMBER_SOURCE_DEFAULT); } + /** + * Indicated the framework does not know whether an emergency call should be placed using + * emergency or normal call routing. This means the underlying radio or IMS implementation is + * free to determine for itself how to route the call. + */ + public static final int EMERGENCY_CALL_ROUTING_UNKNOWN = 0; + /** + * Indicates the radio or IMS implementation must handle the call through emergency routing. + */ + public static final int EMERGENCY_CALL_ROUTING_EMERGENCY = 1; + /** + * Indicates the radio or IMS implementation must handle the call through normal call routing. + */ + public static final int EMERGENCY_CALL_ROUTING_NORMAL = 2; + + /** + * The routing to tell how to handle the call for the corresponding emergency number. + * + * @hide + */ + @IntDef(flag = false, prefix = { "EMERGENCY_CALL_ROUTING_" }, value = { + EMERGENCY_CALL_ROUTING_UNKNOWN, + EMERGENCY_CALL_ROUTING_EMERGENCY, + EMERGENCY_CALL_ROUTING_NORMAL + }) + @Retention(RetentionPolicy.SOURCE) + public @interface EmergencyCallRouting {} + + private final String mNumber; private final String mCountryIso; private final String mMnc; private final int mEmergencyServiceCategoryBitmask; private final int mEmergencyNumberSourceBitmask; + private final int mEmergencyCallRouting; /** @hide */ - public EmergencyNumber(@NonNull String number, @NonNull String countryIso, - @NonNull String mnc, int emergencyServiceCategories, - int emergencyNumberSources) { + public EmergencyNumber(@NonNull String number, @NonNull String countryIso, @NonNull String mnc, + @EmergencyServiceCategories int emergencyServiceCategories, + @EmergencyNumberSources int emergencyNumberSources, + @EmergencyCallRouting int emergencyCallRouting) { this.mNumber = number; this.mCountryIso = countryIso; this.mMnc = mnc; this.mEmergencyServiceCategoryBitmask = emergencyServiceCategories; this.mEmergencyNumberSourceBitmask = emergencyNumberSources; + this.mEmergencyCallRouting = emergencyCallRouting; } /** @hide */ @@ -222,8 +255,33 @@ public final class EmergencyNumber implements Parcelable, Comparable<EmergencyNu mMnc = source.readString(); mEmergencyServiceCategoryBitmask = source.readInt(); mEmergencyNumberSourceBitmask = source.readInt(); + mEmergencyCallRouting = source.readInt(); + } + + @Override + /** @hide */ + public void writeToParcel(Parcel dest, int flags) { + dest.writeString(mNumber); + dest.writeString(mCountryIso); + dest.writeString(mMnc); + dest.writeInt(mEmergencyServiceCategoryBitmask); + dest.writeInt(mEmergencyNumberSourceBitmask); + dest.writeInt(mEmergencyCallRouting); } + public static final Parcelable.Creator<EmergencyNumber> CREATOR = + new Parcelable.Creator<EmergencyNumber>() { + @Override + public EmergencyNumber createFromParcel(Parcel in) { + return new EmergencyNumber(in); + } + + @Override + public EmergencyNumber[] newArray(int size) { + return new EmergencyNumber[size]; + } + }; + /** * Get the dialing number of the emergency number. * @@ -352,14 +410,17 @@ public final class EmergencyNumber implements Parcelable, Comparable<EmergencyNu return (mEmergencyNumberSourceBitmask & sources) == sources; } - @Override - /** @hide */ - public void writeToParcel(Parcel dest, int flags) { - dest.writeString(mNumber); - dest.writeString(mCountryIso); - dest.writeString(mMnc); - dest.writeInt(mEmergencyServiceCategoryBitmask); - dest.writeInt(mEmergencyNumberSourceBitmask); + /** + * Returns the emergency call routing information. + * + * <p>Some regions require some emergency numbers which are not routed using typical emergency + * call processing, but are instead placed as regular phone calls. The emergency call routing + * field provides information about how an emergency call will be routed when it is placed. + * + * @return the emergency call routing requirement + */ + public @EmergencyCallRouting int getEmergencyCallRouting() { + return mEmergencyCallRouting; } @Override @@ -373,7 +434,8 @@ public final class EmergencyNumber implements Parcelable, Comparable<EmergencyNu return "EmergencyNumber:" + "Number-" + mNumber + "|CountryIso-" + mCountryIso + "|Mnc-" + mMnc + "|ServiceCategories-" + Integer.toBinaryString(mEmergencyServiceCategoryBitmask) - + "|Sources-" + Integer.toBinaryString(mEmergencyNumberSourceBitmask); + + "|Sources-" + Integer.toBinaryString(mEmergencyNumberSourceBitmask) + + "|Routing-" + Integer.toBinaryString(mEmergencyCallRouting); } @Override @@ -381,7 +443,19 @@ public final class EmergencyNumber implements Parcelable, Comparable<EmergencyNu if (!EmergencyNumber.class.isInstance(o)) { return false; } - return (o == this || toString().equals(o.toString())); + EmergencyNumber other = (EmergencyNumber) o; + return mNumber.equals(other.mNumber) + && mCountryIso.equals(other.mCountryIso) + && mMnc.equals(other.mMnc) + && mEmergencyServiceCategoryBitmask == other.mEmergencyServiceCategoryBitmask + && mEmergencyNumberSourceBitmask == other.mEmergencyNumberSourceBitmask + && mEmergencyCallRouting == other.mEmergencyCallRouting; + } + + @Override + public int hashCode() { + return Objects.hash(mNumber, mCountryIso, mMnc, mEmergencyServiceCategoryBitmask, + mEmergencyNumberSourceBitmask, mEmergencyCallRouting); } /** @@ -462,12 +536,12 @@ public final class EmergencyNumber implements Parcelable, Comparable<EmergencyNu continue; } for (int j = i + 1; j < emergencyNumberList.size(); j++) { - if (isSameEmergencyNumber( + if (areSameEmergencyNumbers( emergencyNumberList.get(i), emergencyNumberList.get(j))) { Rlog.e(LOG_TAG, "Found unexpected duplicate numbers: " + emergencyNumberList.get(i) + " vs " + emergencyNumberList.get(j)); // Set the merged emergency number in the current position - emergencyNumberList.set(i, mergeNumbers( + emergencyNumberList.set(i, mergeSameEmergencyNumbers( emergencyNumberList.get(i), emergencyNumberList.get(j))); // Mark the emergency number has been merged mergedEmergencyNumber.add(emergencyNumberList.get(j)); @@ -486,8 +560,8 @@ public final class EmergencyNumber implements Parcelable, Comparable<EmergencyNu * Check if two emergency numbers are the same. * * A unique EmergencyNumber has a unique combination of ‘number’, ‘mcc’, 'mnc' and - * 'categories' fields. Multiple Emergency Number Sources should be merged into one bitfield - * for the same EmergencyNumber. + * 'categories', and 'routing' fields. Multiple Emergency Number Sources should be + * merged into one bitfield for the same EmergencyNumber. * * @param first first EmergencyNumber to compare * @param second second EmergencyNumber to compare @@ -495,8 +569,8 @@ public final class EmergencyNumber implements Parcelable, Comparable<EmergencyNu * * @hide */ - public static boolean isSameEmergencyNumber(@NonNull EmergencyNumber first, - @NonNull EmergencyNumber second) { + public static boolean areSameEmergencyNumbers(@NonNull EmergencyNumber first, + @NonNull EmergencyNumber second) { if (!first.getNumber().equals(second.getNumber())) { return false; } @@ -510,11 +584,15 @@ public final class EmergencyNumber implements Parcelable, Comparable<EmergencyNu != second.getEmergencyServiceCategoryBitmask()) { return false; } + if (first.getEmergencyCallRouting() != second.getEmergencyCallRouting()) { + return false; + } return true; } /** - * Get a merged EmergencyNumber for two numbers if they are the same. + * Get a merged EmergencyNumber from two same emergency numbers. Two emergency numbers are + * the same if {@link #areSameEmergencyNumbers} returns {@code true}. * * @param first first EmergencyNumber to compare * @param second second EmergencyNumber to compare @@ -522,27 +600,15 @@ public final class EmergencyNumber implements Parcelable, Comparable<EmergencyNu * * @hide */ - public static EmergencyNumber mergeNumbers(@NonNull EmergencyNumber first, - @NonNull EmergencyNumber second) { - if (isSameEmergencyNumber(first, second)) { + public static EmergencyNumber mergeSameEmergencyNumbers(@NonNull EmergencyNumber first, + @NonNull EmergencyNumber second) { + if (areSameEmergencyNumbers(first, second)) { return new EmergencyNumber(first.getNumber(), first.getCountryIso(), first.getMnc(), first.getEmergencyServiceCategoryBitmask(), first.getEmergencyNumberSourceBitmask() - | second.getEmergencyNumberSourceBitmask()); + | second.getEmergencyNumberSourceBitmask(), + first.getEmergencyCallRouting()); } return null; } - - public static final Parcelable.Creator<EmergencyNumber> CREATOR = - new Parcelable.Creator<EmergencyNumber>() { - @Override - public EmergencyNumber createFromParcel(Parcel in) { - return new EmergencyNumber(in); - } - - @Override - public EmergencyNumber[] newArray(int size) { - return new EmergencyNumber[size]; - } - }; } diff --git a/telephony/java/android/telephony/euicc/EuiccManager.java b/telephony/java/android/telephony/euicc/EuiccManager.java index 9164402c70d7..95dfffd30e72 100644 --- a/telephony/java/android/telephony/euicc/EuiccManager.java +++ b/telephony/java/android/telephony/euicc/EuiccManager.java @@ -30,6 +30,7 @@ import android.content.pm.PackageManager; import android.os.Bundle; import android.os.RemoteException; import android.os.ServiceManager; +import android.telephony.TelephonyManager; import com.android.internal.telephony.euicc.IEuiccController; @@ -40,7 +41,11 @@ import java.lang.annotation.RetentionPolicy; * EuiccManager is the application interface to eUICCs, or eSIMs/embedded SIMs. * * <p>You do not instantiate this class directly; instead, you retrieve an instance through - * {@link Context#getSystemService(String)} and {@link Context#EUICC_SERVICE}. + * {@link Context#getSystemService(String)} and {@link Context#EUICC_SERVICE}. This instance will be + * created using the default eUICC. + * + * <p>On a device with multiple eUICCs, you may want to create multiple EuiccManagers. To do this + * you can call {@link #createForCardId}. * * <p>See {@link #isEnabled} before attempting to use these APIs. */ @@ -248,10 +253,29 @@ public class EuiccManager { public static final int EUICC_OTA_STATUS_UNAVAILABLE = 5; private final Context mContext; + private final int mCardId; /** @hide */ public EuiccManager(Context context) { mContext = context; + TelephonyManager tm = (TelephonyManager) + context.getSystemService(Context.TELEPHONY_SERVICE); + mCardId = tm.getCardIdForDefaultEuicc(); + } + + /** @hide */ + private EuiccManager(Context context, int cardId) { + mContext = context; + mCardId = cardId; + } + + /** + * Create a new EuiccManager object pinned to the given card ID. + * + * @return an EuiccManager that uses the given card ID for all calls. + */ + public EuiccManager createForCardId(int cardId) { + return new EuiccManager(mContext, cardId); } /** @@ -274,7 +298,8 @@ public class EuiccManager { * Returns the EID identifying the eUICC hardware. * * <p>Requires that the calling app has carrier privileges on the active subscription on the - * eUICC. + * current eUICC. A calling app with carrier privileges for one eUICC may not necessarily have + * access to the EID of another eUICC. * * @return the EID. May be null if {@link #isEnabled()} is false or the eUICC is not ready. */ @@ -284,7 +309,7 @@ public class EuiccManager { return null; } try { - return getIEuiccController().getEid(); + return getIEuiccController().getEid(mCardId); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -307,7 +332,7 @@ public class EuiccManager { return EUICC_OTA_STATUS_UNAVAILABLE; } try { - return getIEuiccController().getOtaStatus(); + return getIEuiccController().getOtaStatus(mCardId); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -317,10 +342,10 @@ public class EuiccManager { * Attempt to download the given {@link DownloadableSubscription}. * * <p>Requires the {@code android.Manifest.permission#WRITE_EMBEDDED_SUBSCRIPTIONS} permission, - * or the calling app must be authorized to manage both the currently-active subscription and - * the subscription to be downloaded according to the subscription metadata. Without the former, - * an {@link #EMBEDDED_SUBSCRIPTION_RESULT_RESOLVABLE_ERROR} will be returned in the callback - * intent to prompt the user to accept the download. + * or the calling app must be authorized to manage both the currently-active subscription on the + * current eUICC and the subscription to be downloaded according to the subscription metadata. + * Without the former, an {@link #EMBEDDED_SUBSCRIPTION_RESULT_RESOLVABLE_ERROR} will be + * returned in the callback intent to prompt the user to accept the download. * * @param subscription the subscription to download. * @param switchAfterDownload if true, the profile will be activated upon successful download. @@ -334,7 +359,7 @@ public class EuiccManager { return; } try { - getIEuiccController().downloadSubscription(subscription, switchAfterDownload, + getIEuiccController().downloadSubscription(mCardId, subscription, switchAfterDownload, mContext.getOpPackageName(), null /* resolvedBundle */, callbackIntent); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); @@ -401,7 +426,7 @@ public class EuiccManager { return; } try { - getIEuiccController().continueOperation(resolutionIntent, resolutionExtras); + getIEuiccController().continueOperation(mCardId, resolutionIntent, resolutionExtras); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -433,8 +458,8 @@ public class EuiccManager { return; } try { - getIEuiccController().getDownloadableSubscriptionMetadata( - subscription, mContext.getOpPackageName(), callbackIntent); + getIEuiccController().getDownloadableSubscriptionMetadata(mCardId, subscription, + mContext.getOpPackageName(), callbackIntent); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -463,7 +488,7 @@ public class EuiccManager { return; } try { - getIEuiccController().getDefaultDownloadableSubscriptionList( + getIEuiccController().getDefaultDownloadableSubscriptionList(mCardId, mContext.getOpPackageName(), callbackIntent); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); @@ -482,7 +507,7 @@ public class EuiccManager { return null; } try { - return getIEuiccController().getEuiccInfo(); + return getIEuiccController().getEuiccInfo(mCardId); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -508,7 +533,7 @@ public class EuiccManager { return; } try { - getIEuiccController().deleteSubscription( + getIEuiccController().deleteSubscription(mCardId, subscriptionId, mContext.getOpPackageName(), callbackIntent); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); @@ -536,7 +561,7 @@ public class EuiccManager { return; } try { - getIEuiccController().switchToSubscription( + getIEuiccController().switchToSubscription(mCardId, subscriptionId, mContext.getOpPackageName(), callbackIntent); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); @@ -562,7 +587,7 @@ public class EuiccManager { return; } try { - getIEuiccController().updateSubscriptionNickname( + getIEuiccController().updateSubscriptionNickname(mCardId, subscriptionId, nickname, mContext.getOpPackageName(), callbackIntent); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); @@ -586,7 +611,7 @@ public class EuiccManager { return; } try { - getIEuiccController().eraseSubscriptions(callbackIntent); + getIEuiccController().eraseSubscriptions(mCardId, callbackIntent); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -616,7 +641,7 @@ public class EuiccManager { return; } try { - getIEuiccController().retainSubscriptionsForFactoryReset(callbackIntent); + getIEuiccController().retainSubscriptionsForFactoryReset(mCardId, callbackIntent); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } diff --git a/telephony/java/android/telephony/ims/ImsCallProfile.java b/telephony/java/android/telephony/ims/ImsCallProfile.java index cb6fcd7b62c2..9c8d078a579b 100644 --- a/telephony/java/android/telephony/ims/ImsCallProfile.java +++ b/telephony/java/android/telephony/ims/ImsCallProfile.java @@ -24,9 +24,11 @@ import android.os.Parcel; import android.os.Parcelable; import android.telecom.VideoProfile; import android.telephony.emergency.EmergencyNumber; +import android.telephony.emergency.EmergencyNumber.EmergencyCallRouting; import android.telephony.emergency.EmergencyNumber.EmergencyServiceCategories; import android.util.Log; +import com.android.internal.annotations.VisibleForTesting; import com.android.internal.telephony.PhoneConstants; import java.lang.annotation.Retention; @@ -321,6 +323,20 @@ public final class ImsCallProfile implements Parcelable { EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED; /** + * The emergency call routing, only valid if {@link #getServiceType} returns + * {@link #SERVICE_TYPE_EMERGENCY} + * + * If valid, the value is any of the following constants: + * <ol> + * <li>{@link EmergencyNumber#EMERGENCY_CALL_ROUTING_UNKNOWN} </li> + * <li>{@link EmergencyNumber#EMERGENCY_CALL_ROUTING_NORMAL} </li> + * <li>{@link EmergencyNumber#EMERGENCY_CALL_ROUTING_EMERGENCY} </li> + * </ol> + */ + private @EmergencyCallRouting int mEmergencyCallRouting = + EmergencyNumber.EMERGENCY_CALL_ROUTING_UNKNOWN; + + /** * Extras associated with this {@link ImsCallProfile}. * <p> * Valid data types include: @@ -503,10 +519,12 @@ public final class ImsCallProfile implements Parcelable { @Override public String toString() { - return "{ serviceType=" + mServiceType + - ", callType=" + mCallType + - ", restrictCause=" + mRestrictCause + - ", mediaProfile=" + mMediaProfile.toString() + " }"; + return "{ serviceType=" + mServiceType + + ", callType=" + mCallType + + ", restrictCause=" + mRestrictCause + + ", mediaProfile=" + mMediaProfile.toString() + + ", emergencyServiceCategories=" + mEmergencyCallRouting + + ", emergencyCallRouting=" + mEmergencyCallRouting + " }"; } @Override @@ -522,6 +540,7 @@ public final class ImsCallProfile implements Parcelable { out.writeBundle(filteredExtras); out.writeParcelable(mMediaProfile, 0); out.writeInt(mEmergencyServiceCategories); + out.writeInt(mEmergencyCallRouting); } private void readFromParcel(Parcel in) { @@ -530,6 +549,7 @@ public final class ImsCallProfile implements Parcelable { mCallExtras = in.readBundle(); mMediaProfile = in.readParcelable(ImsStreamMediaProfile.class.getClassLoader()); mEmergencyServiceCategories = in.readInt(); + mEmergencyCallRouting = in.readInt(); } public static final Creator<ImsCallProfile> CREATOR = new Creator<ImsCallProfile>() { @@ -740,6 +760,21 @@ public final class ImsCallProfile implements Parcelable { } /** + * Set the emergency service categories and emergency call routing. The set value is valid + * only if {@link #getServiceType} returns {@link #SERVICE_TYPE_EMERGENCY} + * + * Reference: 3gpp 23.167, Section 6 - Functional description; + * 3gpp 22.101, Section 10 - Emergency Calls. + * + * @hide + */ + public void setEmergencyCallInfo(EmergencyNumber num) { + setEmergencyServiceCategories(num.getEmergencyServiceCategoryBitmask()); + setEmergencyCallRouting(num.getEmergencyCallRouting()); + } + + + /** * Set the emergency service categories. The set value is valid only if * {@link #getServiceType} returns {@link #SERVICE_TYPE_EMERGENCY} * @@ -758,12 +793,29 @@ public final class ImsCallProfile implements Parcelable { * Reference: 3gpp 23.167, Section 6 - Functional description; * 3gpp 22.101, Section 10 - Emergency Calls. */ + @VisibleForTesting public void setEmergencyServiceCategories( @EmergencyServiceCategories int emergencyServiceCategories) { mEmergencyServiceCategories = emergencyServiceCategories; } /** + * Set the emergency call routing, only valid if {@link #getServiceType} returns + * {@link #SERVICE_TYPE_EMERGENCY} + * + * If valid, the value is any of the following constants: + * <ol> + * <li>{@link EmergencyNumber#EMERGENCY_CALL_ROUTING_UNKNOWN} </li> + * <li>{@link EmergencyNumber#EMERGENCY_CALL_ROUTING_NORMAL} </li> + * <li>{@link EmergencyNumber#EMERGENCY_CALL_ROUTING_EMERGENCY} </li> + * </ol> + */ + @VisibleForTesting + public void setEmergencyCallRouting(@EmergencyCallRouting int emergencyCallRouting) { + mEmergencyCallRouting = emergencyCallRouting; + } + + /** * Get the emergency service categories, only valid if {@link #getServiceType} returns * {@link #SERVICE_TYPE_EMERGENCY} * @@ -787,4 +839,19 @@ public final class ImsCallProfile implements Parcelable { public @EmergencyServiceCategories int getEmergencyServiceCategories() { return mEmergencyServiceCategories; } + + /** + * Get the emergency call routing, only valid if {@link #getServiceType} returns + * {@link #SERVICE_TYPE_EMERGENCY} + * + * If valid, the value is any of the following constants: + * <ol> + * <li>{@link EmergencyNumber#EMERGENCY_CALL_ROUTING_UNKNOWN} </li> + * <li>{@link EmergencyNumber#EMERGENCY_CALL_ROUTING_NORMAL} </li> + * <li>{@link EmergencyNumber#EMERGENCY_CALL_ROUTING_EMERGENCY} </li> + * </ol> + */ + public @EmergencyCallRouting int getEmergencyCallRouting() { + return mEmergencyCallRouting; + } } diff --git a/telephony/java/android/telephony/ims/ImsMmTelManager.java b/telephony/java/android/telephony/ims/ImsMmTelManager.java index e2350fe78500..9414abd98b1c 100644 --- a/telephony/java/android/telephony/ims/ImsMmTelManager.java +++ b/telephony/java/android/telephony/ims/ImsMmTelManager.java @@ -92,7 +92,7 @@ public class ImsMmTelManager { public static final int WIFI_MODE_WIFI_PREFERRED = 2; /** - * Callback class for receiving Registration callback events. + * Callback class for receiving IMS network Registration callback events. * @see #registerImsRegistrationCallback(Executor, RegistrationCallback) (RegistrationCallback) * @see #unregisterImsRegistrationCallback(RegistrationCallback) */ @@ -241,7 +241,8 @@ public class ImsMmTelManager { } /** - * Receives IMS capability status updates from the ImsService. + * Receives IMS capability status updates from the ImsService. This information is also + * available via the {@link #isAvailable(int, int)} method below. * * @see #registerMmTelCapabilityCallback(Executor, CapabilityCallback) (CapabilityCallback) * @see #unregisterMmTelCapabilityCallback(CapabilityCallback) @@ -290,6 +291,8 @@ public class ImsMmTelManager { * If unavailable, the feature is not able to support the unavailable capability at this * time. * + * This information can also be queried using the {@link #isAvailable(int, int)} API. + * * @param capabilities The new availability of the capabilities. */ public void onCapabilitiesStatusChanged( @@ -304,7 +307,7 @@ public class ImsMmTelManager { /**@hide*/ // Only exposed as public method for compatibility with deprecated ImsManager APIs. // TODO: clean up dependencies and change back to private visibility. - public void setExecutor(Executor executor) { + public final void setExecutor(Executor executor) { mBinder.setExecutor(executor); } } @@ -342,8 +345,7 @@ public class ImsMmTelManager { * Registers a {@link RegistrationCallback} with the system, which will provide registration * updates for the subscription specified in {@link #createForSubscriptionId(Context, int)}. Use * {@link SubscriptionManager.OnSubscriptionsChangedListener} to listen to Subscription changed - * events and call {@link #unregisterImsRegistrationCallback(RegistrationCallback)} to clean up - * after a subscription is removed. + * events and call {@link #unregisterImsRegistrationCallback(RegistrationCallback)} to clean up. * * When the callback is registered, it will initiate the callback c to be called with the * current registration state. @@ -351,6 +353,12 @@ public class ImsMmTelManager { * @param executor The executor the callback events should be run on. * @param c The {@link RegistrationCallback} to be added. * @see #unregisterImsRegistrationCallback(RegistrationCallback) + * @throws IllegalArgumentException if the subscription associated with this callback is not + * active (SIM is not inserted, ESIM inactive) or invalid, or a null {@link Executor} or + * {@link CapabilityCallback} callback. + * @throws IllegalStateException if the subscription associated with this callback is valid, but + * the {@link ImsService} associated with the subscription is not available. This can happen if + * the service crashed, for example. */ @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void registerImsRegistrationCallback(@CallbackExecutor Executor executor, @@ -370,11 +378,17 @@ public class ImsMmTelManager { } /** - * Removes an existing {@link RegistrationCallback}. Ensure to call this method when cleaning - * up to avoid memory leaks or when the subscription is removed. + * Removes an existing {@link RegistrationCallback}. + * + * When the subscription associated with this callback is removed (SIM removed, ESIM swap, + * etc...), this callback will automatically be removed. If this method is called for an + * inactive subscription, it will result in a no-op. + * * @param c The {@link RegistrationCallback} to be removed. * @see SubscriptionManager.OnSubscriptionsChangedListener * @see #registerImsRegistrationCallback(Executor, RegistrationCallback) + * @throws IllegalArgumentException if the subscription ID associated with this callback is + * invalid. */ @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void unregisterImsRegistrationCallback(@NonNull RegistrationCallback c) { @@ -389,12 +403,14 @@ public class ImsMmTelManager { } /** - * Registers a {@link CapabilityCallback} with the system, which will provide MmTel capability - * updates for the subscription specified in {@link #createForSubscriptionId(Context, int)}. + * Registers a {@link CapabilityCallback} with the system, which will provide MmTel service + * availability updates for the subscription specified in + * {@link #createForSubscriptionId(Context, int)}. The method {@link #isAvailable(int, int)} + * can also be used to query this information at any time. + * * Use {@link SubscriptionManager.OnSubscriptionsChangedListener} to listen to * subscription changed events and call - * {@link #unregisterImsRegistrationCallback(RegistrationCallback)} to clean up after a - * subscription is removed. + * {@link #unregisterImsRegistrationCallback(RegistrationCallback)} to clean up. * * When the callback is registered, it will initiate the callback c to be called with the * current capabilities. @@ -402,9 +418,15 @@ public class ImsMmTelManager { * @param executor The executor the callback events should be run on. * @param c The MmTel {@link CapabilityCallback} to be registered. * @see #unregisterMmTelCapabilityCallback(CapabilityCallback) + * @throws IllegalArgumentException if the subscription associated with this callback is not + * active (SIM is not inserted, ESIM inactive) or invalid, or a null {@link Executor} or + * {@link CapabilityCallback} callback. + * @throws IllegalStateException if the subscription associated with this callback is valid, but + * the {@link ImsService} associated with the subscription is not available. This can happen if + * the service crashed, for example. */ @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) - public void registerMmTelCapabilityCallback(@CallbackExecutor Executor executor, + public void registerMmTelCapabilityCallback(@NonNull @CallbackExecutor Executor executor, @NonNull CapabilityCallback c) { if (c == null) { throw new IllegalArgumentException("Must include a non-null RegistrationCallback."); @@ -421,10 +443,15 @@ public class ImsMmTelManager { } /** - * Removes an existing MmTel {@link CapabilityCallback}. Be sure to call this when cleaning - * up to avoid memory leaks. + * Removes an existing MmTel {@link CapabilityCallback}. + * + * When the subscription associated with this callback is removed (SIM removed, ESIM swap, + * etc...), this callback will automatically be removed. If this method is called for an + * inactive subscription, it will result in a no-op. * @param c The MmTel {@link CapabilityCallback} to be removed. * @see #registerMmTelCapabilityCallback(Executor, CapabilityCallback) + * @throws IllegalArgumentException if the subscription ID associated with this callback is + * invalid. */ @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void unregisterMmTelCapabilityCallback(@NonNull CapabilityCallback c) { diff --git a/telephony/java/android/telephony/ims/ProvisioningManager.java b/telephony/java/android/telephony/ims/ProvisioningManager.java index 916e282f642e..d37198a3e25d 100644 --- a/telephony/java/android/telephony/ims/ProvisioningManager.java +++ b/telephony/java/android/telephony/ims/ProvisioningManager.java @@ -133,33 +133,40 @@ public class ProvisioningManager { } /** - * Register a new {@link Callback} to listen to changes to changes in - * IMS provisioning. Use {@link SubscriptionManager.OnSubscriptionsChangedListener} to listen to - * Subscription changed events and call - * {@link #unregisterProvisioningChangedCallback(Callback)} to clean up after a - * subscription is removed. + * Register a new {@link Callback} to listen to changes to changes in IMS provisioning. + * + * When the subscription associated with this callback is removed (SIM removed, ESIM swap, + * etc...), this callback will automatically be removed. * @param executor The {@link Executor} to call the callback methods on * @param callback The provisioning callbackto be registered. * @see #unregisterProvisioningChangedCallback(Callback) * @see SubscriptionManager.OnSubscriptionsChangedListener + * @throws IllegalArgumentException if the subscription associated with this callback is not + * active (SIM is not inserted, ESIM inactive) or the subscription is invalid. + * @throws IllegalStateException if the subscription associated with this callback is valid, but + * the {@link ImsService} associated with the subscription is not available. This can happen if + * the service crashed, for example. */ @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void registerProvisioningChangedCallback(@CallbackExecutor Executor executor, @NonNull Callback callback) { callback.setExecutor(executor); try { - getITelephony().registerImsProvisioningChangedCallback(mSubId, - callback.getBinder()); + getITelephony().registerImsProvisioningChangedCallback(mSubId, callback.getBinder()); } catch (RemoteException e) { throw e.rethrowAsRuntimeException(); } } /** - * Unregister an existing {@link Callback}. Ensure to call this method when cleaning - * up to avoid memory leaks or when the subscription is removed. + * Unregister an existing {@link Callback}. When the subscription associated with this + * callback is removed (SIM removed, ESIM swap, etc...), this callback will automatically be + * removed. If this method is called for an inactive subscription, it will result in a no-op. * @param callback The existing {@link Callback} to be removed. * @see #registerProvisioningChangedCallback(Executor, Callback) + * + * @throws IllegalArgumentException if the subscription associated with this callback is + * invalid. */ @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void unregisterProvisioningChangedCallback(@NonNull Callback callback) { diff --git a/telephony/java/com/android/internal/telephony/DctConstants.java b/telephony/java/com/android/internal/telephony/DctConstants.java index 96f7a1bc22a0..17516bc24aca 100644 --- a/telephony/java/com/android/internal/telephony/DctConstants.java +++ b/telephony/java/com/android/internal/telephony/DctConstants.java @@ -66,7 +66,8 @@ public class DctConstants { public static final int EVENT_DATA_CONNECTION_DETACHED = BASE + 9; public static final int EVENT_ROAMING_ON = BASE + 11; public static final int EVENT_ROAMING_OFF = BASE + 12; - public static final int EVENT_ENABLE_NEW_APN = BASE + 13; + public static final int EVENT_ENABLE_APN = BASE + 13; + public static final int EVENT_DISABLE_APN = BASE + 14; public static final int EVENT_DISCONNECT_DONE = BASE + 15; public static final int EVENT_DATA_CONNECTION_ATTACHED = BASE + 16; public static final int EVENT_DATA_STALL_ALARM = BASE + 17; @@ -92,6 +93,7 @@ public class DctConstants { public static final int EVENT_DATA_RECONNECT = BASE + 47; public static final int EVENT_ROAMING_SETTING_CHANGE = BASE + 48; public static final int EVENT_DATA_SERVICE_BINDING_CHANGED = BASE + 49; + public static final int EVENT_DEVICE_PROVISIONED_CHANGE = BASE + 50; /***** Constants *****/ diff --git a/telephony/java/com/android/internal/telephony/euicc/IEuiccController.aidl b/telephony/java/com/android/internal/telephony/euicc/IEuiccController.aidl index dd40d560250d..14a36c8c840d 100644 --- a/telephony/java/com/android/internal/telephony/euicc/IEuiccController.aidl +++ b/telephony/java/com/android/internal/telephony/euicc/IEuiccController.aidl @@ -24,22 +24,25 @@ import android.telephony.euicc.EuiccInfo; /** @hide */ interface IEuiccController { - oneway void continueOperation(in Intent resolutionIntent, in Bundle resolutionExtras); - oneway void getDownloadableSubscriptionMetadata(in DownloadableSubscription subscription, + oneway void continueOperation(int cardId, in Intent resolutionIntent, + in Bundle resolutionExtras); + oneway void getDownloadableSubscriptionMetadata(int cardId, + in DownloadableSubscription subscription, String callingPackage, in PendingIntent callbackIntent); - oneway void getDefaultDownloadableSubscriptionList( + oneway void getDefaultDownloadableSubscriptionList(int cardId, String callingPackage, in PendingIntent callbackIntent); - String getEid(); - int getOtaStatus(); - oneway void downloadSubscription(in DownloadableSubscription subscription, - boolean switchAfterDownload, String callingPackage, in Bundle resolvedBundle, in PendingIntent callbackIntent); - EuiccInfo getEuiccInfo(); - oneway void deleteSubscription(int subscriptionId, String callingPackage, + String getEid(int cardId); + int getOtaStatus(int cardId); + oneway void downloadSubscription(int cardId, in DownloadableSubscription subscription, + boolean switchAfterDownload, String callingPackage, in Bundle resolvedBundle, in PendingIntent callbackIntent); - oneway void switchToSubscription(int subscriptionId, String callingPackage, + EuiccInfo getEuiccInfo(int cardId); + oneway void deleteSubscription(int cardId, int subscriptionId, String callingPackage, in PendingIntent callbackIntent); - oneway void updateSubscriptionNickname(int subscriptionId, String nickname, + oneway void switchToSubscription(int cardId, int subscriptionId, String callingPackage, + in PendingIntent callbackIntent); + oneway void updateSubscriptionNickname(int cardId, int subscriptionId, String nickname, String callingPackage, in PendingIntent callbackIntent); - oneway void eraseSubscriptions(in PendingIntent callbackIntent); - oneway void retainSubscriptionsForFactoryReset(in PendingIntent callbackIntent); -}
\ No newline at end of file + oneway void eraseSubscriptions(int cardId, in PendingIntent callbackIntent); + oneway void retainSubscriptionsForFactoryReset(int cardId, in PendingIntent callbackIntent); +} diff --git a/test-legacy/Android.bp b/test-legacy/Android.bp index 833c714f07b0..a69f422b3bdb 100644 --- a/test-legacy/Android.bp +++ b/test-legacy/Android.bp @@ -25,7 +25,7 @@ java_library_static { static_libs: [ "android.test.base-minus-junit", "android.test.runner-minus-junit", - "android.test.mock.impl", + "android.test.mock_static", ], no_framework_libs: true, diff --git a/test-mock/Android.bp b/test-mock/Android.bp index e1d6e01d6d06..43b765d8b783 100644 --- a/test-mock/Android.bp +++ b/test-mock/Android.bp @@ -30,3 +30,19 @@ java_sdk_library { srcs_lib_whitelist_pkgs: ["android"], compile_dex: true, } + +// Build the android.test.mock_static library +// ========================================== +// This is only intended for inclusion in the legacy-android-test. +// Must not be used elewhere. +java_library_static { + name: "android.test.mock_static", + + java_version: "1.8", + srcs: ["src/**/*.java"], + + no_framework_libs: true, + libs: [ + "framework", + ], +} diff --git a/tests/net/java/android/net/shared/LinkPropertiesParcelableUtilTest.java b/tests/net/java/android/net/shared/LinkPropertiesParcelableUtilTest.java new file mode 100644 index 000000000000..4cabfc95b49d --- /dev/null +++ b/tests/net/java/android/net/shared/LinkPropertiesParcelableUtilTest.java @@ -0,0 +1,193 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net.shared; + +import static android.net.shared.LinkPropertiesParcelableUtil.fromStableParcelable; +import static android.net.shared.LinkPropertiesParcelableUtil.toStableParcelable; + +import static org.junit.Assert.assertEquals; + +import android.net.InetAddresses; +import android.net.IpPrefix; +import android.net.LinkAddress; +import android.net.LinkProperties; +import android.net.ProxyInfo; +import android.net.RouteInfo; +import android.net.Uri; +import android.support.test.filters.SmallTest; +import android.support.test.runner.AndroidJUnit4; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; + +import java.lang.reflect.Modifier; +import java.util.Arrays; +import java.util.Collections; + +/** + * Tests for {@link LinkPropertiesParcelableUtil} + */ +@RunWith(AndroidJUnit4.class) +@SmallTest +public class LinkPropertiesParcelableUtilTest { + private LinkProperties mLinkProperties; + + private static final String TEST_LINKPROPS_IFACE = "TEST_IFACE"; + private static final String TEST_STACKED_LINK_1_IFACE = "TEST_STACKED_IFACE_1"; + private static final String TEST_STACKED_LINK_2_IFACE = "TEST_STACKED_IFACE_2"; + + @Before + public void setUp() { + mLinkProperties = makeLinkProperties(TEST_LINKPROPS_IFACE); + mLinkProperties.addStackedLink(makeLinkProperties(TEST_STACKED_LINK_1_IFACE)); + mLinkProperties.addStackedLink(makeLinkProperties(TEST_STACKED_LINK_2_IFACE)); + } + + private static LinkProperties makeLinkProperties(String iface) { + final LinkProperties lp = new LinkProperties(); + lp.setInterfaceName(iface); + lp.setLinkAddresses(Arrays.asList( + new LinkAddress(InetAddresses.parseNumericAddress("192.168.0.42"), 16), + new LinkAddress(InetAddresses.parseNumericAddress("2001:db8::7"), 42))); + lp.setDnsServers(Arrays.asList( + InetAddresses.parseNumericAddress("2001:db8::42"), + InetAddresses.parseNumericAddress("192.168.1.1") + )); + lp.setValidatedPrivateDnsServers(Arrays.asList( + InetAddresses.parseNumericAddress("2001:db8::43"), + InetAddresses.parseNumericAddress("192.168.42.43") + )); + lp.setPcscfServers(Arrays.asList( + InetAddresses.parseNumericAddress("2001:db8::47"), + InetAddresses.parseNumericAddress("192.168.42.47") + )); + lp.setUsePrivateDns(true); + lp.setPrivateDnsServerName("test.example.com"); + lp.setDomains("test1.example.com,test2.example.com"); + lp.addRoute(new RouteInfo( + new IpPrefix(InetAddresses.parseNumericAddress("2001:db8::44"), 45), + InetAddresses.parseNumericAddress("2001:db8::45"), + iface, + RouteInfo.RTN_UNICAST + )); + lp.addRoute(new RouteInfo( + new IpPrefix(InetAddresses.parseNumericAddress("192.168.44.45"), 16), + InetAddresses.parseNumericAddress("192.168.45.1"), + iface, + RouteInfo.RTN_THROW + )); + lp.setHttpProxy(new ProxyInfo("test3.example.com", 8000, + "excl1.example.com,excl2.example.com")); + lp.setMtu(5000); + lp.setTcpBufferSizes("1,2,3,4,5,6"); + lp.setNat64Prefix(new IpPrefix(InetAddresses.parseNumericAddress("2001:db8::48"), 96)); + + // Verify that this test does not miss any new field added later. + // If any added field is not included in LinkProperties#equals, assertLinkPropertiesEquals + // must also be updated. + assertEquals(14, Arrays.stream(LinkProperties.class.getDeclaredFields()) + .filter(f -> !Modifier.isStatic(f.getModifiers())).count()); + + return lp; + } + + @Test + public void testParcelUnparcel() { + doParcelUnparcelTest(); + } + + @Test + public void testParcelUnparcel_NullInterface() { + mLinkProperties.setInterfaceName(null); + doParcelUnparcelTest(); + } + + @Test + public void testParcelUnparcel_NullPrivateDnsServer() { + mLinkProperties.setPrivateDnsServerName(null); + doParcelUnparcelTest(); + } + + @Test + public void testParcelUnparcel_NullDomains() { + mLinkProperties.setDomains(null); + doParcelUnparcelTest(); + } + + @Test + public void testParcelUnparcel_NullProxy() { + mLinkProperties.setHttpProxy(null); + doParcelUnparcelTest(); + } + + @Test + public void testParcelUnparcel_NullTcpBufferSizes() { + mLinkProperties.setTcpBufferSizes(null); + doParcelUnparcelTest(); + } + + @Test + public void testParcelUnparcel_EmptyLinkAddresses() { + mLinkProperties.setLinkAddresses(Collections.emptyList()); + doParcelUnparcelTest(); + } + + @Test + public void testParcelUnparcel_EmptyDnses() { + mLinkProperties.setDnsServers(Collections.emptyList()); + doParcelUnparcelTest(); + } + + @Test + public void testParcelUnparcel_EmptyValidatedPrivateDnses() { + mLinkProperties.setValidatedPrivateDnsServers(Collections.emptyList()); + doParcelUnparcelTest(); + } + + @Test + public void testParcelUnparcel_EmptyRoutes() { + for (RouteInfo r : mLinkProperties.getAllRoutes()) { + mLinkProperties.removeRoute(r); + } + doParcelUnparcelTest(); + } + + @Test + public void testParcelUnparcel_PacFileProxyInfo() { + mLinkProperties.setHttpProxy(new ProxyInfo(Uri.parse("http://pacfile.example.com"))); + doParcelUnparcelTest(); + } + + @Test + public void testParcelUnparcel_NullNat64Prefix() { + mLinkProperties.setNat64Prefix(null); + doParcelUnparcelTest(); + } + + private void doParcelUnparcelTest() { + final LinkProperties unparceled = fromStableParcelable(toStableParcelable(mLinkProperties)); + assertLinkPropertiesEquals(mLinkProperties, unparceled); + } + + private static void assertLinkPropertiesEquals(LinkProperties expected, LinkProperties actual) { + assertEquals(expected, actual); + + // LinkProperties equals() does not include stacked links + assertEquals(expected.getStackedLinks(), actual.getStackedLinks()); + } +} diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java index 2a92a7dabd98..882babff4aee 100644 --- a/tests/net/java/com/android/server/ConnectivityServiceTest.java +++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java @@ -122,7 +122,6 @@ import android.net.NetworkSpecifier; import android.net.NetworkStack; import android.net.NetworkUtils; import android.net.RouteInfo; -import android.net.StringNetworkSpecifier; import android.net.UidRange; import android.net.metrics.IpConnectivityLog; import android.net.shared.NetworkMonitorUtils; @@ -145,6 +144,7 @@ import android.support.test.InstrumentationRegistry; import android.support.test.filters.SmallTest; import android.support.test.runner.AndroidJUnit4; import android.test.mock.MockContentResolver; +import android.text.TextUtils; import android.util.ArraySet; import android.util.Log; @@ -2567,16 +2567,76 @@ public class ConnectivityServiceTest { return new NetworkRequest.Builder().addTransportType(TRANSPORT_WIFI); } + /** + * Verify request matching behavior with network specifiers. + * + * Note: this test is somewhat problematic since it involves removing capabilities from + * agents - i.e. agents rejecting requests which they previously accepted. This is flagged + * as a WTF bug in + * {@link ConnectivityService#mixInCapabilities(NetworkAgentInfo, NetworkCapabilities)} but + * does work. + */ @Test public void testNetworkSpecifier() { + // A NetworkSpecifier subclass that matches all networks but must not be visible to apps. + class ConfidentialMatchAllNetworkSpecifier extends NetworkSpecifier implements + Parcelable { + @Override + public boolean satisfiedBy(NetworkSpecifier other) { + return true; + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) {} + + @Override + public NetworkSpecifier redact() { + return null; + } + } + + // A network specifier that matches either another LocalNetworkSpecifier with the same + // string or a ConfidentialMatchAllNetworkSpecifier, and can be passed to apps as is. + class LocalStringNetworkSpecifier extends NetworkSpecifier implements Parcelable { + private String mString; + + LocalStringNetworkSpecifier(String string) { + mString = string; + } + + @Override + public boolean satisfiedBy(NetworkSpecifier other) { + if (other instanceof LocalStringNetworkSpecifier) { + return TextUtils.equals(mString, + ((LocalStringNetworkSpecifier) other).mString); + } + if (other instanceof ConfidentialMatchAllNetworkSpecifier) return true; + return false; + } + + @Override + public int describeContents() { + return 0; + } + @Override + public void writeToParcel(Parcel dest, int flags) {} + } + + NetworkRequest rEmpty1 = newWifiRequestBuilder().build(); NetworkRequest rEmpty2 = newWifiRequestBuilder().setNetworkSpecifier((String) null).build(); NetworkRequest rEmpty3 = newWifiRequestBuilder().setNetworkSpecifier("").build(); NetworkRequest rEmpty4 = newWifiRequestBuilder().setNetworkSpecifier( (NetworkSpecifier) null).build(); - NetworkRequest rFoo = newWifiRequestBuilder().setNetworkSpecifier("foo").build(); + NetworkRequest rFoo = newWifiRequestBuilder().setNetworkSpecifier( + new LocalStringNetworkSpecifier("foo")).build(); NetworkRequest rBar = newWifiRequestBuilder().setNetworkSpecifier( - new StringNetworkSpecifier("bar")).build(); + new LocalStringNetworkSpecifier("bar")).build(); TestNetworkCallback cEmpty1 = new TestNetworkCallback(); TestNetworkCallback cEmpty2 = new TestNetworkCallback(); @@ -2585,7 +2645,7 @@ public class ConnectivityServiceTest { TestNetworkCallback cFoo = new TestNetworkCallback(); TestNetworkCallback cBar = new TestNetworkCallback(); TestNetworkCallback[] emptyCallbacks = new TestNetworkCallback[] { - cEmpty1, cEmpty2, cEmpty3 }; + cEmpty1, cEmpty2, cEmpty3, cEmpty4 }; mCm.registerNetworkCallback(rEmpty1, cEmpty1); mCm.registerNetworkCallback(rEmpty2, cEmpty2); @@ -2594,6 +2654,9 @@ public class ConnectivityServiceTest { mCm.registerNetworkCallback(rFoo, cFoo); mCm.registerNetworkCallback(rBar, cBar); + LocalStringNetworkSpecifier nsFoo = new LocalStringNetworkSpecifier("foo"); + LocalStringNetworkSpecifier nsBar = new LocalStringNetworkSpecifier("bar"); + mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); mWiFiNetworkAgent.connect(false); cEmpty1.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); @@ -2602,30 +2665,54 @@ public class ConnectivityServiceTest { cEmpty4.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); assertNoCallbacks(cFoo, cBar); - mWiFiNetworkAgent.setNetworkSpecifier(new StringNetworkSpecifier("foo")); + mWiFiNetworkAgent.setNetworkSpecifier(nsFoo); cFoo.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); for (TestNetworkCallback c: emptyCallbacks) { - c.expectCallback(CallbackState.NETWORK_CAPABILITIES, mWiFiNetworkAgent); + c.expectCapabilitiesLike((caps) -> caps.getNetworkSpecifier().equals(nsFoo), + mWiFiNetworkAgent); } - cFoo.expectCallback(CallbackState.NETWORK_CAPABILITIES, mWiFiNetworkAgent); + cFoo.expectCapabilitiesLike((caps) -> caps.getNetworkSpecifier().equals(nsFoo), + mWiFiNetworkAgent); + assertEquals(nsFoo, + mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).getNetworkSpecifier()); cFoo.assertNoCallback(); - mWiFiNetworkAgent.setNetworkSpecifier(new StringNetworkSpecifier("bar")); + mWiFiNetworkAgent.setNetworkSpecifier(nsBar); cFoo.expectCallback(CallbackState.LOST, mWiFiNetworkAgent); cBar.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); for (TestNetworkCallback c: emptyCallbacks) { - c.expectCallback(CallbackState.NETWORK_CAPABILITIES, mWiFiNetworkAgent); + c.expectCapabilitiesLike((caps) -> caps.getNetworkSpecifier().equals(nsBar), + mWiFiNetworkAgent); } - cBar.expectCallback(CallbackState.NETWORK_CAPABILITIES, mWiFiNetworkAgent); + cBar.expectCapabilitiesLike((caps) -> caps.getNetworkSpecifier().equals(nsBar), + mWiFiNetworkAgent); + assertEquals(nsBar, + mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).getNetworkSpecifier()); + cBar.assertNoCallback(); + + mWiFiNetworkAgent.setNetworkSpecifier(new ConfidentialMatchAllNetworkSpecifier()); + cFoo.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); + for (TestNetworkCallback c : emptyCallbacks) { + c.expectCapabilitiesLike((caps) -> caps.getNetworkSpecifier() == null, + mWiFiNetworkAgent); + } + cFoo.expectCapabilitiesLike((caps) -> caps.getNetworkSpecifier() == null, + mWiFiNetworkAgent); + cBar.expectCapabilitiesLike((caps) -> caps.getNetworkSpecifier() == null, + mWiFiNetworkAgent); + assertNull( + mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).getNetworkSpecifier()); + cFoo.assertNoCallback(); cBar.assertNoCallback(); mWiFiNetworkAgent.setNetworkSpecifier(null); + cFoo.expectCallback(CallbackState.LOST, mWiFiNetworkAgent); cBar.expectCallback(CallbackState.LOST, mWiFiNetworkAgent); for (TestNetworkCallback c: emptyCallbacks) { c.expectCallback(CallbackState.NETWORK_CAPABILITIES, mWiFiNetworkAgent); } - assertNoCallbacks(cEmpty1, cEmpty2, cEmpty3, cFoo, cBar); + assertNoCallbacks(cEmpty1, cEmpty2, cEmpty3, cEmpty4, cFoo, cBar); } @Test |