diff options
29 files changed, 1816 insertions, 360 deletions
diff --git a/apex/Android.bp b/apex/Android.bp index cabed3b44d41..c5b4901a9b79 100644 --- a/apex/Android.bp +++ b/apex/Android.bp @@ -147,141 +147,6 @@ java_defaults { } stubs_defaults { - name: "framework-module-stubs-defaults-publicapi", - args: mainline_framework_stubs_args, - installable: false, - sdk_version: "module_current", - annotations_enabled: true, - merge_annotations_dirs: [ - "metalava-manual", - ], - filter_packages: framework_packages_to_document, - check_api: { - current: { - api_file: "api/current.txt", - removed_api_file: "api/removed.txt", - }, - api_lint: { - enabled: true, - }, - }, - dist: { - targets: ["sdk", "win_sdk"], - dir: "apistubs/android/public/api", - }, -} - -stubs_defaults { - name: "framework-module-stubs-defaults-systemapi", - args: mainline_framework_stubs_args + priv_apps, - libs: ["framework-annotations-lib"], - installable: false, - sdk_version: "module_current", - annotations_enabled: true, - merge_annotations_dirs: [ - "metalava-manual", - ], - filter_packages: framework_packages_to_document, - check_api: { - current: { - api_file: "api/system-current.txt", - removed_api_file: "api/system-removed.txt", - }, - api_lint: { - enabled: true, - }, - }, - dist: { - targets: ["sdk", "win_sdk"], - dir: "apistubs/android/system/api", - }, -} - -java_defaults { - name: "framework-module-stubs-lib-defaults-publicapi", - installable: false, - sdk_version: "module_current", - libs: [ "stub-annotations" ], - java_version: "1.8", - dist: { - targets: ["sdk", "win_sdk"], - dir: "apistubs/android/public", - }, -} - -java_defaults { - name: "framework-module-stubs-lib-defaults-systemapi", - installable: false, - sdk_version: "module_current", - libs: [ "stub-annotations" ], - java_version: "1.8", - dist: { - targets: ["sdk", "win_sdk"], - dir: "apistubs/android/system", - }, -} - -java_defaults { - name: "framework-module-stubs-lib-defaults-module_libs_api", - installable: false, - sdk_version: "module_current", - libs: [ "stub-annotations" ], - java_version: "1.8", - dist: { - targets: ["sdk", "win_sdk"], - dir: "apistubs/android/module-lib", - }, -} - -// The defaults for module_libs comes in two parts - defaults for API checks -// and defaults for stub generation. This is because we want the API txt -// files to *only* include the module_libs_api, but the stubs to include -// module_libs_api as well as priv_apps. - -stubs_defaults { - name: "framework-module-api-defaults-module_libs_api", - args: mainline_framework_stubs_args + module_libs, - libs: ["framework-annotations-lib"], - installable: false, - sdk_version: "module_current", - annotations_enabled: true, - merge_annotations_dirs: [ - "metalava-manual", - ], - filter_packages: framework_packages_to_document, - - // Do not generate stubs as they are not needed - generate_stubs: false, - - check_api: { - current: { - api_file: "api/module-lib-current.txt", - removed_api_file: "api/module-lib-removed.txt", - }, - api_lint: { - enabled: true, - }, - }, - dist: { - targets: ["sdk", "win_sdk"], - dir: "apistubs/android/module-lib/api", - }, -} - -stubs_defaults { - name: "framework-module-stubs-defaults-module_libs_api", - args: mainline_framework_stubs_args + module_libs + priv_apps, - libs: ["framework-annotations-lib"], - installable: false, - sdk_version: "module_current", - annotations_enabled: true, - merge_annotations_dirs: [ - "metalava-manual", - ], - filter_packages: framework_packages_to_document, -} - -stubs_defaults { name: "service-module-stubs-srcs-defaults", args: mainline_service_stubs_args, installable: false, diff --git a/api/Android.bp b/api/Android.bp index 9f99b78c11c4..4d7f58edd870 100644 --- a/api/Android.bp +++ b/api/Android.bp @@ -16,25 +16,6 @@ package { default_visibility: ["//visibility:private"], } -// *-current.txt files for use by modules in other directories like cts -filegroup { - name: "frameworks-base-api-current.txt", - srcs: ["current.txt"], - visibility: ["//visibility:public"], -} - -filegroup { - name: "frameworks-base-api-system-current.txt", - srcs: ["system-current.txt"], - visibility: ["//visibility:public"], -} - -filegroup { - name: "frameworks-base-api-system-removed.txt", - srcs: ["system-removed.txt"], - visibility: ["//visibility:public"], -} - genrule { name: "current-api-xml", tools: ["metalava"], @@ -45,7 +26,7 @@ genrule { } genrule { - name: "frameworks-base-api-current-merged.txt", + name: "frameworks-base-api-current.txt", srcs: [ ":conscrypt.module.public.api{.public.api.txt}", ":framework-media{.public.api.txt}", @@ -72,10 +53,11 @@ genrule { dest: "android.txt", }, ], + visibility: ["//visibility:public"], } genrule { - name: "frameworks-base-api-removed-merged.txt", + name: "frameworks-base-api-removed.txt", srcs: [ ":conscrypt.module.public.api{.public.removed-api.txt}", ":framework-media{.public.removed-api.txt}", @@ -100,7 +82,7 @@ genrule { } genrule { - name: "frameworks-base-api-system-current-merged.txt", + name: "frameworks-base-api-system-current.txt", srcs: [ ":framework-media{.system.api.txt}", ":framework-mediaprovider{.system.api.txt}", @@ -126,10 +108,11 @@ genrule { dest: "android.txt", }, ], + visibility: ["//visibility:public"], } genrule { - name: "frameworks-base-api-system-removed-merged.txt", + name: "frameworks-base-api-system-removed.txt", srcs: [ ":framework-media{.system.removed-api.txt}", ":framework-mediaprovider{.system.removed-api.txt}", @@ -150,10 +133,11 @@ genrule { dest: "system-removed.txt", }, ], + visibility: ["//visibility:public"], } genrule { - name: "frameworks-base-api-module-lib-current-merged.txt", + name: "frameworks-base-api-module-lib-current.txt", srcs: [ ":framework-media{.module-lib.api.txt}", ":framework-mediaprovider{.module-lib.api.txt}", @@ -182,7 +166,7 @@ genrule { } genrule { - name: "frameworks-base-api-module-lib-removed-merged.txt", + name: "frameworks-base-api-module-lib-removed.txt", srcs: [ ":framework-media{.module-lib.removed-api.txt}", ":framework-mediaprovider{.module-lib.removed-api.txt}", @@ -208,8 +192,8 @@ genrule { genrule { name: "combined-removed-dex", srcs: [ - ":frameworks-base-api-removed-merged.txt", - ":frameworks-base-api-system-removed-merged.txt", + ":frameworks-base-api-removed.txt", + ":frameworks-base-api-system-removed.txt", ":android.car-stubs-docs{.removed-api.txt}", ":android.car-system-stubs-docs{.removed-api.txt}", ], diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index fd3b8cbb6a50..6957b67702df 100644 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -1678,7 +1678,7 @@ to be explicitly declared in this resource to be enabled. * SDK level 28 makes the following algorithms mandatory : "cbc(aes)", "hmac(md5)", "hmac(sha1)", "hmac(sha256)", "hmac(sha384)", "hmac(sha512)", "rfc4106(gcm(aes))" - * SDK level 30 makes the following algorithms mandatory : "rfc3686(ctr(aes))", + * SDK level 31 makes the following algorithms mandatory : "rfc3686(ctr(aes))", "xcbc(aes)", "rfc7539esp(chacha20,poly1305)" --> <string-array name="config_optionalIpSecAlgorithms" translatable="false"> diff --git a/packages/VpnDialogs/AndroidManifest.xml b/packages/VpnDialogs/AndroidManifest.xml index 693ca52b4ed1..569617a21f15 100644 --- a/packages/VpnDialogs/AndroidManifest.xml +++ b/packages/VpnDialogs/AndroidManifest.xml @@ -23,6 +23,9 @@ <uses-permission android:name="android.permission.CONTROL_ALWAYS_ON_VPN" /> <uses-permission android:name="android.permission.HIDE_NON_SYSTEM_OVERLAY_WINDOWS"/> + <!-- Query all packages on device on R+ --> + <uses-permission android:name="android.permission.QUERY_ALL_PACKAGES" /> + <application android:label="VpnDialogs" android:allowBackup="false"> diff --git a/services/core/java/com/android/server/hdmi/HdmiCecMessageValidator.java b/services/core/java/com/android/server/hdmi/HdmiCecMessageValidator.java index e65614307368..fe97f701e089 100644 --- a/services/core/java/com/android/server/hdmi/HdmiCecMessageValidator.java +++ b/services/core/java/com/android/server/hdmi/HdmiCecMessageValidator.java @@ -122,7 +122,25 @@ public class HdmiCecMessageValidator { addValidationInfo(Constants.MESSAGE_RECORD_STATUS, new RecordStatusInfoValidator(), DEST_DIRECT); - // TODO: Handle messages for the Timer Programming. + addValidationInfo( + Constants.MESSAGE_CLEAR_ANALOG_TIMER, new AnalogueTimerValidator(), DEST_DIRECT); + addValidationInfo( + Constants.MESSAGE_CLEAR_DIGITAL_TIMER, new DigitalTimerValidator(), DEST_DIRECT); + addValidationInfo( + Constants.MESSAGE_CLEAR_EXTERNAL_TIMER, new ExternalTimerValidator(), DEST_DIRECT); + addValidationInfo( + Constants.MESSAGE_SET_ANALOG_TIMER, new AnalogueTimerValidator(), DEST_DIRECT); + addValidationInfo( + Constants.MESSAGE_SET_DIGITAL_TIMER, new DigitalTimerValidator(), DEST_DIRECT); + addValidationInfo( + Constants.MESSAGE_SET_EXTERNAL_TIMER, new ExternalTimerValidator(), DEST_DIRECT); + addValidationInfo( + Constants.MESSAGE_SET_TIMER_PROGRAM_TITLE, new AsciiValidator(1, 14), DEST_DIRECT); + addValidationInfo( + Constants.MESSAGE_TIMER_CLEARED_STATUS, + new TimerClearedStatusValidator(), + DEST_DIRECT); + addValidationInfo(Constants.MESSAGE_TIMER_STATUS, new TimerStatusValidator(), DEST_DIRECT); // Messages for the System Information. FixedLengthValidator oneByteValidator = new FixedLengthValidator(1); @@ -415,6 +433,205 @@ public class HdmiCecMessageValidator { return (Integer.bitCount(value) <= 1); } + /** + * Check if the given value is a valid analogue broadcast type. A valid value is one which falls + * within the range description defined in CEC 1.4 Specification : Operand Descriptions (Section + * 17) + * + * @param value analogue broadcast type + * @return true if the analogue broadcast type is valid + */ + private boolean isValidAnalogueBroadcastType(int value) { + return isWithinRange(value, 0x00, 0x02); + } + + /** + * Check if the given value is a valid analogue frequency. A valid value is one which falls + * within the range description defined in CEC 1.4 Specification : Operand Descriptions (Section + * 17) + * + * @param value analogue frequency + * @return true if the analogue frequency is valid + */ + private boolean isValidAnalogueFrequency(int value) { + value = value & 0xFFFF; + return (value != 0x000 && value != 0xFFFF); + } + + /** + * Check if the given value is a valid broadcast system. A valid value is one which falls within + * the range description defined in CEC 1.4 Specification : Operand Descriptions (Section 17) + * + * @param value broadcast system + * @return true if the broadcast system is valid + */ + private boolean isValidBroadcastSystem(int value) { + return isWithinRange(value, 0, 31); + } + + /** + * Check if the given value is a ARIB type. A valid value is one which falls within the range + * description defined in CEC 1.4 Specification : Operand Descriptions (Section 17) + * + * @param value Digital Broadcast System + * @return true if the Digital Broadcast System is ARIB type + */ + private boolean isAribDbs(int value) { + return (value == 0x00 || isWithinRange(value, 0x08, 0x0A)); + } + + /** + * Check if the given value is a ATSC type. A valid value is one which falls within the range + * description defined in CEC 1.4 Specification : Operand Descriptions (Section 17) + * + * @param value Digital Broadcast System + * @return true if the Digital Broadcast System is ATSC type + */ + private boolean isAtscDbs(int value) { + return (value == 0x01 || isWithinRange(value, 0x10, 0x12)); + } + + /** + * Check if the given value is a DVB type. A valid value is one which falls within the range + * description defined in CEC 1.4 Specification : Operand Descriptions (Section 17) + * + * @param value Digital Broadcast System + * @return true if the Digital Broadcast System is DVB type + */ + private boolean isDvbDbs(int value) { + return (value == 0x02 || isWithinRange(value, 0x18, 0x1B)); + } + + /** + * Check if the given value is a valid Digital Broadcast System. A valid value is one which + * falls within the range description defined in CEC 1.4 Specification : Operand Descriptions + * (Section 17) + * + * @param value Digital Broadcast System + * @return true if the Digital Broadcast System is valid + */ + private boolean isValidDigitalBroadcastSystem(int value) { + return (isAribDbs(value) || isAtscDbs(value) || isDvbDbs(value)); + } + + /** + * Check if the given value is a valid Digital Service Identification. A valid value is one + * which falls within the range description defined in CEC 1.4 Specification : Operand + * Descriptions (Section 17) + * + * @param params Digital Timer Message parameters + * @param offset start offset of Digital Service Identification + * @return true if the Digital Service Identification is valid + */ + private boolean isValidDigitalServiceIdentification(byte[] params, int offset) { + // MSB contains Service Identification Method + int serviceIdentificationMethod = params[offset] & 0x80; + // Last 7 bits contains Digital Broadcast System + int digitalBroadcastSystem = params[offset] & 0x7F; + offset = offset + 1; + if (serviceIdentificationMethod == 0x00) { + // Services identified by Digital IDs + if (isAribDbs(digitalBroadcastSystem)) { + // Validate ARIB type have 6 byte data + return params.length - offset >= 6; + } else if (isAtscDbs(digitalBroadcastSystem)) { + // Validate ATSC type have 4 byte data + return params.length - offset >= 4; + } else if (isDvbDbs(digitalBroadcastSystem)) { + // Validate DVB type have 6 byte data + return params.length - offset >= 6; + } + } else if (serviceIdentificationMethod == 0x80) { + // Services identified by Channel + if (isValidDigitalBroadcastSystem(digitalBroadcastSystem)) { + // First 6 bits contain Channel Number Format + int channelNumberFormat = params[offset] & 0xFC; + if (channelNumberFormat == 0x04) { + // Validate it contains 1-part Channel Number data (16 bits) + return params.length - offset >= 3; + } else if (channelNumberFormat == 0x08) { + // Validate it contains Major Channel Number and Minor Channel Number (26 bits) + return params.length - offset >= 4; + } + } + } + return false; + } + + /** + * Check if the given value is a valid External Plug. A valid value is one which falls within + * the range description defined in CEC 1.4 Specification : Operand Descriptions (Section 17) + * + * @param value External Plug + * @return true if the External Plug is valid + */ + private boolean isValidExternalPlug(int value) { + return isWithinRange(value, 1, 255); + } + + /** + * Check if the given value is a valid External Source. A valid value is one which falls within + * the range description defined in CEC 1.4 Specification : Operand Descriptions (Section 17) + * + * @param value External Source Specifier + * @return true if the External Source is valid + */ + private boolean isValidExternalSource(byte[] params, int offset) { + int externalSourceSpecifier = params[offset]; + offset = offset + 1; + if (externalSourceSpecifier == 0x04) { + // External Plug + return isValidExternalPlug(params[offset]); + } else if (externalSourceSpecifier == 0x05) { + // External Physical Address + // Validate it contains 2 bytes Physical Address + if (params.length - offset >= 2) { + return isValidPhysicalAddress(params, offset); + } + } + return false; + } + + private boolean isValidProgrammedInfo(int programedInfo) { + return (isWithinRange(programedInfo, 0x00, 0x0B)); + } + + private boolean isValidNotProgrammedErrorInfo(int nonProgramedErrorInfo) { + return (isWithinRange(nonProgramedErrorInfo, 0x00, 0x0E)); + } + + private boolean isValidTimerStatusData(byte[] params, int offset) { + int programedIndicator = params[offset] & 0x10; + boolean durationAvailable = false; + if (programedIndicator == 0x10) { + // Programmed + int programedInfo = params[offset] & 0x0F; + if (isValidProgrammedInfo(programedInfo)) { + if (programedInfo == 0x09 || programedInfo == 0x0B) { + durationAvailable = true; + } else { + return true; + } + } + } else { + // Non programmed + int nonProgramedErrorInfo = params[offset] & 0x0F; + if (isValidNotProgrammedErrorInfo(nonProgramedErrorInfo)) { + if (nonProgramedErrorInfo == 0x0E) { + durationAvailable = true; + } else { + return true; + } + } + } + offset = offset + 1; + // Duration Available (2 bytes) + if (durationAvailable && params.length - offset >= 2) { + return (isValidDurationHours(params[offset]) && isValidMinute(params[offset + 1])); + } + return false; + } + private class PhysicalAddressValidator implements ParameterValidator { @Override public int isValid(byte[] params) { @@ -544,4 +761,106 @@ public class HdmiCecMessageValidator { return toErrorCode(isWithinRange(params[0], mMinValue, mMaxValue)); } } + + /** + * Check if the given Analogue Timer message parameters are valid. Valid parameters should + * adhere to message description of Analogue Timer defined in CEC 1.4 Specification : Message + * Descriptions for Timer Programming Feature (CEC Table 12) + */ + private class AnalogueTimerValidator implements ParameterValidator { + @Override + public int isValid(byte[] params) { + if (params.length < 11) { + return ERROR_PARAMETER_SHORT; + } + return toErrorCode( + isValidDayOfMonth(params[0]) // Day of Month + && isValidMonthOfYear(params[1]) // Month of Year + && isValidHour(params[2]) // Start Time - Hour + && isValidMinute(params[3]) // Start Time - Minute + && isValidDurationHours(params[4]) // Duration - Duration Hours + && isValidMinute(params[5]) // Duration - Minute + && isValidRecordingSequence(params[6]) // Recording Sequence + && isValidAnalogueBroadcastType(params[7]) // Analogue Broadcast Type + && isValidAnalogueFrequency( + HdmiUtils.twoBytesToInt(params, 8)) // Analogue Frequency + && isValidBroadcastSystem(params[10])); // Broadcast System + } + } + + /** + * Check if the given Digital Timer message parameters are valid. Valid parameters should adhere + * to message description of Digital Timer defined in CEC 1.4 Specification : Message + * Descriptions for Timer Programming Feature (CEC Table 12) + */ + private class DigitalTimerValidator implements ParameterValidator { + @Override + public int isValid(byte[] params) { + if (params.length < 11) { + return ERROR_PARAMETER_SHORT; + } + return toErrorCode( + isValidDayOfMonth(params[0]) // Day of Month + && isValidMonthOfYear(params[1]) // Month of Year + && isValidHour(params[2]) // Start Time - Hour + && isValidMinute(params[3]) // Start Time - Minute + && isValidDurationHours(params[4]) // Duration - Duration Hours + && isValidMinute(params[5]) // Duration - Minute + && isValidRecordingSequence(params[6]) // Recording Sequence + && isValidDigitalServiceIdentification( + params, 7)); // Digital Service Identification + } + } + + /** + * Check if the given External Timer message parameters are valid. Valid parameters should + * adhere to message description of External Timer defined in CEC 1.4 Specification : Message + * Descriptions for Timer Programming Feature (CEC Table 12) + */ + private class ExternalTimerValidator implements ParameterValidator { + @Override + public int isValid(byte[] params) { + if (params.length < 9) { + return ERROR_PARAMETER_SHORT; + } + return toErrorCode( + isValidDayOfMonth(params[0]) // Day of Month + && isValidMonthOfYear(params[1]) // Month of Year + && isValidHour(params[2]) // Start Time - Hour + && isValidMinute(params[3]) // Start Time - Minute + && isValidDurationHours(params[4]) // Duration - Duration Hours + && isValidMinute(params[5]) // Duration - Minute + && isValidRecordingSequence(params[6]) // Recording Sequence + && isValidExternalSource(params, 7)); // External Source + } + } + + /** + * Check if the given timer cleared status parameter is valid. A valid parameter should lie + * within the range description defined in CEC 1.4 Specification : Operand Descriptions + * (Section 17) + */ + private class TimerClearedStatusValidator implements ParameterValidator { + @Override + public int isValid(byte[] params) { + if (params.length < 1) { + return ERROR_PARAMETER_SHORT; + } + return toErrorCode(isWithinRange(params[0], 0x00, 0x02) || (params[0] & 0xFF) == 0x80); + } + } + + /** + * Check if the given timer status data parameter is valid. A valid parameter should lie within + * the range description defined in CEC 1.4 Specification : Operand Descriptions (Section 17) + */ + private class TimerStatusValidator implements ParameterValidator { + @Override + public int isValid(byte[] params) { + if (params.length < 1) { + return ERROR_PARAMETER_SHORT; + } + return toErrorCode(isValidTimerStatusData(params, 0)); + } + } } diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java index f495cc00bf31..b5c5bb52d050 100644 --- a/services/java/com/android/server/SystemServer.java +++ b/services/java/com/android/server/SystemServer.java @@ -1232,7 +1232,7 @@ public final class SystemServer { mSystemServiceManager.startService(IorapForwardingService.class); t.traceEnd(); - if (Build.IS_DEBUGGABLE) { + if (Build.IS_DEBUGGABLE && ProfcollectForwardingService.enabled()) { t.traceBegin("ProfcollectForwardingService"); mSystemServiceManager.startService(ProfcollectForwardingService.class); t.traceEnd(); diff --git a/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java b/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java index d14ed5a15cf9..19449654f2ec 100644 --- a/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java +++ b/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java @@ -31,6 +31,7 @@ import android.os.ServiceManager; import android.os.SystemProperties; import android.os.UpdateEngine; import android.os.UpdateEngineCallback; +import android.provider.DeviceConfig; import android.util.Log; import com.android.server.IoThread; @@ -68,6 +69,14 @@ public final class ProfcollectForwardingService extends SystemService { sSelfService = this; } + /** + * Check whether profcollect is enabled through device config. + */ + public static boolean enabled() { + return DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_PROFCOLLECT_NATIVE_BOOT, "enabled", + false); + } + @Override public void onStart() { if (DEBUG) { diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecMessageValidatorTest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecMessageValidatorTest.java index 470294073535..553df3bafd00 100644 --- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecMessageValidatorTest.java +++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecMessageValidatorTest.java @@ -130,6 +130,17 @@ public class HdmiCecMessageValidatorTest { } @Test + public void isValid_setTimerProgramTitle() { + assertMessageValidity("40:67:47:61:6D:65:20:6F:66:20:54:68:72:6F:6E:65:73").isEqualTo(OK); + assertMessageValidity("40:67:4A").isEqualTo(OK); + + assertMessageValidity("4F:67:47:4F:54").isEqualTo(ERROR_DESTINATION); + assertMessageValidity("F4:67:47:4F:54").isEqualTo(ERROR_SOURCE); + assertMessageValidity("40:67").isEqualTo(ERROR_PARAMETER_SHORT); + assertMessageValidity("40:67:47:9A:54").isEqualTo(ERROR_PARAMETER); + } + + @Test public void isValid_setMenuLanguage() { assertMessageValidity("4F:32:53:50:41").isEqualTo(OK); assertMessageValidity("0F:32:45:4E:47:8C:49:D3:48").isEqualTo(OK); @@ -182,6 +193,166 @@ public class HdmiCecMessageValidatorTest { assertMessageValidity("40:0A:30").isEqualTo(ERROR_PARAMETER); } + @Test + public void isValid_setAnalogueTimer_clearAnalogueTimer() { + assertMessageValidity("04:33:0C:08:10:1E:04:30:08:00:13:AD:06").isEqualTo(OK); + assertMessageValidity("04:34:04:0C:16:0F:08:37:00:02:EA:60:03:34").isEqualTo(OK); + + assertMessageValidity("0F:33:0C:08:10:1E:04:30:08:00:13:AD:06") + .isEqualTo(ERROR_DESTINATION); + assertMessageValidity("F0:34:04:0C:16:0F:08:37:00:02:EA:60:03").isEqualTo(ERROR_SOURCE); + assertMessageValidity("04:33:0C:08:10:1E:04:30:08:13:AD:06") + .isEqualTo(ERROR_PARAMETER_SHORT); + // Out of range Day of Month + assertMessageValidity("04:34:20:0C:16:0F:08:37:00:02:EA:60:03").isEqualTo(ERROR_PARAMETER); + // Out of range Month of Year + assertMessageValidity("04:33:0C:00:10:1E:04:30:08:00:13:AD:06").isEqualTo(ERROR_PARAMETER); + // Out of range Start Time - Hour + assertMessageValidity("04:34:04:0C:18:0F:08:37:00:02:EA:60:03").isEqualTo(ERROR_PARAMETER); + // Out of range Start Time - Minute + assertMessageValidity("04:33:0C:08:10:50:04:30:08:00:13:AD:06").isEqualTo(ERROR_PARAMETER); + // Out of range Duration - Duration Hours + assertMessageValidity("04:34:04:0C:16:0F:64:37:00:02:EA:60:03").isEqualTo(ERROR_PARAMETER); + // Out of range Duration - Minute + assertMessageValidity("04:33:0C:08:10:1E:04:64:08:00:13:AD:06").isEqualTo(ERROR_PARAMETER); + // Invalid Recording Sequence + assertMessageValidity("04:34:04:0C:16:0F:08:37:88:02:EA:60:03").isEqualTo(ERROR_PARAMETER); + // Invalid Recording Sequence + assertMessageValidity("04:33:0C:08:10:1E:04:30:A2:00:13:AD:06").isEqualTo(ERROR_PARAMETER); + // Out of range Analogue Broadcast Type + assertMessageValidity("04:34:04:0C:16:0F:08:37:00:03:EA:60:03").isEqualTo(ERROR_PARAMETER); + // Out of range Analogue Frequency + assertMessageValidity("04:33:0C:08:10:1E:04:30:08:00:FF:FF:06").isEqualTo(ERROR_PARAMETER); + // Out of range Broadcast System + assertMessageValidity("04:34:04:0C:16:0F:08:37:00:02:EA:60:20").isEqualTo(ERROR_PARAMETER); + } + + @Test + public void isValid_setDigitalTimer_clearDigitalTimer() { + // Services identified by Digital IDs - ARIB Broadcast System + assertMessageValidity("04:99:0C:08:15:05:04:1E:00:00:C4:C2:11:D8:75:30").isEqualTo(OK); + // Service identified by Digital IDs - ATSC Broadcast System + assertMessageValidity("04:97:1E:07:12:20:50:28:01:01:8B:5E:39:5A").isEqualTo(OK); + // Service identified by Digital IDs - DVB Broadcast System + assertMessageValidity("04:99:05:0C:06:0A:19:3B:40:19:8B:44:03:11:04:FC").isEqualTo(OK); + // Service identified by Channel - 1 part channel number + assertMessageValidity("04:97:12:06:0C:2D:5A:19:08:91:04:00:B1").isEqualTo(OK); + // Service identified by Channel - 2 part channel number + assertMessageValidity("04:99:15:09:00:0F:00:2D:04:82:09:C8:72:C8").isEqualTo(OK); + + assertMessageValidity("4F:97:0C:08:15:05:04:1E:00:00:C4:C2:11:D8:75:30") + .isEqualTo(ERROR_DESTINATION); + assertMessageValidity("F0:99:15:09:00:0F:00:2D:04:82:09:C8:72:C8").isEqualTo(ERROR_SOURCE); + assertMessageValidity("04:97:1E:12:20:58:01:01:8B:5E:39:5A") + .isEqualTo(ERROR_PARAMETER_SHORT); + // Out of range Day of Month + assertMessageValidity("04:99:24:0C:06:0A:19:3B:40:19:8B:44:03:11:04:FC") + .isEqualTo(ERROR_PARAMETER); + // Out of range Month of Year + assertMessageValidity("04:97:12:10:0C:2D:5A:19:08:91:04:00:B1").isEqualTo(ERROR_PARAMETER); + // Out of range Start Time - Hour + assertMessageValidity("04:99:0C:08:20:05:04:1E:00:00:C4:C2:11:D8:75:30") + .isEqualTo(ERROR_PARAMETER); + // Out of range Start Time - Minute + assertMessageValidity("04:97:15:09:00:4B:00:2D:04:82:09:C8:72:C8") + .isEqualTo(ERROR_PARAMETER); + // Out of range Duration - Duration Hours + assertMessageValidity("04:99:1E:07:12:20:78:28:01:01:8B:5E:39:5A") + .isEqualTo(ERROR_PARAMETER); + // Out of range Duration - Minute + assertMessageValidity("04:97:05:0C:06:0A:19:48:40:19:8B:44:03:11:04:FC") + .isEqualTo(ERROR_PARAMETER); + // Invalid Recording Sequence + assertMessageValidity("04:99:12:06:0C:2D:5A:19:90:91:04:00:B1").isEqualTo(ERROR_PARAMETER); + // Invalid Recording Sequence + assertMessageValidity("04:97:0C:08:15:05:04:1E:21:00:C4:C2:11:D8:75:30") + .isEqualTo(ERROR_PARAMETER); + + // Invalid Digital Broadcast System + assertMessageValidity("04:99:1E:07:12:20:50:28:01:04:8B:5E:39:5A") + .isEqualTo(ERROR_PARAMETER); + // Invalid Digital Broadcast System + assertMessageValidity("04:97:05:0C:06:0A:19:3B:40:93:8B:44:03:11:04:FC") + .isEqualTo(ERROR_PARAMETER); + // Insufficient data for ARIB Broadcast system + assertMessageValidity("04:99:0C:08:15:05:04:1E:00:00:C4:C2:11:D8:75") + .isEqualTo(ERROR_PARAMETER); + // Insufficient data for ATSC Broadcast system + assertMessageValidity("04:97:1E:07:12:20:50:28:01:01:8B:5E:39").isEqualTo(ERROR_PARAMETER); + // Insufficient data for DVB Broadcast system + assertMessageValidity("04:99:05:0C:06:0A:19:3B:40:19:8B:44:03:11:04") + .isEqualTo(ERROR_PARAMETER); + // Insufficient data for 2 part channel number + assertMessageValidity("04:97:15:09:00:0F:00:2D:04:82:09:C8:72").isEqualTo(ERROR_PARAMETER); + // Invalid Channel Number format + assertMessageValidity("04:99:12:06:0C:2D:5A:19:08:91:0D:00:B1").isEqualTo(ERROR_PARAMETER); + } + + @Test + public void isValid_setExternalTimer_clearExternalTimer() { + assertMessageValidity("40:A1:0C:08:15:05:04:1E:02:04:20").isEqualTo(OK); + assertMessageValidity("40:A2:14:09:12:28:4B:19:10:05:10:00").isEqualTo(OK); + + assertMessageValidity("4F:A1:0C:08:15:05:04:1E:02:04:20").isEqualTo(ERROR_DESTINATION); + assertMessageValidity("F4:A2:14:09:12:28:4B:19:10:05:10:00").isEqualTo(ERROR_SOURCE); + assertMessageValidity("40:A1:0C:08:15:05:04:1E:02:04").isEqualTo(ERROR_PARAMETER_SHORT); + // Out of range Day of Month + assertMessageValidity("40:A2:28:09:12:28:4B:19:10:05:10:00").isEqualTo(ERROR_PARAMETER); + // Out of range Month of Year + assertMessageValidity("40:A1:0C:0F:15:05:04:1E:02:04:20").isEqualTo(ERROR_PARAMETER); + // Out of range Start Time - Hour + assertMessageValidity("40:A2:14:09:1A:28:4B:19:10:05:10:00").isEqualTo(ERROR_PARAMETER); + // Out of range Start Time - Minute + assertMessageValidity("40:A1:0C:08:15:48:04:1E:02:04:20").isEqualTo(ERROR_PARAMETER); + // Out of range Duration - Duration Hours + assertMessageValidity("40:A2:14:09:12:28:66:19:10:05:10:00").isEqualTo(ERROR_PARAMETER); + // Out of range Duration - Minute + assertMessageValidity("40:A1:0C:08:15:05:04:3F:02:04:20").isEqualTo(ERROR_PARAMETER); + // Invalid Recording Sequence + assertMessageValidity("40:A2:14:09:12:28:4B:19:84:05:10:00").isEqualTo(ERROR_PARAMETER); + // Invalid Recording Sequence + assertMessageValidity("40:A1:0C:08:15:05:04:1E:14:04:20").isEqualTo(ERROR_PARAMETER); + // Invalid external source specifier + assertMessageValidity("40:A2:14:09:12:28:4B:19:10:08:10:00").isEqualTo(ERROR_PARAMETER); + // Invalid External PLug + assertMessageValidity("04:A1:0C:08:15:05:04:1E:02:04:00").isEqualTo(ERROR_PARAMETER); + } + + @Test + public void isValid_timerClearedStatus() { + assertMessageValidity("40:43:01:7E").isEqualTo(OK); + assertMessageValidity("40:43:80").isEqualTo(OK); + + assertMessageValidity("4F:43:01").isEqualTo(ERROR_DESTINATION); + assertMessageValidity("F0:43:80").isEqualTo(ERROR_SOURCE); + assertMessageValidity("40:43").isEqualTo(ERROR_PARAMETER_SHORT); + assertMessageValidity("40:43:03").isEqualTo(ERROR_PARAMETER); + } + + @Test + public void isValid_timerStatus() { + // Programmed - Space available + assertMessageValidity("40:35:58").isEqualTo(OK); + // Programmed - Not enough space available + assertMessageValidity("40:35:B9:32:1C:4F").isEqualTo(OK); + // Not programmed - Date out of range + assertMessageValidity("40:35:82:3B").isEqualTo(OK); + // Not programmed - Duplicate + assertMessageValidity("40:35:EE:52:0C").isEqualTo(OK); + + assertMessageValidity("4F:35:58").isEqualTo(ERROR_DESTINATION); + assertMessageValidity("F0:35:82").isEqualTo(ERROR_SOURCE); + assertMessageValidity("40:35").isEqualTo(ERROR_PARAMETER_SHORT); + // Programmed - Invalid programmed info + assertMessageValidity("40:35:BD").isEqualTo(ERROR_PARAMETER); + // Non programmed - Invalid not programmed error info + assertMessageValidity("40:35:DE").isEqualTo(ERROR_PARAMETER); + // Programmed - Might not be enough space available - Invalid duration hours + assertMessageValidity("40:35:BB:96:1C").isEqualTo(ERROR_PARAMETER); + // Not programmed - Duplicate - Invalid duration minutes + assertMessageValidity("40:35:EE:52:4A").isEqualTo(ERROR_PARAMETER); + } + private IntegerSubject assertMessageValidity(String message) { return assertThat(mHdmiCecMessageValidator.isValid(buildMessage(message))); } diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java index 95fb84e55b09..06363b038521 100644 --- a/telephony/java/android/telephony/TelephonyManager.java +++ b/telephony/java/android/telephony/TelephonyManager.java @@ -305,6 +305,8 @@ public class TelephonyManager { private static boolean sServiceHandleCacheEnabled = true; @GuardedBy("sCacheLock") + private static ITelephony sITelephony; + @GuardedBy("sCacheLock") private static IPhoneSubInfo sIPhoneSubInfo; @GuardedBy("sCacheLock") private static ISub sISub; @@ -4185,7 +4187,7 @@ public class TelephonyManager { } } - /** + /** * @param keyAvailability bitmask that defines the availabilty of keys for a type. * @param keyType the key type which is being checked. (WLAN, EPDG) * @return true if the digit at position keyType is 1, else false. @@ -5504,13 +5506,39 @@ public class TelephonyManager { } } - /** - * @hide - */ + /** + * @hide + */ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) private ITelephony getITelephony() { - return ITelephony.Stub.asInterface(TelephonyFrameworkInitializer - .getTelephonyServiceManager().getTelephonyServiceRegisterer().get()); + // Keeps cache disabled until test fixes are checked into AOSP. + if (!sServiceHandleCacheEnabled) { + return ITelephony.Stub.asInterface( + TelephonyFrameworkInitializer + .getTelephonyServiceManager() + .getTelephonyServiceRegisterer() + .get()); + } + + if (sITelephony == null) { + ITelephony temp = ITelephony.Stub.asInterface( + TelephonyFrameworkInitializer + .getTelephonyServiceManager() + .getTelephonyServiceRegisterer() + .get()); + synchronized (sCacheLock) { + if (sITelephony == null && temp != null) { + try { + sITelephony = temp; + sITelephony.asBinder().linkToDeath(sServiceDeath, 0); + } catch (Exception e) { + // something has gone horribly wrong + sITelephony = null; + } + } + } + } + return sITelephony; } private IOns getIOns() { @@ -13444,6 +13472,10 @@ public class TelephonyManager { */ private static void resetServiceCache() { synchronized (sCacheLock) { + if (sITelephony != null) { + sITelephony.asBinder().unlinkToDeath(sServiceDeath, 0); + sITelephony = null; + } if (sISub != null) { sISub.asBinder().unlinkToDeath(sServiceDeath, 0); sISub = null; @@ -13460,9 +13492,9 @@ public class TelephonyManager { } } - /** - * @hide - */ + /** + * @hide + */ static IPhoneSubInfo getSubscriberInfoService() { // Keeps cache disabled until test fixes are checked into AOSP. if (!sServiceHandleCacheEnabled) { diff --git a/telephony/java/android/telephony/ims/ImsRcsManager.java b/telephony/java/android/telephony/ims/ImsRcsManager.java index 94407f1dcd3a..8b6dac82b0eb 100644 --- a/telephony/java/android/telephony/ims/ImsRcsManager.java +++ b/telephony/java/android/telephony/ims/ImsRcsManager.java @@ -29,12 +29,10 @@ import android.os.RemoteException; import android.provider.Settings; import android.telephony.AccessNetworkConstants; import android.telephony.CarrierConfigManager; -import android.telephony.SubscriptionManager; import android.telephony.TelephonyFrameworkInitializer; import android.telephony.ims.aidl.IImsCapabilityCallback; import android.telephony.ims.aidl.IImsRcsController; import android.telephony.ims.feature.ImsFeature; -import android.telephony.ims.feature.RcsFeature; import android.telephony.ims.stub.ImsRegistrationImplBase; import android.util.Log; @@ -77,7 +75,7 @@ public class ImsRcsManager { "android.telephony.ims.action.SHOW_CAPABILITY_DISCOVERY_OPT_IN"; /** - * Receives RCS availability status updates from the ImsService. + * Receives RCS Feature availability status updates from the ImsService. * * @see #isAvailable(int) * @see #registerRcsAvailabilityCallback(Executor, AvailabilityCallback) @@ -101,8 +99,7 @@ public class ImsRcsManager { long callingIdentity = Binder.clearCallingIdentity(); try { - mExecutor.execute(() -> mLocalCallback.onAvailabilityChanged( - new RcsFeature.RcsImsCapabilities(config))); + mExecutor.execute(() -> mLocalCallback.onAvailabilityChanged(config)); } finally { restoreCallingIdentity(callingIdentity); } @@ -137,7 +134,7 @@ public class ImsRcsManager { * * @param capabilities The new availability of the capabilities. */ - public void onAvailabilityChanged(@NonNull RcsFeature.RcsImsCapabilities capabilities) { + public void onAvailabilityChanged(@RcsUceAdapter.RcsImsCapabilityFlag int capabilities) { } /**@hide*/ @@ -394,7 +391,7 @@ public class ImsRcsManager { * @hide */ @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) - public boolean isCapable(@RcsFeature.RcsImsCapabilities.RcsImsCapabilityFlag int capability, + public boolean isCapable(@RcsUceAdapter.RcsImsCapabilityFlag int capability, @ImsRegistrationImplBase.ImsRegistrationTech int radioTech) throws ImsException { IImsRcsController imsRcsController = getIImsRcsController(); if (imsRcsController == null) { @@ -428,7 +425,7 @@ public class ImsRcsManager { * @hide */ @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) - public boolean isAvailable(@RcsFeature.RcsImsCapabilities.RcsImsCapabilityFlag int capability) + public boolean isAvailable(@RcsUceAdapter.RcsImsCapabilityFlag int capability) throws ImsException { IImsRcsController imsRcsController = getIImsRcsController(); if (imsRcsController == null) { diff --git a/telephony/java/android/telephony/ims/RcsContactTerminatedReason.aidl b/telephony/java/android/telephony/ims/RcsContactTerminatedReason.aidl new file mode 100644 index 000000000000..cd1ee8400d3e --- /dev/null +++ b/telephony/java/android/telephony/ims/RcsContactTerminatedReason.aidl @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +package android.telephony.ims; + +parcelable RcsContactTerminatedReason; diff --git a/telephony/java/android/telephony/ims/RcsContactTerminatedReason.java b/telephony/java/android/telephony/ims/RcsContactTerminatedReason.java new file mode 100644 index 000000000000..ee02564267c0 --- /dev/null +++ b/telephony/java/android/telephony/ims/RcsContactTerminatedReason.java @@ -0,0 +1,75 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.telephony.ims; + +import android.annotation.NonNull; +import android.net.Uri; +import android.os.Parcel; +import android.os.Parcelable; + +/** + * When the resource for the presence subscribe event has been terminated, the method + * SubscribeResponseCallback#onResourceTerminated wil be called with a list of + * RcsContactTerminatedReason. + * @hide + */ +public final class RcsContactTerminatedReason implements Parcelable { + private final Uri mContactUri; + private final String mReason; + + public RcsContactTerminatedReason(Uri contact, String reason) { + mContactUri = contact; + mReason = reason; + } + + private RcsContactTerminatedReason(Parcel in) { + mContactUri = in.readParcelable(Uri.class.getClassLoader()); + mReason = in.readString(); + } + + @Override + public void writeToParcel(@NonNull Parcel out, int flags) { + out.writeParcelable(mContactUri, flags); + out.writeString(mReason); + } + + @Override + public int describeContents() { + return 0; + } + + public static final @NonNull Creator<RcsContactTerminatedReason> CREATOR = + new Creator<RcsContactTerminatedReason>() { + @Override + public RcsContactTerminatedReason createFromParcel(Parcel in) { + return new RcsContactTerminatedReason(in); + } + + @Override + public RcsContactTerminatedReason[] newArray(int size) { + return new RcsContactTerminatedReason[size]; + } + }; + + public Uri getContactUri() { + return mContactUri; + } + + public String getReason() { + return mReason; + } +} diff --git a/telephony/java/android/telephony/ims/RcsUceAdapter.java b/telephony/java/android/telephony/ims/RcsUceAdapter.java index 0c88ade4bb77..0aeaecc2af5e 100644 --- a/telephony/java/android/telephony/ims/RcsUceAdapter.java +++ b/telephony/java/android/telephony/ims/RcsUceAdapter.java @@ -47,6 +47,30 @@ public class RcsUceAdapter { private static final String TAG = "RcsUceAdapter"; /** + * This carrier supports User Capability Exchange as, defined by the framework using + * SIP OPTIONS. If set, the RcsFeature should support capability exchange. If not set, this + * RcsFeature should not publish capabilities or service capability requests. + * @hide + */ + public static final int CAPABILITY_TYPE_OPTIONS_UCE = 1 << 0; + + /** + * This carrier supports User Capability Exchange as, defined by the framework using a + * presence server. If set, the RcsFeature should support capability exchange. If not set, this + * RcsFeature should not publish capabilities or service capability requests. + * @hide + */ + public static final int CAPABILITY_TYPE_PRESENCE_UCE = 1 << 1; + + /**@hide*/ + @Retention(RetentionPolicy.SOURCE) + @IntDef(prefix = "CAPABILITY_TYPE_", value = { + CAPABILITY_TYPE_OPTIONS_UCE, + CAPABILITY_TYPE_PRESENCE_UCE + }) + public @interface RcsImsCapabilityFlag {} + + /** * An unknown error has caused the request to fail. * @hide */ @@ -106,11 +130,6 @@ public class RcsUceAdapter { * @hide */ public static final int ERROR_LOST_NETWORK = 12; - /** - * The request has failed because the same request has already been added to the queue. - * @hide - */ - public static final int ERROR_ALREADY_IN_QUEUE = 13; /**@hide*/ @Retention(RetentionPolicy.SOURCE) @@ -125,12 +144,90 @@ public class RcsUceAdapter { ERROR_REQUEST_TOO_LARGE, ERROR_REQUEST_TIMEOUT, ERROR_INSUFFICIENT_MEMORY, - ERROR_LOST_NETWORK, - ERROR_ALREADY_IN_QUEUE + ERROR_LOST_NETWORK }) public @interface ErrorCode {} /** + * A capability update has been requested due to the Entity Tag (ETag) expiring. + * @hide + */ + public static final int CAPABILITY_UPDATE_TRIGGER_ETAG_EXPIRED = 0; + /** + * A capability update has been requested due to moving to LTE with VoPS disabled. + * @hide + */ + public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_LTE_VOPS_DISABLED = 1; + /** + * A capability update has been requested due to moving to LTE with VoPS enabled. + * @hide + */ + public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_LTE_VOPS_ENABLED = 2; + /** + * A capability update has been requested due to moving to eHRPD. + * @hide + */ + public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_EHRPD = 3; + /** + * A capability update has been requested due to moving to HSPA+. + * @hide + */ + public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_HSPAPLUS = 4; + /** + * A capability update has been requested due to moving to 3G. + * @hide + */ + public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_3G = 5; + /** + * A capability update has been requested due to moving to 2G. + * @hide + */ + public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_2G = 6; + /** + * A capability update has been requested due to moving to WLAN + * @hide + */ + public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_WLAN = 7; + /** + * A capability update has been requested due to moving to IWLAN + * @hide + */ + public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_IWLAN = 8; + /** + * A capability update has been requested but the reason is unknown. + * @hide + */ + public static final int CAPABILITY_UPDATE_TRIGGER_UNKNOWN = 9; + /** + * A capability update has been requested due to moving to 5G NR with VoPS disabled. + * @hide + */ + public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_NR5G_VOPS_DISABLED = 10; + /** + * A capability update has been requested due to moving to 5G NR with VoPS enabled. + * @hide + */ + public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_NR5G_VOPS_ENABLED = 11; + + /**@hide*/ + @Retention(RetentionPolicy.SOURCE) + @IntDef(prefix = "ERROR_", value = { + CAPABILITY_UPDATE_TRIGGER_ETAG_EXPIRED, + CAPABILITY_UPDATE_TRIGGER_MOVE_TO_LTE_VOPS_DISABLED, + CAPABILITY_UPDATE_TRIGGER_MOVE_TO_LTE_VOPS_ENABLED, + CAPABILITY_UPDATE_TRIGGER_MOVE_TO_EHRPD, + CAPABILITY_UPDATE_TRIGGER_MOVE_TO_HSPAPLUS, + CAPABILITY_UPDATE_TRIGGER_MOVE_TO_3G, + CAPABILITY_UPDATE_TRIGGER_MOVE_TO_2G, + CAPABILITY_UPDATE_TRIGGER_MOVE_TO_WLAN, + CAPABILITY_UPDATE_TRIGGER_MOVE_TO_IWLAN, + CAPABILITY_UPDATE_TRIGGER_UNKNOWN, + CAPABILITY_UPDATE_TRIGGER_MOVE_TO_NR5G_VOPS_DISABLED, + CAPABILITY_UPDATE_TRIGGER_MOVE_TO_NR5G_VOPS_ENABLED + }) + public @interface StackPublishTriggerType {} + + /** * The last publish has resulted in a "200 OK" response or the device is using SIP OPTIONS for * UCE. * @hide @@ -205,7 +302,7 @@ public class RcsUceAdapter { public void onPublishStateChanged(int publishState) { if (mLocalCallback == null) return; - long callingIdentity = Binder.clearCallingIdentity(); + final long callingIdentity = Binder.clearCallingIdentity(); try { mExecutor.execute(() -> mLocalCallback.onChanged(publishState)); } finally { @@ -238,38 +335,49 @@ public class RcsUceAdapter { } /** - * Provides a one-time callback for the response to a UCE request. After this callback is called - * by the framework, the reference to this callback will be discarded on the service side. + * A callback for the response to a UCE request. The method + * {@link CapabilitiesCallback#onCapabilitiesReceived} will be called zero or more times as the + * capabilities are received for each requested contact. + * <p> + * This request will take a varying amount of time depending on if the contacts requested are + * cached or if it requires a network query. The timeout time of these requests can vary + * depending on the network, however in poor cases it could take up to a minute for a request + * to timeout. In that time only a subset of capabilities may have been retrieved. + * <p> + * After {@link CapabilitiesCallback#onComplete} or {@link CapabilitiesCallback#onError} has + * been called, the reference to this callback will be discarded on the service side. * @see #requestCapabilities(Executor, List, CapabilitiesCallback) * @hide */ - public static class CapabilitiesCallback { + public interface CapabilitiesCallback { /** - * Notify this application that the pending capability request has returned successfully. + * Notify this application that the pending capability request has returned successfully + * for one or more of the requested contacts. * @param contactCapabilities List of capabilities associated with each contact requested. */ - public void onCapabilitiesReceived( - @NonNull List<RcsContactUceCapability> contactCapabilities) { + void onCapabilitiesReceived(@NonNull List<RcsContactUceCapability> contactCapabilities); - } + /** + * The pending request has completed successfully due to all requested contacts information + * being delivered. + */ + void onComplete(); /** * The pending request has resulted in an error and may need to be retried, depending on the * error code. * @param errorCode The reason for the framework being unable to process the request. */ - public void onError(@ErrorCode int errorCode) { - - } + void onError(@ErrorCode int errorCode); } private final Context mContext; private final int mSubId; /** - * Not to be instantiated directly, use - * {@link ImsRcsManager#getUceAdapter()} to instantiate this manager class. + * Not to be instantiated directly, use {@link ImsRcsManager#getUceAdapter()} to instantiate + * this manager class. * @hide */ RcsUceAdapter(Context context, int subId) { @@ -280,6 +388,9 @@ public class RcsUceAdapter { /** * Request the User Capability Exchange capabilities for one or more contacts. * <p> + * This will return the cached capabilities of the contact and will not perform a capability + * poll on the network unless there are contacts being queried with stale information. + * <p> * Be sure to check the availability of this feature using * {@link ImsRcsManager#isAvailable(int)} and ensuring * {@link RcsFeature.RcsImsCapabilities#CAPABILITY_TYPE_OPTIONS_UCE} or @@ -302,7 +413,7 @@ public class RcsUceAdapter { @NonNull List<Uri> contactNumbers, @NonNull CapabilitiesCallback c) throws ImsException { if (c == null) { - throw new IllegalArgumentException("Must include a non-null AvailabilityCallback."); + throw new IllegalArgumentException("Must include a non-null CapabilitiesCallback."); } if (executor == null) { throw new IllegalArgumentException("Must include a non-null Executor."); @@ -321,7 +432,7 @@ public class RcsUceAdapter { IRcsUceControllerCallback internalCallback = new IRcsUceControllerCallback.Stub() { @Override public void onCapabilitiesReceived(List<RcsContactUceCapability> contactCapabilities) { - long callingIdentity = Binder.clearCallingIdentity(); + final long callingIdentity = Binder.clearCallingIdentity(); try { executor.execute(() -> c.onCapabilitiesReceived(contactCapabilities)); @@ -330,8 +441,17 @@ public class RcsUceAdapter { } } @Override + public void onComplete() { + final long callingIdentity = Binder.clearCallingIdentity(); + try { + executor.execute(() -> c.onComplete()); + } finally { + restoreCallingIdentity(callingIdentity); + } + } + @Override public void onError(int errorCode) { - long callingIdentity = Binder.clearCallingIdentity(); + final long callingIdentity = Binder.clearCallingIdentity(); try { executor.execute(() -> c.onError(errorCode)); } finally { @@ -351,6 +471,88 @@ public class RcsUceAdapter { } /** + * Ignore the device cache and perform a capability discovery for one contact, also called + * "availability fetch." + * <p> + * This will always perform a query to the network as long as requests are over the carrier + * availability fetch throttling threshold. If too many network requests are sent too quickly, + * #ERROR_TOO_MANY_REQUESTS will be returned. + * + * <p> + * Be sure to check the availability of this feature using + * {@link ImsRcsManager#isAvailable(int)} and ensuring + * {@link RcsFeature.RcsImsCapabilities#CAPABILITY_TYPE_OPTIONS_UCE} or + * {@link RcsFeature.RcsImsCapabilities#CAPABILITY_TYPE_PRESENCE_UCE} is + * enabled or else this operation will fail with + * {@link #ERROR_NOT_AVAILABLE} or {@link #ERROR_NOT_ENABLED}. + * + * @param contactNumber The contact of the capabilities is being requested for. + * @param c A one-time callback for when the request for capabilities completes or there is + * an error processing the request. + * @hide + */ + @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE) + public void requestNetworkAvailability(@NonNull @CallbackExecutor Executor executor, + @NonNull Uri contactNumber, @NonNull CapabilitiesCallback c) throws ImsException { + if (executor == null) { + throw new IllegalArgumentException("Must include a non-null Executor."); + } + if (contactNumber == null) { + throw new IllegalArgumentException("Must include non-null contact number."); + } + if (c == null) { + throw new IllegalArgumentException("Must include a non-null CapabilitiesCallback."); + } + + IImsRcsController imsRcsController = getIImsRcsController(); + if (imsRcsController == null) { + Log.e(TAG, "requestNetworkAvailability: IImsRcsController is null"); + throw new ImsException("Cannot find remote IMS service", + ImsException.CODE_ERROR_SERVICE_UNAVAILABLE); + } + + IRcsUceControllerCallback internalCallback = new IRcsUceControllerCallback.Stub() { + @Override + public void onCapabilitiesReceived(List<RcsContactUceCapability> contactCapabilities) { + final long callingIdentity = Binder.clearCallingIdentity(); + try { + executor.execute(() -> + c.onCapabilitiesReceived(contactCapabilities)); + } finally { + restoreCallingIdentity(callingIdentity); + } + } + @Override + public void onComplete() { + final long callingIdentity = Binder.clearCallingIdentity(); + try { + executor.execute(() -> c.onComplete()); + } finally { + restoreCallingIdentity(callingIdentity); + } + } + @Override + public void onError(int errorCode) { + final long callingIdentity = Binder.clearCallingIdentity(); + try { + executor.execute(() -> c.onError(errorCode)); + } finally { + restoreCallingIdentity(callingIdentity); + } + } + }; + + try { + imsRcsController.requestNetworkAvailability(mSubId, mContext.getOpPackageName(), + mContext.getAttributionTag(), contactNumber, internalCallback); + } catch (RemoteException e) { + Log.e(TAG, "Error calling IImsRcsController#requestNetworkAvailability", e); + throw new ImsException("Remote IMS Service is not available", + ImsException.CODE_ERROR_SERVICE_UNAVAILABLE); + } + } + + /** * Gets the last publish result from the UCE service if the device is using an RCS presence * server. * @return The last publish result from the UCE service. If the device is using SIP OPTIONS, diff --git a/telephony/java/android/telephony/ims/aidl/ICapabilityExchangeEventListener.aidl b/telephony/java/android/telephony/ims/aidl/ICapabilityExchangeEventListener.aidl new file mode 100644 index 000000000000..a4ffbef9fa84 --- /dev/null +++ b/telephony/java/android/telephony/ims/aidl/ICapabilityExchangeEventListener.aidl @@ -0,0 +1,75 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.telephony.ims.aidl; + +import android.net.Uri; +import android.telephony.ims.aidl.IOptionsRequestCallback; + +import java.util.List; + +/** + * Listener interface for the ImsService to use to notify the framework of UCE events. + * {@hide} + */ +oneway interface ICapabilityExchangeEventListener { + /** + * Trigger the framework to provide a capability update using + * {@link RcsCapabilityExchangeImplBase#publishCapabilities}. + * <p> + * This is typically used when trying to generate an initial PUBLISH for a new + * subscription to the network. The device will cache all presence publications + * after boot until this method is called the first time. + * @param publishTriggerType {@link StackPublishTriggerType} The reason for the + * capability update request. + * @throws ImsException If this {@link RcsPresenceExchangeImplBase} instance is + * not currently connected to the framework. This can happen if the + * {@link RcsFeature} is not {@link ImsFeature#STATE_READY} and the + * {@link RcsFeature} has not received the + * {@link ImsFeature#onFeatureReady()} callback. This may also happen in rare + * cases when the Telephony stack has crashed. + */ + void onRequestPublishCapabilities(int publishTriggerType); + + /** + * Notify the framework that the device's capabilities have been unpublished from the network. + * + * @throws ImsException If this {@link RcsPresenceExchangeImplBase} instance is not currently + * connected to the framework. This can happen if the {@link RcsFeature} is not + * {@link ImsFeature#STATE_READY} and the {@link RcsFeature} has not received the + * {@link ImsFeature#onFeatureReady()} callback. This may also happen in rare cases when the + * Telephony stack has crashed. + */ + void onUnpublish(); + + /** + * Inform the framework of a query for this device's UCE capabilities. + * <p> + * The framework will respond via the + * {@link IOptionsRequestCallback#respondToCapabilityRequest} or + * {@link IOptionsRequestCallback#respondToCapabilityRequestWithError} method. + * @param contactUri The URI associated with the remote contact that is requesting capabilities. + * @param remoteCapabilities The remote contact's capability information. + * @throws ImsException If this {@link RcsSipOptionsImplBase} instance is not currently + * connected to the framework. This can happen if the {@link RcsFeature} is not + * {@link ImsFeature#STATE_READY} and the {@link RcsFeature} has not received + * the {@link ImsFeature#onFeatureReady()} callback. This may also happen in rare cases when + * the Telephony stack has crashed. + */ + void onRemoteCapabilityRequest(in Uri contactUri, + in List<String> remoteCapabilities, + IOptionsRequestCallback cb); +} diff --git a/telephony/java/android/telephony/ims/aidl/IImsRcsController.aidl b/telephony/java/android/telephony/ims/aidl/IImsRcsController.aidl index 6d25a09e079f..8e84e9373f65 100644 --- a/telephony/java/android/telephony/ims/aidl/IImsRcsController.aidl +++ b/telephony/java/android/telephony/ims/aidl/IImsRcsController.aidl @@ -47,6 +47,9 @@ interface IImsRcsController { // ImsUceAdapter specific void requestCapabilities(int subId, String callingPackage, String callingFeatureId, in List<Uri> contactNumbers, IRcsUceControllerCallback c); + void requestNetworkAvailability(int subId, String callingPackage, + String callingFeatureId, in Uri contactNumber, + IRcsUceControllerCallback c); int getUcePublishState(int subId); boolean isUceSettingEnabled(int subId, String callingPackage, String callingFeatureId); void setUceSettingEnabled(int subId, boolean isEnabled); diff --git a/telephony/java/android/telephony/ims/aidl/IImsRcsFeature.aidl b/telephony/java/android/telephony/ims/aidl/IImsRcsFeature.aidl index 4b98b79f1095..b47e3c75b558 100644 --- a/telephony/java/android/telephony/ims/aidl/IImsRcsFeature.aidl +++ b/telephony/java/android/telephony/ims/aidl/IImsRcsFeature.aidl @@ -18,8 +18,12 @@ package android.telephony.ims.aidl; import android.net.Uri; import android.telephony.ims.RcsContactUceCapability; +import android.telephony.ims.aidl.ICapabilityExchangeEventListener; import android.telephony.ims.aidl.IImsCapabilityCallback; +import android.telephony.ims.aidl.IOptionsResponseCallback; +import android.telephony.ims.aidl.IPublishResponseCallback; import android.telephony.ims.aidl.IRcsFeatureListener; +import android.telephony.ims.aidl.ISubscribeResponseCallback; import android.telephony.ims.feature.CapabilityChangeRequest; import java.util.List; @@ -40,6 +44,12 @@ interface IImsRcsFeature { IImsCapabilityCallback c); oneway void queryCapabilityConfiguration(int capability, int radioTech, IImsCapabilityCallback c); + // RcsCapabilityExchangeImplBase specific api + oneway void setCapabilityExchangeEventListener(ICapabilityExchangeEventListener listener); + oneway void publishCapabilities(in String pidfXml, IPublishResponseCallback cb); + oneway void subscribeForCapabilities(in List<Uri> uris, ISubscribeResponseCallback cb); + oneway void sendOptionsCapabilityRequest(in Uri contactUri, + in List<String> myCapabilities, IOptionsResponseCallback cb); // RcsPresenceExchangeImplBase specific api oneway void requestCapabilities(in List<Uri> uris, int operationToken); oneway void updateCapabilities(in RcsContactUceCapability capabilities, int operationToken); @@ -50,4 +60,4 @@ interface IImsRcsFeature { in RcsContactUceCapability ownCapabilities, int operationToken); oneway void respondToCapabilityRequestWithError(in Uri contactUri, int code, in String reason, int operationToken); -}
\ No newline at end of file +} diff --git a/telephony/java/android/telephony/ims/aidl/IOptionsRequestCallback.aidl b/telephony/java/android/telephony/ims/aidl/IOptionsRequestCallback.aidl new file mode 100644 index 000000000000..d55670dd313b --- /dev/null +++ b/telephony/java/android/telephony/ims/aidl/IOptionsRequestCallback.aidl @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.telephony.ims.aidl; + +import android.telephony.ims.RcsContactUceCapability; + +/** + * Interface used by the framework to respond to OPTIONS requests. + * {@hide} + */ +oneway interface IOptionsRequestCallback { + /** + * Respond to a remote capability request from the contact specified with the capabilities + * of this device. + * @param ownCapabilities The capabilities of this device. + */ + void respondToCapabilityRequest(in RcsContactUceCapability ownCapabilities); + + /** + * Respond to a remote capability request from the contact specified with the + * specified error. + * @param contactUri A URI containing the remote contact. + * @param code The SIP response code to respond with. + * @param reason A non-null String containing the reason associated with the SIP code. + */ + void respondToCapabilityRequestWithError(int code, String reason); +} diff --git a/telephony/java/android/telephony/ims/aidl/IOptionsResponseCallback.aidl b/telephony/java/android/telephony/ims/aidl/IOptionsResponseCallback.aidl new file mode 100644 index 000000000000..a8c8329fe55e --- /dev/null +++ b/telephony/java/android/telephony/ims/aidl/IOptionsResponseCallback.aidl @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.telephony.ims.aidl; + +import java.util.List; + +/** + * Interface used by the framework to receive the response from the remote user + * through {@link RcsCapabilityExchangeImplBase#sendOptionsCapabilityRequest} + * {@hide} + */ +oneway interface IOptionsResponseCallback { + void onCommandError(int code); + void onNetworkResponse(int code, String reason, in List<String> theirCaps); +} diff --git a/telephony/java/android/telephony/ims/aidl/IPublishResponseCallback.aidl b/telephony/java/android/telephony/ims/aidl/IPublishResponseCallback.aidl new file mode 100644 index 000000000000..481e7f8b37b9 --- /dev/null +++ b/telephony/java/android/telephony/ims/aidl/IPublishResponseCallback.aidl @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.telephony.ims.aidl; + +import java.util.List; + +/** + * Interface used by the framework to receive the response of the publish + * request through {@link RcsCapabilityExchangeImplBase#publishCapabilities} + * {@hide} + */ +oneway interface IPublishResponseCallback { + void onCommandError(int code); + void onNetworkResponse(int code, String reason); +} diff --git a/telephony/java/android/telephony/ims/aidl/IRcsUceControllerCallback.aidl b/telephony/java/android/telephony/ims/aidl/IRcsUceControllerCallback.aidl index 5975930d5cfa..0bd3e5ed354e 100644 --- a/telephony/java/android/telephony/ims/aidl/IRcsUceControllerCallback.aidl +++ b/telephony/java/android/telephony/ims/aidl/IRcsUceControllerCallback.aidl @@ -25,5 +25,6 @@ import android.telephony.ims.RcsContactUceCapability; */ oneway interface IRcsUceControllerCallback { void onCapabilitiesReceived(in List<RcsContactUceCapability> contactCapabilities); + void onComplete(); void onError(int errorCode); } diff --git a/telephony/java/android/telephony/ims/aidl/ISubscribeResponseCallback.aidl b/telephony/java/android/telephony/ims/aidl/ISubscribeResponseCallback.aidl new file mode 100644 index 000000000000..4deaba1b7a49 --- /dev/null +++ b/telephony/java/android/telephony/ims/aidl/ISubscribeResponseCallback.aidl @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.telephony.ims.aidl; + +import android.net.Uri; +import android.telephony.ims.RcsContactTerminatedReason; + +import java.util.List; +import java.util.Map; + +/** + * Interface used by the framework to receive the response of the subscribe + * request through {@link RcsCapabilityExchangeImplBase#subscribeForCapabilities} + * {@hide} + */ +oneway interface ISubscribeResponseCallback { + void onCommandError(int code); + void onNetworkResponse(int code, in String reason); + void onNotifyCapabilitiesUpdate(in List<String> pidfXmls); + void onResourceTerminated(in List<RcsContactTerminatedReason> uriTerminatedReason); + void onTerminated(in String reason, in String retryAfter); +} diff --git a/telephony/java/android/telephony/ims/aidl/RcsOptionsResponseAidlWrapper.java b/telephony/java/android/telephony/ims/aidl/RcsOptionsResponseAidlWrapper.java new file mode 100644 index 000000000000..47a96af1cba1 --- /dev/null +++ b/telephony/java/android/telephony/ims/aidl/RcsOptionsResponseAidlWrapper.java @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.telephony.ims.aidl; + +import android.os.RemoteException; +import android.telephony.ims.ImsException; +import android.telephony.ims.stub.RcsCapabilityExchangeImplBase.OptionsResponseCallback; + +import java.util.List; + +/** + * Implementation of the callback OptionsResponseCallback by wrapping the internal AIDL from + * telephony. + * @hide + */ +public class RcsOptionsResponseAidlWrapper implements OptionsResponseCallback { + + private final IOptionsResponseCallback mResponseBinder; + + public RcsOptionsResponseAidlWrapper(IOptionsResponseCallback responseBinder) { + mResponseBinder = responseBinder; + } + + @Override + public void onCommandError(int code) { + try { + mResponseBinder.onCommandError(code); + } catch (RemoteException e) { + } + } + + @Override + public void onNetworkResponse(int code, String reason, List<String> theirCaps) + throws ImsException { + try { + mResponseBinder.onNetworkResponse(code, reason, theirCaps); + } catch (RemoteException e) { + } + } +} diff --git a/telephony/java/android/telephony/ims/aidl/RcsPublishResponseAidlWrapper.java b/telephony/java/android/telephony/ims/aidl/RcsPublishResponseAidlWrapper.java new file mode 100644 index 000000000000..22985d0cf85c --- /dev/null +++ b/telephony/java/android/telephony/ims/aidl/RcsPublishResponseAidlWrapper.java @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.telephony.ims.aidl; + +import android.os.RemoteException; +import android.telephony.ims.ImsException; +import android.telephony.ims.stub.RcsCapabilityExchangeImplBase.PublishResponseCallback; + +/** + * Implementation of the callback PublishResponseCallback by wrapping the internal AIDL from + * telephony. + * @hide + */ +public class RcsPublishResponseAidlWrapper implements PublishResponseCallback { + + private final IPublishResponseCallback mResponseBinder; + + public RcsPublishResponseAidlWrapper(IPublishResponseCallback responseBinder) { + mResponseBinder = responseBinder; + } + + @Override + public void onCommandError(int code) { + try { + mResponseBinder.onCommandError(code); + } catch (RemoteException e) { + } + } + + @Override + public void onNetworkResponse(int code, String reason) throws ImsException { + try { + mResponseBinder.onNetworkResponse(code, reason); + } catch (RemoteException e) { + } + } +} diff --git a/telephony/java/android/telephony/ims/aidl/RcsSubscribeResponseAidlWrapper.java b/telephony/java/android/telephony/ims/aidl/RcsSubscribeResponseAidlWrapper.java new file mode 100644 index 000000000000..37588ed98585 --- /dev/null +++ b/telephony/java/android/telephony/ims/aidl/RcsSubscribeResponseAidlWrapper.java @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.telephony.ims.aidl; + +import android.net.Uri; +import android.os.RemoteException; +import android.telephony.ims.ImsException; +import android.telephony.ims.RcsContactTerminatedReason; +import android.telephony.ims.stub.RcsCapabilityExchangeImplBase.SubscribeResponseCallback; +import android.util.Pair; + +import java.util.ArrayList; +import java.util.List; + +/** + * Implementation of the callback OptionsResponseCallback by wrapping the internal AIDL from + * telephony. + * @hide + */ +public class RcsSubscribeResponseAidlWrapper implements SubscribeResponseCallback { + + private final ISubscribeResponseCallback mResponseBinder; + + public RcsSubscribeResponseAidlWrapper(ISubscribeResponseCallback responseBinder) { + mResponseBinder = responseBinder; + } + + @Override + public void onCommandError(int code) { + try { + mResponseBinder.onCommandError(code); + } catch (RemoteException e) { + } + } + + @Override + public void onNetworkResponse(int code, String reason) throws ImsException { + try { + mResponseBinder.onNetworkResponse(code, reason); + } catch (RemoteException e) { + } + } + + @Override + public void onNotifyCapabilitiesUpdate(List<String> pidfXmls) throws ImsException { + try { + mResponseBinder.onNotifyCapabilitiesUpdate(pidfXmls); + } catch (RemoteException e) { + } + } + + @Override + public void onResourceTerminated(List<Pair<Uri, String>> uriTerminatedReason) + throws ImsException { + try { + mResponseBinder.onResourceTerminated(getTerminatedReasonList(uriTerminatedReason)); + } catch (RemoteException e) { + } + } + + private List<RcsContactTerminatedReason> getTerminatedReasonList( + List<Pair<Uri, String>> uriTerminatedReason) { + List<RcsContactTerminatedReason> uriTerminatedReasonList = new ArrayList<>(); + if (uriTerminatedReason != null) { + for (Pair<Uri, String> pair : uriTerminatedReason) { + RcsContactTerminatedReason reason = + new RcsContactTerminatedReason(pair.first, pair.second); + uriTerminatedReasonList.add(reason); + } + } + return uriTerminatedReasonList; + } + + @Override + public void onTerminated(String reason, String retryAfter) throws ImsException { + try { + mResponseBinder.onTerminated(reason, retryAfter); + } catch (RemoteException e) { + } + } +} diff --git a/telephony/java/android/telephony/ims/feature/CapabilityChangeRequest.java b/telephony/java/android/telephony/ims/feature/CapabilityChangeRequest.java index 87a5094a95f3..87a6873d00b2 100644 --- a/telephony/java/android/telephony/ims/feature/CapabilityChangeRequest.java +++ b/telephony/java/android/telephony/ims/feature/CapabilityChangeRequest.java @@ -28,8 +28,8 @@ import java.util.List; import java.util.Set; /** - * Request to send to IMS provider, which will try to enable/disable capabilities that are added to - * the request. + * Used by the framework to enable and disable MMTEL and RCS capabilities. See + * MmTelFeature#changeEnabledCapabilities and RcsFeature#changeEnabledCapabilities. * {@hide} */ @SystemApi diff --git a/telephony/java/android/telephony/ims/feature/RcsFeature.java b/telephony/java/android/telephony/ims/feature/RcsFeature.java index b8ae146784d4..5de2ddc578a1 100644 --- a/telephony/java/android/telephony/ims/feature/RcsFeature.java +++ b/telephony/java/android/telephony/ims/feature/RcsFeature.java @@ -23,12 +23,22 @@ import android.annotation.SystemApi; import android.net.Uri; import android.os.RemoteException; import android.telephony.ims.RcsContactUceCapability; +import android.telephony.ims.RcsUceAdapter; +import android.telephony.ims.aidl.ICapabilityExchangeEventListener; import android.telephony.ims.aidl.IImsCapabilityCallback; import android.telephony.ims.aidl.IImsRcsFeature; +import android.telephony.ims.aidl.IOptionsResponseCallback; +import android.telephony.ims.aidl.IPublishResponseCallback; import android.telephony.ims.aidl.IRcsFeatureListener; +import android.telephony.ims.aidl.ISubscribeResponseCallback; +import android.telephony.ims.aidl.RcsOptionsResponseAidlWrapper; +import android.telephony.ims.aidl.RcsPublishResponseAidlWrapper; +import android.telephony.ims.aidl.RcsSubscribeResponseAidlWrapper; import android.telephony.ims.stub.ImsRegistrationImplBase; -import android.telephony.ims.stub.RcsPresenceExchangeImplBase; -import android.telephony.ims.stub.RcsSipOptionsImplBase; +import android.telephony.ims.stub.RcsCapabilityExchangeImplBase; +import android.telephony.ims.stub.RcsCapabilityExchangeImplBase.OptionsResponseCallback; +import android.telephony.ims.stub.RcsCapabilityExchangeImplBase.PublishResponseCallback; +import android.telephony.ims.stub.RcsCapabilityExchangeImplBase.SubscribeResponseCallback; import android.util.Log; import com.android.internal.telephony.util.TelephonyUtils; @@ -64,9 +74,14 @@ public class RcsFeature extends ImsFeature { mExecutor = executor; } + /** + * @deprecated This method is deprecated. Please call the method + * setCapabilityExchangeEventListener instead. + */ @Override + @Deprecated public void setListener(IRcsFeatureListener listener) { - mReference.setListener(listener); + Log.w(LOG_TAG, "The method setListener is deprecated"); } @Override @@ -106,44 +121,66 @@ public class RcsFeature extends ImsFeature { return executeMethodAsyncForResult(mReference::getFeatureState, "getFeatureState"); } + // RcsCapabilityExchangeImplBase specific APIs + @Override + public void setCapabilityExchangeEventListener( + @NonNull ICapabilityExchangeEventListener listener) throws RemoteException { + executeMethodAsync(() -> mReference.setCapabilityExchangeEventListener(listener), + "setCapabilityExchangeEventListener"); + } + + @Override + public void publishCapabilities(@NonNull String pidfXml, + @NonNull IPublishResponseCallback callback) throws RemoteException { + PublishResponseCallback callbackWrapper = new RcsPublishResponseAidlWrapper(callback); + executeMethodAsync(() -> mReference.getCapabilityExchangeImplBaseInternal() + .publishCapabilities(pidfXml, callbackWrapper), "publishCapabilities"); + } + + @Override + public void subscribeForCapabilities(@NonNull List<Uri> uris, + @NonNull ISubscribeResponseCallback callback) throws RemoteException { + SubscribeResponseCallback wrapper = new RcsSubscribeResponseAidlWrapper(callback); + executeMethodAsync(() -> mReference.getCapabilityExchangeImplBaseInternal() + .subscribeForCapabilities(uris, wrapper), "subscribeForCapabilities"); + } + + @Override + public void sendOptionsCapabilityRequest(@NonNull Uri contactUri, + @NonNull List<String> myCapabilities, @NonNull IOptionsResponseCallback callback) + throws RemoteException { + OptionsResponseCallback callbackWrapper = new RcsOptionsResponseAidlWrapper(callback); + executeMethodAsync(() -> mReference.getCapabilityExchangeImplBaseInternal() + .sendOptionsCapabilityRequest(contactUri, myCapabilities, callbackWrapper), + "sendOptionsCapabilityRequest"); + } + // RcsPresenceExchangeImplBase specific APIS @Override public void requestCapabilities(List<Uri> uris, int operationToken) throws RemoteException { - executeMethodAsync(() -> mReference.getPresenceExchangeInternal() - .requestCapabilities(uris, operationToken), "requestCapabilities"); + throw new RemoteException("Unsupported operation: requestCapabilities"); } @Override public void updateCapabilities(RcsContactUceCapability capabilities, int operationToken) throws RemoteException { - executeMethodAsync(() -> mReference.getPresenceExchangeInternal() - .updateCapabilities(capabilities, operationToken), - "updateCapabilities"); - + throw new RemoteException("Unsupported operation: updateCapabilities"); } // RcsSipOptionsImplBase specific APIS @Override public void sendCapabilityRequest(Uri contactUri, RcsContactUceCapability capabilities, int operationToken) throws RemoteException { - executeMethodAsync(() -> mReference.getOptionsExchangeInternal() - .sendCapabilityRequest(contactUri, capabilities, operationToken), - "sendCapabilityRequest"); - + throw new RemoteException("Unsupported operation: sendCapabilityRequest"); } @Override public void respondToCapabilityRequest(String contactUri, RcsContactUceCapability ownCapabilities, int operationToken) throws RemoteException { - executeMethodAsync(() -> mReference.getOptionsExchangeInternal() - .respondToCapabilityRequest(contactUri, ownCapabilities, - operationToken), "respondToCapabilityRequest"); - + throw new RemoteException("Unsupported operation: respondToCapabilityRequest"); } @Override public void respondToCapabilityRequestWithError(Uri contactUri, int code, String reason, int operationToken) throws RemoteException { - executeMethodAsync(() -> mReference.getOptionsExchangeInternal() - .respondToCapabilityRequestWithError(contactUri, code, reason, - operationToken), "respondToCapabilityRequestWithError"); + throw new RemoteException("Unsupported operation: respondToCapabilityRequestWithError"); } // Call the methods with a clean calling identity on the executor and wait indefinitely for @@ -182,8 +219,8 @@ public class RcsFeature extends ImsFeature { * Contains the capabilities defined and supported by a {@link RcsFeature} in the * form of a bitmask. The capabilities that are used in the RcsFeature are * defined as: - * {@link RcsImsCapabilityFlag#CAPABILITY_TYPE_OPTIONS_UCE} - * {@link RcsImsCapabilityFlag#CAPABILITY_TYPE_PRESENCE_UCE} + * {@link RcsUceAdatper.RcsImsCapabilityFlag#CAPABILITY_TYPE_OPTIONS_UCE} + * {@link RceUceAdapter.RcsImsCapabilityFlag#CAPABILITY_TYPE_PRESENCE_UCE} * * The enabled capabilities of this RcsFeature will be set by the framework * using {@link #changeEnabledCapabilities(CapabilityChangeRequest, CapabilityCallbackProxy)}. @@ -223,7 +260,7 @@ public class RcsFeature extends ImsFeature { */ public static final int CAPABILITY_TYPE_PRESENCE_UCE = 1 << 1; - public RcsImsCapabilities(@RcsImsCapabilityFlag int capabilities) { + public RcsImsCapabilities(@RcsUceAdapter.RcsImsCapabilityFlag int capabilities) { super(capabilities); } @@ -232,25 +269,24 @@ public class RcsFeature extends ImsFeature { } @Override - public void addCapabilities(@RcsImsCapabilityFlag int capabilities) { + public void addCapabilities(@RcsUceAdapter.RcsImsCapabilityFlag int capabilities) { super.addCapabilities(capabilities); } @Override - public void removeCapabilities(@RcsImsCapabilityFlag int capabilities) { + public void removeCapabilities(@RcsUceAdapter.RcsImsCapabilityFlag int capabilities) { super.removeCapabilities(capabilities); } @Override - public boolean isCapable(@RcsImsCapabilityFlag int capabilities) { + public boolean isCapable(@RcsUceAdapter.RcsImsCapabilityFlag int capabilities) { return super.isCapable(capabilities); } } private final RcsFeatureBinder mImsRcsBinder; - private IRcsFeatureListener mListenerBinder; - private RcsPresenceExchangeImplBase mPresExchange; - private RcsSipOptionsImplBase mSipOptions; + private RcsCapabilityExchangeImplBase mCapabilityExchangeImpl; + private ICapabilityExchangeEventListener mCapExchangeEventListener; /** * Create a new RcsFeature. @@ -314,7 +350,7 @@ public class RcsFeature extends ImsFeature { * @hide */ public boolean queryCapabilityConfiguration( - @RcsImsCapabilities.RcsImsCapabilityFlag int capability, + @RcsUceAdapter.RcsImsCapabilityFlag int capability, @ImsRegistrationImplBase.ImsRegistrationTech int radioTech) { // Base Implementation - Override to provide functionality return false; @@ -342,37 +378,22 @@ public class RcsFeature extends ImsFeature { } /** - * Retrieve the implementation of SIP OPTIONS for this {@link RcsFeature}. - * <p> - * Will only be requested by the framework if capability exchange via SIP OPTIONS is - * configured as capable during a - * {@link #changeEnabledCapabilities(CapabilityChangeRequest, CapabilityCallbackProxy)} - * operation and the RcsFeature sets the status of the capability to true using - * {@link #notifyCapabilitiesStatusChanged(RcsImsCapabilities)}. + * Retrieve the implementation of UCE for this {@link RcsFeature}, which can use either + * presence or OPTIONS for capability exchange. * - * @return An instance of {@link RcsSipOptionsImplBase} that implements SIP options exchange if - * it is supported by the device. - * @hide - */ - public @NonNull RcsSipOptionsImplBase getOptionsExchangeImpl() { - // Base Implementation, override to implement functionality - return new RcsSipOptionsImplBase(); - } - - /** - * Retrieve the implementation of UCE presence for this {@link RcsFeature}. - * Will only be requested by the framework if presence exchang is configured as capable during - * a {@link #changeEnabledCapabilities(CapabilityChangeRequest, CapabilityCallbackProxy)} + * Will only be requested by the framework if capability exchange is configured + * as capable during a + * {@link #changeEnabledCapabilities(CapabilityChangeRequest, CapabilityCallbackProxy)} * operation and the RcsFeature sets the status of the capability to true using * {@link #notifyCapabilitiesStatusChanged(RcsImsCapabilities)}. * - * @return An instance of {@link RcsPresenceExchangeImplBase} that implements presence + * @return An instance of {@link RcsCapabilityExchangeImplBase} that implements presence * exchange if it is supported by the device. * @hide */ - public @NonNull RcsPresenceExchangeImplBase getPresenceExchangeImpl() { - // Base Implementation, override to implement functionality. - return new RcsPresenceExchangeImplBase(); + public @NonNull RcsCapabilityExchangeImplBase createCapabilityExchangeImpl() { + // Base Implementation, override to implement functionality + return new RcsCapabilityExchangeImplBase(); } /**{@inheritDoc}*/ @@ -395,39 +416,20 @@ public class RcsFeature extends ImsFeature { return mImsRcsBinder; } - /**@hide*/ - public IRcsFeatureListener getListener() { - synchronized (mLock) { - return mListenerBinder; - } - } - - private void setListener(IRcsFeatureListener listener) { - synchronized (mLock) { - mListenerBinder = listener; - if (mListenerBinder != null) { - onFeatureReady(); - } - } - } - - private RcsPresenceExchangeImplBase getPresenceExchangeInternal() { - synchronized (mLock) { - if (mPresExchange == null) { - mPresExchange = getPresenceExchangeImpl(); - mPresExchange.initialize(this); - } - return mPresExchange; + private void setCapabilityExchangeEventListener(ICapabilityExchangeEventListener listener) { + mCapExchangeEventListener = listener; + if (mCapExchangeEventListener != null) { + onFeatureReady(); } } - private RcsSipOptionsImplBase getOptionsExchangeInternal() { + private RcsCapabilityExchangeImplBase getCapabilityExchangeImplBaseInternal() { synchronized (mLock) { - if (mSipOptions == null) { - mSipOptions = getOptionsExchangeImpl(); - mSipOptions.initialize(this); + if (mCapabilityExchangeImpl == null) { + mCapabilityExchangeImpl = createCapabilityExchangeImpl(); + mCapabilityExchangeImpl.setEventListener(mCapExchangeEventListener); } - return mSipOptions; + return mCapabilityExchangeImpl; } } } diff --git a/telephony/java/android/telephony/ims/stub/RcsCapabilityExchange.java b/telephony/java/android/telephony/ims/stub/RcsCapabilityExchange.java index fda295a27111..0b13efb7b4b4 100644 --- a/telephony/java/android/telephony/ims/stub/RcsCapabilityExchange.java +++ b/telephony/java/android/telephony/ims/stub/RcsCapabilityExchange.java @@ -87,12 +87,8 @@ public class RcsCapabilityExchange { /** @hide */ protected final IRcsFeatureListener getListener() throws ImsException { - IRcsFeatureListener listener = mFeature.getListener(); - if (listener == null) { - throw new ImsException("Connection to Framework has not been established, wait for " - + "onFeatureReady().", ImsException.CODE_ERROR_SERVICE_UNAVAILABLE); - } - return mFeature.getListener(); + throw new ImsException("This method is deprecated.", + ImsException.CODE_ERROR_UNSUPPORTED_OPERATION); } /** diff --git a/telephony/java/android/telephony/ims/stub/RcsCapabilityExchangeImplBase.java b/telephony/java/android/telephony/ims/stub/RcsCapabilityExchangeImplBase.java new file mode 100644 index 000000000000..b5704bfb3569 --- /dev/null +++ b/telephony/java/android/telephony/ims/stub/RcsCapabilityExchangeImplBase.java @@ -0,0 +1,338 @@ +/* + * Copyright (c) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.telephony.ims.stub; + +import android.annotation.IntDef; +import android.annotation.IntRange; +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.net.Uri; +import android.telephony.ims.ImsException; +import android.telephony.ims.aidl.ICapabilityExchangeEventListener; +import android.util.Log; +import android.util.Pair; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.util.List; + +/** + * Base class for different types of Capability exchange. + * @hide + */ +public class RcsCapabilityExchangeImplBase { + + private static final String LOG_TAG = "RcsCapExchangeImplBase"; + + /** + * Service is unknown. + */ + public static final int COMMAND_CODE_SERVICE_UNKNOWN = 0; + + /** + * The command failed with an unknown error. + */ + public static final int COMMAND_CODE_GENERIC_FAILURE = 1; + + /** + * Invalid parameter(s). + */ + public static final int COMMAND_CODE_INVALID_PARAM = 2; + + /** + * Fetch error. + */ + public static final int COMMAND_CODE_FETCH_ERROR = 3; + + /** + * Request timed out. + */ + public static final int COMMAND_CODE_REQUEST_TIMEOUT = 4; + + /** + * Failure due to insufficient memory available. + */ + public static final int COMMAND_CODE_INSUFFICIENT_MEMORY = 5; + + /** + * Network connection is lost. + * @hide + */ + public static final int COMMAND_CODE_LOST_NETWORK_CONNECTION = 6; + + /** + * Requested feature/resource is not supported. + * @hide + */ + public static final int COMMAND_CODE_NOT_SUPPORTED = 7; + + /** + * Contact or resource is not found. + */ + public static final int COMMAND_CODE_NOT_FOUND = 8; + + /** + * Service is not available. + */ + public static final int COMMAND_CODE_SERVICE_UNAVAILABLE = 9; + + /** + * Command resulted in no change in state, ignoring. + */ + public static final int COMMAND_CODE_NO_CHANGE = 10; + + /**@hide*/ + @Retention(RetentionPolicy.SOURCE) + @IntDef(prefix = "COMMAND_CODE_", value = { + COMMAND_CODE_SERVICE_UNKNOWN, + COMMAND_CODE_GENERIC_FAILURE, + COMMAND_CODE_INVALID_PARAM, + COMMAND_CODE_FETCH_ERROR, + COMMAND_CODE_REQUEST_TIMEOUT, + COMMAND_CODE_INSUFFICIENT_MEMORY, + COMMAND_CODE_LOST_NETWORK_CONNECTION, + COMMAND_CODE_NOT_SUPPORTED, + COMMAND_CODE_NOT_FOUND, + COMMAND_CODE_SERVICE_UNAVAILABLE, + COMMAND_CODE_NO_CHANGE + }) + public @interface CommandCode {} + + /** + * Interface used by the framework to receive the response of the publish request. + */ + public interface PublishResponseCallback { + /** + * Notify the framework that the command associated with this callback has failed. + * + * @param code The reason why the associated command has failed. + * @throws ImsException If this {@link RcsCapabilityExchangeImplBase} instance is + * not currently connected to the framework. This can happen if the {@link RcsFeature} + * is not {@link ImsFeature#STATE_READY} and the {@link RcsFeature} has not received + * the {@link ImsFeature#onFeatureReady()} callback. This may also happen in rare cases + * when the Telephony stack has crashed. + */ + void onCommandError(@CommandCode int code) throws ImsException; + + + /** + * Provide the framework with a subsequent network response update to + * {@link #publishCapabilities(String, PublishResponseCallback)}. + * + * @param code The SIP response code sent from the network for the operation + * token specified. + * @param reason The optional reason response from the network. If the network + * provided no reason with the code, the string should be empty. + * @throws ImsException If this {@link RcsCapabilityExchangeImplBase} instance is + * not currently connected to the framework. This can happen if the {@link RcsFeature} + * is not {@link ImsFeature#STATE_READY} and the {@link RcsFeature} has not received + * the {@link ImsFeature#onFeatureReady()} callback. This may also happen in rare cases + * when the Telephony stack has crashed. + */ + void onNetworkResponse(@IntRange(from = 100, to = 699) int code, + @NonNull String reason) throws ImsException; + } + + /** + * Interface used by the framework to respond to OPTIONS requests. + */ + public interface OptionsResponseCallback { + /** + * Notify the framework that the command associated with this callback has failed. + * + * @param code The reason why the associated command has failed. + * @throws ImsException If this {@link RcsCapabilityExchangeImplBase} instance is + * not currently connected to the framework. This can happen if the + * {@link RcsFeature} is not {@link ImsFeature#STATE_READY} and the {@link RcsFeature} + * has not received the {@link ImsFeature#onFeatureReady()} callback. This may also happen + * in rare cases when the Telephony stack has crashed. + */ + void onCommandError(@CommandCode int code) throws ImsException; + + /** + * Send the response of a SIP OPTIONS capability exchange to the framework. + * @param code The SIP response code that was sent by the network in response + * to the request sent by {@link #sendOptionsCapabilityRequest}. + * @param reason The optional SIP response reason sent by the network. + * If none was sent, this should be an empty string. + * @param theirCaps the contact's UCE capabilities associated with the + * capability request. + * @throws ImsException If this {@link RcsSipOptionsImplBase} instance is not + * currently connected to the framework. This can happen if the + * {@link RcsFeature} is not {@link ImsFeature#STATE_READY} and the + * {@link RcsFeature} has not received the + * {@link ImsFeature#onFeatureReady()} callback. This may also happen in rare + * cases when the Telephony stack has crashed. + */ + void onNetworkResponse(int code, @NonNull String reason, + @Nullable List<String> theirCaps) throws ImsException; + } + + /** + * Interface used by the framework to receive the response of the subscribe request. + */ + public interface SubscribeResponseCallback { + /** + * Notify the framework that the command associated with this callback has failed. + * + * @param code The reason why the associated command has failed. + * @throws ImsException If this {@link RcsCapabilityExchangeImplBase} instance is + * not currently connected to the framework. This can happen if the + * {@link RcsFeature} is not + * {@link ImsFeature#STATE_READY} and the {@link RcsFeature} has not received + * the {@link ImsFeature#onFeatureReady()} callback. This may also happen in + * rare cases when the Telephony stack has crashed. + */ + void onCommandError(@CommandCode int code) throws ImsException; + + /** + * Notify the framework of the response to the SUBSCRIBE request from + * {@link #subscribeForCapabilities(List<Uri>, SubscribeResponseCallback)}. + * + * @param code The SIP response code sent from the network for the operation + * token specified. + * @param reason The optional reason response from the network. If the network + * provided no reason with the code, the string should be empty. + * @throws ImsException If this {@link RcsCapabilityExchangeImplBase} instance is + * not currently connected to the framework. This can happen if the + * {@link RcsFeature} is not {@link ImsFeature#STATE_READY} and the + * {@link RcsFeature} has not received the {@link ImsFeature#onFeatureReady()} callback. + * This may also happen in rare cases when the Telephony stack has crashed. + */ + void onNetworkResponse(@IntRange(from = 100, to = 699) int code, + @NonNull String reason) throws ImsException; + + /** + * Provides the framework with latest XML PIDF documents included in the + * network response for the requested contacts' capabilities requested by the + * Framework using {@link #requestCapabilities(List, int)}. This should be + * called every time a new NOTIFY event is received with new capability + * information. + * + * @throws ImsException If this {@link RcsCapabilityExchangeImplBase} instance is + * not currently + * connected to the framework. This can happen if the {@link RcsFeature} is not + * {@link ImsFeature#STATE_READY} and the {@link RcsFeature} has not received + * the {@link ImsFeature#onFeatureReady()} callback. This may also happen in + * rare cases when the + * Telephony stack has crashed. + */ + void onNotifyCapabilitiesUpdate(@NonNull List<String> pidfXmls) throws ImsException; + + /** + * A resource in the resource list for the presence subscribe event has been terminated. + * <p> + * This allows the framework to know that there will not be any capability information for + * a specific contact URI that they subscribed for. + */ + void onResourceTerminated( + @NonNull List<Pair<Uri, String>> uriTerminatedReason) throws ImsException; + + /** + * The subscription associated with a previous #requestCapabilities operation + * has been terminated. This will mostly be due to the subscription expiring, + * but may also happen due to an error. + * <p> + * This allows the framework to know that there will no longer be any + * capability updates for the requested operationToken. + */ + void onTerminated(String reason, String retryAfter) throws ImsException; + } + + + private ICapabilityExchangeEventListener mListener; + + /** + * Set the event listener to send the request to Framework. + */ + public void setEventListener(ICapabilityExchangeEventListener listener) { + mListener = listener; + } + + /** + * Get the event listener. + */ + public ICapabilityExchangeEventListener getEventListener() { + return mListener; + } + + /** + * The user capabilities of one or multiple contacts have been requested by the framework. + * <p> + * The response from the network to the SUBSCRIBE request must be sent back to the framework + * using {@link #onSubscribeNetworkResponse(int, String, int)}. As NOTIFY requests come in from + * the network, the requested contact’s capabilities should be sent back to the framework using + * {@link #onSubscribeNotifyRequest} and {@link onSubscribeResourceTerminated} + * should be called with the presence information for the contacts specified. + * <p> + * Once the subscription is terminated, {@link #onSubscriptionTerminated} must be called for + * the framework to finish listening for NOTIFY responses. + * @param uris A {@link List} of the {@link Uri}s that the framework is requesting the UCE + * capabilities for. + * @param cb The callback of the subscribe request. + */ + public void subscribeForCapabilities(@NonNull List<Uri> uris, + @NonNull SubscribeResponseCallback cb) { + // Stub - to be implemented by service + Log.w(LOG_TAG, "subscribeForCapabilities called with no implementation."); + try { + cb.onCommandError(COMMAND_CODE_NOT_SUPPORTED); + } catch (ImsException e) { + // Do not do anything, this is a stub implementation. + } + } + + /** + * The capabilities of this device have been updated and should be published to the network. + * <p> + * If this operation succeeds, network response updates should be sent to the framework using + * {@link #onNetworkResponse(int, String)}. + * @param pidfXml The XML PIDF document containing the capabilities of this device to be sent + * to the carrier’s presence server. + * @param cb The callback of the publish request + */ + public void publishCapabilities(@NonNull String pidfXml, @NonNull PublishResponseCallback cb) { + // Stub - to be implemented by service + Log.w(LOG_TAG, "publishCapabilities called with no implementation."); + try { + cb.onCommandError(COMMAND_CODE_NOT_SUPPORTED); + } catch (ImsException e) { + // Do not do anything, this is a stub implementation. + } + } + + /** + * Push one's own capabilities to a remote user via the SIP OPTIONS presence exchange mechanism + * in order to receive the capabilities of the remote user in response. + * <p> + * The implementer must call {@link #onNetworkResponse} to send the response of this + * query back to the framework. + * @param contactUri The URI of the remote user that we wish to get the capabilities of. + * @param myCapabilities The capabilities of this device to send to the remote user. + * @param callback The callback of this request which is sent from the remote user. + */ + public void sendOptionsCapabilityRequest(@NonNull Uri contactUri, + @NonNull List<String> myCapabilities, @NonNull OptionsResponseCallback callback) { + // Stub - to be implemented by service + Log.w(LOG_TAG, "sendOptionsCapabilityRequest called with no implementation."); + try { + callback.onCommandError(COMMAND_CODE_NOT_SUPPORTED); + } catch (ImsException e) { + // Do not do anything, this is a stub implementation. + } + } +} diff --git a/telephony/java/com/android/internal/telephony/RILConstants.java b/telephony/java/com/android/internal/telephony/RILConstants.java index ca7efcde4fef..4abf784e9c81 100644 --- a/telephony/java/com/android/internal/telephony/RILConstants.java +++ b/telephony/java/com/android/internal/telephony/RILConstants.java @@ -30,77 +30,96 @@ public interface RILConstants { // from RIL_Errno int SUCCESS = 0; - int RADIO_NOT_AVAILABLE = 1; /* If radio did not start or is resetting */ + int RADIO_NOT_AVAILABLE = 1; /* If radio did not start or is resetting */ int GENERIC_FAILURE = 2; - int PASSWORD_INCORRECT = 3; /* for PIN/PIN2 methods only! */ - int SIM_PIN2 = 4; /* Operation requires SIM PIN2 to be entered */ - int SIM_PUK2 = 5; /* Operation requires SIM PIN2 to be entered */ + int PASSWORD_INCORRECT = 3; /* for PIN/PIN2 methods only! */ + int SIM_PIN2 = 4; /* Operation requires SIM PIN2 to be entered */ + int SIM_PUK2 = 5; /* Operation requires SIM PIN2 to be entered */ int REQUEST_NOT_SUPPORTED = 6; int REQUEST_CANCELLED = 7; - int OP_NOT_ALLOWED_DURING_VOICE_CALL = 8; /* data operation is not allowed during voice call in - class C */ - int OP_NOT_ALLOWED_BEFORE_REG_NW = 9; /* request is not allowed before device registers to - network */ - int SMS_SEND_FAIL_RETRY = 10; /* send sms fail and need retry */ - int SIM_ABSENT = 11; /* ICC card is absent */ - int SUBSCRIPTION_NOT_AVAILABLE = 12; /* fail to find CDMA subscription from specified - location */ - int MODE_NOT_SUPPORTED = 13; /* HW does not support preferred network type */ - int FDN_CHECK_FAILURE = 14; /* send operation barred error when FDN is enabled */ - int ILLEGAL_SIM_OR_ME = 15; /* network selection failure due - to wrong SIM/ME and no - retries needed */ - int MISSING_RESOURCE = 16; /* no logical channel available */ - int NO_SUCH_ELEMENT = 17; /* application not found on SIM */ - int DIAL_MODIFIED_TO_USSD = 18; /* DIAL request modified to USSD */ - int DIAL_MODIFIED_TO_SS = 19; /* DIAL request modified to SS */ - int DIAL_MODIFIED_TO_DIAL = 20; /* DIAL request modified to DIAL with different data*/ - int USSD_MODIFIED_TO_DIAL = 21; /* USSD request modified to DIAL */ - int USSD_MODIFIED_TO_SS = 22; /* USSD request modified to SS */ - int USSD_MODIFIED_TO_USSD = 23; /* USSD request modified to different USSD request */ - int SS_MODIFIED_TO_DIAL = 24; /* SS request modified to DIAL */ - int SS_MODIFIED_TO_USSD = 25; /* SS request modified to USSD */ - int SUBSCRIPTION_NOT_SUPPORTED = 26; /* Subscription not supported */ - int SS_MODIFIED_TO_SS = 27; /* SS request modified to different SS request */ - int SIM_ALREADY_POWERED_OFF = 29; /* SAP: 0x03, Error card aleready powered off */ - int SIM_ALREADY_POWERED_ON = 30; /* SAP: 0x05, Error card already powered on */ - int SIM_DATA_NOT_AVAILABLE = 31; /* SAP: 0x06, Error data not available */ + int OP_NOT_ALLOWED_DURING_VOICE_CALL = 8; /* data operation is not allowed during voice + call in class C */ + int OP_NOT_ALLOWED_BEFORE_REG_NW = 9; /* request is not allowed before device + registers to network */ + int SMS_SEND_FAIL_RETRY = 10; /* send sms fail and need retry */ + int SIM_ABSENT = 11; /* ICC card is absent */ + int SUBSCRIPTION_NOT_AVAILABLE = 12; /* fail to find CDMA subscription from specified + location */ + int MODE_NOT_SUPPORTED = 13; /* HW does not support preferred network type */ + int FDN_CHECK_FAILURE = 14; /* send operation barred error when FDN is + enabled */ + int ILLEGAL_SIM_OR_ME = 15; /* network selection failure due to wrong + SIM/ME and no retries needed */ + int MISSING_RESOURCE = 16; /* no logical channel available */ + int NO_SUCH_ELEMENT = 17; /* application not found on SIM */ + int DIAL_MODIFIED_TO_USSD = 18; /* DIAL request modified to USSD */ + int DIAL_MODIFIED_TO_SS = 19; /* DIAL request modified to SS */ + int DIAL_MODIFIED_TO_DIAL = 20; /* DIAL request modified to DIAL with + different data*/ + int USSD_MODIFIED_TO_DIAL = 21; /* USSD request modified to DIAL */ + int USSD_MODIFIED_TO_SS = 22; /* USSD request modified to SS */ + int USSD_MODIFIED_TO_USSD = 23; /* USSD request modified to different USSD + request */ + int SS_MODIFIED_TO_DIAL = 24; /* SS request modified to DIAL */ + int SS_MODIFIED_TO_USSD = 25; /* SS request modified to USSD */ + int SUBSCRIPTION_NOT_SUPPORTED = 26; /* Subscription not supported */ + int SS_MODIFIED_TO_SS = 27; /* SS request modified to different SS + request */ + int SIM_ALREADY_POWERED_OFF = 29; /* SAP: 0x03, Error card aleready powered off */ + int SIM_ALREADY_POWERED_ON = 30; /* SAP: 0x05, Error card already powered on */ + int SIM_DATA_NOT_AVAILABLE = 31; /* SAP: 0x06, Error data not available */ int SIM_SAP_CONNECT_FAILURE = 32; int SIM_SAP_MSG_SIZE_TOO_LARGE = 33; int SIM_SAP_MSG_SIZE_TOO_SMALL = 34; int SIM_SAP_CONNECT_OK_CALL_ONGOING = 35; - int LCE_NOT_SUPPORTED = 36; /* Link Capacity Estimation (LCE) not supported */ - int NO_MEMORY = 37; /* Not sufficient memory to process the request */ - int INTERNAL_ERR = 38; /* Hit unexpected vendor internal error scenario */ - int SYSTEM_ERR = 39; /* Hit platform or system error */ - int MODEM_ERR = 40; /* Hit unexpected modem error */ - int INVALID_STATE = 41; /* Unexpected request for the current state */ - int NO_RESOURCES = 42; /* Not sufficient resource to process the request */ - int SIM_ERR = 43; /* Received error from SIM card */ - int INVALID_ARGUMENTS = 44; /* Received invalid arguments in request */ - int INVALID_SIM_STATE = 45; /* Can not process the request in current SIM state */ - int INVALID_MODEM_STATE = 46; /* Can not process the request in current Modem state */ - int INVALID_CALL_ID = 47; /* Received invalid call id in request */ - int NO_SMS_TO_ACK = 48; /* ACK received when there is no SMS to ack */ - int NETWORK_ERR = 49; /* Received error from network */ - int REQUEST_RATE_LIMITED = 50; /* Operation denied due to overly-frequent requests */ - int SIM_BUSY = 51; /* SIM is busy */ - int SIM_FULL = 52; /* The target EF is full */ - int NETWORK_REJECT = 53; /* Request is rejected by network */ - int OPERATION_NOT_ALLOWED = 54; /* Not allowed the request now */ - int EMPTY_RECORD = 55; /* The request record is empty */ - int INVALID_SMS_FORMAT = 56; /* Invalid sms format */ - int ENCODING_ERR = 57; /* Message not encoded properly */ - int INVALID_SMSC_ADDRESS = 58; /* SMSC address specified is invalid */ - int NO_SUCH_ENTRY = 59; /* No such entry present to perform the request */ - int NETWORK_NOT_READY = 60; /* Network is not ready to perform the request */ - int NOT_PROVISIONED = 61; /* Device doesnot have this value provisioned */ - int NO_SUBSCRIPTION = 62; /* Device doesnot have subscription */ - int NO_NETWORK_FOUND = 63; /* Network cannot be found */ - int DEVICE_IN_USE = 64; /* Operation cannot be performed because the device - is currently in use */ - int ABORTED = 65; /* Operation aborted */ - int INVALID_RESPONSE = 66; /* Invalid response sent by vendor code */ + int LCE_NOT_SUPPORTED = 36; /* Link Capacity Estimation (LCE) not + supported */ + int NO_MEMORY = 37; /* Not sufficient memory to process the + request */ + int INTERNAL_ERR = 38; /* Hit unexpected vendor internal error + scenario */ + int SYSTEM_ERR = 39; /* Hit platform or system error */ + int MODEM_ERR = 40; /* Hit unexpected modem error */ + int INVALID_STATE = 41; /* Unexpected request for the current state */ + int NO_RESOURCES = 42; /* Not sufficient resource to process the + request */ + int SIM_ERR = 43; /* Received error from SIM card */ + int INVALID_ARGUMENTS = 44; /* Received invalid arguments in request */ + int INVALID_SIM_STATE = 45; /* Can not process the request in current SIM + state */ + int INVALID_MODEM_STATE = 46; /* Can not process the request in current Modem + state */ + int INVALID_CALL_ID = 47; /* Received invalid call id in request */ + int NO_SMS_TO_ACK = 48; /* ACK received when there is no SMS to ack */ + int NETWORK_ERR = 49; /* Received error from network */ + int REQUEST_RATE_LIMITED = 50; /* Operation denied due to overly-frequent + requests */ + int SIM_BUSY = 51; /* SIM is busy */ + int SIM_FULL = 52; /* The target EF is full */ + int NETWORK_REJECT = 53; /* Request is rejected by network */ + int OPERATION_NOT_ALLOWED = 54; /* Not allowed the request now */ + int EMPTY_RECORD = 55; /* The request record is empty */ + int INVALID_SMS_FORMAT = 56; /* Invalid sms format */ + int ENCODING_ERR = 57; /* Message not encoded properly */ + int INVALID_SMSC_ADDRESS = 58; /* SMSC address specified is invalid */ + int NO_SUCH_ENTRY = 59; /* No such entry present to perform the + request */ + int NETWORK_NOT_READY = 60; /* Network is not ready to perform the + request */ + int NOT_PROVISIONED = 61; /* Device doesnot have this value + provisioned */ + int NO_SUBSCRIPTION = 62; /* Device doesnot have subscription */ + int NO_NETWORK_FOUND = 63; /* Network cannot be found */ + int DEVICE_IN_USE = 64; /* Operation cannot be performed because the + device is currently in use */ + int ABORTED = 65; /* Operation aborted */ + int INVALID_RESPONSE = 66; /* Invalid response sent by vendor code */ + int SIMULTANEOUS_SMS_AND_CALL_NOT_ALLOWED = 67; /* 1X voice and SMS are not allowed + simulteneously */ + int ACCESS_BARRED = 68; /* SMS access is barred */ + int BLOCKED_DUE_TO_CALL = 69; /* SMS is blocked due to call control */ + int RF_HARDWARE_ISSUE = 70; /* RF HW issue is detected */ + int NO_RF_CALIBRATION_INFO = 71; /* No RF calibration in device */ // Below is list of OEM specific error codes which can by used by OEMs in case they don't want to // reveal particular replacement for Generic failure |